diff options
Diffstat (limited to 'numpy')
31 files changed, 2688 insertions, 712 deletions
diff --git a/numpy/core/SConscript b/numpy/core/SConscript index bb4ec36fc..5f7212387 100644 --- a/numpy/core/SConscript +++ b/numpy/core/SConscript @@ -408,7 +408,8 @@ env.Prepend(CPPPATH = ['src/private', 'include', '.', 'include/numpy']) # npymath core lib npymath_src = [env.GenerateFromTemplate(pjoin('src', 'npymath', 'npy_math.c.src')), env.GenerateFromTemplate(pjoin('src', 'npymath', 'npy_math_complex.c.src')), - env.GenerateFromTemplate(pjoin('src', 'npymath', 'ieee754.c.src'))] + env.GenerateFromTemplate(pjoin('src', 'npymath', 'ieee754.c.src')), + pjoin('src', 'npymath', 'halffloat.c')] env.DistutilsInstalledStaticExtLibrary("npymath", npymath_src, install_dir='lib') env.Prepend(LIBS=["npymath"]) env.Prepend(LIBPATH=["."]) diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index 5d19534e4..9382b1fae 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -31,10 +31,16 @@ class TypeDescription(object): The typecode(s) of the inputs. out : str or None, optional The typecode(s) of the outputs. + astype : dict or None, optional + If astype['x'] is 'y', uses PyUFunc_x_x_As_y_y/PyUFunc_xx_x_As_yy_y + instead of PyUFunc_x_x/PyUFunc_xx_x. """ - def __init__(self, type, f=None, in_=None, out=None): + def __init__(self, type, f=None, in_=None, out=None, astype=None): self.type = type self.func_data = f + if astype is None: + astype = {} + self.astype_dict = astype if in_ is not None: in_ = in_.replace('P', type) self.in_ = in_ @@ -49,8 +55,9 @@ class TypeDescription(object): if self.out is None: self.out = self.type * nout assert len(self.out) == nout + self.astype = self.astype_dict.get(self.type, None) -_fdata_map = dict(f='npy_%sf', d='npy_%s', g='npy_%sl', +_fdata_map = dict(e='npy_%sf', f='npy_%sf', d='npy_%s', g='npy_%sl', F='nc_%sf', D='nc_%s', G='nc_%sl') def build_func_data(types, f): func_data = [] @@ -59,7 +66,7 @@ def build_func_data(types, f): func_data.append(d) return func_data -def TD(types, f=None, in_=None, out=None): +def TD(types, f=None, astype=None, in_=None, out=None): if f is not None: if isinstance(f, str): func_data = build_func_data(types, f) @@ -78,7 +85,7 @@ def TD(types, f=None, in_=None, out=None): out = (None,) * len(types) tds = [] for t, fd, i, o in zip(types, func_data, in_, out): - tds.append(TypeDescription(t, f=fd, in_=i, out=o)) + tds.append(TypeDescription(t, f=fd, in_=i, out=o, astype=astype)) return tds class Ufunc(object): @@ -166,6 +173,7 @@ chartoname = {'?': 'bool', 'L': 'ulong', 'q': 'longlong', 'Q': 'ulonglong', + 'e': 'half', 'f': 'float', 'd': 'double', 'g': 'longdouble', @@ -180,7 +188,7 @@ chartoname = {'?': 'bool', 'P': 'OBJECT', } -all = '?bBhHiIlLqQfdgFDGOMm' +all = '?bBhHiIlLqQefdgFDGOMm' O = 'O' P = 'P' ints = 'bBhHiIlLqQ' @@ -188,7 +196,7 @@ times = 'Mm' intsO = ints + O bints = '?' + ints bintsO = bints + O -flts = 'fdg' +flts = 'efdg' fltsO = flts + O fltsP = flts + P cmplx = 'FDG' @@ -217,6 +225,10 @@ for code in 'bhilq': uint64 = english_upper(code) break +# This dictionary describes all the ufunc implementations, generating +# all the function names and their corresponding ufunc signatures. TD is +# an object which expands a list of character codes into an array of +# TypeDescriptions. defdict = { 'add' : Ufunc(2, 1, Zero, @@ -274,7 +286,7 @@ defdict = { Ufunc(2, 1, Zero, docstrings.get('numpy.core.umath.fmod'), TD(ints), - TD(flts, f='fmod'), + TD(flts, f='fmod', astype={'e':'f'}), TD(P, f='fmod'), ), 'square' : @@ -299,7 +311,7 @@ defdict = { Ufunc(2, 1, One, docstrings.get('numpy.core.umath.power'), TD(ints), - TD(inexact, f='pow'), + TD(inexact, f='pow', astype={'e':'f'}), TD(O, f='npy_ObjectPower'), ), 'absolute' : @@ -407,12 +419,12 @@ defdict = { 'logaddexp' : Ufunc(2, 1, None, docstrings.get('numpy.core.umath.logaddexp'), - TD(flts, f="logaddexp") + TD(flts, f="logaddexp", astype={'e':'f'}) ), 'logaddexp2' : Ufunc(2, 1, None, docstrings.get('numpy.core.umath.logaddexp2'), - TD(flts, f="logaddexp2") + TD(flts, f="logaddexp2", astype={'e':'f'}) ), # FIXME: decide if the times should have the bitwise operations. 'bitwise_and' : @@ -454,177 +466,177 @@ defdict = { 'degrees' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.degrees'), - TD(fltsP, f='degrees'), + TD(fltsP, f='degrees', astype={'e':'f'}), ), 'rad2deg' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.rad2deg'), - TD(fltsP, f='rad2deg'), + TD(fltsP, f='rad2deg', astype={'e':'f'}), ), 'radians' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.radians'), - TD(fltsP, f='radians'), + TD(fltsP, f='radians', astype={'e':'f'}), ), 'deg2rad' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.deg2rad'), - TD(fltsP, f='deg2rad'), + TD(fltsP, f='deg2rad', astype={'e':'f'}), ), 'arccos' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.arccos'), - TD(inexact, f='acos'), + TD(inexact, f='acos', astype={'e':'f'}), TD(P, f='arccos'), ), 'arccosh' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.arccosh'), - TD(inexact, f='acosh'), + TD(inexact, f='acosh', astype={'e':'f'}), TD(P, f='arccosh'), ), 'arcsin' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.arcsin'), - TD(inexact, f='asin'), + TD(inexact, f='asin', astype={'e':'f'}), TD(P, f='arcsin'), ), 'arcsinh' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.arcsinh'), - TD(inexact, f='asinh'), + TD(inexact, f='asinh', astype={'e':'f'}), TD(P, f='arcsinh'), ), 'arctan' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.arctan'), - TD(inexact, f='atan'), + TD(inexact, f='atan', astype={'e':'f'}), TD(P, f='arctan'), ), 'arctanh' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.arctanh'), - TD(inexact, f='atanh'), + TD(inexact, f='atanh', astype={'e':'f'}), TD(P, f='arctanh'), ), 'cos' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.cos'), - TD(inexact, f='cos'), + TD(inexact, f='cos', astype={'e':'f'}), TD(P, f='cos'), ), 'sin' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.sin'), - TD(inexact, f='sin'), + TD(inexact, f='sin', astype={'e':'f'}), TD(P, f='sin'), ), 'tan' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.tan'), - TD(inexact, f='tan'), + TD(inexact, f='tan', astype={'e':'f'}), TD(P, f='tan'), ), 'cosh' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.cosh'), - TD(inexact, f='cosh'), + TD(inexact, f='cosh', astype={'e':'f'}), TD(P, f='cosh'), ), 'sinh' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.sinh'), - TD(inexact, f='sinh'), + TD(inexact, f='sinh', astype={'e':'f'}), TD(P, f='sinh'), ), 'tanh' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.tanh'), - TD(inexact, f='tanh'), + TD(inexact, f='tanh', astype={'e':'f'}), TD(P, f='tanh'), ), 'exp' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.exp'), - TD(inexact, f='exp'), + TD(inexact, f='exp', astype={'e':'f'}), TD(P, f='exp'), ), 'exp2' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.exp2'), - TD(inexact, f='exp2'), + TD(inexact, f='exp2', astype={'e':'f'}), TD(P, f='exp2'), ), 'expm1' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.expm1'), - TD(inexact, f='expm1'), + TD(inexact, f='expm1', astype={'e':'f'}), TD(P, f='expm1'), ), 'log' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.log'), - TD(inexact, f='log'), + TD(inexact, f='log', astype={'e':'f'}), TD(P, f='log'), ), 'log2' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.log2'), - TD(inexact, f='log2'), + TD(inexact, f='log2', astype={'e':'f'}), TD(P, f='log2'), ), 'log10' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.log10'), - TD(inexact, f='log10'), + TD(inexact, f='log10', astype={'e':'f'}), TD(P, f='log10'), ), 'log1p' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.log1p'), - TD(inexact, f='log1p'), + TD(inexact, f='log1p', astype={'e':'f'}), TD(P, f='log1p'), ), 'sqrt' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.sqrt'), - TD(inexact, f='sqrt'), + TD(inexact, f='sqrt', astype={'e':'f'}), TD(P, f='sqrt'), ), 'ceil' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.ceil'), - TD(flts, f='ceil'), + TD(flts, f='ceil', astype={'e':'f'}), TD(P, f='ceil'), ), 'trunc' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.trunc'), - TD(flts, f='trunc'), + TD(flts, f='trunc', astype={'e':'f'}), TD(P, f='trunc'), ), 'fabs' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.fabs'), - TD(flts, f='fabs'), + TD(flts, f='fabs', astype={'e':'f'}), TD(P, f='fabs'), ), 'floor' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.floor'), - TD(flts, f='floor'), + TD(flts, f='floor', astype={'e':'f'}), TD(P, f='floor'), ), 'rint' : Ufunc(1, 1, None, docstrings.get('numpy.core.umath.rint'), - TD(inexact, f='rint'), + TD(inexact, f='rint', astype={'e':'f'}), TD(P, f='rint'), ), 'arctan2' : Ufunc(2, 1, None, docstrings.get('numpy.core.umath.arctan2'), - TD(flts, f='atan2'), + TD(flts, f='atan2', astype={'e':'f'}), TD(P, f='arctan2'), ), 'remainder' : @@ -636,7 +648,7 @@ defdict = { 'hypot' : Ufunc(2, 1, None, docstrings.get('numpy.core.umath.hypot'), - TD(flts, f='hypot'), + TD(flts, f='hypot', astype={'e':'f'}), TD(P, f='hypot'), ), 'isnan' : @@ -692,7 +704,8 @@ def indent(st,spaces): indented = re.sub(r' +$',r'',indented) return indented -chartotype1 = {'f': 'f_f', +chartotype1 = {'e': 'e_e', + 'f': 'f_f', 'd': 'd_d', 'g': 'g_g', 'F': 'F_F', @@ -701,7 +714,8 @@ chartotype1 = {'f': 'f_f', 'O': 'O_O', 'P': 'O_O_method'} -chartotype2 = {'f': 'ff_f', +chartotype2 = {'e': 'ee_e', + 'f': 'ff_f', 'd': 'dd_d', 'g': 'gg_g', 'F': 'FF_F', @@ -739,8 +753,11 @@ def make_arrays(funcdict): for t in uf.type_descriptions: if t.func_data not in (None, UsesArraysAsData): funclist.append('NULL') - astr = '%s_functions[%d] = PyUFunc_%s;' % \ - (name, k, thedict[t.type]) + astype = '' + if not t.astype is None: + astype = '_As_%s' % thedict[t.astype] + astr = '%s_functions[%d] = PyUFunc_%s%s;' % \ + (name, k, thedict[t.type], astype) code2list.append(astr) if t.type == 'O': astr = '%s_data[%d] = (void *) %s;' % \ diff --git a/numpy/core/code_generators/numpy_api.py b/numpy/core/code_generators/numpy_api.py index 2cc6411d5..9474a131a 100644 --- a/numpy/core/code_generators/numpy_api.py +++ b/numpy/core/code_generators/numpy_api.py @@ -64,6 +64,7 @@ multiarray_types_api = { 'PyTimeIntegerArrType_Type': 39, 'PyDatetimeArrType_Type': 40, 'PyTimedeltaArrType_Type': 41, + 'PyHalfArrType_Type': 221, } #define NPY_NUMUSERTYPES (*(int *)PyArray_API[6]) @@ -290,6 +291,12 @@ ufunc_funcs_api = { 'PyUFunc_ReplaceLoopBySignature': 30, 'PyUFunc_FromFuncAndDataAndSignature': 31, 'PyUFunc_SetUsesArraysAsData': 32, + 'PyUFunc_e_e': 33, + 'PyUFunc_e_e_As_f_f': 34, + 'PyUFunc_e_e_As_d_d': 35, + 'PyUFunc_ee_e': 36, + 'PyUFunc_ee_e_As_ff_f': 37, + 'PyUFunc_ee_e_As_dd_d': 38, } # List of all the dicts which define the C API diff --git a/numpy/core/getlimits.py b/numpy/core/getlimits.py index 4fa020e86..198862d6a 100644 --- a/numpy/core/getlimits.py +++ b/numpy/core/getlimits.py @@ -131,6 +131,10 @@ class finfo(object): itype = ntypes.longlong fmt = '%s' precname = 'long double' + elif dtype is ntypes.half: + itype = ntypes.int16 + fmt = '%12.5e' + precname = 'half' else: raise ValueError, repr(dtype) diff --git a/numpy/core/include/numpy/arrayscalars.h b/numpy/core/include/numpy/arrayscalars.h index 1f7f3c7e3..64450e713 100644 --- a/numpy/core/include/numpy/arrayscalars.h +++ b/numpy/core/include/numpy/arrayscalars.h @@ -71,6 +71,12 @@ typedef struct { typedef struct { PyObject_HEAD + npy_half obval; +} PyHalfScalarObject; + + +typedef struct { + PyObject_HEAD float obval; } PyFloatScalarObject; diff --git a/numpy/core/include/numpy/halffloat.h b/numpy/core/include/numpy/halffloat.h new file mode 100644 index 000000000..c6bb726bc --- /dev/null +++ b/numpy/core/include/numpy/halffloat.h @@ -0,0 +1,68 @@ +#ifndef __NPY_HALFFLOAT_H__ +#define __NPY_HALFFLOAT_H__ + +#include <Python.h> +#include <numpy/ndarraytypes.h> +#include <numpy/npy_math.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Half-precision routines + */ + +/* Conversions */ +float npy_half_to_float(npy_half h); +double npy_half_to_double(npy_half h); +npy_half npy_float_to_half(float f); +npy_half npy_double_to_half(double d); +/* Comparisons */ +int npy_half_eq(npy_half h1, npy_half h2); +int npy_half_ne(npy_half h1, npy_half h2); +int npy_half_le(npy_half h1, npy_half h2); +int npy_half_lt(npy_half h1, npy_half h2); +int npy_half_ge(npy_half h1, npy_half h2); +int npy_half_gt(npy_half h1, npy_half h2); +/* faster *_nonan variants for when you know h1 and h2 are not NaN */ +int npy_half_eq_nonan(npy_half h1, npy_half h2); +int npy_half_lt_nonan(npy_half h1, npy_half h2); +int npy_half_le_nonan(npy_half h1, npy_half h2); +/* Miscellaneous functions */ +int npy_half_iszero(npy_half h); +int npy_half_isnan(npy_half h); +int npy_half_isinf(npy_half h); +int npy_half_isfinite(npy_half h); +int npy_half_signbit(npy_half h); +npy_half npy_half_copysign(npy_half x, npy_half y); +npy_half npy_half_spacing(npy_half h); +npy_half npy_half_nextafter(npy_half x, npy_half y); + +/* + * Half-precision constants + */ + +#define NPY_HALF_ZERO (0x0000u) +#define NPY_HALF_PZERO (0x0000u) +#define NPY_HALF_NZERO (0x8000u) +#define NPY_HALF_ONE (0x3c00u) +#define NPY_HALF_NEGONE (0xbc00u) +#define NPY_HALF_PINF (0x7c00u) +#define NPY_HALF_NINF (0xfc00u) +#define NPY_HALF_NAN (0x7e00u) + +/* + * Bit-level conversions + */ + +npy_uint16 npy_floatbits_to_halfbits(npy_uint32 f); +npy_uint16 npy_doublebits_to_halfbits(npy_uint64 d); +npy_uint32 npy_halfbits_to_floatbits(npy_uint16 h); +npy_uint64 npy_halfbits_to_doublebits(npy_uint16 h); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h index e64ddea6d..98d02287a 100644 --- a/numpy/core/include/numpy/ndarraytypes.h +++ b/numpy/core/include/numpy/ndarraytypes.h @@ -65,10 +65,10 @@ enum NPY_TYPES { NPY_BOOL=0, NPY_INT, NPY_UINT, NPY_LONG, NPY_ULONG, NPY_LONGLONG, NPY_ULONGLONG, - NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE, + NPY_HALF, NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE, NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE, NPY_DATETIME, NPY_TIMEDELTA, - NPY_OBJECT=19, + NPY_OBJECT=20, NPY_STRING, NPY_UNICODE, NPY_VOID, NPY_NTYPES, @@ -88,6 +88,7 @@ enum NPY_TYPES { NPY_BOOL=0, /* default scalar priority */ #define NPY_SCALAR_PRIORITY -1000000.0 +/*TODO HALF - This is used as how many complex floating point types in the code */ /* How many floating point types are there */ #define NPY_NUM_FLOATTYPE 3 @@ -115,6 +116,7 @@ enum NPY_TYPECHAR { NPY_BOOLLTR = '?', NPY_ULONGLTR = 'L', NPY_LONGLONGLTR = 'q', NPY_ULONGLONGLTR = 'Q', + NPY_HALFLTR = 'e', NPY_FLOATLTR = 'f', NPY_DOUBLELTR = 'd', NPY_LONGDOUBLELTR = 'g', @@ -1230,7 +1232,7 @@ PyArrayNeighborhoodIter_Next2D(PyArrayNeighborhoodIterObject* iter); #define PyTypeNum_ISINTEGER(type) (((type) >= NPY_BYTE) && \ ((type) <= NPY_ULONGLONG)) -#define PyTypeNum_ISFLOAT(type) (((type) >= NPY_FLOAT) && \ +#define PyTypeNum_ISFLOAT(type) (((type) >= NPY_HALF) && \ ((type) <= NPY_LONGDOUBLE)) #define PyTypeNum_ISNUMBER(type) ((type) <= NPY_CLONGDOUBLE) diff --git a/numpy/core/include/numpy/noprefix.h b/numpy/core/include/numpy/noprefix.h index d4ccfc4a3..571c9d082 100644 --- a/numpy/core/include/numpy/noprefix.h +++ b/numpy/core/include/numpy/noprefix.h @@ -108,12 +108,14 @@ compatibility measure*/ #define SIZEOF_LONGDOUBLE NPY_SIZEOF_LONGDOUBLE #define SIZEOF_LONGLONG NPY_SIZEOF_LONGLONG +#define SIZEOF_HALF NPY_SIZEOF_HALF #define BITSOF_BOOL NPY_BITSOF_BOOL #define BITSOF_CHAR NPY_BITSOF_CHAR #define BITSOF_SHORT NPY_BITSOF_SHORT #define BITSOF_INT NPY_BITSOF_INT #define BITSOF_LONG NPY_BITSOF_LONG #define BITSOF_LONGLONG NPY_BITSOF_LONGLONG +#define BITSOF_HALF NPY_BITSOF_HALF #define BITSOF_FLOAT NPY_BITSOF_FLOAT #define BITSOF_DOUBLE NPY_BITSOF_DOUBLE #define BITSOF_LONGDOUBLE NPY_BITSOF_LONGDOUBLE diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h index 474f1c3af..998cfdaef 100644 --- a/numpy/core/include/numpy/npy_common.h +++ b/numpy/core/include/numpy/npy_common.h @@ -31,9 +31,11 @@ enum { #define NPY_UINT_FMT "u" #define NPY_LONG_FMT "ld" #define NPY_ULONG_FMT "lu" +#define NPY_HALF_FMT "g" #define NPY_FLOAT_FMT "g" #define NPY_DOUBLE_FMT "g" + #ifdef PY_LONG_LONG typedef PY_LONG_LONG npy_longlong; typedef unsigned PY_LONG_LONG npy_ulonglong; @@ -195,6 +197,7 @@ typedef struct { npy_longdouble real, imag; } npy_clongdouble; #define NPY_MIN_LONG LONG_MIN #define NPY_MAX_ULONG ULONG_MAX +#define NPY_SIZEOF_HALF 2 #define NPY_SIZEOF_DATETIME 8 #define NPY_SIZEOF_TIMEDELTA 8 @@ -204,6 +207,7 @@ typedef struct { npy_longdouble real, imag; } npy_clongdouble; #define NPY_BITSOF_INT (NPY_SIZEOF_INT * CHAR_BIT) #define NPY_BITSOF_LONG (NPY_SIZEOF_LONG * CHAR_BIT) #define NPY_BITSOF_LONGLONG (NPY_SIZEOF_LONGLONG * CHAR_BIT) +#define NPY_BITSOF_HALF (NPY_SIZEOF_HALF * CHAR_BIT) #define NPY_BITSOF_FLOAT (NPY_SIZEOF_FLOAT * CHAR_BIT) #define NPY_BITSOF_DOUBLE (NPY_SIZEOF_DOUBLE * CHAR_BIT) #define NPY_BITSOF_LONGDOUBLE (NPY_SIZEOF_LONGDOUBLE * CHAR_BIT) @@ -582,20 +586,7 @@ typedef struct { npy_longdouble real, imag; } npy_clongdouble; -#if NPY_BITSOF_DOUBLE == 16 -#ifndef NPY_FLOAT16 -#define NPY_FLOAT16 NPY_DOUBLE -#define NPY_COMPLEX32 NPY_CDOUBLE - typedef double npy_float16; - typedef npy_cdouble npy_complex32; -# define PyFloat16ScalarObject PyDoubleScalarObject -# define PyComplex32ScalarObject PyCDoubleScalarObject -# define PyFloat16ArrType_Type PyDoubleArrType_Type -# define PyComplex32ArrType_Type PyCDoubleArrType_Type -#define NPY_FLOAT16_FMT NPY_DOUBLE_FMT -#define NPY_COMPLEX32_FMT NPY_CDOUBLE_FMT -#endif -#elif NPY_BITSOF_DOUBLE == 32 +#if NPY_BITSOF_DOUBLE == 32 #ifndef NPY_FLOAT32 #define NPY_FLOAT32 NPY_DOUBLE #define NPY_COMPLEX64 NPY_CDOUBLE @@ -664,20 +655,7 @@ typedef struct { npy_longdouble real, imag; } npy_clongdouble; -#if NPY_BITSOF_FLOAT == 16 -#ifndef NPY_FLOAT16 -#define NPY_FLOAT16 NPY_FLOAT -#define NPY_COMPLEX32 NPY_CFLOAT - typedef float npy_float16; - typedef npy_cfloat npy_complex32; -# define PyFloat16ScalarObject PyFloatScalarObject -# define PyComplex32ScalarObject PyCFloatScalarObject -# define PyFloat16ArrType_Type PyFloatArrType_Type -# define PyComplex32ArrType_Type PyCFloatArrType_Type -#define NPY_FLOAT16_FMT NPY_FLOAT_FMT -#define NPY_COMPLEX32_FMT NPY_CFLOAT_FMT -#endif -#elif NPY_BITSOF_FLOAT == 32 +#if NPY_BITSOF_FLOAT == 32 #ifndef NPY_FLOAT32 #define NPY_FLOAT32 NPY_FLOAT #define NPY_COMPLEX64 NPY_CFLOAT @@ -744,21 +722,12 @@ typedef struct { npy_longdouble real, imag; } npy_clongdouble; #endif #endif +/* half/float16 isn't a floating-point type in C */ +#define NPY_FLOAT16 NPY_HALF +typedef npy_uint16 npy_half; +typedef npy_half npy_float16; -#if NPY_BITSOF_LONGDOUBLE == 16 -#ifndef NPY_FLOAT16 -#define NPY_FLOAT16 NPY_LONGDOUBLE -#define NPY_COMPLEX32 NPY_CLONGDOUBLE - typedef npy_longdouble npy_float16; - typedef npy_clongdouble npy_complex32; -# define PyFloat16ScalarObject PyLongDoubleScalarObject -# define PyComplex32ScalarObject PyCLongDoubleScalarObject -# define PyFloat16ArrType_Type PyLongDoubleArrType_Type -# define PyComplex32ArrType_Type PyCLongDoubleArrType_Type -#define NPY_FLOAT16_FMT NPY_LONGDOUBLE_FMT -#define NPY_COMPLEX32_FMT NPY_CLONGDOUBLE_FMT -#endif -#elif NPY_BITSOF_LONGDOUBLE == 32 +#if NPY_BITSOF_LONGDOUBLE == 32 #ifndef NPY_FLOAT32 #define NPY_FLOAT32 NPY_LONGDOUBLE #define NPY_COMPLEX64 NPY_CLONGDOUBLE diff --git a/numpy/core/include/numpy/old_defines.h b/numpy/core/include/numpy/old_defines.h index a9dfd5c21..8c83a70a2 100644 --- a/numpy/core/include/numpy/old_defines.h +++ b/numpy/core/include/numpy/old_defines.h @@ -23,6 +23,7 @@ #define PyArray_ULONG NPY_ULONG #define PyArray_LONGLONG NPY_LONGLONG #define PyArray_ULONGLONG NPY_ULONGLONG +#define PyArray_HALF NPY_HALF #define PyArray_FLOAT NPY_FLOAT #define PyArray_DOUBLE NPY_DOUBLE #define PyArray_LONGDOUBLE NPY_LONGDOUBLE @@ -99,6 +100,7 @@ #define PyArray_ULONGLTR NPY_ULONGLTR #define PyArray_LONGLONGLTR NPY_LONGLONGLTR #define PyArray_ULONGLONGLTR NPY_ULONGLONGLTR +#define PyArray_HALFLTR NPY_HALFLTR #define PyArray_FLOATLTR NPY_FLOATLTR #define PyArray_DOUBLELTR NPY_DOUBLELTR #define PyArray_LONGDOUBLELTR NPY_LONGDOUBLELTR diff --git a/numpy/core/include/numpy/ufuncobject.h b/numpy/core/include/numpy/ufuncobject.h index b795b5418..35d173cda 100644 --- a/numpy/core/include/numpy/ufuncobject.h +++ b/numpy/core/include/numpy/ufuncobject.h @@ -324,6 +324,8 @@ typedef struct _loop1d_info { #define generate_divbyzero_error() feraiseexcept(FE_DIVBYZERO) #define generate_overflow_error() feraiseexcept(FE_OVERFLOW) +#define generate_underflow_error() feraiseexcept(FE_UNDERFLOW) +#define generate_invalid_error() feraiseexcept(FE_INVALID) #elif defined(_AIX) @@ -343,6 +345,8 @@ typedef struct _loop1d_info { #define generate_divbyzero_error() fp_raise_xcp(FP_DIV_BY_ZERO) #define generate_overflow_error() fp_raise_xcp(FP_OVERFLOW) +#define generate_underflow_error() fp_raise_xcp(FP_UNDERFLOW) +#define generate_invalid_error() fp_raise_xcp(FP_INVALID) #else @@ -385,6 +389,32 @@ static void generate_overflow_error(void) { } #endif +#if !defined(generate_underflow_error) +static double numeric_small = 1e-300; +static void generate_underflow_error(void) { + double dummy; + dummy = numeric_small * 1e-300; + if (!dummy) + return; + else + numeric_small += 1e-300; + return; +} +#endif + +#if !defined(generate_invalid_error) +static double numeric_inv_inf = NPY_INF; +static void generate_invalid_error(void) { + double dummy; + dummy = numeric_inv_inf - NPY_INF; + if (!dummy) + return; + else + numeric_inv_inf += 1.0; + return; +} +#endif + /* Make sure it gets defined if it isn't already */ #ifndef UFUNC_NOFPE #define UFUNC_NOFPE diff --git a/numpy/core/numerictypes.py b/numpy/core/numerictypes.py index 74b44fdab..4f16d2e3a 100644 --- a/numpy/core/numerictypes.py +++ b/numpy/core/numerictypes.py @@ -65,6 +65,7 @@ Exported symbols include: | ulonglong +-> inexact | +-> floating (floatxx) (kind=f) + | | half | | single | | float_ (double) | | longfloat @@ -828,12 +829,12 @@ del key typecodes = {'Character':'c', 'Integer':'bhilqp', 'UnsignedInteger':'BHILQP', - 'Float':'fdg', + 'Float':'efdg', 'Complex':'FDG', 'AllInteger':'bBhHiIlLqQpP', - 'AllFloat':'fdgFDG', + 'AllFloat':'efdgFDG', 'Datetime': 'Mm', - 'All':'?bhilqpBHILQPfdgFDGSUVOMm'} + 'All':'?bhilqpBHILQPefdgFDGSUVOMm'} # backwards compatibility --- deprecated name typeDict = sctypeDict diff --git a/numpy/core/setup.py b/numpy/core/setup.py index f71ec108a..b854e879f 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -610,6 +610,8 @@ def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import get_cmd subpath = join('src', 'umath') + # NOTE: For manual template conversion of loops.h.src, read the note + # in that file. sources = [join(local_dir, subpath, 'loops.c.src'), join(local_dir, subpath, 'umathmodule.c.src')] @@ -660,7 +662,7 @@ def configuration(parent_package='',top_path=None): generate_numpyconfig_h, generate_numpy_api, ], - ) + libraries=['npymath']) # npymath needs the config.h and numpyconfig.h files to be generated, but # build_clib cannot handle generate_config_h and generate_numpyconfig_h @@ -692,6 +694,7 @@ def configuration(parent_package='',top_path=None): sources=[join('src', 'npymath', 'npy_math.c.src'), join('src', 'npymath', 'ieee754.c.src'), join('src', 'npymath', 'npy_math_complex.c.src'), + join('src', 'npymath', 'halffloat.c'), get_mathlib_info], install_dir='lib') config.add_npy_pkg_config("npymath.ini.in", "lib/npy-pkg-config", @@ -802,6 +805,7 @@ def configuration(parent_package='',top_path=None): generate_numpyconfig_h, generate_numpy_api, generate_ufunc_api], + libraries=['npymath'], ) # Configure blasdot diff --git a/numpy/core/src/_sortmodule.c.src b/numpy/core/src/_sortmodule.c.src index 709a26a1c..527d0c402 100644 --- a/numpy/core/src/_sortmodule.c.src +++ b/numpy/core/src/_sortmodule.c.src @@ -30,6 +30,7 @@ #include "Python.h" #include "numpy/noprefix.h" #include "numpy/npy_math.h" +#include "numpy/halffloat.h" #include "npy_config.h" @@ -48,12 +49,12 @@ /**begin repeat * * #TYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, * CDOUBLE,CLONGDOUBLE, INTP# * #type = npy_bool, npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, * npy_uint, npy_long, npy_ulong, npy_longlong, npy_ulonglong, - * npy_float, npy_double, npy_longdouble, npy_cfloat, npy_cdouble, - * npy_clongdouble, npy_intp# + * npy_half, npy_float, npy_double, npy_longdouble, npy_cfloat, + * npy_cdouble, npy_clongdouble, npy_intp# */ #define @TYPE@_SWAP(a,b) {@type@ tmp = (b); (b)=(a); (a) = tmp;} @@ -92,6 +93,19 @@ NPY_INLINE static int } /**end repeat**/ +NPY_INLINE static int +HALF_LT(npy_half a, npy_half b) +{ + int ret; + + if (npy_half_isnan(b)) { + ret = !npy_half_isnan(a); + } else { + ret = !npy_half_isnan(a) && npy_half_lt_nonan(a, b); + } + + return ret; +} /* * For inline functions SUN recommends not using a return in the then part @@ -217,10 +231,10 @@ UNICODE_LT(npy_ucs4 *s1, npy_ucs4 *s2, size_t len) /**begin repeat * * #TYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE# * #type = Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, ushort, float, double, longdouble, * cfloat, cdouble, clongdouble# */ @@ -965,7 +979,7 @@ add_sortfuncs(void) /**begin repeat * * #TYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, STRING, UNICODE# */ descr = PyArray_DescrFromType(PyArray_@TYPE@); diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src index fb48704ba..c9d517c50 100644 --- a/numpy/core/src/multiarray/arraytypes.c.src +++ b/numpy/core/src/multiarray/arraytypes.c.src @@ -12,6 +12,7 @@ #include "numpy/npy_3kcompat.h" #include "numpy/npy_math.h" +#include "numpy/halffloat.h" #include "common.h" #include "ctors.h" @@ -21,6 +22,7 @@ #include "numpyos.h" + /* ***************************************************************************** ** PYTHON TYPES TO C TYPES ** @@ -45,6 +47,18 @@ MyPyFloat_AsDouble(PyObject *obj) return ret; } +static npy_half +MyPyFloat_AsHalf(PyObject *obj) +{ + return npy_double_to_half(MyPyFloat_AsDouble(obj)); +} + +static PyObject * +MyPyFloat_FromHalf(npy_half h) +{ + return PyFloat_FromDouble(npy_half_to_double(h)); +} + /**begin repeat * #type = long, longlong# @@ -97,18 +111,18 @@ static char * _SEQUENCE_MESSAGE = "error setting an array element with a sequenc /**begin repeat * * #TYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, LONG, UINT, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE# + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE# * #func1 = PyBool_FromLong, PyInt_FromLong*6, PyLong_FromUnsignedLong*2, * PyLong_FromLongLong, PyLong_FromUnsignedLongLong, - * PyFloat_FromDouble*2# + * MyPyFloat_FromHalf, PyFloat_FromDouble*2# * #func2 = PyObject_IsTrue, MyPyLong_AsLong*6, MyPyLong_AsUnsignedLong*2, * MyPyLong_AsLongLong, MyPyLong_AsUnsignedLongLong, - * MyPyFloat_AsDouble*2# + * MyPyFloat_AsHalf, MyPyFloat_AsDouble*2# * #type = Bool, byte, ubyte, short, ushort, int, long, uint, ulong, - * longlong, ulonglong, float, double# - * #type1 = long*7, ulong*2, longlong, ulonglong, float, double# + * longlong, ulonglong, npy_half, float, double# + * #type1 = long*7, ulong*2, longlong, ulonglong, npy_half, float, double# * #kind = Bool, Byte, UByte, Short, UShort, Int, Long, UInt, ULong, - * LongLong, ULongLong, Float, Double# + * LongLong, ULongLong, Half, Float, Double# */ static PyObject * @TYPE@_getitem(char *ip, PyArrayObject *ap) { @@ -1236,7 +1250,7 @@ TIMEDELTA_setitem(PyObject *op, char *ov, PyArrayObject *ap) { * #totype = byte, ubyte, short, ushort, int, uint, long, ulong, * longlong, ulonglong, float, double, longdouble, datetime, * timedelta# -*/ + */ /**begin repeat1 * @@ -1278,6 +1292,97 @@ static void /**begin repeat * + * #TYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, + * LONGLONG, ULONGLONG, LONGDOUBLE, DATETIME, + * TIMEDELTA# + * #type = byte, ubyte, short, ushort, int, uint, long, ulong, + * longlong, ulonglong, longdouble, datetime, + * timedelta# + */ + +static void +@TYPE@_to_HALF(@type@ *ip, npy_half *op, intp n, + PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +{ + while (n--) { + *op++ = npy_float_to_half((float)(*ip++)); + } +} + +static void +HALF_to_@TYPE@(npy_half *ip, @type@ *op, intp n, + PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +{ + while (n--) { + *op++ = (@type@)npy_half_to_float(*ip++); + } +} + +/**end repeat**/ +#if SIZEOF_SHORT == 2 +#define HALF_to_HALF SHORT_to_SHORT +#elif SIZEOF_INT == 2 +#define HALF_to_HALF INT_to_INT +#endif + +/**begin repeat + * + * #TYPE = FLOAT, DOUBLE, CFLOAT, CDOUBLE# + * #type = float, double, float, double# + * #itype = npy_uint32, npy_uint64, npy_uint32, npy_uint64# + * #iscomplex = 0, 0, 1, 1# + */ + +static void +@TYPE@_to_HALF(@itype@ *ip, npy_half *op, intp n, + PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +{ + while (n--) { + *op++ = npy_@type@bits_to_halfbits(*ip); +#if @iscomplex@ + ip += 2; +#else + ip++; +#endif + } +} + +static void +HALF_to_@TYPE@(npy_half *ip, @itype@ *op, intp n, + PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +{ + while (n--) { + *op++ = npy_halfbits_to_@type@bits(*ip++); +#if @iscomplex@ + *op++ = 0; +#endif + } +} + +/**end repeat**/ + +static void +CLONGDOUBLE_to_HALF(longdouble *ip, npy_half *op, intp n, + PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +{ + while (n--) { + *op++ = npy_double_to_half((double) (*ip++)); + ip += 2; + } +} + +static void +HALF_to_CLONGDOUBLE(npy_half *ip, longdouble *op, intp n, + PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +{ + while (n--) { + *op++ = npy_half_to_double(*ip++); + *op++ = 0; + } +} + +/**begin repeat + * * #FROMTYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, DATETIME, * TIMEDELTA# @@ -1295,6 +1400,15 @@ static void } /**end repeat**/ +static void +HALF_to_BOOL(npy_half *ip, Bool *op, intp n, + PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +{ + while (n--) { + *op++ = (Bool)(!npy_half_iszero(*ip++)); + } +} + /**begin repeat * * #FROMTYPE = CFLOAT, CDOUBLE, CLONGDOUBLE# @@ -1314,18 +1428,20 @@ static void /**begin repeat * #TOTYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, DATETIME, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, DATETIME, * TIMEDELTA# * #totype = byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, datetime, + * longlong, ulonglong, npy_half, float, double, longdouble, datetime, * timedelta# -*/ + * #one = 1*10, NPY_HALF_ONE, 1*5# + * #zero = 0*10, NPY_HALF_ZERO, 0*5# + */ static void BOOL_to_@TOTYPE@(Bool *ip, @totype@ *op, intp n, PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) { while (n--) { - *op++ = (@totype@)(*ip++ != FALSE); + *op++ = (@totype@)((*ip++ != FALSE) ? @one@ : @zero@); } } /**end repeat**/ @@ -1383,14 +1499,14 @@ static void /**begin repeat * * #FROMTYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, STRING, UNICODE, VOID, OBJECT, * DATETIME, TIMEDELTA# * #fromtype = Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, npy_half, float, double, longdouble, * cfloat, cdouble, clongdouble, char, char, char, PyObject *, * datetime, timedelta# - * #skip = 1*17, aip->descr->elsize*3, 1*3# + * #skip = 1*18, aip->descr->elsize*3, 1*3# */ static void @FROMTYPE@_to_OBJECT(@fromtype@ *ip, PyObject **op, intp n, PyArrayObject *aip, @@ -1431,14 +1547,14 @@ static void /**begin repeat * * #TOTYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, STRING, UNICODE, VOID, DATETIME, * TIMEDELTA# * #totype = Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, npy_half, float, double, longdouble, * cfloat, cdouble, clongdouble, char, char, char, datetime, * timedelta# - * #skip = 1*17, aop->descr->elsize*3, 1*2# + * #skip = 1*18, aop->descr->elsize*3, 1*2# */ static void OBJECT_to_@TOTYPE@(PyObject **ip, @totype@ *op, intp n, @@ -1461,13 +1577,13 @@ OBJECT_to_@TOTYPE@(PyObject **ip, @totype@ *op, intp n, /**begin repeat * - * #from = STRING*22, UNICODE*22, VOID*22# - * #fromtyp = char*66# - * #to = (BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE, STRING, UNICODE, VOID, DATETIME, TIMEDELTA)*3# - * #totyp = (Bool, byte, ubyte, short, ushort, int, uint, long, ulong, longlong, ulonglong, float, double, longdouble, cfloat, cdouble, clongdouble, char, char, char, datetime, timedelta)*3# - * #oskip = (1*17,aop->descr->elsize*3,1*2)*3# - * #convert = 1*17, 0*3, 1*2, 1*17, 0*3, 1*2, 0*22# - * #convstr = (Int*9, Long*2, Float*3, Complex*3, Tuple*3, Long*2)*3# + * #from = STRING*23, UNICODE*23, VOID*23# + * #fromtyp = char*69# + * #to = (BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE, STRING, UNICODE, VOID, DATETIME, TIMEDELTA)*3# + * #totyp = (Bool, byte, ubyte, short, ushort, int, uint, long, ulong, longlong, ulonglong, npy_half, float, double, longdouble, cfloat, cdouble, clongdouble, char, char, char, datetime, timedelta)*3# + * #oskip = (1*18,aop->descr->elsize*3,1*2)*3# + * #convert = 1*18, 0*3, 1*2, 1*18, 0*3, 1*2, 0*23# + * #convstr = (Int*9, Long*2, Float*4, Complex*3, Tuple*3, Long*2)*3# */ static void @from@_to_@to@(@fromtyp@ *ip, @totyp@ *op, intp n, PyArrayObject *aip, @@ -1484,23 +1600,23 @@ static void return; } /* convert from Python object to needed one */ - if (@convert@) { - PyObject *new, *args; - /* call out to the Python builtin given by convstr */ - args = Py_BuildValue("(N)", temp); +#if @convert@ + PyObject *new, *args; + /* call out to the Python builtin given by convstr */ + args = Py_BuildValue("(N)", temp); #if defined(NPY_PY3K) #define PyInt_Type PyLong_Type #endif - new = Py@convstr@_Type.tp_new(&Py@convstr@_Type, args, NULL); + new = Py@convstr@_Type.tp_new(&Py@convstr@_Type, args, NULL); #if defined(NPY_PY3K) #undef PyInt_Type #endif - Py_DECREF(args); - temp = new; - if (temp == NULL) { - return; - } + Py_DECREF(args); + temp = new; + if (temp == NULL) { + return; } +#endif /* @convert@ */ if (@to@_setitem(temp,(char *)op, aop)) { Py_DECREF(temp); return; @@ -1513,13 +1629,13 @@ static void /**begin repeat * - * #to = STRING*19, UNICODE*19, VOID*19# - * #totyp = char*19, char*19, char*19# + * #to = STRING*20, UNICODE*20, VOID*20# + * #totyp = char*20, char*20, char*20# * #from = (BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, DATETIME, TIMEDELTA)*3# * #fromtyp = (Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, npy_half, float, double, longdouble, * cfloat, cdouble, clongdouble, datetime, timedelta)*3# */ static void @@ -1587,6 +1703,17 @@ static int } /**end repeat**/ +static int +HALF_scan(FILE *fp, npy_half *ip, void *NPY_UNUSED(ignore), PyArray_Descr *NPY_UNUSED(ignored)) +{ + double result; + int ret; + + ret = NumPyOS_ascii_ftolf(fp, &result); + *ip = npy_double_to_half(result); + return ret; +} + /**begin repeat * #fname = BYTE, UBYTE# * #type = byte, ubyte# @@ -1666,6 +1793,15 @@ static int } /**end repeat**/ +static int +HALF_fromstr(char *str, npy_half *ip, char **endptr, PyArray_Descr *NPY_UNUSED(ignore)) +{ + double result; + + result = NumPyOS_ascii_strtod(str, endptr); + *ip = npy_double_to_half(result); + return 0; +} /**begin repeat @@ -1684,11 +1820,11 @@ static int /**begin repeat * - * #fname = SHORT, USHORT, INT, UINT, LONG, ULONG, LONGLONG, ULONGLONG, FLOAT, + * #fname = SHORT, USHORT, INT, UINT, LONG, ULONG, LONGLONG, ULONGLONG, HALF, FLOAT, * DOUBLE, LONGDOUBLE, DATETIME, TIMEDELTA# - * #fsize = SHORT, SHORT, INT, INT, LONG, LONG, LONGLONG, LONGLONG, FLOAT, + * #fsize = SHORT, SHORT, INT, INT, LONG, LONG, LONGLONG, LONGLONG, HALF, FLOAT, * DOUBLE, LONGDOUBLE, DATETIME, TIMEDELTA# - * #type = short, ushort, int, uint, long, ulong, longlong, ulonglong, float, + * #type = short, ushort, int, uint, long, ulong, longlong, ulonglong, npy_half, float, * double, longdouble, datetime, timedelta# */ static void @@ -2223,22 +2359,25 @@ UNICODE_copyswap (char *dst, char *src, int swap, PyArrayObject *arr) ***************************************************************************** */ +#define _NONZERO(a) ((a) != 0) + /**begin repeat * * #fname = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * DATETIME, TIMEDELTA# * #type = Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, npy_half, float, double, longdouble, * datetime, timedelta# - * #isfloat = 0*11, 1*3, 0*2# + * #isfloat = 0*11, 1*4, 0*2# + * #nonzero = _NONZERO*11, !npy_half_iszero, _NONZERO*5# */ static Bool @fname@_nonzero (char *ip, PyArrayObject *ap) { if (ap == NULL || PyArray_ISBEHAVED_RO(ap)) { @type@ *ptmp = (@type@ *)ip; - return (Bool) (*ptmp != 0); + return (Bool) @nonzero@(*ptmp); } else { /* @@ -2252,7 +2391,7 @@ static Bool #else memcpy(&tmp, ip, sizeof(@type@)); #endif - return (Bool) (tmp != 0); + return (Bool) @nonzero@(tmp); } } /**end repeat**/ @@ -2562,6 +2701,31 @@ C@TYPE@_compare(@type@ *pa, @type@ *pb) /**end repeat**/ +static int +HALF_compare (npy_half *pa, npy_half *pb, PyArrayObject *NPY_UNUSED(ap)) +{ + npy_half a = *pa, b = *pb; + Bool a_isnan, b_isnan; + int ret; + + a_isnan = npy_half_isnan(a); + b_isnan = npy_half_isnan(b); + + if (a_isnan) { + ret = b_isnan ? 0 : -1; + } else if (b_isnan) { + ret = 1; + } else if(npy_half_lt_nonan(a, b)) { + ret = -1; + } else if(npy_half_lt_nonan(b, a)) { + ret = 1; + } else { + ret = 0; + } + + return ret; +} + /* object type */ @@ -2728,18 +2892,21 @@ finish: ***************************************************************************** */ +#define _LESS_THAN_OR_EQUAL(a,b) ((a) <= (b)) /**begin repeat * * #fname = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, DATETIME, TIMEDELTA# * #type = Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, npy_half, float, double, longdouble, * float, double, longdouble, datetime, timedelta# - * #isfloat = 0*11, 1*6, 0*2# - * #iscomplex = 0*14, 1*3, 0*2# - * #incr = ip++*14, ip+=2*3, ip++*2# + * #isfloat = 0*11, 1*7, 0*2# + * #isnan = nop*11, npy_half_isnan, npy_isnan*6, nop*2# + * #le = _LESS_THAN_OR_EQUAL*11, npy_half_le, _LESS_THAN_OR_EQUAL*8# + * #iscomplex = 0*15, 1*3, 0*2# + * #incr = ip++*15, ip+=2*3, ip++*2# */ static int @fname@_argmax(@type@ *ip, intp n, intp *max_ind, PyArrayObject *NPY_UNUSED(aip)) @@ -2753,13 +2920,13 @@ static int *max_ind = 0; #if @isfloat@ - if (npy_isnan(mp)) { + if (@isnan@(mp)) { /* nan encountered; it's maximal */ return 0; } #endif #if @iscomplex@ - if (npy_isnan(mp_im)) { + if (@isnan@(mp_im)) { /* nan encountered; it's maximal */ return 0; } @@ -2773,21 +2940,21 @@ static int #if @iscomplex@ /* Lexical order for complex numbers */ if ((ip[0] > mp) || ((ip[0] == mp) && (ip[1] > mp_im)) - || npy_isnan(ip[0]) || npy_isnan(ip[1])) { + || @isnan@(ip[0]) || @isnan@(ip[1])) { mp = ip[0]; mp_im = ip[1]; *max_ind = i; - if (npy_isnan(mp) || npy_isnan(mp_im)) { + if (@isnan@(mp) || @isnan@(mp_im)) { /* nan encountered, it's maximal */ break; } } #else - if (!(*ip <= mp)) { /* negated, for correct nan handling */ + if (!@le@(*ip, mp)) { /* negated, for correct nan handling */ mp = *ip; *max_ind = i; #if @isfloat@ - if (npy_isnan(mp)) { + if (@isnan@(mp)) { /* nan encountered, it's maximal */ break; } @@ -2800,6 +2967,8 @@ static int /**end repeat**/ +#undef _LESS_THAN_OR_EQUAL + static int OBJECT_argmax(PyObject **ip, intp n, intp *max_ind, PyArrayObject *NPY_UNUSED(aip)) { @@ -2910,6 +3079,19 @@ static void } /**end repeat**/ +static void +HALF_dot(char *ip1, npy_intp is1, char *ip2, npy_intp is2, char *op, npy_intp n, + void *NPY_UNUSED(ignore)) +{ + float tmp = 0.0f; + npy_intp i; + + for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) { + tmp += npy_half_to_float(*((npy_half *)ip1)) * + npy_half_to_float(*((npy_half *)ip2)); + } + *((npy_half *)op) = npy_float_to_half(tmp); +} /**begin repeat * @@ -3041,6 +3223,19 @@ static void } /**end repeat**/ +static void +HALF_fill(npy_half *buffer, npy_intp length, void *NPY_UNUSED(ignored)) +{ + npy_intp i; + float start = npy_half_to_float(buffer[0]); + float delta = npy_half_to_float(buffer[1]); + + delta -= start; + for (i = 2; i < length; ++i) { + buffer[i] = npy_float_to_half(start + i*delta); + } +} + /**begin repeat * * #NAME = CFLOAT, CDOUBLE, CLONGDOUBLE# @@ -3095,10 +3290,10 @@ static void /**begin repeat * * #NAME = SHORT, USHORT, INT, UINT, LONG, ULONG, LONGLONG, ULONGLONG, - * FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE, + * HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE, * DATETIME, TIMEDELTA# * #typ = short, ushort, int, uint, long, ulong, longlong, ulonglong, - * float, double, longdouble, cfloat, cdouble, clongdouble, + * npy_half, float, double, longdouble, cfloat, cdouble, clongdouble, * datetime, timedelta# */ static void @@ -3120,15 +3315,27 @@ static void ***************************************************************************** */ +#define _LESS_THAN(a, b) ((a) < (b)) +#define _GREATER_THAN(a, b) ((a) > (b)) +/* + * In fastclip, 'b' was already checked for NaN, so the half comparison + * only needs to check 'a' for NaN. + */ +#define _HALF_LESS_THAN(a, b) (!npy_half_isnan(a) && npy_half_lt_nonan(a, b)) +#define _HALF_GREATER_THAN(a, b) (!npy_half_isnan(a) && npy_half_lt_nonan(b, a)) /**begin repeat * * #name = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * DATETIME, TIMEDELTA# * #type = Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, npy_half, float, double, longdouble, * datetime, timedelta# + * #isfloat = 0*11, 1*4, 0*2# + * #isnan = nop*11, npy_half_isnan, npy_isnan*3, nop*2# + * #lt = _LESS_THAN*11, _HALF_LESS_THAN, _LESS_THAN*5# + * #gt = _GREATER_THAN*11, _HALF_GREATER_THAN, _GREATER_THAN*5# */ static void @name@_fastclip(@type@ *in, intp ni, @type@ *min, @type@ *max, @type@ *out) @@ -3138,30 +3345,47 @@ static void if (max != NULL) { max_val = *max; +#if @isfloat@ + /* NaNs result in no clipping, so optimize the case away */ + if (@isnan@(max_val)) { + if (min == NULL) { + return; + } + max = NULL; + } +#endif } if (min != NULL) { min_val = *min; +#if @isfloat@ + if (@isnan@(min_val)) { + if (max == NULL) { + return; + } + min = NULL; + } +#endif } if (max == NULL) { for (i = 0; i < ni; i++) { - if (in[i] < min_val) { + if (@lt@(in[i], min_val)) { out[i] = min_val; } } } else if (min == NULL) { for (i = 0; i < ni; i++) { - if (in[i] > max_val) { + if (@gt@(in[i], max_val)) { out[i] = max_val; } } } else { for (i = 0; i < ni; i++) { - if (in[i] < min_val) { + if (@lt@(in[i], min_val)) { out[i] = min_val; } - else if (in[i] > max_val) { + else if (@gt@(in[i], max_val)) { out[i] = max_val; } } @@ -3169,6 +3393,11 @@ static void } /**end repeat**/ +#undef _LESS_THAN +#undef _GREATER_THAN +#undef _HALF_LESS_THAN +#undef _HALF_GREATER_THAN + /**begin repeat * * #name = CFLOAT, CDOUBLE, CLONGDOUBLE# @@ -3229,10 +3458,10 @@ static void /**begin repeat * * #name = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, DATETIME, TIMEDELTA# * #type = Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, npy_half, float, double, longdouble, * cfloat, cdouble, clongdouble, datetime, timedelta# */ static void @@ -3273,10 +3502,10 @@ static void /**begin repeat * * #name = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, DATETIME, TIMEDELTA# * #type = Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, npy_half, float, double, longdouble, * cfloat, cdouble, clongdouble, datetime, timedelta# */ static int @@ -3431,6 +3660,7 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = { (PyArray_VectorUnaryFunc*)@from@_to_ULONG, (PyArray_VectorUnaryFunc*)@from@_to_LONGLONG, (PyArray_VectorUnaryFunc*)@from@_to_ULONGLONG, + (PyArray_VectorUnaryFunc*)@from@_to_HALF, (PyArray_VectorUnaryFunc*)@from@_to_FLOAT, (PyArray_VectorUnaryFunc*)@from@_to_DOUBLE, (PyArray_VectorUnaryFunc*)@from@_to_LONGDOUBLE, @@ -3469,24 +3699,23 @@ static PyArray_Descr @from@_Descr = { /**end repeat**/ - /**begin repeat * * #from = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, OBJECT, DATETIME, TIMEDELTA# - * #num = 1*14, 2*3, 1*3# + * #num = 1*15, 2*3, 1*3# * #fromtyp = Bool, byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, longdouble, + * longlong, ulonglong, npy_half, float, double, longdouble, * float, double, longdouble, PyObject *, datetime, timedelta# * #NAME = Bool, Byte, UByte, Short, UShort, Int, UInt, Long, ULong, - * LongLong, ULongLong, Float, Double, LongDouble, + * LongLong, ULongLong, Half, Float, Double, LongDouble, * CFloat, CDouble, CLongDouble, Object, Datetime, Timedelta# * #kind = GENBOOL, SIGNED, UNSIGNED, SIGNED, UNSIGNED, SIGNED, UNSIGNED, SIGNED, UNSIGNED, - * SIGNED, UNSIGNED, FLOATING, FLOATING, FLOATING, + * SIGNED, UNSIGNED, FLOATING, FLOATING, FLOATING, FLOATING, * COMPLEX, COMPLEX, COMPLEX, OBJECT, DATETIME, TIMEDELTA# - * #endian = |*3, =*14, |, =*2# - * #isobject= 0*17,NPY_OBJECT_DTYPE_FLAGS,0*2# + * #endian = |*3, =*15, |, =*2# + * #isobject= 0*18,NPY_OBJECT_DTYPE_FLAGS,0*2# */ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = { (PyArray_GetItemFunc*)@from@_getitem, @@ -3527,6 +3756,7 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = { (PyArray_VectorUnaryFunc*)@from@_to_ULONG, (PyArray_VectorUnaryFunc*)@from@_to_LONGLONG, (PyArray_VectorUnaryFunc*)@from@_to_ULONGLONG, + (PyArray_VectorUnaryFunc*)@from@_to_HALF, (PyArray_VectorUnaryFunc*)@from@_to_FLOAT, (PyArray_VectorUnaryFunc*)@from@_to_DOUBLE, (PyArray_VectorUnaryFunc*)@from@_to_LONGDOUBLE, @@ -3603,6 +3833,7 @@ static PyArray_Descr *_builtin_descrs[] = { &ULONG_Descr, &LONGLONG_Descr, &ULONGLONG_Descr, + &HALF_Descr, &FLOAT_Descr, &DOUBLE_Descr, &LONGDOUBLE_Descr, @@ -3699,7 +3930,7 @@ set_typeinfo(PyObject *dict) /**begin repeat * * #name = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, INTP, UINTP, - * LONG, ULONG, LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONG, ULONG, LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, OBJECT, STRING, UNICODE, VOID, * DATETIME,TIMEDELTA# */ @@ -3709,7 +3940,7 @@ set_typeinfo(PyObject *dict) /**begin repeat * #name = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, - * LONG, ULONG, LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONG, ULONG, LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, OBJECT, STRING, UNICODE, VOID, * DATETIME, TIMEDELTA# */ @@ -3766,9 +3997,9 @@ set_typeinfo(PyObject *dict) /**begin repeat * - * #type = float, double, longdouble, cfloat, cdouble, clongdouble# - * #name = FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE# - * #Name = Float, Double, LongDouble, CFloat, CDouble, CLongDouble# + * #type = npy_half, float, double, longdouble, cfloat, cdouble, clongdouble# + * #name = HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE# + * #Name = Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble# */ PyDict_SetItemString(infodict, "@name@", #if defined(NPY_PY3K) diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c index abc254058..4ad2e9f51 100644 --- a/numpy/core/src/multiarray/conversion_utils.c +++ b/numpy/core/src/multiarray/conversion_utils.c @@ -687,6 +687,9 @@ PyArray_TypestrConvert(int itemsize, int gentype) } else if (gentype == PyArray_FLOATINGLTR) { switch(itemsize) { + case 2: + newtype = PyArray_FLOAT16; + break; case 4: newtype = PyArray_FLOAT32; break; diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c index d2aaf054f..0040e8ad5 100644 --- a/numpy/core/src/multiarray/convert_datatype.c +++ b/numpy/core/src/multiarray/convert_datatype.c @@ -567,7 +567,6 @@ PyArray_CanCastSafely(int fromtype, int totype) } } } - return 0; } diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index f35bfd662..d4dba719c 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -2946,6 +2946,7 @@ setup_scalartypes(PyObject *NPY_UNUSED(dict)) SINGLE_INHERIT(ULong, UnsignedInteger); SINGLE_INHERIT(ULongLong, UnsignedInteger); + SINGLE_INHERIT(Half, Floating); SINGLE_INHERIT(Float, Floating); DUAL_INHERIT(Double, Float, Floating); SINGLE_INHERIT(LongDouble, Floating); diff --git a/numpy/core/src/multiarray/scalarapi.c b/numpy/core/src/multiarray/scalarapi.c index f549ad35c..87e140c4e 100644 --- a/numpy/core/src/multiarray/scalarapi.c +++ b/numpy/core/src/multiarray/scalarapi.c @@ -57,6 +57,7 @@ scalar_value(PyObject *scalar, PyArray_Descr *descr) CASE(ULONG, ULong); CASE(LONGLONG, LongLong); CASE(ULONGLONG, ULongLong); + CASE(HALF, Half); CASE(FLOAT, Float); CASE(DOUBLE, Double); CASE(LONGDOUBLE, LongDouble); @@ -110,6 +111,7 @@ scalar_value(PyObject *scalar, PyArray_Descr *descr) else { /* Inexact */ if _CHK(Floating) { + _IFCASE(Half); _IFCASE(Float); _IFCASE(Double); _IFCASE(LongDouble); diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index b2e8690c7..c66337602 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -9,6 +9,7 @@ #define NPY_NO_PREFIX #include "numpy/arrayobject.h" #include "numpy/npy_math.h" +#include "numpy/halffloat.h" #include "numpy/arrayscalars.h" #include "numpy/npy_3kcompat.h" @@ -478,6 +479,12 @@ format_c@name@(char *buf, size_t buflen, c@name@ val, unsigned int prec) /**end repeat**/ +NPY_NO_EXPORT void +format_half(char *buf, size_t buflen, npy_half val, unsigned int prec) +{ + format_float(buf, buflen, npy_half_to_float(val), prec); +} + /* * over-ride repr and str of array-scalar strings and unicode to * remove NULL bytes and then call the corresponding functions @@ -516,7 +523,9 @@ static PyObject * } /**end repeat**/ -/* These values are finfo.precision + 2 */ +/* The REPR values are finfo.precision + 2 */ +#define HALFPREC_REPR 5 +#define HALFPREC_STR 5 #define FLOATPREC_REPR 8 #define FLOATPREC_STR 6 #define DOUBLEPREC_REPR 17 @@ -536,9 +545,10 @@ static PyObject * */ /**begin repeat - * #name = float, double, longdouble# - * #Name = Float, Double, LongDouble# - * #NAME = FLOAT, DOUBLE, LONGDOUBLE# + * #name = half, float, double, longdouble# + * #Name = Half, Float, Double, LongDouble# + * #NAME = HALF, FLOAT, DOUBLE, LONGDOUBLE# + * #hascomplex = 0, 1, 1, 1# */ /**begin repeat1 * #kind = str, repr# @@ -551,12 +561,13 @@ static PyObject * @name@type_@kind@(PyObject *self) { char buf[100]; - @name@ val = ((Py@Name@ScalarObject *)self)->obval; + npy_@name@ val = ((Py@Name@ScalarObject *)self)->obval; format_@name@(buf, sizeof(buf), val, PREC); return PyUString_FromString(buf); } +#if @hascomplex@ static PyObject * c@name@type_@kind@(PyObject *self) { @@ -566,6 +577,7 @@ c@name@type_@kind@(PyObject *self) format_c@name@(buf, sizeof(buf), val, PREC); return PyUString_FromString(buf); } +#endif #undef PREC @@ -576,16 +588,17 @@ c@name@type_@kind@(PyObject *self) * float type print (control print a, where a is a float type instance) */ /**begin repeat - * #name = float, double, longdouble# - * #Name = Float, Double, LongDouble# - * #NAME = FLOAT, DOUBLE, LONGDOUBLE# + * #name = half, float, double, longdouble# + * #Name = Half, Float, Double, LongDouble# + * #NAME = HALF, FLOAT, DOUBLE, LONGDOUBLE# + * #hascomplex = 0, 1, 1, 1# */ static int @name@type_print(PyObject *v, FILE *fp, int flags) { char buf[100]; - @name@ val = ((Py@Name@ScalarObject *)v)->obval; + npy_@name@ val = ((Py@Name@ScalarObject *)v)->obval; format_@name@(buf, sizeof(buf), val, (flags & Py_PRINT_RAW) ? @NAME@PREC_STR : @NAME@PREC_REPR); @@ -595,6 +608,7 @@ static int return 0; } +#if @hascomplex@ static int c@name@type_print(PyObject *v, FILE *fp, int flags) { @@ -609,6 +623,7 @@ c@name@type_print(PyObject *v, FILE *fp, int flags) Py_END_ALLOW_THREADS return 0; } +#endif /**end repeat**/ @@ -2117,13 +2132,13 @@ object_arrtype_dealloc(PyObject *v) /**begin repeat * #name = byte, short, int, long, longlong, ubyte, ushort, uint, ulong, - * ulonglong, float, double, longdouble, cfloat, cdouble, clongdouble, - * string, unicode, object, datetime, timedelta# + * ulonglong, half, float, double, longdouble, cfloat, cdouble, + * clongdouble, string, unicode, object, datetime, timedelta# * #TYPE = BYTE, SHORT, INT, LONG, LONGLONG, UBYTE, USHORT, UINT, ULONG, - * ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE, - * STRING, UNICODE, OBJECT, DATETIME, TIMEDELTA# - * #work = 0,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,z,z,0,0,0# - * #default = 0*16,1*2,2,0*2# + * ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, + * CLONGDOUBLE, STRING, UNICODE, OBJECT, DATETIME, TIMEDELTA# + * #work = 0,0,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,z,z,0,0,0# + * #default = 0*17,1*2,2,0*2# */ #define _NPY_UNUSED2_1 @@ -2161,9 +2176,9 @@ static PyObject * */ if (obj == NULL) { #if @default@ == 0 - char *mem = malloc(sizeof(@name@)); + char *mem = malloc(sizeof(npy_@name@)); - memset(mem, 0, sizeof(@name@)); + memset(mem, 0, sizeof(npy_@name@)); robj = PyArray_Scalar(mem, typecode, NULL); free(mem); #elif @default@ == 1 @@ -2625,6 +2640,12 @@ c@lname@_arrtype_hash(PyObject *obj) /**end repeat**/ static long +half_arrtype_hash(PyObject *obj) +{ + return _Py_HashDouble(npy_half_to_double(((PyHalfScalarObject *)obj)->obval)); +} + +static long object_arrtype_hash(PyObject *obj) { return PyObject_Hash(((PyObjectScalarObject *)obj)->obval); @@ -3058,10 +3079,10 @@ NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = { /**begin repeat * #NAME = Byte, Short, Int, Long, LongLong, UByte, UShort, UInt, ULong, - * ULongLong, Float, Double, LongDouble, Datetime, Timedelta# - * #name = int*5, uint*5, float*3, datetime, timedelta# - * #CNAME = (CHAR, SHORT, INT, LONG, LONGLONG)*2, FLOAT, DOUBLE, LONGDOUBLE, - * DATETIME, TIMEDELTA# + * ULongLong, Half, Float, Double, LongDouble, Datetime, Timedelta# + * #name = int*5, uint*5, float*4, datetime, timedelta# + * #CNAME = (CHAR, SHORT, INT, LONG, LONGLONG)*2, HALF, FLOAT, DOUBLE, + * LONGDOUBLE, DATETIME, TIMEDELTA# */ #if BITSOF_@CNAME@ == 8 #define _THIS_SIZE "8" @@ -3276,10 +3297,10 @@ initialize_casting_tables(void) /* Compile-time loop of scalar kinds */ /**begin repeat * #NAME = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE# - * #SCKIND = BOOL, (INTNEG, INTPOS)*5, FLOAT, FLOAT, FLOAT, - * COMPLEX, COMPLEX, COMPLEX# + * #SCKIND = BOOL, (INTNEG, INTPOS)*5, FLOAT*4, + * COMPLEX*3# */ _npy_scalar_kinds_table[PyArray_@NAME@] = PyArray_@SCKIND@_SCALAR; /**end repeat**/ @@ -3309,22 +3330,22 @@ initialize_casting_tables(void) /* Compile-time loop of casting rules */ /**begin repeat * #FROM_NAME = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE# * #FROM_BASENAME = BYTE, BYTE, SHORT, SHORT, INT, INT, LONG, LONG, - * LONGLONG, LONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, LONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * FLOAT, DOUBLE, LONGDOUBLE# * #from_isint = 1, 0, 1, 0, 1, 0, 1, 0, - * 1, 0, 0, 0, 0, + * 1, 0, 0, 0, 0, 0, * 0, 0, 0# * #from_isuint = 0, 1, 0, 1, 0, 1, 0, 1, - * 0, 1, 0, 0, 0, + * 0, 1, 0, 0, 0, 0, * 0, 0, 0# * #from_isfloat = 0, 0, 0, 0, 0, 0, 0, 0, - * 0, 0, 1, 1, 1, + * 0, 0, 1, 1, 1, 1, * 0, 0, 0# * #from_iscomplex = 0, 0, 0, 0, 0, 0, 0, 0, - * 0, 0, 0, 0, 0, + * 0, 0, 0, 0, 0, 0, * 1, 1, 1# */ #define _FROM_BSIZE NPY_SIZEOF_@FROM_BASENAME@ @@ -3335,22 +3356,22 @@ initialize_casting_tables(void) /**begin repeat1 * #TO_NAME = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, - * LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE# * #TO_BASENAME = BYTE, BYTE, SHORT, SHORT, INT, INT, LONG, LONG, - * LONGLONG, LONGLONG, FLOAT, DOUBLE, LONGDOUBLE, + * LONGLONG, LONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, * FLOAT, DOUBLE, LONGDOUBLE# * #to_isint = 1, 0, 1, 0, 1, 0, 1, 0, - * 1, 0, 0, 0, 0, + * 1, 0, 0, 0, 0, 0, * 0, 0, 0# * #to_isuint = 0, 1, 0, 1, 0, 1, 0, 1, - * 0, 1, 0, 0, 0, + * 0, 1, 0, 0, 0, 0, * 0, 0, 0# * #to_isfloat = 0, 0, 0, 0, 0, 0, 0, 0, - * 0, 0, 1, 1, 1, + * 0, 0, 1, 1, 1, 1, * 0, 0, 0# * #to_iscomplex = 0, 0, 0, 0, 0, 0, 0, 0, - * 0, 0, 0, 0, 0, + * 0, 0, 0, 0, 0, 0, * 1, 1, 1# */ #define _TO_BSIZE NPY_SIZEOF_@TO_BASENAME@ @@ -3499,11 +3520,13 @@ initialize_numeric_types(void) /**begin repeat * #name = bool, byte, short, int, long, longlong, ubyte, ushort, uint, - * ulong, ulonglong, float, double, longdouble, cfloat, cdouble, - * clongdouble, string, unicode, void, object, datetime, timedelta# + * ulong, ulonglong, half, float, double, longdouble, cfloat, + * cdouble, clongdouble, string, unicode, void, object, datetime, + * timedelta# * #NAME = Bool, Byte, Short, Int, Long, LongLong, UByte, UShort, UInt, - * ULong, ULongLong, Float, Double, LongDouble, CFloat, CDouble, - * CLongDouble, String, Unicode, Void, Object, Datetime, Timedelta# + * ULong, ULongLong, Half, Float, Double, LongDouble, CFloat, + * CDouble, CLongDouble, String, Unicode, Void, Object, Datetime, + * Timedelta# */ Py@NAME@ArrType_Type.tp_flags = BASEFLAGS; Py@NAME@ArrType_Type.tp_new = @name@_arrtype_new; @@ -3512,11 +3535,11 @@ initialize_numeric_types(void) /**begin repeat * #name = bool, byte, short, ubyte, ushort, uint, ulong, ulonglong, - * float, longdouble, cfloat, clongdouble, void, object, datetime, - * timedelta# + * half, float, longdouble, cfloat, clongdouble, void, object, + * datetime, timedelta# * #NAME = Bool, Byte, Short, UByte, UShort, UInt, ULong, ULongLong, - * Float, LongDouble, CFloat, CLongDouble, Void, Object, Datetime, - * Timedelta# + * Half, Float, LongDouble, CFloat, CLongDouble, Void, Object, + * Datetime, Timedelta# */ Py@NAME@ArrType_Type.tp_hash = @name@_arrtype_hash; /**end repeat**/ @@ -3546,6 +3569,8 @@ initialize_numeric_types(void) /**begin repeat * #name = repr, str# */ + PyHalfArrType_Type.tp_@name@ = halftype_@name@; + PyFloatArrType_Type.tp_@name@ = floattype_@name@; PyCFloatArrType_Type.tp_@name@ = cfloattype_@name@; @@ -3553,6 +3578,7 @@ initialize_numeric_types(void) PyCDoubleArrType_Type.tp_@name@ = cdoubletype_@name@; /**end repeat**/ + PyHalfArrType_Type.tp_print = halftype_print; PyFloatArrType_Type.tp_print = floattype_print; PyDoubleArrType_Type.tp_print = doubletype_print; PyLongDoubleArrType_Type.tp_print = longdoubletype_print; @@ -3608,6 +3634,7 @@ static PyTypeObject *typeobjects[] = { &PyULongArrType_Type, &PyLongLongArrType_Type, &PyULongLongArrType_Type, + &PyHalfArrType_Type, &PyFloatArrType_Type, &PyDoubleArrType_Type, &PyLongDoubleArrType_Type, diff --git a/numpy/core/src/npymath/halffloat.c b/numpy/core/src/npymath/halffloat.c new file mode 100644 index 000000000..da92d3e12 --- /dev/null +++ b/numpy/core/src/npymath/halffloat.c @@ -0,0 +1,525 @@ +#include "numpy/halffloat.h" +#include "numpy/ufuncobject.h" + +/* + * This chooses between 'ties to even' and 'ties away from zero'. + */ +#define NPY_HALF_ROUND_TIES_TO_EVEN 1 +/* + * If these are 1, the conversions try to trigger underflow, + * overflow, and invalid exceptions in the FP system when needed. + */ +#define NPY_HALF_GENERATE_OVERFLOW 1 +#define NPY_HALF_GENERATE_UNDERFLOW 1 +#define NPY_HALF_GENERATE_INVALID 1 + +/* + ******************************************************************** + * HALF-PRECISION ROUTINES * + ******************************************************************** + */ + +float npy_half_to_float(npy_half h) +{ + union { float ret; npy_uint32 retbits; } conv; + conv.retbits = npy_halfbits_to_floatbits(h); + return conv.ret; +} + +double npy_half_to_double(npy_half h) +{ + union { double ret; npy_uint64 retbits; } conv; + conv.retbits = npy_halfbits_to_doublebits(h); + return conv.ret; +} + +npy_half npy_float_to_half(float f) +{ + union { float f; npy_uint32 fbits; } conv; + conv.f = f; + return npy_floatbits_to_halfbits(conv.fbits); +} + +npy_half npy_double_to_half(double d) +{ + union { double d; npy_uint64 dbits; } conv; + conv.d = d; + return npy_doublebits_to_halfbits(conv.dbits); +} + +int npy_half_iszero(npy_half h) +{ + return (h&0x7fff) == 0; +} + +int npy_half_isnan(npy_half h) +{ + return ((h&0x7c00u) == 0x7c00u) && ((h&0x03ffu) != 0x0000u); +} + +int npy_half_isinf(npy_half h) +{ + return ((h&0x7fffu) == 0x7c00u); +} + +int npy_half_isfinite(npy_half h) +{ + return ((h&0x7c00u) != 0x7c00u); +} + +int npy_half_signbit(npy_half h) +{ + return (h&0x8000u) != 0; +} + +npy_half npy_half_spacing(npy_half h) +{ + npy_half ret; + npy_uint16 h_exp = h&0x7c00u; + npy_uint16 h_sig = h&0x03ffu; + if (h_exp == 0x7c00u || h == 0x7bffu) { +#if NPY_HALF_GENERATE_INVALID + generate_invalid_error(); +#endif + ret = NPY_HALF_NAN; + } else if ((h&0x8000u) && h_sig == 0) { /* Negative boundary case */ + if (h_exp > 0x2c00u) { /* If result is normalized */ + ret = h_exp - 0x2c00u; + } else if(h_exp > 0x0400u) { /* The result is a subnormal, but not the smallest */ + ret = 1 << ((h_exp >> 10) - 2); + } else { + ret = 0x0001u; /* Smallest subnormal half */ + } + } else if (h_exp > 0x2800u) { /* If result is still normalized */ + ret = h_exp - 0x2800u; + } else if (h_exp > 0x0400u) { /* The result is a subnormal, but not the smallest */ + ret = 1 << ((h_exp >> 10) - 1); + } else { + ret = 0x0001u; + } + + return ret; +} + +npy_half npy_half_copysign(npy_half x, npy_half y) +{ + return (x&0x7fffu) | (y&0x8000u); +} + +npy_half npy_half_nextafter(npy_half x, npy_half y) +{ + npy_half ret; + + if (!npy_half_isfinite(x) || npy_half_isnan(y)) { +#if NPY_HALF_GENERATE_INVALID + generate_invalid_error(); +#endif + ret = NPY_HALF_NAN; + } else if (npy_half_eq_nonan(x, y)) { + ret = x; + } else if (npy_half_iszero(x)) { + ret = (y&0x8000u) + 1; /* Smallest subnormal half */ + } else if (!(x&0x8000u)) { /* x > 0 */ + if ((npy_int16)x > (npy_int16)y) { /* x > y */ + ret = x-1; + } else { + ret = x+1; + } + } else { + if (!(y&0x8000u) || (x&0x7fffu) > (y&0x7fffu)) { /* x < y */ + ret = x-1; + } else { + ret = x+1; + } + } +#ifdef NPY_HALF_GENERATE_OVERFLOW + if (npy_half_isinf(ret)) { + generate_overflow_error(); + } +#endif + + return ret; +} + +int npy_half_eq_nonan(npy_half h1, npy_half h2) +{ + return (h1 == h2 || ((h1 | h2) & 0x7fff) == 0); +} + +int npy_half_eq(npy_half h1, npy_half h2) +{ + /* + * The equality cases are as follows: + * - If either value is NaN, never equal. + * - If the values are equal, equal. + * - If the values are both signed zeros, equal. + */ + return (!npy_half_isnan(h1) && !npy_half_isnan(h2)) && + (h1 == h2 || ((h1 | h2) & 0x7fff) == 0); +} + +int npy_half_ne(npy_half h1, npy_half h2) +{ + return !npy_half_eq(h1, h2); +} + +int npy_half_lt_nonan(npy_half h1, npy_half h2) +{ + if (h1&0x8000u) { + if (h2&0x8000u) { + return (h1&0x7fffu) > (h2&0x7fffu); + } else { + /* Signed zeros are equal, have to check for it */ + return (h1 != 0x8000u) || (h2 != 0x0000u); + } + } else { + if (h2&0x8000u) { + return 0; + } else { + return (h1&0x7fffu) < (h2&0x7fffu); + } + } +} + +int npy_half_lt(npy_half h1, npy_half h2) +{ + return (!npy_half_isnan(h1) && !npy_half_isnan(h2)) && npy_half_lt_nonan(h1, h2); +} + +int npy_half_gt(npy_half h1, npy_half h2) +{ + return npy_half_lt(h2, h1); +} + +int npy_half_le_nonan(npy_half h1, npy_half h2) +{ + if (h1&0x8000u) { + if (h2&0x8000u) { + return (h1&0x7fffu) >= (h2&0x7fffu); + } else { + return 1; + } + } else { + if (h2&0x8000u) { + /* Signed zeros are equal, have to check for it */ + return (h1 == 0x0000u) && (h2 == 0x8000u); + } else { + return (h1&0x7fffu) <= (h2&0x7fffu); + } + } +} + +int npy_half_le(npy_half h1, npy_half h2) +{ + return (!npy_half_isnan(h1) && !npy_half_isnan(h2)) && npy_half_le_nonan(h1, h2); +} + +int npy_half_ge(npy_half h1, npy_half h2) +{ + return npy_half_le(h2, h1); +} + + + +/* + ******************************************************************** + * BIT-LEVEL CONVERSIONS * + ******************************************************************** + */ + +npy_uint16 npy_floatbits_to_halfbits(npy_uint32 f) +{ + npy_uint32 f_exp, f_sig; + npy_uint16 h_sgn, h_exp, h_sig; + + h_sgn = (npy_uint16) ((f&0x80000000u) >> 16); + f_exp = (f&0x7f800000u); + + /* Exponent overflow/NaN converts to signed inf/NaN */ + if (f_exp >= 0x47800000u) { + if (f_exp == 0x7f800000u) { + /* Inf or NaN */ + f_sig = (f&0x007fffffu); + if (f_sig != 0) { + /* NaN - propagate the flag in the significand... */ + npy_uint16 ret = (npy_uint16) (0x7c00u + (f_sig >> 13)); + /* ...but make sure it stays a NaN */ + if (ret == 0x7c00u) { + ret++; + } + return h_sgn + ret; + } else { + /* signed inf */ + return (npy_uint16) (h_sgn + 0x7c00u); + } + } else { + /* overflow to signed inf */ +#if NPY_HALF_GENERATE_OVERFLOW + generate_overflow_error(); +#endif + return (npy_uint16) (h_sgn + 0x7c00u); + } + } + + /* Exponent underflow converts to a subnormal half or signed zero */ + if (f_exp <= 0x38000000u) { + /* + * Signed zeros, subnormal floats, and floats with small + * exponents all convert to signed zero halfs. + */ + if (f_exp < 0x33000000u) { +#if NPY_HALF_GENERATE_UNDERFLOW + /* If f != 0, it underflowed to 0 */ + if ((f&0x7fffffff) != 0) { + generate_underflow_error(); + } +#endif + return h_sgn; + } + /* Make the subnormal significand */ + f_exp >>= 23; + f_sig = (0x00800000u + (f&0x007fffffu)); +#if NPY_HALF_GENERATE_UNDERFLOW + /* If it's not exactly represented, it underflowed */ + if ((f_sig&(((npy_uint32)1 << (126 - f_exp)) - 1)) != 0) { + generate_underflow_error(); + } +#endif + f_sig >>= (113 - f_exp); + /* Handle rounding by adding 1 to the bit beyond half precision */ +#if NPY_HALF_ROUND_TIES_TO_EVEN + /* + * If the last bit in the half significand is 0 (already even), and + * the remaining bit pattern is 1000...0, then we do not add one + * to the bit after the half significand. In all other cases, we do. + */ + if ((f_sig&0x00003fffu) != 0x00001000u) { + f_sig += 0x00001000u; + } +#else + f_sig += 0x00001000u; +#endif + h_sig = (npy_uint16) (f_sig >> 13); + /* + * If the rounding causes a bit to spill into h_exp, it will + * increment h_exp from zero to one and h_sig will be zero. + * This is the correct result. + */ + return (npy_uint16) (h_sgn + h_sig); + } + + /* Regular case with no overflow or underflow */ + h_exp = (npy_uint16) ((f_exp - 0x38000000u) >> 13); + /* Handle rounding by adding 1 to the bit beyond half precision */ + f_sig = (f&0x007fffffu); +#if NPY_HALF_ROUND_TIES_TO_EVEN + /* + * If the last bit in the half significand is 0 (already even), and + * the remaining bit pattern is 1000...0, then we do not add one + * to the bit after the half significand. In all other cases, we do. + */ + if ((f_sig&0x00003fffu) != 0x00001000u) { + f_sig += 0x00001000u; + } +#else + f_sig += 0x00001000u; +#endif + h_sig = (npy_uint16) (f_sig >> 13); + /* + * If the rounding causes a bit to spill into h_exp, it will + * increment h_exp by one and h_sig will be zero. This is the + * correct result. h_exp may increment to 15, at greatest, in + * which case the result overflows to a signed inf. + */ +#if NPY_HALF_GENERATE_OVERFLOW + h_sig += h_exp; + if (h_sig == 0x7c00u) { + generate_overflow_error(); + } + return h_sgn + h_sig; +#else + return h_sgn + h_exp + h_sig; +#endif +} + +npy_uint16 npy_doublebits_to_halfbits(npy_uint64 d) +{ + npy_uint64 d_exp, d_sig; + npy_uint16 h_sgn, h_exp, h_sig; + + h_sgn = (d&0x8000000000000000u) >> 48; + d_exp = (d&0x7ff0000000000000u); + + /* Exponent overflow/NaN converts to signed inf/NaN */ + if (d_exp >= 0x40f0000000000000u) { + if (d_exp == 0x7ff0000000000000u) { + /* Inf or NaN */ + d_sig = (d&0x000fffffffffffffu); + if (d_sig != 0) { + /* NaN - propagate the flag in the significand... */ + npy_uint16 ret = (npy_uint16) (0x7c00u + (d_sig >> 42)); + /* ...but make sure it stays a NaN */ + if (ret == 0x7c00u) { + ret++; + } + return h_sgn + ret; + } else { + /* signed inf */ + return h_sgn + 0x7c00u; + } + } else { + /* overflow to signed inf */ +#if NPY_HALF_GENERATE_OVERFLOW + generate_overflow_error(); +#endif + return h_sgn + 0x7c00u; + } + } + + /* Exponent underflow converts to subnormal half or signed zero */ + if (d_exp <= 0x3f00000000000000u) { + /* + * Signed zeros, subnormal floats, and floats with small + * exponents all convert to signed zero halfs. + */ + if (d_exp < 0x3e60000000000000u) { +#if NPY_HALF_GENERATE_UNDERFLOW + /* If d != 0, it underflowed to 0 */ + if ((d&0x7fffffffffffffff) != 0) { + generate_underflow_error(); + } +#endif + return h_sgn; + } + /* Make the subnormal significand */ + d_exp >>= 52; + d_sig = (0x0010000000000000u + (d&0x000fffffffffffffu)); +#if NPY_HALF_GENERATE_UNDERFLOW + /* If it's not exactly represented, it underflowed */ + if ((d_sig&(((npy_uint64)1 << (1051 - d_exp)) - 1)) != 0) { + generate_underflow_error(); + } +#endif + d_sig >>= (1009 - d_exp); + /* Handle rounding by adding 1 to the bit beyond half precision */ +#if NPY_HALF_ROUND_TIES_TO_EVEN + /* + * If the last bit in the half significand is 0 (already even), and + * the remaining bit pattern is 1000...0, then we do not add one + * to the bit after the half significand. In all other cases, we do. + */ + if ((d_sig&0x000007ffffffffffu) != 0x0000020000000000u) { + d_sig += 0x0000020000000000u; + } +#else + d_sig += 0x0000020000000000u; +#endif + h_sig = (npy_uint16) (d_sig >> 42); + /* + * If the rounding causes a bit to spill into h_exp, it will + * increment h_exp from zero to one and h_sig will be zero. + * This is the correct result. + */ + return h_sgn + h_sig; + } + + /* Regular case with no overflow or underflow */ + h_exp = (npy_uint16) ((d_exp - 0x3f00000000000000u) >> 42); + /* Handle rounding by adding 1 to the bit beyond half precision */ + d_sig = (d&0x000fffffffffffffu); +#if NPY_HALF_ROUND_TIES_TO_EVEN + /* + * If the last bit in the half significand is 0 (already even), and + * the remaining bit pattern is 1000...0, then we do not add one + * to the bit after the half significand. In all other cases, we do. + */ + if ((d_sig&0x000007ffffffffffu) != 0x0000020000000000u) { + d_sig += 0x0000020000000000u; + } +#else + d_sig += 0x0000020000000000u; +#endif + h_sig = (npy_uint16) (d_sig >> 42); + + /* + * If the rounding causes a bit to spill into h_exp, it will + * increment h_exp by one and h_sig will be zero. This is the + * correct result. h_exp may increment to 15, at greatest, in + * which case the result overflows to a signed inf. + */ +#if NPY_HALF_GENERATE_OVERFLOW + h_sig += h_exp; + if (h_sig == 0x7c00u) { + generate_overflow_error(); + } + return h_sgn + h_sig; +#else + return h_sgn + h_exp + h_sig; +#endif +} + +npy_uint32 npy_halfbits_to_floatbits(npy_uint16 h) +{ + npy_uint16 h_exp, h_sig; + npy_uint32 f_sgn, f_exp, f_sig; + + h_exp = (h&0x7c00u); + f_sgn = ((npy_uint32)h&0x8000u) << 16; + switch (h_exp) { + case 0x0000u: /* 0 or subnormal */ + h_sig = (h&0x03ffu); + /* Signed zero */ + if (h_sig == 0) { + return f_sgn; + } + /* Subnormal */ + h_sig <<= 1; + while ((h_sig&0x0400u) == 0) { + h_sig <<= 1; + h_exp++; + } + f_exp = ((npy_uint32)(127 - 15 - h_exp)) << 23; + f_sig = ((npy_uint32)(h_sig&0x03ffu)) << 13; + return f_sgn + f_exp + f_sig; + case 0x7c00u: /* inf or NaN */ + /* All-ones exponent and a copy of the significand */ + return f_sgn + 0x7f800000u + (((npy_uint32)(h&0x03ffu)) << 13); + default: /* normalized */ + /* Just need to adjust the exponent and shift */ + return f_sgn + (((npy_uint32)(h&0x7fffu) + 0x1c000u) << 13); + } +} + +npy_uint64 npy_halfbits_to_doublebits(npy_uint16 h) +{ + npy_uint16 h_exp, h_sig; + npy_uint64 d_sgn, d_exp, d_sig; + + h_exp = (h&0x7c00u); + d_sgn = ((npy_uint64)h&0x8000u) << 48; + switch (h_exp) { + case 0x0000u: /* 0 or subnormal */ + h_sig = (h&0x03ffu); + /* Signed zero */ + if (h_sig == 0) { + return d_sgn; + } + /* Subnormal */ + h_sig <<= 1; + while ((h_sig&0x0400u) == 0) { + h_sig <<= 1; + h_exp++; + } + d_exp = ((npy_uint64)(1023 - 15 - h_exp)) << 52; + d_sig = ((npy_uint64)(h_sig&0x03ffu)) << 42; + return d_sgn + d_exp + d_sig; + case 0x7c00u: /* inf or NaN */ + /* All-ones exponent and a copy of the significand */ + return d_sgn + 0x7ff0000000000000u + + (((npy_uint64)(h&0x03ffu)) << 42); + default: /* normalized */ + /* Just need to adjust the exponent and shift */ + return d_sgn + (((npy_uint64)(h&0x7fffu) + 0xfc000u) << 42); + } +} + diff --git a/numpy/core/src/scalarmathmodule.c.src b/numpy/core/src/scalarmathmodule.c.src index c4e6263ba..712932958 100644 --- a/numpy/core/src/scalarmathmodule.c.src +++ b/numpy/core/src/scalarmathmodule.c.src @@ -13,6 +13,8 @@ #include "numpy/npy_3kcompat.h" +#include "numpy/halffloat.h" + /** numarray adapted routines.... **/ #if SIZEOF_LONGLONG == 64 || SIZEOF_LONGLONG == 128 @@ -352,6 +354,17 @@ static @name@ (*_basic_@name@_fmod)(@name@, @name@); *(outp) = _basic_@name@_floor((a) / (b)) /**end repeat**/ +static npy_half (*_basic_half_floor)(npy_half); +static npy_half (*_basic_half_sqrt)(npy_half); +static npy_half (*_basic_half_fmod)(npy_half, npy_half); +#define half_ctype_add(a, b, outp) *(outp) = npy_float_to_half(npy_half_to_float(a) + npy_half_to_float(b)) +#define half_ctype_subtract(a, b, outp) *(outp) = npy_float_to_half(npy_half_to_float(a) - npy_half_to_float(b)) +#define half_ctype_multiply(a, b, outp) *(outp) = npy_float_to_half(npy_half_to_float(a) * npy_half_to_float(b)) +#define half_ctype_divide(a, b, outp) *(outp) = npy_float_to_half(npy_half_to_float(a) / npy_half_to_float(b)) +#define half_ctype_true_divide half_ctype_divide +#define half_ctype_floor_divide(a, b, outp) \ + *(outp) = npy_float_to_half(_basic_float_floor(npy_half_to_float(a) / npy_half_to_float(b))) + /**begin repeat * #name = cfloat, cdouble, clongdouble# * #rtype = float, double, longdouble# @@ -397,11 +410,20 @@ static void } /**end repeat**/ +static void +half_ctype_remainder(npy_half a, npy_half b, npy_half *out) { + float mod, fa = npy_half_to_float(a), fb = npy_half_to_float(b); + mod = _basic_float_fmod(fa, fb); + if (mod && (((fb < 0) != (mod < 0)))) { + mod += fb; + } + *out = npy_float_to_half(mod); +} /**begin repeat * #name = byte, ubyte, short, ushort, int, uint, long, ulong, longlong, - * ulonglong, float, double, longdouble, cfloat, cdouble, clongdouble# + * ulonglong, half, float, double, longdouble, cfloat, cdouble, clongdouble# */ #define @name@_ctype_divmod(a, b, out, out2) { \ @name@_ctype_floor_divide(a, b, out); \ @@ -410,11 +432,11 @@ static void /**end repeat**/ /**begin repeat - * #name = float, double, longdouble# + * #name = half, float, double, longdouble# */ -static @name@ (*_basic_@name@_pow)(@name@ a, @name@ b); +static npy_@name@ (*_basic_@name@_pow)(npy_@name@ a, npy_@name@ b); static void -@name@_ctype_power(@name@ a, @name@ b, @name@ *out) { +@name@_ctype_power(npy_@name@ a, npy_@name@ b, npy_@name@ *out) { *out = _basic_@name@_pow(a, b); } /**end repeat**/ @@ -425,7 +447,7 @@ static void * #uns = (0,1)*5,0*3# */ static void -@name@_ctype_negative(@name@ a, @name@ *out) +@name@_ctype_negative(npy_@name@ a, npy_@name@ *out) { #if @uns@ generate_overflow_error(); @@ -434,6 +456,12 @@ static void } /**end repeat**/ +static void +half_ctype_negative(npy_half a, npy_half *out) +{ + *out = a^0x8000u; +} + /**begin repeat * #name = cfloat, cdouble, clongdouble# @@ -448,10 +476,10 @@ static void /**begin repeat * #name = byte, ubyte, short, ushort, int, uint, long, ulong, longlong, - * ulonglong, float, double, longdouble# + * ulonglong, half, float, double, longdouble# */ static void -@name@_ctype_positive(@name@ a, @name@ *out) +@name@_ctype_positive(npy_@name@ a, npy_@name@ *out) { *out = a; } @@ -497,6 +525,12 @@ static void } /**end repeat**/ +static void +half_ctype_absolute(npy_half a, npy_half *out) +{ + *out = a&0x7fffu; +} + /**begin repeat * #name = cfloat, cdouble, clongdouble# * #rname = float, double, longdouble# @@ -534,15 +568,15 @@ static void /**begin repeat * #name = byte, ubyte, short, ushort, int, uint, long, ulong, longlong, - * ulonglong, float, double, longdouble, cfloat, cdouble, clongdouble# + * ulonglong, half, float, double, longdouble, cfloat, cdouble, clongdouble# * #Name = Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, - * ULongLong, Float, Double, LongDouble, CFloat, CDouble, CLongDouble# + * ULongLong, Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble# * #NAME = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG, LONGLONG, - * ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE# + * ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE# */ static int -_@name@_convert_to_ctype(PyObject *a, @name@ *arg1) +_@name@_convert_to_ctype(PyObject *a, npy_@name@ *arg1) { PyObject *temp; @@ -585,11 +619,11 @@ _@name@_convert_to_ctype(PyObject *a, @name@ *arg1) /**begin repeat * #name = byte, ubyte, short, ushort, int, uint, long, ulong, - * longlong, ulonglong, float, double, cfloat, cdouble# + * longlong, ulonglong, half, float, double, cfloat, cdouble# */ static int -_@name@_convert2_to_ctypes(PyObject *a, @name@ *arg1, - PyObject *b, @name@ *arg2) +_@name@_convert2_to_ctypes(PyObject *a, npy_@name@ *arg1, + PyObject *b, npy_@name@ *arg2) { int ret; ret = _@name@_convert_to_ctype(a, arg1); @@ -635,14 +669,32 @@ _@name@_convert2_to_ctypes(PyObject *a, @name@ *arg1, #endif /**begin repeat - #name=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong)*13, (float, double, longdouble, cfloat, cdouble, clongdouble)*6, (float, double, longdouble)*2# - #Name=(Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong)*13, (Float, Double, LongDouble, CFloat, CDouble, CLongDouble)*6, (Float, Double, LongDouble)*2# - #oper=add*10, subtract*10, multiply*10, divide*10, remainder*10, divmod*10, floor_divide*10, lshift*10, rshift*10, and*10, or*10, xor*10, true_divide*10, add*6, subtract*6, multiply*6, divide*6, floor_divide*6, true_divide*6, divmod*3, remainder*3# - #fperr=1*70,0*50,1*52# - #twoout=0*50,1*10,0*106,1*3,0*3# - #otyp=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong)*12, float*4, double*6, (float, double, longdouble, cfloat, cdouble, clongdouble)*6, (float, double, longdouble)*2# - #OName=(Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong)*12, Float*4, Double*6, (Float, Double, LongDouble, CFloat, CDouble, CLongDouble)*6, (Float, Double, LongDouble)*2# -**/ + * #name=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong)*13, + * (half, float, double, longdouble, cfloat, cdouble, clongdouble)*6, + * (half, float, double, longdouble)*2# + * #Name=(Byte,UByte,Short,UShort,Int,UInt,Long,ULong,LongLong,ULongLong)*13, + * (Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble)*6, + * (Half, Float, Double, LongDouble)*2# + * #oper=add*10, subtract*10, multiply*10, divide*10, remainder*10, + * divmod*10, floor_divide*10, lshift*10, rshift*10, and*10, + * or*10, xor*10, true_divide*10, + * add*7, subtract*7, multiply*7, divide*7, floor_divide*7, true_divide*7, + * divmod*4, remainder*4# + * #fperr=1*70,0*50,1*10, + * 1*42, + * 1*8# + * #twoout=0*50,1*10,0*70, + * 0*42, + * 1*4,0*4# + * #otyp=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong)*12, + * float*4, double*6, + * (half, float, double, longdouble, cfloat, cdouble, clongdouble)*6, + * (half, float, double, longdouble)*2# + * #OName=(Byte,UByte,Short,UShort,Int,UInt,Long,ULong,LongLong,ULongLong)*12, + * Float*4, Double*6, + * (Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble)*6, + * (Half, Float, Double, LongDouble)*2# + */ #if !defined(CODEGEN_SKIP_@oper@_FLAG) @@ -650,16 +702,16 @@ static PyObject * @name@_@oper@(PyObject *a, PyObject *b) { PyObject *ret; - @name@ arg1, arg2; + npy_@name@ arg1, arg2; /* * NOTE: In gcc >= 4.1, the compiler will reorder floating point operations and * floating point error state checks. In particular, the arithmetic operations * were being reordered so that the errors weren't caught. Declaring this output * variable volatile was the minimal fix for the issue. (Ticket #1671) */ - volatile @otyp@ out; + volatile npy_@otyp@ out; #if @twoout@ - @otyp@ out2; + npy_@otyp@ out2; PyObject *obj; #endif @@ -698,9 +750,9 @@ static PyObject * * as a function call. */ #if @twoout@ - @name@_ctype_@oper@(arg1, arg2, (@otyp@ *)&out, &out2); + @name@_ctype_@oper@(arg1, arg2, (npy_@otyp@ *)&out, &out2); #else - @name@_ctype_@oper@(arg1, arg2, (@otyp@ *)&out); + @name@_ctype_@oper@(arg1, arg2, (npy_@otyp@ *)&out); #endif #if @fperr@ @@ -758,30 +810,36 @@ static PyObject * #undef CODEGEN_SKIP_divide_FLAG +#define _IS_ZERO(x) (x ==0) /**begin repeat - #name=byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float, double, longdouble, cfloat, cdouble, clongdouble# - #Name=Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, Float, Double, LongDouble, CFloat, CDouble, CLongDouble# - #otyp=float*4, double*6, float, double, longdouble, cfloat, cdouble, clongdouble# - #OName=Float*4, Double*6, Float, Double, LongDouble, CFloat, CDouble, CLongDouble# - #isint=(1,0)*5,0*6# - #cmplx=0*13,1*3# -**/ + * #name=byte, ubyte, short, ushort, int, uint, long, ulong, longlong, ulonglong, + * half, float, double, longdouble, cfloat, cdouble, clongdouble# + * #Name=Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, + * Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble# + * #otyp=float*4, double*6, half, float, double, longdouble, cfloat, cdouble, clongdouble# + * #OName=Float*4, Double*6, Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble# + * #isint=(1,0)*5,0*7# + * #cmplx=0*14,1*3# + * #iszero=_IS_ZERO*10, npy_half_iszero, _IS_ZERO*6# + * #zero=0*10, NPY_HALF_ZERO, 0*6# + * #one=1*10, NPY_HALF_ONE, 1*6# + */ static PyObject * @name@_power(PyObject *a, PyObject *b, PyObject *NPY_UNUSED(c)) { PyObject *ret; - @name@ arg1, arg2; + npy_@name@ arg1, arg2; int retstatus; int first; #if @cmplx@ - @name@ out = {0,0}; - @otyp@ out1; - out1.real = out.imag = 0; + npy_@name@ out = {@zero@,@zero@}; + npy_@otyp@ out1; + out1.real = out.imag = @zero@; #else - @name@ out = 0; - @otyp@ out1=0; + npy_@name@ out = @zero@; + npy_@otyp@ out1 = @zero@; #endif switch(_@name@_convert2_to_ctypes(a, &arg1, b, &arg2)) { @@ -812,13 +870,13 @@ static PyObject * * as a function call. */ #if @cmplx@ - if (arg2.real == 0 && arg2.imag == 0) { - out1.real = out.real = 1; - out1.imag = out.imag = 0; + if (@iszero@(arg2.real) && @iszero@(arg2.imag)) { + out1.real = out.real = @one@; + out1.imag = out.imag = @zero@; } #else - if (arg2 == 0) { - out1 = out = 1; + if (@iszero@(arg2)) { + out1 = out = @one@; } #endif #if @isint@ @@ -875,6 +933,7 @@ static PyObject * return ret; } /**end repeat**/ +#undef _IS_ZERO /**begin repeat @@ -885,24 +944,29 @@ static PyObject * /**end repeat**/ /**begin repeat - * #name = (float,double,longdouble,cfloat,cdouble,clongdouble)*5# - * #oper = lshift*6, rshift*6, and*6, or*6, xor*6# + * #name = (half,float,double,longdouble,cfloat,cdouble,clongdouble)*5# + * #oper = lshift*7, rshift*7, and*7, or*7, xor*7# */ #define @name@_@oper@ NULL /**end repeat**/ /**begin repeat - * #name=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,cfloat,cdouble,clongdouble)*3, byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong# - * #otyp=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,cfloat,cdouble,clongdouble)*2,byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,float,double,longdouble,byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong# - * #OName=(Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, Float, Double, LongDouble, CFloat, CDouble, CLongDouble)*2, Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, Float, Double, LongDouble, Float, Double, LongDouble, Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong# - * #oper=negative*16, positive*16, absolute*16, invert*10# + * #name=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,half,float,double,longdouble,cfloat,cdouble,clongdouble)*3, + * byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong# + * #otyp=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,half,float,double,longdouble,cfloat,cdouble,clongdouble)*2, + * byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,half,float,double,longdouble,float,double,longdouble, + * byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong# + * #OName=(Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble)*2, + Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, Half, Float, Double, LongDouble, Float, Double, LongDouble, + Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong# + * #oper=negative*17, positive*17, absolute*17, invert*10# */ static PyObject * @name@_@oper@(PyObject *a) { - @name@ arg1; - @otyp@ out; + npy_@name@ arg1; + npy_@otyp@ out; PyObject *ret; switch(_@name@_convert_to_ctype(a, &arg1)) { @@ -935,7 +999,7 @@ static PyObject * /**end repeat**/ /**begin repeat - * #name = float, double, longdouble, cfloat, cdouble, clongdouble# + * #name = half, float, double, longdouble, cfloat, cdouble, clongdouble# */ #define @name@_invert NULL /**end repeat**/ @@ -946,16 +1010,18 @@ static PyObject * #define NONZERO_NAME(prefix, suffix) prefix##nonzero##suffix #endif +#define _IS_NONZERO(x) (x != 0) /**begin repeat * #name = byte, ubyte, short, ushort, int, uint, long, ulong, longlong, - * ulonglong, float, double, longdouble, cfloat, cdouble, clongdouble# - * #simp=1*13,0*3# + * ulonglong, half, float, double, longdouble, cfloat, cdouble, clongdouble# + * #simp=1*14,0*3# + * #nonzero=_IS_NONZERO*10, !npy_half_iszero, _IS_NONZERO*6# */ static int NONZERO_NAME(@name@_,)(PyObject *a) { int ret; - @name@ arg1; + npy_@name@ arg1; if (_@name@_convert_to_ctype(a, &arg1) < 0) { if (PyErr_Occurred()) { @@ -970,21 +1036,21 @@ NONZERO_NAME(@name@_,)(PyObject *a) */ #if @simp@ - ret = (arg1 != 0); + ret = @nonzero@(arg1); #else - ret = ((arg1.real != 0) || (arg1.imag != 0)); + ret = (@nonzero@(arg1.real) || @nonzero@(arg1.imag)); #endif return ret; } /**end repeat**/ +#undef _IS_NONZERO static int emit_complexwarning() { static PyObject *cls = NULL; - int ret; if (cls == NULL) { PyObject *mod; mod = PyImport_ImportModule("numpy.core"); @@ -1006,23 +1072,24 @@ emit_complexwarning() /**begin repeat * - * #name=byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,cfloat,cdouble,clongdouble# - * #Name=Byte,UByte,Short,UShort,Int,UInt,Long,ULong,LongLong,ULongLong,Float,Double,LongDouble,CFloat,CDouble,CLongDouble# - * #cmplx=0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1# - * #sign=(signed,unsigned)*5,,,,,,# - * #unsigntyp=0,1,0,1,0,1,0,1,0,1,0*6# - * #ctype=long*8,PY_LONG_LONG*2,double*6# - * #realtyp=0*10,1*6# - * #func=(PyLong_FromLong,PyLong_FromUnsignedLong)*4,PyLong_FromLongLong,PyLong_FromUnsignedLongLong,PyLong_FromDouble*6# + * #name=byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,half,float,double,longdouble,cfloat,cdouble,clongdouble# + * #Name=Byte,UByte,Short,UShort,Int,UInt,Long,ULong,LongLong,ULongLong,Half,Float,Double,LongDouble,CFloat,CDouble,CLongDouble# + * #cmplx=0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1# + * #sign=(signed,unsigned)*5,,,,,,,# + * #unsigntyp=0,1,0,1,0,1,0,1,0,1,0*7# + * #ctype=long*8,PY_LONG_LONG*2,double*7# + * #to_ctype=,,,,,,,,,,npy_half_to_double,,,,,,# + * #realtyp=0*10,1*7# + * #func=(PyLong_FromLong,PyLong_FromUnsignedLong)*4,PyLong_FromLongLong,PyLong_FromUnsignedLongLong,PyLong_FromDouble*7# */ static PyObject * @name@_int(PyObject *obj) { #if @cmplx@ - @sign@ @ctype@ x= PyArrayScalar_VAL(obj, @Name@).real; + @sign@ @ctype@ x= @to_ctype@(PyArrayScalar_VAL(obj, @Name@).real); int ret; #else - @sign@ @ctype@ x= PyArrayScalar_VAL(obj, @Name@); + @sign@ @ctype@ x= @to_ctype@(PyArrayScalar_VAL(obj, @Name@)); #endif #if @realtyp@ double ix; @@ -1049,11 +1116,12 @@ static PyObject * /**begin repeat * - * #name=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,cfloat,cdouble,clongdouble)*2# - * #Name=(Byte,UByte,Short,UShort,Int,UInt,Long,ULong,LongLong,ULongLong,Float,Double,LongDouble,CFloat,CDouble,CLongDouble)*2# - * #cmplx=(0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1)*2# - * #which=long*16,float*16# - * #func=(PyLong_FromLongLong, PyLong_FromUnsignedLongLong)*5,PyLong_FromDouble*6,PyFloat_FromDouble*16# + * #name=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,half,float,double,longdouble,cfloat,cdouble,clongdouble)*2# + * #Name=(Byte,UByte,Short,UShort,Int,UInt,Long,ULong,LongLong,ULongLong,Half,Float,Double,LongDouble,CFloat,CDouble,CLongDouble)*2# + * #cmplx=(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1)*2# + * #to_ctype=(,,,,,,,,,,npy_half_to_double,,,,,,)*2# + * #which=long*17,float*17# + * #func=(PyLong_FromLongLong, PyLong_FromUnsignedLongLong)*5,PyLong_FromDouble*7,PyFloat_FromDouble*17# */ static PyObject * @name@_@which@(PyObject *obj) @@ -1064,9 +1132,9 @@ static PyObject * if (ret < 0) { return NULL; } - return @func@((PyArrayScalar_VAL(obj, @Name@)).real); + return @func@(@to_ctype@((PyArrayScalar_VAL(obj, @Name@)).real)); #else - return @func@((PyArrayScalar_VAL(obj, @Name@))); + return @func@(@to_ctype@(PyArrayScalar_VAL(obj, @Name@))); #endif } /**end repeat**/ @@ -1075,10 +1143,10 @@ static PyObject * /**begin repeat * - * #name=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,cfloat,cdouble,clongdouble)*2# - * #oper=oct*16, hex*16# - * #kind=(int*5, long*5, int, long*2, int, long*2)*2# - * #cap=(Int*5, Long*5, Int, Long*2, Int, Long*2)*2# + * #name=(byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,half,float,double,longdouble,cfloat,cdouble,clongdouble)*2# + * #oper=oct*17, hex*17# + * #kind=(int*5, long*5, int*2, long*2, int, long*2)*2# + * #cap=(Int*5, Long*5, Int*2, Long*2, Int, Long*2)*2# */ static PyObject * @name@_@oper@(PyObject *obj) @@ -1095,21 +1163,23 @@ static PyObject * /**begin repeat * #oper=le,ge,lt,gt,eq,ne# * #op=<=,>=,<,>,==,!=# + * #halfop=npy_half_le,npy_half_ge,npy_half_lt,npy_half_gt,npy_half_eq,npy_half_ne# */ #define def_cmp_@oper@(arg1, arg2) (arg1 @op@ arg2) #define cmplx_cmp_@oper@(arg1, arg2) ((arg1.real == arg2.real) ? \ arg1.imag @op@ arg2.imag : \ arg1.real @op@ arg2.real) +#define def_half_cmp_@oper@(arg1, arg2) @halfop@(arg1, arg2) /**end repeat**/ /**begin repeat - * #name=byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,cfloat,cdouble,clongdouble# - * #simp=def*13,cmplx*3# + * #name=byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,half,float,double,longdouble,cfloat,cdouble,clongdouble# + * #simp=def*10,def_half,def*3,cmplx*3# */ static PyObject* @name@_richcompare(PyObject *self, PyObject *other, int cmp_op) { - @name@ arg1, arg2; + npy_@name@ arg1, arg2; int out=0; switch(_@name@_convert2_to_ctypes(self, &arg1, other, &arg2)) { @@ -1158,7 +1228,7 @@ static PyObject* /**begin repeat - #name=byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,cfloat,cdouble,clongdouble# + #name=byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,half,float,double,longdouble,cfloat,cdouble,clongdouble# **/ static PyNumberMethods @name@_as_number = { (binaryfunc)@name@_add, /*nb_add*/ @@ -1231,8 +1301,8 @@ static void add_scalarmath(void) { /**begin repeat - #name=byte,ubyte,short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,cfloat,cdouble,clongdouble# - #NAME=Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, Float, Double, LongDouble, CFloat, CDouble, CLongDouble# + #name=byte, ubyte, short, ushort, int, uint, long, ulong, longlong, ulonglong, half, float, double, longdouble, cfloat, cdouble, clongdouble# + #NAME=Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble# **/ #if PY_VERSION_HEX >= 0x02050000 @name@_as_number.nb_index = Py@NAME@ArrType_Type.tp_as_number->nb_index; @@ -1280,6 +1350,7 @@ get_functions(void) i = 0; j = 0; while(signatures[i] != PyArray_FLOAT) {i+=3; j++;} + _basic_half_pow = funcdata[j-1]; _basic_float_pow = funcdata[j]; _basic_double_pow = funcdata[j+1]; _basic_longdouble_pow = funcdata[j+2]; @@ -1296,6 +1367,7 @@ get_functions(void) i = 0; j = 0; while(signatures[i] != PyArray_FLOAT) {i+=2; j++;} + _basic_half_floor = funcdata[j-1]; _basic_float_floor = funcdata[j]; _basic_double_floor = funcdata[j+1]; _basic_longdouble_floor = funcdata[j+2]; @@ -1309,6 +1381,7 @@ get_functions(void) i = 0; j = 0; while(signatures[i] != PyArray_FLOAT) {i+=2; j++;} + _basic_half_sqrt = funcdata[j-1]; _basic_float_sqrt = funcdata[j]; _basic_double_sqrt = funcdata[j+1]; _basic_longdouble_sqrt = funcdata[j+2]; @@ -1322,6 +1395,7 @@ get_functions(void) i = 0; j = 0; while(signatures[i] != PyArray_FLOAT) {i+=3; j++;} + _basic_half_fmod = funcdata[j-1]; _basic_float_fmod = funcdata[j]; _basic_double_fmod = funcdata[j+1]; _basic_longdouble_fmod = funcdata[j+2]; diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index c61d16ae4..0c777e464 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -13,11 +13,13 @@ #include "numpy/noprefix.h" #include "numpy/ufuncobject.h" #include "numpy/npy_math.h" +#include "numpy/halffloat.h" #include "numpy/npy_3kcompat.h" #include "ufunc_object.h" + /* ***************************************************************************** ** UFUNC LOOPS ** @@ -56,13 +58,17 @@ intp i;\ for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1) -#define BINARY_REDUCE_LOOP(TYPE)\ - char *iop1 = args[0], *ip2 = args[1]; \ +#define BINARY_REDUCE_LOOP_INNER\ + char *ip2 = args[1]; \ intp is2 = steps[1]; \ intp n = dimensions[0]; \ intp i; \ - TYPE io1 = *(TYPE *)iop1; \ for(i = 0; i < n; i++, ip2 += is2) + +#define BINARY_REDUCE_LOOP(TYPE)\ + char *iop1 = args[0]; \ + TYPE io1 = *(TYPE *)iop1; \ + BINARY_REDUCE_LOOP_INNER #define BINARY_LOOP_TWO_OUT\ char *ip1 = args[0], *ip2 = args[1], *op1 = args[2], *op2 = args[3];\ @@ -76,9 +82,11 @@ *****************************************************************************/ +typedef float halfUnaryFunc(npy_half x); typedef float floatUnaryFunc(float x); typedef double doubleUnaryFunc(double x); typedef longdouble longdoubleUnaryFunc(longdouble x); +typedef npy_half halfBinaryFunc(npy_half x, npy_half y); typedef float floatBinaryFunc(float x, float y); typedef double doubleBinaryFunc(double x, double y); typedef longdouble longdoubleBinaryFunc(longdouble x, longdouble y); @@ -86,6 +94,39 @@ typedef longdouble longdoubleBinaryFunc(longdouble x, longdouble y); /*UFUNC_API*/ NPY_NO_EXPORT void +PyUFunc_e_e(char **args, intp *dimensions, intp *steps, void *func) +{ + halfUnaryFunc *f = (halfUnaryFunc *)func; + UNARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + *(npy_half *)op1 = f(in1); + } +} + +/*UFUNC_API*/ +NPY_NO_EXPORT void +PyUFunc_e_e_As_f_f(char **args, intp *dimensions, intp *steps, void *func) +{ + floatUnaryFunc *f = (floatUnaryFunc *)func; + UNARY_LOOP { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + *(npy_half *)op1 = npy_float_to_half(f(in1)); + } +} + +/*UFUNC_API*/ +NPY_NO_EXPORT void +PyUFunc_e_e_As_d_d(char **args, intp *dimensions, intp *steps, void *func) +{ + doubleUnaryFunc *f = (doubleUnaryFunc *)func; + UNARY_LOOP { + const double in1 = npy_half_to_double(*(npy_half *)ip1); + *(npy_half *)op1 = npy_double_to_half(f(in1)); + } +} + +/*UFUNC_API*/ +NPY_NO_EXPORT void PyUFunc_f_f(char **args, intp *dimensions, intp *steps, void *func) { floatUnaryFunc *f = (floatUnaryFunc *)func; @@ -108,6 +149,42 @@ PyUFunc_f_f_As_d_d(char **args, intp *dimensions, intp *steps, void *func) /*UFUNC_API*/ NPY_NO_EXPORT void +PyUFunc_ee_e(char **args, intp *dimensions, intp *steps, void *func) +{ + halfBinaryFunc *f = (halfBinaryFunc *)func; + BINARY_LOOP { + npy_half in1 = *(npy_half *)ip1; + npy_half in2 = *(npy_half *)ip2; + *(npy_half *)op1 = f(in1, in2); + } +} + +/*UFUNC_API*/ +NPY_NO_EXPORT void +PyUFunc_ee_e_As_ff_f(char **args, intp *dimensions, intp *steps, void *func) +{ + floatBinaryFunc *f = (floatBinaryFunc *)func; + BINARY_LOOP { + float in1 = npy_half_to_float(*(npy_half *)ip1); + float in2 = npy_half_to_float(*(npy_half *)ip2); + *(npy_half *)op1 = npy_float_to_half(f(in1, in2)); + } +} + +/*UFUNC_API*/ +NPY_NO_EXPORT void +PyUFunc_ee_e_As_dd_d(char **args, intp *dimensions, intp *steps, void *func) +{ + doubleBinaryFunc *f = (doubleBinaryFunc *)func; + BINARY_LOOP { + double in1 = npy_half_to_double(*(npy_half *)ip1); + double in2 = npy_half_to_double(*(npy_half *)ip2); + *(npy_half *)op1 = npy_double_to_half(f(in1, in2)); + } +} + +/*UFUNC_API*/ +NPY_NO_EXPORT void PyUFunc_ff_f(char **args, intp *dimensions, intp *steps, void *func) { floatBinaryFunc *f = (floatBinaryFunc *)func; @@ -1053,8 +1130,6 @@ NPY_NO_EXPORT void } /**end repeat1**/ -/**end repeat1**/ - /**begin repeat1 * #kind = equal, not_equal, less, less_equal, greater, greater_equal, * logical_and, logical_or# @@ -1322,6 +1397,311 @@ NPY_NO_EXPORT void /**end repeat**/ +/* + ***************************************************************************** + ** HALF-FLOAT LOOPS ** + ***************************************************************************** + */ + + +/**begin repeat + * Arithmetic + * # kind = add, subtract, multiply, divide# + * # OP = +, -, *, /# + */ +NPY_NO_EXPORT void +HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + if(IS_BINARY_REDUCE) { + char *iop1 = args[0]; + float io1 = npy_half_to_float(*(npy_half *)iop1); + BINARY_REDUCE_LOOP_INNER { + io1 @OP@= npy_half_to_float(*(npy_half *)ip2); + } + *((npy_half *)iop1) = npy_float_to_half(io1); + } + else { + BINARY_LOOP { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + const float in2 = npy_half_to_float(*(npy_half *)ip2); + *((npy_half *)op1) = npy_float_to_half(in1 @OP@ in2); + } + } +} +/**end repeat**/ + +#define _HALF_LOGICAL_AND(a,b) (!npy_half_iszero(a) && !npy_half_iszero(b)) +#define _HALF_LOGICAL_OR(a,b) (!npy_half_iszero(a) || !npy_half_iszero(b)) +/**begin repeat + * #kind = equal, not_equal, less, less_equal, greater, greater_equal, + * logical_and, logical_or# + * #OP = npy_half_eq, npy_half_ne, npy_half_lt, npy_half_le, npy_half_gt, npy_half_ge, _HALF_LOGICAL_AND, _HALF_LOGICAL_OR# + */ +NPY_NO_EXPORT void +HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + BINARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + const npy_half in2 = *(npy_half *)ip2; + *((Bool *)op1) = @OP@(in1, in2); + } +} +/**end repeat**/ +#undef _HALF_LOGICAL_AND +#undef _HALF_LOGICAL_OR + +NPY_NO_EXPORT void +HALF_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + BINARY_LOOP { + const int in1 = !npy_half_iszero(*(npy_half *)ip1); + const int in2 = !npy_half_iszero(*(npy_half *)ip2); + *((Bool *)op1)= (in1 && !in2) || (!in1 && in2); + } +} + +NPY_NO_EXPORT void +HALF_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + UNARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + *((Bool *)op1) = npy_half_iszero(in1); + } +} + +/**begin repeat + * #kind = isnan, isinf, isfinite, signbit# + * #func = npy_half_isnan, npy_half_isinf, npy_half_isfinite, npy_half_signbit# + **/ +NPY_NO_EXPORT void +HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + UNARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + *((Bool *)op1) = @func@(in1) != 0; + } +} +/**end repeat**/ + +NPY_NO_EXPORT void +HALF_spacing(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + UNARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + *((npy_half *)op1) = npy_half_spacing(in1); + } +} + +NPY_NO_EXPORT void +HALF_copysign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + BINARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + const npy_half in2 = *(npy_half *)ip2; + *((npy_half *)op1)= npy_half_copysign(in1, in2); + } +} + +NPY_NO_EXPORT void +HALF_nextafter(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + BINARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + const npy_half in2 = *(npy_half *)ip2; + *((npy_half *)op1)= npy_half_nextafter(in1, in2); + } +} + +/**begin repeat + * #kind = maximum, minimum# + * #OP = npy_half_ge, npy_half_le# + **/ +NPY_NO_EXPORT void +HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + /* */ + BINARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + const npy_half in2 = *(npy_half *)ip2; + *((npy_half *)op1) = (@OP@(in1, in2) || npy_half_isnan(in1)) ? in1 : in2; + } +} +/**end repeat**/ + +/**begin repeat + * #kind = fmax, fmin# + * #OP = npy_half_ge, npy_half_le# + **/ +NPY_NO_EXPORT void +HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + /* */ + BINARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + const npy_half in2 = *(npy_half *)ip2; + *((npy_half *)op1) = (@OP@(in1, in2) || npy_half_isnan(in2)) ? in1 : in2; + } +} +/**end repeat**/ + +NPY_NO_EXPORT void +HALF_floor_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + BINARY_LOOP { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + const float in2 = npy_half_to_float(*(npy_half *)ip2); + *((npy_half *)op1) = npy_float_to_half(npy_floorf(in1/in2)); + } +} + +NPY_NO_EXPORT void +HALF_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + BINARY_LOOP { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + const float in2 = npy_half_to_float(*(npy_half *)ip2); + const float res = npy_fmodf(in1,in2); + if (res && ((in2 < 0) != (res < 0))) { + *((npy_half *)op1) = npy_float_to_half(res + in2); + } + else { + *((npy_half *)op1) = npy_float_to_half(res); + } + } +} + +NPY_NO_EXPORT void +HALF_square(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data)) +{ + UNARY_LOOP { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + *((npy_half *)op1) = npy_float_to_half(in1*in1); + } +} + +NPY_NO_EXPORT void +HALF_reciprocal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data)) +{ + UNARY_LOOP { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + *((npy_half *)op1) = npy_float_to_half(1/in1); + } +} + +NPY_NO_EXPORT void +HALF_ones_like(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data)) +{ + OUTPUT_LOOP { + *((npy_half *)op1) = NPY_HALF_ONE; + } +} + +NPY_NO_EXPORT void +HALF_conjugate(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + UNARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + *((npy_half *)op1) = in1; + } +} + +NPY_NO_EXPORT void +HALF_absolute(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + UNARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + *((npy_half *)op1) = in1&0x7fffu; + } +} + +NPY_NO_EXPORT void +HALF_negative(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + UNARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + *((npy_half *)op1) = in1^0x8000u; + } +} + +NPY_NO_EXPORT void +HALF_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + /* Sign of nan is nan */ + UNARY_LOOP { + const npy_half in1 = *(npy_half *)ip1; + *((npy_half *)op1) = npy_half_isnan(in1) ? in1 : + (((in1&0x7fffu) == 0) ? 0 : + (((in1&0x8000u) == 0) ? NPY_HALF_ONE : NPY_HALF_NEGONE)); + } +} + +NPY_NO_EXPORT void +HALF_modf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + float temp; + + UNARY_LOOP_TWO_OUT { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + *((npy_half *)op1) = npy_float_to_half(npy_modff(in1, &temp)); + *((npy_half *)op2) = npy_float_to_half(temp); + } +} + +#ifdef HAVE_FREXPF +NPY_NO_EXPORT void +HALF_frexp(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + UNARY_LOOP_TWO_OUT { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + *((npy_half *)op1) = npy_float_to_half(frexpf(in1, (int *)op2)); + } +} +#endif + +#ifdef HAVE_LDEXPF +NPY_NO_EXPORT void +HALF_ldexp(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + BINARY_LOOP { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + const int in2 = *(int *)ip2; + *((npy_half *)op1) = npy_float_to_half(ldexpf(in1, in2)); + } +} + +NPY_NO_EXPORT void +HALF_ldexp_long(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) +{ + /* + * Additional loop to handle long integer inputs (cf. #866, #1633). + * long != int on many 64-bit platforms, so we need this second loop + * to handle the default integer type. + */ + BINARY_LOOP { + const float in1 = npy_half_to_float(*(npy_half *)ip1); + const long in2 = *(long *)ip2; + if (((int)in2) == in2) { + /* Range OK */ + *((npy_half *)op1) = npy_float_to_half(ldexpf(in1, ((int)in2))); + } + else { + /* + * Outside int range -- also ldexp will overflow in this case, + * given that exponent has less bits than int. + */ + if (in2 > 0) { + *((npy_half *)op1) = npy_float_to_half(ldexpf(in1, NPY_MAX_INT)); + } + else { + *((npy_half *)op1) = npy_float_to_half(ldexpf(in1, NPY_MIN_INT)); + } + } + } +} +#endif + +#define HALF_true_divide HALF_divide + /* ***************************************************************************** diff --git a/numpy/core/src/umath/loops.h b/numpy/core/src/umath/loops.h index 7cb4b22cc..2d8343b47 100644 --- a/numpy/core/src/umath/loops.h +++ b/numpy/core/src/umath/loops.h @@ -12,6 +12,20 @@ * vim:syntax=c */ +/* + ***************************************************************************** + ** IMPORTANT NOTE for loops.h.src -> loops.h ** + ***************************************************************************** + * The template file loops.h.src is not automatically converted into + * loops.h by the build system. If you edit this file, you must manually + * do the conversion using numpy/distutils/conv_template.py from the + * command line as follows: + * + * $ cd <NumPy source root directory> + * $ python numpy/distutils/conv_template.py numpy/core/src/umath/loops.h.src + * $ + */ + #ifndef _NPY_UMATH_LOOPS_H_ #define _NPY_UMATH_LOOPS_H_ @@ -32,116 +46,116 @@ ***************************************************************************** */ -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_fmax(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_negative(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 32 +#line 46 NPY_NO_EXPORT void BOOL_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 41 +#line 55 NPY_NO_EXPORT void BOOL_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 41 +#line 55 NPY_NO_EXPORT void BOOL_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 49 +#line 63 NPY_NO_EXPORT void BOOL_absolute(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 49 +#line 63 NPY_NO_EXPORT void BOOL_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -155,9 +169,9 @@ BOOL_ones_like(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data ***************************************************************************** */ -#line 67 +#line 81 -#line 73 +#line 87 #define BYTE_floor_divide BYTE_divide #define BYTE_fmax BYTE_maximum @@ -184,76 +198,76 @@ BYTE_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fu NPY_NO_EXPORT void BYTE_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void BYTE_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void BYTE_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void BYTE_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void BYTE_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void BYTE_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void BYTE_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void BYTE_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void BYTE_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void BYTE_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void BYTE_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void BYTE_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void BYTE_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void BYTE_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void BYTE_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void BYTE_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void BYTE_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -261,11 +275,11 @@ BYTE_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fun NPY_NO_EXPORT void BYTE_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void BYTE_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void BYTE_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -280,7 +294,7 @@ NPY_NO_EXPORT void BYTE_fmod(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 73 +#line 87 #define UBYTE_floor_divide UBYTE_divide #define UBYTE_fmax UBYTE_maximum @@ -307,76 +321,76 @@ UBYTE_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(f NPY_NO_EXPORT void UBYTE_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UBYTE_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UBYTE_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UBYTE_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UBYTE_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UBYTE_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UBYTE_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UBYTE_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UBYTE_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UBYTE_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UBYTE_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UBYTE_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UBYTE_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UBYTE_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UBYTE_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UBYTE_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UBYTE_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -384,11 +398,11 @@ UBYTE_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fu NPY_NO_EXPORT void UBYTE_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void UBYTE_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void UBYTE_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -428,9 +442,9 @@ BYTE_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func NPY_NO_EXPORT void UBYTE_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 67 +#line 81 -#line 73 +#line 87 #define SHORT_floor_divide SHORT_divide #define SHORT_fmax SHORT_maximum @@ -457,76 +471,76 @@ SHORT_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(f NPY_NO_EXPORT void SHORT_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void SHORT_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void SHORT_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void SHORT_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void SHORT_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void SHORT_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void SHORT_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void SHORT_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void SHORT_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void SHORT_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void SHORT_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void SHORT_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void SHORT_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void SHORT_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void SHORT_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void SHORT_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void SHORT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -534,11 +548,11 @@ SHORT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fu NPY_NO_EXPORT void SHORT_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void SHORT_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void SHORT_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -553,7 +567,7 @@ NPY_NO_EXPORT void SHORT_fmod(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 73 +#line 87 #define USHORT_floor_divide USHORT_divide #define USHORT_fmax USHORT_maximum @@ -580,76 +594,76 @@ USHORT_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED( NPY_NO_EXPORT void USHORT_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void USHORT_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void USHORT_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void USHORT_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void USHORT_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void USHORT_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void USHORT_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void USHORT_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void USHORT_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void USHORT_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void USHORT_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void USHORT_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void USHORT_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void USHORT_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void USHORT_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void USHORT_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void USHORT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -657,11 +671,11 @@ USHORT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(f NPY_NO_EXPORT void USHORT_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void USHORT_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void USHORT_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -701,9 +715,9 @@ SHORT_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fun NPY_NO_EXPORT void USHORT_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 67 +#line 81 -#line 73 +#line 87 #define INT_floor_divide INT_divide #define INT_fmax INT_maximum @@ -730,76 +744,76 @@ INT_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fun NPY_NO_EXPORT void INT_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void INT_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void INT_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void INT_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void INT_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void INT_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void INT_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void INT_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void INT_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void INT_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void INT_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void INT_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void INT_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void INT_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void INT_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void INT_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void INT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -807,11 +821,11 @@ INT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func NPY_NO_EXPORT void INT_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void INT_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void INT_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -826,7 +840,7 @@ NPY_NO_EXPORT void INT_fmod(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 73 +#line 87 #define UINT_floor_divide UINT_divide #define UINT_fmax UINT_maximum @@ -853,76 +867,76 @@ UINT_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fu NPY_NO_EXPORT void UINT_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UINT_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UINT_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UINT_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UINT_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UINT_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UINT_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UINT_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void UINT_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UINT_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UINT_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UINT_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UINT_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UINT_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UINT_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UINT_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void UINT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -930,11 +944,11 @@ UINT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fun NPY_NO_EXPORT void UINT_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void UINT_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void UINT_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -974,9 +988,9 @@ INT_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func) NPY_NO_EXPORT void UINT_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 67 +#line 81 -#line 73 +#line 87 #define LONG_floor_divide LONG_divide #define LONG_fmax LONG_maximum @@ -1003,76 +1017,76 @@ LONG_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fu NPY_NO_EXPORT void LONG_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONG_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONG_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONG_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONG_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONG_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONG_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONG_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONG_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONG_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONG_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONG_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONG_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONG_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONG_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONG_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONG_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1080,11 +1094,11 @@ LONG_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fun NPY_NO_EXPORT void LONG_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void LONG_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void LONG_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1099,7 +1113,7 @@ NPY_NO_EXPORT void LONG_fmod(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 73 +#line 87 #define ULONG_floor_divide ULONG_divide #define ULONG_fmax ULONG_maximum @@ -1126,76 +1140,76 @@ ULONG_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(f NPY_NO_EXPORT void ULONG_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONG_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONG_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONG_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONG_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONG_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONG_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONG_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONG_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONG_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONG_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONG_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONG_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONG_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONG_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONG_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONG_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1203,11 +1217,11 @@ ULONG_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fu NPY_NO_EXPORT void ULONG_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void ULONG_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void ULONG_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1247,9 +1261,9 @@ LONG_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func NPY_NO_EXPORT void ULONG_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 67 +#line 81 -#line 73 +#line 87 #define LONGLONG_floor_divide LONGLONG_divide #define LONGLONG_fmax LONGLONG_maximum @@ -1276,76 +1290,76 @@ LONGLONG_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSE NPY_NO_EXPORT void LONGLONG_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONGLONG_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONGLONG_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONGLONG_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONGLONG_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONGLONG_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONGLONG_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONGLONG_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void LONGLONG_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONGLONG_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONGLONG_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONGLONG_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONGLONG_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONGLONG_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONGLONG_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONGLONG_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void LONGLONG_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1353,11 +1367,11 @@ LONGLONG_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED NPY_NO_EXPORT void LONGLONG_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void LONGLONG_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void LONGLONG_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1372,7 +1386,7 @@ NPY_NO_EXPORT void LONGLONG_fmod(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 73 +#line 87 #define ULONGLONG_floor_divide ULONGLONG_divide #define ULONGLONG_fmax ULONGLONG_maximum @@ -1399,76 +1413,76 @@ ULONGLONG_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUS NPY_NO_EXPORT void ULONGLONG_invert(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONGLONG_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONGLONG_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONGLONG_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONGLONG_bitwise_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONGLONG_bitwise_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONGLONG_bitwise_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONGLONG_left_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 105 +#line 119 NPY_NO_EXPORT void ULONGLONG_right_shift(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONGLONG_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONGLONG_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONGLONG_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONGLONG_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONGLONG_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONGLONG_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONGLONG_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 115 +#line 129 NPY_NO_EXPORT void ULONGLONG_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1476,11 +1490,11 @@ ULONGLONG_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSE NPY_NO_EXPORT void ULONGLONG_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void ULONGLONG_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 126 +#line 140 NPY_NO_EXPORT void ULONGLONG_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1528,55 +1542,209 @@ ULONGLONG_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED */ -#line 180 +#line 194 + + +#line 201 +NPY_NO_EXPORT void +HALF_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 201 +NPY_NO_EXPORT void +HALF_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 201 +NPY_NO_EXPORT void +HALF_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 201 +NPY_NO_EXPORT void +HALF_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + + +#line 210 +NPY_NO_EXPORT void +HALF_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 210 +NPY_NO_EXPORT void +HALF_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 210 +NPY_NO_EXPORT void +HALF_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); +#line 210 +NPY_NO_EXPORT void +HALF_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 210 +NPY_NO_EXPORT void +HALF_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 210 +NPY_NO_EXPORT void +HALF_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 210 +NPY_NO_EXPORT void +HALF_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 210 +NPY_NO_EXPORT void +HALF_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + + +NPY_NO_EXPORT void +HALF_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +NPY_NO_EXPORT void +HALF_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 224 +NPY_NO_EXPORT void +HALF_isnan(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 224 +NPY_NO_EXPORT void +HALF_isinf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 224 +NPY_NO_EXPORT void +HALF_isfinite(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 224 +NPY_NO_EXPORT void +HALF_signbit(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 224 +NPY_NO_EXPORT void +HALF_copysign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 224 +NPY_NO_EXPORT void +HALF_nextafter(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 224 +NPY_NO_EXPORT void +HALF_spacing(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + + +#line 232 +NPY_NO_EXPORT void +HALF_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 232 +NPY_NO_EXPORT void +HALF_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + + +#line 240 +NPY_NO_EXPORT void +HALF_fmax(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#line 240 +NPY_NO_EXPORT void +HALF_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + + +NPY_NO_EXPORT void +HALF_floor_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +NPY_NO_EXPORT void +HALF_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +NPY_NO_EXPORT void +HALF_square(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data)); + +NPY_NO_EXPORT void +HALF_reciprocal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data)); + + +NPY_NO_EXPORT void +HALF_ones_like(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data)); + +NPY_NO_EXPORT void +HALF_conjugate(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +NPY_NO_EXPORT void +HALF_absolute(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +NPY_NO_EXPORT void +HALF_negative(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + + +NPY_NO_EXPORT void +HALF_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + + +NPY_NO_EXPORT void +HALF_modf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); + +#ifdef HAVE_FREXPF +NPY_NO_EXPORT void +HALF_frexp(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); +#endif + +#ifdef HAVE_LDEXPF +NPY_NO_EXPORT void +HALF_ldexp(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); +NPY_NO_EXPORT void +HALF_ldexp_long(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); +#endif + +#define HALF_true_divide HALF_divide + + +#line 194 + + +#line 201 NPY_NO_EXPORT void FLOAT_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 201 NPY_NO_EXPORT void FLOAT_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 201 NPY_NO_EXPORT void FLOAT_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 201 NPY_NO_EXPORT void FLOAT_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void FLOAT_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void FLOAT_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void FLOAT_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void FLOAT_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void FLOAT_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void FLOAT_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void FLOAT_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void FLOAT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1587,49 +1755,49 @@ FLOAT_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(f NPY_NO_EXPORT void FLOAT_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void FLOAT_isnan(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void FLOAT_isinf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void FLOAT_isfinite(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void FLOAT_signbit(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void FLOAT_copysign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void FLOAT_nextafter(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void FLOAT_spacing(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 218 +#line 232 NPY_NO_EXPORT void FLOAT_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 218 +#line 232 NPY_NO_EXPORT void FLOAT_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 226 +#line 240 NPY_NO_EXPORT void FLOAT_fmax(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 226 +#line 240 NPY_NO_EXPORT void FLOAT_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1682,55 +1850,55 @@ FLOAT_ldexp_long(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fu #define FLOAT_true_divide FLOAT_divide -#line 180 +#line 194 -#line 187 +#line 201 NPY_NO_EXPORT void DOUBLE_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 201 NPY_NO_EXPORT void DOUBLE_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 201 NPY_NO_EXPORT void DOUBLE_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 201 NPY_NO_EXPORT void DOUBLE_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void DOUBLE_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void DOUBLE_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void DOUBLE_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void DOUBLE_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void DOUBLE_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void DOUBLE_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void DOUBLE_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void DOUBLE_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1741,49 +1909,49 @@ DOUBLE_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED( NPY_NO_EXPORT void DOUBLE_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void DOUBLE_isnan(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void DOUBLE_isinf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void DOUBLE_isfinite(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void DOUBLE_signbit(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void DOUBLE_copysign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void DOUBLE_nextafter(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void DOUBLE_spacing(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 218 +#line 232 NPY_NO_EXPORT void DOUBLE_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 218 +#line 232 NPY_NO_EXPORT void DOUBLE_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 226 +#line 240 NPY_NO_EXPORT void DOUBLE_fmax(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 226 +#line 240 NPY_NO_EXPORT void DOUBLE_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1836,55 +2004,55 @@ DOUBLE_ldexp_long(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(f #define DOUBLE_true_divide DOUBLE_divide -#line 180 +#line 194 -#line 187 +#line 201 NPY_NO_EXPORT void LONGDOUBLE_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 201 NPY_NO_EXPORT void LONGDOUBLE_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 201 NPY_NO_EXPORT void LONGDOUBLE_multiply(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 187 +#line 201 NPY_NO_EXPORT void LONGDOUBLE_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void LONGDOUBLE_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void LONGDOUBLE_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void LONGDOUBLE_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void LONGDOUBLE_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void LONGDOUBLE_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void LONGDOUBLE_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void LONGDOUBLE_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 196 +#line 210 NPY_NO_EXPORT void LONGDOUBLE_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -1895,49 +2063,49 @@ LONGDOUBLE_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNU NPY_NO_EXPORT void LONGDOUBLE_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void LONGDOUBLE_isnan(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void LONGDOUBLE_isinf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void LONGDOUBLE_isfinite(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void LONGDOUBLE_signbit(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void LONGDOUBLE_copysign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void LONGDOUBLE_nextafter(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 210 +#line 224 NPY_NO_EXPORT void LONGDOUBLE_spacing(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 218 +#line 232 NPY_NO_EXPORT void LONGDOUBLE_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 218 +#line 232 NPY_NO_EXPORT void LONGDOUBLE_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 226 +#line 240 NPY_NO_EXPORT void LONGDOUBLE_fmax(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 226 +#line 240 NPY_NO_EXPORT void LONGDOUBLE_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2005,14 +2173,14 @@ LONGDOUBLE_ldexp_long(char **args, intp *dimensions, intp *steps, void *NPY_UNUS #define CEQ(xr,xi,yr,yi) (xr == yr && xi == yi); #define CNE(xr,xi,yr,yi) (xr != yr || xi != yi); -#line 298 +#line 314 -#line 304 +#line 320 NPY_NO_EXPORT void CFLOAT_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 304 +#line 320 NPY_NO_EXPORT void CFLOAT_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2027,36 +2195,36 @@ CFLOAT_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func) NPY_NO_EXPORT void CFLOAT_floor_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CFLOAT_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CFLOAT_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CFLOAT_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CFLOAT_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CFLOAT_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CFLOAT_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 331 +#line 347 NPY_NO_EXPORT void CFLOAT_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 331 +#line 347 NPY_NO_EXPORT void CFLOAT_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2066,15 +2234,15 @@ CFLOAT_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED( NPY_NO_EXPORT void CFLOAT_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 345 +#line 361 NPY_NO_EXPORT void CFLOAT_isnan(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 345 +#line 361 NPY_NO_EXPORT void CFLOAT_isinf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 345 +#line 361 NPY_NO_EXPORT void CFLOAT_isfinite(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2100,20 +2268,20 @@ CFLOAT__arg(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void CFLOAT_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 374 +#line 390 NPY_NO_EXPORT void CFLOAT_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 374 +#line 390 NPY_NO_EXPORT void CFLOAT_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 382 +#line 398 NPY_NO_EXPORT void CFLOAT_fmax(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 382 +#line 398 NPY_NO_EXPORT void CFLOAT_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2121,14 +2289,14 @@ CFLOAT_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); #define CFLOAT_true_divide CFLOAT_divide -#line 298 +#line 314 -#line 304 +#line 320 NPY_NO_EXPORT void CDOUBLE_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 304 +#line 320 NPY_NO_EXPORT void CDOUBLE_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2143,36 +2311,36 @@ CDOUBLE_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func NPY_NO_EXPORT void CDOUBLE_floor_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CDOUBLE_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CDOUBLE_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CDOUBLE_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CDOUBLE_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CDOUBLE_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CDOUBLE_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 331 +#line 347 NPY_NO_EXPORT void CDOUBLE_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 331 +#line 347 NPY_NO_EXPORT void CDOUBLE_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2182,15 +2350,15 @@ CDOUBLE_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED NPY_NO_EXPORT void CDOUBLE_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 345 +#line 361 NPY_NO_EXPORT void CDOUBLE_isnan(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 345 +#line 361 NPY_NO_EXPORT void CDOUBLE_isinf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 345 +#line 361 NPY_NO_EXPORT void CDOUBLE_isfinite(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2216,20 +2384,20 @@ CDOUBLE__arg(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) NPY_NO_EXPORT void CDOUBLE_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 374 +#line 390 NPY_NO_EXPORT void CDOUBLE_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 374 +#line 390 NPY_NO_EXPORT void CDOUBLE_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 382 +#line 398 NPY_NO_EXPORT void CDOUBLE_fmax(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 382 +#line 398 NPY_NO_EXPORT void CDOUBLE_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2237,14 +2405,14 @@ CDOUBLE_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) #define CDOUBLE_true_divide CDOUBLE_divide -#line 298 +#line 314 -#line 304 +#line 320 NPY_NO_EXPORT void CLONGDOUBLE_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 304 +#line 320 NPY_NO_EXPORT void CLONGDOUBLE_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2259,36 +2427,36 @@ CLONGDOUBLE_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED( NPY_NO_EXPORT void CLONGDOUBLE_floor_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CLONGDOUBLE_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CLONGDOUBLE_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CLONGDOUBLE_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CLONGDOUBLE_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CLONGDOUBLE_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 322 +#line 338 NPY_NO_EXPORT void CLONGDOUBLE_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 331 +#line 347 NPY_NO_EXPORT void CLONGDOUBLE_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 331 +#line 347 NPY_NO_EXPORT void CLONGDOUBLE_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2298,15 +2466,15 @@ CLONGDOUBLE_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UN NPY_NO_EXPORT void CLONGDOUBLE_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 345 +#line 361 NPY_NO_EXPORT void CLONGDOUBLE_isnan(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 345 +#line 361 NPY_NO_EXPORT void CLONGDOUBLE_isinf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 345 +#line 361 NPY_NO_EXPORT void CLONGDOUBLE_isfinite(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2332,20 +2500,20 @@ CLONGDOUBLE__arg(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fu NPY_NO_EXPORT void CLONGDOUBLE_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 374 +#line 390 NPY_NO_EXPORT void CLONGDOUBLE_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 374 +#line 390 NPY_NO_EXPORT void CLONGDOUBLE_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 382 +#line 398 NPY_NO_EXPORT void CLONGDOUBLE_fmax(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 382 +#line 398 NPY_NO_EXPORT void CLONGDOUBLE_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2367,121 +2535,121 @@ CLONGDOUBLE_fmin(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(fu ***************************************************************************** */ -#line 406 +#line 422 #define DATETIME_fmax DATETIME_maximum #define DATETIME_fmin DATETIME_minimum -#line 406 +#line 422 #define TIMEDELTA_fmax TIMEDELTA_maximum #define TIMEDELTA_fmin TIMEDELTA_minimum -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_absolute(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_absolute(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_logical_and(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_logical_or(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_maximum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_minimum(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_negative(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_negative(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_ones_like(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_ones_like(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 415 +#line 431 NPY_NO_EXPORT void DATETIME_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); @@ -2513,27 +2681,27 @@ TIMEDELTA_mm_m_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UN ***************************************************************************** */ -#line 450 +#line 466 NPY_NO_EXPORT void OBJECT_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 450 +#line 466 NPY_NO_EXPORT void OBJECT_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 450 +#line 466 NPY_NO_EXPORT void OBJECT_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 450 +#line 466 NPY_NO_EXPORT void OBJECT_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 450 +#line 466 NPY_NO_EXPORT void OBJECT_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); -#line 450 +#line 466 NPY_NO_EXPORT void OBJECT_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)); diff --git a/numpy/core/src/umath/loops.h.src b/numpy/core/src/umath/loops.h.src index 33dfe882e..d4ec0a78d 100644 --- a/numpy/core/src/umath/loops.h.src +++ b/numpy/core/src/umath/loops.h.src @@ -3,6 +3,20 @@ * vim:syntax=c */ +/* + ***************************************************************************** + ** IMPORTANT NOTE for loops.h.src -> loops.h ** + ***************************************************************************** + * The template file loops.h.src is not automatically converted into + * loops.h by the build system. If you edit this file, you must manually + * do the conversion using numpy/distutils/conv_template.py from the + * command line as follows: + * + * $ cd <NumPy source root directory> + * $ python numpy/distutils/conv_template.py numpy/core/src/umath/loops.h.src + * $ + */ + #ifndef _NPY_UMATH_LOOPS_H_ #define _NPY_UMATH_LOOPS_H_ @@ -172,10 +186,10 @@ U@TYPE@_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(f /**begin repeat * Float types - * #type = float, double, longdouble# - * #TYPE = FLOAT, DOUBLE, LONGDOUBLE# - * #c = f, , l# - * #C = F, , L# + * #type = npy_half, float, double, longdouble# + * #TYPE = HALF, FLOAT, DOUBLE, LONGDOUBLE# + * #c = f, f, , l# + * #C = F, F, , L# */ diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index be38a9f10..39b04db73 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -224,10 +224,11 @@ _lowest_type(char intype) case PyArray_ULONG: case PyArray_ULONGLONG: return PyArray_UBYTE; - /* case PyArray_FLOAT:*/ + /* case PyArray_HALF: */ + case PyArray_FLOAT: case PyArray_DOUBLE: case PyArray_LONGDOUBLE: - return PyArray_FLOAT; + return PyArray_HALF; /* case PyArray_CFLOAT:*/ case PyArray_CDOUBLE: case PyArray_CLONGDOUBLE: @@ -3328,7 +3329,7 @@ PyUFunc_GenericReduction(PyUFuncObject *self, PyObject *args, * is used for add and multiply reduction to avoid overflow */ int typenum = PyArray_TYPE(mp); - if ((typenum < NPY_FLOAT) + if ((typenum < NPY_HALF) && ((strcmp(self->name,"add") == 0) || (strcmp(self->name,"multiply") == 0))) { if (PyTypeNum_ISBOOL(typenum)) { diff --git a/numpy/core/src/umath/umathmodule.c.src b/numpy/core/src/umath/umathmodule.c.src index c3da9f3d3..7a76c2b3e 100644 --- a/numpy/core/src/umath/umathmodule.c.src +++ b/numpy/core/src/umath/umathmodule.c.src @@ -155,6 +155,7 @@ ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUS static PyUFuncGenericFunction frexp_functions[] = { #ifdef HAVE_FREXPF + HALF_frexp, FLOAT_frexp, #endif DOUBLE_frexp @@ -168,6 +169,7 @@ static void * blank6_data[] = { (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL}; static char frexp_signatures[] = { #ifdef HAVE_FREXPF + PyArray_HALF, PyArray_HALF, PyArray_INT, PyArray_FLOAT, PyArray_FLOAT, PyArray_INT, #endif PyArray_DOUBLE, PyArray_DOUBLE, PyArray_INT @@ -184,7 +186,9 @@ static char frexp_signatures[] = { static PyUFuncGenericFunction ldexp_functions[] = { #ifdef HAVE_LDEXPF + HALF_ldexp, FLOAT_ldexp, + LDEXP_LONG(HALF), LDEXP_LONG(FLOAT), #endif DOUBLE_ldexp, @@ -198,7 +202,9 @@ static PyUFuncGenericFunction ldexp_functions[] = { static char ldexp_signatures[] = { #ifdef HAVE_LDEXPF + PyArray_HALF, PyArray_INT, PyArray_HALF, PyArray_FLOAT, PyArray_INT, PyArray_FLOAT, + PyArray_HALF, PyArray_LONG, PyArray_HALF, PyArray_FLOAT, PyArray_LONG, PyArray_FLOAT, #endif PyArray_DOUBLE, PyArray_INT, PyArray_DOUBLE, @@ -212,14 +218,9 @@ static char ldexp_signatures[] = { static void InitOtherOperators(PyObject *dictionary) { PyObject *f; - int num=1; + int num; -#ifdef HAVE_FREXPL - num += 1; -#endif -#ifdef HAVE_FREXPF - num += 1; -#endif + num = sizeof(frexp_functions) / sizeof(frexp_functions[0]); f = PyUFunc_FromFuncAndData(frexp_functions, blank3_data, frexp_signatures, num, 1, 2, PyUFunc_None, "frexp", @@ -228,13 +229,7 @@ InitOtherOperators(PyObject *dictionary) { PyDict_SetItemString(dictionary, "frexp", f); Py_DECREF(f); - num = 2; -#ifdef HAVE_LDEXPL - num += 2; -#endif -#ifdef HAVE_LDEXPF - num += 2; -#endif + num = sizeof(ldexp_functions) / sizeof(ldexp_functions[0]); f = PyUFunc_FromFuncAndData(ldexp_functions, blank6_data, ldexp_signatures, num, 2, 1, PyUFunc_None, "ldexp", "Compute y = x1 * 2**x2.",0); diff --git a/numpy/core/tests/test_getlimits.py b/numpy/core/tests/test_getlimits.py index f52463cbb..569dc0cc6 100644 --- a/numpy/core/tests/test_getlimits.py +++ b/numpy/core/tests/test_getlimits.py @@ -4,7 +4,7 @@ from numpy.testing import * from numpy.core import finfo, iinfo -from numpy import single,double,longdouble +from numpy import half, single, double, longdouble import numpy as np ################################################## @@ -15,6 +15,12 @@ class TestPythonFloat(TestCase): ftype2 = finfo(float) assert_equal(id(ftype),id(ftype2)) +class TestHalf(TestCase): + def test_singleton(self): + ftype = finfo(half) + ftype2 = finfo(half) + assert_equal(id(ftype),id(ftype2)) + class TestSingle(TestCase): def test_singleton(self): ftype = finfo(single) diff --git a/numpy/core/tests/test_half.py b/numpy/core/tests/test_half.py new file mode 100644 index 000000000..409e50e92 --- /dev/null +++ b/numpy/core/tests/test_half.py @@ -0,0 +1,421 @@ +import numpy as np +from numpy import uint16, float16, float32, float64 +from numpy.testing import * + +import warnings + +def assert_raises_fpe(strmatch, callable, *args, **kwargs): + try: + callable(*args, **kwargs) + except FloatingPointError, exc: + assert_(str(exc).find(strmatch) >= 0, + "Did not raise floating point %s error" % strmatch) + else: + assert_(False, + "Did not raise floating point %s error" % strmatch) + +class TestHalf(TestCase): + def setUp(self): + # An array of all possible float16 values + self.all_f16 = np.arange(0x10000, dtype=uint16) + self.all_f16.dtype = float16 + self.all_f32 = np.array(self.all_f16, dtype=float32) + self.all_f64 = np.array(self.all_f16, dtype=float64) + + # An array of all non-NaN float16 values, in sorted order + self.nonan_f16 = np.concatenate( + (np.arange(0xfc00,0x7fff,-1, dtype=uint16), + np.arange(0x0000,0x7c01,1, dtype=uint16)) + ) + self.nonan_f16.dtype = float16 + self.nonan_f32 = np.array(self.nonan_f16, dtype=float32) + self.nonan_f64 = np.array(self.nonan_f16, dtype=float64) + + # An array of all finite float16 values, in sorted order + self.finite_f16 = self.nonan_f16[1:-1] + self.finite_f32 = self.nonan_f32[1:-1] + self.finite_f64 = self.nonan_f64[1:-1] + + def test_half_conversions(self): + """Checks that all 16-bit values survive conversion + to/from 32-bit and 64-bit float""" + # Because the underlying routines preserve the NaN bits, every + # value is preserved when converting to/from other floats. + + # Convert from float32 back to float16 + b = np.array(self.all_f32, dtype=float16) + assert_equal(self.all_f16.view(dtype=uint16), + b.view(dtype=uint16)) + + # Convert from float64 back to float16 + b = np.array(self.all_f64, dtype=float16) + assert_equal(self.all_f16.view(dtype=uint16), + b.view(dtype=uint16)) + + # Convert float16 to longdouble and back + # This doesn't necessarily preserve the extra NaN bits, + # so exclude NaNs. + a_ld = np.array(self.nonan_f16, dtype=np.longdouble) + b = np.array(a_ld, dtype=float16) + assert_equal(self.nonan_f16.view(dtype=uint16), + b.view(dtype=uint16)) + + # Check the range for which all integers can be represented + i_int = np.arange(-2048,2049) + i_f16 = np.array(i_int, dtype=float16) + j = np.array(i_f16, dtype=np.int) + assert_equal(i_int,j) + + def test_nans_infs(self): + # Check some of the ufuncs + assert_equal(np.isnan(self.all_f16), np.isnan(self.all_f32)) + assert_equal(np.isinf(self.all_f16), np.isinf(self.all_f32)) + assert_equal(np.isfinite(self.all_f16), np.isfinite(self.all_f32)) + assert_equal(np.signbit(self.all_f16), np.signbit(self.all_f32)) + + # Check comparisons of all values with NaN + nan = float16(np.nan) + + assert_(not (self.all_f16 == nan).any()) + assert_(not (nan == self.all_f16).any()) + + assert_((self.all_f16 != nan).all()) + assert_((nan != self.all_f16).all()) + + assert_(not (self.all_f16 < nan).any()) + assert_(not (nan < self.all_f16).any()) + + assert_(not (self.all_f16 <= nan).any()) + assert_(not (nan <= self.all_f16).any()) + + assert_(not (self.all_f16 > nan).any()) + assert_(not (nan > self.all_f16).any()) + + assert_(not (self.all_f16 >= nan).any()) + assert_(not (nan >= self.all_f16).any()) + + + def test_half_values(self): + """Confirms a small number of known half values""" + a = np.array([1.0, -1.0, + 2.0, -2.0, + 0.0999755859375, 0.333251953125, # 1/10, 1/3 + 65504, -65504, # Maximum magnitude + 2.0**(-14), -2.0**(-14), # Minimum normal + 2.0**(-24), -2.0**(-24), # Minimum subnormal + 0, -1/1e1000, # Signed zeros + np.inf, -np.inf]) + b = np.array([0x3c00, 0xbc00, + 0x4000, 0xc000, + 0x2e66, 0x3555, + 0x7bff, 0xfbff, + 0x0400, 0x8400, + 0x0001, 0x8001, + 0x0000, 0x8000, + 0x7c00, 0xfc00], dtype=uint16) + b.dtype = float16 + assert_equal(a, b) + + def test_half_rounding(self): + """Checks that rounding when converting to half is correct""" + a = np.array([2.0**-25 + 2.0**-35, # Rounds to minimum subnormal + 2.0**-25, # Underflows to zero (nearest even mode) + 2.0**-26, # Underflows to zero + 1.0+2.0**-11 + 2.0**-16, # rounds to 1.0+2**(-10) + 1.0+2.0**-11, # rounds to 1.0 (nearest even mode) + 1.0+2.0**-12, # rounds to 1.0 + 65519, # rounds to 65504 + 65520], # rounds to inf + dtype=float64) + rounded = [2.0**-24, + 0.0, + 0.0, + 1.0+2.0**(-10), + 1.0, + 1.0, + 65504, + np.inf] + + # Check float64->float16 rounding + b = np.array(a, dtype=float16) + assert_equal(b, rounded) + + # Check float32->float16 rounding + a = np.array(a, dtype=float32) + b = np.array(a, dtype=float16) + assert_equal(b, rounded) + + def test_half_correctness(self): + """Take every finite float16, and check the casting functions with + a manual conversion.""" + + # Create an array of all finite float16s + a_f16 = self.finite_f16 + a_bits = a_f16.view(dtype=uint16) + + # Convert to 64-bit float manually + a_sgn = (-1.0)**((a_bits&0x8000) >> 15) + a_exp = np.array((a_bits&0x7c00) >> 10, dtype=np.int32) - 15 + a_man = (a_bits&0x03ff) * 2.0**(-10) + # Implicit bit of normalized floats + a_man[a_exp!=-15] += 1 + # Denormalized exponent is -14 + a_exp[a_exp==-15] = -14 + + a_manual = a_sgn * a_man * 2.0**a_exp + + a32_fail = np.nonzero(self.finite_f32 != a_manual)[0] + if len(a32_fail) != 0: + bad_index = a32_fail[0] + assert_equal(self.finite_f32, a_manual, + "First non-equal is half value %x -> %g != %g" % + (a[bad_index], + self.finite_f32[bad_index], + a_manual[bad_index])) + + a64_fail = np.nonzero(self.finite_f64 != a_manual)[0] + if len(a64_fail) != 0: + bad_index = a64_fail[0] + assert_equal(self.finite_f64, a_manual, + "First non-equal is half value %x -> %g != %g" % + (a[bad_index], + self.finite_f64[bad_index], + a_manual[bad_index])) + + def test_half_ordering(self): + """Make sure comparisons are working right""" + + # All non-NaN float16 values in reverse order + a = self.nonan_f16[::-1].copy() + + # 32-bit float copy + b = np.array(a, dtype=float32) + + # Should sort the same + a.sort() + b.sort() + assert_equal(a, b) + + # Comparisons should work + assert_((a[:-1] <= a[1:]).all()) + assert_(not (a[:-1] > a[1:]).any()) + assert_((a[1:] >= a[:-1]).all()) + assert_(not (a[1:] < a[:-1]).any()) + # All != except for +/-0 + assert_equal(np.nonzero(a[:-1] < a[1:])[0].size, a.size-2) + assert_equal(np.nonzero(a[1:] > a[:-1])[0].size, a.size-2) + + def test_half_funcs(self): + """Test the various ArrFuncs""" + + # fill + assert_equal(np.arange(10, dtype=float16), + np.arange(10, dtype=float32)) + + # fillwithscalar + a = np.zeros((5,), dtype=float16) + a.fill(1) + assert_equal(a, np.ones((5,), dtype=float16)) + + # nonzero and copyswap + a = np.array([0,0,-1,-1/1e20,0,2.0**-24, 7.629e-6], dtype=float16) + assert_equal(a.nonzero()[0], + [2,5,6]) + a = a.byteswap().newbyteorder() + assert_equal(a.nonzero()[0], + [2,5,6]) + + # dot + a = np.arange(0, 10, 0.5, dtype=float16) + b = np.ones((20,), dtype=float16) + assert_equal(np.dot(a,b), + 95) + + # argmax + a = np.array([0, -np.inf, -2, 0.5, 12.55, 7.3, 2.1, 12.4], dtype=float16) + assert_equal(a.argmax(), + 4) + a = np.array([0, -np.inf, -2, np.inf, 12.55, np.nan, 2.1, 12.4], dtype=float16) + assert_equal(a.argmax(), + 5) + + # getitem + a = np.arange(10, dtype=float16) + for i in range(10): + assert_equal(a.item(i),i) + + def test_spacing_nextafter(self): + """Test np.spacing and np.nextafter""" + # All non-negative finite #'s + a = np.arange(0x7c00, dtype=uint16) + hinf = np.array((np.inf,), dtype=float16) + a_f16 = a.view(dtype=float16) + + assert_equal(np.spacing(a_f16[:-1]), a_f16[1:]-a_f16[:-1]) + + assert_equal(np.nextafter(a_f16[:-1], hinf), a_f16[1:]) + assert_equal(np.nextafter(a_f16[0], -hinf), -a_f16[1]) + assert_equal(np.nextafter(a_f16[1:], -hinf), a_f16[:-1]) + + # switch to negatives + a |= 0x8000 + + assert_equal(np.spacing(a_f16[0]), np.spacing(a_f16[1])) + assert_equal(np.spacing(a_f16[1:]), a_f16[:-1]-a_f16[1:]) + + assert_equal(np.nextafter(a_f16[0], hinf), -a_f16[1]) + assert_equal(np.nextafter(a_f16[1:], hinf), a_f16[:-1]) + assert_equal(np.nextafter(a_f16[:-1], -hinf), a_f16[1:]) + + + def test_half_ufuncs(self): + """Test the various ufuncs""" + + a = np.array([0,1,2,4,2], dtype=float16) + b = np.array([-2,5,1,4,3], dtype=float16) + c = np.array([0,-1,-np.inf,np.nan,6], dtype=float16) + + assert_equal(np.add(a,b), [-2,6,3,8,5]) + assert_equal(np.subtract(a,b), [2,-4,1,0,-1]) + assert_equal(np.multiply(a,b), [0,5,2,16,6]) + assert_equal(np.divide(a,b), [0,0.199951171875,2,1,0.66650390625]) + + assert_equal(np.equal(a,b), [False,False,False,True,False]) + assert_equal(np.not_equal(a,b), [True,True,True,False,True]) + assert_equal(np.less(a,b), [False,True,False,False,True]) + assert_equal(np.less_equal(a,b), [False,True,False,True,True]) + assert_equal(np.greater(a,b), [True,False,True,False,False]) + assert_equal(np.greater_equal(a,b), [True,False,True,True,False]) + assert_equal(np.logical_and(a,b), [False,True,True,True,True]) + assert_equal(np.logical_or(a,b), [True,True,True,True,True]) + assert_equal(np.logical_xor(a,b), [True,False,False,False,False]) + assert_equal(np.logical_not(a), [True,False,False,False,False]) + + assert_equal(np.isnan(c), [False,False,False,True,False]) + assert_equal(np.isinf(c), [False,False,True,False,False]) + assert_equal(np.isfinite(c), [True,True,False,False,True]) + assert_equal(np.signbit(b), [True,False,False,False,False]) + + assert_equal(np.copysign(b,a), [2,5,1,4,3]) + + assert_equal(np.maximum(a,b), [0,5,2,4,3]) + x = np.maximum(b,c) + assert_(np.isnan(x[3])) + x[3] = 0 + assert_equal(x, [0,5,1,0,6]) + assert_equal(np.minimum(a,b), [-2,1,1,4,2]) + x = np.minimum(b,c) + assert_(np.isnan(x[3])) + x[3] = 0 + assert_equal(x, [-2,-1,-np.inf,0,3]) + assert_equal(np.fmax(a,b), [0,5,2,4,3]) + assert_equal(np.fmax(b,c), [0,5,1,4,6]) + assert_equal(np.fmin(a,b), [-2,1,1,4,2]) + assert_equal(np.fmin(b,c), [-2,-1,-np.inf,4,3]) + + assert_equal(np.floor_divide(a,b), [0,0,2,1,0]) + assert_equal(np.remainder(a,b), [0,1,0,0,2]) + assert_equal(np.square(b), [4,25,1,16,9]) + assert_equal(np.reciprocal(b), [-0.5,0.199951171875,1,0.25,0.333251953125]) + assert_equal(np.ones_like(b), [1,1,1,1,1]) + assert_equal(np.conjugate(b), b) + assert_equal(np.absolute(b), [2,5,1,4,3]) + assert_equal(np.negative(b), [2,-5,-1,-4,-3]) + assert_equal(np.sign(b), [-1,1,1,1,1]) + assert_equal(np.modf(b), ([0,0,0,0,0],b)) + assert_equal(np.frexp(b), ([-0.5,0.625,0.5,0.5,0.75],[2,3,1,3,2])) + assert_equal(np.ldexp(b,[0,1,2,4,2]), [-2,10,4,64,12]) + + def test_half_coercion(self): + """Test that half gets coerced properly with the other types""" + a16 = np.array((1,),dtype=float16) + a32 = np.array((1,),dtype=float32) + b16 = float16(1) + b32 = float32(1) + + assert_equal(np.power(a16,2).dtype, float16) + assert_equal(np.power(a16,2.0).dtype, float16) + assert_equal(np.power(a16,b16).dtype, float16) + assert_equal(np.power(a16,b32).dtype, float16) + assert_equal(np.power(a16,a16).dtype, float16) + assert_equal(np.power(a16,a32).dtype, float32) + + assert_equal(np.power(b16,2).dtype, float64) + assert_equal(np.power(b16,2.0).dtype, float64) + assert_equal(np.power(b16,b16).dtype, float16) + assert_equal(np.power(b16,b32).dtype, float32) + assert_equal(np.power(b16,a16).dtype, float16) + assert_equal(np.power(b16,a32).dtype, float32) + + assert_equal(np.power(a32,a16).dtype, float32) + assert_equal(np.power(a32,b16).dtype, float32) + assert_equal(np.power(b32,a16).dtype, float16) + assert_equal(np.power(b32,b16).dtype, float32) + + def test_half_fpe(self): + """Test that half raises the correct underflows and overflows""" + oldsettings = np.seterr(all='raise') + try: + sx16 = np.array((1e-4,),dtype=float16) + bx16 = np.array((1e4,),dtype=float16) + sy16 = float16(1e-4) + by16 = float16(1e4) + + # Underflow errors + assert_raises_fpe('underflow', lambda a,b:a*b, sx16, sx16) + assert_raises_fpe('underflow', lambda a,b:a*b, sx16, sy16) + assert_raises_fpe('underflow', lambda a,b:a*b, sy16, sx16) + assert_raises_fpe('underflow', lambda a,b:a*b, sy16, sy16) + assert_raises_fpe('underflow', lambda a,b:a/b, sx16, bx16) + assert_raises_fpe('underflow', lambda a,b:a/b, sx16, by16) + assert_raises_fpe('underflow', lambda a,b:a/b, sy16, bx16) + assert_raises_fpe('underflow', lambda a,b:a/b, sy16, by16) + assert_raises_fpe('underflow', lambda a,b:a/b, + float16(2.**-14), float16(2**11)) + assert_raises_fpe('underflow', lambda a,b:a/b, + float16(-2.**-14), float16(2**11)) + assert_raises_fpe('underflow', lambda a,b:a/b, + float16(2.**-14+2**-24), float16(2)) + assert_raises_fpe('underflow', lambda a,b:a/b, + float16(-2.**-14-2**-24), float16(2)) + assert_raises_fpe('underflow', lambda a,b:a/b, + float16(2.**-14+2**-23), float16(4)) + + # Overflow errors + assert_raises_fpe('overflow', lambda a,b:a*b, bx16, bx16) + assert_raises_fpe('overflow', lambda a,b:a*b, bx16, by16) + assert_raises_fpe('overflow', lambda a,b:a*b, by16, bx16) + assert_raises_fpe('overflow', lambda a,b:a*b, by16, by16) + assert_raises_fpe('overflow', lambda a,b:a/b, bx16, sx16) + assert_raises_fpe('overflow', lambda a,b:a/b, bx16, sy16) + assert_raises_fpe('overflow', lambda a,b:a/b, by16, sx16) + assert_raises_fpe('overflow', lambda a,b:a/b, by16, sy16) + assert_raises_fpe('overflow', lambda a,b:a+b, + float16(65504), float16(17)) + assert_raises_fpe('overflow', lambda a,b:a-b, + float16(-65504), float16(17)) + assert_raises_fpe('overflow', np.nextafter, float16(65504), float16(np.inf)) + assert_raises_fpe('overflow', np.nextafter, float16(-65504), float16(-np.inf)) + + # Invalid value errors + assert_raises_fpe('invalid', np.divide, float16(np.inf), float16(np.inf)) + assert_raises_fpe('invalid', np.spacing, float16(65504)) + assert_raises_fpe('invalid', np.spacing, float16(np.inf)) + assert_raises_fpe('invalid', np.spacing, float16(np.nan)) + assert_raises_fpe('invalid', np.nextafter, float16(np.inf), float16(0)) + assert_raises_fpe('invalid', np.nextafter, float16(-np.inf), float16(0)) + assert_raises_fpe('invalid', np.nextafter, float16(0), float16(np.nan)) + + # These should not raise + float16(65472)+float16(32) + float16(2**-13)/float16(2) + float16(2**-14)/float16(2**10) + np.spacing(float16(-65504)) + np.nextafter(float16(65504), float16(-np.inf)) + np.nextafter(float16(-65504), float16(np.inf)) + float16(2**-14)/float16(2**10) + float16(-2**-14)/float16(2**10) + float16(2**-14+2**-23)/float16(2) + float16(-2**-14-2**-23)/float16(2) + finally: + np.seterr(**oldsettings) diff --git a/numpy/doc/basics.py b/numpy/doc/basics.py index ea651bbc7..97e982204 100644 --- a/numpy/doc/basics.py +++ b/numpy/doc/basics.py @@ -23,6 +23,8 @@ uint16 Unsigned integer (0 to 65535) uint32 Unsigned integer (0 to 4294967295) uint64 Unsigned integer (0 to 18446744073709551615) float Shorthand for ``float64``. +float16 Half precision float: sign bit, 5 bits exponent, + 10 bits mantissa float32 Single precision float: sign bit, 8 bits exponent, 23 bits mantissa float64 Double precision float: sign bit, 11 bits exponent, diff --git a/numpy/doc/structured_arrays.py b/numpy/doc/structured_arrays.py index 21fdf87ea..6eafd71cd 100644 --- a/numpy/doc/structured_arrays.py +++ b/numpy/doc/structured_arrays.py @@ -70,10 +70,10 @@ In this case, the constructor expects a comma-separated list of type specifiers, optionally with extra shape information. The type specifiers can take 4 different forms: :: - a) b1, i1, i2, i4, i8, u1, u2, u4, u8, f4, f8, c8, c16, a<n> + a) b1, i1, i2, i4, i8, u1, u2, u4, u8, f2, f4, f8, c8, c16, a<n> (representing bytes, ints, unsigned ints, floats, complex and fixed length strings of specified byte lengths) - b) int8,...,uint8,...,float32, float64, complex64, complex128 + b) int8,...,uint8,...,float16, float32, float64, complex64, complex128 (this time with bit sizes) c) older Numeric/numarray type specifications (e.g. Float32). Don't use these in new code! |