Skip to content

Commit c899a67

Browse files
committed
BUG: Fix out-of-bound minimum offset for in1d table method
We could always use ar2.dtype, but we want intp anyway, so that is nicer. But if the minimum value doesn't fit intp, NumPy would complain (it may even guaranteed to work to force-cast, but...) So just try to use intp, but if that doesn't work use ar2.dtype which must work, but means we'll have to cast once more (even if that cast is probably just a view in principle). Closes numpygh-26922
1 parent 244509c commit c899a67

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

numpy/lib/_arraysetops_impl.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,8 +915,25 @@ def _in1d(ar1, ar2, assume_unique=False, invert=False, *, kind=None):
915915

916916
# Mask out elements we know won't work
917917
basic_mask = (ar1 <= ar2_max) & (ar1 >= ar2_min)
918+
in_range_ar1 = ar1[basic_mask]
919+
if in_range_ar1.size == 0:
920+
# Nothing more to do, since all values are out of range.
921+
return outgoing_array
922+
923+
# Unfortunately, ar2_min can be out of range for `intp` even
924+
# if the calculation result must fit in range (and be positive).
925+
# In that case, use ar2.dtype which must work for all unmasked
926+
# values.
927+
try:
928+
ar2_min = np.array(ar2_min, dtype=np.intp)
929+
dtype = np.intp
930+
except OverflowError:
931+
dtype = ar2.dtype
932+
933+
out = np.empty_like(in_range_ar1, dtype=np.intp)
918934
outgoing_array[basic_mask] = isin_helper_ar[
919-
np.subtract(ar1[basic_mask], ar2_min, dtype=np.intp)]
935+
np.subtract(in_range_ar1, ar2_min, dtype=dtype,
936+
out=out, casting="unsafe")]
920937

921938
return outgoing_array
922939
elif kind == 'table': # not range_safe_from_overflow

numpy/lib/tests/test_arraysetops.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,22 @@ def test_isin_mixed_dtype(self, dtype1, dtype2, kind):
440440
else:
441441
assert_array_equal(isin(ar1, ar2, kind=kind), expected)
442442

443+
@pytest.mark.parametrize("data", [
444+
np.array([2**63, 2**63+1], dtype=np.uint64),
445+
np.array([-2**62, -2**62-1], dtype=np.int64),
446+
])
447+
@pytest.mark.parametrize("kind", [None, "sort", "table"])
448+
def test_isin_mixed_huge_vals(self, kind, data):
449+
"""Test values outside intp range (negative ones if 32bit system)"""
450+
query = data[1]
451+
res = np.isin(data, query, kind=kind)
452+
assert_array_equal(res, [False, True])
453+
# Also check that nothing weird happens for values can't possibly
454+
# in range.
455+
data = data.astype(np.int32) # clearly different values
456+
res = np.isin(data, query, kind=kind)
457+
assert_array_equal(res, [False, False])
458+
443459
@pytest.mark.parametrize("kind", [None, "sort", "table"])
444460
def test_isin_mixed_boolean(self, kind):
445461
"""Test that isin works as expected for bool/int input."""

0 commit comments

Comments
 (0)