Skip to content

Commit 5f84050

Browse files
authored
Merge pull request #115 from IntelPython/add-more-tests-for-interfaces
Add more vendored NumPy tests
2 parents 3f5c671 + 24fb318 commit 5f84050

File tree

5 files changed

+251
-209
lines changed

5 files changed

+251
-209
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
* Added third-party tests from `numpy.random` which tests the `mkl_random.interfaces.numpy_random` interface [gh-103](https://github.com/IntelPython/mkl_random/pull/103)
1515

1616
### Changed
17-
* Updates to `mkl_random` implementations to better align with newer versions of `numpy.random` [gh-103](https://github.com/IntelPython/mkl_random/pull/103)
17+
* Updates to `mkl_random` implementations to better align with newer versions of `numpy.random` [gh-103](https://github.com/IntelPython/mkl_random/pull/103), [gh-115](https://github.com/IntelPython/mkl_random/pull/115)
1818
* Made conda recipe dependency on numpy configurable through `USE_NUMPY_BASE` environment variable [gh-105](https://github.com/IntelPython/mkl_random/pull/105)
1919

2020
### Fixed

mkl_random/mklrand.pyx

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,17 +2189,17 @@ cdef class _MKLRandomState:
21892189

21902190
if size is not None:
21912191
if (np.prod(size) == 0):
2192-
return np.empty(size, dtype=np.dtype(dtype))
2192+
return np.empty(size, dtype=np.dtype(_dtype))
21932193

2194-
lowbnd, highbnd, randfunc = self._choose_randint_type(dtype)
2194+
lowbnd, highbnd, randfunc = self._choose_randint_type(_dtype)
21952195

21962196
if low < lowbnd:
21972197
raise ValueError(
2198-
f"low is out of bounds for {np.dtype(dtype).name}"
2198+
f"low is out of bounds for {np.dtype(_dtype).name}"
21992199
)
22002200
if high > highbnd:
22012201
raise ValueError(
2202-
f"high is out of bounds for {np.dtype(dtype).name}"
2202+
f"high is out of bounds for {np.dtype(_dtype).name}"
22032203
)
22042204
if low >= high:
22052205
raise ValueError("low >= high")
@@ -6303,29 +6303,55 @@ cdef class _MKLRandomState:
63036303
array([100, 0])
63046304
63056305
"""
6306-
cdef cnp.npy_intp d
6306+
cdef cnp.npy_intp d, sz, niter
63076307
cdef cnp.ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr"
63086308
cdef double *pix
63096309
cdef int *mnix
6310-
cdef cnp.npy_intp sz
6311-
6312-
d = len(pvals)
6313-
parr = <cnp.ndarray>cnp.PyArray_ContiguousFromObject(
6314-
pvals, cnp.NPY_DOUBLE, 1, 1
6310+
cdef long ni
6311+
6312+
parr = <cnp.ndarray>cnp.PyArray_FROMANY(
6313+
pvals,
6314+
cnp.NPY_DOUBLE,
6315+
0,
6316+
1,
6317+
cnp.NPY_ARRAY_ALIGNED | cnp.NPY_ARRAY_C_CONTIGUOUS
63156318
)
6319+
if cnp.PyArray_NDIM(parr) == 0:
6320+
raise TypeError("pvals must be a 1-d sequence")
6321+
d = cnp.PyArray_SIZE(parr)
63166322
pix = <double*>cnp.PyArray_DATA(parr)
6317-
6318-
if kahan_sum(pix, d-1) > (1.0 + 1e-12):
6319-
raise ValueError("sum(pvals[:-1]) > 1.0")
6320-
6323+
if (
6324+
not np.all(np.greater_equal(parr, 0))
6325+
or not np.all(np.less_equal(parr, 1))
6326+
):
6327+
raise ValueError("pvals < 0, pvals > 1 or pvals is NaN")
6328+
6329+
if d and kahan_sum(pix, d - 1) > (1.0 + 1e-12):
6330+
# When floating, but not float dtype, and close, improve the error
6331+
# 1.0001 works for float16 and float32
6332+
if (isinstance(pvals, np.ndarray)
6333+
and np.issubdtype(pvals.dtype, np.floating)
6334+
and pvals.dtype != float
6335+
and pvals.sum() < 1.0001):
6336+
msg = ("sum(pvals[:-1].astype(np.float64)) > 1.0. The pvals "
6337+
"array is cast to 64-bit floating point prior to "
6338+
"checking the sum. Precision changes when casting may "
6339+
"cause problems even if the sum of the original pvals "
6340+
"is valid.")
6341+
else:
6342+
msg = "sum(pvals[:-1]) > 1.0"
6343+
raise ValueError(msg)
63216344
shape = _shape_from_size(size, d)
63226345
multin = np.zeros(shape, np.int32)
6323-
63246346
mnarr = <cnp.ndarray>multin
63256347
mnix = <int*>cnp.PyArray_DATA(mnarr)
63266348
sz = cnp.PyArray_SIZE(mnarr)
6327-
6328-
irk_multinomial_vec(self.internal_state, sz // d, mnix, n, d, pix)
6349+
ni = n
6350+
if (ni < 0):
6351+
raise ValueError("n < 0")
6352+
# numpy#20483: Avoids divide by 0
6353+
niter = sz // d if d else 0
6354+
irk_multinomial_vec(self.internal_state, niter, mnix, n, d, pix)
63296355

63306356
return multin
63316357

@@ -6614,11 +6640,27 @@ cdef class _MKLRandomState:
66146640
66156641
"""
66166642
if isinstance(x, (int, np.integer)):
6617-
arr = np.arange(x)
6618-
else:
6619-
arr = np.array(x)
6620-
self.shuffle(arr)
6621-
return arr
6643+
# keep using long as the default here (main numpy switched to intp)
6644+
arr = np.arange(x, dtype=np.result_type(x, np.long))
6645+
self.shuffle(arr)
6646+
return arr
6647+
6648+
arr = np.asarray(x)
6649+
if arr.ndim < 1:
6650+
raise IndexError("x must be an integer or at least 1-dimensional")
6651+
6652+
# shuffle has fast-path for 1-d
6653+
if arr.ndim == 1:
6654+
# Return a copy if same memory
6655+
if np.may_share_memory(arr, x):
6656+
arr = np.array(arr)
6657+
self.shuffle(arr)
6658+
return arr
6659+
6660+
# Shuffle index array, dtype to ensure fast path
6661+
idx = np.arange(arr.shape[0], dtype=np.intp)
6662+
self.shuffle(idx)
6663+
return arr[idx]
66226664

66236665

66246666
cdef class MKLRandomState(_MKLRandomState):

mkl_random/tests/test_random.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ class RandIntData(NamedTuple):
224224
def randint():
225225
rfunc_method = rnd.randint
226226
integral_dtypes = [
227-
np.bool_,
227+
np.bool,
228228
np.int8,
229229
np.uint8,
230230
np.int16,
@@ -323,8 +323,9 @@ def test_randint_respect_dtype_singleton(randint):
323323
assert_equal(sample.dtype, np.dtype(dt))
324324

325325
for dt in (bool, int):
326-
lbnd = 0 if dt is bool else np.iinfo(np.dtype(dt)).min
327-
ubnd = 2 if dt is bool else np.iinfo(np.dtype(dt)).max + 1
326+
# The legacy rng uses "long" as the default integer:
327+
lbnd = 0 if dt is bool else np.iinfo("long").min
328+
ubnd = 2 if dt is bool else np.iinfo("long").max + 1
328329

329330
# gh-7284: Ensure that we get Python data types
330331
sample = randint.rfunc(lbnd, ubnd, dtype=dt)

mkl_random/tests/test_regression.py

Lines changed: 0 additions & 183 deletions
This file was deleted.

0 commit comments

Comments
 (0)