@@ -45,14 +45,20 @@ class TypeDescription:
45
45
astype : dict or None, optional
46
46
If astype['x'] is 'y', uses PyUFunc_x_x_As_y_y/PyUFunc_xx_x_As_yy_y
47
47
instead of PyUFunc_x_x/PyUFunc_xx_x.
48
+ cfunc_alias : str or none, optional
49
+ Appended to inner loop C function name, e.g., FLOAT_{cfunc_alias}. See make_arrays.
50
+ NOTE: it doesn't support 'astype'
48
51
simd: list
49
52
Available SIMD ufunc loops, dispatched at runtime in specified order
50
53
Currently only supported for simples types (see make_arrays)
51
- dispatch: list
52
- Available SIMD ufunc loops, dispatched at runtime in specified order
53
- Currently only supported for simples types (see make_arrays)
54
+ dispatch: str or None, optional
55
+ Dispatch-able source name without its extension '.dispatch.c' that
56
+ contains the definition of ufunc, dispatched at runtime depending on the
57
+ specified targets of the dispatch-able source.
58
+ NOTE: it doesn't support 'astype'
54
59
"""
55
- def __init__ (self , type , f = None , in_ = None , out = None , astype = None , simd = None , dispatch = None ):
60
+ def __init__ (self , type , f = None , in_ = None , out = None , astype = None , cfunc_alias = None ,
61
+ simd = None , dispatch = None ):
56
62
self .type = type
57
63
self .func_data = f
58
64
if astype is None :
@@ -64,6 +70,7 @@ def __init__(self, type, f=None, in_=None, out=None, astype=None, simd=None, dis
64
70
if out is not None :
65
71
out = out .replace ('P' , type )
66
72
self .out = out
73
+ self .cfunc_alias = cfunc_alias
67
74
self .simd = simd
68
75
self .dispatch = dispatch
69
76
@@ -90,7 +97,8 @@ def build_func_data(types, f):
90
97
func_data = [_fdata_map .get (t , '%s' ) % (f ,) for t in types ]
91
98
return func_data
92
99
93
- def TD (types , f = None , astype = None , in_ = None , out = None , simd = None , dispatch = None ):
100
+ def TD (types , f = None , astype = None , in_ = None , out = None , cfunc_alias = None ,
101
+ simd = None , dispatch = None ):
94
102
if f is not None :
95
103
if isinstance (f , str ):
96
104
func_data = build_func_data (types , f )
@@ -119,13 +127,15 @@ def TD(types, f=None, astype=None, in_=None, out=None, simd=None, dispatch=None)
119
127
simdt = [k for k , v in simd if t in v ]
120
128
else :
121
129
simdt = []
130
+
122
131
# [(dispatch file name without extension '.dispatch.c*', list of types)]
123
132
if dispatch :
124
- dispt = [k for k , v in dispatch if t in v ]
133
+ dispt = ( [k for k , v in dispatch if t in v ] + [ None ])[ 0 ]
125
134
else :
126
- dispt = []
135
+ dispt = None
127
136
tds .append (TypeDescription (
128
- t , f = fd , in_ = i , out = o , astype = astype , simd = simdt , dispatch = dispt
137
+ t , f = fd , in_ = i , out = o , astype = astype , cfunc_alias = cfunc_alias ,
138
+ simd = simdt , dispatch = dispt
129
139
))
130
140
return tds
131
141
@@ -280,7 +290,7 @@ def english_upper(s):
280
290
Ufunc (2 , 1 , Zero ,
281
291
docstrings .get ('numpy.core.umath.add' ),
282
292
'PyUFunc_AdditionTypeResolver' ,
283
- TD (notimes_or_obj , simd = [('avx512f ' , cmplxvec ),( 'avx2 ' , ints )]),
293
+ TD (notimes_or_obj , simd = [('avx2 ' , ints )], dispatch = [( 'loops_arithm_fp ' , 'fdFD' )]),
284
294
[TypeDescription ('M' , FullTypeDescr , 'Mm' , 'M' ),
285
295
TypeDescription ('m' , FullTypeDescr , 'mm' , 'm' ),
286
296
TypeDescription ('M' , FullTypeDescr , 'mM' , 'M' ),
@@ -291,7 +301,7 @@ def english_upper(s):
291
301
Ufunc (2 , 1 , None , # Zero is only a unit to the right, not the left
292
302
docstrings .get ('numpy.core.umath.subtract' ),
293
303
'PyUFunc_SubtractionTypeResolver' ,
294
- TD (ints + inexact , simd = [('avx512f ' , cmplxvec ),( 'avx2 ' , ints )]),
304
+ TD (ints + inexact , simd = [('avx2 ' , ints )], dispatch = [( 'loops_arithm_fp ' , 'fdFD' )]),
295
305
[TypeDescription ('M' , FullTypeDescr , 'Mm' , 'M' ),
296
306
TypeDescription ('m' , FullTypeDescr , 'mm' , 'm' ),
297
307
TypeDescription ('M' , FullTypeDescr , 'MM' , 'm' ),
@@ -302,7 +312,7 @@ def english_upper(s):
302
312
Ufunc (2 , 1 , One ,
303
313
docstrings .get ('numpy.core.umath.multiply' ),
304
314
'PyUFunc_MultiplicationTypeResolver' ,
305
- TD (notimes_or_obj , simd = [('avx512f ' , cmplxvec ),( 'avx2 ' , ints )]),
315
+ TD (notimes_or_obj , simd = [('avx2 ' , ints )], dispatch = [( 'loops_arithm_fp ' , 'fdFD' )]),
306
316
[TypeDescription ('m' , FullTypeDescr , 'mq' , 'm' ),
307
317
TypeDescription ('m' , FullTypeDescr , 'qm' , 'm' ),
308
318
TypeDescription ('m' , FullTypeDescr , 'md' , 'm' ),
@@ -326,10 +336,10 @@ def english_upper(s):
326
336
Ufunc (2 , 1 , None , # One is only a unit to the right, not the left
327
337
docstrings .get ('numpy.core.umath.true_divide' ),
328
338
'PyUFunc_TrueDivisionTypeResolver' ,
329
- TD (flts + cmplx ),
330
- [TypeDescription ('m' , FullTypeDescr , 'mq' , 'm' ),
331
- TypeDescription ('m' , FullTypeDescr , 'md' , 'm' ),
332
- TypeDescription ('m' , FullTypeDescr , 'mm' , 'd' ),
339
+ TD (flts + cmplx , cfunc_alias = 'divide' , dispatch = [( 'loops_arithm_fp' , 'fd' )] ),
340
+ [TypeDescription ('m' , FullTypeDescr , 'mq' , 'm' , cfunc_alias = 'divide' ),
341
+ TypeDescription ('m' , FullTypeDescr , 'md' , 'm' , cfunc_alias = 'divide' ),
342
+ TypeDescription ('m' , FullTypeDescr , 'mm' , 'd' , cfunc_alias = 'divide' ),
333
343
],
334
344
TD (O , f = 'PyNumber_TrueDivide' ),
335
345
),
@@ -1000,6 +1010,7 @@ def make_arrays(funcdict):
1000
1010
# later
1001
1011
code1list = []
1002
1012
code2list = []
1013
+ dispdict = {}
1003
1014
names = sorted (funcdict .keys ())
1004
1015
for name in names :
1005
1016
uf = funcdict [name ]
@@ -1010,44 +1021,33 @@ def make_arrays(funcdict):
1010
1021
sub = 0
1011
1022
1012
1023
for t in uf .type_descriptions :
1024
+ cfunc_alias = t .cfunc_alias if t .cfunc_alias else name
1025
+ cfunc_fname = None
1013
1026
if t .func_data is FullTypeDescr :
1014
1027
tname = english_upper (chartoname [t .type ])
1015
1028
datalist .append ('(void *)NULL' )
1016
- funclist .append (
1017
- '%s_%s_%s_%s' % (tname , t .in_ , t .out , name ))
1029
+ cfunc_fname = f"{ tname } _{ t .in_ } _{ t .out } _{ cfunc_alias } "
1018
1030
elif isinstance (t .func_data , FuncNameSuffix ):
1019
1031
datalist .append ('(void *)NULL' )
1020
1032
tname = english_upper (chartoname [t .type ])
1021
- funclist .append (
1022
- '%s_%s_%s' % (tname , name , t .func_data .suffix ))
1033
+ cfunc_fname = f"{ tname } _{ cfunc_alias } _{ t .func_data .suffix } "
1023
1034
elif t .func_data is None :
1024
1035
datalist .append ('(void *)NULL' )
1025
1036
tname = english_upper (chartoname [t .type ])
1026
- funclist . append ( '%s_%s' % ( tname , name ))
1037
+ cfunc_fname = f" { tname } _ { cfunc_alias } "
1027
1038
if t .simd is not None :
1028
1039
for vt in t .simd :
1029
1040
code2list .append (textwrap .dedent ("""\
1030
1041
#ifdef HAVE_ATTRIBUTE_TARGET_{ISA}
1031
1042
if (NPY_CPU_HAVE({ISA})) {{
1032
- {fname}_functions[{idx}] = {type}_{fname }_{isa};
1043
+ {fname}_functions[{idx}] = {cname }_{isa};
1033
1044
}}
1034
1045
#endif
1035
1046
""" ).format (
1036
1047
ISA = vt .upper (), isa = vt ,
1037
- fname = name , type = tname , idx = k
1038
- ))
1039
- if t .dispatch is not None :
1040
- for dname in t .dispatch :
1041
- code2list .append (textwrap .dedent ("""\
1042
- #ifndef NPY_DISABLE_OPTIMIZATION
1043
- #include "{dname}.dispatch.h"
1044
- #endif
1045
- NPY_CPU_DISPATCH_CALL_XB({name}_functions[{k}] = {tname}_{name});
1046
- """ ).format (
1047
- dname = dname , name = name , tname = tname , k = k
1048
+ fname = name , cname = cfunc_fname , idx = k
1048
1049
))
1049
1050
else :
1050
- funclist .append ('NULL' )
1051
1051
try :
1052
1052
thedict = arity_lookup [uf .nin , uf .nout ]
1053
1053
except KeyError as e :
@@ -1077,6 +1077,13 @@ def make_arrays(funcdict):
1077
1077
#datalist.append('(void *)%s' % t.func_data)
1078
1078
sub += 1
1079
1079
1080
+ if cfunc_fname :
1081
+ funclist .append (cfunc_fname )
1082
+ if t .dispatch :
1083
+ dispdict .setdefault (t .dispatch , []).append ((name , k , cfunc_fname ))
1084
+ else :
1085
+ funclist .append ('NULL' )
1086
+
1080
1087
for x in t .in_ + t .out :
1081
1088
siglist .append ('NPY_%s' % (english_upper (chartoname [x ]),))
1082
1089
@@ -1091,6 +1098,17 @@ def make_arrays(funcdict):
1091
1098
% (name , datanames ))
1092
1099
code1list .append ("static char %s_signatures[] = {%s};"
1093
1100
% (name , signames ))
1101
+
1102
+ for dname , funcs in dispdict .items ():
1103
+ code2list .append (textwrap .dedent (f"""
1104
+ #ifndef NPY_DISABLE_OPTIMIZATION
1105
+ #include "{ dname } .dispatch.h"
1106
+ #endif
1107
+ """ ))
1108
+ for (ufunc_name , func_idx , cfunc_name ) in funcs :
1109
+ code2list .append (textwrap .dedent (f"""\
1110
+ NPY_CPU_DISPATCH_CALL_XB({ ufunc_name } _functions[{ func_idx } ] = { cfunc_name } );
1111
+ """ ))
1094
1112
return "\n " .join (code1list ), "\n " .join (code2list )
1095
1113
1096
1114
def make_ufuncs (funcdict ):
0 commit comments