1 /* 2 C99 compatibility for SciPy 3 4 The Rules: 5 - Every function definition must have compiler guard so that it is not defined twice. 6 - This file should only affect compilers that do not support C99 natively. 7 - All functions should be defined as "static" to limit linker conflicts. 8 */ 9 #ifndef SCIPY_C99_COMPAT 10 #define SCIPY_C99_COMPAT 11 #include <float.h> 12 13 #if defined(_MSC_VER) && _MSC_VER <= 1600 14 /* MSVC 2008 and MSVC 2010 */ 15 #ifndef isnan 16 #define isnan(x) _isnan((x)) 17 #endif 18 19 #ifndef signbit signbit(double x)20 static int signbit(double x) 21 { 22 return x > 0; 23 } 24 #endif 25 26 #ifndef copysign copysign(double x,double y)27 static double copysign(double x, double y) 28 { 29 if (x >= 0) { 30 if (y >= 0) { 31 return x; 32 } 33 else { 34 return -x; 35 } 36 } 37 else { 38 if (y >= 0) { 39 return -x; 40 } 41 else { 42 return x; 43 } 44 } 45 } 46 #endif 47 48 #ifndef fmax fmax(double x,double y)49 static double fmax(double x, double y) 50 { 51 /* z > nan for z != nan is required by C the standard */ 52 int xnan = isnan(x), ynan = isnan(y); 53 54 if (xnan || ynan) 55 { 56 if (xnan && !ynan) 57 return y; 58 if (!xnan && ynan) 59 return x; 60 return x; 61 } 62 63 /* +0 > -0 is preferred by C the standard */ 64 if (x == 0 && y == 0) 65 { 66 int xs = signbit(x), ys = signbit(y); 67 if (xs && !ys) 68 return y; 69 if (!xs && ys) 70 return x; 71 return x; 72 } 73 74 if (x > y) { 75 return x; 76 } 77 else { 78 return y; 79 } 80 } 81 #endif 82 83 #ifndef fmin fmin(double x,double y)84 static double fmin(double x, double y) 85 { 86 /* z > nan for z != nan is required by C the standard */ 87 int xnan = isnan(x), ynan = isnan(y); 88 89 if (xnan || ynan) 90 { 91 if (xnan && !ynan) 92 return y; 93 if (!xnan && ynan) 94 return x; 95 return x; 96 } 97 98 /* +0 > -0 is preferred by C the standard */ 99 if (x == 0 && y == 0) 100 { 101 int xs = signbit(x), ys = signbit(y); 102 if (xs && !ys) 103 return x; 104 if (!xs && ys) 105 return y; 106 return y; 107 } 108 109 if (x > y) { 110 return y; 111 } 112 else { 113 return x; 114 } 115 } 116 #endif 117 #endif 118 119 #if (__STDC_VERSION__ < 199901L) 120 /* Hopefully fail in fewer cases */ 121 122 /* For compilers which aren't MSVC and haven't defined isnan */ 123 #ifndef isnan 124 #define isnan(x) ((x) != (x)) 125 #endif 126 127 #ifndef isfinite 128 #ifdef _MSC_VER 129 /* MSVC 2015 and newer still don't have everything */ 130 #define isfinite(x) _finite((x)) 131 #else 132 #define isfinite(x) !isnan((x) + (-x)) 133 #endif 134 #endif 135 136 #ifndef isinf 137 #define isinf(x) (!isfinite(x) && !isnan(x)) 138 #endif 139 140 #ifndef fma 141 #define fma(x, y, z) ((x)*(y) + (z)) 142 #endif 143 #endif 144 145 /* 146 * portable isnan/isinf; in cmath only available in C++11 and npy_math 147 * versions don't work well (they get undef'd by cmath, see gh-5689) 148 * Implementation based on npy_math.h 149 */ 150 #ifndef sc_isnan 151 #define sc_isnan isnan 152 #endif 153 #ifndef sc_isinf 154 #define sc_isinf isinf 155 #endif 156 #ifndef sc_isfinite 157 #define sc_isfinite isfinite 158 #endif 159 #ifndef sc_fma 160 #define sc_fma fma 161 #endif 162 #endif 163