diff options
| author | Matti Picus <matti.picus@gmail.com> | 2019-11-25 11:07:30 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-11-25 11:07:30 -0800 |
| commit | 4de39979cbe26741c01bded893ce0269116c7153 (patch) | |
| tree | 054f1fcb7af41c4057cda2937e01acb60e4de944 | |
| parent | 9ed9806637297aa3915294ce1ae97184529dbd04 (diff) | |
| parent | ac757b50edbbdb49cf0c1804d7f6273e16d269a4 (diff) | |
| download | numpy-4de39979cbe26741c01bded893ce0269116c7153.tar.gz | |
Merge pull request #14718 from eric-wieser/disable-Q_-_m_casting
API: Forbid Q<->m safe casting
| -rw-r--r-- | doc/release/upcoming_changes/14718.compatibility.rst | 8 | ||||
| -rw-r--r-- | doc/source/reference/ufuncs.rst | 6 | ||||
| -rw-r--r-- | numpy/core/src/multiarray/convert_datatype.c | 8 | ||||
| -rw-r--r-- | numpy/core/src/multiarray/scalartypes.c.src | 7 | ||||
| -rw-r--r-- | numpy/core/tests/test_datetime.py | 9 | ||||
| -rw-r--r-- | numpy/core/tests/test_scalarmath.py | 12 |
6 files changed, 43 insertions, 7 deletions
diff --git a/doc/release/upcoming_changes/14718.compatibility.rst b/doc/release/upcoming_changes/14718.compatibility.rst new file mode 100644 index 000000000..3d6e71ead --- /dev/null +++ b/doc/release/upcoming_changes/14718.compatibility.rst @@ -0,0 +1,8 @@ +``np.can_cast(np.uint64, np.timedelta64, casting='safe')`` is now ``False`` +--------------------------------------------------------------------------- + +Previously this was ``True`` - however, this was inconsistent with ``uint64`` +not being safely castable to ``int64``, and resulting in strange type +resolution. + +If this impacts your code, cast ``uint64`` to ``int64`` first. diff --git a/doc/source/reference/ufuncs.rst b/doc/source/reference/ufuncs.rst index 0416d6efc..361cf11b9 100644 --- a/doc/source/reference/ufuncs.rst +++ b/doc/source/reference/ufuncs.rst @@ -253,9 +253,9 @@ can generate this table for your system with the code given in the Figure. B - - Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y - Y H - - - Y Y Y Y - Y Y Y Y Y - Y Y Y Y Y Y Y Y Y Y - Y I - - - - Y Y Y - - Y Y Y Y - - Y Y - Y Y Y Y Y Y - Y - L - - - - - - - - - - Y Y Y - - Y Y - Y Y Y Y Y Y - Y - Q - - - - - - - - - - Y Y Y - - Y Y - Y Y Y Y Y Y - Y - P - - - - - - - - - - Y Y Y - - Y Y - Y Y Y Y Y Y - Y + L - - - - - - - - - - Y Y Y - - Y Y - Y Y Y Y Y Y - - + Q - - - - - - - - - - Y Y Y - - Y Y - Y Y Y Y Y Y - - + P - - - - - - - - - - Y Y Y - - Y Y - Y Y Y Y Y Y - - e - - - - - - - - - - - - - Y Y Y Y Y Y Y Y Y Y Y - - f - - - - - - - - - - - - - - Y Y Y Y Y Y Y Y Y Y - - d - - - - - - - - - - - - - - - Y Y - Y Y Y Y Y Y - - diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c index 025c66013..4326448dc 100644 --- a/numpy/core/src/multiarray/convert_datatype.c +++ b/numpy/core/src/multiarray/convert_datatype.c @@ -877,7 +877,13 @@ PyArray_CanCastTypeTo(PyArray_Descr *from, PyArray_Descr *to, from_order = dtype_kind_to_ordering(from->kind); to_order = dtype_kind_to_ordering(to->kind); - return from_order != -1 && from_order <= to_order; + if (to->kind == 'm') { + /* both types being timedelta is already handled before. */ + int integer_order = dtype_kind_to_ordering('i'); + return (from_order != -1) && (from_order <= integer_order); + } + + return (from_order != -1) && (from_order <= to_order); } else { return 0; diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index 32d712e0c..5da7f7738 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -4060,8 +4060,11 @@ initialize_casting_tables(void) _npy_can_cast_safely_table[_FROM_NUM][NPY_STRING] = 1; _npy_can_cast_safely_table[_FROM_NUM][NPY_UNICODE] = 1; - /* Allow casts from any integer to the TIMEDELTA type */ -#if @from_isint@ || @from_isuint@ +#if @from_isint@ && NPY_SIZEOF_TIMEDELTA >= _FROM_BSIZE + /* Allow casts from smaller or equal signed integers to the TIMEDELTA type */ + _npy_can_cast_safely_table[_FROM_NUM][NPY_TIMEDELTA] = 1; +#elif @from_isuint@ && NPY_SIZEOF_TIMEDELTA > _FROM_BSIZE + /* Allow casts from smaller unsigned integers to the TIMEDELTA type */ _npy_can_cast_safely_table[_FROM_NUM][NPY_TIMEDELTA] = 1; #endif diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index e8ffbbb9d..8bc6476da 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -75,6 +75,15 @@ class TestDateTime(object): # Can cast safely/same_kind from integer to timedelta assert_(np.can_cast('i8', 'm8', casting='same_kind')) assert_(np.can_cast('i8', 'm8', casting='safe')) + assert_(np.can_cast('i4', 'm8', casting='same_kind')) + assert_(np.can_cast('i4', 'm8', casting='safe')) + assert_(np.can_cast('u4', 'm8', casting='same_kind')) + assert_(np.can_cast('u4', 'm8', casting='safe')) + + # Cannot cast safely from unsigned integer of the same size, which + # could overflow + assert_(np.can_cast('u8', 'm8', casting='same_kind')) + assert_(not np.can_cast('u8', 'm8', casting='safe')) # Cannot cast safely/same_kind from float to timedelta assert_(not np.can_cast('f4', 'm8', casting='same_kind')) diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index 854df5590..c84380cd9 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -11,7 +11,7 @@ import numpy as np from numpy.testing import ( assert_, assert_equal, assert_raises, assert_almost_equal, assert_array_equal, IS_PYPY, suppress_warnings, _gen_alignment_data, - assert_warns + assert_warns, assert_raises_regex, ) types = [np.bool_, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, @@ -293,6 +293,16 @@ class TestModulus(object): rem = operator.mod(finf, fone) assert_(np.isnan(rem), 'dt: %s' % dt) + def test_inplace_floordiv_handling(self): + # issue gh-12927 + # this only applies to in-place floordiv //=, because the output type + # promotes to float which does not fit + a = np.array([1, 2], np.int64) + b = np.array([1, 2], np.uint64) + pattern = 'could not be coerced to provided output parameter' + with assert_raises_regex(TypeError, pattern): + a //= b + class TestComplexDivision(object): def test_zero_division(self): |
