70
70
static int
71
71
_does_loop_use_arrays (void * data );
72
72
73
- static int
74
- assign_reduce_identity_zero (PyArrayObject * result , void * data );
75
-
76
- static int
77
- assign_reduce_identity_minusone (PyArrayObject * result , void * data );
78
-
79
- static int
80
- assign_reduce_identity_one (PyArrayObject * result , void * data );
81
-
82
-
83
73
/*UFUNC_API*/
84
74
NPY_NO_EXPORT int
85
75
PyUFunc_getfperr (void )
@@ -1847,6 +1837,42 @@ _get_coredim_sizes(PyUFuncObject *ufunc, PyArrayObject **op,
1847
1837
return 0 ;
1848
1838
}
1849
1839
1840
+ /*
1841
+ * Returns a new reference
1842
+ * TODO: store a reference in the ufunc object itself, rather than
1843
+ * constructing one each time
1844
+ */
1845
+ static PyObject *
1846
+ _get_identity (PyUFuncObject * ufunc , npy_bool * reorderable ) {
1847
+ switch (ufunc -> identity ) {
1848
+ case PyUFunc_One :
1849
+ * reorderable = 1 ;
1850
+ return PyInt_FromLong (1 );
1851
+
1852
+ case PyUFunc_Zero :
1853
+ * reorderable = 1 ;
1854
+ return PyInt_FromLong (0 );
1855
+
1856
+ case PyUFunc_MinusOne :
1857
+ * reorderable = 1 ;
1858
+ return PyInt_FromLong (-1 );
1859
+
1860
+ case PyUFunc_ReorderableNone :
1861
+ * reorderable = 1 ;
1862
+ Py_RETURN_NONE ;
1863
+
1864
+ case PyUFunc_None :
1865
+ * reorderable = 0 ;
1866
+ Py_RETURN_NONE ;
1867
+
1868
+ default :
1869
+ PyErr_Format (PyExc_ValueError ,
1870
+ "ufunc %s has an invalid identity" , ufunc_get_name_cstr (ufunc ));
1871
+ return NULL ;
1872
+ }
1873
+ }
1874
+
1875
+
1850
1876
static int
1851
1877
PyUFunc_GeneralizedFunction (PyUFuncObject * ufunc ,
1852
1878
PyObject * args , PyObject * kwds ,
@@ -2249,34 +2275,27 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
2249
2275
* product of two zero-length arrays will be a scalar,
2250
2276
* which has size one.
2251
2277
*/
2278
+ npy_bool reorderable ;
2279
+ PyObject * identity = _get_identity (ufunc , & reorderable );
2280
+ if (identity == NULL ) {
2281
+ retval = -1 ;
2282
+ goto fail ;
2283
+ }
2284
+
2252
2285
for (i = nin ; i < nop ; ++ i ) {
2253
2286
if (PyArray_SIZE (op [i ]) != 0 ) {
2254
- switch (ufunc -> identity ) {
2255
- case PyUFunc_Zero :
2256
- assign_reduce_identity_zero (op [i ], NULL );
2257
- break ;
2258
- case PyUFunc_One :
2259
- assign_reduce_identity_one (op [i ], NULL );
2260
- break ;
2261
- case PyUFunc_MinusOne :
2262
- assign_reduce_identity_minusone (op [i ], NULL );
2263
- break ;
2264
- case PyUFunc_None :
2265
- case PyUFunc_ReorderableNone :
2266
- PyErr_Format (PyExc_ValueError ,
2267
- "ufunc %s " ,
2268
- ufunc_name );
2269
- retval = -1 ;
2270
- goto fail ;
2271
- default :
2272
- PyErr_Format (PyExc_ValueError ,
2273
- "ufunc %s has an invalid identity for reduction" ,
2274
- ufunc_name );
2275
- retval = -1 ;
2276
- goto fail ;
2287
+ if (identity == Py_None ) {
2288
+ PyErr_Format (PyExc_ValueError ,
2289
+ "ufunc %s " ,
2290
+ ufunc_name );
2291
+ Py_DECREF (identity );
2292
+ retval = -1 ;
2293
+ goto fail ;
2277
2294
}
2295
+ PyArray_FillWithScalar (op [i ], identity );
2278
2296
}
2279
2297
}
2298
+ Py_DECREF (identity );
2280
2299
}
2281
2300
2282
2301
/* Check whether any errors occurred during the loop */
@@ -2665,31 +2684,6 @@ reduce_type_resolver(PyUFuncObject *ufunc, PyArrayObject *arr,
2665
2684
return 0 ;
2666
2685
}
2667
2686
2668
- static int
2669
- assign_reduce_identity_zero (PyArrayObject * result , void * NPY_UNUSED (data ))
2670
- {
2671
- return PyArray_FillWithScalar (result , PyArrayScalar_False );
2672
- }
2673
-
2674
- static int
2675
- assign_reduce_identity_one (PyArrayObject * result , void * NPY_UNUSED (data ))
2676
- {
2677
- return PyArray_FillWithScalar (result , PyArrayScalar_True );
2678
- }
2679
-
2680
- static int
2681
- assign_reduce_identity_minusone (PyArrayObject * result , void * NPY_UNUSED (data ))
2682
- {
2683
- static PyObject * MinusOne = NULL ;
2684
-
2685
- if (MinusOne == NULL ) {
2686
- if ((MinusOne = PyInt_FromLong (-1 )) == NULL ) {
2687
- return -1 ;
2688
- }
2689
- }
2690
- return PyArray_FillWithScalar (result , MinusOne );
2691
- }
2692
-
2693
2687
static int
2694
2688
reduce_loop (NpyIter * iter , char * * dataptrs , npy_intp * strides ,
2695
2689
npy_intp * countptr , NpyIter_IterNextFunc * iternext ,
@@ -2795,11 +2789,12 @@ static PyArrayObject *
2795
2789
PyUFunc_Reduce (PyUFuncObject * ufunc , PyArrayObject * arr , PyArrayObject * out ,
2796
2790
int naxes , int * axes , PyArray_Descr * odtype , int keepdims )
2797
2791
{
2798
- int iaxes , reorderable , ndim ;
2792
+ int iaxes , ndim ;
2793
+ npy_bool reorderable ;
2799
2794
npy_bool axis_flags [NPY_MAXDIMS ];
2800
2795
PyArray_Descr * dtype ;
2801
2796
PyArrayObject * result ;
2802
- PyArray_AssignReduceIdentityFunc * assign_identity = NULL ;
2797
+ PyObject * identity = NULL ;
2803
2798
const char * ufunc_name = ufunc_get_name_cstr (ufunc );
2804
2799
/* These parameters come from a TLS global */
2805
2800
int buffersize = 0 , errormask = 0 ;
@@ -2820,72 +2815,41 @@ PyUFunc_Reduce(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
2820
2815
axis_flags [axis ] = 1 ;
2821
2816
}
2822
2817
2823
- switch (ufunc -> identity ) {
2824
- case PyUFunc_Zero :
2825
- assign_identity = & assign_reduce_identity_zero ;
2826
- reorderable = 1 ;
2827
- /*
2828
- * The identity for a dynamic dtype like
2829
- * object arrays can't be used in general
2830
- */
2831
- if (PyArray_ISOBJECT (arr ) && PyArray_SIZE (arr ) != 0 ) {
2832
- assign_identity = NULL ;
2833
- }
2834
- break ;
2835
- case PyUFunc_One :
2836
- assign_identity = & assign_reduce_identity_one ;
2837
- reorderable = 1 ;
2838
- /*
2839
- * The identity for a dynamic dtype like
2840
- * object arrays can't be used in general
2841
- */
2842
- if (PyArray_ISOBJECT (arr ) && PyArray_SIZE (arr ) != 0 ) {
2843
- assign_identity = NULL ;
2844
- }
2845
- break ;
2846
- case PyUFunc_MinusOne :
2847
- assign_identity = & assign_reduce_identity_minusone ;
2848
- reorderable = 1 ;
2849
- /*
2850
- * The identity for a dynamic dtype like
2851
- * object arrays can't be used in general
2852
- */
2853
- if (PyArray_ISOBJECT (arr ) && PyArray_SIZE (arr ) != 0 ) {
2854
- assign_identity = NULL ;
2855
- }
2856
- break ;
2857
-
2858
- case PyUFunc_None :
2859
- reorderable = 0 ;
2860
- break ;
2861
- case PyUFunc_ReorderableNone :
2862
- reorderable = 1 ;
2863
- break ;
2864
- default :
2865
- PyErr_Format (PyExc_ValueError ,
2866
- "ufunc %s has an invalid identity for reduction" ,
2867
- ufunc_name );
2868
- return NULL ;
2818
+ if (_get_bufsize_errmask (NULL , "reduce" , & buffersize , & errormask ) < 0 ) {
2819
+ return NULL ;
2869
2820
}
2870
2821
2871
- if (_get_bufsize_errmask (NULL , "reduce" , & buffersize , & errormask ) < 0 ) {
2822
+ /* Get the identity */
2823
+ identity = _get_identity (ufunc , & reorderable );
2824
+ if (identity == NULL ) {
2872
2825
return NULL ;
2873
2826
}
2827
+ /*
2828
+ * The identity for a dynamic dtype like
2829
+ * object arrays can't be used in general
2830
+ */
2831
+ if (identity != Py_None && PyArray_ISOBJECT (arr ) && PyArray_SIZE (arr ) != 0 ) {
2832
+ Py_DECREF (identity );
2833
+ identity = Py_None ;
2834
+ Py_INCREF (identity );
2835
+ }
2874
2836
2875
2837
/* Get the reduction dtype */
2876
2838
if (reduce_type_resolver (ufunc , arr , odtype , & dtype ) < 0 ) {
2839
+ Py_DECREF (identity );
2877
2840
return NULL ;
2878
2841
}
2879
2842
2880
2843
result = PyUFunc_ReduceWrapper (arr , out , NULL , dtype , dtype ,
2881
2844
NPY_UNSAFE_CASTING ,
2882
2845
axis_flags , reorderable ,
2883
2846
keepdims , 0 ,
2884
- assign_identity ,
2847
+ identity ,
2885
2848
reduce_loop ,
2886
2849
ufunc , buffersize , ufunc_name , errormask );
2887
2850
2888
2851
Py_DECREF (dtype );
2852
+ Py_DECREF (identity );
2889
2853
return result ;
2890
2854
}
2891
2855
@@ -5377,15 +5341,8 @@ ufunc_get_name(PyUFuncObject *ufunc)
5377
5341
static PyObject *
5378
5342
ufunc_get_identity (PyUFuncObject * ufunc )
5379
5343
{
5380
- switch (ufunc -> identity ) {
5381
- case PyUFunc_One :
5382
- return PyInt_FromLong (1 );
5383
- case PyUFunc_Zero :
5384
- return PyInt_FromLong (0 );
5385
- case PyUFunc_MinusOne :
5386
- return PyInt_FromLong (-1 );
5387
- }
5388
- Py_RETURN_NONE ;
5344
+ npy_bool reorderable ;
5345
+ return _get_identity (ufunc , & reorderable );
5389
5346
}
5390
5347
5391
5348
static PyObject *
0 commit comments