summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2010-12-01 20:12:18 -0700
committerCharles Harris <charlesr.harris@gmail.com>2010-12-01 20:12:18 -0700
commit2ee163942a7461b14f53523dadbda7b4e5e18efd (patch)
tree39b447663a83c021c34b8cdf32a3644e1bfe9ebc
parentaf84876fac13ac2e4e44ac0cae599fe9d6e68643 (diff)
parentc6f8dbbd240ada8d0edd0527cd218cfc46deec41 (diff)
downloadnumpy-2ee163942a7461b14f53523dadbda7b4e5e18efd.tar.gz
Merge branch 'm-paradox-implement_half_dtype'
-rw-r--r--doc/source/reference/arrays.dtypes.rst2
-rw-r--r--doc/source/reference/arrays.scalars.rst4
-rw-r--r--doc/source/reference/c-api.coremath.rst201
-rw-r--r--doc/source/reference/c-api.dtype.rst14
-rw-r--r--doc/source/reference/c-api.ufunc.rst34
-rw-r--r--doc/source/reference/figures/dtype-hierarchy.diabin4332 -> 4728 bytes
-rw-r--r--doc/source/reference/figures/dtype-hierarchy.pngbin131045 -> 18746 bytes
-rw-r--r--doc/source/reference/ufuncs.rst56
-rw-r--r--doc/source/user/c-info.beyond-basics.rst2
-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
40 files changed, 2956 insertions, 757 deletions
diff --git a/doc/source/reference/arrays.dtypes.rst b/doc/source/reference/arrays.dtypes.rst
index c1b09f609..c89a282f4 100644
--- a/doc/source/reference/arrays.dtypes.rst
+++ b/doc/source/reference/arrays.dtypes.rst
@@ -137,7 +137,7 @@ What can be converted to a data-type object is described below:
Array-scalar types
- The 21 built-in :ref:`array scalar type objects
+ The 24 built-in :ref:`array scalar type objects
<arrays.scalars.built-in>` all convert to an associated data-type object.
This is true for their sub-classes as well.
diff --git a/doc/source/reference/arrays.scalars.rst b/doc/source/reference/arrays.scalars.rst
index 62e22146a..0d5d3f59e 100644
--- a/doc/source/reference/arrays.scalars.rst
+++ b/doc/source/reference/arrays.scalars.rst
@@ -12,7 +12,7 @@ convenient in applications that don't need to be concerned with all
the ways data can be represented in a computer. For scientific
computing, however, more control is often needed.
-In NumPy, there are 21 new fundamental Python types to describe
+In NumPy, there are 24 new fundamental Python types to describe
different types of scalars. These type descriptors are mostly based on
the types available in the C language that CPython is written in, with
several additional types compatible with Python's types.
@@ -138,10 +138,12 @@ Unsigned integers:
Floating-point numbers:
=================== ============================= ===============
+:class:`half` ``'e'``
:class:`single` compatible: C float ``'f'``
:class:`double` compatible: C double
:class:`float_` compatible: Python float ``'d'``
:class:`longfloat` compatible: C long float ``'g'``
+:class:`float16` 16 bits
:class:`float32` 32 bits
:class:`float64` 64 bits
:class:`float96` 96 bits, platform?
diff --git a/doc/source/reference/c-api.coremath.rst b/doc/source/reference/c-api.coremath.rst
index 5c50f36e4..6584f216d 100644
--- a/doc/source/reference/c-api.coremath.rst
+++ b/doc/source/reference/c-api.coremath.rst
@@ -18,7 +18,7 @@ library contains most math-related C99 functionality, which can be used on
platforms where C99 is not well supported. The core math functions have the
same API as the C99 ones, except for the npy_* prefix.
-The available functions are defined in npy_math.h - please refer to this header
+The available functions are defined in <numpy/npy_math.h> - please refer to this header when
in doubt.
Floating point classification
@@ -55,7 +55,7 @@ Floating point classification
This is a macro, and is equivalent to C99 isfinite: works for single,
double and extended precision, and return a non 0 value is x is neither a
- NaN or a infinity.
+ NaN nor an infinity.
.. cfunction:: int npy_isinf(x)
@@ -181,3 +181,200 @@ compile and link options to your extension in your setup.py:
In other words, the usage of info is exactly the same as when using blas_info
and co.
+
+Half-precision functions
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 2.0.0
+
+The header file <numpy/halffloat.h> provides functions to work with
+IEEE 754-2008 16-bit floating point values. While this format is
+not typically used for numerical computations, it is useful for
+storing values which require floating point but do not need much precision.
+It can also be used as an educational tool to understand the nature
+of floating point round-off error.
+
+Like for other types, NumPy includes a typedef npy_half for the 16 bit
+float. Unlike for most of the other types, you cannot use this as a
+normal type in C, since is is a typedef for npy_uint16. For example,
+1.0 looks like 0x3c00 to C, and if you do an equality comparison
+between the different signed zeros, you will get -0.0 != 0.0
+(0x8000 != 0x0000), which is incorrect.
+
+For these reasons, NumPy provides an API to work with npy_half values
+accessible by including <numpy/halffloat.h> and linking to 'npymath'.
+For functions that are not provided directly, such as the arithmetic
+operations, the preferred method is to convert to float
+or double and back again, as in the following example.
+
+.. code-block:: c
+
+ npy_half sum(int n, npy_half *array) {
+ float ret = 0;
+ while(n--) {
+ ret += npy_half_to_float(*array++);
+ }
+ return npy_float_to_half(ret);
+ }
+
+External Links:
+
+* `754-2008 IEEE Standard for Floating-Point Arithmetic`__
+* `Half-precision Float Wikipedia Article`__.
+* `OpenGL Half Float Pixel Support`__
+* `The OpenEXR image format`__.
+
+__ http://ieeexplore.ieee.org/servlet/opac?punumber=4610933
+__ http://en.wikipedia.org/wiki/Half_precision_floating-point_format
+__ http://www.opengl.org/registry/specs/ARB/half_float_pixel.txt
+__ http://www.openexr.com/about.html
+
+.. cvar:: NPY_HALF_ZERO
+
+ This macro is defined to positive zero.
+
+.. cvar:: NPY_HALF_PZERO
+
+ This macro is defined to positive zero.
+
+.. cvar:: NPY_HALF_NZERO
+
+ This macro is defined to negative zero.
+
+.. cvar:: NPY_HALF_ONE
+
+ This macro is defined to 1.0.
+
+.. cvar:: NPY_HALF_NEGONE
+
+ This macro is defined to -1.0.
+
+.. cvar:: NPY_HALF_PINF
+
+ This macro is defined to +inf.
+
+.. cvar:: NPY_HALF_NINF
+
+ This macro is defined to -inf.
+
+.. cvar:: NPY_HALF_NAN
+
+ This macro is defined to a NaN value, guaranteed to have its sign bit unset.
+
+.. cfunction:: float npy_half_to_float(npy_half h)
+
+ Converts a half-precision float to a single-precision float.
+
+.. cfunction:: double npy_half_to_double(npy_half h)
+
+ Converts a half-precision float to a double-precision float.
+
+.. cfunction:: npy_half npy_float_to_half(float f)
+
+ Converts a single-precision float to a half-precision float. The
+ value is rounded to the nearest representable half, with ties going
+ to the nearest even. If the value is too small or too big, the
+ system's floating point underflow or overflow bit will be set.
+
+.. cfunction:: npy_half npy_double_to_half(double d)
+
+ Converts a double-precision float to a half-precision float. The
+ value is rounded to the nearest representable half, with ties going
+ to the nearest even. If the value is too small or too big, the
+ system's floating point underflow or overflow bit will be set.
+
+.. cfunction:: int npy_half_eq(npy_half h1, npy_half h2)
+
+ Compares two half-precision floats (h1 == h2).
+
+.. cfunction:: int npy_half_ne(npy_half h1, npy_half h2)
+
+ Compares two half-precision floats (h1 != h2).
+
+.. cfunction:: int npy_half_le(npy_half h1, npy_half h2)
+
+ Compares two half-precision floats (h1 <= h2).
+
+.. cfunction:: int npy_half_lt(npy_half h1, npy_half h2)
+
+ Compares two half-precision floats (h1 < h2).
+
+.. cfunction:: int npy_half_ge(npy_half h1, npy_half h2)
+
+ Compares two half-precision floats (h1 >= h2).
+
+.. cfunction:: int npy_half_gt(npy_half h1, npy_half h2)
+
+ Compares two half-precision floats (h1 > h2).
+
+.. cfunction:: int npy_half_eq_nonan(npy_half h1, npy_half h2)
+
+ Compares two half-precision floats that are known to not be NaN (h1 == h2). If
+ a value is NaN, the result is undefined.
+
+.. cfunction:: int npy_half_lt_nonan(npy_half h1, npy_half h2)
+
+ Compares two half-precision floats that are known to not be NaN (h1 < h2). If
+ a value is NaN, the result is undefined.
+
+.. cfunction:: int npy_half_le_nonan(npy_half h1, npy_half h2)
+
+ Compares two half-precision floats that are known to not be NaN (h1 <= h2). If
+ a value is NaN, the result is undefined.
+
+.. cfunction:: int npy_half_iszero(npy_half h)
+
+ Tests whether the half-precision float has a value equal to zero. This may be slightly
+ faster than calling npy_half_eq(h, NPY_ZERO).
+
+.. cfunction:: int npy_half_isnan(npy_half h)
+
+ Tests whether the half-precision float is a NaN.
+
+.. cfunction:: int npy_half_isinf(npy_half h)
+
+ Tests whether the half-precision float is plus or minus Inf.
+
+.. cfunction:: int npy_half_isfinite(npy_half h)
+
+ Tests whether the half-precision float is finite (not NaN or Inf).
+
+.. cfunction:: int npy_half_signbit(npy_half h)
+
+ Returns 1 is h is negative, 0 otherwise.
+
+.. cfunction:: npy_half npy_half_copysign(npy_half x, npy_half y)
+
+ Returns the value of x with the sign bit copied from y. Works for any value,
+ including Inf and NaN.
+
+.. cfunction:: npy_half npy_half_spacing(npy_half h)
+
+ This is the same for half-precision float as npy_spacing and npy_spacingf
+ described in the low-level floating point section.
+
+.. cfunction:: npy_half npy_half_nextafter(npy_half x, npy_half y)
+
+ This is the same for half-precision float as npy_nextafter and npy_nextafterf
+ described in the low-level floating point section.
+
+.. cfunction:: npy_uint16 npy_floatbits_to_halfbits(npy_uint32 f)
+
+ Low-level function which converts a 32-bit single-precision float, stored
+ as a uint32, into a 16-bit half-precision float.
+
+.. cfunction:: npy_uint16 npy_doublebits_to_halfbits(npy_uint64 d)
+
+ Low-level function which converts a 64-bit double-precision float, stored
+ as a uint64, into a 16-bit half-precision float.
+
+.. cfunction:: npy_uint32 npy_halfbits_to_floatbits(npy_uint16 h)
+
+ Low-level function which converts a 16-bit half-precision float
+ into a 32-bit single-precision float, stored as a uint32.
+
+.. cfunction:: npy_uint64 npy_halfbits_to_doublebits(npy_uint16 h)
+
+ Low-level function which converts a 16-bit half-precision float
+ into a 64-bit double-precision float, stored as a uint64.
+
diff --git a/doc/source/reference/c-api.dtype.rst b/doc/source/reference/c-api.dtype.rst
index 569a4ccb3..01f5260de 100644
--- a/doc/source/reference/c-api.dtype.rst
+++ b/doc/source/reference/c-api.dtype.rst
@@ -3,7 +3,7 @@ Data Type API
.. sectionauthor:: Travis E. Oliphant
-The standard array can have 21 different data types (and has some
+The standard array can have 24 different data types (and has some
support for adding your own types). These data types all have an
enumerated type, an enumerated type-character, and a corresponding
array scalar Python type object (placed in a hierarchy). There are
@@ -25,15 +25,16 @@ select the precision desired.
Enumerated Types
----------------
-There is a list of enumerated types defined providing the basic 21
+There is a list of enumerated types defined providing the basic 24
data types plus some useful generic names. Whenever the code requires
a type number, one of these enumerated types is requested. The types
are all called :cdata:`NPY_{NAME}` where ``{NAME}`` can be
**BOOL**, **BYTE**, **UBYTE**, **SHORT**, **USHORT**, **INT**,
**UINT**, **LONG**, **ULONG**, **LONGLONG**, **ULONGLONG**,
- **FLOAT**, **DOUBLE**, **LONGDOUBLE**, **CFLOAT**, **CDOUBLE**,
- **CLONGDOUBLE**, **OBJECT**, **STRING**, **UNICODE**, **VOID**
+ **HALF**, **FLOAT**, **DOUBLE**, **LONGDOUBLE**, **CFLOAT**,
+ **CDOUBLE**, **CLONGDOUBLE**, **DATETIME**, **TIMEDELTA**,
+ **OBJECT**, **STRING**, **UNICODE**, **VOID**
**NTYPES**, **NOTYPE**, **USERDEF**, **DEFAULT_TYPE**
@@ -44,8 +45,9 @@ is :cdata:`NPY_{NAME}LTR` where ``{NAME}`` can be
**BOOL**, **BYTE**, **UBYTE**, **SHORT**, **USHORT**, **INT**,
**UINT**, **LONG**, **ULONG**, **LONGLONG**, **ULONGLONG**,
- **FLOAT**, **DOUBLE**, **LONGDOUBLE**, **CFLOAT**, **CDOUBLE**,
- **CLONGDOUBLE**, **OBJECT**, **STRING**, **VOID**
+ **HALF**, **FLOAT**, **DOUBLE**, **LONGDOUBLE**, **CFLOAT**,
+ **CDOUBLE**, **CLONGDOUBLE**, **DATETIME**, **TIMEDELTA**,
+ **OBJECT**, **STRING**, **VOID**
**INTP**, **UINTP**
diff --git a/doc/source/reference/c-api.ufunc.rst b/doc/source/reference/c-api.ufunc.rst
index 384a69cf7..f299251cb 100644
--- a/doc/source/reference/c-api.ufunc.rst
+++ b/doc/source/reference/c-api.ufunc.rst
@@ -234,18 +234,27 @@ structure.
.. cfunction:: void PyUFunc_G_G(char** args, npy_intp* dimensions,
npy_intp* steps, void* func)
+.. cfunction:: void PyUFunc_e_e(char** args, npy_intp* dimensions,
+ npy_intp* steps, void* func)
+
+.. cfunction:: void PyUFunc_e_e_As_f_f(char** args, npy_intp* dimensions,
+ npy_intp* steps, void* func)
+
+.. cfunction:: void PyUFunc_e_e_As_d_d(char** args, npy_intp* dimensions,
+ npy_intp* steps, void* func)
+
Type specific, core 1-d functions for ufuncs where each
calculation is obtained by calling a function taking one input
argument and returning one output. This function is passed in
``func``. The letters correspond to dtypechar's of the supported
- data types ( ``f`` - float, ``d`` - double, ``g`` - long double,
- ``F`` - cfloat, ``D`` - cdouble, ``G`` - clongdouble). The
- argument *func* must support the same signature. The _As_X_X
- variants assume ndarray's of one data type but cast the values to
- use an underlying function that takes a different data type. Thus,
- :cfunc:`PyUFunc_f_f_As_d_d` uses ndarrays of data type :cdata:`NPY_FLOAT`
- but calls out to a C-function that takes double and returns
- double.
+ data types ( ``e`` - half, ``f`` - float, ``d`` - double,
+ ``g`` - long double, ``F`` - cfloat, ``D`` - cdouble,
+ ``G`` - clongdouble). The argument *func* must support the same
+ signature. The _As_X_X variants assume ndarray's of one data type
+ but cast the values to use an underlying function that takes a
+ different data type. Thus, :cfunc:`PyUFunc_f_f_As_d_d` uses
+ ndarrays of data type :cdata:`NPY_FLOAT` but calls out to a
+ C-function that takes double and returns double.
.. cfunction:: void PyUFunc_ff_f_As_dd_d(char** args, npy_intp* dimensions,
npy_intp* steps, void* func)
@@ -271,6 +280,15 @@ structure.
.. cfunction:: void PyUFunc_GG_G(char** args, npy_intp* dimensions,
npy_intp* steps, void* func)
+.. cfunction:: void PyUFunc_ee_e(char** args, npy_intp* dimensions,
+ npy_intp* steps, void* func)
+
+.. cfunction:: void PyUFunc_ee_e_As_ff_f(char** args, npy_intp* dimensions,
+ npy_intp* steps, void* func)
+
+.. cfunction:: void PyUFunc_ee_e_As_dd_d(char** args, npy_intp* dimensions,
+ npy_intp* steps, void* func)
+
Type specific, core 1-d functions for ufuncs where each
calculation is obtained by calling a function taking two input
arguments and returning one output. The underlying function to
diff --git a/doc/source/reference/figures/dtype-hierarchy.dia b/doc/source/reference/figures/dtype-hierarchy.dia
index 65379b880..62e925cfd 100644
--- a/doc/source/reference/figures/dtype-hierarchy.dia
+++ b/doc/source/reference/figures/dtype-hierarchy.dia
Binary files differ
diff --git a/doc/source/reference/figures/dtype-hierarchy.png b/doc/source/reference/figures/dtype-hierarchy.png
index 5722ac527..6c45758b1 100644
--- a/doc/source/reference/figures/dtype-hierarchy.png
+++ b/doc/source/reference/figures/dtype-hierarchy.png
Binary files differ
diff --git a/doc/source/reference/ufuncs.rst b/doc/source/reference/ufuncs.rst
index 77269be58..dedbf2929 100644
--- a/doc/source/reference/ufuncs.rst
+++ b/doc/source/reference/ufuncs.rst
@@ -207,7 +207,7 @@ implemented by the question of when a data type can be cast "safely"
to another data type. The answer to this question can be determined in
Python with a function call: :func:`can_cast(fromtype, totype)
<can_cast>`. The Figure below shows the results of this call for
-the 21 internally supported types on the author's 32-bit system. You
+the 24 internally supported types on the author's 64-bit system. You
can generate this table for your system with the code given in the Figure.
.. admonition:: Figure
@@ -224,34 +224,38 @@ can generate this table for your system with the code given in the Figure.
... print int(np.can_cast(row, col)),
... print
>>> print_table(np.typecodes['All'])
- X ? b h i l q p B H I L Q P f d g F D G S U V O
- ? 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- b 0 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
- h 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
- i 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1
- l 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1
- q 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1
- p 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1
- B 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- H 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- I 0 0 0 0 0 1 0 0 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1
- L 0 0 0 0 0 1 0 0 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1
- Q 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 1 1 1 1 1
- P 0 0 0 0 0 1 0 0 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1
- f 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
- d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1
- g 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 1
- F 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
- D 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
- G 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
- S 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
- U 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1
- V 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
- O 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
+ X ? b h i l q p B H I L Q P e f d g F D G S U V O M m
+ ? 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ b 0 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0
+ h 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0
+ i 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 0
+ l 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 0
+ q 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 0
+ p 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 0
+ B 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0
+ H 0 0 0 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 0
+ I 0 0 0 0 1 1 1 0 0 1 1 1 1 0 0 1 1 0 1 1 1 1 1 1 0 0
+ L 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 1 1 1 1 1 1 0 0
+ Q 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 1 1 1 1 1 1 0 0
+ P 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 1 1 1 1 1 1 0 0
+ e 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0
+ f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0
+ d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 0
+ g 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 1 0 0
+ F 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0
+ D 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0
+ G 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0
+ S 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0
+ U 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0
+ V 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0
+ O 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0
+ M 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
+ m 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
+
You should note that, while included in the table for completeness,
the 'S', 'U', and 'V' types cannot be operated on by ufuncs. Also,
-note that on a 64-bit system the integer types may have different
+note that on a 32-bit system the integer types may have different
sizes, resulting in a slightly altered table.
Mixed scalar-array operations use a different set of casting rules
diff --git a/doc/source/user/c-info.beyond-basics.rst b/doc/source/user/c-info.beyond-basics.rst
index 563467e72..5ff92a122 100644
--- a/doc/source/user/c-info.beyond-basics.rst
+++ b/doc/source/user/c-info.beyond-basics.rst
@@ -389,7 +389,7 @@ register ufuncs for user-defined data-types.
User-defined data-types
=======================
-NumPy comes with 21 builtin data-types. While this covers a large
+NumPy comes with 24 builtin data-types. While this covers a large
majority of possible use cases, it is conceivable that a user may have
a need for an additional data-type. There is some support for adding
an additional data-type into the NumPy system. This additional data-
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!