Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e6b99c9

Browse files
committed
MAINT: umath: generate the ldexp and frexp ufuncs like all the others.
1 parent af5ff55 commit e6b99c9

3 files changed

Lines changed: 103 additions & 97 deletions

File tree

numpy/core/code_generators/generate_umath.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,20 @@
2020
class FullTypeDescr(object):
2121
pass
2222

23+
class FuncNameSuffix(object):
24+
"""Stores the suffix to append when generating function names.
25+
"""
26+
def __init__(self, suffix):
27+
self.suffix = suffix
28+
2329
class TypeDescription(object):
2430
"""Type signature for a ufunc.
2531
2632
Attributes
2733
----------
2834
type : str
2935
Character representing the nominal type.
30-
func_data : str or None or FullTypeDescr, optional
36+
func_data : str or None or FullTypeDescr or FuncNameSuffix, optional
3137
The string representing the expression to insert into the data array, if
3238
any.
3339
in_ : str or None, optional
@@ -795,6 +801,30 @@ def english_upper(s):
795801
None,
796802
TD(flts),
797803
),
804+
'ldexp' :
805+
Ufunc(2, 1, None,
806+
docstrings.get('numpy.core.umath.ldexp'),
807+
None,
808+
[TypeDescription('e', None, 'ei', 'e'),
809+
TypeDescription('f', None, 'fi', 'f'),
810+
TypeDescription('e', FuncNameSuffix('long'), 'el', 'e'),
811+
TypeDescription('f', FuncNameSuffix('long'), 'fl', 'f'),
812+
TypeDescription('d', None, 'di', 'd'),
813+
TypeDescription('d', FuncNameSuffix('long'), 'dl', 'd'),
814+
TypeDescription('g', None, 'gi', 'g'),
815+
TypeDescription('g', FuncNameSuffix('long'), 'gl', 'g'),
816+
],
817+
),
818+
'frexp' :
819+
Ufunc(1, 2, None,
820+
docstrings.get('numpy.core.umath.frexp'),
821+
None,
822+
[TypeDescription('e', None, 'e', 'ei'),
823+
TypeDescription('f', None, 'f', 'fi'),
824+
TypeDescription('d', None, 'd', 'di'),
825+
TypeDescription('g', None, 'g', 'gi'),
826+
],
827+
)
798828
}
799829

800830
if sys.version_info[0] >= 3:
@@ -854,7 +884,7 @@ def make_arrays(funcdict):
854884
thedict = chartotype1 # one input and one output
855885

856886
for t in uf.type_descriptions:
857-
if t.func_data not in (None, FullTypeDescr):
887+
if t.func_data not in (None, FullTypeDescr) and not isinstance(t.func_data, FuncNameSuffix):
858888
funclist.append('NULL')
859889
astype = ''
860890
if not t.astype is None:
@@ -880,6 +910,10 @@ def make_arrays(funcdict):
880910
tname = english_upper(chartoname[t.type])
881911
datalist.append('(void *)NULL')
882912
funclist.append('%s_%s_%s_%s' % (tname, t.in_, t.out, name))
913+
elif isinstance(t.func_data, FuncNameSuffix):
914+
datalist.append('(void *)NULL')
915+
tname = english_upper(chartoname[t.type])
916+
funclist.append('%s_%s_%s' % (tname, name, t.func_data.suffix))
883917
else:
884918
datalist.append('(void *)NULL')
885919
tname = english_upper(chartoname[t.type])

numpy/core/code_generators/ufunc_docstrings.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3312,3 +3312,65 @@ def add_newdoc(place, name, doc):
33123312
array([0, 0, 0, 0, 1])
33133313
33143314
""")
3315+
3316+
add_newdoc('numpy.core.umath', 'ldexp',
3317+
"""
3318+
Scale floating point value by a power of 2, element-wise.
3319+
3320+
Equivalent to ``x1 * 2**x2``.
3321+
3322+
Parameters
3323+
----------
3324+
x1 : array_like
3325+
Input array to be scaled.
3326+
x2 : array_like
3327+
Input array of exponents.
3328+
3329+
Returns
3330+
-------
3331+
y: ndarray
3332+
The corresponding scaled values.
3333+
3334+
See Also
3335+
--------
3336+
frexp : Extract significand and exponent from floating point number
3337+
3338+
Examples
3339+
--------
3340+
>>> np.ldexp(0.5, np.arange(-1,4))
3341+
array([ 0.25, 0.5 , 1. , 2. , 4. ])
3342+
3343+
""")
3344+
3345+
add_newdoc('numpy.core.umath', 'frexp',
3346+
"""
3347+
Extract significand and exponent from a floating point number.
3348+
3349+
All floating point numbers are of the form: ``y1 * 2**y2`` where `y1`,
3350+
the significand, is a number between 0.5 and 1, or 0 and `y2`, the
3351+
exponent, is an integer.
3352+
3353+
Parameters
3354+
----------
3355+
x: array_like
3356+
Input array.
3357+
3358+
Returns
3359+
-------
3360+
y1 : ndarray
3361+
The normalized significands from `x`.
3362+
y2 : ndarray
3363+
The exponents from `x`.
3364+
3365+
See Also
3366+
--------
3367+
ldexp : Scale floating point number by power of 2
3368+
3369+
Examples
3370+
--------
3371+
>>> np.frexp([0.25, 0.5, 1, 2, 4])
3372+
(array([ 0.5, 0.5, 0.5, 0.5, 0.5]),
3373+
array([-1, 0, 1, 2, 3], dtype=int32))
3374+
3375+
""")
3376+

numpy/core/src/umath/umathmodule.c

