Support mcount/gprof test with GCC defaulting to PIE
[glibc.git] / sysdeps / generic / math_private.h
blob4d962e1d09f445cce97a87e1f7d4a3c11e5965fd
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 <float.h>
24 #include <get-rounding-mode.h>
26 /* Gather machine dependent _Floatn support. */
27 #include <bits/floatn.h>
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. */
40 /* A union which permits us to convert between a double and two 32 bit
41 ints. */
43 #if __FLOAT_WORD_ORDER == __BIG_ENDIAN
45 typedef union
47 double value;
48 struct
50 uint32_t msw;
51 uint32_t lsw;
52 } parts;
53 uint64_t word;
54 } ieee_double_shape_type;
56 #endif
58 #if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
60 typedef union
62 double value;
63 struct
65 uint32_t lsw;
66 uint32_t msw;
67 } parts;
68 uint64_t word;
69 } ieee_double_shape_type;
71 #endif
73 /* Get two 32 bit ints from a double. */
75 #define EXTRACT_WORDS(ix0,ix1,d) \
76 do { \
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)
83 /* Get the more significant 32 bit int from a double. */
85 #ifndef GET_HIGH_WORD
86 # define GET_HIGH_WORD(i,d) \
87 do { \
88 ieee_double_shape_type gh_u; \
89 gh_u.value = (d); \
90 (i) = gh_u.parts.msw; \
91 } while (0)
92 #endif
94 /* Get the less significant 32 bit int from a double. */
96 #ifndef GET_LOW_WORD
97 # define GET_LOW_WORD(i,d) \
98 do { \
99 ieee_double_shape_type gl_u; \
100 gl_u.value = (d); \
101 (i) = gl_u.parts.lsw; \
102 } while (0)
103 #endif
105 /* Get all in one, efficient on 64-bit machines. */
106 #ifndef EXTRACT_WORDS64
107 # define EXTRACT_WORDS64(i,d) \
108 do { \
109 ieee_double_shape_type gh_u; \
110 gh_u.value = (d); \
111 (i) = gh_u.word; \
112 } while (0)
113 #endif
115 /* Set a double from two 32 bit ints. */
116 #ifndef INSERT_WORDS
117 # define INSERT_WORDS(d,ix0,ix1) \
118 do { \
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)
124 #endif
126 /* Get all in one, efficient on 64-bit machines. */
127 #ifndef INSERT_WORDS64
128 # define INSERT_WORDS64(d,i) \
129 do { \
130 ieee_double_shape_type iw_u; \
131 iw_u.word = (i); \
132 (d) = iw_u.value; \
133 } while (0)
134 #endif
136 /* Set the more significant 32 bits of a double from an int. */
137 #ifndef SET_HIGH_WORD
138 #define SET_HIGH_WORD(d,v) \
139 do { \
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)
145 #endif
147 /* Set the less significant 32 bits of a double from an int. */
148 #ifndef SET_LOW_WORD
149 # define SET_LOW_WORD(d,v) \
150 do { \
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)
156 #endif
158 /* A union which permits us to convert between a float and a 32 bit
159 int. */
161 typedef union
163 float value;
164 uint32_t word;
165 } ieee_float_shape_type;
167 /* Get a 32 bit int from a float. */
168 #ifndef GET_FLOAT_WORD
169 # define GET_FLOAT_WORD(i,d) \
170 do { \
171 ieee_float_shape_type gf_u; \
172 gf_u.value = (d); \
173 (i) = gf_u.word; \
174 } while (0)
175 #endif
177 /* Set a float from a 32 bit int. */
178 #ifndef SET_FLOAT_WORD
179 # define SET_FLOAT_WORD(d,i) \
180 do { \
181 ieee_float_shape_type sf_u; \
182 sf_u.word = (i); \
183 (d) = sf_u.value; \
184 } while (0)
185 #endif
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)
191 /* Get long double macros from a separate header. */
192 #include <math_ldbl.h>
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_
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_
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_
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
227 #if __HAVE_DISTINCT_FLOAT128
229 /* __builtin_isinf_sign is broken in GCC < 7 for float128. */
230 # if ! __GNUC_PREREQ (7, 0)
231 # include <ieee754_float128.h>
232 extern inline int
233 __isinff128 (_Float128 x)
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);
241 # endif
243 extern inline _Float128
244 fabsf128 (_Float128 x)
246 return __builtin_fabsf128 (x);
248 #endif
252 /* fdlibm kernel function */
253 extern double __kernel_standard (double,double,int);
254 extern float __kernel_standard_f (float,float,int);
255 extern long double __kernel_standard_l (long double,long double,int);
257 /* Prototypes for functions of the IBM Accurate Mathematical Library. */
258 extern double __exp1 (double __x, double __xx, double __error);
259 extern double __sin (double __x);
260 extern double __cos (double __x);
261 extern int __branred (double __x, double *__a, double *__aa);
262 extern void __doasin (double __x, double __dx, double __v[]);
263 extern void __dubsin (double __x, double __dx, double __v[]);
264 extern void __dubcos (double __x, double __dx, double __v[]);
265 extern double __halfulp (double __x, double __y);
266 extern double __sin32 (double __x, double __res, double __res1);
267 extern double __cos32 (double __x, double __res, double __res1);
268 extern double __mpsin (double __x, double __dx, bool __range_reduce);
269 extern double __mpcos (double __x, double __dx, bool __range_reduce);
270 extern double __slowexp (double __x);
271 extern double __slowpow (double __x, double __y, double __z);
272 extern void __docos (double __x, double __dx, double __v[]);
274 #ifndef math_opt_barrier
275 # define math_opt_barrier(x) \
276 ({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; })
277 # define math_force_eval(x) \
278 ({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); })
279 #endif
281 /* math_narrow_eval reduces its floating-point argument to the range
282 and precision of its semantic type. (The original evaluation may
283 still occur with excess range and precision, so the result may be
284 affected by double rounding.) */
285 #if FLT_EVAL_METHOD == 0
286 # define math_narrow_eval(x) (x)
287 #else
288 # if FLT_EVAL_METHOD == 1
289 # define excess_precision(type) __builtin_types_compatible_p (type, float)
290 # else
291 # define excess_precision(type) (__builtin_types_compatible_p (type, float) \
292 || __builtin_types_compatible_p (type, \
293 double))
294 # endif
295 # define math_narrow_eval(x) \
296 ({ \
297 __typeof (x) math_narrow_eval_tmp = (x); \
298 if (excess_precision (__typeof (math_narrow_eval_tmp))) \
299 __asm__ ("" : "+m" (math_narrow_eval_tmp)); \
300 math_narrow_eval_tmp; \
302 #endif
304 #define fabs_tg(x) __MATH_TG ((x), (__typeof (x)) __builtin_fabs, (x))
306 #define min_of_type_f FLT_MIN
307 #define min_of_type_ DBL_MIN
308 #define min_of_type_l LDBL_MIN
309 #define min_of_type_f128 FLT128_MIN
311 #define min_of_type(x) __MATH_TG ((x), (__typeof (x)) min_of_type_, )
313 /* If X (which is not a NaN) is subnormal, force an underflow
314 exception. */
315 #define math_check_force_underflow(x) \
316 do \
318 __typeof (x) force_underflow_tmp = (x); \
319 if (fabs_tg (force_underflow_tmp) \
320 < min_of_type (force_underflow_tmp)) \
322 __typeof (force_underflow_tmp) force_underflow_tmp2 \
323 = force_underflow_tmp * force_underflow_tmp; \
324 math_force_eval (force_underflow_tmp2); \
327 while (0)
328 /* Likewise, but X is also known to be nonnegative. */
329 #define math_check_force_underflow_nonneg(x) \
330 do \
332 __typeof (x) force_underflow_tmp = (x); \
333 if (force_underflow_tmp \
334 < min_of_type (force_underflow_tmp)) \
336 __typeof (force_underflow_tmp) force_underflow_tmp2 \
337 = force_underflow_tmp * force_underflow_tmp; \
338 math_force_eval (force_underflow_tmp2); \
341 while (0)
342 /* Likewise, for both real and imaginary parts of a complex
343 result. */
344 #define math_check_force_underflow_complex(x) \
345 do \
347 __typeof (x) force_underflow_complex_tmp = (x); \
348 math_check_force_underflow (__real__ force_underflow_complex_tmp); \
349 math_check_force_underflow (__imag__ force_underflow_complex_tmp); \
351 while (0)
353 /* The standards only specify one variant of the fenv.h interfaces.
354 But at least for some architectures we can be more efficient if we
355 know what operations are going to be performed. Therefore we
356 define additional interfaces. By default they refer to the normal
357 interfaces. */
359 static __always_inline void
360 default_libc_feholdexcept (fenv_t *e)
362 (void) __feholdexcept (e);
365 #ifndef libc_feholdexcept
366 # define libc_feholdexcept default_libc_feholdexcept
367 #endif
368 #ifndef libc_feholdexceptf
369 # define libc_feholdexceptf default_libc_feholdexcept
370 #endif
371 #ifndef libc_feholdexceptl
372 # define libc_feholdexceptl default_libc_feholdexcept
373 #endif
375 static __always_inline void
376 default_libc_fesetround (int r)
378 (void) __fesetround (r);
381 #ifndef libc_fesetround
382 # define libc_fesetround default_libc_fesetround
383 #endif
384 #ifndef libc_fesetroundf
385 # define libc_fesetroundf default_libc_fesetround
386 #endif
387 #ifndef libc_fesetroundl
388 # define libc_fesetroundl default_libc_fesetround
389 #endif
391 static __always_inline void
392 default_libc_feholdexcept_setround (fenv_t *e, int r)
394 __feholdexcept (e);
395 __fesetround (r);
398 #ifndef libc_feholdexcept_setround
399 # define libc_feholdexcept_setround default_libc_feholdexcept_setround
400 #endif
401 #ifndef libc_feholdexcept_setroundf
402 # define libc_feholdexcept_setroundf default_libc_feholdexcept_setround
403 #endif
404 #ifndef libc_feholdexcept_setroundl
405 # define libc_feholdexcept_setroundl default_libc_feholdexcept_setround
406 #endif
408 #ifndef libc_feholdsetround_53bit
409 # define libc_feholdsetround_53bit libc_feholdsetround
410 #endif
412 #ifndef libc_fetestexcept
413 # define libc_fetestexcept fetestexcept
414 #endif
415 #ifndef libc_fetestexceptf
416 # define libc_fetestexceptf fetestexcept
417 #endif
418 #ifndef libc_fetestexceptl
419 # define libc_fetestexceptl fetestexcept
420 #endif
422 static __always_inline void
423 default_libc_fesetenv (fenv_t *e)
425 (void) __fesetenv (e);
428 #ifndef libc_fesetenv
429 # define libc_fesetenv default_libc_fesetenv
430 #endif
431 #ifndef libc_fesetenvf
432 # define libc_fesetenvf default_libc_fesetenv
433 #endif
434 #ifndef libc_fesetenvl
435 # define libc_fesetenvl default_libc_fesetenv
436 #endif
438 static __always_inline void
439 default_libc_feupdateenv (fenv_t *e)
441 (void) __feupdateenv (e);
444 #ifndef libc_feupdateenv
445 # define libc_feupdateenv default_libc_feupdateenv
446 #endif
447 #ifndef libc_feupdateenvf
448 # define libc_feupdateenvf default_libc_feupdateenv
449 #endif
450 #ifndef libc_feupdateenvl
451 # define libc_feupdateenvl default_libc_feupdateenv
452 #endif
454 #ifndef libc_feresetround_53bit
455 # define libc_feresetround_53bit libc_feresetround
456 #endif
458 static __always_inline int
459 default_libc_feupdateenv_test (fenv_t *e, int ex)
461 int ret = fetestexcept (ex);
462 __feupdateenv (e);
463 return ret;
466 #ifndef libc_feupdateenv_test
467 # define libc_feupdateenv_test default_libc_feupdateenv_test
468 #endif
469 #ifndef libc_feupdateenv_testf
470 # define libc_feupdateenv_testf default_libc_feupdateenv_test
471 #endif
472 #ifndef libc_feupdateenv_testl
473 # define libc_feupdateenv_testl default_libc_feupdateenv_test
474 #endif
476 /* Save and set the rounding mode. The use of fenv_t to store the old mode
477 allows a target-specific version of this function to avoid converting the
478 rounding mode from the fpu format. By default we have no choice but to
479 manipulate the entire env. */
481 #ifndef libc_feholdsetround
482 # define libc_feholdsetround libc_feholdexcept_setround
483 #endif
484 #ifndef libc_feholdsetroundf
485 # define libc_feholdsetroundf libc_feholdexcept_setroundf
486 #endif
487 #ifndef libc_feholdsetroundl
488 # define libc_feholdsetroundl libc_feholdexcept_setroundl
489 #endif
491 /* ... and the reverse. */
493 #ifndef libc_feresetround
494 # define libc_feresetround libc_feupdateenv
495 #endif
496 #ifndef libc_feresetroundf
497 # define libc_feresetroundf libc_feupdateenvf
498 #endif
499 #ifndef libc_feresetroundl
500 # define libc_feresetroundl libc_feupdateenvl
501 #endif
503 /* ... and a version that may also discard exceptions. */
505 #ifndef libc_feresetround_noex
506 # define libc_feresetround_noex libc_fesetenv
507 #endif
508 #ifndef libc_feresetround_noexf
509 # define libc_feresetround_noexf libc_fesetenvf
510 #endif
511 #ifndef libc_feresetround_noexl
512 # define libc_feresetround_noexl libc_fesetenvl
513 #endif
515 #ifndef HAVE_RM_CTX
516 # define HAVE_RM_CTX 0
517 #endif
519 #if HAVE_RM_CTX
520 /* Set/Restore Rounding Modes only when necessary. If defined, these functions
521 set/restore floating point state only if the state needed within the lexical
522 block is different from the current state. This saves a lot of time when
523 the floating point unit is much slower than the fixed point units. */
525 # ifndef libc_feholdsetround_noex_ctx
526 # define libc_feholdsetround_noex_ctx libc_feholdsetround_ctx
527 # endif
528 # ifndef libc_feholdsetround_noexf_ctx
529 # define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx
530 # endif
531 # ifndef libc_feholdsetround_noexl_ctx
532 # define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx
533 # endif
535 # ifndef libc_feresetround_noex_ctx
536 # define libc_feresetround_noex_ctx libc_fesetenv_ctx
537 # endif
538 # ifndef libc_feresetround_noexf_ctx
539 # define libc_feresetround_noexf_ctx libc_fesetenvf_ctx
540 # endif
541 # ifndef libc_feresetround_noexl_ctx
542 # define libc_feresetround_noexl_ctx libc_fesetenvl_ctx
543 # endif
545 #else
547 /* Default implementation using standard fenv functions.
548 Avoid unnecessary rounding mode changes by first checking the
549 current rounding mode. Note the use of __glibc_unlikely is
550 important for performance. */
552 static __always_inline void
553 libc_feholdsetround_ctx (struct rm_ctx *ctx, int round)
555 ctx->updated_status = false;
557 /* Update rounding mode only if different. */
558 if (__glibc_unlikely (round != get_rounding_mode ()))
560 ctx->updated_status = true;
561 __fegetenv (&ctx->env);
562 __fesetround (round);
566 static __always_inline void
567 libc_feresetround_ctx (struct rm_ctx *ctx)
569 /* Restore the rounding mode if updated. */
570 if (__glibc_unlikely (ctx->updated_status))
571 __feupdateenv (&ctx->env);
574 static __always_inline void
575 libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round)
577 /* Save exception flags and rounding mode. */
578 __fegetenv (&ctx->env);
580 /* Update rounding mode only if different. */
581 if (__glibc_unlikely (round != get_rounding_mode ()))
582 __fesetround (round);
585 static __always_inline void
586 libc_feresetround_noex_ctx (struct rm_ctx *ctx)
588 /* Restore exception flags and rounding mode. */
589 __fesetenv (&ctx->env);
592 # define libc_feholdsetroundf_ctx libc_feholdsetround_ctx
593 # define libc_feholdsetroundl_ctx libc_feholdsetround_ctx
594 # define libc_feresetroundf_ctx libc_feresetround_ctx
595 # define libc_feresetroundl_ctx libc_feresetround_ctx
597 # define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx
598 # define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx
599 # define libc_feresetround_noexf_ctx libc_feresetround_noex_ctx
600 # define libc_feresetround_noexl_ctx libc_feresetround_noex_ctx
602 #endif
604 #ifndef libc_feholdsetround_53bit_ctx
605 # define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx
606 #endif
607 #ifndef libc_feresetround_53bit_ctx
608 # define libc_feresetround_53bit_ctx libc_feresetround_ctx
609 #endif
611 #define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \
612 struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \
613 ROUNDFUNC ## _ctx (&ctx, (RM))
615 /* Set the rounding mode within a lexical block. Restore the rounding mode to
616 the value at the start of the block. The exception mode must be preserved.
617 Exceptions raised within the block must be set in the exception flags.
618 Non-stop mode may be enabled inside the block. */
620 #define SET_RESTORE_ROUND(RM) \
621 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround)
622 #define SET_RESTORE_ROUNDF(RM) \
623 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf)
624 #define SET_RESTORE_ROUNDL(RM) \
625 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl)
627 /* Set the rounding mode within a lexical block. Restore the rounding mode to
628 the value at the start of the block. The exception mode must be preserved.
629 Exceptions raised within the block must be discarded, and exception flags
630 are restored to the value at the start of the block.
631 Non-stop mode may be enabled inside the block. */
633 #define SET_RESTORE_ROUND_NOEX(RM) \
634 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \
635 libc_feresetround_noex)
636 #define SET_RESTORE_ROUND_NOEXF(RM) \
637 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \
638 libc_feresetround_noexf)
639 #define SET_RESTORE_ROUND_NOEXL(RM) \
640 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \
641 libc_feresetround_noexl)
643 /* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */
644 #define SET_RESTORE_ROUND_53BIT(RM) \
645 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit, \
646 libc_feresetround_53bit)
648 #endif /* _MATH_PRIVATE_H_ */