@@ -27,6 +27,20 @@ cdef np.npy_intp compute_numel(size):
27
27
n = size
28
28
return n
29
29
30
+ cdef check_output(object out, object dtype, object size):
31
+ if out is None :
32
+ return
33
+ cdef np.ndarray out_array = < np.ndarray> out
34
+ if not (np.PyArray_CHKFLAGS(out_array, np.NPY_CARRAY) or
35
+ np.PyArray_CHKFLAGS(out_array, np.NPY_FARRAY)):
36
+ raise ValueError (' Supplied output array is not contiguous, writable or aligned.' )
37
+ if out_array.dtype != dtype:
38
+ raise TypeError (' Supplied output array has the wrong type. '
39
+ ' Expected {0}, got {0}' .format(dtype, out_array.dtype))
40
+ if size is not None :
41
+ # TODO: enable this !!! if tuple(size) != out_array.shape:
42
+ raise ValueError (' size and out cannot be simultaneously used' )
43
+
30
44
cdef double POISSON_LAM_MAX = < double > np.iinfo(' l' ).max - np.sqrt(np.iinfo(' l' ).max)* 10
31
45
32
46
cdef enum ConstraintType:
@@ -101,7 +115,8 @@ cdef int check_constraint(double val, object name, constraint_type cons) except
101
115
return 0
102
116
103
117
cdef object cont_broadcast_1(aug_state* state, void * func, object size, object lock,
104
- np.ndarray a_arr, object a_name, constraint_type a_constraint):
118
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
119
+ object out):
105
120
106
121
cdef np.ndarray randoms
107
122
cdef double a_val
@@ -113,10 +128,12 @@ cdef object cont_broadcast_1(aug_state* state, void* func, object size, object l
113
128
if a_constraint != CONS_NONE:
114
129
check_array_constraint(a_arr, a_name, a_constraint)
115
130
116
- if size is not None :
131
+ if size is not None and out is None :
117
132
randoms = < np.ndarray> np.empty(size, np.double)
118
- else :
133
+ elif out is None :
119
134
randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr), np.PyArray_DIMS(a_arr), np.NPY_DOUBLE)
135
+ else :
136
+ randoms = < np.ndarray> out
120
137
121
138
randoms_data = < double * > np.PyArray_DATA(randoms)
122
139
n = np.PyArray_SIZE(randoms)
@@ -214,11 +231,13 @@ cdef object cont_broadcast_3(aug_state* state, void* func, object size, object l
214
231
cdef object cont(aug_state* state, void * func, object size, object lock, int narg,
215
232
object a, object a_name, constraint_type a_constraint,
216
233
object b, object b_name, constraint_type b_constraint,
217
- object c, object c_name, constraint_type c_constraint):
234
+ object c, object c_name, constraint_type c_constraint,
235
+ object out):
218
236
219
237
cdef np.ndarray a_arr, b_arr, c_arr
220
238
cdef double _a = 0.0 , _b = 0.0 , _c = 0.0
221
239
cdef bint is_scalar = True
240
+ check_output(out, np.float64, size)
222
241
if narg > 0 :
223
242
a_arr = < np.ndarray> np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
224
243
is_scalar = is_scalar and np.PyArray_NDIM(a_arr) == 0
@@ -232,7 +251,8 @@ cdef object cont(aug_state* state, void* func, object size, object lock, int nar
232
251
if not is_scalar:
233
252
if narg == 1 :
234
253
return cont_broadcast_1(state, func, size, lock,
235
- a_arr, a_name, a_constraint)
254
+ a_arr, a_name, a_constraint,
255
+ out)
236
256
elif narg == 2 :
237
257
return cont_broadcast_2(state, func, size, lock,
238
258
a_arr, a_name, a_constraint,
@@ -256,7 +276,7 @@ cdef object cont(aug_state* state, void* func, object size, object lock, int nar
256
276
if c_constraint != CONS_NONE and is_scalar:
257
277
check_constraint(_c, c_name, c_constraint)
258
278
259
- if size is None :
279
+ if size is None and out is None :
260
280
with lock:
261
281
if narg == 0 :
262
282
return (< random_double_0> func)(state)
@@ -267,8 +287,15 @@ cdef object cont(aug_state* state, void* func, object size, object lock, int nar
267
287
elif narg == 3 :
268
288
return (< random_double_3> func)(state, _a, _b, _c)
269
289
270
- cdef np.npy_intp i, n = compute_numel(size)
271
- cdef np.ndarray randoms = np.empty(n, np.double)
290
+ cdef np.npy_intp i, n
291
+ cdef np.ndarray randoms
292
+ if out is None :
293
+ n = compute_numel(size)
294
+ randoms = np.empty(n, np.double)
295
+ else :
296
+ randoms = < np.ndarray> out
297
+ n = np.PyArray_SIZE(randoms)
298
+
272
299
cdef double * randoms_data = < double * > np.PyArray_DATA(randoms)
273
300
cdef random_double_0 f0;
274
301
cdef random_double_1 f1;
@@ -293,7 +320,10 @@ cdef object cont(aug_state* state, void* func, object size, object lock, int nar
293
320
for i in range (n):
294
321
randoms_data[i] = f3(state, _a, _b, _c)
295
322
296
- return np.asarray(randoms).reshape(size)
323
+ if out is None :
324
+ return np.asarray(randoms).reshape(size)
325
+ else :
326
+ return out
297
327
298
328
cdef object discrete_broadcast_d(aug_state* state, void * func, object size, object lock,
299
329
np.ndarray a_arr, object a_name, constraint_type a_constraint):
@@ -602,7 +632,8 @@ cdef object disc(aug_state* state, void* func, object size, object lock,
602
632
603
633
604
634
cdef object cont_broadcast_float_1(aug_state* state, void * func, object size, object lock,
605
- np.ndarray a_arr, object a_name, constraint_type a_constraint):
635
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
636
+ object out):
606
637
607
638
cdef np.ndarray randoms
608
639
cdef float a_val
@@ -614,12 +645,14 @@ cdef object cont_broadcast_float_1(aug_state* state, void* func, object size, ob
614
645
if a_constraint != CONS_NONE:
615
646
check_array_constraint(a_arr, a_name, a_constraint)
616
647
617
- if size is not None :
648
+ if size is not None and out is None :
618
649
randoms = < np.ndarray> np.empty(size, np.float32)
619
- else :
650
+ elif out is None :
620
651
randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr),
621
652
np.PyArray_DIMS(a_arr),
622
653
np.NPY_FLOAT32)
654
+ else :
655
+ randoms = < np.ndarray> out
623
656
624
657
randoms_data = < float * > np.PyArray_DATA(randoms)
625
658
n = np.PyArray_SIZE(randoms)
@@ -635,36 +668,46 @@ cdef object cont_broadcast_float_1(aug_state* state, void* func, object size, ob
635
668
return randoms
636
669
637
670
cdef object cont_float(aug_state* state, void * func, object size, object lock,
638
- object a, object a_name, constraint_type a_constraint):
671
+ object a, object a_name, constraint_type a_constraint,
672
+ object out):
639
673
640
674
cdef np.ndarray a_arr, b_arr, c_arr
641
675
cdef float _a
642
676
cdef bint is_scalar = True
643
677
cdef int requirements = np.NPY_ALIGNED | np.NPY_FORCECAST
644
-
678
+ check_output(out, np.float32, size)
645
679
a_arr = < np.ndarray> np.PyArray_FROMANY(a, np.NPY_FLOAT32, 0 , 0 , requirements)
646
680
# a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_FLOAT32, np.NPY_ALIGNED)
647
681
is_scalar = np.PyArray_NDIM(a_arr) == 0
648
682
649
683
if not is_scalar:
650
- return cont_broadcast_float_1(state, func, size, lock, a_arr, a_name, a_constraint)
684
+ return cont_broadcast_float_1(state, func, size, lock, a_arr, a_name, a_constraint, out )
651
685
652
686
_a = < float > PyFloat_AsDouble(a)
653
687
if a_constraint != CONS_NONE:
654
688
check_constraint(_a, a_name, a_constraint)
655
689
656
- if size is None :
690
+ if size is None and out is None :
657
691
with lock:
658
692
return (< random_float_1> func)(state, _a)
659
693
660
- cdef np.npy_intp i, n = compute_numel(size)
661
- cdef np.ndarray randoms = np.empty(n, np.float32)
694
+ cdef np.npy_intp i, n
695
+ cdef np.ndarray randoms
696
+ if out is None :
697
+ n = compute_numel(size)
698
+ randoms = np.empty(n, np.float32)
699
+ else :
700
+ randoms = < np.ndarray> out
701
+ n = np.PyArray_SIZE(randoms)
702
+
662
703
cdef float * randoms_data = < float * > np.PyArray_DATA(randoms)
663
704
cdef random_float_1 f1 = < random_float_1> func;
664
705
665
706
with lock, nogil:
666
707
for i in range (n):
667
708
randoms_data[i] = f1(state, _a)
668
709
669
- return np.asarray(randoms).reshape(size)
670
-
710
+ if out is None :
711
+ return np.asarray(randoms).reshape(size)
712
+ else :
713
+ return out
0 commit comments