Merge branch 'vendor/MPFR'
[dragonfly.git] / lib / libm / src / math_private.h
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  * $NetBSD: math_private.h,v 1.16 2010/09/16 20:39:50 drochner Exp $
15  */
16
17 #ifndef _MATH_PRIVATE_H_
18 #define _MATH_PRIVATE_H_
19
20 #include <sys/types.h>
21
22 /* The original fdlibm code used statements like:
23         n0 = ((*(int*)&one)>>29)^1;             * index of high word *
24         ix0 = *(n0+(int*)&x);                   * high word of x *
25         ix1 = *((1-n0)+(int*)&x);               * low word of x *
26    to dig two 32 bit words out of the 64 bit IEEE floating point
27    value.  That is non-ANSI, and, moreover, the gcc instruction
28    scheduler gets it wrong.  We instead use the following macros.
29    Unlike the original code, we determine the endianness at compile
30    time, not at run time; I don't see much benefit to selecting
31    endianness at run time.  */
32
33 /* A union which permits us to convert between a double and two 32 bit
34    ints.  */
35
36 /*
37  * The ARM ports are little endian except for the FPA word order which is
38  * big endian.
39  */
40
41 #if BYTE_ORDER == BIG_ENDIAN
42
43 typedef union
44 {
45   double value;
46   struct
47   {
48     u_int32_t msw;
49     u_int32_t lsw;
50   } parts;
51   struct
52   {
53     u_int64_t w;
54   } xparts;
55 } ieee_double_shape_type;
56
57 #endif
58
59 #if BYTE_ORDER == LITTLE_ENDIAN
60
61 typedef union
62 {
63   double value;
64   struct
65   {
66     u_int32_t lsw;
67     u_int32_t msw;
68   } parts;
69   struct
70   {
71     u_int64_t w;
72   } xparts;
73 } ieee_double_shape_type;
74
75 #endif
76
77 /* Get two 32 bit ints from a double.  */
78
79 #define EXTRACT_WORDS(ix0,ix1,d)                                \
80 do {                                                            \
81   ieee_double_shape_type ew_u;                                  \
82   ew_u.value = (d);                                             \
83   (ix0) = ew_u.parts.msw;                                       \
84   (ix1) = ew_u.parts.lsw;                                       \
85 } while (/*CONSTCOND*/0)
86
87 /*
88  * Get a 64-bit int from a double.
89  * Origin: FreeBSD msun/src/math_private.h
90  */
91 #define EXTRACT_WORD64(ix,d)                                    \
92 do {                                                            \
93   ieee_double_shape_type ew_u;                                  \
94   ew_u.value = (d);                                             \
95   (ix) = ew_u.xparts.w;                                         \
96 } while (0)
97
98 /* Get the more significant 32 bit int from a double.  */
99
100 #define GET_HIGH_WORD(i,d)                                      \
101 do {                                                            \
102   ieee_double_shape_type gh_u;                                  \
103   gh_u.value = (d);                                             \
104   (i) = gh_u.parts.msw;                                         \
105 } while (/*CONSTCOND*/0)
106
107 /* Get the less significant 32 bit int from a double.  */
108
109 #define GET_LOW_WORD(i,d)                                       \
110 do {                                                            \
111   ieee_double_shape_type gl_u;                                  \
112   gl_u.value = (d);                                             \
113   (i) = gl_u.parts.lsw;                                         \
114 } while (/*CONSTCOND*/0)
115
116 /* Set a double from two 32 bit ints.  */
117
118 #define INSERT_WORDS(d,ix0,ix1)                                 \
119 do {                                                            \
120   ieee_double_shape_type iw_u;                                  \
121   iw_u.parts.msw = (ix0);                                       \
122   iw_u.parts.lsw = (ix1);                                       \
123   (d) = iw_u.value;                                             \
124 } while (/*CONSTCOND*/0)
125
126 /*
127  * Set a double from a 64-bit int.
128  * Origin: FreeBSD msun/src/math_private.h
129  */
130 #define INSERT_WORD64(d,ix)                                     \
131 do {                                                            \
132   ieee_double_shape_type iw_u;                                  \
133   iw_u.xparts.w = (ix);                                         \
134   (d) = iw_u.value;                                             \
135 } while (0)
136
137 /* Set the more significant 32 bits of a double from an int.  */
138
139 #define SET_HIGH_WORD(d,v)                                      \
140 do {                                                            \
141   ieee_double_shape_type sh_u;                                  \
142   sh_u.value = (d);                                             \
143   sh_u.parts.msw = (v);                                         \
144   (d) = sh_u.value;                                             \
145 } while (/*CONSTCOND*/0)
146
147 /* Set the less significant 32 bits of a double from an int.  */
148
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 (/*CONSTCOND*/0)
156
157 /* A union which permits us to convert between a float and a 32 bit
158    int.  */
159
160 typedef union
161 {
162   float value;
163   u_int32_t word;
164 } ieee_float_shape_type;
165
166 /* Get a 32 bit int from a float.  */
167
168 #define GET_FLOAT_WORD(i,d)                                     \
169 do {                                                            \
170   ieee_float_shape_type gf_u;                                   \
171   gf_u.value = (d);                                             \
172   (i) = gf_u.word;                                              \
173 } while (/*CONSTCOND*/0)
174
175 /* Set a float from a 32 bit int.  */
176
177 #define SET_FLOAT_WORD(d,i)                                     \
178 do {                                                            \
179   ieee_float_shape_type sf_u;                                   \
180   sf_u.word = (i);                                              \
181   (d) = sf_u.value;                                             \
182 } while (/*CONSTCOND*/0)
183
184 /*
185  * Get expsign as a 16 bit int from a long double.
186  * Origin: FreeBSD msun/src/math_private.h
187  */
188
189 #define GET_LDBL_EXPSIGN(i,d)                                   \
190 do {                                                            \
191   union IEEEl2bits ge_u;                                        \
192   ge_u.e = (d);                                                 \
193   (i) = ge_u.xbits.expsign;                                     \
194 } while (/*CONSTCOND*/0)
195
196 /*
197  * Set expsign of a long double from a 16 bit int.
198  */
199
200 #define SET_LDBL_EXPSIGN(d,v)                                   \
201 do {                                                            \
202   union IEEEl2bits se_u;                                        \
203   se_u.e = (d);                                                 \
204   se_u.xbits.expsign = (v);                                     \
205   (d) = se_u.e;                                                 \
206 } while (/*CONSTCOND*/0)
207
208 /*
209  * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
210  */
211 #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
212 #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
213 #else
214 #define STRICT_ASSIGN(type, lval, rval) do {    \
215         volatile type __lval;                   \
216                                                 \
217         if (sizeof(type) >= sizeof(double))     \
218                 (lval) = (rval);                \
219         else {                                  \
220                 __lval = (rval);                \
221                 (lval) = __lval;                \
222         }                                       \
223 } while (/*CONSTCOND*/0)
224 #endif
225
226 #ifdef  _COMPLEX_H
227
228 /*
229  * Quoting from ISO/IEC 9899:TC2:
230  *
231  * 6.2.5.13 Types
232  * Each complex type has the same representation and alignment requirements as
233  * an array type containing exactly two elements of the corresponding real type;
234  * the first element is equal to the real part, and the second element to the
235  * imaginary part, of the complex number.
236  */
237 typedef union {
238         float complex z;
239         float parts[2];
240 } float_complex;
241
242 typedef union {
243         double complex z;
244         double parts[2];
245 } double_complex;
246
247 typedef union {
248         long double complex z;
249         long double parts[2];
250 } long_double_complex;
251
252 #define REAL_PART(z)    ((z).parts[0])
253 #define IMAG_PART(z)    ((z).parts[1])
254
255 /*
256  * Inline functions that can be used to construct complex values.
257  *
258  * The C99 standard intends x+I*y to be used for this, but x+I*y is
259  * currently unusable in general since gcc introduces many overflow,
260  * underflow, sign and efficiency bugs by rewriting I*y as
261  * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
262  * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
263  * to -0.0+I*0.0.
264  */
265 static __inline float complex
266 cpackf(float x, float y)
267 {
268         float_complex fc;
269
270         REAL_PART(fc) = x;
271         IMAG_PART(fc) = y;
272         return (fc.z);
273 }
274
275 static __inline double complex
276 cpack(double x, double y)
277 {
278         double_complex dc;
279
280         REAL_PART(dc) = x;
281         IMAG_PART(dc) = y;
282         return (dc.z);
283 }
284
285 static __inline long double complex
286 cpackl(long double x, long double y)
287 {
288         long_double_complex ldc;
289
290         REAL_PART(ldc) = x;
291         IMAG_PART(ldc) = y;
292         return (ldc.z);
293 }
294
295 #endif  /* _COMPLEX_H */
296
297 __BEGIN_DECLS
298 #pragma GCC visibility push(hidden)
299
300 /* fdlibm kernel function */
301 int     __kernel_rem_pio2(double*,double*,int,int,int);
302
303 /* double precision kernel functions */
304 int     __libm_rem_pio2(double, double*);
305 double  __kernel_sin(double, double, int);
306 double  __kernel_cos(double, double);
307 double  __kernel_tan(double, double, int);
308
309 /* float precision kernel functions */
310 int     __libm_rem_pio2f(float,double*);
311 float   __kernel_sindf(double);
312 float   __kernel_cosdf(double);
313 float   __kernel_tandf(double, int);
314
315 /* long double precision kernel functions */
316 long double __kernel_sinl(long double, long double, int);
317 long double __kernel_cosl(long double, long double);
318 long double __kernel_tanl(long double, long double, int);
319
320 #pragma GCC visibility pop
321 __END_DECLS
322
323 #endif /* _MATH_PRIVATE_H_ */