diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/include/numpy/ufuncobject.h | 5 | ||||
-rw-r--r-- | numpy/core/setup.py | 105 | ||||
-rw-r--r-- | numpy/core/src/_isnan.c | 46 | ||||
-rw-r--r-- | numpy/core/src/_signbit.c | 2 | ||||
-rw-r--r-- | numpy/core/src/math_c99.inc.src | 264 | ||||
-rw-r--r-- | numpy/core/src/umathmodule.c.src | 635 | ||||
-rw-r--r-- | numpy/distutils/command/config.py | 68 |
7 files changed, 444 insertions, 681 deletions
diff --git a/numpy/core/include/numpy/ufuncobject.h b/numpy/core/include/numpy/ufuncobject.h index 91f37f99c..96934b820 100644 --- a/numpy/core/include/numpy/ufuncobject.h +++ b/numpy/core/include/numpy/ufuncobject.h @@ -263,11 +263,6 @@ typedef struct _loop1d_info { | ((SW_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0); \ } -#define isnan(x) (_isnan((double)(x))) -#define isinf(x) ((_fpclass((double)(x)) == _FPCLASS_PINF) || \ - (_fpclass((double)(x)) == _FPCLASS_NINF)) -#define isfinite(x) (_finite((double) x)) - /* Solaris --------------------------------------------------------*/ /* --------ignoring SunOS ieee_flags approach, someone else can ** deal with that! */ diff --git a/numpy/core/setup.py b/numpy/core/setup.py index cd15d793e..9e3847cbf 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -5,20 +5,6 @@ from os.path import join from numpy.distutils import log from distutils.dep_util import newer -FUNCTIONS_TO_CHECK = [ - ('expl', 'HAVE_LONGDOUBLE_FUNCS'), - ('expf', 'HAVE_FLOAT_FUNCS'), - ('log1p', 'HAVE_LOG1P'), - ('expm1', 'HAVE_EXPM1'), - ('asinh', 'HAVE_INVERSE_HYPERBOLIC'), - ('atanhf', 'HAVE_INVERSE_HYPERBOLIC_FLOAT'), - ('atanhl', 'HAVE_INVERSE_HYPERBOLIC_LONGDOUBLE'), - ('isnan', 'HAVE_ISNAN'), - ('isinf', 'HAVE_ISINF'), - ('rint', 'HAVE_RINT'), - ('trunc', 'HAVE_TRUNC'), - ] - def is_npy_no_signal(): """Return True if the NPY_NO_SIGNAL symbol must be defined in configuration header.""" @@ -49,6 +35,75 @@ def is_npy_no_smp(): nosmp = 0 return nosmp == 1 +def check_math_capabilities(config, moredefs, mathlibs): + def check_func(func_name): + return config.check_func(func_name, libraries=mathlibs, + decl=True, call=True) + + def check_funcs_once(funcs_name): + decl = dict([(f, True) for f in funcs_name]) + st = config.check_funcs_once(funcs_name, libraries=mathlibs, + decl=decl, call=decl) + if st: + moredefs.extend([name_to_defsymb(f) for f in funcs_name]) + return st + + def check_funcs(funcs_name): + # Use check_funcs_once first, and if it does not work, test func per + # func. Return success only if all the functions are available + if not check_funcs_once(funcs_name): + # Global check failed, check func per func + for f in funcs_name: + if check_func(f): + moredefs.append(name_to_defsymb(f)) + return 0 + else: + return 1 + + def name_to_defsymb(name): + return "HAVE_%s" % name.upper() + + #use_msvc = config.check_decl("_MSC_VER") + + # Mandatory functions: if not found, fail the build + mandatory_funcs = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", + "floor", "ceil", "sqrt", "log10", "log", "exp", "asin", + "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp'] + + if not check_funcs_once(mandatory_funcs): + raise SystemError("One of the required function to build numpy is not" + " available (the list is %s)." % str(mandatory_funcs)) + + # Standard functions which may not be available and for which we have a + # replacement implementation + # XXX: we do not test for hypot because python checks for it (HAVE_HYPOT in + # python.h... I wish they would clean their public headers someday) + optional_stdfuncs = ["expm1", "log1p", "acosh", "asinh", "atanh", + "rint", "trunc"] + + check_funcs(optional_stdfuncs) + + # C99 functions: float and long double versions + c99_funcs = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor", + "ceil", "rint", "trunc", "sqrt", "log10", "log", "exp", + "expm1", "asin", "acos", "atan", "asinh", "acosh", "atanh", + "hypot", "atan2", "pow", "fmod", "modf", 'frexp', 'ldexp'] + + for prec in ['l', 'f']: + fns = [f + prec for f in c99_funcs] + check_funcs(fns) + + # Normally, isnan and isinf are macro (C99), but some platforms only have + # func, or both func and macro version. Check for macro only, and define + # replacement ones if not found. + # Note: including Python.h is necessary because it modifies some math.h + # definitions + for f in ["isnan", "isinf", "signbit", "isfinite"]: + st = config.check_decl(f, headers = ["Python.h", "math.h"]) + if st: + moredefs.append(name_to_defsymb("decl_%s" % f)) + + def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import Configuration,dot_join from numpy.distutils.system_info import get_info, default_lib_dirs @@ -106,14 +161,7 @@ def configuration(parent_package='',top_path=None): ext.libraries.extend(mathlibs) moredefs.append(('MATHLIB',','.join(mathlibs))) - def check_func(func_name): - return config_cmd.check_func(func_name, - libraries=mathlibs, decl=False, - headers=['math.h']) - - for func_name, defsymbol in FUNCTIONS_TO_CHECK: - if check_func(func_name): - moredefs.append(defsymbol) + check_math_capabilities(config_cmd, moredefs, mathlibs) if is_npy_no_signal(): moredefs.append('__NPY_PRIVATE_NO_SIGNAL') @@ -136,6 +184,17 @@ def configuration(parent_package='',top_path=None): target_f.write('#define %s\n' % (d)) else: target_f.write('#define %s %s\n' % (d[0],d[1])) + + # Keep those for backward compatibility for now + target_f.write(""" +#ifdef HAVE_EXPL +#define HAVE_LONGDOUBLE_FUNCS +#endif + +#ifdef HAVE_EXPF +#define HAVE_FLOAT_FUNCS +#endif +""") target_f.close() print 'File:',target target_f = open(target) @@ -264,7 +323,6 @@ def configuration(parent_package='',top_path=None): join('src','scalartypes.inc.src'), join('src','arraytypes.inc.src'), join('src','_signbit.c'), - join('src','_isnan.c'), join('src','ucsnarrow.c'), join('include','numpy','*object.h'), 'include/numpy/fenv/fenv.c', @@ -298,6 +356,7 @@ def configuration(parent_package='',top_path=None): generate_ufunc_api, join('src','scalartypes.inc.src'), join('src','arraytypes.inc.src'), + join('src','math_c99.inc.src'), ], depends = [join('src','ufuncobject.c'), generate_umath_py, diff --git a/numpy/core/src/_isnan.c b/numpy/core/src/_isnan.c deleted file mode 100644 index bff6e0a49..000000000 --- a/numpy/core/src/_isnan.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Adapted from cephes */ - -static int -isnan(double x) -{ - union - { - double d; - unsigned short s[4]; - unsigned int i[2]; - } u; - - u.d = x; - -#if SIZEOF_INT == 4 - -#ifdef WORDS_BIGENDIAN /* defined in pyconfig.h */ - if( ((u.i[0] & 0x7ff00000) == 0x7ff00000) - && (((u.i[0] & 0x000fffff) != 0) || (u.i[1] != 0))) - return 1; -#else - if( ((u.i[1] & 0x7ff00000) == 0x7ff00000) - && (((u.i[1] & 0x000fffff) != 0) || (u.i[0] != 0))) - return 1; -#endif - -#else /* SIZEOF_INT != 4 */ - -#ifdef WORDS_BIGENDIAN - if( (u.s[0] & 0x7ff0) == 0x7ff0) - { - if( ((u.s[0] & 0x000f) | u.s[1] | u.s[2] | u.s[3]) != 0 ) - return 1; - } -#else - if( (u.s[3] & 0x7ff0) == 0x7ff0) - { - if( ((u.s[3] & 0x000f) | u.s[2] | u.s[1] | u.s[0]) != 0 ) - return 1; - } -#endif - -#endif /* SIZEOF_INT */ - - return 0; -} diff --git a/numpy/core/src/_signbit.c b/numpy/core/src/_signbit.c index 2be3649fd..3074c2716 100644 --- a/numpy/core/src/_signbit.c +++ b/numpy/core/src/_signbit.c @@ -1,7 +1,7 @@ /* Adapted from cephes */ static int -signbit(double x) +signbit_d(double x) { union { diff --git a/numpy/core/src/math_c99.inc.src b/numpy/core/src/math_c99.inc.src new file mode 100644 index 000000000..14399f699 --- /dev/null +++ b/numpy/core/src/math_c99.inc.src @@ -0,0 +1,264 @@ +/* + * vim:syntax=c + * A small module to implement missing C99 math capabilities required by numpy + * + * Please keep this independant of python ! + */ + +/* + ***************************************************************************** + ** BASIC MATH FUNCTIONS ** + ***************************************************************************** + */ + +/* Original code by Konrad Hinsen. */ +#ifndef HAVE_EXPM1 +double expm1(double x) +{ + double u = exp(x); + if (u == 1.0) { + return x; + } else if (u-1.0 == -1.0) { + return -1; + } else { + return (u-1.0) * x/log(u); + } +} +#endif + +#ifndef HAVE_LOG1P +double log1p(double x) +{ + double u = 1. + x; + if (u == 1.0) { + return x; + } else { + return log(u) * x / (u-1.); + } +} +#endif + +#ifndef HAVE_HYPOT +double hypot(double x, double y) +{ + double yx; + + x = fabs(x); + y = fabs(y); + if (x < y) { + double temp = x; + x = y; + y = temp; + } + if (x == 0.) + return 0.; + else { + yx = y/x; + return x*sqrt(1.+yx*yx); + } +} +#endif + +#ifndef HAVE_ACOSH +double acosh(double x) +{ + return 2*log(sqrt((x+1.0)/2)+sqrt((x-1.0)/2)); +} +#endif + +#ifndef HAVE_ASINH +double asinh(double xx) +{ + double x, d; + int sign; + if (xx < 0.0) { + sign = -1; + x = -xx; + } + else { + sign = 1; + x = xx; + } + if (x > 1e8) { + d = x; + } else { + d = sqrt(x*x + 1); + } + return sign*log1p(x*(1.0 + x/(d+1))); +} +#endif + +#ifndef HAVE_ATANH +static double atanh(double x) +{ + return 0.5*log1p(2.0*x/(1.0-x)); +} +#endif + +#ifndef HAVE_RINT +double rint(double x) +{ + double y, r; + + y = floor(x); + r = x - y; + + if (r > 0.5) goto rndup; + + /* Round to nearest even */ + if (r==0.5) { + r = y - 2.0*floor(0.5*y); + if (r==1.0) { + rndup: + y+=1.0; + } + } + return y; +} +#endif + +#ifndef HAVE_TRUNC +double trunc(double x) +{ + if (x < 0) { + return ceil(x); + } + else { + return floor(x); + } + +} +#endif + +/* + ***************************************************************************** + ** IEEE 754 FPU HANDLING ** + ***************************************************************************** + */ +#if !defined(HAVE_DECL_ISNAN) + # define isnan(x) ((x) != (x)) +#endif + +/* VS 2003 with /Ox optimizes (x)-(x) to 0, which is not IEEE compliant. So we + * force (x) + (-x), which seems to work. */ +#if !defined(HAVE_DECL_ISFINITE) + # define isfinite(x) !isnan((x) + (-x)) +#endif + +#if !defined(HAVE_DECL_ISINF) +#define isinf(x) (!isfinite(x) && !isnan(x)) +#endif + +#if !defined(HAVE_DECL_SIGNBIT) + #include "_signbit.c" + # define signbit(x) \ + (sizeof (x) == sizeof (long double) ? signbit_ld (x) \ + : sizeof (x) == sizeof (double) ? signbit_d (x) \ + : signbit_f (x)) + +static int signbit_f (float x) +{ + return signbit_d((double)x); +} + +static int signbit_ld (long double x) +{ + return signbit_d((double)x); +} +#endif + +/* + * if C99 extensions not available then define dummy functions that use the + * double versions for + * + * sin, cos, tan + * sinh, cosh, tanh, + * fabs, floor, ceil, rint, trunc + * sqrt, log10, log, exp, expm1 + * asin, acos, atan, + * asinh, acosh, atanh + * + * hypot, atan2, pow, fmod, modf + * + * We assume the above are always available in their double versions. + * + * NOTE: some facilities may be available as macro only instead of functions. + * For simplicity, we define our own functions and undef the macros. We could + * instead test for the macro, but I am lazy to do that for now. + */ + +/* + * One value argument function + */ + +/**begin repeat + + #kind=(sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,rint,trunc,sqrt,log10,log,exp,expm1,asin,acos,atan,asinh,acosh,atanh,log1p)*2# + #KIND=(SIN,COS,TAN,SINH,COSH,TANH,FABS,FLOOR,CEIL,RINT,TRUNC,SQRT,LOG10,LOG,EXP,EXPM1,ASIN,ACOS,ATAN,ASINH,ACOSH,ATANH,LOG1P)*2# + #typ=longdouble*23, float*23# + #c=l*23,f*23# + #C=L*23,F*23# + #TYPE=LONGDOUBLE*23, FLOAT*23# +*/ + +#ifndef HAVE_@KIND@@C@ +#ifdef @kind@@c@ +#undef @kind@@c@ +#endif +@typ@ @kind@@c@(@typ@ x) +{ + return (@typ@) @kind@((double)x); +} +#endif +/**end repeat**/ + +/* + * Two values arguments function + */ + +/**begin repeat + + #kind=(atan2,hypot,pow,fmod)*2# + #KIND=(ATAN2,HYPOT,POW,FMOD)*2# + #typ=longdouble*4, float*4# + #c=l*4,f*4# + #C=L*4,F*4# + #TYPE=LONGDOUBLE*4,FLOAT*4# +*/ +#ifndef HAVE_@KIND@@C@ +#ifdef @kind@@c@ +#undef @kind@@c@ +#endif +@typ@ @kind@@c@(@typ@ x, @typ@ y) +{ + return (@typ@) @kind@((double)x, (double) y); +} +#endif +/**end repeat**/ + +/* + * One value - one pointer argument function + */ + +/**begin repeat + #kind=modf*2# + #KIND=MODF*2# + #c=l,f# + #C=L,F# + #typ=longdouble, float# + #TYPE=LONGDOUBLE, FLOAT# +*/ +#ifndef HAVE_@KIND@@C@ +#ifdef modf@c@ +#undef modf@c@ +#endif +@typ@ modf@c@(@typ@ x, @typ@ *iptr) +{ + double nx, niptr, y; + nx = (double) x; + y = modf(nx, &niptr); + *iptr = (@typ@) niptr; + return (@typ@) y; +} +#endif +/**end repeat**/ diff --git a/numpy/core/src/umathmodule.c.src b/numpy/core/src/umathmodule.c.src index 77675c441..4d7734cca 100644 --- a/numpy/core/src/umathmodule.c.src +++ b/numpy/core/src/umathmodule.c.src @@ -1,6 +1,10 @@ /* -*- c -*- */ /* + * vim:syntax=c + */ + +/* ***************************************************************************** ** INCLUDES ** ***************************************************************************** @@ -13,435 +17,10 @@ #include "config.h" #include <math.h> -/* - ***************************************************************************** - ** BASIC MATH FUNCTIONS ** - ***************************************************************************** - */ - -/* A whole slew of basic math functions are provided originally - by Konrad Hinsen. */ - -#if !defined(__STDC__) && !defined(_MSC_VER) -extern double fmod (double, double); -extern double frexp (double, int *); -extern double ldexp (double, int); -extern double modf (double, double *); -#endif #ifndef M_PI #define M_PI 3.14159265358979323846264338328 #endif - - -#if defined(DISTUTILS_USE_SDK) -/* win32 on AMD64 build architecture */ -/* See also http://projects.scipy.org/scipy/numpy/ticket/164 */ -#ifndef HAVE_FABSF -#ifdef fabsf -#undef fabsf -#endif -static float fabsf(float x) -{ - return (float)fabs((double)(x)); -} -#endif -#ifndef HAVE_HYPOTF -static float hypotf(float x, float y) -{ - return (float)hypot((double)(x), (double)(y)); -} -#endif -#ifndef HAVE_RINTF -#ifndef HAVE_RINT -static double rint (double x); -#endif -static float rintf(float x) -{ - return (float)rint((double)(x)); -} -#endif -#ifndef HAVE_FREXPF -static float frexpf(float x, int * i) -{ - return (float)frexp((double)(x), i); -} -#endif -#ifndef HAVE_LDEXPF -static float ldexpf(float x, int i) -{ - return (float)ldexp((double)(x), i); -} -#endif -#define tanhf nc_tanhf -#endif - -#ifndef HAVE_INVERSE_HYPERBOLIC -static double acosh(double x) -{ - return 2*log(sqrt((x+1.0)/2)+sqrt((x-1.0)/2)); -} - -double log1p(double); -static double asinh(double xx) -{ - double x, d; - int sign; - if (xx < 0.0) { - sign = -1; - x = -xx; - } - else { - sign = 1; - x = xx; - } - if (x > 1e8) { - d = x; - } else { - d = sqrt(x*x + 1); - } - return sign*log1p(x*(1.0 + x/(d+1))); -} - -static double atanh(double x) -{ - return 0.5*log1p(2.0*x/(1.0-x)); -} -#endif - -#if !defined(HAVE_INVERSE_HYPERBOLIC_FLOAT) -#ifdef HAVE_FLOAT_FUNCS -#ifdef log1pf -#undef log1pf -#endif -#ifdef logf -#undef logf -#endif -#ifdef sqrtf -#undef sqrtf -#endif -float log1pf(float); -#ifdef DISTUTILS_USE_SDK -DL_IMPORT(float) logf(float); -DL_IMPORT(float) sqrtf(float); -#else -/* should these be extern?: */ -float logf(float); -float sqrtf(float); -#endif -#ifdef acoshf -#undef acoshf -#endif -static float acoshf(float x) -{ - return 2*logf(sqrtf((x+1)/2)+sqrtf((x-1)/2)); -} - -#ifdef asinhf -#undef asinhf -#endif -static float asinhf(float xx) -{ - float x, d; - int sign; - if (xx < 0) { - sign = -1; - x = -xx; - } - else { - sign = 1; - x = xx; - } - if (x > 1e5) { - d = x; - } else { - d = sqrtf(x*x + 1); - } - return sign*log1pf(x*(1 + x/(d+1))); -} - -#ifdef atanhf -#undef atanhf -#endif -static float atanhf(float x) -{ - return log1pf(2*x/(1-x))/2; -} -#else -#ifdef acoshf -#undef acoshf -#endif -static float acoshf(float x) -{ - return (float)acosh((double)(x)); -} - -#ifdef asinhf -#undef asinhf -#endif -static float asinhf(float x) -{ - return (float)asinh((double)(x)); -} - -#ifdef atanhf -#undef atanhf -#endif -static float atanhf(float x) -{ - return (float)atanh((double)(x)); -} -#endif -#endif - - -#if !defined(HAVE_INVERSE_HYPERBOLIC_LONGDOUBLE) -#ifdef HAVE_LONGDOUBLE_FUNCS -#ifdef logl -#undef logl -#endif -#ifdef sqrtl -#undef sqrtl -#endif -#ifdef log1pl -#undef log1pl -#endif -longdouble logl(longdouble); -longdouble sqrtl(longdouble); -longdouble log1pl(longdouble); -#ifdef acoshl -#undef acoshl -#endif -static longdouble acoshl(longdouble x) -{ - return 2*logl(sqrtl((x+1.0)/2)+sqrtl((x-1.0)/2)); -} - -#ifdef asinhl -#undef asinhl -#endif -static longdouble asinhl(longdouble xx) -{ - longdouble x, d; - int sign; - if (xx < 0.0) { - sign = -1; - x = -xx; - } - else { - sign = 1; - x = xx; - } - if (x > 1e17) { - d = x; - } else { - d = sqrtl(x*x + 1); - } - return sign*log1pl(x*(1.0 + x/(d+1))); -} - -#ifdef atanhl -#undef atanhl -#endif -static longdouble atanhl(longdouble x) -{ - return 0.5*log1pl(2.0*x/(1.0-x)); -} - -#else - -#ifdef acoshl -#undef acoshl -#endif -static longdouble acoshl(longdouble x) -{ - return (longdouble)acosh((double)(x)); -} - -#ifdef asinhl -#undef asinhl -#endif -static longdouble asinhl(longdouble x) -{ - return (longdouble)asinh((double)(x)); -} - -#ifdef atanhl -#undef atanhl -#endif -static longdouble atanhl(longdouble x) -{ - return (longdouble)atanh((double)(x)); -} - -#endif -#endif - - -#ifdef HAVE_HYPOT -#if !defined(NeXT) && !defined(_MSC_VER) -extern double hypot(double, double); -#endif -#else -static double hypot(double x, double y) -{ - double yx; - - x = fabs(x); - y = fabs(y); - if (x < y) { - double temp = x; - x = y; - y = temp; - } - if (x == 0.) - return 0.; - else { - yx = y/x; - return x*sqrt(1.+yx*yx); - } -} -#endif - -#ifndef HAVE_RINT -/* needs cleanup */ -static double -rint(double x) -{ - double y, r; - - y = floor(x); - r = x - y; - - if (r > 0.5) goto rndup; - - /* Round to nearest even */ - if (r==0.5) { - r = y - 2.0*floor(0.5*y); - if (r==1.0) { - rndup: - y+=1.0; - } - } - return y; -} -#endif - -/* - * Comment out trunc definition until build problems are fixed. - */ -/* -#ifndef HAVE_TRUNC -static double -trunc(double x) -{ - if (x < 0) { - return ceil(x); - } - else { - return floor(x); - } - -} -#endif -*/ - - - - -/* Define isnan, isinf, isfinite, signbit if needed */ -/* Use fpclassify if possible */ -/* isnan, isinf -- - these will use macros and then fpclassify if available before - defaulting to a dumb convert-to-double version... - - isfinite -- define a macro if not already available - signbit -- if macro available use it, otherwise define a function - and a dumb convert-to-double version for other types. -*/ - -#if defined(fpclassify) - -#if !defined(isnan) -#define isnan(x) (fpclassify(x) == FP_NAN) -#endif -#if !defined(isinf) -#define isinf(x) (fpclassify(x) == FP_INFINITE) -#endif - -#else /* check to see if already have a function like this */ - -#if !defined(HAVE_ISNAN) - -#if !defined(isnan) -#include "_isnan.c" -#endif -#endif /* HAVE_ISNAN */ - -#if !defined(HAVE_ISINF) -#if !defined(isinf) -#define isinf(x) (!isnan((x)) && isnan((x)-(x))) -#endif -#endif /* HAVE_ISINF */ - -#endif /* defined(fpclassify) */ - - -/* Define signbit if needed */ -#if !defined(signbit) -#include "_signbit.c" -#endif - -/* Now defined the extended type macros */ - -#if !defined(isnan) - -#if !defined(HAVE_LONGDOUBLE_FUNCS) || !defined(HAVE_ISNAN) -#define isnanl(x) isnan((double)(x)) -#endif - -#if !defined(HAVE_FLOAT_FUNCS) || !defined(HAVE_ISNAN) -#define isnanf(x) isnan((double)(x)) -#endif - -#else /* !defined(isnan) */ - -#define isnanl(x) isnan((x)) -#define isnanf(x) isnan((x)) - -#endif /* !defined(isnan) */ - - -#if !defined(isinf) - -#if !defined(HAVE_LONGDOUBLE_FUNCS) || !defined(HAVE_ISINF) -#define isinfl(x) (!isnanl((x)) && isnanl((x)-(x))) -#endif - -#if !defined(HAVE_FLOAT_FUNCS) || !defined(HAVE_ISINF) -#define isinff(x) (!isnanf((x)) && isnanf((x)-(x))) -#endif - -#else /* !defined(isinf) */ - -#define isinfl(x) isinf((x)) -#define isinff(x) isinf((x)) - -#endif /* !defined(isinf) */ - - -#if !defined(signbit) -#define signbitl(x) ((longdouble) signbit((double)(x))) -#define signbitf(x) ((float) signbit((double) (x))) -#else -#define signbitl(x) signbit((x)) -#define signbitf(x) signbit((x)) -#endif - -#if !defined(isfinite) -#define isfinite(x) (!(isinf((x)) || isnan((x)))) -#endif -#define isfinitef(x) (!(isinff((x)) || isnanf((x)))) -#define isfinitel(x) (!(isinfl((x)) || isnanl((x)))) +#include "math_c99.inc" float degreesf(float x) { return x * (float)(180.0/M_PI); @@ -463,168 +42,6 @@ longdouble radiansl(longdouble x) { return x * (M_PI/180.0L); } -/* First, the C functions that do the real work */ - -/* if C99 extensions not available then define dummy functions that use the - double versions for - - sin, cos, tan - sinh, cosh, tanh, - fabs, floor, ceil, fmod, sqrt, log10, log, exp, fabs - asin, acos, atan, - asinh, acosh, atanh - - hypot, atan2, pow -*/ - -/**begin repeat - - #kind=(sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,sqrt,log10,log,exp,asin,acos,atan,rint)*2# - #typ=longdouble*17, float*17# - #c=l*17,f*17# - #TYPE=LONGDOUBLE*17, FLOAT*17# -*/ - -#ifndef HAVE_@TYPE@_FUNCS -#ifdef @kind@@c@ -#undef @kind@@c@ -#endif -@typ@ @kind@@c@(@typ@ x) { - return (@typ@) @kind@((double)x); -} -#endif -/**end repeat**/ - -/**begin repeat - - #kind=(atan2,hypot,pow,fmod)*2# - #typ=longdouble*4, float*4# - #c=l*4,f*4# - #TYPE=LONGDOUBLE*4,FLOAT*4# -*/ -#ifndef HAVE_@TYPE@_FUNCS -#ifdef @kind@@c@ -#undef @kind@@c@ -#endif -@typ@ @kind@@c@(@typ@ x, @typ@ y) { - return (@typ@) @kind@((double)x, (double) y); -} -#endif -/**end repeat**/ - -/**begin repeat - #kind=modf*2# - #typ=longdouble, float# - #c=l,f# - #TYPE=LONGDOUBLE, FLOAT# -*/ -#ifndef HAVE_@TYPE@_FUNCS -#ifdef modf@c@ -#undef modf@c@ -#endif -@typ@ modf@c@(@typ@ x, @typ@ *iptr) { - double nx, niptr, y; - nx = (double) x; - y = modf(nx, &niptr); - *iptr = (@typ@) niptr; - return (@typ@) y; -} -#endif -/**end repeat**/ - - - -#ifndef HAVE_LOG1P -double log1p(double x) -{ - double u = 1. + x; - if (u == 1.0) { - return x; - } else { - return log(u) * x / (u-1.); - } -} -#endif - -#if !defined(HAVE_LOG1P) || !defined(HAVE_LONGDOUBLE_FUNCS) -#ifdef log1pl -#undef log1pl -#endif -longdouble log1pl(longdouble x) -{ - longdouble u = 1. + x; - if (u == 1.0) { - return x; - } else { - return logl(u) * x / (u-1.); - } -} -#endif - -#if !defined(HAVE_LOG1P) || !defined(HAVE_FLOAT_FUNCS) -#ifdef log1pf -#undef log1pf -#endif -float log1pf(float x) -{ - float u = 1 + x; - if (u == 1) { - return x; - } else { - return logf(u) * x / (u-1); - } -} -#endif - -#ifndef HAVE_EXPM1 -static double expm1(double x) -{ - double u = exp(x); - if (u == 1.0) { - return x; - } else if (u-1.0 == -1.0) { - return -1; - } else { - return (u-1.0) * x/log(u); - } -} -#endif - -#if !defined(HAVE_EXPM1) || !defined(HAVE_LONGDOUBLE_FUNCS) -#ifdef expml1 -#undef expml1 -#endif -static longdouble expm1l(longdouble x) -{ - longdouble u = expl(x); - if (u == 1.0) { - return x; - } else if (u-1.0 == -1.0) { - return -1; - } else { - return (u-1.0) * x/logl(u); - } -} -#endif - -#if !defined(HAVE_EXPM1) || !defined(HAVE_FLOAT_FUNCS) -#ifdef expm1f -#undef expm1f -#endif -static float expm1f(float x) -{ - float u = expf(x); - if (u == 1) { - return x; - } else if (u-1 == -1) { - return -1; - } else { - return (u-1) * x/logf(u); - } -} -#endif - - /* ***************************************************************************** ** COMPLEX FUNCTIONS ** @@ -2047,7 +1464,6 @@ static void #kind=isnan*3, isinf*3, isfinite*3, signbit*3# #TYPE=(FLOAT, DOUBLE, LONGDOUBLE)*4# #typ=(float, double, longdouble)*4# - #c=(f,,l)*4# */ static void @TYPE@_@kind@(char **args, intp *dimensions, intp *steps, void *func) @@ -2056,7 +1472,7 @@ static void intp is=steps[0], os=steps[1], n=dimensions[0]; char *ip=args[0], *op=args[1]; for(i=0; i<n; i++, ip+=is, op+=os) { - *((Bool *)op) = (Bool) (@kind@@c@(*((@typ@ *)ip)) != 0); + *((Bool *)op) = (Bool) (@kind@(*((@typ@ *)ip)) != 0); } } /**end repeat**/ @@ -2066,7 +1482,6 @@ static void #kind=isnan*3, isinf*3, isfinite*3# #TYPE=(CFLOAT, CDOUBLE, CLONGDOUBLE)*3# #typ=(float, double, longdouble)*3# - #c=(f,,l)*3# #OP=||*6,&&*3# */ static void @@ -2076,8 +1491,8 @@ static void intp is=steps[0], os=steps[1], n=dimensions[0]; char *ip=args[0], *op=args[1]; for(i=0; i<n; i++, ip+=is, op+=os) { - *((Bool *)op) = @kind@@c@(((@typ@ *)ip)[0]) @OP@ \ - @kind@@c@(((@typ@ *)ip)[1]); + *((Bool *)op) = @kind@(((@typ@ *)ip)[0]) @OP@ \ + @kind@(((@typ@ *)ip)[1]); } } /**end repeat**/ @@ -2108,13 +1523,13 @@ static void } /**end repeat**/ -#define HAVE_DOUBLE_FUNCS /**begin repeat #TYPE=FLOAT, DOUBLE, LONGDOUBLE# #typ=float, double, longdouble# #c=f,,l# + #C=F,,L# */ -#ifdef HAVE_@TYPE@_FUNCS +#ifdef HAVE_FREXP@C@ static void @TYPE@_frexp(char **args, intp *dimensions, intp *steps, void *func) { @@ -2130,7 +1545,9 @@ static void *((int *) op2) = y2; } } +#endif +#ifdef HAVE_LDEXP@C@ static void @TYPE@_ldexp(char **args, intp *dimensions, intp *steps, void *func) { @@ -2148,47 +1565,46 @@ static void } #endif /**end repeat**/ -#undef HAVE_DOUBLE_FUNCS static PyUFuncGenericFunction frexp_functions[] = { -#ifdef HAVE_FLOAT_FUNCS +#ifdef HAVE_FREXPF FLOAT_frexp, #endif DOUBLE_frexp -#ifdef HAVE_LONGDOUBLE_FUNCS +#ifdef HAVE_FREXPL ,LONGDOUBLE_frexp #endif }; static void * blank3_data[] = { (void *)NULL, (void *)NULL, (void *)NULL}; static char frexp_signatures[] = { -#ifdef HAVE_FLOAT_FUNCS +#ifdef HAVE_FREXPF PyArray_FLOAT, PyArray_FLOAT, PyArray_INT, #endif PyArray_DOUBLE, PyArray_DOUBLE, PyArray_INT -#ifdef HAVE_LONGDOUBLE_FUNCS +#ifdef HAVE_FREXPL ,PyArray_LONGDOUBLE, PyArray_LONGDOUBLE, PyArray_INT #endif }; static PyUFuncGenericFunction ldexp_functions[] = { -#ifdef HAVE_FLOAT_FUNCS +#ifdef HAVE_LDEXPF FLOAT_ldexp, #endif DOUBLE_ldexp -#ifdef HAVE_LONGDOUBLE_FUNCS +#ifdef HAVE_LDEXPL ,LONGDOUBLE_ldexp #endif }; static char ldexp_signatures[] = { -#ifdef HAVE_FLOAT_FUNCS +#ifdef HAVE_LDEXPF PyArray_FLOAT, PyArray_INT, PyArray_FLOAT, #endif PyArray_DOUBLE, PyArray_INT, PyArray_DOUBLE -#ifdef HAVE_LONGDOUBLE_FUNCS +#ifdef HAVE_LDEXPL ,PyArray_LONGDOUBLE, PyArray_INT, PyArray_LONGDOUBLE #endif }; @@ -2241,10 +1657,10 @@ InitOtherOperators(PyObject *dictionary) { PyObject *f; int num=1; -#ifdef HAVE_LONGDOUBLE_FUNCS +#ifdef HAVE_FREXPL num += 1; #endif -#ifdef HAVE_FLOAT_FUNCS +#ifdef HAVE_FREXPF num += 1; #endif f = PyUFunc_FromFuncAndData(frexp_functions, blank3_data, @@ -2255,6 +1671,13 @@ InitOtherOperators(PyObject *dictionary) { PyDict_SetItemString(dictionary, "frexp", f); Py_DECREF(f); + num = 1; +#ifdef HAVE_LDEXPL + num += 1; +#endif +#ifdef HAVE_LDEXPF + num += 1; +#endif f = PyUFunc_FromFuncAndData(ldexp_functions, blank3_data, ldexp_signatures, num, 2, 1, PyUFunc_None, "ldexp", "Compute y = x1 * 2**x2.",0); diff --git a/numpy/distutils/command/config.py b/numpy/distutils/command/config.py index ce42a36e0..5170bfcb0 100644 --- a/numpy/distutils/command/config.py +++ b/numpy/distutils/command/config.py @@ -126,6 +126,13 @@ int main() body = [] if decl: body.append("int %s ();" % func) + # Handle MSVC intrisincs: force MS compiler to make a function call. + # Useful to test for some functions when built with optimization on, to + # avoid build error because the intrisinc and our 'fake' test + # declaration do not match. + body.append("#ifdef _MSC_VER") + body.append("#pragma function(%s)" % func) + body.append("#endif") body.append("int main (void) {") if call: if call_args is None: @@ -140,6 +147,67 @@ int main() return self.try_link(body, headers, include_dirs, libraries, library_dirs) + def check_funcs_once(self, funcs, + headers=None, include_dirs=None, + libraries=None, library_dirs=None, + decl=False, call=False, call_args=None): + """Check a list of functions at once. + + This is useful to speed up things, since all the functions in the funcs + list will be put in one compilation unit. + + Arguments + --------- + + funcs: seq + list of functions to test + include_dirs : seq + list of header paths + libraries : seq + list of libraries to link the code snippet to + libraru_dirs : seq + list of library paths + decl : dict + for every (key, value), the declaration in the value will be + used for function in key. If a function is not in the + dictionay, no declaration will be used. + call : dict + for every item (f, value), if the value is True, a call will be + done to the function f""" + self._check_compiler() + body = [] + if decl: + for f, v in decl.items(): + if v: + body.append("int %s ();" % f) + + # Handle MS intrinsics. See check_func for more info. + body.append("#ifdef _MSC_VER") + for func in funcs: + body.append("#pragma function(%s)" % func) + body.append("#endif") + + body.append("int main (void) {") + if call: + for f in funcs: + if call.has_key(f) and call[f]: + if not (call_args and call_args.has_key(f) and call_args[f]): + args = '' + else: + args = call_args[f] + body.append(" %s(%s);" % (f, args)) + else: + body.append(" %s;" % f) + else: + for f in funcs: + body.append(" %s;" % f) + body.append(" return 0;") + body.append("}") + body = '\n'.join(body) + "\n" + + return self.try_link(body, headers, include_dirs, + libraries, library_dirs) + def get_output(self, body, headers=None, include_dirs=None, libraries=None, library_dirs=None, lang="c"): |