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
14 */
15
16#ifndef _MATH_PRIVATE_H_
17#define _MATH_PRIVATE_H_
18
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>
25
26/* Gather machine dependent _Floatn support. */
27#include <bits/floatn.h>
28
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
43#if __FLOAT_WORD_ORDER == __BIG_ENDIAN
44
45typedef union
46{
47 double value;
48 struct
49 {
50 uint32_t msw;
51 uint32_t lsw;
52 } parts;
53 uint64_t word;
54} ieee_double_shape_type;
55
56#endif
57
58#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
59
60typedef union
61{
62 double value;
63 struct
64 {
65 uint32_t lsw;
66 uint32_t msw;
67 } parts;
68 uint64_t word;
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
85#ifndef GET_HIGH_WORD
86# define GET_HIGH_WORD(i,d) \
87do { \
88 ieee_double_shape_type gh_u; \
89 gh_u.value = (d); \
90 (i) = gh_u.parts.msw; \
91} while (0)
92#endif
93
94/* Get the less significant 32 bit int from a double. */
95
96#ifndef GET_LOW_WORD
97# define GET_LOW_WORD(i,d) \
98do { \
99 ieee_double_shape_type gl_u; \
100 gl_u.value = (d); \
101 (i) = gl_u.parts.lsw; \
102} while (0)
103#endif
104
105/* Get all in one, efficient on 64-bit machines. */
106#ifndef EXTRACT_WORDS64
107# define EXTRACT_WORDS64(i,d) \
108do { \
109 ieee_double_shape_type gh_u; \
110 gh_u.value = (d); \
111 (i) = gh_u.word; \
112} while (0)
113#endif
114
115/* Set a double from two 32 bit ints. */
116#ifndef INSERT_WORDS
117# define INSERT_WORDS(d,ix0,ix1) \
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)
124#endif
125
126/* Get all in one, efficient on 64-bit machines. */
127#ifndef INSERT_WORDS64
128# define INSERT_WORDS64(d,i) \
129do { \
130 ieee_double_shape_type iw_u; \
131 iw_u.word = (i); \
132 (d) = iw_u.value; \
133} while (0)
134#endif
135
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) \
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)
145#endif
146
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) \
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)
156#endif
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;
164 uint32_t word;
165} ieee_float_shape_type;
166
167/* Get a 32 bit int from a float. */
168#ifndef GET_FLOAT_WORD
169# define GET_FLOAT_WORD(i,d) \
170do { \
171 ieee_float_shape_type gf_u; \
172 gf_u.value = (d); \
173 (i) = gf_u.word; \
174} while (0)
175#endif
176
177/* Set a float from a 32 bit int. */
178#ifndef SET_FLOAT_WORD
179# define SET_FLOAT_WORD(d,i) \
180do { \
181 ieee_float_shape_type sf_u; \
182 sf_u.word = (i); \
183 (d) = sf_u.value; \
184} while (0)
185#endif
186
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
191/* Get long double macros from a separate header. */
192#include <math_ldbl.h>
193
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_
216
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
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);
263extern double __mpsin (double __x, double __dx, bool __range_reduce);
264extern double __mpcos (double __x, double __dx, bool __range_reduce);
265extern double __slowexp (double __x);
266extern double __slowpow (double __x, double __y, double __z);
267extern void __docos (double __x, double __dx, double __v[]);
268
269#ifndef math_opt_barrier
270# define math_opt_barrier(x) \
271({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; })
272# define math_force_eval(x) \
273({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); })
274#endif
275
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
299#define fabs_tg(x) __MATH_TG ((x), (__typeof (x)) __builtin_fabs, (x))
300
301/* These must be function-like macros because some __MATH_TG
302 implementations macro-expand the function-name argument before
303 concatenating a suffix to it. */
304#define min_of_type_f() FLT_MIN
305#define min_of_type_() DBL_MIN
306#define min_of_type_l() LDBL_MIN
307#define min_of_type_f128() FLT128_MIN
308
309#define min_of_type(x) __MATH_TG ((x), (__typeof (x)) min_of_type_, ())
310
311/* If X (which is not a NaN) is subnormal, force an underflow
312 exception. */
313#define math_check_force_underflow(x) \
314 do \
315 { \
316 __typeof (x) force_underflow_tmp = (x); \
317 if (fabs_tg (force_underflow_tmp) \
318 < min_of_type (force_underflow_tmp)) \
319 { \
320 __typeof (force_underflow_tmp) force_underflow_tmp2 \
321 = force_underflow_tmp * force_underflow_tmp; \
322 math_force_eval (force_underflow_tmp2); \
323 } \
324 } \
325 while (0)
326/* Likewise, but X is also known to be nonnegative. */
327#define math_check_force_underflow_nonneg(x) \
328 do \
329 { \
330 __typeof (x) force_underflow_tmp = (x); \
331 if (force_underflow_tmp \
332 < min_of_type (force_underflow_tmp)) \
333 { \
334 __typeof (force_underflow_tmp) force_underflow_tmp2 \
335 = force_underflow_tmp * force_underflow_tmp; \
336 math_force_eval (force_underflow_tmp2); \
337 } \
338 } \
339 while (0)
340/* Likewise, for both real and imaginary parts of a complex
341 result. */
342#define math_check_force_underflow_complex(x) \
343 do \
344 { \
345 __typeof (x) force_underflow_complex_tmp = (x); \
346 math_check_force_underflow (__real__ force_underflow_complex_tmp); \
347 math_check_force_underflow (__imag__ force_underflow_complex_tmp); \
348 } \
349 while (0)
350
351/* The standards only specify one variant of the fenv.h interfaces.
352 But at least for some architectures we can be more efficient if we
353 know what operations are going to be performed. Therefore we
354 define additional interfaces. By default they refer to the normal
355 interfaces. */
356
357static __always_inline void
358default_libc_feholdexcept (fenv_t *e)
359{
360 (void) __feholdexcept (e);
361}
362
363#ifndef libc_feholdexcept
364# define libc_feholdexcept default_libc_feholdexcept
365#endif
366#ifndef libc_feholdexceptf
367# define libc_feholdexceptf default_libc_feholdexcept
368#endif
369#ifndef libc_feholdexceptl
370# define libc_feholdexceptl default_libc_feholdexcept
371#endif
372
373static __always_inline void
374default_libc_fesetround (int r)
375{
376 (void) __fesetround (r);
377}
378
379#ifndef libc_fesetround
380# define libc_fesetround default_libc_fesetround
381#endif
382#ifndef libc_fesetroundf
383# define libc_fesetroundf default_libc_fesetround
384#endif
385#ifndef libc_fesetroundl
386# define libc_fesetroundl default_libc_fesetround
387#endif
388
389static __always_inline void
390default_libc_feholdexcept_setround (fenv_t *e, int r)
391{
392 __feholdexcept (e);
393 __fesetround (r);
394}
395
396#ifndef libc_feholdexcept_setround
397# define libc_feholdexcept_setround default_libc_feholdexcept_setround
398#endif
399#ifndef libc_feholdexcept_setroundf
400# define libc_feholdexcept_setroundf default_libc_feholdexcept_setround
401#endif
402#ifndef libc_feholdexcept_setroundl
403# define libc_feholdexcept_setroundl default_libc_feholdexcept_setround
404#endif
405
406#ifndef libc_feholdsetround_53bit
407# define libc_feholdsetround_53bit libc_feholdsetround
408#endif
409
410#ifndef libc_fetestexcept
411# define libc_fetestexcept fetestexcept
412#endif
413#ifndef libc_fetestexceptf
414# define libc_fetestexceptf fetestexcept
415#endif
416#ifndef libc_fetestexceptl
417# define libc_fetestexceptl fetestexcept
418#endif
419
420static __always_inline void
421default_libc_fesetenv (fenv_t *e)
422{
423 (void) __fesetenv (e);
424}
425
426#ifndef libc_fesetenv
427# define libc_fesetenv default_libc_fesetenv
428#endif
429#ifndef libc_fesetenvf
430# define libc_fesetenvf default_libc_fesetenv
431#endif
432#ifndef libc_fesetenvl
433# define libc_fesetenvl default_libc_fesetenv
434#endif
435
436static __always_inline void
437default_libc_feupdateenv (fenv_t *e)
438{
439 (void) __feupdateenv (e);
440}
441
442#ifndef libc_feupdateenv
443# define libc_feupdateenv default_libc_feupdateenv
444#endif
445#ifndef libc_feupdateenvf
446# define libc_feupdateenvf default_libc_feupdateenv
447#endif
448#ifndef libc_feupdateenvl
449# define libc_feupdateenvl default_libc_feupdateenv
450#endif
451
452#ifndef libc_feresetround_53bit
453# define libc_feresetround_53bit libc_feresetround
454#endif
455
456static __always_inline int
457default_libc_feupdateenv_test (fenv_t *e, int ex)
458{
459 int ret = fetestexcept (ex);
460 __feupdateenv (e);
461 return ret;
462}
463
464#ifndef libc_feupdateenv_test
465# define libc_feupdateenv_test default_libc_feupdateenv_test
466#endif
467#ifndef libc_feupdateenv_testf
468# define libc_feupdateenv_testf default_libc_feupdateenv_test
469#endif
470#ifndef libc_feupdateenv_testl
471# define libc_feupdateenv_testl default_libc_feupdateenv_test
472#endif
473
474/* Save and set the rounding mode. The use of fenv_t to store the old mode
475 allows a target-specific version of this function to avoid converting the
476 rounding mode from the fpu format. By default we have no choice but to
477 manipulate the entire env. */
478
479#ifndef libc_feholdsetround
480# define libc_feholdsetround libc_feholdexcept_setround
481#endif
482#ifndef libc_feholdsetroundf
483# define libc_feholdsetroundf libc_feholdexcept_setroundf
484#endif
485#ifndef libc_feholdsetroundl
486# define libc_feholdsetroundl libc_feholdexcept_setroundl
487#endif
488
489/* ... and the reverse. */
490
491#ifndef libc_feresetround
492# define libc_feresetround libc_feupdateenv
493#endif
494#ifndef libc_feresetroundf
495# define libc_feresetroundf libc_feupdateenvf
496#endif
497#ifndef libc_feresetroundl
498# define libc_feresetroundl libc_feupdateenvl
499#endif
500
501/* ... and a version that also discards exceptions. */
502
503#ifndef libc_feresetround_noex
504# define libc_feresetround_noex libc_fesetenv
505#endif
506#ifndef libc_feresetround_noexf
507# define libc_feresetround_noexf libc_fesetenvf
508#endif
509#ifndef libc_feresetround_noexl
510# define libc_feresetround_noexl libc_fesetenvl
511#endif
512
513#ifndef HAVE_RM_CTX
514# define HAVE_RM_CTX 0
515#endif
516
517
518/* Default implementation using standard fenv functions.
519 Avoid unnecessary rounding mode changes by first checking the
520 current rounding mode. Note the use of __glibc_unlikely is
521 important for performance. */
522
523static __always_inline void
524default_libc_feholdsetround_ctx (struct rm_ctx *ctx, int round)
525{
526 ctx->updated_status = false;
527
528 /* Update rounding mode only if different. */
529 if (__glibc_unlikely (round != get_rounding_mode ()))
530 {
531 ctx->updated_status = true;
532 __fegetenv (&ctx->env);
533 __fesetround (round);
534 }
535}
536
537static __always_inline void
538default_libc_feresetround_ctx (struct rm_ctx *ctx)
539{
540 /* Restore the rounding mode if updated. */
541 if (__glibc_unlikely (ctx->updated_status))
542 __feupdateenv (&ctx->env);
543}
544
545static __always_inline void
546default_libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round)
547{
548 /* Save exception flags and rounding mode, and disable exception
549 traps. */
550 __feholdexcept (&ctx->env);
551
552 /* Update rounding mode only if different. */
553 if (__glibc_unlikely (round != get_rounding_mode ()))
554 __fesetround (round);
555}
556
557static __always_inline void
558default_libc_feresetround_noex_ctx (struct rm_ctx *ctx)
559{
560 /* Restore exception flags and rounding mode. */
561 __fesetenv (&ctx->env);
562}
563
564#if HAVE_RM_CTX
565/* Set/Restore Rounding Modes only when necessary. If defined, these functions
566 set/restore floating point state only if the state needed within the lexical
567 block is different from the current state. This saves a lot of time when
568 the floating point unit is much slower than the fixed point units. */
569
570# ifndef libc_feholdsetround_noex_ctx
571# define libc_feholdsetround_noex_ctx libc_feholdsetround_ctx
572# endif
573# ifndef libc_feholdsetround_noexf_ctx
574# define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx
575# endif
576# ifndef libc_feholdsetround_noexl_ctx
577# define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx
578# endif
579
580# ifndef libc_feresetround_noex_ctx
581# define libc_feresetround_noex_ctx libc_fesetenv_ctx
582# endif
583# ifndef libc_feresetround_noexf_ctx
584# define libc_feresetround_noexf_ctx libc_fesetenvf_ctx
585# endif
586# ifndef libc_feresetround_noexl_ctx
587# define libc_feresetround_noexl_ctx libc_fesetenvl_ctx
588# endif
589
590#else
591
592# define libc_feholdsetround_ctx default_libc_feholdsetround_ctx
593# define libc_feresetround_ctx default_libc_feresetround_ctx
594# define libc_feholdsetround_noex_ctx default_libc_feholdsetround_noex_ctx
595# define libc_feresetround_noex_ctx default_libc_feresetround_noex_ctx
596
597# define libc_feholdsetroundf_ctx libc_feholdsetround_ctx
598# define libc_feholdsetroundl_ctx libc_feholdsetround_ctx
599# define libc_feresetroundf_ctx libc_feresetround_ctx
600# define libc_feresetroundl_ctx libc_feresetround_ctx
601
602# define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx
603# define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx
604# define libc_feresetround_noexf_ctx libc_feresetround_noex_ctx
605# define libc_feresetround_noexl_ctx libc_feresetround_noex_ctx
606
607#endif
608
609#ifndef libc_feholdsetround_53bit_ctx
610# define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx
611#endif
612#ifndef libc_feresetround_53bit_ctx
613# define libc_feresetround_53bit_ctx libc_feresetround_ctx
614#endif
615
616#define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \
617 struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \
618 ROUNDFUNC ## _ctx (&ctx, (RM))
619
620/* Set the rounding mode within a lexical block. Restore the rounding mode to
621 the value at the start of the block. The exception mode must be preserved.
622 Exceptions raised within the block must be set in the exception flags.
623 Non-stop mode may be enabled inside the block. */
624
625#define SET_RESTORE_ROUND(RM) \
626 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround)
627#define SET_RESTORE_ROUNDF(RM) \
628 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf)
629#define SET_RESTORE_ROUNDL(RM) \
630 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl)
631
632/* Set the rounding mode within a lexical block. Restore the rounding mode to
633 the value at the start of the block. The exception mode must be preserved.
634 Exceptions raised within the block must be discarded, and exception flags
635 are restored to the value at the start of the block.
636 Non-stop mode must be enabled inside the block. */
637
638#define SET_RESTORE_ROUND_NOEX(RM) \
639 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \
640 libc_feresetround_noex)
641#define SET_RESTORE_ROUND_NOEXF(RM) \
642 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \
643 libc_feresetround_noexf)
644#define SET_RESTORE_ROUND_NOEXL(RM) \
645 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \
646 libc_feresetround_noexl)
647
648/* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */
649#define SET_RESTORE_ROUND_53BIT(RM) \
650 SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit, \
651 libc_feresetround_53bit)
652
653#endif /* _MATH_PRIVATE_H_ */
654