Skip to content

Commit 2c4cc10

Browse files
committed
restore atan2 implementation, clean up c99 mandatory functions
1 parent 759e0cd commit 2c4cc10

File tree

3 files changed

+116
-30
lines changed

3 files changed

+116
-30
lines changed

numpy/core/setup.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,6 @@ def check_funcs(funcs_name, headers=["feature_detection_math.h"]):
243243
m = fn.replace("(", "_").replace(")", "_")
244244
moredefs.append((fname2def(m), 1))
245245

246-
# C99 functions: float and long double versions
247-
check_funcs(C99_FUNCS_SINGLE)
248-
check_funcs(C99_FUNCS_EXTENDED)
249-
250246
def check_complex(config, mathlibs):
251247
priv = []
252248
pub = []

numpy/core/setup_common.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,28 @@ def set_sig(sig):
120120
set_sig(line)
121121

122122
# Mandatory functions: if not found, fail the build
123-
MANDATORY_FUNCS = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs",
124-
"floor", "ceil", "sqrt", "log10", "log", "exp", "asin",
125-
"acos", "atan", "fmod", 'modf', 'frexp', 'ldexp',
126-
"expm1", "log1p", "acosh", "asinh", "atanh",
127-
"rint", "trunc", "exp2", "atan2",
128-
"copysign", "nextafter", "strtoll", "strtoull", "cbrt"]
123+
MANDATORY_FUNCS = [
124+
"sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs",
125+
"floor", "ceil", "sqrt", "log10", "log", "exp", "asin",
126+
"acos", "atan", "fmod", 'modf', 'frexp', 'ldexp',
127+
"expm1", "log1p", "acosh", "asinh", "atanh",
128+
"rint", "trunc", "exp2",
129+
"copysign", "nextafter", "strtoll", "strtoull", "cbrt",
130+
# C99, mandatory
131+
"sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor", "ceil",
132+
"rint", "trunc", "sqrt", "log10", "log", "log1p", "exp", "expm1",
133+
"asin", "acos", "atan", "asinh", "acosh", "atanh",
134+
]
129135

130136
OPTIONAL_STDFUNCS = [
131-
# cygwin
132-
"log2",
133-
# macos for powl
134-
"pow",
135-
# 32-bit windows
136-
"hypot"
137+
# cygwin
138+
"log2",
139+
# macos for powl
140+
"pow",
141+
# 32-bit windows
142+
"hypot",
143+
# 32-bit mingw, visual studio 2015
144+
"atan2",
137145
]
138146

139147
OPTIONAL_LOCALE_FUNCS = ["strtold_l"]
@@ -238,16 +246,6 @@ def set_sig(sig):
238246
"ftello", "fseeko"
239247
]
240248

241-
# C99 functions: float and long double versions
242-
C99_FUNCS = [
243-
"sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor", "ceil",
244-
"rint", "trunc", "sqrt", "log10", "log", "log1p", "exp", "expm1",
245-
"asin", "acos", "atan", "asinh", "acosh", "atanh", "hypot", "atan2",
246-
"pow", "fmod", "modf", 'frexp', 'ldexp', "exp2", "log2", "copysign",
247-
"nextafter", "cbrt"
248-
]
249-
C99_FUNCS_SINGLE = [f + 'f' for f in C99_FUNCS]
250-
C99_FUNCS_EXTENDED = [f + 'l' for f in C99_FUNCS]
251249
C99_COMPLEX_TYPES = [
252250
'complex double', 'complex float', 'complex long double'
253251
]

numpy/core/src/npymath/npy_math_internal.h.src

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,98 @@ NPY_INPLACE double npy_log2(double x)
126126
#endif
127127
}
128128

