xref: /reactos/sdk/include/crt/mingw_math.h (revision 8a978a17)
1 
2 #ifndef __GNUC__
3 #error This file should be included only with GCC compiler
4 #endif
5 
6 #ifndef __NO_ISOCEXT
7 #if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
8 	|| !defined __STRICT_ANSI__ || defined __cplusplus
9 
10 #if __MINGW_GNUC_PREREQ(3, 3)
11 #define HUGE_VALF	__builtin_huge_valf()
12 #define HUGE_VALL	__builtin_huge_vall()
13 #define INFINITY	__builtin_inf()
14 #define NAN		__builtin_nan("")
15 #else
16 extern const float __INFF;
17 #define HUGE_VALF __INFF
18 extern const long double  __INFL;
19 #define HUGE_VALL __INFL
20 #define INFINITY HUGE_VALF
21 extern const double __QNAN;
22 #define NAN __QNAN
23 #endif /* __MINGW_GNUC_PREREQ(3, 3) */
24 
25 /* Use the compiler's builtin define for FLT_EVAL_METHOD to
26    set float_t and double_t.  */
27 #if defined(__FLT_EVAL_METHOD__)
28 # if ( __FLT_EVAL_METHOD__== 0)
29 typedef float float_t;
30 typedef double double_t;
31 # elif (__FLT_EVAL_METHOD__ == 1)
32 typedef double float_t;
33 typedef double double_t;
34 # elif (__FLT_EVAL_METHOD__ == 2)
35 typedef long double float_t;
36 typedef long double double_t;
37 #endif
38 #else /* ix87 FPU default */
39 typedef long double float_t;
40 typedef long double double_t;
41 #endif
42 
43 /* 7.12.3.1 */
44 /*
45    Return values for fpclassify.
46    These are based on Intel x87 fpu condition codes
47    in the high byte of status word and differ from
48    the return values for MS IEEE 754 extension _fpclass()
49 */
50 #define FP_NAN		0x0100
51 #define FP_NORMAL	0x0400
52 #define FP_INFINITE	(FP_NAN | FP_NORMAL)
53 #define FP_ZERO		0x4000
54 #define FP_SUBNORMAL	(FP_NORMAL | FP_ZERO)
55 /* 0x0200 is signbit mask */
56 
57 /*
58   We can't inline float or double, because we want to ensure truncation
59   to semantic type before classification.
60   (A normal long double value might become subnormal when
61   converted to double, and zero when converted to float.)
62 */
63 
64   extern int __cdecl __fpclassifyl (long double);
65   extern int __cdecl __fpclassifyf (float);
66   extern int __cdecl __fpclassify (double);
67 
68 #ifndef __CRT__NO_INLINE
69   __CRT_INLINE int __cdecl __fpclassifyl (long double x) {
70     unsigned short sw;
71     __asm__ __volatile__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x));
72     return sw & (FP_NAN | FP_NORMAL | FP_ZERO );
73   }
74   __CRT_INLINE int __cdecl __fpclassify (double x) {
75     unsigned short sw;
76     __asm__ __volatile__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x));
77     return sw & (FP_NAN | FP_NORMAL | FP_ZERO );
78   }
79   __CRT_INLINE int __cdecl __fpclassifyf (float x) {
80     unsigned short sw;
81     __asm__ __volatile__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x));
82     return sw & (FP_NAN | FP_NORMAL | FP_ZERO );
83   }
84 #endif
85 
86 #define fpclassify(x) (sizeof (x) == sizeof (float) ? __fpclassifyf (x)	  \
87   : sizeof (x) == sizeof (double) ? __fpclassify (x) \
88   : __fpclassifyl (x))
89 
90 /* 7.12.3.2 */
91 #define isfinite(x) ((fpclassify(x) & FP_NAN) == 0)
92 
93 /* 7.12.3.3 */
94 #define isinf(x) (fpclassify(x) == FP_INFINITE)
95 
96 /* 7.12.3.4 */
97 /* We don't need to worry about truncation here:
98    A NaN stays a NaN. */
99 
100   extern int __cdecl __isnan (double);
101   extern int __cdecl __isnanf (float);
102   extern int __cdecl __isnanl (long double);
103 
104 #ifndef __CRT__NO_INLINE
105   __CRT_INLINE int __cdecl __isnan (double _x)
106   {
107     unsigned short sw;
108     __asm__ __volatile__ ("fxam;"
109       "fstsw %%ax": "=a" (sw) : "t" (_x));
110     return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL))
111       == FP_NAN;
112   }
113 
114   __CRT_INLINE int __cdecl __isnanf (float _x)
115   {
116     unsigned short sw;
117     __asm__ __volatile__ ("fxam;"
118       "fstsw %%ax": "=a" (sw) : "t" (_x));
119     return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL))
120       == FP_NAN;
121   }
122 
123   __CRT_INLINE int __cdecl __isnanl (long double _x)
124   {
125     unsigned short sw;
126     __asm__ __volatile__ ("fxam;"
127       "fstsw %%ax": "=a" (sw) : "t" (_x));
128     return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL))
129       == FP_NAN;
130   }
131 #endif
132 
133 #define isnan(x) (sizeof (x) == sizeof (float) ? __isnanf (x)	\
134   : sizeof (x) == sizeof (double) ? __isnan (x)	\
135   : __isnanl (x))
136 
137 /* 7.12.3.5 */
138 #define isnormal(x) (fpclassify(x) == FP_NORMAL)
139 
140 /* 7.12.3.6 The signbit macro */
141   extern int __cdecl __signbit (double);
142   extern int __cdecl __signbitf (float);
143   extern int __cdecl __signbitl (long double);
144 #ifndef __CRT__NO_INLINE
145   __CRT_INLINE int __cdecl __signbit (double x) {
146     unsigned short stw;
147     __asm__ __volatile__ ( "fxam; fstsw %%ax;": "=a" (stw) : "t" (x));
148     return stw & 0x0200;
149   }
150 
151   __CRT_INLINE int __cdecl __signbitf (float x) {
152     unsigned short stw;
153     __asm__ __volatile__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x));
154     return stw & 0x0200;
155   }
156 
157   __CRT_INLINE int __cdecl __signbitl (long double x) {
158     unsigned short stw;
159     __asm__ __volatile__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x));
160     return stw & 0x0200;
161   }
162 #endif
163 
164 #define signbit(x) (sizeof (x) == sizeof (float) ? __signbitf (x)	\
165   : sizeof (x) == sizeof (double) ? __signbit (x)	\
166   : __signbitl (x))
167 
168 /* 7.12.4 Trigonometric functions: Double in C89 */
169   // Already in math.h
170 
171 /* 7.12.5 Hyperbolic functions: Double in C89  */
172   // Already in math.h
173 
174 /* Inverse hyperbolic trig functions  */
175 /* 7.12.5.1 */
176   extern double __cdecl acosh (double);
177   extern float __cdecl acoshf (float);
178   extern long double __cdecl acoshl (long double);
179 
180 /* 7.12.5.2 */
181   extern double __cdecl asinh (double);
182   extern float __cdecl asinhf (float);
183   extern long double __cdecl asinhl (long double);
184 
185 /* 7.12.5.3 */
186   extern double __cdecl atanh (double);
187   extern float __cdecl atanhf  (float);
188   extern long double __cdecl atanhl (long double);
189 
190 /* Exponentials and logarithms  */
191 /* 7.12.6.1 Double in C89 */
192   // exp functions. Already in math.h
193 
194 /* 7.12.6.2 */
195   extern double __cdecl exp2(double);
196   extern float __cdecl exp2f(float);
197   extern long double __cdecl exp2l(long double);
198 
199 /* 7.12.6.3 The expm1 functions */
200 /* TODO: These could be inlined */
201   extern double __cdecl expm1(double);
202   extern float __cdecl expm1f(float);
203   extern long double __cdecl expm1l(long double);
204 
205 /* 7.12.6.4 Double in C89 */
206   // frexp functions. Already in math.h
207 
208 /* 7.12.6.5 */
209 #define FP_ILOGB0 ((int)0x80000000)
210 #define FP_ILOGBNAN ((int)0x80000000)
211   extern int __cdecl ilogb (double);
212   extern int __cdecl ilogbf (float);
213   extern int __cdecl ilogbl (long double);
214 
215 /* 7.12.6.6  Double in C89 */
216   // ldexp functions. Already in math.h
217 
218 /* 7.12.6.7 Double in C89 */
219   // log functions. Already in math.h
220 
221 /* 7.12.6.8 Double in C89 */
222   // log10 functions. Already in math.h
223 
224 /* 7.12.6.9 */
225   extern double __cdecl log1p(double);
226   extern float __cdecl log1pf(float);
227   extern long double __cdecl log1pl(long double);
228 
229 /* 7.12.6.10 */
230   extern double __cdecl log2 (double);
231   extern float __cdecl log2f (float);
232   extern long double __cdecl log2l (long double);
233 
234 /* 7.12.6.11 */
235   extern double __cdecl logb (double);
236   extern float __cdecl logbf (float);
237   extern long double __cdecl logbl (long double);
238 
239 /* Inline versions.  GCC-4.0+ can do a better fast-math optimization
240    with __builtins. */
241 #ifndef __CRT__NO_INLINE
242 #if !(__MINGW_GNUC_PREREQ (4, 0) && defined (__FAST_MATH__))
243   __CRT_INLINE double __cdecl logb (double x)
244   {
245     double res = 0.0;
246     __asm__ __volatile__ ("fxtract\n\t"
247       "fstp	%%st" : "=t" (res) : "0" (x));
248     return res;
249   }
250 
251   __CRT_INLINE float __cdecl logbf (float x)
252   {
253     float res = 0.0F;
254     __asm__ __volatile__ ("fxtract\n\t"
255       "fstp	%%st" : "=t" (res) : "0" (x));
256     return res;
257   }
258 
259   __CRT_INLINE long double __cdecl logbl (long double x)
260   {
261     long double res = 0.0l;
262     __asm__ __volatile__ ("fxtract\n\t"
263       "fstp	%%st" : "=t" (res) : "0" (x));
264     return res;
265   }
266 #endif /* !defined __FAST_MATH__ || !__MINGW_GNUC_PREREQ (4, 0) */
267 #endif /* __CRT__NO_INLINE */
268 
269 /* 7.12.6.12  Double in C89 */
270   // modf functions. Already in math.h
271 
272 /* 7.12.6.13 */
273   extern double __cdecl scalbn (double, int);
274   extern float __cdecl scalbnf (float, int);
275   extern long double __cdecl scalbnl (long double, int);
276 
277   extern double __cdecl scalbln (double, long);
278   extern float __cdecl scalblnf (float, long);
279   extern long double __cdecl scalblnl (long double, long);
280 
281 /* 7.12.7.1 */
282 /* Implementations adapted from Cephes versions */
283   extern double __cdecl cbrt (double);
284   extern float __cdecl cbrtf (float);
285   extern long double __cdecl cbrtl (long double);
286 
287 /* 7.12.7.2 The fabs functions: Double in C89 */
288   // Already in math.h
289 
290 /* 7.12.7.3  */
291   // hypot functions. Already in math.h
292 
293 /* 7.12.7.4 The pow functions. Double in C89 */
294   // Already in math.h
295 
296 /* 7.12.7.5 The sqrt functions. Double in C89. */
297   // Already in math.h
298 
299 /* 7.12.8.1 The erf functions  */
300   extern double __cdecl erf (double);
301   extern float __cdecl erff (float);
302   extern long double __cdecl erfl (long double);
303 
304 /* 7.12.8.2 The erfc functions  */
305   extern double __cdecl erfc (double);
306   extern float __cdecl erfcf (float);
307   extern long double __cdecl erfcl (long double);
308 
309 /* 7.12.8.3 The lgamma functions */
310   extern double __cdecl lgamma (double);
311   extern float __cdecl lgammaf (float);
312   extern long double __cdecl lgammal (long double);
313 
314 /* 7.12.8.4 The tgamma functions */
315   extern double __cdecl tgamma (double);
316   extern float __cdecl tgammaf (float);
317   extern long double __cdecl tgammal (long double);
318 
319 /* 7.12.9.1 Double in C89 */
320   // ceil functions. Already in math.h
321 
322 /* 7.12.9.2 Double in C89 */
323   // floor functions. Already in math.h
324 
325 /* 7.12.9.3 */
326   extern double __cdecl nearbyint ( double);
327   extern float __cdecl nearbyintf (float);
328   extern long double __cdecl nearbyintl (long double);
329 
330 /* 7.12.9.4 */
331 /* round, using fpu control word settings */
332 extern double __cdecl rint (double);
333 extern float __cdecl rintf (float);
334 extern long double __cdecl rintl (long double);
335 
336 /* 7.12.9.5 */
337 extern long __cdecl lrint (double);
338 extern long __cdecl lrintf (float);
339 extern long __cdecl lrintl (long double);
340 
341 __MINGW_EXTENSION long long __cdecl llrint (double);
342 __MINGW_EXTENSION long long __cdecl llrintf (float);
343 __MINGW_EXTENSION long long __cdecl llrintl (long double);
344 
345 /* Inline versions of above.
346    GCC 4.0+ can do a better fast-math job with __builtins. */
347 
348 #ifndef __CRT__NO_INLINE
349 #if !(__MINGW_GNUC_PREREQ (4, 0) && defined __FAST_MATH__ )
350   __CRT_INLINE double __cdecl rint (double x)
351   {
352     double retval = 0.0;
353     __asm__ __volatile__ ("frndint;": "=t" (retval) : "0" (x));
354     return retval;
355   }
356 
357   __CRT_INLINE float __cdecl rintf (float x)
358   {
359     float retval = 0.0;
360     __asm__ __volatile__ ("frndint;" : "=t" (retval) : "0" (x) );
361     return retval;
362   }
363 
364   __CRT_INLINE long double __cdecl rintl (long double x)
365   {
366     long double retval = 0.0l;
367     __asm__ __volatile__ ("frndint;" : "=t" (retval) : "0" (x) );
368     return retval;
369   }
370 
371   __CRT_INLINE long __cdecl lrint (double x)
372   {
373     long retval = 0;
374     __asm__ __volatile__							      \
375       ("fistpl %0"  : "=m" (retval) : "t" (x) : "st");				      \
376       return retval;
377   }
378 
379   __CRT_INLINE long __cdecl lrintf (float x)
380   {
381     long retval = 0;
382     __asm__ __volatile__							      \
383       ("fistpl %0"  : "=m" (retval) : "t" (x) : "st");				      \
384       return retval;
385   }
386 
387   __CRT_INLINE long __cdecl lrintl (long double x)
388   {
389     long retval = 0;
390     __asm__ __volatile__							      \
391       ("fistpl %0"  : "=m" (retval) : "t" (x) : "st");				      \
392       return retval;
393   }
394 
395   __MINGW_EXTENSION __CRT_INLINE long long __cdecl llrint (double x)
396   {
397     __MINGW_EXTENSION long long retval = 0ll;
398     __asm__ __volatile__							      \
399       ("fistpll %0"  : "=m" (retval) : "t" (x) : "st");				      \
400       return retval;
401   }
402 
403   __MINGW_EXTENSION __CRT_INLINE long long __cdecl llrintf (float x)
404   {
405     __MINGW_EXTENSION long long retval = 0ll;
406     __asm__ __volatile__							      \
407       ("fistpll %0"  : "=m" (retval) : "t" (x) : "st");				      \
408       return retval;
409   }
410 
411   __MINGW_EXTENSION __CRT_INLINE long long __cdecl llrintl (long double x)
412   {
413     __MINGW_EXTENSION long long retval = 0ll;
414     __asm__ __volatile__							      \
415       ("fistpll %0"  : "=m" (retval) : "t" (x) : "st");				      \
416       return retval;
417   }
418 #endif /* !__FAST_MATH__ || !__MINGW_GNUC_PREREQ (4,0)  */
419 #endif /* !__CRT__NO_INLINE */
420 
421 /* 7.12.9.6 */
422 /* round away from zero, regardless of fpu control word settings */
423   extern double __cdecl round (double);
424   extern float __cdecl roundf (float);
425   extern long double __cdecl roundl (long double);
426 
427 /* 7.12.9.7  */
428   extern long __cdecl lround (double);
429   extern long __cdecl lroundf (float);
430   extern long __cdecl lroundl (long double);
431   __MINGW_EXTENSION long long __cdecl llround (double);
432   __MINGW_EXTENSION long long __cdecl llroundf (float);
433   __MINGW_EXTENSION long long __cdecl llroundl (long double);
434 
435 /* 7.12.9.8 */
436 /* round towards zero, regardless of fpu control word settings */
437   extern double __cdecl trunc (double);
438   extern float __cdecl truncf (float);
439   extern long double __cdecl truncl (long double);
440 
441 /* 7.12.10.1 Double in C89 */
442   // fmod functions. Already in math.h
443 
444 /* 7.12.10.2 */
445   extern double __cdecl remainder (double, double);
446   extern float __cdecl remainderf (float, float);
447   extern long double __cdecl remainderl (long double, long double);
448 
449 /* 7.12.10.3 */
450   extern double __cdecl remquo(double, double, int *);
451   extern float __cdecl remquof(float, float, int *);
452   extern long double __cdecl remquol(long double, long double, int *);
453 
454 /* 7.12.11.1 */
455   extern double __cdecl copysign (double, double); /* in libmoldname.a */
456   extern float __cdecl copysignf (float, float);
457   extern long double __cdecl copysignl (long double, long double);
458 
459 /* 7.12.11.2 Return a NaN */
460   extern double __cdecl nan(const char *tagp);
461   extern float __cdecl nanf(const char *tagp);
462   extern long double __cdecl nanl(const char *tagp);
463 
464 #ifndef __STRICT_ANSI__
465 #define _nan() nan("")
466 #define _nanf() nanf("")
467 #define _nanl() nanl("")
468 #endif
469 
470 /* 7.12.11.3 */
471   extern double __cdecl nextafter (double, double); /* in libmoldname.a */
472   extern float __cdecl nextafterf (float, float);
473   extern long double __cdecl nextafterl (long double, long double);
474 
475 /* 7.12.11.4 The nexttoward functions */
476   extern double __cdecl nexttoward (double,  long double);
477   extern float __cdecl nexttowardf (float,  long double);
478   extern long double __cdecl nexttowardl (long double, long double);
479 
480 /* 7.12.12.1 */
481 /*  x > y ? (x - y) : 0.0  */
482   extern double __cdecl fdim (double x, double y);
483   extern float __cdecl fdimf (float x, float y);
484   extern long double __cdecl fdiml (long double x, long double y);
485 
486 /* fmax and fmin.
487    NaN arguments are treated as missing data: if one argument is a NaN
488    and the other numeric, then these functions choose the numeric
489    value. */
490 
491 /* 7.12.12.2 */
492   extern double __cdecl fmax  (double, double);
493   extern float __cdecl fmaxf (float, float);
494   extern long double __cdecl fmaxl (long double, long double);
495 
496 /* 7.12.12.3 */
497   extern double __cdecl fmin (double, double);
498   extern float __cdecl fminf (float, float);
499   extern long double __cdecl fminl (long double, long double);
500 
501 /* 7.12.13.1 */
502 /* return x * y + z as a ternary op */
503   extern double __cdecl fma (double, double, double);
504   extern float __cdecl fmaf (float, float, float);
505   extern long double __cdecl fmal (long double, long double, long double);
506 
507 /* 7.12.14 */
508 /*
509  *  With these functions, comparisons involving quiet NaNs set the FP
510  *  condition code to "unordered".  The IEEE floating-point spec
511  *  dictates that the result of floating-point comparisons should be
512  *  false whenever a NaN is involved, with the exception of the != op,
513  *  which always returns true: yes, (NaN != NaN) is true).
514  */
515 
516 #if __GNUC__ >= 3
517 
518 #define isgreater(x, y) __builtin_isgreater(x, y)
519 #define isgreaterequal(x, y) __builtin_isgreaterequal(x, y)
520 #define isless(x, y) __builtin_isless(x, y)
521 #define islessequal(x, y) __builtin_islessequal(x, y)
522 #define islessgreater(x, y) __builtin_islessgreater(x, y)
523 #define isunordered(x, y) __builtin_isunordered(x, y)
524 
525 #else
526 /*  helper  */
527 #ifndef __CRT__NO_INLINE
528   __CRT_INLINE int  __cdecl
529     __fp_unordered_compare (long double x, long double y){
530       unsigned short retval;
531       __asm__ __volatile__ ("fucom %%st(1);"
532 	"fnstsw;": "=a" (retval) : "t" (x), "u" (y));
533       return retval;
534   }
535 #endif
536 
537 #define isgreater(x, y) ((__fp_unordered_compare(x, y)  & 0x4500) == 0)
538 #define isless(x, y) ((__fp_unordered_compare (y, x)  & 0x4500) == 0)
539 #define isgreaterequal(x, y) ((__fp_unordered_compare (x, y)  & FP_INFINITE) == 0)
540 #define islessequal(x, y) ((__fp_unordered_compare(y, x)  & FP_INFINITE) == 0)
541 #define islessgreater(x, y) ((__fp_unordered_compare(x, y)  & FP_SUBNORMAL) == 0)
542 #define isunordered(x, y) ((__fp_unordered_compare(x, y)  & 0x4500) == 0x4500)
543 
544 #endif
545 
546 #endif /* C99 or non strict ANSI or C++ */
547 #endif /* __NO_ISOCEXT */