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