]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/generic/math_private.h
Obsolete matherr, _LIB_VERSION, libieee.a.
[thirdparty/glibc.git] / sysdeps / generic / math_private.h
CommitLineData
f7eac6eb
RM
1/*
2 * ====================================================
3 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
4 *
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 * ====================================================
10 */
11
12/*
13 * from: @(#)fdlibm.h 5.1 93/09/24
f7eac6eb
RM
14 */
15
16#ifndef _MATH_PRIVATE_H_
17#define _MATH_PRIVATE_H_
18
abfbdde1 19#include <endian.h>
cf00cc00 20#include <stdint.h>
f7eac6eb 21#include <sys/types.h>
b4dabbb4 22#include <fenv.h>
c8235dda 23#include <float.h>
e6d90d67 24#include <get-rounding-mode.h>
f7eac6eb 25
81f26b53
PM
26/* Gather machine dependent _Floatn support. */
27#include <bits/floatn.h>
28
f7eac6eb
RM
29/* The original fdlibm code used statements like:
30 n0 = ((*(int*)&one)>>29)^1; * index of high word *
31 ix0 = *(n0+(int*)&x); * high word of x *
32 ix1 = *((1-n0)+(int*)&x); * low word of x *
33 to dig two 32 bit words out of the 64 bit IEEE floating point
34 value. That is non-ANSI, and, moreover, the gcc instruction
35 scheduler gets it wrong. We instead use the following macros.
36 Unlike the original code, we determine the endianness at compile
37 time, not at run time; I don't see much benefit to selecting
38 endianness at run time. */
39
40/* A union which permits us to convert between a double and two 32 bit
41 ints. */
42
963394a2 43#if __FLOAT_WORD_ORDER == __BIG_ENDIAN
f7eac6eb
RM
44
45typedef union
46{
47 double value;
48 struct
49 {
24ab7723
JM
50 uint32_t msw;
51 uint32_t lsw;
f7eac6eb 52 } parts;
cf00cc00 53 uint64_t word;
f7eac6eb
RM
54} ieee_double_shape_type;
55
56#endif
57
963394a2 58#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
f7eac6eb
RM
59
60typedef union
61{
62 double value;
63 struct
64 {
24ab7723
JM
65 uint32_t lsw;
66 uint32_t msw;
f7eac6eb 67 } parts;
cf00cc00 68 uint64_t word;
f7eac6eb
RM
69} ieee_double_shape_type;
70
71#endif
72
73/* Get two 32 bit ints from a double. */
74
75#define EXTRACT_WORDS(ix0,ix1,d) \
76do { \
77 ieee_double_shape_type ew_u; \
78 ew_u.value = (d); \
79 (ix0) = ew_u.parts.msw; \
80 (ix1) = ew_u.parts.lsw; \
81} while (0)
82
83/* Get the more significant 32 bit int from a double. */
84
4851a949
RH
85#ifndef GET_HIGH_WORD
86# define GET_HIGH_WORD(i,d) \
f7eac6eb
RM
87do { \
88 ieee_double_shape_type gh_u; \
89 gh_u.value = (d); \
90 (i) = gh_u.parts.msw; \
91} while (0)
4851a949 92#endif
f7eac6eb
RM
93
94/* Get the less significant 32 bit int from a double. */
95
4851a949
RH
96#ifndef GET_LOW_WORD
97# define GET_LOW_WORD(i,d) \
f7eac6eb
RM
98do { \
99 ieee_double_shape_type gl_u; \
100 gl_u.value = (d); \
101 (i) = gl_u.parts.lsw; \
102} while (0)
4851a949 103#endif
f7eac6eb 104
cf00cc00 105/* Get all in one, efficient on 64-bit machines. */
4851a949
RH
106#ifndef EXTRACT_WORDS64
107# define EXTRACT_WORDS64(i,d) \
cf00cc00
UD
108do { \
109 ieee_double_shape_type gh_u; \
110 gh_u.value = (d); \
111 (i) = gh_u.word; \
112} while (0)
4851a949 113#endif
cf00cc00 114
f7eac6eb 115/* Set a double from two 32 bit ints. */
4851a949
RH
116#ifndef INSERT_WORDS
117# define INSERT_WORDS(d,ix0,ix1) \
f7eac6eb
RM
118do { \
119 ieee_double_shape_type iw_u; \
120 iw_u.parts.msw = (ix0); \
121 iw_u.parts.lsw = (ix1); \
122 (d) = iw_u.value; \
123} while (0)
4851a949 124#endif
f7eac6eb 125
cf00cc00 126/* Get all in one, efficient on 64-bit machines. */
4851a949
RH
127#ifndef INSERT_WORDS64
128# define INSERT_WORDS64(d,i) \
cf00cc00
UD
129do { \
130 ieee_double_shape_type iw_u; \
131 iw_u.word = (i); \
132 (d) = iw_u.value; \
133} while (0)
4851a949 134#endif
cf00cc00 135
f7eac6eb 136/* Set the more significant 32 bits of a double from an int. */
4851a949 137#ifndef SET_HIGH_WORD
f7eac6eb
RM
138#define SET_HIGH_WORD(d,v) \
139do { \
140 ieee_double_shape_type sh_u; \
141 sh_u.value = (d); \
142 sh_u.parts.msw = (v); \
143 (d) = sh_u.value; \
144} while (0)
4851a949 145#endif
f7eac6eb
RM
146
147/* Set the less significant 32 bits of a double from an int. */
4851a949
RH
148#ifndef SET_LOW_WORD
149# define SET_LOW_WORD(d,v) \
f7eac6eb
RM
150do { \
151 ieee_double_shape_type sl_u; \
152 sl_u.value = (d); \
153 sl_u.parts.lsw = (v); \
154 (d) = sl_u.value; \
155} while (0)
4851a949 156#endif
f7eac6eb
RM
157
158/* A union which permits us to convert between a float and a 32 bit
159 int. */
160
161typedef union
162{
163 float value;
24ab7723 164 uint32_t word;
f7eac6eb
RM
165} ieee_float_shape_type;
166
167/* Get a 32 bit int from a float. */
4851a949
RH
168#ifndef GET_FLOAT_WORD
169# define GET_FLOAT_WORD(i,d) \
f7eac6eb
RM
170do { \
171 ieee_float_shape_type gf_u; \
172 gf_u.value = (d); \
173 (i) = gf_u.word; \
174} while (0)
4851a949 175#endif
f7eac6eb
RM
176
177/* Set a float from a 32 bit int. */
4851a949
RH
178#ifndef SET_FLOAT_WORD
179# define SET_FLOAT_WORD(d,i) \
f7eac6eb
RM
180do { \
181 ieee_float_shape_type sf_u; \
182 sf_u.word = (i); \
183 (d) = sf_u.value; \
184} while (0)
4851a949 185#endif
f7eac6eb 186
593bf718
PM
187/* We need to guarantee an expansion of name when building
188 ldbl-128 files as another type (e.g _Float128). */
189#define mathx_hidden_def(name) hidden_def(name)
190
abfbdde1
UD
191/* Get long double macros from a separate header. */
192#include <math_ldbl.h>
76060ec0 193
9581e76d
GG
194/* Include function declarations for each floating-point. */
195#define _Mdouble_ double
196#define _MSUF_
197#include <math_private_calls.h>
198#undef _MSUF_
199#undef _Mdouble_
200
201#define _Mdouble_ float
202#define _MSUF_ f
203#define __MATH_DECLARING_FLOAT
204#include <math_private_calls.h>
205#undef __MATH_DECLARING_FLOAT
206#undef _MSUF_
207#undef _Mdouble_
208
209#define _Mdouble_ long double
210#define _MSUF_ l
211#define __MATH_DECLARING_LONG_DOUBLE
212#include <math_private_calls.h>
213#undef __MATH_DECLARING_LONG_DOUBLE
214#undef _MSUF_
215#undef _Mdouble_
f7eac6eb 216
81f26b53
PM
217#if __HAVE_DISTINCT_FLOAT128
218# define _Mdouble_ _Float128
219# define _MSUF_ f128
220# define __MATH_DECLARING_FLOATN
221# include <math_private_calls.h>
222# undef __MATH_DECLARING_FLOATN
223# undef _MSUF_
224# undef _Mdouble_
225#endif
226
227#if __HAVE_DISTINCT_FLOAT128
228
229/* __builtin_isinf_sign is broken in GCC < 7 for float128. */
230# if ! __GNUC_PREREQ (7, 0)
231# include <ieee754_float128.h>
232extern inline int
233__isinff128 (_Float128 x)
234{
235 int64_t hx, lx;
236 GET_FLOAT128_WORDS64 (hx, lx, x);
237 lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL;
238 lx |= -lx;
239 return ~(lx >> 63) & (hx >> 62);
240}
241# endif
242
243extern inline _Float128
244fabsf128 (_Float128 x)
245{
246 return __builtin_fabsf128 (x);
247}
248#endif
249
250
251
15b3c029
AJ
252/* Prototypes for functions of the IBM Accurate Mathematical Library. */
253extern double __exp1 (double __x, double __xx, double __error);
254extern double __sin (double __x);
255extern double __cos (double __x);
256extern int __branred (double __x, double *__a, double *__aa);
257extern void __doasin (double __x, double __dx, double __v[]);
258extern void __dubsin (double __x, double __dx, double __v[]);
259extern void __dubcos (double __x, double __dx, double __v[]);
260extern double __halfulp (double __x, double __y);
261extern double __sin32 (double __x, double __res, double __res1);
262extern double __cos32 (double __x, double __res, double __res1);
09544cbc
SP
263extern double __mpsin (double __x, double __dx, bool __range_reduce);
264extern double __mpcos (double __x, double __dx, bool __range_reduce);
15b3c029
AJ
265extern double __slowexp (double __x);
266extern double __slowpow (double __x, double __y, double __z);
267extern void __docos (double __x, double __dx, double __v[]);
268
3e336a87 269#ifndef math_opt_barrier
a784e502 270# define math_opt_barrier(x) \
f6ce9294 271({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; })
a784e502
UD
272# define math_force_eval(x) \
273({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); })
3e336a87
UD
274#endif
275
c8235dda
JM
276/* math_narrow_eval reduces its floating-point argument to the range
277 and precision of its semantic type. (The original evaluation may
278 still occur with excess range and precision, so the result may be
279 affected by double rounding.) */
280#if FLT_EVAL_METHOD == 0
281# define math_narrow_eval(x) (x)
282#else
283# if FLT_EVAL_METHOD == 1
284# define excess_precision(type) __builtin_types_compatible_p (type, float)
285# else
286# define excess_precision(type) (__builtin_types_compatible_p (type, float) \
287 || __builtin_types_compatible_p (type, \
288 double))
289# endif
290# define math_narrow_eval(x) \
291 ({ \
292 __typeof (x) math_narrow_eval_tmp = (x); \
293 if (excess_precision (__typeof (math_narrow_eval_tmp))) \
294 __asm__ ("" : "+m" (math_narrow_eval_tmp)); \
295 math_narrow_eval_tmp; \
296 })
297#endif
298
b4e75104 299#define fabs_tg(x) __MATH_TG ((x), (__typeof (x)) __builtin_fabs, (x))
81f26b53 300
219dd320
JM
301#define min_of_type_f FLT_MIN
302#define min_of_type_ DBL_MIN
303#define min_of_type_l LDBL_MIN
304#define min_of_type_f128 FLT128_MIN
305
306#define min_of_type(x) __MATH_TG ((x), (__typeof (x)) min_of_type_, )
d96164c3
JM
307
308/* If X (which is not a NaN) is subnormal, force an underflow
309 exception. */
310#define math_check_force_underflow(x) \
311 do \
312 { \
313 __typeof (x) force_underflow_tmp = (x); \
314 if (fabs_tg (force_underflow_tmp) \
219dd320 315 < min_of_type (force_underflow_tmp)) \
d96164c3
JM
316 { \
317 __typeof (force_underflow_tmp) force_underflow_tmp2 \
318 = force_underflow_tmp * force_underflow_tmp; \
319 math_force_eval (force_underflow_tmp2); \
320 } \
321 } \
322 while (0)
323/* Likewise, but X is also known to be nonnegative. */
324#define math_check_force_underflow_nonneg(x) \
325 do \
326 { \
327 __typeof (x) force_underflow_tmp = (x); \
328 if (force_underflow_tmp \
219dd320 329 < min_of_type (force_underflow_tmp)) \
d96164c3
JM
330 { \
331 __typeof (force_underflow_tmp) force_underflow_tmp2 \
332 = force_underflow_tmp * force_underflow_tmp; \
333 math_force_eval (force_underflow_tmp2); \
334 } \
335 } \
336 while (0)
337/* Likewise, for both real and imaginary parts of a complex
338 result. */
339#define math_check_force_underflow_complex(x) \
340 do \
341 { \
342 __typeof (x) force_underflow_complex_tmp = (x); \
343 math_check_force_underflow (__real__ force_underflow_complex_tmp); \
344 math_check_force_underflow (__imag__ force_underflow_complex_tmp); \
345 } \
346 while (0)
d38f1dba
UD
347
348/* The standards only specify one variant of the fenv.h interfaces.
349 But at least for some architectures we can be more efficient if we
350 know what operations are going to be performed. Therefore we
351 define additional interfaces. By default they refer to the normal
352 interfaces. */
d38f1dba 353
b4dabbb4
RH
354static __always_inline void
355default_libc_feholdexcept (fenv_t *e)
356{
ef9faf13 357 (void) __feholdexcept (e);
b4dabbb4
RH
358}
359
360#ifndef libc_feholdexcept
361# define libc_feholdexcept default_libc_feholdexcept
362#endif
363#ifndef libc_feholdexceptf
364# define libc_feholdexceptf default_libc_feholdexcept
365#endif
366#ifndef libc_feholdexceptl
367# define libc_feholdexceptl default_libc_feholdexcept
368#endif
369
5b5b04d6
JM
370static __always_inline void
371default_libc_fesetround (int r)
372{
01238691 373 (void) __fesetround (r);
5b5b04d6
JM
374}
375
376#ifndef libc_fesetround
377# define libc_fesetround default_libc_fesetround
378#endif
379#ifndef libc_fesetroundf
380# define libc_fesetroundf default_libc_fesetround
381#endif
382#ifndef libc_fesetroundl
383# define libc_fesetroundl default_libc_fesetround
384#endif
385
b4dabbb4
RH
386static __always_inline void
387default_libc_feholdexcept_setround (fenv_t *e, int r)
388{
ef9faf13 389 __feholdexcept (e);
01238691 390 __fesetround (r);
b4dabbb4
RH
391}
392
393#ifndef libc_feholdexcept_setround
394# define libc_feholdexcept_setround default_libc_feholdexcept_setround
395#endif
396#ifndef libc_feholdexcept_setroundf
397# define libc_feholdexcept_setroundf default_libc_feholdexcept_setround
398#endif
399#ifndef libc_feholdexcept_setroundl
400# define libc_feholdexcept_setroundl default_libc_feholdexcept_setround
401#endif
402
4c60cb0c
SP
403#ifndef libc_feholdsetround_53bit
404# define libc_feholdsetround_53bit libc_feholdsetround
b4dabbb4 405#endif
4855e3dd 406
b4dabbb4
RH
407#ifndef libc_fetestexcept
408# define libc_fetestexcept fetestexcept
409#endif
410#ifndef libc_fetestexceptf
411# define libc_fetestexceptf fetestexcept
412#endif
413#ifndef libc_fetestexceptl
414# define libc_fetestexceptl fetestexcept
415#endif
c4814b6b 416
b4dabbb4
RH
417static __always_inline void
418default_libc_fesetenv (fenv_t *e)
419{
cd42798a 420 (void) __fesetenv (e);
b4dabbb4 421}
d9a8d0ab 422
b4dabbb4
RH
423#ifndef libc_fesetenv
424# define libc_fesetenv default_libc_fesetenv
425#endif
426#ifndef libc_fesetenvf
427# define libc_fesetenvf default_libc_fesetenv
428#endif
429#ifndef libc_fesetenvl
430# define libc_fesetenvl default_libc_fesetenv
431#endif
d38f1dba 432
b4dabbb4
RH
433static __always_inline void
434default_libc_feupdateenv (fenv_t *e)
435{
8116321f 436 (void) __feupdateenv (e);
b4dabbb4
RH
437}
438
439#ifndef libc_feupdateenv
440# define libc_feupdateenv default_libc_feupdateenv
441#endif
442#ifndef libc_feupdateenvf
443# define libc_feupdateenvf default_libc_feupdateenv
444#endif
445#ifndef libc_feupdateenvl
446# define libc_feupdateenvl default_libc_feupdateenv
447#endif
d9a8d0ab 448
4c60cb0c
SP
449#ifndef libc_feresetround_53bit
450# define libc_feresetround_53bit libc_feresetround
b4dabbb4 451#endif
c4814b6b 452
0fe0f1f8
RH
453static __always_inline int
454default_libc_feupdateenv_test (fenv_t *e, int ex)
455{
456 int ret = fetestexcept (ex);
8116321f 457 __feupdateenv (e);
0fe0f1f8
RH
458 return ret;
459}
460
461#ifndef libc_feupdateenv_test
462# define libc_feupdateenv_test default_libc_feupdateenv_test
463#endif
464#ifndef libc_feupdateenv_testf
465# define libc_feupdateenv_testf default_libc_feupdateenv_test
466#endif
467#ifndef libc_feupdateenv_testl
468# define libc_feupdateenv_testl default_libc_feupdateenv_test
469#endif
470
eb92c487
RH
471/* Save and set the rounding mode. The use of fenv_t to store the old mode
472 allows a target-specific version of this function to avoid converting the
473 rounding mode from the fpu format. By default we have no choice but to
474 manipulate the entire env. */
475
476#ifndef libc_feholdsetround
477# define libc_feholdsetround libc_feholdexcept_setround
478#endif
479#ifndef libc_feholdsetroundf
480# define libc_feholdsetroundf libc_feholdexcept_setroundf
481#endif
482#ifndef libc_feholdsetroundl
483# define libc_feholdsetroundl libc_feholdexcept_setroundl
484#endif
485
486/* ... and the reverse. */
487
488#ifndef libc_feresetround
489# define libc_feresetround libc_feupdateenv
490#endif
491#ifndef libc_feresetroundf
492# define libc_feresetroundf libc_feupdateenvf
493#endif
494#ifndef libc_feresetroundl
495# define libc_feresetroundl libc_feupdateenvl
496#endif
497
498/* ... and a version that may also discard exceptions. */
499
500#ifndef libc_feresetround_noex
501# define libc_feresetround_noex libc_fesetenv
502#endif
503#ifndef libc_feresetround_noexf
504# define libc_feresetround_noexf libc_fesetenvf
505#endif
506#ifndef libc_feresetround_noexl
507# define libc_feresetround_noexl libc_fesetenvl
508#endif
509
e6d90d67
WD
510#ifndef HAVE_RM_CTX
511# define HAVE_RM_CTX 0
512#endif
513
d0ac1324 514#if HAVE_RM_CTX
25061094
SP
515/* Set/Restore Rounding Modes only when necessary. If defined, these functions
516 set/restore floating point state only if the state needed within the lexical
517 block is different from the current state. This saves a lot of time when
518 the floating point unit is much slower than the fixed point units. */
519
e6d90d67
WD
520# ifndef libc_feholdsetround_noex_ctx
521# define libc_feholdsetround_noex_ctx libc_feholdsetround_ctx
522# endif
523# ifndef libc_feholdsetround_noexf_ctx
524# define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx
525# endif
526# ifndef libc_feholdsetround_noexl_ctx
527# define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx
528# endif
529
25061094
SP
530# ifndef libc_feresetround_noex_ctx
531# define libc_feresetround_noex_ctx libc_fesetenv_ctx
532# endif
533# ifndef libc_feresetround_noexf_ctx
534# define libc_feresetround_noexf_ctx libc_fesetenvf_ctx
535# endif
536# ifndef libc_feresetround_noexl_ctx
537# define libc_feresetround_noexl_ctx libc_fesetenvl_ctx
538# endif
539
e6d90d67 540#else
25061094 541
e6d90d67
WD
542/* Default implementation using standard fenv functions.
543 Avoid unnecessary rounding mode changes by first checking the
544 current rounding mode. Note the use of __glibc_unlikely is
545 important for performance. */
25061094 546
e6d90d67
WD
547static __always_inline void
548libc_feholdsetround_ctx (struct rm_ctx *ctx, int round)
549{
550 ctx->updated_status = false;
551
552 /* Update rounding mode only if different. */
553 if (__glibc_unlikely (round != get_rounding_mode ()))
554 {
555 ctx->updated_status = true;
73a268c7 556 __fegetenv (&ctx->env);
01238691 557 __fesetround (round);
e6d90d67
WD
558 }
559}
560
561static __always_inline void
562libc_feresetround_ctx (struct rm_ctx *ctx)
563{
564 /* Restore the rounding mode if updated. */
565 if (__glibc_unlikely (ctx->updated_status))
8116321f 566 __feupdateenv (&ctx->env);
e6d90d67
WD
567}
568
569static __always_inline void
570libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round)
571{
572 /* Save exception flags and rounding mode. */
73a268c7 573 __fegetenv (&ctx->env);
e6d90d67
WD
574
575 /* Update rounding mode only if different. */
576 if (__glibc_unlikely (round != get_rounding_mode ()))
01238691 577 __fesetround (round);
e6d90d67
WD
578}
579
580static __always_inline void
581libc_feresetround_noex_ctx (struct rm_ctx *ctx)
582{
583 /* Restore exception flags and rounding mode. */
cd42798a 584 __fesetenv (&ctx->env);
e6d90d67
WD
585}
586
587# define libc_feholdsetroundf_ctx libc_feholdsetround_ctx
588# define libc_feholdsetroundl_ctx libc_feholdsetround_ctx
589# define libc_feresetroundf_ctx libc_feresetround_ctx
590# define libc_feresetroundl_ctx libc_feresetround_ctx
591
592# define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx
593# define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx
594# define libc_feresetround_noexf_ctx libc_feresetround_noex_ctx
595# define libc_feresetround_noexl_ctx libc_feresetround_noex_ctx
596
597#endif
598
599#ifndef libc_feholdsetround_53bit_ctx
600# define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx
601#endif
602#ifndef libc_feresetround_53bit_ctx
603# define libc_feresetround_53bit_ctx libc_feresetround_ctx
25061094
SP
604#endif
605
e6d90d67
WD
606#define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \
607 struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \
608 ROUNDFUNC ## _ctx (&ctx, (RM))
609
610/* Set the rounding mode within a lexical block. Restore the rounding mode to
611 the value at the start of the block. The exception mode must be preserved.
612 Exceptions raised within the block must be set in the exception flags.
613 Non-stop mode may be enabled inside the block. */
eb92c487
RH
614
615#define SET_RESTORE_ROUND(RM) \
25061094 616 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround)
eb92c487 617#define SET_RESTORE_ROUNDF(RM) \
25061094 618 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf)
eb92c487 619#define SET_RESTORE_ROUNDL(RM) \
25061094 620 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl)
eb92c487 621
e6d90d67
WD
622/* Set the rounding mode within a lexical block. Restore the rounding mode to
623 the value at the start of the block. The exception mode must be preserved.
624 Exceptions raised within the block must be discarded, and exception flags
625 are restored to the value at the start of the block.
626 Non-stop mode may be enabled inside the block. */
eb92c487
RH
627
628#define SET_RESTORE_ROUND_NOEX(RM) \
e6d90d67
WD
629 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \
630 libc_feresetround_noex)
eb92c487 631#define SET_RESTORE_ROUND_NOEXF(RM) \
e6d90d67
WD
632 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \
633 libc_feresetround_noexf)
eb92c487 634#define SET_RESTORE_ROUND_NOEXL(RM) \
e6d90d67
WD
635 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \
636 libc_feresetround_noexl)
eb92c487
RH
637
638/* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */
639#define SET_RESTORE_ROUND_53BIT(RM) \
25061094
SP
640 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit, \
641 libc_feresetround_53bit)
eb92c487 642
f7eac6eb 643#endif /* _MATH_PRIVATE_H_ */