Lines changed: 5 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -201,99 +201,6 @@ ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUS
201201
** SETUP UFUNCS **
202202
*****************************************************************************
203203
*/
204-
205-
/* Less automated additions to the ufuncs */
206-
207-
static PyUFuncGenericFunction frexp_functions[] = {
208-
#ifdef HAVE_FREXPF
209-
HALF_frexp,
210-
FLOAT_frexp,
211-
#endif
212-
DOUBLE_frexp
213-
#ifdef HAVE_FREXPL
214-
,LONGDOUBLE_frexp
215-
#endif
216-
};
217-
218-
static void * blank3_data[] = { (void *)NULL, (void *)NULL, (void *)NULL};
219-
static void * blank6_data[] = { (void *)NULL, (void *)NULL, (void *)NULL,
220-
(void *)NULL, (void *)NULL, (void *)NULL};
221-
static char frexp_signatures[] = {
222-
#ifdef HAVE_FREXPF
223-
NPY_HALF, NPY_HALF, NPY_INT,
224-
NPY_FLOAT, NPY_FLOAT, NPY_INT,
225-
#endif
226-
NPY_DOUBLE, NPY_DOUBLE, NPY_INT
227-
#ifdef HAVE_FREXPL
228-
,NPY_LONGDOUBLE, NPY_LONGDOUBLE, NPY_INT
229-
#endif
230-
};
231-
232-
#if NPY_SIZEOF_LONG == NPY_SIZEOF_INT
233-
#define LDEXP_LONG(typ) typ##_ldexp
234-
#else
235-
#define LDEXP_LONG(typ) typ##_ldexp_long
236-
#endif
237-
238-
static PyUFuncGenericFunction ldexp_functions[] = {
239-
#ifdef HAVE_LDEXPF
240-
HALF_ldexp,
241-
FLOAT_ldexp,
242-
LDEXP_LONG(HALF),
243-
LDEXP_LONG(FLOAT),
244-
#endif
245-
DOUBLE_ldexp,
246-
LDEXP_LONG(DOUBLE)
247-
#ifdef HAVE_LDEXPL
248-
,
249-
LONGDOUBLE_ldexp,
250-
LDEXP_LONG(LONGDOUBLE)
251-
#endif
252-
};
253-
254-
static char ldexp_signatures[] = {
255-
#ifdef HAVE_LDEXPF
256-
NPY_HALF, NPY_INT, NPY_HALF,
257-
NPY_FLOAT, NPY_INT, NPY_FLOAT,
258-
NPY_HALF, NPY_LONG, NPY_HALF,
259-
NPY_FLOAT, NPY_LONG, NPY_FLOAT,
260-
#endif
261-
NPY_DOUBLE, NPY_INT, NPY_DOUBLE,
262-
NPY_DOUBLE, NPY_LONG, NPY_DOUBLE
263-
#ifdef HAVE_LDEXPL
264-
,NPY_LONGDOUBLE, NPY_INT, NPY_LONGDOUBLE
265-
,NPY_LONGDOUBLE, NPY_LONG, NPY_LONGDOUBLE
266-
#endif
267-
};
268-
269-
static void
270-
InitOtherOperators(PyObject *dictionary) {
271-
PyObject *f;
272-
int num;
273-
274-
num = sizeof(frexp_functions) / sizeof(frexp_functions[0]);
275-
f = PyUFunc_FromFuncAndData(frexp_functions, blank3_data,
276-
frexp_signatures, num,
277-
1, 2, PyUFunc_None, "frexp",
278-
"Split the number, x, into a normalized"\
279-
" fraction (y1) and exponent (y2)",0);
280-
PyDict_SetItemString(dictionary, "frexp", f);
281-
Py_DECREF(f);
282-
283-
num = sizeof(ldexp_functions) / sizeof(ldexp_functions[0]);
284-
f = PyUFunc_FromFuncAndData(ldexp_functions, blank6_data, ldexp_signatures, num,
285-
2, 1, PyUFunc_None, "ldexp",
286-
"Compute y = x1 * 2**x2.",0);
287-
PyDict_SetItemString(dictionary, "ldexp", f);
288-
Py_DECREF(f);
289-
290-
#if defined(NPY_PY3K)
291-
f = PyDict_GetItemString(dictionary, "true_divide");
292-
PyDict_SetItemString(dictionary, "divide", f);
293-
#endif
294-
return;
295-
}
296-
297204
NPY_VISIBILITY_HIDDEN PyObject * npy_um_str_out = NULL;
298205
NPY_VISIBILITY_HIDDEN PyObject * npy_um_str_subok = NULL;
299206
NPY_VISIBILITY_HIDDEN PyObject * npy_um_str_array_prepare = NULL;
@@ -409,15 +316,18 @@ PyMODINIT_FUNC initumath(void)
409316
/* Load the ufunc operators into the array module's namespace */
410317
InitOperators(d);
411318

412-
InitOtherOperators(d);
413-
414319
PyDict_SetItemString(d, "pi", s = PyFloat_FromDouble(NPY_PI));
415320
Py_DECREF(s);
416321
PyDict_SetItemString(d, "e", s = PyFloat_FromDouble(NPY_E));
417322
Py_DECREF(s);
418323
PyDict_SetItemString(d, "euler_gamma", s = PyFloat_FromDouble(NPY_EULER));
419324
Py_DECREF(s);
420325

326+
#if defined(NPY_PY3K)
327+
s = PyDict_GetItemString(d, "true_divide");
328+
PyDict_SetItemString(d, "divide", s);
329+
#endif
330+
421331
#define ADDCONST(str) PyModule_AddIntConstant(m, #str, UFUNC_##str)
422332
#define ADDSCONST(str) PyModule_AddStringConstant(m, "UFUNC_" #str, UFUNC_##str)
423333

0 commit comments

Comments
 (0)