diff options
| author | Meekail Zain <34613774+Micky774@users.noreply.github.com> | 2022-06-13 16:55:04 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-13 13:55:04 -0700 |
| commit | cadfd83cb1e1df466eb91eb9c38dd2775455d64d (patch) | |
| tree | 6ed4c3805fe0a5861345df3c8e56c5479d350524 /numpy | |
| parent | 80e55b2dcecbd1475f74324847fa806d8159b9da (diff) | |
| download | numpy-cadfd83cb1e1df466eb91eb9c38dd2775455d64d.tar.gz | |
ENH: issue overflow warning when using `abs` on `np.int8(-128)` (#21648)
Checks condition a == NPY_MIN_@NAME@ to determine whether an overflow error has occurred for np.int8 type. See #21289 and #21188 (comment) for reference.
This also adds error integer overflow handling to the `-scalar` paths and "activates" a test for the unsigned versions.
A few tests are skipped, because the tests were buggy (they never ran). These paths require followups to fix.
Diffstat (limited to 'numpy')
| -rw-r--r-- | numpy/core/src/umath/scalarmath.c.src | 22 | ||||
| -rw-r--r-- | numpy/core/tests/test_scalarmath.py | 10 | ||||
| -rw-r--r-- | numpy/typing/tests/data/pass/arithmetic.py | 6 |
3 files changed, 31 insertions, 7 deletions
diff --git a/numpy/core/src/umath/scalarmath.c.src b/numpy/core/src/umath/scalarmath.c.src index 4993546f8..412f171ec 100644 --- a/numpy/core/src/umath/scalarmath.c.src +++ b/numpy/core/src/umath/scalarmath.c.src @@ -584,10 +584,15 @@ static NPY_INLINE int /**begin repeat * #name = byte, short, int, long, longlong# * #type = npy_byte, npy_short, npy_int, npy_long, npy_longlong# + * #NAME = BYTE, SHORT, INT, LONG, LONGLONG# */ static NPY_INLINE int @name@_ctype_absolute(@type@ a, @type@ *out) { + if (a == NPY_MIN_@NAME@) { + *out = a; + return NPY_FPE_OVERFLOW; + } *out = (a < 0 ? -a : a); return 0; } @@ -1564,8 +1569,23 @@ static PyObject * val = PyArrayScalar_VAL(a, @Name@); + int retstatus = @name@_ctype_@oper@(val, &out); - @name@_ctype_@oper@(val, &out); + if (retstatus) { + int bufsize, errmask; + PyObject *errobj; + + if (PyUFunc_GetPyValues("@name@_scalars", &bufsize, &errmask, + &errobj) < 0) { + return NULL; + } + int first = 1; + if (PyUFunc_handlefperr(errmask, errobj, retstatus, &first)) { + Py_XDECREF(errobj); + return NULL; + } + Py_XDECREF(errobj); + } /* * TODO: Complex absolute should check floating point flags. diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index b7fe5183e..57937a7a9 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -897,8 +897,11 @@ def test_scalar_integer_operation_overflow(dtype, operation): @pytest.mark.parametrize("dtype", np.typecodes["Integer"]) @pytest.mark.parametrize("operation", [ lambda min, neg_1: abs(min), - lambda min, neg_1: min * neg_1, - lambda min, neg_1: min // neg_1], ids=["abs", "*", "//"]) + pytest.param(lambda min, neg_1: min * neg_1, + marks=pytest.mark.xfail(reason="broken on some platforms")), + pytest.param(lambda min, neg_1: min // neg_1, + marks=pytest.mark.skip(reason="broken on some platforms"))], + ids=["abs", "*", "//"]) def test_scalar_signed_integer_overflow(dtype, operation): # The minimum signed integer can "overflow" for some additional operations st = np.dtype(dtype).type @@ -910,8 +913,7 @@ def test_scalar_signed_integer_overflow(dtype, operation): @pytest.mark.parametrize("dtype", np.typecodes["UnsignedInteger"]) -@pytest.mark.xfail # TODO: the check is quite simply missing! -def test_scalar_signed_integer_overflow(dtype): +def test_scalar_unsigned_integer_overflow(dtype): val = np.dtype(dtype).type(8) with pytest.warns(RuntimeWarning, match="overflow encountered"): -val diff --git a/numpy/typing/tests/data/pass/arithmetic.py b/numpy/typing/tests/data/pass/arithmetic.py index 4ed69c923..07a990127 100644 --- a/numpy/typing/tests/data/pass/arithmetic.py +++ b/numpy/typing/tests/data/pass/arithmetic.py @@ -2,6 +2,7 @@ from __future__ import annotations from typing import Any import numpy as np +import pytest c16 = np.complex128(1) f8 = np.float64(1) @@ -330,8 +331,9 @@ AR_O **= AR_LIKE_O -f4 -i8 -i4 --u8 --u4 +with pytest.warns(RuntimeWarning): + -u8 + -u4 -td -AR_f |
