Skip to content

Commit 4e816b3

Browse files
committed
Merge pull request #34 from bashtage/fix-scalar-array
FIX: Fix behavior with scalar arrays
2 parents 01c0213 + adf5121 commit 4e816b3

File tree

4 files changed

+209
-146
lines changed

4 files changed

+209
-146
lines changed

randomstate/array_utilities.pxi

Lines changed: 99 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,14 @@ cdef int check_constraint(double val, object name, constraint_type cons) except
101101
return 0
102102

103103
cdef object cont_broadcast_1(aug_state* state, void* func, object size, object lock,
104-
object a, object a_name, constraint_type a_constraint):
104+
np.ndarray a_arr, object a_name, constraint_type a_constraint):
105105

106-
cdef np.ndarray a_arr, randoms
106+
cdef np.ndarray randoms
107107
cdef double *randoms_data
108108
cdef np.broadcast it
109109
cdef random_double_1 f = (<random_double_1>func)
110110
cdef np.npy_intp i, n
111111

112-
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
113112
if a_constraint != CONS_NONE:
114113
check_array_constraint(a_arr, a_name, a_constraint)
115114

@@ -132,19 +131,17 @@ cdef object cont_broadcast_1(aug_state* state, void* func, object size, object l
132131
return randoms
133132

134133
cdef object cont_broadcast_2(aug_state* state, void* func, object size, object lock,
135-
object a, object a_name, constraint_type a_constraint,
136-
object b, object b_name, constraint_type b_constraint):
137-
cdef np.ndarray a_arr, b_arr, randoms
134+
np.ndarray a_arr, object a_name, constraint_type a_constraint,
135+
np.ndarray b_arr, object b_name, constraint_type b_constraint):
136+
cdef np.ndarray randoms
138137
cdef double *randoms_data
139138
cdef np.broadcast it
140139
cdef random_double_2 f = (<random_double_2>func)
141140
cdef np.npy_intp i, n
142141

143-
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
144142
if a_constraint != CONS_NONE:
145143
check_array_constraint(a_arr, a_name, a_constraint)
146144

147-
b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_DOUBLE, np.NPY_ALIGNED)
148145
if b_constraint != CONS_NONE:
149146
check_array_constraint(b_arr, b_name, b_constraint)
150147

@@ -171,24 +168,21 @@ cdef object cont_broadcast_2(aug_state* state, void* func, object size, object l
171168
return randoms
172169

173170
cdef object cont_broadcast_3(aug_state* state, void* func, object size, object lock,
174-
object a, object a_name, constraint_type a_constraint,
175-
object b, object b_name, constraint_type b_constraint,
176-
object c, object c_name, constraint_type c_constraint):
177-
cdef np.ndarray a_arr, b_arr, c_arr, randoms
171+
np.ndarray a_arr, object a_name, constraint_type a_constraint,
172+
np.ndarray b_arr, object b_name, constraint_type b_constraint,
173+
np.ndarray c_arr, object c_name, constraint_type c_constraint):
174+
cdef np.ndarray randoms
178175
cdef double *randoms_data
179176
cdef np.broadcast it
180177
cdef random_double_3 f = (<random_double_3>func)
181178
cdef np.npy_intp i, n
182179

183-
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
184180
if a_constraint != CONS_NONE:
185181
check_array_constraint(a_arr, a_name, a_constraint)
186182

187-
b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_DOUBLE, np.NPY_ALIGNED)
188183
if b_constraint != CONS_NONE:
189184
check_array_constraint(b_arr, b_name, b_constraint)
190185

191-
c_arr = <np.ndarray>np.PyArray_FROM_OTF(c, np.NPY_DOUBLE, np.NPY_ALIGNED)
192186
if c_constraint != CONS_NONE:
193187
check_array_constraint(c_arr, c_name, c_constraint)
194188

@@ -219,43 +213,45 @@ cdef object cont(aug_state* state, void* func, object size, object lock, int nar
219213
object b, object b_name, constraint_type b_constraint,
220214
object c, object c_name, constraint_type c_constraint):
221215

