Skip to content

Commit b4f38e6

Browse files
committed
REF: Final cleanup
Remove unused code paths and rename from _combined
1 parent 7fdfbf5 commit b4f38e6

File tree

3 files changed

+15
-308
lines changed

3 files changed

+15
-308
lines changed

randomstate/bounded_integers.pxi.in

Lines changed: 4 additions & 294 deletions
Original file line numberDiff line numberDiff line change
@@ -11,79 +11,6 @@ _randint_type = {'bool': (0, 2),
1111

1212
ctypedef np.npy_bool bool_t
1313

14-
{{
15-
py:
16-
ctypes = (('int64', 'uint64'),
17-
('int32', 'uint32'),
18-
('int16', 'uint16'),
19-
('int8', 'uint8'),
20-
('uint64', 'uint64'),
21-
('uint32', 'uint32'),
22-
('uint16', 'uint16'),
23-
('uint8', 'uint8'),
24-
('bool','bool'),
25-
)}}
26-
27-
{{for nptype, utype in ctypes}}
28-
29-
{{ py: otype = nptype + '_' if nptype == 'bool' else nptype }}
30-
31-
cdef object _rand_{{nptype}}(low, high, size, aug_state *state, lock):
32-
"""
33-
_rand_{{nptype}}(self, low, high, size, rngstate)
34-
35-
Return random np.{{nptype}} integers between `low` and `high`, inclusive.
36-
37-
Return random integers from the "discrete uniform" distribution in the
38-
closed interval [`low`, `high`). If `high` is None (the default),
39-
then results are from [0, `low`). On entry the arguments are presumed
40-
to have been validated for size and order for the np.{{nptype}} type.
41-
42-
Parameters
43-
----------
44-
low : int
45-
Lowest (signed) integer to be drawn from the distribution (unless
46-
``high=None``, in which case this parameter is the *highest* such
47-
integer).
48-
high : int
49-
If provided, the largest (signed) integer to be drawn from the
50-
distribution (see above for behavior if ``high=None``).
51-
size : int or tuple of ints
52-
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
53-
``m * n * k`` samples are drawn. Default is None, in which case a
54-
single value is returned.
55-
rngstate : encapsulated pointer to rk_state
56-
The specific type depends on the python version. In Python 2 it is
57-
a PyCObject, in Python 3 a PyCapsule object.
58-
59-
Returns
60-
-------
61-
out : python scalar or ndarray of np.{{nptype}}
62-
`size`-shaped array of random integers from the appropriate
63-
distribution, or a single such random int if `size` not provided.
64-
65-
"""
66-
cdef {{utype}}_t off, rng, buf
67-
cdef {{utype}}_t *out
68-
cdef np.ndarray array
69-
cdef np.npy_intp cnt
70-
71-
rng = <{{utype}}_t>(high - low)
72-
off = <{{utype}}_t>(<{{nptype}}_t>low)
73-
if size is None:
74-
with lock:
75-
random_bounded_{{utype}}_fill(state, off, rng, 1, &buf)
76-
return np.{{otype}}(<{{nptype}}_t>buf)
77-
else:
78-
array = <np.ndarray>np.empty(size, np.{{nptype}})
79-
cnt = np.PyArray_SIZE(array)
80-
out = <{{utype}}_t *>np.PyArray_DATA(array)
81-
with lock, nogil:
82-
random_bounded_{{utype}}_fill(state, off, rng, cnt, out)
83-
return array
84-
85-
{{endfor}}
86-
8714
cdef inline uint64_t _gen_mask(uint64_t max_val) nogil:
8815
# Smallest bit mask >= max
8916
cdef uint64_t mask = max_val
@@ -110,9 +37,9 @@ bc_ctypes = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000U
11037

11138
{{ py: otype = nptype + '_' if nptype == 'bool' else nptype }}
11239

113-
cdef object _rand_{{nptype}}_combined(object low, object high, object size, aug_state *state, object lock):
40+
cdef object _rand_{{nptype}}(object low, object high, object size, aug_state *state, object lock):
11441
"""
115-
_rand_{{nptype}}_combined(low, high, size, *state, lock)
42+
_rand_{{nptype}}(low, high, size, *state, lock)
11643

11744
Return random np.{{nptype}} integers between `low` and `high`, inclusive.
11845

@@ -225,223 +152,6 @@ cdef object _rand_{{nptype}}_combined(object low, object high, object size, aug_
225152
{{endfor}}
226153

227154

228-
{{
229-
py:
230-
bc_ctypes = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000ULL'),
231-
('uint16', 'uint16', 'uint32', 'NPY_UINT32', 1, 16, 0, '0X10000UL'),
232-
('uint8', 'uint8', 'uint16', 'NPY_UINT16', 3, 8, 0, '0X100UL'),
233-
('bool','uint8', 'uint8', 'NPY_UINT8', 31, 1, 0, '0x2UL'),
234-
('int32', 'uint32', 'uint64', 'NPY_INT64', 0, 0, '-0x80000000LL', '0x80000000LL'),
235-
('int16', 'uint16', 'uint32', 'NPY_INT32', 1, 16, '-0x8000LL', '0x8000LL' ),
236-
('int8', 'uint8', 'uint16', 'NPY_INT16', 3, 8, '-0x80LL', '0x80LL' ),
237-
)}}
238-
239-
{{for nptype, utype, nptype_up, npctype, remaining, bitshift, lb, ub in bc_ctypes}}
240-
241-
{{ py: otype = nptype + '_' if nptype == 'bool' else nptype }}
242-
243-
cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, aug_state *state, object lock):
244-
"""
245-
Generate bounded random {{nptype}} values using broadcasting
246-
247-
Parameters
248-
----------
249-
low : int or array-like
250-
Array containing the lowest (signed) integers to be drawn from the
251-
distribution.
252-
high : int or array-like
253-
Array containing the the open interval bound for the distribution.
254-
size : int or tuple of ints
255-
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
256-
``m * n * k`` samples are drawn. Default is None, in which case
257-
the output shape is determined by the broadcast shapes of low and
258-
high
259-
state : augmented random state
260-
State to use in the core random number generators
261-
lock : threading.Lock
262-
Lock to prevent multiple using a single RandomState simultaneously
263-
264-
Returns
265-
-------
266-
out : ndarray of np.{{nptype}}
267-
array of random integers from the appropriate distribution where the
268-
size is determined by size if provided or the broadcast shape of low
269-
and high
270-
"""
271-
cdef np.ndarray low_arr, high_arr, out_arr
272-
cdef np.npy_intp i
273-
cdef np.broadcast it
274-
cdef int buf_rem = 0
275-
276-
cdef {{utype}}_t *out_data
277-
cdef {{utype}}_t val, mask, off
278-
cdef {{nptype_up}}_t rng, last_rng, low_v, high_v
279-
cdef uint32_t buf
280-
281-
# TODO: Direct error check? Probably not
282-
# TODO: Make constant?
283-
low_arr = <np.ndarray>low
284-
high_arr = <np.ndarray>high
285-
if np.any(np.less(low_arr, {{lb}})):
286-
raise ValueError('low is out of bounds for {{nptype}}')
287-
if np.any(np.greater(high_arr, {{ub}})):
288-
raise ValueError('high is out of bounds for {{nptype}}')
289-
if np.any(np.greater_equal(low_arr, high_arr)):
290-
raise ValueError('low >= high')
291-
292-
low_arr = <np.ndarray>np.PyArray_FROM_OTF(low, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST)
293-
high_arr = <np.ndarray>np.PyArray_FROM_OTF(high, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST)
294-
295-
if size is not None:
296-
out_arr = <np.ndarray>np.empty(size, np.{{otype}})
297-
else:
298-
it = np.PyArray_MultiIterNew2(low_arr, high_arr)
299-
out_arr = <np.ndarray>np.empty(it.shape, np.{{otype}})
300-
301-
it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr)
302-
out_data = <{{utype}}_t *>np.PyArray_DATA(out_arr)
303-
n = np.PyArray_SIZE(out_arr)
304-
mask = last_rng = 0
305-
with lock, nogil:
306-
for i in range(n):
307-
low_v = (<{{nptype_up}}_t*>np.PyArray_MultiIter_DATA(it, 0))[0]
308-
high_v = (<{{nptype_up}}_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
309-
rng = (high_v - 1) - low_v
310-
off = <{{utype}}_t>(<{{nptype_up}}_t>low_v)
311-
if rng == 0:
312-
out_data[i] = 0
313-
continue
314-
315-
if rng != last_rng:
316-
# TODO: Is this too much of an optimization? is it worth it?
317-
# Smallest bit mask >= max
318-
mask = <{{utype}}_t>_gen_mask(rng)
319-
320-
while True:
321-
if not buf_rem:
322-
buf = random_uint32(state)
323-
buf_rem = {{remaining}}
324-
else:
325-
buf >>= {{bitshift}}
326-
buf_rem -= 1
327-
val = <{{utype}}_t>buf & mask
328-
if val <= rng:
329-
break
330-
out_data[i] = off + val
331-
332-
np.PyArray_MultiIter_NEXT(it)
333-
334-
return out_arr
335-
336-
{{endfor}}
337-
338-
339-
{{
340-
py:
341-
big_bc_ctypes = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'),
342-
('int64', 'uint64', 'NPY_INT64', '-0x8000000000000000LL', '0x7FFFFFFFFFFFFFFFLL' )
343-
)}}
344-
345-
{{for nptype, utype, npctype, lb, ub in big_bc_ctypes}}
346-
347-
{{ py: otype = nptype}}
348-
349-
cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, aug_state *state, object lock):
350-
"""
351-
Generate bounded random {{nptype}} values using broadcasting
352-
353-
Parameters
354-
----------
355-
low : int or array-like
356-
Array containing the lowest (signed) integers to be drawn from the
357-
distribution.
358-
high : int or array-like
359-
Array containing the the open interval bound for the distribution.
360-
size : int or tuple of ints
361-
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
362-
``m * n * k`` samples are drawn. Default is None, in which case
363-
the output shape is determined by the broadcast shapes of low and
364-
high
365-
state : augmented random state
366-
State to use in the core random number generators
367-
lock : threading.Lock
368-
Lock to prevent multiple using a single RandomState simultaneously
369-
370-
Returns
371-
-------
372-
out : ndarray of np.{{nptype}}
373-
array of random integers from the appropriate distribution where the
374-
size is determined by size if provided or the broadcast shape of low
375-
and high
376-
"""
377-
cdef np.ndarray low_arr, high_arr, out_arr, highm1_arr
378-
cdef np.npy_intp i
379-
cdef np.broadcast it
380-
cdef int buf_rem = 0
381-
cdef object closed_upper
382-
383-
cdef uint64_t *out_data
384-
cdef {{nptype}}_t *highm1_data
385-
cdef {{nptype}}_t low_v, high_v
386-
cdef uint64_t rng, last_rng, val, mask, off
387-
388-
low_arr = <np.ndarray>low
389-
high_arr = <np.ndarray>high
390-
391-
if np.any(np.less(low_arr, {{lb}})):
392-
raise ValueError('low is out of bounds for {{nptype}}')
393-
394-
highm1_arr = <np.ndarray>np.empty_like(high_arr, dtype=np.{{nptype}})
395-
highm1_data = <{{nptype}}_t *>np.PyArray_DATA(highm1_arr)
396-
n = np.PyArray_SIZE(high_arr)
397-
flat = high_arr.flat
398-
for i in range(n):
399-
closed_upper = int(flat[i]) - 1
400-
if closed_upper > {{ub}}:
401-
raise ValueError('high is out of bounds for {{nptype}}')
402-
if closed_upper < {{lb}}:
403-
raise ValueError('low >= high')
404-
405-
highm1_data[i] = <{{nptype}}_t>closed_upper
406-
407-
if np.any(np.greater(low_arr, highm1_arr)):
408-
raise ValueError('low >= high')
409-
410-
high_arr = highm1_arr
411-
low_arr = <np.ndarray>np.PyArray_FROM_OTF(low, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST)
412-
413-
if size is not None:
414-
out_arr = <np.ndarray>np.empty(size, np.{{nptype}})
415-
else:
416-
it = np.PyArray_MultiIterNew2(low_arr, high_arr)
417-
out_arr = <np.ndarray>np.empty(it.shape, np.{{nptype}})
418-
419-
it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr)
420-
out_data = <uint64_t *>np.PyArray_DATA(out_arr)
421-
n = np.PyArray_SIZE(out_arr)
422-
mask = last_rng = 0
423-
with lock, nogil:
424-
for i in range(n):
425-
low_v = (<{{nptype}}_t*>np.PyArray_MultiIter_DATA(it, 0))[0]
426-
high_v = (<{{nptype}}_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
427-
rng = <{{nptype}}_t>(high_v - low_v) # No -1 here since implemented above
428-
off = low_v
429-
if rng == 0:
430-
out_data[i] = 0
431-
continue
432-
433-
if rng != last_rng:
434-
mask = _gen_mask(rng)
435-
out_data[i] = random_bounded_uint64(state, off, rng, mask)
436-
437-
np.PyArray_MultiIter_NEXT(it)
438-
439-
return out_arr
440-
441-
{{endfor}}
442-
443-
444-
445155
{{
446156
py:
447157
big_bc_ctypes = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'),
@@ -452,9 +162,9 @@ big_bc_ctypes = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFF
452162

453163
{{ py: otype = nptype}}
454164

455-
cdef object _rand_{{nptype}}_combined(object low, object high, object size, aug_state *state, object lock):
165+
cdef object _rand_{{nptype}}(object low, object high, object size, aug_state *state, object lock):
456166
"""
457-
Generate bounded random {{nptype}} values using broadcasting
167+
Generate bounded random {{nptype}} values
458168

459169
Parameters
460170
----------

randomstate/distributions.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,15 +1536,13 @@ void random_bounded_uint64_fill(aug_state *state, uint64_t off, uint64_t rng, np
15361536
*/
15371537
void random_bounded_uint32_fill(aug_state *state, uint32_t off, uint32_t rng, npy_intp cnt, uint32_t *out)
15381538
{
1539-
uint32_t mask;
1539+
uint32_t mask;
15401540
npy_intp i;
1541-
uint32_t buf = 0;
1542-
int bcnt = 0;
15431541

15441542
/* Smallest bit mask >= max */
15451543
mask = (uint32_t)gen_mask(rng);
15461544
for (i = 0; i < cnt; i++) {
1547-
out[i] = bounded_uint32(state, off, rng, mask, &bcnt, &buf);
1545+
out[i] = bounded_uint32(state, off, rng, mask);
15481546
}
15491547
}
15501548

randomstate/randomstate.pyx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,25 +1024,24 @@ cdef class RandomState:
10241024
raise TypeError('Unsupported dtype "%s" for randint' % key)
10251025

10261026
if key == 'int32':
1027-
ret = _rand_int32_combined(low, high, size, &self.rng_state, self.lock)
1027+
ret = _rand_int32(low, high, size, &self.rng_state, self.lock)
10281028
elif key == 'int64':
1029-
ret = _rand_int64_combined(low, high, size, &self.rng_state, self.lock)
1029+
ret = _rand_int64(low, high, size, &self.rng_state, self.lock)
10301030
elif key == 'int16':
1031-
ret = _rand_int16_combined(low, high, size, &self.rng_state, self.lock)
1031+
ret = _rand_int16(low, high, size, &self.rng_state, self.lock)
10321032
elif key == 'int8':
1033-
ret = _rand_int8_combined(low, high, size, &self.rng_state, self.lock)
1033+
ret = _rand_int8(low, high, size, &self.rng_state, self.lock)
10341034
elif key == 'uint64':
1035-
ret = _rand_uint64_combined(low, high, size, &self.rng_state, self.lock)
1035+
ret = _rand_uint64(low, high, size, &self.rng_state, self.lock)
10361036
elif key == 'uint32':
1037-
ret = _rand_uint32_combined(low, high, size, &self.rng_state, self.lock)
1037+
ret = _rand_uint32(low, high, size, &self.rng_state, self.lock)
10381038
elif key == 'uint16':
1039-
ret = _rand_uint16_combined(low, high, size, &self.rng_state, self.lock)
1039+
ret = _rand_uint16(low, high, size, &self.rng_state, self.lock)
10401040
elif key == 'uint8':
1041-
ret = _rand_uint8_combined(low, high, size, &self.rng_state, self.lock)
1041+
ret = _rand_uint8(low, high, size, &self.rng_state, self.lock)
10421042
elif key == 'bool':
1043-
ret = _rand_bool_combined(low, high, size, &self.rng_state, self.lock)
1043+
ret = _rand_bool(low, high, size, &self.rng_state, self.lock)
10441044

1045-
10461045
if size is None and dtype in (np.bool, np.int, np.long):
10471046
if np.array(ret).shape == ():
10481047
return dtype(ret)

0 commit comments

Comments
 (0)