10
10
import ufunc_docstrings as docstrings
11
11
sys .path .pop (0 )
12
12
13
- Zero = "PyUFunc_Zero"
14
- One = "PyUFunc_One"
15
- None_ = "PyUFunc_None"
16
- AllOnes = "PyUFunc_MinusOne"
17
- ReorderableNone = "PyUFunc_ReorderableNone"
13
+ Zero = "PyInt_FromLong(0)"
14
+ One = "PyInt_FromLong(1)"
15
+ True_ = "(Py_INCREF(Py_True), Py_True)"
16
+ False_ = "(Py_INCREF(Py_False), Py_False)"
17
+ None_ = object ()
18
+ AllOnes = "PyInt_FromLong(-1)"
19
+ MinusInfinity = 'PyFloat_FromDouble(-NPY_INFINITY)'
20
+ ReorderableNone = "(Py_INCREF(Py_None), Py_None)"
18
21
19
22
# Sentinel value to specify using the full type description in the
20
23
# function name
@@ -458,7 +461,7 @@ def english_upper(s):
458
461
[TypeDescription ('O' , FullTypeDescr , 'OO' , 'O' )],
459
462
),
460
463
'logical_and' :
461
- Ufunc (2 , 1 , One ,
464
+ Ufunc (2 , 1 , True_ ,
462
465
docstrings .get ('numpy.core.umath.logical_and' ),
463
466
'PyUFunc_SimpleBinaryComparisonTypeResolver' ,
464
467
TD (nodatetime_or_obj , out = '?' , simd = [('avx2' , ints )]),
@@ -472,14 +475,14 @@ def english_upper(s):
472
475
TD (O , f = 'npy_ObjectLogicalNot' ),
473
476
),
474
477
'logical_or' :
475
- Ufunc (2 , 1 , Zero ,
478
+ Ufunc (2 , 1 , False_ ,
476
479
docstrings .get ('numpy.core.umath.logical_or' ),
477
480
'PyUFunc_SimpleBinaryComparisonTypeResolver' ,
478
481
TD (nodatetime_or_obj , out = '?' , simd = [('avx2' , ints )]),
479
482
TD (O , f = 'npy_ObjectLogicalOr' ),
480
483
),
481
484
'logical_xor' :
482
- Ufunc (2 , 1 , Zero ,
485
+ Ufunc (2 , 1 , False_ ,
483
486
docstrings .get ('numpy.core.umath.logical_xor' ),
484
487
'PyUFunc_SimpleBinaryComparisonTypeResolver' ,
485
488
TD (nodatetime_or_obj , out = '?' ),
@@ -514,7 +517,7 @@ def english_upper(s):
514
517
TD (O , f = 'npy_ObjectMin' )
515
518
),
516
519
'logaddexp' :
517
- Ufunc (2 , 1 , None ,
520
+ Ufunc (2 , 1 , MinusInfinity ,
518
521
docstrings .get ('numpy.core.umath.logaddexp' ),
519
522
None ,
520
523
TD (flts , f = "logaddexp" , astype = {'e' :'f' })
@@ -1048,18 +1051,38 @@ def make_ufuncs(funcdict):
1048
1051
# do not play well with \n
1049
1052
docstring = '\\ n\" \" ' .join (docstring .split (r"\n" ))
1050
1053
fmt = textwrap .dedent ("""\
1051
- f = PyUFunc_FromFuncAndData(
1054
+ identity = {identity_expr};
1055
+ if ({has_identity} && identity == NULL) {{
1056
+ return -1;
1057
+ }}
1058
+ f = PyUFunc_FromFuncAndDataAndSignatureAndIdentity(
1052
1059
{name}_functions, {name}_data, {name}_signatures, {nloops},
1053
1060
{nin}, {nout}, {identity}, "{name}",
1054
- "{doc}", 0
1061
+ "{doc}", 0, NULL, identity
1055
1062
);
1063
+ if ({has_identity}) {{
1064
+ Py_DECREF(identity);
1065
+ }}
1056
1066
if (f == NULL) {{
1057
1067
return -1;
1058
- }}""" )
1059
- mlist .append (fmt .format (
1068
+ }}
1069
+ """ )
1070
+ args = dict (
1060
1071
name = name , nloops = len (uf .type_descriptions ),
1061
- nin = uf .nin , nout = uf .nout , identity = uf .identity , doc = docstring
1062
- ))
1072
+ nin = uf .nin , nout = uf .nout ,
1073
+ has_identity = '0' if uf .identity is None_ else '1' ,
1074
+ identity = 'PyUFunc_IdentityValue' ,
1075
+ identity_expr = uf .identity ,
1076
+ doc = docstring
1077
+ )
1078
+
1079
+ # Only PyUFunc_None means don't reorder - we pass this using the old
1080
+ # argument
1081
+ if uf .identity is None_ :
1082
+ args ['identity' ] = 'PyUFunc_None'
1083
+ args ['identity_expr' ] = 'NULL'
1084
+
1085
+ mlist .append (fmt .format (** args ))
1063
1086
if uf .typereso is not None :
1064
1087
mlist .append (
1065
1088
r"((PyUFuncObject *)f)->type_resolver = &%s;" % uf .typereso )
@@ -1087,7 +1110,7 @@ def make_code(funcdict, filename):
1087
1110
1088
1111
static int
1089
1112
InitOperators(PyObject *dictionary) {
1090
- PyObject *f;
1113
+ PyObject *f, *identity ;
1091
1114
1092
1115
%s
1093
1116
%s
0 commit comments