soft-fp: Use __label__ for all labels within macros.
[glibc.git] / sysdeps / generic / math_private.h
blob0ab547d82f797d177a787b1f8fa7f64cd031f06f
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>
23 #include <get-rounding-mode.h>
25 /* The original fdlibm code used statements like:
26 n0 = ((*(int*)&one)>>29)^1; * index of high word *
27 ix0 = *(n0+(int*)&x); * high word of x *
28 ix1 = *((1-n0)+(int*)&x); * low word of x *
29 to dig two 32 bit words out of the 64 bit IEEE floating point
30 value. That is non-ANSI, and, moreover, the gcc instruction
31 scheduler gets it wrong. We instead use the following macros.
32 Unlike the original code, we determine the endianness at compile
33 time, not at run time; I don't see much benefit to selecting
34 endianness at run time. */
36 /* A union which permits us to convert between a double and two 32 bit
37 ints. */
39 #if __FLOAT_WORD_ORDER == BIG_ENDIAN
41 typedef union
43 double value;
44 struct
46 u_int32_t msw;
47 u_int32_t lsw;
48 } parts;
49 uint64_t word;
50 } ieee_double_shape_type;
52 #endif
54 #if __FLOAT_WORD_ORDER == LITTLE_ENDIAN
56 typedef union
58 double value;
59 struct
61 u_int32_t lsw;
62 u_int32_t msw;
63 } parts;
64 uint64_t word;
65 } ieee_double_shape_type;
67 #endif
69 /* Get two 32 bit ints from a double. */
71 #define EXTRACT_WORDS(ix0,ix1,d) \
72 do { \
73 ieee_double_shape_type ew_u; \
74 ew_u.value = (d); \
75 (ix0) = ew_u.parts.msw; \
76 (ix1) = ew_u.parts.lsw; \
77 } while (0)
79 /* Get the more significant 32 bit int from a double. */
81 #ifndef GET_HIGH_WORD
82 # define GET_HIGH_WORD(i,d) \
83 do { \
84 ieee_double_shape_type gh_u; \
85 gh_u.value = (d); \
86 (i) = gh_u.parts.msw; \
87 } while (0)
88 #endif
90 /* Get the less significant 32 bit int from a double. */
92 #ifndef GET_LOW_WORD
93 # define GET_LOW_WORD(i,d) \
94 do { \
95 ieee_double_shape_type gl_u; \
96 gl_u.value = (d); \
97 (i) = gl_u.parts.lsw; \
98 } while (0)
99 #endif
101 /* Get all in one, efficient on 64-bit machines. */
102 #ifndef EXTRACT_WORDS64
103 # define EXTRACT_WORDS64(i,d) \
104 do { \
105 ieee_double_shape_type gh_u; \
106 gh_u.value = (d); \
107 (i) = gh_u.word; \
108 } while (0)
109 #endif
111 /* Set a double from two 32 bit ints. */
112 #ifndef INSERT_WORDS
113 # define INSERT_WORDS(d,ix0,ix1) \
114 do { \
115 ieee_double_shape_type iw_u; \
116 iw_u.parts.msw = (ix0); \
117 iw_u.parts.lsw = (ix1); \
118 (d) = iw_u.value; \
119 } while (0)
120 #endif
122 /* Get all in one, efficient on 64-bit machines. */
123 #ifndef INSERT_WORDS64
124 # define INSERT_WORDS64(d,i) \
125 do { \
126 ieee_double_shape_type iw_u; \
127 iw_u.word = (i); \
128 (d) = iw_u.value; \
129 } while (0)
130 #endif
132 /* Set the more significant 32 bits of a double from an int. */
133 #ifndef SET_HIGH_WORD
134 #define SET_HIGH_WORD(d,v) \
135 do { \
136 ieee_double_shape_type sh_u; \
137 sh_u.value = (d); \
138 sh_u.parts.msw = (v); \
139 (d) = sh_u.value; \
140 } while (0)
141 #endif
143 /* Set the less significant 32 bits of a double from an int. */
144 #ifndef SET_LOW_WORD
145 # define SET_LOW_WORD(d,v) \
146 do { \
147 ieee_double_shape_type sl_u; \
148 sl_u.value = (d); \
149 sl_u.parts.lsw = (v); \
150 (d) = sl_u.value; \
151 } while (0)
152 #endif
154 /* A union which permits us to convert between a float and a 32 bit
155 int. */
157 typedef union
159 float value;
160 u_int32_t word;
161 } ieee_float_shape_type;
163 /* Get a 32 bit int from a float. */
164 #ifndef GET_FLOAT_WORD
165 # define GET_FLOAT_WORD(i,d) \
166 do { \
167 ieee_float_shape_type gf_u; \
168 gf_u.value = (d); \
169 (i) = gf_u.word; \
170 } while (0)
171 #endif
173 /* Set a float from a 32 bit int. */
174 #ifndef SET_FLOAT_WORD
175 # define SET_FLOAT_WORD(d,i) \
176 do { \
177 ieee_float_shape_type sf_u; \
178 sf_u.word = (i); \
179 (d) = sf_u.value; \
180 } while (0)
181 #endif
183 /* Get long double macros from a separate header. */
184 #include <math_ldbl.h>
186 /* ieee style elementary functions */
187 extern double __ieee754_sqrt (double);
188 extern double __ieee754_acos (double);
189 extern double __ieee754_acosh (double);
190 extern double __ieee754_log (double);
191 extern double __ieee754_atanh (double);
192 extern double __ieee754_asin (double);
193 extern double __ieee754_atan2 (double,double);
194 extern double __ieee754_exp (double);
195 extern double __ieee754_exp2 (double);
196 extern double __ieee754_exp10 (double);
197 extern double __ieee754_cosh (double);
198 extern double __ieee754_fmod (double,double);
199 extern double __ieee754_pow (double,double);
200 extern double __ieee754_lgamma_r (double,int *);
201 extern double __ieee754_gamma_r (double,int *);
202 extern double __ieee754_lgamma (double);
203 extern double __ieee754_gamma (double);
204 extern double __ieee754_log10 (double);
205 extern double __ieee754_log2 (double);
206 extern double __ieee754_sinh (double);
207 extern double __ieee754_hypot (double,double);
208 extern double __ieee754_j0 (double);
209 extern double __ieee754_j1 (double);
210 extern double __ieee754_y0 (double);
211 extern double __ieee754_y1 (double);
212 extern double __ieee754_jn (int,double);
213 extern double __ieee754_yn (int,double);
214 extern double __ieee754_remainder (double,double);
215 extern int32_t __ieee754_rem_pio2 (double,double*);
216 extern double __ieee754_scalb (double,double);
217 extern int __ieee754_ilogb (double);
219 /* fdlibm kernel function */
220 extern double __kernel_standard (double,double,int);
221 extern float __kernel_standard_f (float,float,int);
222 extern long double __kernel_standard_l (long double,long double,int);
223 extern double __kernel_sin (double,double,int);
224 extern double __kernel_cos (double,double);
225 extern double __kernel_tan (double,double,int);
226 extern int __kernel_rem_pio2 (double*,double*,int,int,int, const int32_t*);
228 /* internal functions. */
229 extern double __copysign (double x, double __y);
231 extern inline double __copysign (double x, double y)
232 { return __builtin_copysign (x, y); }
234 /* ieee style elementary float functions */
235 extern float __ieee754_sqrtf (float);
236 extern float __ieee754_acosf (float);
237 extern float __ieee754_acoshf (float);
238 extern float __ieee754_logf (float);
239 extern float __ieee754_atanhf (float);
240 extern float __ieee754_asinf (float);
241 extern float __ieee754_atan2f (float,float);
242 extern float __ieee754_expf (float);
243 extern float __ieee754_exp2f (float);
244 extern float __ieee754_exp10f (float);
245 extern float __ieee754_coshf (float);
246 extern float __ieee754_fmodf (float,float);
247 extern float __ieee754_powf (float,float);
248 extern float __ieee754_lgammaf_r (float,int *);
249 extern float __ieee754_gammaf_r (float,int *);
250 extern float __ieee754_lgammaf (float);
251 extern float __ieee754_gammaf (float);
252 extern float __ieee754_log10f (float);
253 extern float __ieee754_log2f (float);
254 extern float __ieee754_sinhf (float);
255 extern float __ieee754_hypotf (float,float);
256 extern float __ieee754_j0f (float);
257 extern float __ieee754_j1f (float);
258 extern float __ieee754_y0f (float);
259 extern float __ieee754_y1f (float);
260 extern float __ieee754_jnf (int,float);
261 extern float __ieee754_ynf (int,float);
262 extern float __ieee754_remainderf (float,float);
263 extern int32_t __ieee754_rem_pio2f (float,float*);
264 extern float __ieee754_scalbf (float,float);
265 extern int __ieee754_ilogbf (float);
268 /* float versions of fdlibm kernel functions */
269 extern float __kernel_sinf (float,float,int);
270 extern float __kernel_cosf (float,float);
271 extern float __kernel_tanf (float,float,int);
272 extern int __kernel_rem_pio2f (float*,float*,int,int,int, const int32_t*);
274 /* internal functions. */
275 extern float __copysignf (float x, float __y);
277 extern inline float __copysignf (float x, float y)
278 { return __builtin_copysignf (x, y); }
280 /* ieee style elementary long double functions */
281 extern long double __ieee754_sqrtl (long double);
282 extern long double __ieee754_acosl (long double);
283 extern long double __ieee754_acoshl (long double);
284 extern long double __ieee754_logl (long double);
285 extern long double __ieee754_atanhl (long double);
286 extern long double __ieee754_asinl (long double);
287 extern long double __ieee754_atan2l (long double,long double);
288 extern long double __ieee754_expl (long double);
289 extern long double __ieee754_exp2l (long double);
290 extern long double __ieee754_exp10l (long double);
291 extern long double __ieee754_coshl (long double);
292 extern long double __ieee754_fmodl (long double,long double);
293 extern long double __ieee754_powl (long double,long double);
294 extern long double __ieee754_lgammal_r (long double,int *);
295 extern long double __ieee754_gammal_r (long double,int *);
296 extern long double __ieee754_lgammal (long double);
297 extern long double __ieee754_gammal (long double);
298 extern long double __ieee754_log10l (long double);
299 extern long double __ieee754_log2l (long double);
300 extern long double __ieee754_sinhl (long double);
301 extern long double __ieee754_hypotl (long double,long double);
302 extern long double __ieee754_j0l (long double);
303 extern long double __ieee754_j1l (long double);
304 extern long double __ieee754_y0l (long double);
305 extern long double __ieee754_y1l (long double);
306 extern long double __ieee754_jnl (int,long double);
307 extern long double __ieee754_ynl (int,long double);
308 extern long double __ieee754_remainderl (long double,long double);
309 extern int __ieee754_rem_pio2l (long double,long double*);
310 extern long double __ieee754_scalbl (long double,long double);
311 extern int __ieee754_ilogbl (long double);
313 /* long double versions of fdlibm kernel functions */
314 extern long double __kernel_sinl (long double,long double,int);
315 extern long double __kernel_cosl (long double,long double);
316 extern long double __kernel_tanl (long double,long double,int);
317 extern void __kernel_sincosl (long double,long double,
318 long double *,long double *, int);
319 extern int __kernel_rem_pio2l (long double*,long double*,int,int,
320 int,const int*);
322 #ifndef NO_LONG_DOUBLE
323 /* prototypes required to compile the ldbl-96 support without warnings */
324 extern int __finitel (long double);
325 extern int __ilogbl (long double);
326 extern int __isinfl (long double);
327 extern int __isnanl (long double);
328 extern long double __atanl (long double);
329 extern long double __copysignl (long double, long double);
330 extern long double __expm1l (long double);
331 extern long double __floorl (long double);
332 extern long double __frexpl (long double, int *);
333 extern long double __ldexpl (long double, int);
334 extern long double __log1pl (long double);
335 extern long double __nanl (const char *);
336 extern long double __rintl (long double);
337 extern long double __scalbnl (long double, int);
338 extern long double __sqrtl (long double x);
339 extern long double fabsl (long double x);
340 extern void __sincosl (long double, long double *, long double *);
341 extern long double __logbl (long double x);
342 extern long double __significandl (long double x);
344 extern inline long double __copysignl (long double x, long double y)
345 { return __builtin_copysignl (x, y); }
347 #endif
349 /* Prototypes for functions of the IBM Accurate Mathematical Library. */
350 extern double __exp1 (double __x, double __xx, double __error);
351 extern double __sin (double __x);
352 extern double __cos (double __x);
353 extern int __branred (double __x, double *__a, double *__aa);
354 extern void __doasin (double __x, double __dx, double __v[]);
355 extern void __dubsin (double __x, double __dx, double __v[]);
356 extern void __dubcos (double __x, double __dx, double __v[]);
357 extern double __halfulp (double __x, double __y);
358 extern double __sin32 (double __x, double __res, double __res1);
359 extern double __cos32 (double __x, double __res, double __res1);
360 extern double __mpsin (double __x, double __dx, bool __range_reduce);
361 extern double __mpcos (double __x, double __dx, bool __range_reduce);
362 extern double __slowexp (double __x);
363 extern double __slowpow (double __x, double __y, double __z);
364 extern void __docos (double __x, double __dx, double __v[]);
366 /* Return X^2 + Y^2 - 1, computed without large cancellation error.
367 It is given that 1 > X >= Y >= epsilon / 2, and that either X >=
368 0.75 or Y >= 0.5. */
369 extern float __x2y2m1f (float x, float y);
370 extern double __x2y2m1 (double x, double y);
371 extern long double __x2y2m1l (long double x, long double y);
373 /* Compute the product of X + X_EPS, X + X_EPS + 1, ..., X + X_EPS + N
374 - 1, in the form R * (1 + *EPS) where the return value R is an
375 approximation to the product and *EPS is set to indicate the
376 approximate error in the return value. X is such that all the
377 values X + 1, ..., X + N - 1 are exactly representable, and X_EPS /
378 X is small enough that factors quadratic in it can be
379 neglected. */
380 extern float __gamma_productf (float x, float x_eps, int n, float *eps);
381 extern double __gamma_product (double x, double x_eps, int n, double *eps);
382 extern long double __gamma_productl (long double x, long double x_eps,
383 int n, long double *eps);
385 #ifndef math_opt_barrier
386 # define math_opt_barrier(x) \
387 ({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; })
388 # define math_force_eval(x) \
389 ({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); })
390 #endif
393 /* The standards only specify one variant of the fenv.h interfaces.
394 But at least for some architectures we can be more efficient if we
395 know what operations are going to be performed. Therefore we
396 define additional interfaces. By default they refer to the normal
397 interfaces. */
399 static __always_inline void
400 default_libc_feholdexcept (fenv_t *e)
402 (void) __feholdexcept (e);
405 #ifndef libc_feholdexcept
406 # define libc_feholdexcept default_libc_feholdexcept
407 #endif
408 #ifndef libc_feholdexceptf
409 # define libc_feholdexceptf default_libc_feholdexcept
410 #endif
411 #ifndef libc_feholdexceptl
412 # define libc_feholdexceptl default_libc_feholdexcept
413 #endif
415 static __always_inline void
416 default_libc_fesetround (int r)
418 (void) __fesetround (r);
421 #ifndef libc_fesetround
422 # define libc_fesetround default_libc_fesetround
423 #endif
424 #ifndef libc_fesetroundf
425 # define libc_fesetroundf default_libc_fesetround
426 #endif
427 #ifndef libc_fesetroundl
428 # define libc_fesetroundl default_libc_fesetround
429 #endif
431 static __always_inline void
432 default_libc_feholdexcept_setround (fenv_t *e, int r)
434 __feholdexcept (e);
435 __fesetround (r);
438 #ifndef libc_feholdexcept_setround
439 # define libc_feholdexcept_setround default_libc_feholdexcept_setround
440 #endif
441 #ifndef libc_feholdexcept_setroundf
442 # define libc_feholdexcept_setroundf default_libc_feholdexcept_setround
443 #endif
444 #ifndef libc_feholdexcept_setroundl
445 # define libc_feholdexcept_setroundl default_libc_feholdexcept_setround
446 #endif
448 #ifndef libc_feholdsetround_53bit
449 # define libc_feholdsetround_53bit libc_feholdsetround
450 #endif
452 #ifndef libc_fetestexcept
453 # define libc_fetestexcept fetestexcept
454 #endif
455 #ifndef libc_fetestexceptf
456 # define libc_fetestexceptf fetestexcept
457 #endif
458 #ifndef libc_fetestexceptl
459 # define libc_fetestexceptl fetestexcept
460 #endif
462 static __always_inline void
463 default_libc_fesetenv (fenv_t *e)
465 (void) __fesetenv (e);
468 #ifndef libc_fesetenv
469 # define libc_fesetenv default_libc_fesetenv
470 #endif
471 #ifndef libc_fesetenvf
472 # define libc_fesetenvf default_libc_fesetenv
473 #endif
474 #ifndef libc_fesetenvl
475 # define libc_fesetenvl default_libc_fesetenv
476 #endif
478 static __always_inline void
479 default_libc_feupdateenv (fenv_t *e)
481 (void) __feupdateenv (e);
484 #ifndef libc_feupdateenv
485 # define libc_feupdateenv default_libc_feupdateenv
486 #endif
487 #ifndef libc_feupdateenvf
488 # define libc_feupdateenvf default_libc_feupdateenv
489 #endif
490 #ifndef libc_feupdateenvl
491 # define libc_feupdateenvl default_libc_feupdateenv
492 #endif
494 #ifndef libc_feresetround_53bit
495 # define libc_feresetround_53bit libc_feresetround
496 #endif
498 static __always_inline int
499 default_libc_feupdateenv_test (fenv_t *e, int ex)
501 int ret = fetestexcept (ex);
502 __feupdateenv (e);
503 return ret;
506 #ifndef libc_feupdateenv_test
507 # define libc_feupdateenv_test default_libc_feupdateenv_test
508 #endif
509 #ifndef libc_feupdateenv_testf
510 # define libc_feupdateenv_testf default_libc_feupdateenv_test
511 #endif
512 #ifndef libc_feupdateenv_testl
513 # define libc_feupdateenv_testl default_libc_feupdateenv_test
514 #endif
516 /* Save and set the rounding mode. The use of fenv_t to store the old mode
517 allows a target-specific version of this function to avoid converting the
518 rounding mode from the fpu format. By default we have no choice but to
519 manipulate the entire env. */
521 #ifndef libc_feholdsetround
522 # define libc_feholdsetround libc_feholdexcept_setround
523 #endif
524 #ifndef libc_feholdsetroundf
525 # define libc_feholdsetroundf libc_feholdexcept_setroundf
526 #endif
527 #ifndef libc_feholdsetroundl
528 # define libc_feholdsetroundl libc_feholdexcept_setroundl
529 #endif
531 /* ... and the reverse. */
533 #ifndef libc_feresetround
534 # define libc_feresetround libc_feupdateenv
535 #endif
536 #ifndef libc_feresetroundf
537 # define libc_feresetroundf libc_feupdateenvf
538 #endif
539 #ifndef libc_feresetroundl
540 # define libc_feresetroundl libc_feupdateenvl
541 #endif
543 /* ... and a version that may also discard exceptions. */
545 #ifndef libc_feresetround_noex
546 # define libc_feresetround_noex libc_fesetenv
547 #endif
548 #ifndef libc_feresetround_noexf
549 # define libc_feresetround_noexf libc_fesetenvf
550 #endif
551 #ifndef libc_feresetround_noexl
552 # define libc_feresetround_noexl libc_fesetenvl
553 #endif
555 #ifndef HAVE_RM_CTX
556 # define HAVE_RM_CTX 0
557 #endif
559 #if HAVE_RM_CTX
560 /* Set/Restore Rounding Modes only when necessary. If defined, these functions
561 set/restore floating point state only if the state needed within the lexical
562 block is different from the current state. This saves a lot of time when
563 the floating point unit is much slower than the fixed point units. */
565 # ifndef libc_feholdsetround_noex_ctx
566 # define libc_feholdsetround_noex_ctx libc_feholdsetround_ctx
567 # endif
568 # ifndef libc_feholdsetround_noexf_ctx
569 # define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx
570 # endif
571 # ifndef libc_feholdsetround_noexl_ctx
572 # define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx
573 # endif
575 # ifndef libc_feresetround_noex_ctx
576 # define libc_feresetround_noex_ctx libc_fesetenv_ctx
577 # endif
578 # ifndef libc_feresetround_noexf_ctx
579 # define libc_feresetround_noexf_ctx libc_fesetenvf_ctx
580 # endif
581 # ifndef libc_feresetround_noexl_ctx
582 # define libc_feresetround_noexl_ctx libc_fesetenvl_ctx
583 # endif
585 #else
587 /* Default implementation using standard fenv functions.
588 Avoid unnecessary rounding mode changes by first checking the
589 current rounding mode. Note the use of __glibc_unlikely is
590 important for performance. */
592 static __always_inline void
593 libc_feholdsetround_ctx (struct rm_ctx *ctx, int round)
595 ctx->updated_status = false;
597 /* Update rounding mode only if different. */
598 if (__glibc_unlikely (round != get_rounding_mode ()))
600 ctx->updated_status = true;
601 __fegetenv (&ctx->env);
602 __fesetround (round);
606 static __always_inline void
607 libc_feresetround_ctx (struct rm_ctx *ctx)
609 /* Restore the rounding mode if updated. */
610 if (__glibc_unlikely (ctx->updated_status))
611 __feupdateenv (&ctx->env);
614 static __always_inline void
615 libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round)
617 /* Save exception flags and rounding mode. */
618 __fegetenv (&ctx->env);
620 /* Update rounding mode only if different. */
621 if (__glibc_unlikely (round != get_rounding_mode ()))
622 __fesetround (round);
625 static __always_inline void
626 libc_feresetround_noex_ctx (struct rm_ctx *ctx)
628 /* Restore exception flags and rounding mode. */
629 __fesetenv (&ctx->env);
632 # define libc_feholdsetroundf_ctx libc_feholdsetround_ctx
633 # define libc_feholdsetroundl_ctx libc_feholdsetround_ctx
634 # define libc_feresetroundf_ctx libc_feresetround_ctx
635 # define libc_feresetroundl_ctx libc_feresetround_ctx
637 # define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx
638 # define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx
639 # define libc_feresetround_noexf_ctx libc_feresetround_noex_ctx
640 # define libc_feresetround_noexl_ctx libc_feresetround_noex_ctx
642 #endif
644 #ifndef libc_feholdsetround_53bit_ctx
645 # define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx
646 #endif
647 #ifndef libc_feresetround_53bit_ctx
648 # define libc_feresetround_53bit_ctx libc_feresetround_ctx
649 #endif
651 #define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \
652 struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \
653 ROUNDFUNC ## _ctx (&ctx, (RM))
655 /* Set the rounding mode within a lexical block. Restore the rounding mode to
656 the value at the start of the block. The exception mode must be preserved.
657 Exceptions raised within the block must be set in the exception flags.
658 Non-stop mode may be enabled inside the block. */
660 #define SET_RESTORE_ROUND(RM) \
661 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround)
662 #define SET_RESTORE_ROUNDF(RM) \
663 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf)
664 #define SET_RESTORE_ROUNDL(RM) \
665 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl)
667 /* Set the rounding mode within a lexical block. Restore the rounding mode to
668 the value at the start of the block. The exception mode must be preserved.
669 Exceptions raised within the block must be discarded, and exception flags
670 are restored to the value at the start of the block.
671 Non-stop mode may be enabled inside the block. */
673 #define SET_RESTORE_ROUND_NOEX(RM) \
674 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \
675 libc_feresetround_noex)
676 #define SET_RESTORE_ROUND_NOEXF(RM) \
677 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \
678 libc_feresetround_noexf)
679 #define SET_RESTORE_ROUND_NOEXL(RM) \
680 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \
681 libc_feresetround_noexl)
683 /* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */
684 #define SET_RESTORE_ROUND_53BIT(RM) \
685 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit, \
686 libc_feresetround_53bit)
688 #define __nan(str) \
689 (__builtin_constant_p (str) && str[0] == '\0' ? NAN : __nan (str))
690 #define __nanf(str) \
691 (__builtin_constant_p (str) && str[0] == '\0' ? NAN : __nan (str))
692 #define __nanl(str) \
693 (__builtin_constant_p (str) && str[0] == '\0' ? NAN : __nan (str))
695 #endif /* _MATH_PRIVATE_H_ */