129+
/* Taken from FreeBSD mlib, adapted for numpy
130+
*
131+
* XXX: we could be a bit faster by reusing high/low words for inf/nan
132+
* classification instead of calling npy_isinf/npy_isnan: we should have some
133+
* macros for this, though, instead of doing it manually
134+
*/
135+
/* XXX: we should have this in npy_math.h */
136+
#define NPY_DBL_EPSILON 1.2246467991473531772E-16
137+
NPY_INPLACE double npy_atan2(double y, double x)
138+
{
139+
#ifdef HAVE_ATAN2
140+
return atan2(y, x);
141+
#else
142+
npy_int32 k, m, iy, ix, hx, hy;
143+
npy_uint32 lx,ly;
144+
double z;
145+
146+
EXTRACT_WORDS(hx, lx, x);
147+
ix = hx & 0x7fffffff;
148+
EXTRACT_WORDS(hy, ly, y);
149+
iy = hy & 0x7fffffff;
150+
151+
/* if x or y is nan, return nan */
152+
if (npy_isnan(x * y)) {
153+
return x + y;
154+
}
155+
156+
if (x == 1.0) {
157+
return npy_atan(y);
158+
}
159+
160+
m = 2 * (npy_signbit((x)) != 0) + (npy_signbit((y)) != 0);
161+
if (y == 0.0) {
162+
switch(m) {
163+
case 0:
164+
case 1: return y; /* atan(+-0,+anything)=+-0 */
165+
case 2: return NPY_PI;/* atan(+0,-anything) = pi */
166+
case 3: return -NPY_PI;/* atan(-0,-anything) =-pi */
167+
}
168+
}
169+
170+
if (x == 0.0) {
171+
return y > 0 ? NPY_PI_2 : -NPY_PI_2;
172+
}
173+
174+
if (npy_isinf(x)) {
175+
if (npy_isinf(y)) {
176+
switch(m) {
177+
case 0: return NPY_PI_4;/* atan(+INF,+INF) */
178+
case 1: return -NPY_PI_4;/* atan(-INF,+INF) */
179+
case 2: return 3.0*NPY_PI_4;/*atan(+INF,-INF)*/
180+
case 3: return -3.0*NPY_PI_4;/*atan(-INF,-INF)*/
181+
}
182+
} else {
183+
switch(m) {
184+
case 0: return NPY_PZERO; /* atan(+...,+INF) */
185+
case 1: return NPY_NZERO; /* atan(-...,+INF) */
186+
case 2: return NPY_PI; /* atan(+...,-INF) */
187+
case 3: return -NPY_PI; /* atan(-...,-INF) */
188+
}
189+
}
190+
}
191+
192+
if (npy_isinf(y)) {
193+
return y > 0 ? NPY_PI_2 : -NPY_PI_2;
194+
}
195+
196+
/* compute y/x */
197+
k = (iy - ix) >> 20;
198+
if (k > 60) { /* |y/x| > 2**60 */
199+
z = NPY_PI_2 + 0.5 * NPY_DBL_EPSILON;
200+
m &= 1;
201+
} else if (hx < 0 && k < -60) {
202+
z = 0.0; /* 0 > |y|/x > -2**-60 */
203+
} else {
204+
z = npy_atan(npy_fabs(y/x)); /* safe to do y/x */
205+
}
206+
207+
switch (m) {
208+
case 0: return z ; /* atan(+,+) */
209+
case 1: return -z ; /* atan(-,+) */
210+
case 2: return NPY_PI - (z - NPY_DBL_EPSILON);/* atan(+,-) */
211+
default: /* case 3 */
212+
return (z - NPY_DBL_EPSILON) - NPY_PI;/* atan(-,-) */
213+
}
214+
#endif
215+
}
216+
217+
218+
219+
220+
129221
NPY_INPLACE double npy_hypot(double x, double y)
130222
{
131223
#ifdef HAVE_HYPOT
@@ -228,8 +320,8 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x)
228320
/* C99 mandatory */
229321

230322
/**begin repeat1
231-
* #kind = atan2,fmod,copysign#
232-
* #KIND = ATAN2,FMOD,COPYSIGN#
323+
* #kind = fmod,copysign#
324+
* #KIND = FMOD,COPYSIGN#
233325
*/
234326
NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y)
235327
{
@@ -301,8 +393,8 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x)
301393

302394

303395
/**begin repeat1
304-
* #kind = hypot,pow#
305-
* #KIND = HYPOT,POW#
396+
* #kind = atan2,hypot,pow#
397+
* #KIND = ATAN2,HYPOT,POW#
306398
*/
307399
#ifdef @kind@@c@
308400
#undef @kind@@c@

0 commit comments

Comments
 (0)