summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/umath/loops_arithmetic.dispatch.c.src49
-rw-r--r--numpy/core/tests/test_regression.py2
-rw-r--r--numpy/core/tests/test_umath.py30
3 files changed, 52 insertions, 29 deletions
diff --git a/numpy/core/src/umath/loops_arithmetic.dispatch.c.src b/numpy/core/src/umath/loops_arithmetic.dispatch.c.src
index 16a9eac2e..15f438cbe 100644
--- a/numpy/core/src/umath/loops_arithmetic.dispatch.c.src
+++ b/numpy/core/src/umath/loops_arithmetic.dispatch.c.src
@@ -51,13 +51,14 @@ simd_divide_by_scalar_contig_@sfx@(char **args, npy_intp len)
const npyv_@sfx@x3 divisor = npyv_divisor_@sfx@(scalar);
if (scalar == -1) {
- npyv_b@len@ noverflow = npyv_cvt_b@len@_@sfx@(npyv_setall_@sfx@(-1));
- npyv_@sfx@ vzero = npyv_zero_@sfx@();
+ npyv_b@len@ noverflow = npyv_cvt_b@len@_@sfx@(npyv_setall_@sfx@(-1));
+ const npyv_@sfx@ vzero = npyv_zero_@sfx@();
+ const npyv_@sfx@ vmin = npyv_setall_@sfx@(NPY_MIN_INT@len@);
for (; len >= vstep; len -= vstep, src += vstep, dst += vstep) {
npyv_@sfx@ a = npyv_load_@sfx@(src);
npyv_b@len@ gt_min = npyv_cmpgt_@sfx@(a, npyv_setall_@sfx@(NPY_MIN_INT@len@));
noverflow = npyv_and_b@len@(noverflow, gt_min);
- npyv_@sfx@ neg = npyv_ifsub_@sfx@(gt_min, vzero, a, vzero);
+ npyv_@sfx@ neg = npyv_ifsub_@sfx@(gt_min, vzero, a, vmin);
npyv_store_@sfx@(dst, neg);
}
@@ -66,13 +67,13 @@ simd_divide_by_scalar_contig_@sfx@(char **args, npy_intp len)
npyv_lanetype_@sfx@ a = *src;
if (a == NPY_MIN_INT@len@) {
raise_err = 1;
- *dst = 0;
+ *dst = NPY_MIN_INT@len@;
} else {
*dst = -a;
}
}
if (raise_err) {
- npy_set_floatstatus_divbyzero();
+ npy_set_floatstatus_overflow();
}
} else {
for (; len >= vstep; len -= vstep, src += vstep, dst += vstep) {
@@ -253,7 +254,8 @@ vsx4_simd_divide_contig_@sfx@(char **args, npy_intp len)
const npyv_@sfx@ vneg_one = npyv_setall_@sfx@(-1);
const npyv_@sfx@ vzero = npyv_zero_@sfx@();
const npyv_@sfx@ vmin = npyv_setall_@sfx@(NPY_MIN_INT@len@);
- npyv_b@len@ warn = npyv_cvt_b@len@_@sfx@(npyv_zero_@sfx@());
+ npyv_b@len@ warn_zero = npyv_cvt_b@len@_@sfx@(npyv_zero_@sfx@());
+ npyv_b@len@ warn_overflow = npyv_cvt_b@len@_@sfx@(npyv_zero_@sfx@());
const int vstep = npyv_nlanes_@sfx@;
for (; len >= vstep; len -= vstep, src1 += vstep, src2 += vstep,
@@ -267,10 +269,8 @@ vsx4_simd_divide_contig_@sfx@(char **args, npy_intp len)
npyv_b@len@ amin = npyv_cmpeq_@sfx@(a, vmin);
npyv_b@len@ bneg_one = npyv_cmpeq_@sfx@(b, vneg_one);
npyv_b@len@ overflow = npyv_and_@sfx@(bneg_one, amin);
- npyv_b@len@ error = npyv_or_@sfx@(bzero, overflow);
- // in case of overflow or b = 0, 'cvtozero' forces quo/rem to be 0
- npyv_@sfx@ cvtozero = npyv_select_@sfx@(error, vzero, vneg_one);
- warn = npyv_or_@sfx@(error, warn);
+ warn_zero = npyv_or_@sfx@(bzero, warn_zero);
+ warn_overflow = npyv_or_@sfx@(overflow, warn_overflow);
// handle mixed case the way Python does
// ((a > 0) == (b > 0) || rem == 0)
npyv_b@len@ a_gt_zero = npyv_cmpgt_@sfx@(a, vzero);
@@ -280,21 +280,30 @@ vsx4_simd_divide_contig_@sfx@(char **args, npy_intp len)
npyv_b@len@ or = npyv_or_@sfx@(ab_eq_cond, rem_zero);
npyv_@sfx@ to_sub = npyv_select_@sfx@(or, vzero, vneg_one);
quo = npyv_add_@sfx@(quo, to_sub);
- npyv_store_@sfx@(dst1, npyv_and_@sfx@(cvtozero, quo));
+ // Divide by zero
+ quo = npyv_select_@sfx@(bzero, vzero, quo);
+ // Overflow
+ quo = npyv_select_@sfx@(overflow, vmin, quo);
+ npyv_store_@sfx@(dst1, quo);
}
- if (!vec_all_eq(warn, vzero)) {
+ if (!vec_all_eq(warn_zero, vzero)) {
npy_set_floatstatus_divbyzero();
}
+ if (!vec_all_eq(warn_overflow, vzero)) {
+ npy_set_floatstatus_overflow();
+ }
for (; len > 0; --len, ++src1, ++src2, ++dst1) {
const npyv_lanetype_@sfx@ a = *src1;
const npyv_lanetype_@sfx@ b = *src2;
- if (b == 0 || (a == NPY_MIN_INT@len@ && b == -1)) {
+ if (NPY_UNLIKELY(b == 0)) {
npy_set_floatstatus_divbyzero();
*dst1 = 0;
- }
- else {
+ } else if (NPY_UNLIKELY((a == NPY_MIN_INT@len@) && (b == -1))) {
+ npy_set_floatstatus_overflow();
+ *dst1 = NPY_MIN_INT@len@;
+ } else {
*dst1 = a / b;
if (((a > 0) != (b > 0)) && ((*dst1 * b) != a)) {
*dst1 -= 1;
@@ -340,8 +349,14 @@ NPY_FINLINE @type@ floor_div_@TYPE@(const @type@ n, const @type@ d)
* (i.e. a different approach than npy_set_floatstatus_divbyzero()).
*/
if (NPY_UNLIKELY(d == 0 || (n == NPY_MIN_@TYPE@ && d == -1))) {
- npy_set_floatstatus_divbyzero();
- return 0;
+ if (d == 0) {
+ npy_set_floatstatus_divbyzero();
+ return 0;
+ }
+ else {
+ npy_set_floatstatus_overflow();
+ return NPY_MIN_@TYPE@;
+ }
}
@type@ r = n / d;
// Negative quotients needs to be rounded down
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index 98e0df9b8..4388023dc 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -1496,7 +1496,7 @@ class TestRegression:
min = np.array([np.iinfo(t).min])
min //= -1
- with np.errstate(divide="ignore"):
+ with np.errstate(over="ignore"):
for t in (np.int8, np.int16, np.int32, np.int64, int):
test_type(t)
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index 7b6e2ee92..a696fceb8 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -327,7 +327,9 @@ class TestDivision:
a_lst, b_lst = a.tolist(), b.tolist()
c_div = lambda n, d: (
- 0 if d == 0 or (n and n == fo.min and d == -1) else n//d
+ 0 if d == 0 else (
+ fo.min if (n and n == fo.min and d == -1) else n//d
+ )
)
with np.errstate(divide='ignore'):
ac = a.copy()
@@ -342,7 +344,7 @@ class TestDivision:
for divisor in divisors:
ac = a.copy()
- with np.errstate(divide='ignore'):
+ with np.errstate(divide='ignore', over='ignore'):
div_a = a // divisor
ac //= divisor
div_lst = [c_div(i, divisor) for i in a_lst]
@@ -350,21 +352,25 @@ class TestDivision:
assert all(div_a == div_lst), msg
assert all(ac == div_lst), msg_eq
- with np.errstate(divide='raise'):
- if 0 in b or (fo.min and -1 in b and fo.min in a):
+ with np.errstate(divide='raise', over='raise'):
+ if 0 in b:
# Verify overflow case
- with pytest.raises(FloatingPointError):
+ with pytest.raises(FloatingPointError,
+ match="divide by zero encountered in floor_divide"):
a // b
else:
a // b
if fo.min and fo.min in a:
- with pytest.raises(FloatingPointError):
+ with pytest.raises(FloatingPointError,
+ match='overflow encountered in floor_divide'):
a // -1
elif fo.min:
a // -1
- with pytest.raises(FloatingPointError):
+ with pytest.raises(FloatingPointError,
+ match="divide by zero encountered in floor_divide"):
a // 0
- with pytest.raises(FloatingPointError):
+ with pytest.raises(FloatingPointError,
+ match="divide by zero encountered in floor_divide"):
ac = a.copy()
ac //= 0
@@ -392,11 +398,13 @@ class TestDivision:
msg = "Reduce floor integer division check"
assert div_a == div_lst, msg
- with np.errstate(divide='raise'):
- with pytest.raises(FloatingPointError):
+ with np.errstate(divide='raise', over='raise'):
+ with pytest.raises(FloatingPointError,
+ match="divide by zero encountered in reduce"):
np.floor_divide.reduce(np.arange(-100, 100, dtype=dtype))
if fo.min:
- with pytest.raises(FloatingPointError):
+ with pytest.raises(FloatingPointError,
+ match='overflow encountered in reduce'):
np.floor_divide.reduce(
np.array([fo.min, 1, -1], dtype=dtype)
)