Skip to content

Commit aff0f59

Browse files
committed
REF: Update to include bool in combined generator
Add bool to combined generator
1 parent 6607b17 commit aff0f59

File tree

5 files changed

+94
-63
lines changed

5 files changed

+94
-63
lines changed

randomstate/bounded_integers.pxi.in

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ py:
100100
bc_ctypes = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000ULL'),
101101
('uint16', 'uint16', 'uint32', 'NPY_UINT32', 1, 16, 0, '0X10000UL'),
102102
('uint8', 'uint8', 'uint16', 'NPY_UINT16', 3, 8, 0, '0X100UL'),
103-
('bool','uint8', 'uint8', 'NPY_UINT8', 31, 1, 0, '0x2UL'),
103+
('bool','bool', 'uint8', 'NPY_UINT8', 31, 1, 0, '0x2UL'),
104104
('int32', 'uint32', 'uint64', 'NPY_INT64', 0, 0, '-0x80000000LL', '0x80000000LL'),
105105
('int16', 'uint16', 'uint32', 'NPY_INT32', 1, 16, '-0x8000LL', '0x8000LL' ),
106106
('int8', 'uint8', 'uint16', 'NPY_INT16', 3, 8, '-0x80LL', '0x80LL' ),
@@ -145,11 +145,11 @@ cdef object _rand_{{nptype}}_combined(object low, object high, object size, aug_
145145
distribution, or a single such random int if `size` not provided.
146146

147147
"""
148-
cdef {{utype}}_t off, val, mask
148+
cdef {{utype}}_t rng, last_rng, off, val, mask, out_val
149149
cdef uint32_t buf
150150
cdef {{utype}}_t *out
151151
cdef {{utype}}_t *out_data
152-
cdef {{nptype_up}}_t rng, last_rng, low_v, high_v
152+
cdef {{nptype_up}}_t low_v, high_v
153153
cdef np.ndarray low_arr, high_arr, out_arr
154154
cdef np.npy_intp i, cnt
155155
cdef np.broadcast it
@@ -174,8 +174,8 @@ cdef object _rand_{{nptype}}_combined(object low, object high, object size, aug_
174174
off = <{{utype}}_t>(<{{nptype}}_t>low)
175175
if size is None:
176176
with lock:
177-
random_bounded_{{utype}}_fill(state, off, rng, 1, out)
178-
return np.{{otype}}(<{{nptype}}_t>out[0])
177+
random_bounded_{{utype}}_fill(state, off, rng, 1, &out_val)
178+
return np.{{otype}}(<{{nptype}}_t>out_val)
179179
else:
180180
out_arr = <np.ndarray>np.empty(size, np.{{nptype}})
181181
cnt = np.PyArray_SIZE(out_arr)
@@ -211,14 +211,14 @@ cdef object _rand_{{nptype}}_combined(object low, object high, object size, aug_
211211
for i in range(n):
212212
low_v = (<{{nptype_up}}_t*>np.PyArray_MultiIter_DATA(it, 0))[0]
213213
high_v = (<{{nptype_up}}_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
214-
rng = (high_v - 1) - low_v
214+
rng = <{{utype}}_t>((high_v - 1) - low_v)
215215
off = <{{utype}}_t>(<{{nptype_up}}_t>low_v)
216216

217217
if rng != last_rng:
218218
# Smallest bit mask >= max
219219
mask = <{{utype}}_t>_gen_mask(rng)
220220

221-
out[i] = random_buffered_bounded_{{utype}}(state, off, rng, mask, &buf_rem, &buf)
221+
out_data[i] = random_buffered_bounded_{{utype}}(state, off, rng, mask, &buf_rem, &buf)
222222

223223
np.PyArray_MultiIter_NEXT(it)
224224

randomstate/distributions.c

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,7 +1403,7 @@ static inline uint64_t gen_mask(uint64_t max)
14031403
*/
14041404

14051405

1406-
inline uint64_t random_bounded_uint64(aug_state *state, uint64_t off, uint64_t rng, uint64_t mask)
1406+
static inline uint64_t bounded_uint64(aug_state *state, uint64_t off, uint64_t rng, uint64_t mask)
14071407
{
14081408
uint64_t val;
14091409
if (rng == 0)
@@ -1418,8 +1418,13 @@ inline uint64_t random_bounded_uint64(aug_state *state, uint64_t off, uint64_t r
14181418
return off + val;
14191419
}
14201420

1421+
uint64_t random_bounded_uint64(aug_state *state, uint64_t off, uint64_t rng, uint64_t mask)
1422+
{
1423+
return bounded_uint64(state, off, rng, mask);
1424+
}
14211425

1422-
inline uint32_t random_buffered_bounded_uint32(aug_state *state, uint32_t off, uint32_t rng, uint32_t mask, int *bcnt, uint32_t *buf)
1426+
1427+
static inline uint32_t bounded_uint32(aug_state *state, uint32_t off, uint32_t rng, uint32_t mask)
14231428
{
14241429
/*
14251430
* The buffer and buffer count are not used here but are included to allow
@@ -1435,7 +1440,15 @@ inline uint32_t random_buffered_bounded_uint32(aug_state *state, uint32_t off, u
14351440
return off + val;
14361441
}
14371442

1438-
inline uint16_t random_buffered_bounded_uint16(aug_state *state, uint16_t off, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf)
1443+
uint32_t random_buffered_bounded_uint32(aug_state *state, uint32_t off, uint32_t rng, uint32_t mask, int *bcnt, uint32_t *buf)
1444+
{
1445+
/*
1446+
* Unused bcnt and buf are here only to allow templating with other uint generators
1447+
*/
1448+
return bounded_uint32(state, off, rng, mask);
1449+
}
1450+
1451+
static inline buffered_bounded_uint16(aug_state *state, uint16_t off, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf)
14391452
{
14401453
uint16_t val;
14411454
if (rng == 0)
@@ -1455,7 +1468,12 @@ inline uint16_t random_buffered_bounded_uint16(aug_state *state, uint16_t off, u
14551468
return off + val;
14561469
}
14571470

1458-
inline uint8_t random_buffered_bounded_uint8(aug_state *state, uint8_t off, uint8_t rng, uint8_t mask, int *bcnt, uint32_t *buf)
1471+
uint16_t random_buffered_bounded_uint16(aug_state *state, uint16_t off, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf)
1472+
{
1473+
return buffered_bounded_uint16(state, off, rng, mask, bcnt, buf);
1474+
}
1475+
1476+
static inline uint8_t buffered_bounded_uint8(aug_state *state, uint8_t off, uint8_t rng, uint8_t mask, int *bcnt, uint32_t *buf)
14591477
{
14601478
uint8_t val;
14611479
if (rng == 0)
@@ -1474,6 +1492,31 @@ inline uint8_t random_buffered_bounded_uint8(aug_state *state, uint8_t off, uint
14741492
return off + val;
14751493
}
14761494

1495+
uint8_t random_buffered_bounded_uint8(aug_state *state, uint8_t off, uint8_t rng, uint8_t mask, int *bcnt, uint32_t *buf)
1496+
{
1497+
return buffered_bounded_uint8(state, off, rng, mask, bcnt, buf);
1498+
}
1499+
1500+
static inline npy_bool buffered_bounded_bool(aug_state *state, npy_bool off, npy_bool rng, npy_bool mask, int *bcnt, uint32_t *buf)
1501+
{
1502+
if (rng == 0)
1503+
return off;
1504+
if (!(bcnt[0])) {
1505+
buf[0] = random_uint32(state);
1506+
bcnt[0] = 31;
1507+
}
1508+
else {
1509+
buf[0] >>= 1;
1510+
bcnt[0] -= 1;
1511+
}
1512+
return (buf[0] & 0x00000001UL) != 0;
1513+
}
1514+
1515+
npy_bool random_buffered_bounded_bool(aug_state *state, npy_bool off, npy_bool rng, npy_bool mask, int *bcnt, uint32_t *buf)
1516+
{
1517+
return buffered_bounded_bool(state, off, rng, mask, bcnt, buf);
1518+
}
1519+
14771520
void random_bounded_uint64_fill(aug_state *state, uint64_t off, uint64_t rng, npy_intp cnt, uint64_t *out)
14781521
{
14791522
uint64_t mask;
@@ -1482,7 +1525,7 @@ void random_bounded_uint64_fill(aug_state *state, uint64_t off, uint64_t rng, np
14821525
/* Smallest bit mask >= max */
14831526
mask = gen_mask(rng);
14841527
for (i = 0; i < cnt; i++) {
1485-
out[i] = random_bounded_uint64(state, off, rng, mask);
1528+
out[i] = bounded_uint64(state, off, rng, mask);
14861529
}
14871530
}
14881531

@@ -1493,15 +1536,15 @@ void random_bounded_uint64_fill(aug_state *state, uint64_t off, uint64_t rng, np
14931536
*/
14941537
void random_bounded_uint32_fill(aug_state *state, uint32_t off, uint32_t rng, npy_intp cnt, uint32_t *out)
14951538
{
1496-
uint32_t val, mask;
1539+
uint32_t mask;
14971540
npy_intp i;
14981541
uint32_t buf = 0;
14991542
int bcnt = 0;
15001543

15011544
/* Smallest bit mask >= max */
15021545
mask = (uint32_t)gen_mask(rng);
15031546
for (i = 0; i < cnt; i++) {
1504-
out[i] = random_buffered_bounded_uint32(state, off, rng, mask, &bcnt, &buf);
1547+
out[i] = bounded_uint32(state, off, rng, mask, &bcnt, &buf);
15051548
}
15061549
}
15071550

@@ -1520,7 +1563,7 @@ void random_bounded_uint16_fill(aug_state *state, uint16_t off, uint16_t rng, np
15201563
/* Smallest bit mask >= max */
15211564
mask = (uint16_t)gen_mask(rng);
15221565
for (i = 0; i < cnt; i++) {
1523-
out[i] = random_buffered_bounded_uint16(state, off, rng, mask, &bcnt, &buf);
1566+
out[i] = buffered_bounded_uint16(state, off, rng, mask, &bcnt, &buf);
15241567
}
15251568
}
15261569

@@ -1538,7 +1581,7 @@ void random_bounded_uint8_fill(aug_state *state, uint8_t off, uint8_t rng, npy_i
15381581
/* Smallest bit mask >= max */
15391582
mask = (uint8_t)gen_mask(rng);
15401583
for (i = 0; i < cnt; i++) {
1541-
out[i] = random_buffered_bounded_uint8(state, off, rng, mask, &bcnt, &buf);
1584+
out[i] = buffered_bounded_uint8(state, off, rng, mask, &bcnt, &buf);
15421585
}
15431586

15441587
}
@@ -1550,27 +1593,13 @@ void random_bounded_uint8_fill(aug_state *state, uint8_t off, uint8_t rng, npy_i
15501593
*/
15511594
void random_bounded_bool_fill(aug_state *state, npy_bool off, npy_bool rng, npy_intp cnt, npy_bool *out)
15521595
{
1596+
npy_bool mask = 0;
15531597
npy_intp i;
15541598
uint32_t buf = 0;
15551599
int bcnt = 0;
15561600

1557-
if (rng == 0) {
1558-
for (i = 0; i < cnt; i++) {
1559-
out[i] = off;
1560-
}
1561-
return;
1562-
}
1563-
15641601
for (i = 0; i < cnt; i++) {
1565-
if (!bcnt) {
1566-
buf = random_uint32(state);
1567-
bcnt = 31;
1568-
}
1569-
else {
1570-
buf >>= 1;
1571-
bcnt--;
1572-
}
1573-
out[i] = (buf & 0x00000001) != 0;
1602+
out[i] = buffered_bounded_bool(state, off, rng, mask, &bcnt, &buf);
15741603
}
15751604
}
15761605

randomstate/distributions.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,12 @@ extern double random_standard_gamma_zig_double(aug_state* state, double shape);
176176

177177
extern float random_standard_gamma_zig_float(aug_state* state, float shape);
178178

179-
inline uint32_t random_buffered_bounded_uint32(aug_state *state, uint32_t off, uint32_t rng, uint32_t mask, int *bcnt, uint32_t *buf);
179+
extern uint64_t random_bounded_uint64(aug_state *state, uint64_t off, uint64_t rng, uint64_t mask);
180180

181-
inline uint16_t random_buffered_bounded_uint16(aug_state *state, uint16_t off, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf);
181+
extern uint32_t random_buffered_bounded_uint32(aug_state *state, uint32_t off, uint32_t rng, uint32_t mask, int *bcnt, uint32_t *buf);
182182

183-
inline uint8_t random_buffered_bounded_uint8(aug_state *state, uint8_t off, uint8_t rng, uint8_t mask, int *bcnt, uint32_t *buf);
183+
extern uint16_t random_buffered_bounded_uint16(aug_state *state, uint16_t off, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf);
184+
185+
extern uint8_t random_buffered_bounded_uint8(aug_state *state, uint8_t off, uint8_t rng, uint8_t mask, int *bcnt, uint32_t *buf);
186+
187+
extern npy_bool random_buffered_bounded_bool(aug_state *state, npy_bool off, npy_bool rng, npy_bool mask, int *bcnt, uint32_t *buf);

randomstate/randomstate.pyx

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ cdef extern from "distributions.h":
6868
cdef uint32_t random_buffered_bounded_uint32(aug_state *state, uint32_t off, uint32_t rng, uint32_t mask, int *bcnt, uint32_t *buf) nogil
6969
cdef uint16_t random_buffered_bounded_uint16(aug_state *state, uint16_t off, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf) nogil
7070
cdef uint8_t random_buffered_bounded_uint8(aug_state *state, uint8_t off, uint8_t rng, uint8_t mask, int *bcnt, uint32_t *buf) nogil
71-
71+
cdef np.npy_bool random_buffered_bounded_bool(aug_state *state, np.npy_bool off, np.npy_bool rng, np.npy_bool mask, int *bcnt, uint32_t *buf) nogil
72+
7273
cdef long random_positive_int(aug_state* state) nogil
7374
cdef unsigned long random_uint(aug_state* state) nogil
7475
cdef unsigned long random_interval(aug_state* state, unsigned long max) nogil
@@ -1021,6 +1022,27 @@ cdef class RandomState:
10211022
if not key in _randint_type:
10221023
raise TypeError('Unsupported dtype "%s" for randint' % key)
10231024

1025+
if key == 'int32':
1026+
ret = _rand_int32_combined(low, high, size, &self.rng_state, self.lock)
1027+
elif key == 'int16':
1028+
ret = _rand_int16_combined(low, high, size, &self.rng_state, self.lock)
1029+
elif key == 'int8':
1030+
ret = _rand_int8_combined(low, high, size, &self.rng_state, self.lock)
1031+
elif key == 'uint32':
1032+
ret = _rand_uint32_combined(low, high, size, &self.rng_state, self.lock)
1033+
elif key == 'uint16':
1034+
ret = _rand_uint16_combined(low, high, size, &self.rng_state, self.lock)
1035+
elif key == 'uint8':
1036+
ret = _rand_uint8_combined(low, high, size, &self.rng_state, self.lock)
1037+
elif key == 'bool':
1038+
ret = _rand_bool_combined(low, high, size, &self.rng_state, self.lock)
1039+
1040+
if key != 'int64' and key != 'uint64':
1041+
if size is None and dtype in (np.bool, np.int, np.long):
1042+
if np.array(ret).shape == ():
1043+
return dtype(ret)
1044+
return ret
1045+
10241046
lowbnd, highbnd = _randint_type[key]
10251047

10261048
low = np.asarray(low)
@@ -1042,22 +1064,10 @@ cdef class RandomState:
10421064
if ilow >= ihigh:
10431065
raise ValueError("low >= high")
10441066

1045-
if key == 'int32':
1046-
ret = _rand_int32(ilow, ihigh - 1, size, &self.rng_state, self.lock)
1047-
elif key == 'int64':
1067+
if key == 'int64':
10481068
ret = _rand_int64(ilow, ihigh - 1, size, &self.rng_state, self.lock)
1049-
elif key == 'int16':
1050-
ret = _rand_int16(ilow, ihigh - 1, size, &self.rng_state, self.lock)
1051-
elif key == 'int8':
1052-
ret = _rand_int8(ilow, ihigh - 1, size, &self.rng_state, self.lock)
10531069
elif key == 'uint64':
10541070
ret = _rand_uint64(ilow, ihigh - 1, size, &self.rng_state, self.lock)
1055-
elif key == 'uint32':
1056-
ret = _rand_uint32(ilow, ihigh - 1, size, &self.rng_state, self.lock)
1057-
elif key == 'uint16':
1058-
ret = _rand_uint16(ilow, ihigh - 1, size, &self.rng_state, self.lock)
1059-
elif key == 'uint8':
1060-
ret = _rand_uint8(ilow, ihigh - 1, size, &self.rng_state, self.lock)
10611071
elif key == 'bool':
10621072
ret = _rand_bool(ilow, ihigh - 1, size, &self.rng_state, self.lock)
10631073

@@ -1066,22 +1076,10 @@ cdef class RandomState:
10661076
return dtype(ret)
10671077
return ret
10681078

1069-
if key == 'int32':
1070-
ret = _rand_int32_broadcast(low, high, size, &self.rng_state, self.lock)
1071-
elif key == 'int64':
1079+
if key == 'int64':
10721080
ret = _rand_int64_broadcast(low, high, size, &self.rng_state, self.lock)
1073-
elif key == 'int16':
1074-
ret = _rand_int16_broadcast(low, high, size, &self.rng_state, self.lock)
1075-
elif key == 'int8':
1076-
ret = _rand_int8_broadcast(low, high, size, &self.rng_state, self.lock)
10771081
elif key == 'uint64':
10781082
ret = _rand_uint64_broadcast(low, high, size, &self.rng_state, self.lock)
1079-
elif key == 'uint32':
1080-
ret = _rand_uint32_broadcast(low, high, size, &self.rng_state, self.lock)
1081-
elif key == 'uint16':
1082-
ret = _rand_uint16_broadcast(low, high, size, &self.rng_state, self.lock)
1083-
elif key == 'uint8':
1084-
ret = _rand_uint8_broadcast(low, high, size, &self.rng_state, self.lock)
10851083
elif key == 'bool':
10861084
ret = _rand_bool_broadcast(low, high, size, &self.rng_state, self.lock)
10871085

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
'RNG_PCG32', 'RNG_PCG64', 'RNG_XORSHIFT128', 'RNG_XOROSHIRO128PLUS',
3535
'RNG_XORSHIFT1024', 'RNG_SFMT']
3636

37-
compile_rngs = rngs[:1]
37+
compile_rngs = rngs[:]
3838

3939
extra_defs = [('_CRT_SECURE_NO_WARNINGS', '1')] if os.name == 'nt' else []
4040
extra_link_args = ['/LTCG', 'Advapi32.lib', 'Kernel32.lib'] if os.name == 'nt' else []

0 commit comments

Comments
 (0)