216+
cdef np.ndarray a_arr, b_arr, c_arr
222217
cdef double _a = 0.0, _b = 0.0, _c = 0.0
223218
cdef bint is_scalar = True
219+
if narg > 0:
220+
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
221+
is_scalar = is_scalar and np.PyArray_NDIM(a_arr) == 0
222+
if narg > 1:
223+
b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_DOUBLE, np.NPY_ALIGNED)
224+
is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0
225+
if narg == 3:
226+
c_arr = <np.ndarray>np.PyArray_FROM_OTF(c, np.NPY_DOUBLE, np.NPY_ALIGNED)
227+
is_scalar = is_scalar and np.PyArray_NDIM(c_arr) == 0
228+
229+
if not is_scalar:
230+
if narg == 1:
231+
return cont_broadcast_1(state, func, size, lock,
232+
a_arr, a_name, a_constraint)
233+
elif narg == 2:
234+
return cont_broadcast_2(state, func, size, lock,
235+
a_arr, a_name, a_constraint,
236+
b_arr, b_name, b_constraint)
237+
else:
238+
return cont_broadcast_3(state, func, size, lock,
239+
a_arr, a_name, a_constraint,
240+
b_arr, b_name, b_constraint,
241+
c_arr, c_name, c_constraint)
242+
224243
if narg > 0:
225244
_a = PyFloat_AsDouble(a)
226-
if _a == -1.0:
227-
if PyErr_Occurred():
228-
is_scalar = False
229245
if a_constraint != CONS_NONE and is_scalar:
230246
check_constraint(_a, a_name, a_constraint)
231-
if narg > 1 and is_scalar:
247+
if narg > 1:
232248
_b = PyFloat_AsDouble(b)
233-
if _b == -1.0:
234-
if PyErr_Occurred():
235-
is_scalar = False
236-
if b_constraint != CONS_NONE and is_scalar:
249+
if b_constraint != CONS_NONE:
237250
check_constraint(_b, b_name, b_constraint)
238-
if narg == 3 and is_scalar:
251+
if narg == 3:
239252
_c = PyFloat_AsDouble(c)
240-
if _c == -1.0:
241-
if PyErr_Occurred():
242-
is_scalar = False
243253
if c_constraint != CONS_NONE and is_scalar:
244254
check_constraint(_c, c_name, c_constraint)
245-
if not is_scalar:
246-
PyErr_Clear()
247-
if narg == 1:
248-
return cont_broadcast_1(state, func, size, lock,
249-
a, a_name, a_constraint)
250-
elif narg == 2:
251-
return cont_broadcast_2(state, func, size, lock,
252-
a, a_name, a_constraint,
253-
b, b_name, b_constraint)
254-
else:
255-
return cont_broadcast_3(state, func, size, lock,
256-
a, a_name, a_constraint,
257-
b, b_name, b_constraint,
258-
c, c_name, c_constraint)
259255

260256
if size is None:
261257
if narg == 0:
@@ -296,15 +292,14 @@ cdef object cont(aug_state* state, void* func, object size, object lock, int nar
296292
return np.asarray(randoms).reshape(size)
297293

298294
cdef object discrete_broadcast_d(aug_state* state, void* func, object size, object lock,
299-
object a, object a_name, constraint_type a_constraint):
295+
np.ndarray a_arr, object a_name, constraint_type a_constraint):
300296

301-
cdef np.ndarray a_arr, randoms
297+
cdef np.ndarray randoms
302298
cdef long *randoms_data
303299
cdef np.broadcast it
304300
cdef random_uint_d f = (<random_uint_d>func)
305301
cdef np.npy_intp i, n
306302

307-
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
308303
if a_constraint != CONS_NONE:
309304
check_array_constraint(a_arr, a_name, a_constraint)
310305

@@ -328,18 +323,16 @@ cdef object discrete_broadcast_d(aug_state* state, void* func, object size, obje
328323
return randoms
329324

330325
cdef object discrete_broadcast_dd(aug_state* state, void* func, object size, object lock,
331-
object a, object a_name, constraint_type a_constraint,
332-
object b, object b_name, constraint_type b_constraint):
333-
cdef np.ndarray a_arr, b_arr, randoms
326+
np.ndarray a_arr, object a_name, constraint_type a_constraint,
327+
np.ndarray b_arr, object b_name, constraint_type b_constraint):
328+
cdef np.ndarray randoms
334329
cdef long *randoms_data
335330
cdef np.broadcast it
336331
cdef random_uint_dd f = (<random_uint_dd>func)
337332
cdef np.npy_intp i, n
338333

339-
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
340334
if a_constraint != CONS_NONE:
341335
check_array_constraint(a_arr, a_name, a_constraint)
342-
b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_DOUBLE, np.NPY_ALIGNED)
343336
if b_constraint != CONS_NONE:
344337
check_array_constraint(b_arr, b_name, b_constraint)
345338

