summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2016-02-15 12:49:02 -0700
committerCharles Harris <charlesr.harris@gmail.com>2016-02-18 21:31:05 -0700
commit8556c5dcf623efa57d037b0b9685a81a896010d5 (patch)
tree3c0b683d6826587fc847889993c6510a3745a138
parent25c23f1d956104a072a95355ffaa7a38b53710b7 (diff)
downloadnumpy-8556c5dcf623efa57d037b0b9685a81a896010d5.tar.gz
ENH: Make numpy floating scalars consistent with Python divmod.
The following numpy scalar floating functions are reimplemented using the npy_divmod function. - remainder ('%') - floor_division ('//') - divmod Note that numpy scalars warn on zero division rather than raise. divmod example, Python floats In [1]: a = 78 * 6e-8 In [2]: b = 6e-8 In [3]: divmod(a, b) Out[3]: (77.0, 5.999999999999965e-08) Before this commit numpy float64 gave In [4]: divmod(float64(a), float64(b)) Out[4]: (78.0, 0.0) After this commit numpy float64 gives In [4]: divmod(float64(a), float64(b)) Out[4]: (77.0, 5.9999999999999651e-08)
-rw-r--r--numpy/core/setup.py2
-rw-r--r--numpy/core/src/umath/scalarmath.c.src80
2 files changed, 55 insertions, 27 deletions
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 2e9e277af..593b21f6d 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -896,6 +896,8 @@ def configuration(parent_package='',top_path=None):
umath_deps = [
generate_umath_py,
+ join('include', 'numpy', 'npy_math.h'),
+ join('include', 'numpy', 'halffloat.h'),
join('src', 'multiarray', 'common.h'),
join('src', 'private', 'templ_common.h.src'),
join('src', 'umath', 'simd.inc.src'),
diff --git a/numpy/core/src/umath/scalarmath.c.src b/numpy/core/src/umath/scalarmath.c.src
index 706eccb31..0f762d707 100644
--- a/numpy/core/src/umath/scalarmath.c.src
+++ b/numpy/core/src/umath/scalarmath.c.src
@@ -175,6 +175,7 @@ static void
}
#define @name@_ctype_floor_divide @name@_ctype_divide
+
static void
@name@_ctype_remainder(@type@ a, @type@ b, @type@ *out) {
if (a == 0 || b == 0) {
@@ -268,17 +269,39 @@ static void
/**begin repeat
* #name = float, double, longdouble#
* #type = npy_float, npy_double, npy_longdouble#
+ * #c = f, , l#
*/
static @type@ (*_basic_@name@_floor)(@type@);
static @type@ (*_basic_@name@_sqrt)(@type@);
static @type@ (*_basic_@name@_fmod)(@type@, @type@);
+
#define @name@_ctype_add(a, b, outp) *(outp) = (a) + (b)
#define @name@_ctype_subtract(a, b, outp) *(outp) = (a) - (b)
#define @name@_ctype_multiply(a, b, outp) *(outp) = (a) * (b)
#define @name@_ctype_divide(a, b, outp) *(outp) = (a) / (b)
#define @name@_ctype_true_divide @name@_ctype_divide
-#define @name@_ctype_floor_divide(a, b, outp) \
- *(outp) = _basic_@name@_floor((a) / (b))
+
+
+static void
+@name@_ctype_floor_divide(@type@ a, @type@ b, @type@ *out) {
+ @type@ mod;
+
+ *out = npy_divmod@c@(a, b, &mod);
+}
+
+
+static void
+@name@_ctype_remainder(@type@ a, @type@ b, @type@ *out) {
+ npy_divmod@c@(a, b, out);
+}
+
+
+static void
+@name@_ctype_divmod(@type@ a, @type@ b, @type@ *out1, @type@ *out2) {
+ *out1 = npy_divmod@c@(a, b, out2);
+}
+
+
/**end repeat**/
static npy_half (*_basic_half_floor)(npy_half);
@@ -294,9 +317,26 @@ static npy_half (*_basic_half_fmod)(npy_half, npy_half);
#define half_ctype_divide(a, b, outp) *(outp) = \
npy_float_to_half(npy_half_to_float(a) / npy_half_to_float(b))
#define half_ctype_true_divide half_ctype_divide
-#define half_ctype_floor_divide(a, b, outp) \
- *(outp) = npy_float_to_half(_basic_float_floor(npy_half_to_float(a) / \
- npy_half_to_float(b)))
+
+
+static void
+half_ctype_floor_divide(npy_half a, npy_half b, npy_half *out) {
+ npy_half mod;
+
+ *out = npy_half_divmod(a, b, &mod);
+}
+
+
+static void
+half_ctype_remainder(npy_half a, npy_half b, npy_half *out) {
+ npy_half_divmod(a, b, out);
+}
+
+
+static void
+half_ctype_divmod(npy_half a, npy_half b, npy_half *out1, npy_half *out2) {
+ *out1 = npy_half_divmod(a, b, out2);
+}
/**begin repeat
* #name = cfloat, cdouble, clongdouble#
@@ -344,38 +384,23 @@ static npy_half (*_basic_half_fmod)(npy_half, npy_half);
(outp)->imag = (in1i*rat - in1r)*scl; \
} \
} while(0)
+
#define @name@_ctype_true_divide @name@_ctype_divide
+
#define @name@_ctype_floor_divide(a, b, outp) do { \
- (outp)->real = _basic_@rname@_floor \
- (((a).real*(b).real + (a).imag*(b).imag) / \
- ((b).real*(b).real + (b).imag*(b).imag)); \
+ @rname@_ctype_floor_divide( \
+ ((a).real*(b).real + (a).imag*(b).imag), \
+ ((b).real*(b).real + (b).imag*(b).imag), \
+ &((outp)->real)); \
(outp)->imag = 0; \
} while(0)
/**end repeat**/
-/**begin repeat
- * #name = float, double, longdouble#
- * #type = npy_float, npy_double, npy_longdouble#
- */
-static void
-@name@_ctype_remainder(@type@ a, @type@ b, @type@ *out) {
- @type@ tmp = a/b;
- *out = b * (tmp - _basic_@name@_floor(tmp));
-}
-/**end repeat**/
-
-static void
-half_ctype_remainder(npy_half a, npy_half b, npy_half *out) {
- float tmp, fa = npy_half_to_float(a), fb = npy_half_to_float(b);
- float_ctype_remainder(fa, fb, &tmp);
- *out = npy_float_to_half(tmp);
-}
/**begin repeat
* #name = byte, ubyte, short, ushort, int, uint, long, ulong,
- * longlong, ulonglong, half, float, double, longdouble,
- * cfloat, cdouble, clongdouble#
+ * longlong, ulonglong, cfloat, cdouble, clongdouble#
*/
#define @name@_ctype_divmod(a, b, out, out2) { \
@name@_ctype_floor_divide(a, b, out); \
@@ -383,6 +408,7 @@ half_ctype_remainder(npy_half a, npy_half b, npy_half *out) {
}
/**end repeat**/
+
/**begin repeat
* #name = float, double, longdouble#
* #type = npy_float, npy_double, npy_longdouble#