summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2014-05-05 16:44:39 -0600
committerCharles Harris <charlesr.harris@gmail.com>2014-05-06 16:24:10 -0600
commitff99924f3a82ee09cb76cc6cc94fc196a112fb30 (patch)
treede9cae03a83b37048c90e5429d246a6bd1d43da1
parent6f5329fdf45dc97314fa593d0a5a4c1d24e753c5 (diff)
downloadnumpy-ff99924f3a82ee09cb76cc6cc94fc196a112fb30.tar.gz
MAINT: Change default inplace, ufunc(...,out=x) casting to same_kind.
There has been a warning of this change since numpy 1.7. numpy 1.10 is a good time to do it. The nanvar function needed a fix after the change, and the tests and documentation are updated.
-rw-r--r--doc/source/reference/ufuncs.rst17
-rw-r--r--numpy/core/include/numpy/ndarraytypes.h6
-rw-r--r--numpy/core/src/multiarray/common.c2
-rw-r--r--numpy/core/src/multiarray/convert_datatype.c54
-rw-r--r--numpy/core/tests/test_ufunc.py39
-rw-r--r--numpy/lib/nanfunctions.py6
6 files changed, 26 insertions, 98 deletions
diff --git a/doc/source/reference/ufuncs.rst b/doc/source/reference/ufuncs.rst
index 2ae794f59..3d6112058 100644
--- a/doc/source/reference/ufuncs.rst
+++ b/doc/source/reference/ufuncs.rst
@@ -313,16 +313,15 @@ advanced usage and will not typically be used.
.. versionadded:: 1.6
+ May be 'no', 'equiv', 'safe', 'same_kind', or 'unsafe'.
+ See :func:`can_cast` for explanations of the parameter values.
+
Provides a policy for what kind of casting is permitted. For compatibility
- with previous versions of NumPy, this defaults to 'unsafe'. May be 'no',
- 'equiv', 'safe', 'same_kind', or 'unsafe'. See :func:`can_cast` for
- explanations of the parameter values.
-
- In a future version of numpy, this argument will default to
- 'same_kind'. As part of this transition, starting in version 1.7,
- ufuncs will produce a DeprecationWarning for calls which are
- allowed under the 'unsafe' rules, but not under the 'same_kind'
- rules.
+ with previous versions of NumPy, this defaults to 'unsafe' for numpy < 1.7.
+ In numpy 1.7 a transition to 'same_kind' was begun where ufuncs produce a
+ DeprecationWarning for calls which are allowed under the 'unsafe'
+ rules, but not under the 'same_kind' rules. In numpy 1.10 the default
+ will be 'same_kind'.
*order*
diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h
index 21ff8cd1a..78f79d5fe 100644
--- a/numpy/core/include/numpy/ndarraytypes.h
+++ b/numpy/core/include/numpy/ndarraytypes.h
@@ -203,12 +203,6 @@ typedef enum {
NPY_SAME_KIND_CASTING=3,
/* Allow any casts */
NPY_UNSAFE_CASTING=4,
-
- /*
- * Temporary internal definition only, will be removed in upcoming
- * release, see below
- * */
- NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND = 100,
} NPY_CASTING;
typedef enum {
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c
index 2b3d3c3d2..f1656afd0 100644
--- a/numpy/core/src/multiarray/common.c
+++ b/numpy/core/src/multiarray/common.c
@@ -84,7 +84,7 @@ PyArray_GetAttrString_SuppressException(PyObject *obj, char *name)
-NPY_NO_EXPORT NPY_CASTING NPY_DEFAULT_ASSIGN_CASTING = NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND;
+NPY_NO_EXPORT NPY_CASTING NPY_DEFAULT_ASSIGN_CASTING = NPY_SAME_KIND_CASTING;
NPY_NO_EXPORT PyArray_Descr *
diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c
index 1db3bfe85..fa5fb6b67 100644
--- a/numpy/core/src/multiarray/convert_datatype.c
+++ b/numpy/core/src/multiarray/convert_datatype.c
@@ -624,63 +624,19 @@ type_num_unsigned_to_signed(int type_num)
}
}
-/*
- * NOTE: once the UNSAFE_CASTING -> SAME_KIND_CASTING transition is over,
- * we should remove NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND
- * and PyArray_CanCastTypeTo_impl should be renamed back to
- * PyArray_CanCastTypeTo.
- */
-static npy_bool
-PyArray_CanCastTypeTo_impl(PyArray_Descr *from, PyArray_Descr *to,
- NPY_CASTING casting);
-
/*NUMPY_API
* Returns true if data of type 'from' may be cast to data of type
* 'to' according to the rule 'casting'.
*/
NPY_NO_EXPORT npy_bool
PyArray_CanCastTypeTo(PyArray_Descr *from, PyArray_Descr *to,
- NPY_CASTING casting)
-{
- /* fast path for basic types */
- if (NPY_LIKELY(from->type_num < NPY_OBJECT) &&
- NPY_LIKELY(from->type_num == to->type_num) &&
- NPY_LIKELY(from->byteorder == to->byteorder)) {
- return 1;
- }
- else if (casting == NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND) {
- npy_bool unsafe_ok, same_kind_ok;
- unsafe_ok = PyArray_CanCastTypeTo_impl(from, to, NPY_UNSAFE_CASTING);
- same_kind_ok = PyArray_CanCastTypeTo_impl(from, to,
- NPY_SAME_KIND_CASTING);
- if (unsafe_ok && !same_kind_ok) {
- char * msg = "Implicitly casting between incompatible kinds. In "
- "a future numpy release, this will raise an error. "
- "Use casting=\"unsafe\" if this is intentional.";
- if (DEPRECATE(msg) < 0) {
- /* We have no way to propagate an exception :-( */
- PyErr_Clear();
- PySys_WriteStderr("Sorry, you requested this warning "
- "be raised as an error, but we couldn't "
- "do it. (See issue #3806 in the numpy "
- "bug tracker.) So FYI, it was: "
- "DeprecationWarning: %s\n",
- msg);
- }
- }
- return unsafe_ok;
- }
- else {
- return PyArray_CanCastTypeTo_impl(from, to, casting);
- }
-}
-
-static npy_bool
-PyArray_CanCastTypeTo_impl(PyArray_Descr *from, PyArray_Descr *to,
NPY_CASTING casting)
{
- /* If unsafe casts are allowed */
- if (casting == NPY_UNSAFE_CASTING) {
+ /* Fast path for unsafe casts or basic types */
+ if (casting == NPY_UNSAFE_CASTING ||
+ (NPY_LIKELY(from->type_num < NPY_OBJECT) &&
+ NPY_LIKELY(from->type_num == to->type_num) &&
+ NPY_LIKELY(from->byteorder == to->byteorder))) {
return 1;
}
/* Equivalent types can be cast with any value of 'casting' */
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index 080606dce..7b8aff72a 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -834,45 +834,20 @@ class TestUfunc(TestCase):
def test_safe_casting(self):
# In old versions of numpy, in-place operations used the 'unsafe'
- # casting rules. In some future version, 'same_kind' will become the
- # default.
+ # casting rules. In versions >= 1.10, 'same_kind' is the
+ # default and an exception is raised instead of a warning.
+ # when 'same_kind' is not satisfied.
a = np.array([1, 2, 3], dtype=int)
# Non-in-place addition is fine
assert_array_equal(assert_no_warnings(np.add, a, 1.1),
[2.1, 3.1, 4.1])
- assert_warns(DeprecationWarning, np.add, a, 1.1, out=a)
- assert_array_equal(a, [2, 3, 4])
+ assert_raises(TypeError, np.add, a, 1.1, out=a)
def add_inplace(a, b):
a += b
- assert_warns(DeprecationWarning, add_inplace, a, 1.1)
- assert_array_equal(a, [3, 4, 5])
- # Make sure that explicitly overriding the warning is allowed:
+ assert_raises(TypeError, add_inplace, a, 1.1)
+ # Make sure that explicitly overriding the exception is allowed:
assert_no_warnings(np.add, a, 1.1, out=a, casting="unsafe")
- assert_array_equal(a, [4, 5, 6])
-
- # There's no way to propagate exceptions from the place where we issue
- # this deprecation warning, so we must throw the exception away
- # entirely rather than cause it to be raised at some other point, or
- # trigger some other unsuspecting if (PyErr_Occurred()) { ...} at some
- # other location entirely.
- import warnings
- import sys
- if sys.version_info[0] >= 3:
- from io import StringIO
- else:
- from StringIO import StringIO
- with warnings.catch_warnings():
- warnings.simplefilter("error")
- old_stderr = sys.stderr
- try:
- sys.stderr = StringIO()
- # No error, but dumps to stderr
- a += 1.1
- # No error on the next bit of code executed either
- 1 + 1
- assert_("Implicitly casting" in sys.stderr.getvalue())
- finally:
- sys.stderr = old_stderr
+ assert_array_equal(a, [2, 3, 4])
def test_ufunc_custom_out(self):
# Test ufunc with built in input types and custom output type
diff --git a/numpy/lib/nanfunctions.py b/numpy/lib/nanfunctions.py
index 818e130a8..e6b375884 100644
--- a/numpy/lib/nanfunctions.py
+++ b/numpy/lib/nanfunctions.py
@@ -35,6 +35,10 @@ def _replace_nan(a, val):
marking the locations where NaNs were present. If `a` is not of
inexact type, do nothing and return `a` together with a mask of None.
+ Note that scalars will end up as array scalars, which is important
+ for using the result as the value of the out argument in some
+ operations.
+
Parameters
----------
a : array-like
@@ -850,7 +854,7 @@ def nanvar(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
avg = _divide_by_count(avg, cnt)
# Compute squared deviation from mean.
- arr -= avg
+ np.subtract(arr, avg, out=arr, casting='unsafe')
arr = _copyto(arr, 0, mask)
if issubclass(arr.dtype.type, np.complexfloating):
sqr = np.multiply(arr, arr.conj(), out=arr).real