@@ -365,20 +358,18 @@ cdef object discrete_broadcast_dd(aug_state* state, void* func, object size, obj
365358
return randoms
366359

367360
cdef object discrete_broadcast_di(aug_state* state, void* func, object size, object lock,
368-
object a, object a_name, constraint_type a_constraint,
369-
object b, object b_name, constraint_type b_constraint):
370-
cdef np.ndarray a_arr, b_arr, randoms
361+
np.ndarray a_arr, object a_name, constraint_type a_constraint,
362+
np.ndarray b_arr, object b_name, constraint_type b_constraint):
363+
cdef np.ndarray randoms
371364
cdef long *randoms_data
372365
cdef np.broadcast it
373366
cdef random_uint_di f = (<random_uint_di>func)
374367
cdef np.npy_intp i, n
375368

376369

377-
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
378370
if a_constraint != CONS_NONE:
379371
check_array_constraint(a_arr, a_name, a_constraint)
380372

381-
b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_LONG, np.NPY_ALIGNED)
382373
if b_constraint != CONS_NONE:
383374
check_array_constraint(b_arr, b_name, b_constraint)
384375

@@ -403,24 +394,21 @@ cdef object discrete_broadcast_di(aug_state* state, void* func, object size, obj
403394
return randoms
404395

405396
cdef object discrete_broadcast_iii(aug_state* state, void* func, object size, object lock,
406-
object a, object a_name, constraint_type a_constraint,
407-
object b, object b_name, constraint_type b_constraint,
408-
object c, object c_name, constraint_type c_constraint):
409-
cdef np.ndarray a_arr, b_arr, c_arr, randoms
397+
np.ndarray a_arr, object a_name, constraint_type a_constraint,
398+
np.ndarray b_arr, object b_name, constraint_type b_constraint,
399+
np.ndarray c_arr, object c_name, constraint_type c_constraint):
400+
cdef np.ndarray randoms
410401
cdef long *randoms_data
411402
cdef np.broadcast it
412403
cdef random_uint_iii f = (<random_uint_iii>func)
413404
cdef np.npy_intp i, n
414405

415-
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_LONG, np.NPY_ALIGNED)
416406
if a_constraint != CONS_NONE:
417407
check_array_constraint(a_arr, a_name, a_constraint)
418408

419-
b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_LONG, np.NPY_ALIGNED)
420409
if b_constraint != CONS_NONE:
421410
check_array_constraint(b_arr, b_name, b_constraint)
422411

423-
c_arr = <np.ndarray>np.PyArray_FROM_OTF(c, np.NPY_LONG, np.NPY_ALIGNED)
424412
if c_constraint != CONS_NONE:
425413
check_array_constraint(c_arr, c_name, c_constraint)
426414

@@ -446,14 +434,13 @@ cdef object discrete_broadcast_iii(aug_state* state, void* func, object size, ob
446434
return randoms
447435

448436
cdef object discrete_broadcast_i(aug_state* state, void* func, object size, object lock,
449-
object a, object a_name, constraint_type a_constraint):
450-
cdef np.ndarray a_arr, randoms
437+
np.ndarray a_arr, object a_name, constraint_type a_constraint):
438+
cdef np.ndarray randoms
451439
cdef long *randoms_data
452440
cdef np.broadcast it
453441
cdef random_uint_i f = (<random_uint_i>func)
454442
cdef np.npy_intp i, n
455443

456-
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_LONG, np.NPY_ALIGNED)
457444
if a_constraint != CONS_NONE:
458445
check_array_constraint(a_arr, a_name, a_constraint)
459446

