diff options
-rw-r--r-- | numpy/core/code_generators/generate_umath.py | 2 | ||||
-rw-r--r-- | numpy/core/src/multiarray/calculation.c | 25 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 33 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_object.h | 9 | ||||
-rw-r--r-- | numpy/core/tests/test_datetime.py | 39 | ||||
-rw-r--r-- | numpy/ma/core.py | 5 | ||||
-rw-r--r-- | numpy/ma/tests/test_core.py | 4 |
7 files changed, 88 insertions, 29 deletions
diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index 957607f40..296f4683d 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -333,7 +333,7 @@ defdict = { 'ones_like' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.ones_like'), - 'PyUFunc_SimpleUnaryOperationTypeResolution', + 'PyUFunc_OnesLikeTypeResolution', TD(noobj), TD(O, f='Py_get_one'), ), diff --git a/numpy/core/src/multiarray/calculation.c b/numpy/core/src/multiarray/calculation.c index 8f32ce21c..dc6a7b15d 100644 --- a/numpy/core/src/multiarray/calculation.c +++ b/numpy/core/src/multiarray/calculation.c @@ -733,7 +733,30 @@ _GenericBinaryOutFunction(PyArrayObject *m1, PyObject *m2, PyArrayObject *out, return PyObject_CallFunction(op, "OO", m1, m2); } else { - return PyObject_CallFunction(op, "OOO", m1, m2, out); + PyObject *args, *kw, *ret; + + args = Py_BuildValue("OOO", m1, m2, out); + if (args == NULL) { + return NULL; + } + kw = PyDict_New(); + if (kw == NULL) { + Py_DECREF(args); + return NULL; + } + if (PyDict_SetItemString(kw, "casting", + PyUString_FromString("unsafe")) < 0) { + Py_DECREF(args); + Py_DECREF(kw); + return NULL; + } + + ret = PyObject_Call(op, args, kw); + + Py_DECREF(args); + Py_DECREF(kw); + + return ret; } } diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index dcc29f2ba..69f9afecf 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -2012,6 +2012,27 @@ PyUFunc_SimpleUnaryOperationTypeResolution(PyUFuncObject *ufunc, } /* + * The ones_like function shouldn't really be a ufunc, but while it + * still is, this provides type resolution that always forces UNSAFE + * casting. + */ +NPY_NO_EXPORT int +PyUFunc_OnesLikeTypeResolution(PyUFuncObject *ufunc, + NPY_CASTING NPY_UNUSED(casting), + PyArrayObject **operands, + PyObject *type_tup, + PyArray_Descr **out_dtypes, + PyUFuncGenericFunction *out_innerloop, + void **out_innerloopdata) +{ + return PyUFunc_SimpleUnaryOperationTypeResolution(ufunc, + NPY_UNSAFE_CASTING, + operands, type_tup, out_dtypes, + out_innerloop, out_innerloopdata); +} + + +/* * This function applies special type resolution rules for the case * where all the functions have the pattern XX->X, using * PyArray_ResultType instead of a linear search to get the best @@ -3486,11 +3507,9 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *self, NPY_ORDER order = NPY_KEEPORDER; /* - * Many things in NumPy do unsafe casting (doing int += float, etc). - * The strictness should probably become a state parameter, similar - * to the seterr/geterr. + * Currently trying out SAME_KIND casting rule by default. */ - NPY_CASTING casting = NPY_UNSAFE_CASTING; + NPY_CASTING casting = NPY_SAME_KIND_CASTING; /* When provided, extobj and typetup contain borrowed references */ PyObject *extobj = NULL, *type_tup = NULL; @@ -3870,11 +3889,9 @@ PyUFunc_GenericFunction(PyUFuncObject *self, NPY_ORDER order = NPY_KEEPORDER; /* - * Many things in NumPy do unsafe casting (doing int += float, etc). - * The strictness should probably become a state parameter, similar - * to the seterr/geterr. + * Currently trying out SAME_KIND casting rule by default. */ - NPY_CASTING casting = NPY_UNSAFE_CASTING; + NPY_CASTING casting = NPY_SAME_KIND_CASTING; /* When provided, extobj and typetup contain borrowed references */ PyObject *extobj = NULL, *type_tup = NULL; diff --git a/numpy/core/src/umath/ufunc_object.h b/numpy/core/src/umath/ufunc_object.h index 2a5fd63a1..59754380c 100644 --- a/numpy/core/src/umath/ufunc_object.h +++ b/numpy/core/src/umath/ufunc_object.h @@ -26,6 +26,15 @@ PyUFunc_SimpleUnaryOperationTypeResolution(PyUFuncObject *ufunc, void **out_innerloopdata); NPY_NO_EXPORT int +PyUFunc_OnesLikeTypeResolution(PyUFuncObject *ufunc, + NPY_CASTING casting, + PyArrayObject **operands, + PyObject *type_tup, + PyArray_Descr **out_dtypes, + PyUFuncGenericFunction *out_innerloop, + void **out_innerloopdata); + +NPY_NO_EXPORT int PyUFunc_SimpleBinaryOperationTypeResolution(PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index 9af00a81b..271a5dea9 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -625,10 +625,12 @@ class TestDateTime(TestCase): dt1 = np.dtype('M8[%s]' % unit1) for unit2 in ['D', 'h', 'm', 's', 'ms', 'us']: dt2 = np.dtype('M8[%s]' % unit2) - assert_equal(np.array('1932-02-17', dtype='M').astype(dt1), - np.array('1932-02-17T00:00:00Z', dtype='M').astype(dt2)) - assert_equal(np.array('10000-04-27', dtype='M').astype(dt1), - np.array('10000-04-27T00:00:00Z', dtype='M').astype(dt2)) + assert_(np.equal(np.array('1932-02-17', dtype='M').astype(dt1), + np.array('1932-02-17T00:00:00Z', dtype='M').astype(dt2), + casting='unsafe')) + assert_(np.equal(np.array('10000-04-27', dtype='M').astype(dt1), + np.array('10000-04-27T00:00:00Z', dtype='M').astype(dt2), + casting='unsafe')) # Shouldn't be able to compare datetime and timedelta # TODO: Changing to 'same_kind' or 'safe' casting in the ufuncs by @@ -743,10 +745,12 @@ class TestDateTime(TestCase): assert_equal((tda + dta).dtype, np.dtype('M8[D]')) # In M8 + m8, the result goes to higher precision - assert_equal(dta + tdb, dtc) - assert_equal((dta + tdb).dtype, np.dtype('M8[h]')) - assert_equal(tdb + dta, dtc) - assert_equal((tdb + dta).dtype, np.dtype('M8[h]')) + assert_equal(np.add(dta, tdb, casting='unsafe'), dtc) + assert_equal(np.add(dta, tdb, casting='unsafe').dtype, + np.dtype('M8[h]')) + assert_equal(np.add(tdb, dta, casting='unsafe'), dtc) + assert_equal(np.add(tdb, dta, casting='unsafe').dtype, + np.dtype('M8[h]')) # M8 + M8 assert_raises(TypeError, np.add, dta, dtb) @@ -805,14 +809,19 @@ class TestDateTime(TestCase): assert_equal((dtb - tda).dtype, np.dtype('M8[D]')) # In M8 - m8, the result goes to higher precision - assert_equal(dtc - tdb, dte) - assert_equal((dtc - tdb).dtype, np.dtype('M8[h]')) + assert_equal(np.subtract(dtc, tdb, casting='unsafe'), dte) + assert_equal(np.subtract(dtc, tdb, casting='unsafe').dtype, + np.dtype('M8[h]')) # M8 - M8 with different goes to higher precision - assert_equal(dtc - dtd, np.timedelta64(0,'h')) - assert_equal((dtc - dtd).dtype, np.dtype('m8[h]')) - assert_equal(dtd - dtc, np.timedelta64(0,'h')) - assert_equal((dtd - dtc).dtype, np.dtype('m8[h]')) + assert_equal(np.subtract(dtc, dtd, casting='unsafe'), + np.timedelta64(0,'h')) + assert_equal(np.subtract(dtc, dtd, casting='unsafe').dtype, + np.dtype('m8[h]')) + assert_equal(np.subtract(dtd, dtc, casting='unsafe'), + np.timedelta64(0,'h')) + assert_equal(np.subtract(dtd, dtc, casting='unsafe').dtype, + np.dtype('m8[h]')) # m8 - M8 assert_raises(TypeError, np.subtract, tda, dta) @@ -926,7 +935,7 @@ class TestDateTime(TestCase): # Interaction with NaT a = np.array('1999-03-12T13Z', dtype='M8[2m]') - dtnat = np.array('NaT', dtype='M8[D]') + dtnat = np.array('NaT', dtype='M8[h]') assert_equal(np.minimum(a,dtnat), a) assert_equal(np.minimum(dtnat,a), a) assert_equal(np.maximum(a,dtnat), a) diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 2cb888d55..50c60cd9d 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -4771,7 +4771,7 @@ class MaskedArray(ndarray): if dvar is not masked: dvar = sqrt(dvar) if out is not None: - out **= 0.5 + np.power(out, 0.5, out=out, casting='unsafe') return out return dvar std.__doc__ = np.std.__doc__ @@ -5207,7 +5207,8 @@ class MaskedArray(ndarray): result -= self.min(axis=axis, fill_value=fill_value) return result out.flat = self.max(axis=axis, out=out, fill_value=fill_value) - out -= self.min(axis=axis, fill_value=fill_value) + min_value = self.min(axis=axis, fill_value=fill_value) + np.subtract(out, min_value, out=out, casting='unsafe') return out def take(self, indices, axis=None, out=None, mode='raise'): diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index 2a2a76c24..b4ec3e540 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -1031,7 +1031,7 @@ class TestMaskedArrayArithmetic(TestCase): def test_noshrinking(self): "Check that we don't shrink a mask when not wanted" # Binary operations - a = masked_array([1, 2, 3], mask=[False, False, False], shrink=False) + a = masked_array([1., 2., 3.], mask=[False, False, False], shrink=False) b = a + 1 assert_equal(b.mask, [0, 0, 0]) # In place binary operation @@ -1646,7 +1646,7 @@ class TestMaskedArrayInPlaceArithmetics(TestCase): """Test of inplace additions""" (x, y, xm) = self.intdata m = xm.mask - a = arange(10, dtype=float) + a = arange(10, dtype=np.int16) a[-1] = masked x += a xm += a |