Fix HAVE_RM_CTX -Wundef warnings
[glibc.git] / sysdeps / generic / math_private.h
blob0ac70e3b1b3a14e3269a5d5f78e29077a4767224
1 /*
2 * ====================================================
3 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 * Developed at SunPro, a Sun Microsystems, Inc. business.
6 * Permission to use, copy, modify, and distribute this
7 * software is freely granted, provided that this notice
8 * is preserved.
9 * ====================================================
13 * from: @(#)fdlibm.h 5.1 93/09/24
16 #ifndef _MATH_PRIVATE_H_
17 #define _MATH_PRIVATE_H_
19 #include <endian.h>
20 #include <stdint.h>
21 #include <sys/types.h>
22 #include <fenv.h>
24 /* The original fdlibm code used statements like:
25 n0 = ((*(int*)&one)>>29)^1; * index of high word *
26 ix0 = *(n0+(int*)&x); * high word of x *
27 ix1 = *((1-n0)+(int*)&x); * low word of x *
28 to dig two 32 bit words out of the 64 bit IEEE floating point
29 value. That is non-ANSI, and, moreover, the gcc instruction
30 scheduler gets it wrong. We instead use the following macros.
31 Unlike the original code, we determine the endianness at compile
32 time, not at run time; I don't see much benefit to selecting
33 endianness at run time. */
35 /* A union which permits us to convert between a double and two 32 bit
36 ints. */
38 #if __FLOAT_WORD_ORDER == BIG_ENDIAN
40 typedef union
42 double value;
43 struct
45 u_int32_t msw;
46 u_int32_t lsw;
47 } parts;
48 uint64_t word;
49 } ieee_double_shape_type;
51 #endif
53 #if __FLOAT_WORD_ORDER == LITTLE_ENDIAN
55 typedef union
57 double value;
58 struct
60 u_int32_t lsw;
61 u_int32_t msw;
62 } parts;
63 uint64_t word;
64 } ieee_double_shape_type;
66 #endif
68 /* Get two 32 bit ints from a double. */
70 #define EXTRACT_WORDS(ix0,ix1,d) \
71 do { \
72 ieee_double_shape_type ew_u; \
73 ew_u.value = (d); \
74 (ix0) = ew_u.parts.msw; \
75 (ix1) = ew_u.parts.lsw; \
76 } while (0)
78 /* Get the more significant 32 bit int from a double. */
80 #ifndef GET_HIGH_WORD
81 # define GET_HIGH_WORD(i,d) \
82 do { \
83 ieee_double_shape_type gh_u; \
84 gh_u.value = (d); \
85 (i) = gh_u.parts.msw; \
86 } while (0)
87 #endif
89 /* Get the less significant 32 bit int from a double. */
91 #ifndef GET_LOW_WORD
92 # define GET_LOW_WORD(i,d) \
93 do { \
94 ieee_double_shape_type gl_u; \
95 gl_u.value = (d); \
96 (i) = gl_u.parts.lsw; \
97 } while (0)
98 #endif
100 /* Get all in one, efficient on 64-bit machines. */
101 #ifndef EXTRACT_WORDS64
102 # define EXTRACT_WORDS64(i,d) \
103 do { \
104 ieee_double_shape_type gh_u; \
105 gh_u.value = (d); \
106 (i) = gh_u.word; \
107 } while (0)
108 #endif
110 /* Set a double from two 32 bit ints. */
111 #ifndef INSERT_WORDS
112 # define INSERT_WORDS(d,ix0,ix1) \
113 do { \
114 ieee_double_shape_type iw_u; \
115 iw_u.parts.msw = (ix0); \
116 iw_u.parts.lsw = (ix1); \
117 (d) = iw_u.value; \
118 } while (0)
119 #endif
121 /* Get all in one, efficient on 64-bit machines. */
122 #ifndef INSERT_WORDS64
123 # define INSERT_WORDS64(d,i) \
124 do { \
125 ieee_double_shape_type iw_u; \
126 iw_u.word = (i); \
127 (d) = iw_u.value; \
128 } while (0)
129 #endif
131 /* Set the more significant 32 bits of a double from an int. */
132 #ifndef SET_HIGH_WORD
133 #define SET_HIGH_WORD(d,v) \
134 do { \
135 ieee_double_shape_type sh_u; \
136 sh_u.value = (d); \
137 sh_u.parts.msw = (v); \
138 (d) = sh_u.value; \
139 } while (0)
140 #endif
142 /* Set the less significant 32 bits of a double from an int. */
143 #ifndef SET_LOW_WORD
144 # define SET_LOW_WORD(d,v) \
145 do { \
146 ieee_double_shape_type sl_u; \
147 sl_u.value = (d); \
148 sl_u.parts.lsw = (v); \
149 (d) = sl_u.value; \
150 } while (0)
151 #endif
153 /* A union which permits us to convert between a float and a 32 bit
154 int. */
156 typedef union
158 float value;
159 u_int32_t word;
160 } ieee_float_shape_type;
162 /* Get a 32 bit int from a float. */
163 #ifndef GET_FLOAT_WORD
164 # define GET_FLOAT_WORD(i,d) \
165 do { \
166 ieee_float_shape_type gf_u; \
167 gf_u.value = (d); \
168 (i) = gf_u.word; \
169 } while (0)
170 #endif
172 /* Set a float from a 32 bit int. */
173 #ifndef SET_FLOAT_WORD
174 # define SET_FLOAT_WORD(d,i) \
175 do { \
176 ieee_float_shape_type sf_u; \
177 sf_u.word = (i); \
178 (d) = sf_u.value; \
179 } while (0)
180 #endif
182 /* Get long double macros from a separate header. */
183 #include <math_ldbl.h>
185 /* ieee style elementary functions */
186 extern double __ieee754_sqrt (double);
187 extern double __ieee754_acos (double);
188 extern double __ieee754_acosh (double);
189 extern double __ieee754_log (double);
190 extern double __ieee754_atanh (double);
191 extern double __ieee754_asin (double);
192 extern double __ieee754_atan2 (double,double);
193 extern double __ieee754_exp (double);
194 extern double __ieee754_exp2 (double);
195 extern double __ieee754_exp10 (double);
196 extern double __ieee754_cosh (double);
197 extern double __ieee754_fmod (double,double);
198 extern double __ieee754_pow (double,double);
199 extern double __ieee754_lgamma_r (double,int *);
200 extern double __ieee754_gamma_r (double,int *);
201 extern double __ieee754_lgamma (double);
202 extern double __ieee754_gamma (double);
203 extern double __ieee754_log10 (double);
204 extern double __ieee754_log2 (double);
205 extern double __ieee754_sinh (double);
206 extern double __ieee754_hypot (double,double);
207 extern double __ieee754_j0 (double);
208 extern double __ieee754_j1 (double);
209 extern double __ieee754_y0 (double);
210 extern double __ieee754_y1 (double);
211 extern double __ieee754_jn (int,double);
212 extern double __ieee754_yn (int,double);
213 extern double __ieee754_remainder (double,double);
214 extern int32_t __ieee754_rem_pio2 (double,double*);
215 extern double __ieee754_scalb (double,double);
216 extern int __ieee754_ilogb (double);
218 /* fdlibm kernel function */
219 extern double __kernel_standard (double,double,int);
220 extern float __kernel_standard_f (float,float,int);
221 extern long double __kernel_standard_l (long double,long double,int);
222 extern double __kernel_sin (double,double,int);
223 extern double __kernel_cos (double,double);
224 extern double __kernel_tan (double,double,int);
225 extern int __kernel_rem_pio2 (double*,double*,int,int,int, const int32_t*);
227 /* internal functions. */
228 extern double __copysign (double x, double __y);
230 extern inline double __copysign (double x, double y)
231 { return __builtin_copysign (x, y); }
233 /* ieee style elementary float functions */
234 extern float __ieee754_sqrtf (float);
235 extern float __ieee754_acosf (float);
236 extern float __ieee754_acoshf (float);
237 extern float __ieee754_logf (float);
238 extern float __ieee754_atanhf (float);
239 extern float __ieee754_asinf (float);
240 extern float __ieee754_atan2f (float,float);
241 extern float __ieee754_expf (float);
242 extern float __ieee754_exp2f (float);
243 extern float __ieee754_exp10f (float);
244 extern float __ieee754_coshf (float);
245 extern float __ieee754_fmodf (float,float);
246 extern float __ieee754_powf (float,float);
247 extern float __ieee754_lgammaf_r (float,int *);
248 extern float __ieee754_gammaf_r (float,int *);
249 extern float __ieee754_lgammaf (float);
250 extern float __ieee754_gammaf (float);
251 extern float __ieee754_log10f (float);
252 extern float __ieee754_log2f (float);
253 extern float __ieee754_sinhf (float);
254 extern float __ieee754_hypotf (float,float);
255 extern float __ieee754_j0f (float);
256 extern float __ieee754_j1f (float);
257 extern float __ieee754_y0f (float);
258 extern float __ieee754_y1f (float);
259 extern float __ieee754_jnf (int,float);
260 extern float __ieee754_ynf (int,float);
261 extern float __ieee754_remainderf (float,float);
262 extern int32_t __ieee754_rem_pio2f (float,float*);
263 extern float __ieee754_scalbf (float,float);
264 extern int __ieee754_ilogbf (float);
267 /* float versions of fdlibm kernel functions */
268 extern float __kernel_sinf (float,float,int);
269 extern float __kernel_cosf (float,float);
270 extern float __kernel_tanf (float,float,int);
271 extern int __kernel_rem_pio2f (float*,float*,int,int,int, const int32_t*);
273 /* internal functions. */
274 extern float __copysignf (float x, float __y);
276 extern inline float __copysignf (float x, float y)
277 { return __builtin_copysignf (x, y); }
279 /* ieee style elementary long double functions */
280 extern long double __ieee754_sqrtl (long double);
281 extern long double __ieee754_acosl (long double);
282 extern long double __ieee754_acoshl (long double);
283 extern long double __ieee754_logl (long double);
284 extern long double __ieee754_atanhl (long double);
285 extern long double __ieee754_asinl (long double);
286 extern long double __ieee754_atan2l (long double,long double);
287 extern long double __ieee754_expl (long double);
288 extern long double __ieee754_exp2l (long double);
289 extern long double __ieee754_exp10l (long double);
290 extern long double __ieee754_coshl (long double);
291 extern long double __ieee754_fmodl (long double,long double);
292 extern long double __ieee754_powl (long double,long double);
293 extern long double __ieee754_lgammal_r (long double,int *);
294 extern long double __ieee754_gammal_r (long double,int *);
295 extern long double __ieee754_lgammal (long double);
296 extern long double __ieee754_gammal (long double);
297 extern long double __ieee754_log10l (long double);
298 extern long double __ieee754_log2l (long double);
299 extern long double __ieee754_sinhl (long double);
300 extern long double __ieee754_hypotl (long double,long double);
301 extern long double __ieee754_j0l (long double);
302 extern long double __ieee754_j1l (long double);
303 extern long double __ieee754_y0l (long double);
304 extern long double __ieee754_y1l (long double);
305 extern long double __ieee754_jnl (int,long double);
306 extern long double __ieee754_ynl (int,long double);
307 extern long double __ieee754_remainderl (long double,long double);
308 extern int __ieee754_rem_pio2l (long double,long double*);
309 extern long double __ieee754_scalbl (long double,long double);
310 extern int __ieee754_ilogbl (long double);
312 /* long double versions of fdlibm kernel functions */
313 extern long double __kernel_sinl (long double,long double,int);
314 extern long double __kernel_cosl (long double,long double);
315 extern long double __kernel_tanl (long double,long double,int);
316 extern void __kernel_sincosl (long double,long double,
317 long double *,long double *, int);
318 extern int __kernel_rem_pio2l (long double*,long double*,int,int,
319 int,const int*);
321 #ifndef NO_LONG_DOUBLE
322 /* prototypes required to compile the ldbl-96 support without warnings */
323 extern int __finitel (long double);
324 extern int __ilogbl (long double);
325 extern int __isinfl (long double);
326 extern int __isnanl (long double);
327 extern long double __atanl (long double);
328 extern long double __copysignl (long double, long double);
329 extern long double __expm1l (long double);
330 extern long double __floorl (long double);
331 extern long double __frexpl (long double, int *);
332 extern long double __ldexpl (long double, int);
333 extern long double __log1pl (long double);
334 extern long double __nanl (const char *);
335 extern long double __rintl (long double);
336 extern long double __scalbnl (long double, int);
337 extern long double __sqrtl (long double x);
338 extern long double fabsl (long double x);
339 extern void __sincosl (long double, long double *, long double *);
340 extern long double __logbl (long double x);
341 extern long double __significandl (long double x);
343 extern inline long double __copysignl (long double x, long double y)
344 { return __builtin_copysignl (x, y); }
346 #endif
348 /* Prototypes for functions of the IBM Accurate Mathematical Library. */
349 extern double __exp1 (double __x, double __xx, double __error);
350 extern double __sin (double __x);
351 extern double __cos (double __x);
352 extern int __branred (double __x, double *__a, double *__aa);
353 extern void __doasin (double __x, double __dx, double __v[]);
354 extern void __dubsin (double __x, double __dx, double __v[]);
355 extern void __dubcos (double __x, double __dx, double __v[]);
356 extern double __halfulp (double __x, double __y);
357 extern double __sin32 (double __x, double __res, double __res1);
358 extern double __cos32 (double __x, double __res, double __res1);
359 extern double __mpsin (double __x, double __dx, bool __range_reduce);
360 extern double __mpcos (double __x, double __dx, bool __range_reduce);
361 extern double __slowexp (double __x);
362 extern double __slowpow (double __x, double __y, double __z);
363 extern void __docos (double __x, double __dx, double __v[]);
365 /* Return X^2 + Y^2 - 1, computed without large cancellation error.
366 It is given that 1 > X >= Y >= epsilon / 2, and that either X >=
367 0.75 or Y >= 0.5. */
368 extern float __x2y2m1f (float x, float y);
369 extern double __x2y2m1 (double x, double y);
370 extern long double __x2y2m1l (long double x, long double y);
372 /* Compute the product of X + X_EPS, X + X_EPS + 1, ..., X + X_EPS + N
373 - 1, in the form R * (1 + *EPS) where the return value R is an
374 approximation to the product and *EPS is set to indicate the
375 approximate error in the return value. X is such that all the
376 values X + 1, ..., X + N - 1 are exactly representable, and X_EPS /
377 X is small enough that factors quadratic in it can be
378 neglected. */
379 extern float __gamma_productf (float x, float x_eps, int n, float *eps);
380 extern double __gamma_product (double x, double x_eps, int n, double *eps);
381 extern long double __gamma_productl (long double x, long double x_eps,
382 int n, long double *eps);
384 #ifndef math_opt_barrier
385 # define math_opt_barrier(x) \
386 ({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; })
387 # define math_force_eval(x) \
388 ({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); })
389 #endif
392 /* The standards only specify one variant of the fenv.h interfaces.
393 But at least for some architectures we can be more efficient if we
394 know what operations are going to be performed. Therefore we
395 define additional interfaces. By default they refer to the normal
396 interfaces. */
398 static __always_inline void
399 default_libc_feholdexcept (fenv_t *e)
401 (void) feholdexcept (e);
404 #ifndef libc_feholdexcept
405 # define libc_feholdexcept default_libc_feholdexcept
406 #endif
407 #ifndef libc_feholdexceptf
408 # define libc_feholdexceptf default_libc_feholdexcept
409 #endif
410 #ifndef libc_feholdexceptl
411 # define libc_feholdexceptl default_libc_feholdexcept
412 #endif
414 static __always_inline void
415 default_libc_fesetround (int r)
417 (void) fesetround (r);
420 #ifndef libc_fesetround
421 # define libc_fesetround default_libc_fesetround
422 #endif
423 #ifndef libc_fesetroundf
424 # define libc_fesetroundf default_libc_fesetround
425 #endif
426 #ifndef libc_fesetroundl
427 # define libc_fesetroundl default_libc_fesetround
428 #endif
430 static __always_inline void
431 default_libc_feholdexcept_setround (fenv_t *e, int r)
433 feholdexcept (e);
434 fesetround (r);
437 #ifndef libc_feholdexcept_setround
438 # define libc_feholdexcept_setround default_libc_feholdexcept_setround
439 #endif
440 #ifndef libc_feholdexcept_setroundf
441 # define libc_feholdexcept_setroundf default_libc_feholdexcept_setround
442 #endif
443 #ifndef libc_feholdexcept_setroundl
444 # define libc_feholdexcept_setroundl default_libc_feholdexcept_setround
445 #endif
447 #ifndef libc_feholdsetround_53bit
448 # define libc_feholdsetround_53bit libc_feholdsetround
449 #endif
451 #ifndef libc_fetestexcept
452 # define libc_fetestexcept fetestexcept
453 #endif
454 #ifndef libc_fetestexceptf
455 # define libc_fetestexceptf fetestexcept
456 #endif
457 #ifndef libc_fetestexceptl
458 # define libc_fetestexceptl fetestexcept
459 #endif
461 static __always_inline void
462 default_libc_fesetenv (fenv_t *e)
464 (void) fesetenv (e);
467 #ifndef libc_fesetenv
468 # define libc_fesetenv default_libc_fesetenv
469 #endif
470 #ifndef libc_fesetenvf
471 # define libc_fesetenvf default_libc_fesetenv
472 #endif
473 #ifndef libc_fesetenvl
474 # define libc_fesetenvl default_libc_fesetenv
475 #endif
477 static __always_inline void
478 default_libc_feupdateenv (fenv_t *e)
480 (void) feupdateenv (e);
483 #ifndef libc_feupdateenv
484 # define libc_feupdateenv default_libc_feupdateenv
485 #endif
486 #ifndef libc_feupdateenvf
487 # define libc_feupdateenvf default_libc_feupdateenv
488 #endif
489 #ifndef libc_feupdateenvl
490 # define libc_feupdateenvl default_libc_feupdateenv
491 #endif
493 #ifndef libc_feresetround_53bit
494 # define libc_feresetround_53bit libc_feresetround
495 #endif
497 static __always_inline int
498 default_libc_feupdateenv_test (fenv_t *e, int ex)
500 int ret = fetestexcept (ex);
501 feupdateenv (e);
502 return ret;
505 #ifndef libc_feupdateenv_test
506 # define libc_feupdateenv_test default_libc_feupdateenv_test
507 #endif
508 #ifndef libc_feupdateenv_testf
509 # define libc_feupdateenv_testf default_libc_feupdateenv_test
510 #endif
511 #ifndef libc_feupdateenv_testl
512 # define libc_feupdateenv_testl default_libc_feupdateenv_test
513 #endif
515 /* Save and set the rounding mode. The use of fenv_t to store the old mode
516 allows a target-specific version of this function to avoid converting the
517 rounding mode from the fpu format. By default we have no choice but to
518 manipulate the entire env. */
520 #ifndef libc_feholdsetround
521 # define libc_feholdsetround libc_feholdexcept_setround
522 #endif
523 #ifndef libc_feholdsetroundf
524 # define libc_feholdsetroundf libc_feholdexcept_setroundf
525 #endif
526 #ifndef libc_feholdsetroundl
527 # define libc_feholdsetroundl libc_feholdexcept_setroundl
528 #endif
530 /* ... and the reverse. */
532 #ifndef libc_feresetround
533 # define libc_feresetround libc_feupdateenv
534 #endif
535 #ifndef libc_feresetroundf
536 # define libc_feresetroundf libc_feupdateenvf
537 #endif
538 #ifndef libc_feresetroundl
539 # define libc_feresetroundl libc_feupdateenvl
540 #endif
542 /* ... and a version that may also discard exceptions. */
544 #ifndef libc_feresetround_noex
545 # define libc_feresetround_noex libc_fesetenv
546 #endif
547 #ifndef libc_feresetround_noexf
548 # define libc_feresetround_noexf libc_fesetenvf
549 #endif
550 #ifndef libc_feresetround_noexl
551 # define libc_feresetround_noexl libc_fesetenvl
552 #endif
554 #ifdef HAVE_RM_CTX
555 /* Set/Restore Rounding Modes only when necessary. If defined, these functions
556 set/restore floating point state only if the state needed within the lexical
557 block is different from the current state. This saves a lot of time when
558 the floating point unit is much slower than the fixed point units. */
560 # ifndef libc_feresetround_noex_ctx
561 # define libc_feresetround_noex_ctx libc_fesetenv_ctx
562 # endif
563 # ifndef libc_feresetround_noexf_ctx
564 # define libc_feresetround_noexf_ctx libc_fesetenvf_ctx
565 # endif
566 # ifndef libc_feresetround_noexl_ctx
567 # define libc_feresetround_noexl_ctx libc_fesetenvl_ctx
568 # endif
570 # ifndef libc_feholdsetround_53bit_ctx
571 # define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx
572 # endif
574 # ifndef libc_feresetround_53bit_ctx
575 # define libc_feresetround_53bit_ctx libc_feresetround_ctx
576 # endif
578 # define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \
579 struct rm_ctx ctx __attribute__((cleanup(CLEANUPFUNC ## _ctx))); \
580 ROUNDFUNC ## _ctx (&ctx, (RM))
581 #else
582 # define SET_RESTORE_ROUND_GENERIC(RM, ROUNDFUNC, CLEANUPFUNC) \
583 fenv_t __libc_save_rm __attribute__((cleanup(CLEANUPFUNC))); \
584 ROUNDFUNC (&__libc_save_rm, (RM))
585 #endif
587 /* Save and restore the rounding mode within a lexical block. */
589 #define SET_RESTORE_ROUND(RM) \
590 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround)
591 #define SET_RESTORE_ROUNDF(RM) \
592 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf)
593 #define SET_RESTORE_ROUNDL(RM) \
594 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl)
596 /* Save and restore the rounding mode within a lexical block, and also
597 the set of exceptions raised within the block may be discarded. */
599 #define SET_RESTORE_ROUND_NOEX(RM) \
600 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround_noex)
601 #define SET_RESTORE_ROUND_NOEXF(RM) \
602 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetround_noexf)
603 #define SET_RESTORE_ROUND_NOEXL(RM) \
604 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetround_noexl)
606 /* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */
607 #define SET_RESTORE_ROUND_53BIT(RM) \
608 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit, \
609 libc_feresetround_53bit)
611 #define __nan(str) \
612 (__builtin_constant_p (str) && str[0] == '\0' ? NAN : __nan (str))
613 #define __nanf(str) \
614 (__builtin_constant_p (str) && str[0] == '\0' ? NAN : __nan (str))
615 #define __nanl(str) \
616 (__builtin_constant_p (str) && str[0] == '\0' ? NAN : __nan (str))
618 #endif /* _MATH_PRIVATE_H_ */