1*f504f610SAugustin Cavalier #ifndef _LIBM_H
2*f504f610SAugustin Cavalier #define _LIBM_H
3*f504f610SAugustin Cavalier
4*f504f610SAugustin Cavalier #include <stdint.h>
5*f504f610SAugustin Cavalier #include <float.h>
6*f504f610SAugustin Cavalier #include <math.h>
7*f504f610SAugustin Cavalier #include <endian.h>
8*f504f610SAugustin Cavalier #include <features.h>
9*f504f610SAugustin Cavalier #include "fp_arch.h"
10*f504f610SAugustin Cavalier
11*f504f610SAugustin Cavalier #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
12*f504f610SAugustin Cavalier #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN
13*f504f610SAugustin Cavalier union ldshape {
14*f504f610SAugustin Cavalier long double f;
15*f504f610SAugustin Cavalier struct {
16*f504f610SAugustin Cavalier uint64_t m;
17*f504f610SAugustin Cavalier uint16_t se;
18*f504f610SAugustin Cavalier } i;
19*f504f610SAugustin Cavalier };
20*f504f610SAugustin Cavalier #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN
21*f504f610SAugustin Cavalier /* This is the m68k variant of 80-bit long double, and this definition only works
22*f504f610SAugustin Cavalier * on archs where the alignment requirement of uint64_t is <= 4. */
23*f504f610SAugustin Cavalier union ldshape {
24*f504f610SAugustin Cavalier long double f;
25*f504f610SAugustin Cavalier struct {
26*f504f610SAugustin Cavalier uint16_t se;
27*f504f610SAugustin Cavalier uint16_t pad;
28*f504f610SAugustin Cavalier uint64_t m;
29*f504f610SAugustin Cavalier } i;
30*f504f610SAugustin Cavalier };
31*f504f610SAugustin Cavalier #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN
32*f504f610SAugustin Cavalier union ldshape {
33*f504f610SAugustin Cavalier long double f;
34*f504f610SAugustin Cavalier struct {
35*f504f610SAugustin Cavalier uint64_t lo;
36*f504f610SAugustin Cavalier uint32_t mid;
37*f504f610SAugustin Cavalier uint16_t top;
38*f504f610SAugustin Cavalier uint16_t se;
39*f504f610SAugustin Cavalier } i;
40*f504f610SAugustin Cavalier struct {
41*f504f610SAugustin Cavalier uint64_t lo;
42*f504f610SAugustin Cavalier uint64_t hi;
43*f504f610SAugustin Cavalier } i2;
44*f504f610SAugustin Cavalier };
45*f504f610SAugustin Cavalier #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN
46*f504f610SAugustin Cavalier union ldshape {
47*f504f610SAugustin Cavalier long double f;
48*f504f610SAugustin Cavalier struct {
49*f504f610SAugustin Cavalier uint16_t se;
50*f504f610SAugustin Cavalier uint16_t top;
51*f504f610SAugustin Cavalier uint32_t mid;
52*f504f610SAugustin Cavalier uint64_t lo;
53*f504f610SAugustin Cavalier } i;
54*f504f610SAugustin Cavalier struct {
55*f504f610SAugustin Cavalier uint64_t hi;
56*f504f610SAugustin Cavalier uint64_t lo;
57*f504f610SAugustin Cavalier } i2;
58*f504f610SAugustin Cavalier };
59*f504f610SAugustin Cavalier #else
60*f504f610SAugustin Cavalier #error Unsupported long double representation
61*f504f610SAugustin Cavalier #endif
62*f504f610SAugustin Cavalier
63*f504f610SAugustin Cavalier /* Support non-nearest rounding mode. */
64*f504f610SAugustin Cavalier #define WANT_ROUNDING 1
65*f504f610SAugustin Cavalier /* Support signaling NaNs. */
66*f504f610SAugustin Cavalier #define WANT_SNAN 0
67*f504f610SAugustin Cavalier
68*f504f610SAugustin Cavalier #if WANT_SNAN
69*f504f610SAugustin Cavalier #error SNaN is unsupported
70*f504f610SAugustin Cavalier #else
71*f504f610SAugustin Cavalier #define issignalingf_inline(x) 0
72*f504f610SAugustin Cavalier #define issignaling_inline(x) 0
73*f504f610SAugustin Cavalier #endif
74*f504f610SAugustin Cavalier
75*f504f610SAugustin Cavalier #ifndef TOINT_INTRINSICS
76*f504f610SAugustin Cavalier #define TOINT_INTRINSICS 0
77*f504f610SAugustin Cavalier #endif
78*f504f610SAugustin Cavalier
79*f504f610SAugustin Cavalier #if TOINT_INTRINSICS
80*f504f610SAugustin Cavalier /* Round x to nearest int in all rounding modes, ties have to be rounded
81*f504f610SAugustin Cavalier consistently with converttoint so the results match. If the result
82*f504f610SAugustin Cavalier would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */
83*f504f610SAugustin Cavalier static double_t roundtoint(double_t);
84*f504f610SAugustin Cavalier
85*f504f610SAugustin Cavalier /* Convert x to nearest int in all rounding modes, ties have to be rounded
86*f504f610SAugustin Cavalier consistently with roundtoint. If the result is not representible in an
87*f504f610SAugustin Cavalier int32_t then the semantics is unspecified. */
88*f504f610SAugustin Cavalier static int32_t converttoint(double_t);
89*f504f610SAugustin Cavalier #endif
90*f504f610SAugustin Cavalier
91*f504f610SAugustin Cavalier /* Helps static branch prediction so hot path can be better optimized. */
92*f504f610SAugustin Cavalier #ifdef __GNUC__
93*f504f610SAugustin Cavalier #define predict_true(x) __builtin_expect(!!(x), 1)
94*f504f610SAugustin Cavalier #define predict_false(x) __builtin_expect(x, 0)
95*f504f610SAugustin Cavalier #else
96*f504f610SAugustin Cavalier #define predict_true(x) (x)
97*f504f610SAugustin Cavalier #define predict_false(x) (x)
98*f504f610SAugustin Cavalier #endif
99*f504f610SAugustin Cavalier
100*f504f610SAugustin Cavalier /* Evaluate an expression as the specified type. With standard excess
101*f504f610SAugustin Cavalier precision handling a type cast or assignment is enough (with
102*f504f610SAugustin Cavalier -ffloat-store an assignment is required, in old compilers argument
103*f504f610SAugustin Cavalier passing and return statement may not drop excess precision). */
104*f504f610SAugustin Cavalier
eval_as_float(float x)105*f504f610SAugustin Cavalier static inline float eval_as_float(float x)
106*f504f610SAugustin Cavalier {
107*f504f610SAugustin Cavalier float y = x;
108*f504f610SAugustin Cavalier return y;
109*f504f610SAugustin Cavalier }
110*f504f610SAugustin Cavalier
eval_as_double(double x)111*f504f610SAugustin Cavalier static inline double eval_as_double(double x)
112*f504f610SAugustin Cavalier {
113*f504f610SAugustin Cavalier double y = x;
114*f504f610SAugustin Cavalier return y;
115*f504f610SAugustin Cavalier }
116*f504f610SAugustin Cavalier
117*f504f610SAugustin Cavalier /* fp_barrier returns its input, but limits code transformations
118*f504f610SAugustin Cavalier as if it had a side-effect (e.g. observable io) and returned
119*f504f610SAugustin Cavalier an arbitrary value. */
120*f504f610SAugustin Cavalier
121*f504f610SAugustin Cavalier #ifndef fp_barrierf
122*f504f610SAugustin Cavalier #define fp_barrierf fp_barrierf
fp_barrierf(float x)123*f504f610SAugustin Cavalier static inline float fp_barrierf(float x)
124*f504f610SAugustin Cavalier {
125*f504f610SAugustin Cavalier volatile float y = x;
126*f504f610SAugustin Cavalier return y;
127*f504f610SAugustin Cavalier }
128*f504f610SAugustin Cavalier #endif
129*f504f610SAugustin Cavalier
130*f504f610SAugustin Cavalier #ifndef fp_barrier
131*f504f610SAugustin Cavalier #define fp_barrier fp_barrier
fp_barrier(double x)132*f504f610SAugustin Cavalier static inline double fp_barrier(double x)
133*f504f610SAugustin Cavalier {
134*f504f610SAugustin Cavalier volatile double y = x;
135*f504f610SAugustin Cavalier return y;
136*f504f610SAugustin Cavalier }
137*f504f610SAugustin Cavalier #endif
138*f504f610SAugustin Cavalier
139*f504f610SAugustin Cavalier #ifndef fp_barrierl
140*f504f610SAugustin Cavalier #define fp_barrierl fp_barrierl
fp_barrierl(long double x)141*f504f610SAugustin Cavalier static inline long double fp_barrierl(long double x)
142*f504f610SAugustin Cavalier {
143*f504f610SAugustin Cavalier volatile long double y = x;
144*f504f610SAugustin Cavalier return y;
145*f504f610SAugustin Cavalier }
146*f504f610SAugustin Cavalier #endif
147*f504f610SAugustin Cavalier
148*f504f610SAugustin Cavalier /* fp_force_eval ensures that the input value is computed when that's
149*f504f610SAugustin Cavalier otherwise unused. To prevent the constant folding of the input
150*f504f610SAugustin Cavalier expression, an additional fp_barrier may be needed or a compilation
151*f504f610SAugustin Cavalier mode that does so (e.g. -frounding-math in gcc). Then it can be
152*f504f610SAugustin Cavalier used to evaluate an expression for its fenv side-effects only. */
153*f504f610SAugustin Cavalier
154*f504f610SAugustin Cavalier #ifndef fp_force_evalf
155*f504f610SAugustin Cavalier #define fp_force_evalf fp_force_evalf
fp_force_evalf(float x)156*f504f610SAugustin Cavalier static inline void fp_force_evalf(float x)
157*f504f610SAugustin Cavalier {
158*f504f610SAugustin Cavalier volatile float y;
159*f504f610SAugustin Cavalier y = x;
160*f504f610SAugustin Cavalier }
161*f504f610SAugustin Cavalier #endif
162*f504f610SAugustin Cavalier
163*f504f610SAugustin Cavalier #ifndef fp_force_eval
164*f504f610SAugustin Cavalier #define fp_force_eval fp_force_eval
fp_force_eval(double x)165*f504f610SAugustin Cavalier static inline void fp_force_eval(double x)
166*f504f610SAugustin Cavalier {
167*f504f610SAugustin Cavalier volatile double y;
168*f504f610SAugustin Cavalier y = x;
169*f504f610SAugustin Cavalier }
170*f504f610SAugustin Cavalier #endif
171*f504f610SAugustin Cavalier
172*f504f610SAugustin Cavalier #ifndef fp_force_evall
173*f504f610SAugustin Cavalier #define fp_force_evall fp_force_evall
fp_force_evall(long double x)174*f504f610SAugustin Cavalier static inline void fp_force_evall(long double x)
175*f504f610SAugustin Cavalier {
176*f504f610SAugustin Cavalier volatile long double y;
177*f504f610SAugustin Cavalier y = x;
178*f504f610SAugustin Cavalier }
179*f504f610SAugustin Cavalier #endif
180*f504f610SAugustin Cavalier
181*f504f610SAugustin Cavalier #define FORCE_EVAL(x) do { \
182*f504f610SAugustin Cavalier if (sizeof(x) == sizeof(float)) { \
183*f504f610SAugustin Cavalier fp_force_evalf(x); \
184*f504f610SAugustin Cavalier } else if (sizeof(x) == sizeof(double)) { \
185*f504f610SAugustin Cavalier fp_force_eval(x); \
186*f504f610SAugustin Cavalier } else { \
187*f504f610SAugustin Cavalier fp_force_evall(x); \
188*f504f610SAugustin Cavalier } \
189*f504f610SAugustin Cavalier } while(0)
190*f504f610SAugustin Cavalier
191*f504f610SAugustin Cavalier #define asuint(f) ((union{float _f; uint32_t _i;}){f})._i
192*f504f610SAugustin Cavalier #define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f
193*f504f610SAugustin Cavalier #define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i
194*f504f610SAugustin Cavalier #define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f
195*f504f610SAugustin Cavalier
196*f504f610SAugustin Cavalier #define EXTRACT_WORDS(hi,lo,d) \
197*f504f610SAugustin Cavalier do { \
198*f504f610SAugustin Cavalier uint64_t __u = asuint64(d); \
199*f504f610SAugustin Cavalier (hi) = __u >> 32; \
200*f504f610SAugustin Cavalier (lo) = (uint32_t)__u; \
201*f504f610SAugustin Cavalier } while (0)
202*f504f610SAugustin Cavalier
203*f504f610SAugustin Cavalier #define GET_HIGH_WORD(hi,d) \
204*f504f610SAugustin Cavalier do { \
205*f504f610SAugustin Cavalier (hi) = asuint64(d) >> 32; \
206*f504f610SAugustin Cavalier } while (0)
207*f504f610SAugustin Cavalier
208*f504f610SAugustin Cavalier #define GET_LOW_WORD(lo,d) \
209*f504f610SAugustin Cavalier do { \
210*f504f610SAugustin Cavalier (lo) = (uint32_t)asuint64(d); \
211*f504f610SAugustin Cavalier } while (0)
212*f504f610SAugustin Cavalier
213*f504f610SAugustin Cavalier #define INSERT_WORDS(d,hi,lo) \
214*f504f610SAugustin Cavalier do { \
215*f504f610SAugustin Cavalier (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \
216*f504f610SAugustin Cavalier } while (0)
217*f504f610SAugustin Cavalier
218*f504f610SAugustin Cavalier #define SET_HIGH_WORD(d,hi) \
219*f504f610SAugustin Cavalier INSERT_WORDS(d, hi, (uint32_t)asuint64(d))
220*f504f610SAugustin Cavalier
221*f504f610SAugustin Cavalier #define SET_LOW_WORD(d,lo) \
222*f504f610SAugustin Cavalier INSERT_WORDS(d, asuint64(d)>>32, lo)
223*f504f610SAugustin Cavalier
224*f504f610SAugustin Cavalier #define GET_FLOAT_WORD(w,d) \
225*f504f610SAugustin Cavalier do { \
226*f504f610SAugustin Cavalier (w) = asuint(d); \
227*f504f610SAugustin Cavalier } while (0)
228*f504f610SAugustin Cavalier
229*f504f610SAugustin Cavalier #define SET_FLOAT_WORD(d,w) \
230*f504f610SAugustin Cavalier do { \
231*f504f610SAugustin Cavalier (d) = asfloat(w); \
232*f504f610SAugustin Cavalier } while (0)
233*f504f610SAugustin Cavalier
234*f504f610SAugustin Cavalier hidden int __rem_pio2_large(double*,double*,int,int,int);
235*f504f610SAugustin Cavalier
236*f504f610SAugustin Cavalier hidden int __rem_pio2(double,double*);
237*f504f610SAugustin Cavalier hidden double __sin(double,double,int);
238*f504f610SAugustin Cavalier hidden double __cos(double,double);
239*f504f610SAugustin Cavalier hidden double __tan(double,double,int);
240*f504f610SAugustin Cavalier hidden double __expo2(double);
241*f504f610SAugustin Cavalier
242*f504f610SAugustin Cavalier hidden int __rem_pio2f(float,double*);
243*f504f610SAugustin Cavalier hidden float __sindf(double);
244*f504f610SAugustin Cavalier hidden float __cosdf(double);
245*f504f610SAugustin Cavalier hidden float __tandf(double,int);
246*f504f610SAugustin Cavalier hidden float __expo2f(float);
247*f504f610SAugustin Cavalier
248*f504f610SAugustin Cavalier hidden int __rem_pio2l(long double, long double *);
249*f504f610SAugustin Cavalier hidden long double __sinl(long double, long double, int);
250*f504f610SAugustin Cavalier hidden long double __cosl(long double, long double);
251*f504f610SAugustin Cavalier hidden long double __tanl(long double, long double, int);
252*f504f610SAugustin Cavalier
253*f504f610SAugustin Cavalier hidden long double __polevll(long double, const long double *, int);
254*f504f610SAugustin Cavalier hidden long double __p1evll(long double, const long double *, int);
255*f504f610SAugustin Cavalier
256*f504f610SAugustin Cavalier extern int __signgam;
257*f504f610SAugustin Cavalier hidden double __lgamma_r(double, int *);
258*f504f610SAugustin Cavalier hidden float __lgammaf_r(float, int *);
259*f504f610SAugustin Cavalier
260*f504f610SAugustin Cavalier /* error handling functions */
261*f504f610SAugustin Cavalier hidden float __math_xflowf(uint32_t, float);
262*f504f610SAugustin Cavalier hidden float __math_uflowf(uint32_t);
263*f504f610SAugustin Cavalier hidden float __math_oflowf(uint32_t);
264*f504f610SAugustin Cavalier hidden float __math_divzerof(uint32_t);
265*f504f610SAugustin Cavalier hidden float __math_invalidf(float);
266*f504f610SAugustin Cavalier hidden double __math_xflow(uint32_t, double);
267*f504f610SAugustin Cavalier hidden double __math_uflow(uint32_t);
268*f504f610SAugustin Cavalier hidden double __math_oflow(uint32_t);
269*f504f610SAugustin Cavalier hidden double __math_divzero(uint32_t);
270*f504f610SAugustin Cavalier hidden double __math_invalid(double);
271*f504f610SAugustin Cavalier
272*f504f610SAugustin Cavalier #endif
273