summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/SConscript3
-rw-r--r--numpy/core/code_generators/generate_umath.py107
-rw-r--r--numpy/core/code_generators/numpy_api.py7
-rw-r--r--numpy/core/getlimits.py4
-rw-r--r--numpy/core/include/numpy/arrayscalars.h6
-rw-r--r--numpy/core/include/numpy/halffloat.h68
-rw-r--r--numpy/core/include/numpy/ndarraytypes.h8
-rw-r--r--numpy/core/include/numpy/noprefix.h2
-rw-r--r--numpy/core/include/numpy/npy_common.h53
-rw-r--r--numpy/core/include/numpy/old_defines.h2
-rw-r--r--numpy/core/include/numpy/ufuncobject.h30
-rw-r--r--numpy/core/numerictypes.py7
-rw-r--r--numpy/core/setup.py6
-rw-r--r--numpy/core/src/_sortmodule.c.src26
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src395
-rw-r--r--numpy/core/src/multiarray/conversion_utils.c3
-rw-r--r--numpy/core/src/multiarray/convert_datatype.c1
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c1
-rw-r--r--numpy/core/src/multiarray/scalarapi.c2
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src115
-rw-r--r--numpy/core/src/npymath/halffloat.c525
-rw-r--r--numpy/core/src/scalarmathmodule.c.src248
-rw-r--r--numpy/core/src/umath/loops.c.src390
-rw-r--r--numpy/core/src/umath/loops.h904
-rw-r--r--numpy/core/src/umath/loops.h.src22
-rw-r--r--numpy/core/src/umath/ufunc_object.c7
-rw-r--r--numpy/core/src/umath/umathmodule.c.src23
-rw-r--r--numpy/core/tests/test_getlimits.py8
-rw-r--r--numpy/core/tests/test_half.py421
-rw-r--r--numpy/doc/basics.py2
-rw-r--r--numpy/doc/structured_arrays.py4
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!