~ubuntu-branches/ubuntu/precise/python-numpy/precise

« back to all changes in this revision

Viewing changes to numpy/core/src/umath/loops.c.src

  • Committer: Package Import Robot
  • Author(s): Julian Taylor
  • Date: 2012-02-11 12:55:21 UTC
  • mfrom: (7.1.9 experimental) (7.2.3 sid)
  • Revision ID: package-import@ubuntu.com-20120211125521-31q3am7pp3mvt1ho
Tags: 1:1.6.1-5ubuntu1
* debian/patches/search-multiarch-paths.patch: (LP: #818867)
  - add multiarch libdirs to numpy.distutils.system_info
* Merge from Debian unstable, remaining changes:
  - debian/patches/20_disable-plot-extension.patch
     Disable plot_directive extension, and catch ImportErrors when
     matplotlib cannot be imported, which allows us to remove
     python-matplotlib from dependencies.  This is required because
     python-numpy is in main, while python-matplotlib is in universe.
  - Build using dh_python2
    add bin/f2py* to .install files
  - keep Replaces: python-numpy (<< 1:1.3.0-4) in python-numpy-dbg
    for lucid upgrades

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
#include "numpy/noprefix.h"
14
14
#include "numpy/ufuncobject.h"
15
15
#include "numpy/npy_math.h"
 
16
#include "numpy/halffloat.h"
16
17
 
17
18
#include "numpy/npy_3kcompat.h"
18
19
 
19
20
#include "ufunc_object.h"
20
21
 
 
22
 
21
23
/*
22
24
 *****************************************************************************
23
25
 **                             UFUNC LOOPS                                 **
56
58
    intp i;\
57
59
    for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1)
58
60
 
59
 
#define BINARY_REDUCE_LOOP(TYPE)\
60
 
    char *iop1 = args[0], *ip2 = args[1]; \
 
61
#define BINARY_REDUCE_LOOP_INNER\
 
62
    char *ip2 = args[1]; \
61
63
    intp is2 = steps[1]; \
62
64
    intp n = dimensions[0]; \
63
65
    intp i; \
 
66
    for(i = 0; i < n; i++, ip2 += is2)
 
67
 
 
68
#define BINARY_REDUCE_LOOP(TYPE)\
 
69
    char *iop1 = args[0]; \
64
70
    TYPE io1 = *(TYPE *)iop1; \
65
 
    for(i = 0; i < n; i++, ip2 += is2)
 
71
    BINARY_REDUCE_LOOP_INNER
66
72
 
67
73
#define BINARY_LOOP_TWO_OUT\
68
74
    char *ip1 = args[0], *ip2 = args[1], *op1 = args[2], *op2 = args[3];\
76
82
 *****************************************************************************/
77
83
 
78
84
 
 
85
typedef float halfUnaryFunc(npy_half x);
79
86
typedef float floatUnaryFunc(float x);
80
87
typedef double doubleUnaryFunc(double x);
81
88
typedef longdouble longdoubleUnaryFunc(longdouble x);
 
89
typedef npy_half halfBinaryFunc(npy_half x, npy_half y);
82
90
typedef float floatBinaryFunc(float x, float y);
83
91
typedef double doubleBinaryFunc(double x, double y);
84
92
typedef longdouble longdoubleBinaryFunc(longdouble x, longdouble y);
86
94
 
87
95
/*UFUNC_API*/
88
96
NPY_NO_EXPORT void
 
97
PyUFunc_e_e(char **args, intp *dimensions, intp *steps, void *func)
 
98
{
 
99
    halfUnaryFunc *f = (halfUnaryFunc *)func;
 
100
    UNARY_LOOP {
 
101
        const npy_half in1 = *(npy_half *)ip1;
 
102
        *(npy_half *)op1 = f(in1);
 
103
    }
 
104
}
 
105
 
 
106
/*UFUNC_API*/
 
107
NPY_NO_EXPORT void
 
108
PyUFunc_e_e_As_f_f(char **args, intp *dimensions, intp *steps, void *func)
 
109
{
 
110
    floatUnaryFunc *f = (floatUnaryFunc *)func;
 
111
    UNARY_LOOP {
 
112
        const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
113
        *(npy_half *)op1 = npy_float_to_half(f(in1));
 
114
    }
 
115
}
 
116
 
 
117
/*UFUNC_API*/
 
118
NPY_NO_EXPORT void
 
119
PyUFunc_e_e_As_d_d(char **args, intp *dimensions, intp *steps, void *func)
 
120
{
 
121
    doubleUnaryFunc *f = (doubleUnaryFunc *)func;
 
122
    UNARY_LOOP {
 
123
        const double in1 = npy_half_to_double(*(npy_half *)ip1);
 
124
        *(npy_half *)op1 = npy_double_to_half(f(in1));
 
125
    }
 
126
}
 
127
 
 
128
/*UFUNC_API*/
 
129
NPY_NO_EXPORT void
89
130
PyUFunc_f_f(char **args, intp *dimensions, intp *steps, void *func)
90
131
{
91
132
    floatUnaryFunc *f = (floatUnaryFunc *)func;
108
149
 
109
150
/*UFUNC_API*/
110
151
NPY_NO_EXPORT void
 
152
PyUFunc_ee_e(char **args, intp *dimensions, intp *steps, void *func)
 
153
{
 
154
    halfBinaryFunc *f = (halfBinaryFunc *)func;
 
155
    BINARY_LOOP {
 
156
        npy_half in1 = *(npy_half *)ip1;
 
157
        npy_half in2 = *(npy_half *)ip2;
 
158
        *(npy_half *)op1 = f(in1, in2);
 
159
    }
 
160
}
 
161
 
 
162
/*UFUNC_API*/
 
163
NPY_NO_EXPORT void
 
164
PyUFunc_ee_e_As_ff_f(char **args, intp *dimensions, intp *steps, void *func)
 
165
{
 
166
    floatBinaryFunc *f = (floatBinaryFunc *)func;
 
167
    BINARY_LOOP {
 
168
        float in1 = npy_half_to_float(*(npy_half *)ip1);
 
169
        float in2 = npy_half_to_float(*(npy_half *)ip2);
 
170
        *(npy_half *)op1 = npy_float_to_half(f(in1, in2));
 
171
    }
 
172
}
 
173
 
 
174
/*UFUNC_API*/
 
175
NPY_NO_EXPORT void
 
176
PyUFunc_ee_e_As_dd_d(char **args, intp *dimensions, intp *steps, void *func)
 
177
{
 
178
    doubleBinaryFunc *f = (doubleBinaryFunc *)func;
 
179
    BINARY_LOOP {
 
180
        double in1 = npy_half_to_double(*(npy_half *)ip1);
 
181
        double in2 = npy_half_to_double(*(npy_half *)ip2);
 
182
        *(npy_half *)op1 = npy_double_to_half(f(in1, in2));
 
183
    }
 
184
}
 
185
 
 
186
/*UFUNC_API*/
 
187
NPY_NO_EXPORT void
111
188
PyUFunc_ff_f(char **args, intp *dimensions, intp *steps, void *func)
112
189
{
113
190
    floatBinaryFunc *f = (floatBinaryFunc *)func;
311
388
    UNARY_LOOP {
312
389
        PyObject *in1 = *(PyObject **)ip1;
313
390
        PyObject **out = (PyObject **)op1;
314
 
        PyObject *ret = f(in1);
315
 
        if ((ret == NULL) || PyErr_Occurred()) {
 
391
        PyObject *ret = f(in1 ? in1 : Py_None);
 
392
        if (ret == NULL) {
316
393
            return;
317
394
        }
318
395
        Py_XDECREF(*out);
328
405
    UNARY_LOOP {
329
406
        PyObject *in1 = *(PyObject **)ip1;
330
407
        PyObject **out = (PyObject **)op1;
331
 
        PyObject *ret = PyObject_CallMethod(in1, meth, NULL);
 
408
        PyObject *ret = PyObject_CallMethod(in1 ? in1 : Py_None, meth, NULL);
332
409
        if (ret == NULL) {
333
410
            return;
334
411
        }
346
423
        PyObject *in1 = *(PyObject **)ip1;
347
424
        PyObject *in2 = *(PyObject **)ip2;
348
425
        PyObject **out = (PyObject **)op1;
349
 
        PyObject *ret = f(in1, in2);
350
 
        if (PyErr_Occurred()) {
 
426
        PyObject *ret = f(in1 ? in1 : Py_None, in2 ? in2 : Py_None);
 
427
        if (ret == NULL) {
351
428
            return;
352
429
        }
353
430
        Py_XDECREF(*out);
364
441
        PyObject *in1 = *(PyObject **)ip1;
365
442
        PyObject *in2 = *(PyObject **)ip2;
366
443
        PyObject **out = (PyObject **)op1;
367
 
        PyObject *ret = PyObject_CallMethod(in1, meth, "(O)", in2);
 
444
        PyObject *ret = PyObject_CallMethod(in1 ? in1 : Py_None,
 
445
                                            meth, "(O)", in2);
368
446
        if (ret == NULL) {
369
447
            return;
370
448
        }
405
483
        for(j = 0; j < nin; j++) {
406
484
            in = *((PyObject **)ptrs[j]);
407
485
            if (in == NULL) {
408
 
                Py_DECREF(arglist);
409
 
                return;
 
486
                in = Py_None;
410
487
            }
411
488
            PyTuple_SET_ITEM(arglist, j, in);
412
489
            Py_INCREF(in);
683
760
NPY_NO_EXPORT void
684
761
@S@@TYPE@_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
685
762
{
686
 
    BINARY_LOOP {
687
 
        const @s@@type@ in1 = *(@s@@type@ *)ip1;
688
 
        const @s@@type@ in2 = *(@s@@type@ *)ip2;
689
 
        *((@s@@type@ *)op1) = (in1 @OP@ in2) ? in1 : in2;
 
763
    if (IS_BINARY_REDUCE) {
 
764
        BINARY_REDUCE_LOOP(@s@@type@) {
 
765
            const @s@@type@ in2 = *(@type@ *)ip2;
 
766
            io1 = (io1 @OP@ in2) ? io1 : in2;
 
767
        }
 
768
        *((@s@@type@ *)iop1) = io1;
 
769
    }
 
770
    else {
 
771
        BINARY_LOOP {
 
772
            const @s@@type@ in1 = *(@s@@type@ *)ip1;
 
773
            const @s@@type@ in2 = *(@s@@type@ *)ip2;
 
774
            *((@s@@type@ *)op1) = (in1 @OP@ in2) ? in1 : in2;
 
775
        }
690
776
    }
691
777
}
692
778
/**end repeat2**/
718
804
        const @s@@type@ in1 = *(@s@@type@ *)ip1;
719
805
        const @s@@type@ in2 = *(@s@@type@ *)ip2;
720
806
        if (in2 == 0) {
721
 
            generate_divbyzero_error();
 
807
            npy_set_floatstatus_divbyzero();
722
808
            *((@s@@type@ *)op1) = 0;
723
809
        }
724
810
        else {
777
863
         * by -1 causes a SIFGPE (division overflow). We treat this case here
778
864
         * (to avoid a SIGFPE crash at python level), but a good solution would
779
865
         * be to treat integer division problems separately from FPU exceptions
780
 
         * (i.e. fixing generate_divbyzero_error()).
 
866
         * (i.e. a different approach than npy_set_floatstatus_divbyzero()).
781
867
         */
782
868
        if (in2 == 0 || (in1 == NPY_MIN_@TYPE@ && in2 == -1)) {
783
 
            generate_divbyzero_error();
 
869
            npy_set_floatstatus_divbyzero();
784
870
            *((@type@ *)op1) = 0;
785
871
        }
786
872
        else if (((in1 > 0) != (in2 > 0)) && (in1 % in2 != 0)) {
799
885
        const u@type@ in1 = *(u@type@ *)ip1;
800
886
        const u@type@ in2 = *(u@type@ *)ip2;
801
887
        if (in2 == 0) {
802
 
            generate_divbyzero_error();
 
888
            npy_set_floatstatus_divbyzero();
803
889
            *((u@type@ *)op1) = 0;
804
890
        }
805
891
        else {
815
901
        const @type@ in1 = *(@type@ *)ip1;
816
902
        const @type@ in2 = *(@type@ *)ip2;
817
903
        if (in2 == 0) {
818
 
            generate_divbyzero_error();
 
904
            npy_set_floatstatus_divbyzero();
819
905
            *((@type@ *)op1) = 0;
820
906
        }
821
907
        else {
838
924
        const u@type@ in1 = *(u@type@ *)ip1;
839
925
        const u@type@ in2 = *(u@type@ *)ip2;
840
926
        if (in2 == 0) {
841
 
            generate_divbyzero_error();
 
927
            npy_set_floatstatus_divbyzero();
842
928
            *((@type@ *)op1) = 0;
843
929
        }
844
930
        else {
849
935
 
850
936
/**end repeat**/
851
937
 
 
938
/*
 
939
 *****************************************************************************
 
940
 **                           DATETIME LOOPS                                **
 
941
 *****************************************************************************
 
942
 */
 
943
 
 
944
/**begin repeat
 
945
 * #type = datetime, timedelta#
 
946
 * #TYPE = DATETIME, TIMEDELTA#
 
947
 * #ftype = double, double#
 
948
 */
 
949
 
 
950
NPY_NO_EXPORT void
 
951
@TYPE@_ones_like(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data))
 
952
{
 
953
    OUTPUT_LOOP {
 
954
        *((@type@ *)op1) = 1;
 
955
    }
 
956
}
 
957
 
 
958
NPY_NO_EXPORT void
 
959
@TYPE@_negative(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
960
{
 
961
    UNARY_LOOP {
 
962
        const @type@ in1 = *(@type@ *)ip1;
 
963
        *((@type@ *)op1) = (@type@)(-(@type@)in1);
 
964
    }
 
965
}
 
966
 
 
967
NPY_NO_EXPORT void
 
968
@TYPE@_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
969
{
 
970
    UNARY_LOOP {
 
971
        const @type@ in1 = *(@type@ *)ip1;
 
972
        *((Bool *)op1) = !in1;
 
973
    }
 
974
}
 
975
 
 
976
 
 
977
/**begin repeat1
 
978
 * #kind = equal, not_equal, greater, greater_equal, less, less_equal,
 
979
 *         logical_and, logical_or#
 
980
 * #OP =  ==, !=, >, >=, <, <=, &&, ||#
 
981
 */
 
982
NPY_NO_EXPORT void
 
983
@TYPE@_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
984
{
 
985
    BINARY_LOOP {
 
986
        const @type@ in1 = *(@type@ *)ip1;
 
987
        const @type@ in2 = *(@type@ *)ip2;
 
988
        *((Bool *)op1) = in1 @OP@ in2;
 
989
    }
 
990
}
 
991
/**end repeat1**/
 
992
 
 
993
NPY_NO_EXPORT void
 
994
@TYPE@_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
995
{
 
996
    BINARY_LOOP {
 
997
        const @type@ in1 = *(@type@ *)ip1;
 
998
        const @type@ in2 = *(@type@ *)ip2;
 
999
        *((Bool *)op1)= (in1 && !in2) || (!in1 && in2);
 
1000
    }
 
1001
}
 
1002
 
 
1003
/**begin repeat1
 
1004
 * #kind = maximum, minimum#
 
1005
 * #OP =  >, <#
 
1006
 **/
 
1007
NPY_NO_EXPORT void
 
1008
@TYPE@_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1009
{
 
1010
    if (IS_BINARY_REDUCE) {
 
1011
        BINARY_REDUCE_LOOP(@type@) {
 
1012
            const @type@ in2 = *(@type@ *)ip2;
 
1013
            io1 = (io1 @OP@ in2) ? io1 : in2;
 
1014
        }
 
1015
        *((@type@ *)iop1) = io1;
 
1016
    }
 
1017
    else {
 
1018
    BINARY_LOOP {
 
1019
        const @type@ in1 = *(@type@ *)ip1;
 
1020
        const @type@ in2 = *(@type@ *)ip2;
 
1021
        *((@type@ *)op1) = (in1 @OP@ in2) ? in1 : in2;
 
1022
    }
 
1023
    }
 
1024
}
 
1025
/**end repeat1**/
 
1026
 
 
1027
NPY_NO_EXPORT void
 
1028
@TYPE@_absolute(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1029
{
 
1030
    UNARY_LOOP {
 
1031
        const @type@ in1 = *(@type@ *)ip1;
 
1032
        *((@type@ *)op1) = (in1 >= 0) ? in1 : -in1;
 
1033
    }
 
1034
}
 
1035
 
 
1036
NPY_NO_EXPORT void
 
1037
@TYPE@_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1038
{
 
1039
    UNARY_LOOP {
 
1040
        const @type@ in1 = *(@type@ *)ip1;
 
1041
        *((@type@ *)op1) = in1 > 0 ? 1 : (in1 < 0 ? -1 : 0);
 
1042
    }
 
1043
}
 
1044
 
 
1045
/**end repeat**/
 
1046
 
 
1047
/* FIXME: implement the following correctly using the metadata:  data is the
 
1048
   sequence of ndarrays in the same order as args.
 
1049
 */
 
1050
NPY_NO_EXPORT void
 
1051
DATETIME_Mm_M_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data))
 
1052
{
 
1053
    BINARY_LOOP {
 
1054
        const datetime in1 = *(datetime *)ip1;
 
1055
        const timedelta in2 = *(timedelta *)ip2;
 
1056
        *((datetime *)op1) = in1 + in2;
 
1057
    }
 
1058
}
 
1059
 
 
1060
NPY_NO_EXPORT void
 
1061
DATETIME_mM_M_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1062
{
 
1063
    BINARY_LOOP {
 
1064
        const timedelta in1 = *(timedelta *)ip1;
 
1065
        const datetime in2 = *(datetime *)ip2;
 
1066
        *((datetime *)op1) = in1 + in2;
 
1067
    }
 
1068
}
 
1069
 
 
1070
NPY_NO_EXPORT void
 
1071
TIMEDELTA_mm_m_add(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1072
{
 
1073
    BINARY_LOOP {
 
1074
        const timedelta in1 = *(timedelta *)ip1;
 
1075
        const timedelta in2 = *(timedelta *)ip2;
 
1076
        *((timedelta *)op1) = in1 + in2;
 
1077
    }
 
1078
}
 
1079
 
 
1080
NPY_NO_EXPORT void
 
1081
DATETIME_Mm_M_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1082
{
 
1083
    BINARY_LOOP {
 
1084
        const datetime in1 = *(datetime *)ip1;
 
1085
        const timedelta in2 = *(timedelta *)ip2;
 
1086
        *((datetime *)op1) = in1 - in2;
 
1087
    }
 
1088
}
 
1089
 
 
1090
NPY_NO_EXPORT void
 
1091
DATETIME_MM_m_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1092
{
 
1093
    BINARY_LOOP {
 
1094
        const datetime in1 = *(datetime *)ip1;
 
1095
        const datetime in2 = *(datetime *)ip2;
 
1096
        *((timedelta *)op1) = in1 - in2;
 
1097
    }
 
1098
}
 
1099
 
 
1100
NPY_NO_EXPORT void
 
1101
TIMEDELTA_mm_m_subtract(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1102
{
 
1103
    BINARY_LOOP {
 
1104
        const timedelta in1 = *(timedelta *)ip1;
 
1105
        const timedelta in2 = *(timedelta *)ip2;
 
1106
        *((timedelta *)op1) = in1 - in2;
 
1107
    }
 
1108
}
 
1109
 
852
1110
 
853
1111
/*
854
1112
 *****************************************************************************
890
1148
}
891
1149
/**end repeat1**/
892
1150
 
893
 
/**end repeat1**/
894
 
 
895
1151
/**begin repeat1
896
1152
 * #kind = equal, not_equal, less, less_equal, greater, greater_equal,
897
1153
 *        logical_and, logical_or#
978
1234
@TYPE@_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
979
1235
{
980
1236
    /*  */
981
 
    BINARY_LOOP {
982
 
        const @type@ in1 = *(@type@ *)ip1;
983
 
        const @type@ in2 = *(@type@ *)ip2;
984
 
        *((@type@ *)op1) = (in1 @OP@ in2 || npy_isnan(in1)) ? in1 : in2;
 
1237
    if (IS_BINARY_REDUCE) {
 
1238
        BINARY_REDUCE_LOOP(@type@) {
 
1239
            const @type@ in2 = *(@type@ *)ip2;
 
1240
            io1 = (io1 @OP@ in2 || npy_isnan(io1)) ? io1 : in2;
 
1241
        }
 
1242
        *((@type@ *)iop1) = io1;
 
1243
    }
 
1244
    else {
 
1245
        BINARY_LOOP {
 
1246
            const @type@ in1 = *(@type@ *)ip1;
 
1247
            const @type@ in2 = *(@type@ *)ip2;
 
1248
            *((@type@ *)op1) = (in1 @OP@ in2 || npy_isnan(in1)) ? in1 : in2;
 
1249
        }
985
1250
    }
986
1251
}
987
1252
/**end repeat1**/
994
1259
@TYPE@_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
995
1260
{
996
1261
    /*  */
997
 
    BINARY_LOOP {
998
 
        const @type@ in1 = *(@type@ *)ip1;
999
 
        const @type@ in2 = *(@type@ *)ip2;
1000
 
        *((@type@ *)op1) = (in1 @OP@ in2 || npy_isnan(in2)) ? in1 : in2;
 
1262
    if (IS_BINARY_REDUCE) {
 
1263
        BINARY_REDUCE_LOOP(@type@) {
 
1264
            const @type@ in2 = *(@type@ *)ip2;
 
1265
            io1 = (io1 @OP@ in2 || npy_isnan(in2)) ? io1 : in2;
 
1266
        }
 
1267
        *((@type@ *)iop1) = io1;
 
1268
    }
 
1269
    else {
 
1270
        BINARY_LOOP {
 
1271
            const @type@ in1 = *(@type@ *)ip1;
 
1272
            const @type@ in2 = *(@type@ *)ip2;
 
1273
            *((@type@ *)op1) = (in1 @OP@ in2 || npy_isnan(in2)) ? in1 : in2;
 
1274
        }
1001
1275
    }
1002
1276
}
1003
1277
/**end repeat1**/
1159
1433
 
1160
1434
/**end repeat**/
1161
1435
 
 
1436
/*
 
1437
 *****************************************************************************
 
1438
 **                          HALF-FLOAT LOOPS                               **
 
1439
 *****************************************************************************
 
1440
 */
 
1441
 
 
1442
 
 
1443
/**begin repeat
 
1444
 * Arithmetic
 
1445
 * # kind = add, subtract, multiply, divide#
 
1446
 * # OP = +, -, *, /#
 
1447
 */
 
1448
NPY_NO_EXPORT void
 
1449
HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1450
{
 
1451
    if(IS_BINARY_REDUCE) {
 
1452
        char *iop1 = args[0];
 
1453
        float io1 = npy_half_to_float(*(npy_half *)iop1);
 
1454
        BINARY_REDUCE_LOOP_INNER {
 
1455
            io1 @OP@= npy_half_to_float(*(npy_half *)ip2);
 
1456
        }
 
1457
        *((npy_half *)iop1) = npy_float_to_half(io1);
 
1458
    }
 
1459
    else {
 
1460
        BINARY_LOOP {
 
1461
            const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
1462
            const float in2 = npy_half_to_float(*(npy_half *)ip2);
 
1463
            *((npy_half *)op1) = npy_float_to_half(in1 @OP@ in2);
 
1464
        }
 
1465
    }
 
1466
}
 
1467
/**end repeat**/
 
1468
 
 
1469
#define _HALF_LOGICAL_AND(a,b) (!npy_half_iszero(a) && !npy_half_iszero(b))
 
1470
#define _HALF_LOGICAL_OR(a,b) (!npy_half_iszero(a) || !npy_half_iszero(b))
 
1471
/**begin repeat
 
1472
 * #kind = equal, not_equal, less, less_equal, greater, greater_equal,
 
1473
 *        logical_and, logical_or#
 
1474
 * #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#
 
1475
 */
 
1476
NPY_NO_EXPORT void
 
1477
HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1478
{
 
1479
    BINARY_LOOP {
 
1480
        const npy_half in1 = *(npy_half *)ip1;
 
1481
        const npy_half in2 = *(npy_half *)ip2;
 
1482
        *((Bool *)op1) = @OP@(in1, in2);
 
1483
    }
 
1484
}
 
1485
/**end repeat**/
 
1486
#undef _HALF_LOGICAL_AND
 
1487
#undef _HALF_LOGICAL_OR
 
1488
 
 
1489
NPY_NO_EXPORT void
 
1490
HALF_logical_xor(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1491
{
 
1492
    BINARY_LOOP {
 
1493
        const int in1 = !npy_half_iszero(*(npy_half *)ip1);
 
1494
        const int in2 = !npy_half_iszero(*(npy_half *)ip2);
 
1495
        *((Bool *)op1)= (in1 && !in2) || (!in1 && in2);
 
1496
    }
 
1497
}
 
1498
 
 
1499
NPY_NO_EXPORT void
 
1500
HALF_logical_not(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1501
{
 
1502
    UNARY_LOOP {
 
1503
        const npy_half in1 = *(npy_half *)ip1;
 
1504
        *((Bool *)op1) = npy_half_iszero(in1);
 
1505
    }
 
1506
}
 
1507
 
 
1508
/**begin repeat
 
1509
 * #kind = isnan, isinf, isfinite, signbit#
 
1510
 * #func = npy_half_isnan, npy_half_isinf, npy_half_isfinite, npy_half_signbit#
 
1511
 **/
 
1512
NPY_NO_EXPORT void
 
1513
HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1514
{
 
1515
    UNARY_LOOP {
 
1516
        const npy_half in1 = *(npy_half *)ip1;
 
1517
        *((Bool *)op1) = @func@(in1) != 0;
 
1518
    }
 
1519
}
 
1520
/**end repeat**/
 
1521
 
 
1522
NPY_NO_EXPORT void
 
1523
HALF_spacing(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1524
{
 
1525
    UNARY_LOOP {
 
1526
        const npy_half in1 = *(npy_half *)ip1;
 
1527
        *((npy_half *)op1) = npy_half_spacing(in1);
 
1528
    }
 
1529
}
 
1530
 
 
1531
NPY_NO_EXPORT void
 
1532
HALF_copysign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1533
{
 
1534
    BINARY_LOOP {
 
1535
        const npy_half in1 = *(npy_half *)ip1;
 
1536
        const npy_half in2 = *(npy_half *)ip2;
 
1537
        *((npy_half *)op1)= npy_half_copysign(in1, in2);
 
1538
    }
 
1539
}
 
1540
 
 
1541
NPY_NO_EXPORT void
 
1542
HALF_nextafter(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1543
{
 
1544
    BINARY_LOOP {
 
1545
        const npy_half in1 = *(npy_half *)ip1;
 
1546
        const npy_half in2 = *(npy_half *)ip2;
 
1547
        *((npy_half *)op1)= npy_half_nextafter(in1, in2);
 
1548
    }
 
1549
}
 
1550
 
 
1551
/**begin repeat
 
1552
 * #kind = maximum, minimum#
 
1553
 * #OP =  npy_half_ge, npy_half_le#
 
1554
 **/
 
1555
NPY_NO_EXPORT void
 
1556
HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1557
{
 
1558
    /*  */
 
1559
    BINARY_LOOP {
 
1560
        const npy_half in1 = *(npy_half *)ip1;
 
1561
        const npy_half in2 = *(npy_half *)ip2;
 
1562
        *((npy_half *)op1) = (@OP@(in1, in2) || npy_half_isnan(in1)) ? in1 : in2;
 
1563
    }
 
1564
}
 
1565
/**end repeat**/
 
1566
 
 
1567
/**begin repeat
 
1568
 * #kind = fmax, fmin#
 
1569
 * #OP =  npy_half_ge, npy_half_le#
 
1570
 **/
 
1571
NPY_NO_EXPORT void
 
1572
HALF_@kind@(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1573
{
 
1574
    /*  */
 
1575
    BINARY_LOOP {
 
1576
        const npy_half in1 = *(npy_half *)ip1;
 
1577
        const npy_half in2 = *(npy_half *)ip2;
 
1578
        *((npy_half *)op1) = (@OP@(in1, in2) || npy_half_isnan(in2)) ? in1 : in2;
 
1579
    }
 
1580
}
 
1581
/**end repeat**/
 
1582
 
 
1583
NPY_NO_EXPORT void
 
1584
HALF_floor_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1585
{
 
1586
    BINARY_LOOP {
 
1587
        const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
1588
        const float in2 = npy_half_to_float(*(npy_half *)ip2);
 
1589
        *((npy_half *)op1) = npy_float_to_half(npy_floorf(in1/in2));
 
1590
    }
 
1591
}
 
1592
 
 
1593
NPY_NO_EXPORT void
 
1594
HALF_remainder(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1595
{
 
1596
    BINARY_LOOP {
 
1597
        const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
1598
        const float in2 = npy_half_to_float(*(npy_half *)ip2);
 
1599
        const float res = npy_fmodf(in1,in2);
 
1600
        if (res && ((in2 < 0) != (res < 0))) {
 
1601
            *((npy_half *)op1) = npy_float_to_half(res + in2);
 
1602
        }
 
1603
        else {
 
1604
            *((npy_half *)op1) = npy_float_to_half(res);
 
1605
        }
 
1606
    }
 
1607
}
 
1608
 
 
1609
NPY_NO_EXPORT void
 
1610
HALF_square(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data))
 
1611
{
 
1612
    UNARY_LOOP {
 
1613
        const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
1614
        *((npy_half *)op1) = npy_float_to_half(in1*in1);
 
1615
    }
 
1616
}
 
1617
 
 
1618
NPY_NO_EXPORT void
 
1619
HALF_reciprocal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data))
 
1620
{
 
1621
    UNARY_LOOP {
 
1622
        const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
1623
        *((npy_half *)op1) = npy_float_to_half(1/in1);
 
1624
    }
 
1625
}
 
1626
 
 
1627
NPY_NO_EXPORT void
 
1628
HALF_ones_like(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(data))
 
1629
{
 
1630
    OUTPUT_LOOP {
 
1631
        *((npy_half *)op1) = NPY_HALF_ONE;
 
1632
    }
 
1633
}
 
1634
 
 
1635
NPY_NO_EXPORT void
 
1636
HALF_conjugate(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1637
{
 
1638
    UNARY_LOOP {
 
1639
        const npy_half in1 = *(npy_half *)ip1;
 
1640
        *((npy_half *)op1) = in1;
 
1641
    }
 
1642
}
 
1643
 
 
1644
NPY_NO_EXPORT void
 
1645
HALF_absolute(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1646
{
 
1647
    UNARY_LOOP {
 
1648
        const npy_half in1 = *(npy_half *)ip1;
 
1649
        *((npy_half *)op1) = in1&0x7fffu;
 
1650
    }
 
1651
}
 
1652
 
 
1653
NPY_NO_EXPORT void
 
1654
HALF_negative(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1655
{
 
1656
    UNARY_LOOP {
 
1657
        const npy_half in1 = *(npy_half *)ip1;
 
1658
        *((npy_half *)op1) = in1^0x8000u;
 
1659
    }
 
1660
}
 
1661
 
 
1662
NPY_NO_EXPORT void
 
1663
HALF_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1664
{
 
1665
    /* Sign of nan is nan */
 
1666
    UNARY_LOOP {
 
1667
        const npy_half in1 = *(npy_half *)ip1;
 
1668
        *((npy_half *)op1) = npy_half_isnan(in1) ? in1 :
 
1669
                    (((in1&0x7fffu) == 0) ? 0 :
 
1670
                      (((in1&0x8000u) == 0) ? NPY_HALF_ONE : NPY_HALF_NEGONE));
 
1671
    }
 
1672
}
 
1673
 
 
1674
NPY_NO_EXPORT void
 
1675
HALF_modf(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1676
{
 
1677
    float temp;
 
1678
 
 
1679
    UNARY_LOOP_TWO_OUT {
 
1680
        const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
1681
        *((npy_half *)op1) = npy_float_to_half(npy_modff(in1, &temp));
 
1682
        *((npy_half *)op2) = npy_float_to_half(temp);
 
1683
    }
 
1684
}
 
1685
 
 
1686
#ifdef HAVE_FREXPF
 
1687
NPY_NO_EXPORT void
 
1688
HALF_frexp(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1689
{
 
1690
    UNARY_LOOP_TWO_OUT {
 
1691
        const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
1692
        *((npy_half *)op1) = npy_float_to_half(frexpf(in1, (int *)op2));
 
1693
    }
 
1694
}
 
1695
#endif
 
1696
 
 
1697
#ifdef HAVE_LDEXPF
 
1698
NPY_NO_EXPORT void
 
1699
HALF_ldexp(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1700
{
 
1701
    BINARY_LOOP {
 
1702
        const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
1703
        const int in2 = *(int *)ip2;
 
1704
        *((npy_half *)op1) = npy_float_to_half(ldexpf(in1, in2));
 
1705
    }
 
1706
}
 
1707
 
 
1708
NPY_NO_EXPORT void
 
1709
HALF_ldexp_long(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
 
1710
{
 
1711
    /*
 
1712
     * Additional loop to handle long integer inputs (cf. #866, #1633).
 
1713
     * long != int on many 64-bit platforms, so we need this second loop
 
1714
     * to handle the default integer type.
 
1715
     */
 
1716
    BINARY_LOOP {
 
1717
        const float in1 = npy_half_to_float(*(npy_half *)ip1);
 
1718
        const long in2 = *(long *)ip2;
 
1719
        if (((int)in2) == in2) {
 
1720
            /* Range OK */
 
1721
            *((npy_half *)op1) = npy_float_to_half(ldexpf(in1, ((int)in2)));
 
1722
        }
 
1723
        else {
 
1724
            /*
 
1725
             * Outside int range -- also ldexp will overflow in this case,
 
1726
             * given that exponent has less bits than int.
 
1727
             */
 
1728
            if (in2 > 0) {
 
1729
                *((npy_half *)op1) = npy_float_to_half(ldexpf(in1, NPY_MAX_INT));
 
1730
            }
 
1731
            else {
 
1732
                *((npy_half *)op1) = npy_float_to_half(ldexpf(in1, NPY_MIN_INT));
 
1733
            }
 
1734
        }
 
1735
    }
 
1736
}
 
1737
#endif
 
1738
 
 
1739
#define HALF_true_divide HALF_divide
 
1740
 
1162
1741
 
1163
1742
/*
1164
1743
 *****************************************************************************
1494
2073
    BINARY_LOOP {
1495
2074
        PyObject *in1 = *(PyObject **)ip1;
1496
2075
        PyObject *in2 = *(PyObject **)ip2;
1497
 
        int ret = PyObject_RichCompareBool(in1, in2, Py_@OP@);
 
2076
        int ret = PyObject_RichCompareBool(
 
2077
                            in1 ? in1 : Py_None,
 
2078
                            in2 ? in2 : Py_None, Py_@OP@);
1498
2079
        if (ret == -1) {
1499
2080
            return;
1500
2081
        }
1513
2094
        PyObject **out = (PyObject **)op1;
1514
2095
        int v;
1515
2096
        PyObject *ret;
1516
 
        PyObject_Cmp(in1, zero, &v);
 
2097
        PyObject_Cmp(in1 ? in1 : Py_None, zero, &v);
1517
2098
        ret = PyLong_FromLong(v);
1518
2099
        if (PyErr_Occurred()) {
1519
2100
            return;
1527
2108
    UNARY_LOOP {
1528
2109
        PyObject *in1 = *(PyObject **)ip1;
1529
2110
        PyObject **out = (PyObject **)op1;
1530
 
        PyObject *ret = PyInt_FromLong(PyObject_Compare(in1, zero));
 
2111
        PyObject *ret = PyInt_FromLong(
 
2112
                            PyObject_Compare(in1 ? in1 : Py_None, zero));
1531
2113
        if (PyErr_Occurred()) {
1532
2114
            return;
1533
2115
        }
1543
2125
 **                              END LOOPS                                  **
1544
2126
 *****************************************************************************
1545
2127
 */
1546
 
 
1547