@@ -485,72 +472,74 @@ cdef object disc(aug_state* state, void* func, object size, object lock,
485472
cdef double _da = 0, _db = 0
486473
cdef long _ia = 0, _ib = 0 , _ic = 0
487474
cdef bint is_scalar = True
475+
if narg_double > 0:
476+
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
477+
is_scalar = is_scalar and np.PyArray_NDIM(a_arr) == 0
478+
if narg_double > 1:
479+
b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_DOUBLE, np.NPY_ALIGNED)
480+
is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0
481+
elif narg_long == 1:
482+
b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_LONG, np.NPY_ALIGNED)
483+
is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0
484+
else:
485+
if narg_long > 0:
486+
a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_LONG, np.NPY_ALIGNED)
487+
is_scalar = is_scalar and np.PyArray_NDIM(a_arr) == 0
488+
if narg_long > 1:
489+
b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_LONG, np.NPY_ALIGNED)
490+
is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0
491+
if narg_long > 2 :
492+
c_arr = <np.ndarray>np.PyArray_FROM_OTF(c, np.NPY_LONG, np.NPY_ALIGNED)
493+
is_scalar = is_scalar and np.PyArray_NDIM(c_arr) == 0
494+
495+
if not is_scalar:
496+
if narg_long == 0:
497+
if narg_double == 1:
498+
return discrete_broadcast_d(state, func, size, lock,
499+
a_arr, a_name, a_constraint)
500+
elif narg_double == 2:
501+
return discrete_broadcast_dd(state, func, size, lock,
502+
a_arr, a_name, a_constraint,
503+
b_arr, b_name, b_constraint)
504+
elif narg_long == 1:
505+
if narg_double == 0:
506+
return discrete_broadcast_i(state, func, size, lock,
507+
a_arr, a_name, a_constraint)
508+
elif narg_double == 1:
509+
return discrete_broadcast_di(state, func, size, lock,
510+
a_arr, a_name, a_constraint,
511+
b_arr, b_name, b_constraint)
512+
else:
513+
raise NotImplementedError("No vector path available")
514+
515+
488516
if narg_double > 0:
489517
_da = PyFloat_AsDouble(a)
490-
if _da == -1.0:
491-
if PyErr_Occurred():
492-
is_scalar = False
493518
if a_constraint != CONS_NONE and is_scalar:
494519
check_constraint(_da, a_name, a_constraint)
495520

496-
if narg_double > 1 and is_scalar:
521+
if narg_double > 1:
497522
_db = PyFloat_AsDouble(b)
498-
if _db == -1.0:
499-
if PyErr_Occurred():
500-
is_scalar = False
501523
if b_constraint != CONS_NONE and is_scalar:
502524
check_constraint(_db, b_name, b_constraint)
503-
if narg_long == 1 and is_scalar:
525+
elif narg_long == 1:
504526
_ib = PyInt_AsLong(b)
505-
if _ib == -1:
506-
if PyErr_Occurred():
507-
is_scalar = False
508527
if b_constraint != CONS_NONE and is_scalar:
509528
check_constraint(<double>_ib, b_name, b_constraint)
510529
else:
511530
if narg_long > 0:
512531
_ia = PyInt_AsLong(a)
513-
if _ia == -1:
514-
if PyErr_Occurred():
515-
is_scalar = False
516-
elif a_constraint != CONS_NONE and is_scalar:
532+
if a_constraint != CONS_NONE and is_scalar:
517533
check_constraint(<double>_ia, a_name, a_constraint)
518-
if narg_long > 1 and is_scalar:
534+
if narg_long > 1:
519535
_ib = PyInt_AsLong(b)
520-
if _ib == -1:
521-
if PyErr_Occurred():
522-
is_scalar = False
523-
elif b_constraint != CONS_NONE and is_scalar:
536+
if b_constraint != CONS_NONE and is_scalar:
524537
check_constraint(<double>_ib, b_name, b_constraint)
525-
if narg_long > 2 and is_scalar:
538+
if narg_long > 2 :
526539
_ic = PyInt_AsLong(c)
527-
if _ic == -1:
528-
if PyErr_Occurred():
529-
is_scalar = False
530-
elif c_constraint != CONS_NONE and is_scalar:
540+
if c_constraint != CONS_NONE and is_scalar:
531541
check_constraint(<double>_ic, c_name, c_constraint)
532542

533-
if not is_scalar:
534-
PyErr_Clear()
535-
if narg_long == 0:
536-
if narg_double == 1:
537-
return discrete_broadcast_d(state, func, size, lock,
538-
a, a_name, a_constraint)
539-
elif narg_double == 2:
540-
return discrete_broadcast_dd(state, func, size, lock,
541-
a, a_name, a_constraint,
542-
b, b_name, b_constraint)
543-
elif narg_long == 1:
544-
if narg_double == 0:
545-
return discrete_broadcast_i(state, func, size, lock,
546-
a, a_name, a_constraint)
547-
elif narg_double == 1:
548-
return discrete_broadcast_di(state, func, size, lock,
549-
a, a_name, a_constraint,
550-
b, b_name, b_constraint)
551-
else:
552-
raise NotImplementedError("No vector path available")
553-
554543
if size is None:
555544
if narg_long == 0:
556545
if narg_double == 0:
@@ -576,7 +565,6 @@ cdef object disc(aug_state* state, void* func, object size, object lock,
576565
cdef random_uint_i fi;
577566
cdef random_uint_iii fiii;
578567

579-
580568
with lock, nogil:
581569
if narg_long == 0:
582570
if narg_double == 0:

0 commit comments

Comments
 (0)