|
114 | 114 | #include <stdio.h>
|
115 | 115 |
|
116 | 116 | static inline npy_double spacing(npy_double x) {
|
117 |
| - return nextafter(x, HUGE_VAL) - x; |
| 117 | + if (isinf(x)) |
| 118 | + return ((npy_double) NAN); |
| 119 | + return copysign(nextafter(fabs(x), ((npy_double) INFINITY)), x) - x; |
118 | 120 | }
|
119 | 121 |
|
120 | 122 | static inline npy_float spacingf(npy_float x) {
|
121 |
| - return nextafterf(x, HUGE_VALF) - x; |
| 123 | + if (isinff(x)) |
| 124 | + return ((npy_float) NAN); |
| 125 | + |
| 126 | + return copysignf(nextafterf(fabsf(x), INFINITY), x) - x; |
122 | 127 | }
|
123 | 128 |
|
124 |
| -static inline npy_double divmod(npy_double x1, npy_double x2, npy_double *mod) { |
125 |
| - npy_double q = floor(x1 / x2); |
126 | 129 |
|
127 |
| - *mod = x1 - q * x2; |
| 130 | +/**begin repeat |
| 131 | + * Float types |
| 132 | + * #type = npy_float, npy_double# |
| 133 | + * #c = f, # |
| 134 | + */ |
| 135 | +/* |
| 136 | + * Python version of divmod. |
| 137 | + * |
| 138 | + * The implementation is mostly copied from cpython 3.5. |
| 139 | + */ |
| 140 | +static inline @type@ |
| 141 | +divmod@c@(@type@ a, @type@ b, @type@ *modulus) |
| 142 | +{ |
| 143 | + @type@ div, mod, floordiv; |
128 | 144 |
|
129 |
| - return q; |
130 |
| -} |
| 145 | + mod = fmod@c@(a, b); |
131 | 146 |
|
132 |
| -static inline npy_float divmodf(npy_float x1, npy_float x2, npy_float *mod) { |
133 |
| - npy_float q = floorf(x1 / x2); |
| 147 | + if (!b) { |
| 148 | + /* If b == 0, return result of fmod. For IEEE is nan */ |
| 149 | + *modulus = mod; |
| 150 | + return mod; |
| 151 | + } |
134 | 152 |
|
135 |
| - *mod = x1 - q * x2; |
| 153 | + /* a - mod should be very nearly an integer multiple of b */ |
| 154 | + div = (a - mod) / b; |
136 | 155 |
|
137 |
| - return q; |
| 156 | + /* adjust fmod result to conform to Python convention of remainder */ |
| 157 | + if (mod) { |
| 158 | + if ((b < 0) != (mod < 0)) { |
| 159 | + mod += b; |
| 160 | + div -= 1.0@c@; |
| 161 | + } |
| 162 | + } |
| 163 | + else { |
| 164 | + /* if mod is zero ensure correct sign */ |
| 165 | + mod = copysign@c@(0, b); |
| 166 | + } |
| 167 | + |
| 168 | + /* snap quotient to nearest integral value */ |
| 169 | + if (div) { |
| 170 | + floordiv = floor@c@(div); |
| 171 | + if (div - floordiv > 0.5@c@) |
| 172 | + floordiv += 1.0@c@; |
| 173 | + } |
| 174 | + else { |
| 175 | + /* if div is zero ensure correct sign */ |
| 176 | + floordiv = copysign@c@(0, a/b); |
| 177 | + } |
| 178 | + |
| 179 | + *modulus = mod; |
| 180 | + return floordiv; |
138 | 181 | }
|
| 182 | +/**end repeat**/ |
139 | 183 |
|
140 | 184 | /*
|
141 | 185 | *****************************************************************************
|
@@ -1732,7 +1776,7 @@ NPY_NO_EXPORT void
|
1732 | 1776 | {
|
1733 | 1777 | UNARY_LOOP {
|
1734 | 1778 | const @type@ in1 = *(@type@ *)ip1;
|
1735 |
| - *((@type@ *)op1) = (nextafter@c@(in1, HUGE_VAL)) - in1; |
| 1779 | + *((@type@ *)op1) = (spacing@c@(in1)); |
1736 | 1780 | }
|
1737 | 1781 | }
|
1738 | 1782 |
|
|
0 commit comments