Branch data Line data Source code
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 : : * $FreeBSD: src/lib/msun/src/math_private.h,v 1.34 2011/10/21 06:27:56 das Exp $
15 : : */
16 : :
17 : : #ifndef _MATH_PRIVATE_H_
18 : : #define _MATH_PRIVATE_H_
19 : :
20 : : #include <openlibm_complex.h>
21 : : #include <openlibm_defs.h>
22 : : #include "cdefs-compat.h"
23 : : #include "types-compat.h"
24 : : #include "fpmath.h"
25 : : #include <stdint.h>
26 : : #include "math_private_openbsd.h"
27 : :
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 : :
41 : : /*
42 : : * A union which permits us to convert between a double and two 32 bit
43 : : * ints.
44 : : */
45 : :
46 : : #if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
47 : :
48 : : typedef union
49 : : {
50 : : double value;
51 : : struct
52 : : {
53 : : u_int32_t msw;
54 : : u_int32_t lsw;
55 : : } parts;
56 : : struct
57 : : {
58 : : u_int64_t w;
59 : : } xparts;
60 : : } ieee_double_shape_type;
61 : :
62 : : #endif
63 : :
64 : : #if __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
65 : :
66 : : typedef union
67 : : {
68 : : double value;
69 : : struct
70 : : {
71 : : u_int32_t lsw;
72 : : u_int32_t msw;
73 : : } parts;
74 : : struct
75 : : {
76 : : u_int64_t w;
77 : : } xparts;
78 : : } ieee_double_shape_type;
79 : :
80 : : #endif
81 : :
82 : : /* Get two 32 bit ints from a double. */
83 : :
84 : : #define EXTRACT_WORDS(ix0,ix1,d) \
85 : : do { \
86 : : ieee_double_shape_type ew_u; \
87 : : ew_u.value = (d); \
88 : : (ix0) = ew_u.parts.msw; \
89 : : (ix1) = ew_u.parts.lsw; \
90 : : } while (0)
91 : :
92 : : /* Get a 64-bit int from a double. */
93 : : #define EXTRACT_WORD64(ix,d) \
94 : : do { \
95 : : ieee_double_shape_type ew_u; \
96 : : ew_u.value = (d); \
97 : : (ix) = ew_u.xparts.w; \
98 : : } while (0)
99 : :
100 : : /* Get the more significant 32 bit int from a double. */
101 : :
102 : : #define GET_HIGH_WORD(i,d) \
103 : : do { \
104 : : ieee_double_shape_type gh_u; \
105 : : gh_u.value = (d); \
106 : : (i) = gh_u.parts.msw; \
107 : : } while (0)
108 : :
109 : : /* Get the less significant 32 bit int from a double. */
110 : :
111 : : #define GET_LOW_WORD(i,d) \
112 : : do { \
113 : : ieee_double_shape_type gl_u; \
114 : : gl_u.value = (d); \
115 : : (i) = gl_u.parts.lsw; \
116 : : } while (0)
117 : :
118 : : /* Set a double from two 32 bit ints. */
119 : :
120 : : #define INSERT_WORDS(d,ix0,ix1) \
121 : : do { \
122 : : ieee_double_shape_type iw_u; \
123 : : iw_u.parts.msw = (ix0); \
124 : : iw_u.parts.lsw = (ix1); \
125 : : (d) = iw_u.value; \
126 : : } while (0)
127 : :
128 : : /* Set a double from a 64-bit int. */
129 : : #define INSERT_WORD64(d,ix) \
130 : : do { \
131 : : ieee_double_shape_type iw_u; \
132 : : iw_u.xparts.w = (ix); \
133 : : (d) = iw_u.value; \
134 : : } while (0)
135 : :
136 : : /* Set the more significant 32 bits of a double from an int. */
137 : :
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 : :
146 : : /* Set the less significant 32 bits of a double from an int. */
147 : :
148 : : #define SET_LOW_WORD(d,v) \
149 : : do { \
150 : : ieee_double_shape_type sl_u; \
151 : : sl_u.value = (d); \
152 : : sl_u.parts.lsw = (v); \
153 : : (d) = sl_u.value; \
154 : : } while (0)
155 : :
156 : : /*
157 : : * A union which permits us to convert between a float and a 32 bit
158 : : * int.
159 : : */
160 : :
161 : : typedef union
162 : : {
163 : : float value;
164 : : /* FIXME: Assumes 32 bit int. */
165 : : unsigned int word;
166 : : } ieee_float_shape_type;
167 : :
168 : : /* Get a 32 bit int from a float. */
169 : :
170 : : #define GET_FLOAT_WORD(i,d) \
171 : : do { \
172 : : ieee_float_shape_type gf_u; \
173 : : gf_u.value = (d); \
174 : : (i) = gf_u.word; \
175 : : } while (0)
176 : :
177 : : /* Set a float from a 32 bit int. */
178 : :
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 : :
186 : : /* Get expsign as a 16 bit int from a long double. */
187 : :
188 : : #define GET_LDBL_EXPSIGN(i,d) \
189 : : do { \
190 : : union IEEEl2bits ge_u; \
191 : : ge_u.e = (d); \
192 : : (i) = ge_u.xbits.expsign; \
193 : : } while (0)
194 : :
195 : : /* Set expsign of a long double from a 16 bit int. */
196 : :
197 : : #define SET_LDBL_EXPSIGN(d,v) \
198 : : do { \
199 : : union IEEEl2bits se_u; \
200 : : se_u.e = (d); \
201 : : se_u.xbits.expsign = (v); \
202 : : (d) = se_u.e; \
203 : : } while (0)
204 : :
205 : :
206 : : #ifndef __FreeBSD__
207 : : #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
208 : : #else
209 : : #ifdef FLT_EVAL_METHOD
210 : : // Attempt to get strict C99 semantics for assignment with non-C99 compilers.
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(long double)) \
218 : : (lval) = (rval); \
219 : : else { \
220 : : __lval = (rval); \
221 : : (lval) = __lval; \
222 : : } \
223 : : } while (0)
224 : : #endif
225 : : #endif
226 : : #endif
227 : :
228 : : /*
229 : : * Common routine to process the arguments to nan(), nanf(), and nanl().
230 : : */
231 : : void __scan_nan(u_int32_t *__words, int __num_words, const char *__s);
232 : :
233 : : /*
234 : : * Mix 1 or 2 NaNs. First add 0 to each arg. This normally just turns
235 : : * signaling NaNs into quiet NaNs by setting a quiet bit. We do this
236 : : * because we want to never return a signaling NaN, and also because we
237 : : * don't want the quiet bit to affect the result. Then mix the converted
238 : : * args using addition. The result is typically the arg whose mantissa
239 : : * bits (considered as in integer) are largest.
240 : : *
241 : : * Technical complications: the result in bits might depend on the precision
242 : : * and/or on compiler optimizations, especially when different register sets
243 : : * are used for different precisions. Try to make the result not depend on
244 : : * at least the precision by always doing the main mixing step in long double
245 : : * precision. Try to reduce dependencies on optimizations by adding the
246 : : * the 0's in different precisions (unless everything is in long double
247 : : * precision).
248 : : */
249 : : #define nan_mix(x, y) (((x) + 0.0L) + ((y) + 0))
250 : :
251 : : #ifdef __GNUCLIKE_ASM
252 : :
253 : : /* Asm versions of some functions. */
254 : :
255 : : #ifdef __amd64__
256 : : static __inline int
257 : 0 : irint(double x)
258 : : {
259 : : int n;
260 : :
261 : 0 : __asm__("cvtsd2si %1,%0" : "=r" (n) : "x" (x));
262 : 0 : return (n);
263 : : }
264 : : #define HAVE_EFFICIENT_IRINT
265 : : #endif
266 : :
267 : : #ifdef __i386__
268 : : static __inline int
269 : : irint(double x)
270 : : {
271 : : int n;
272 : :
273 : : __asm__("fistl %0" : "=m" (n) : "t" (x));
274 : : return (n);
275 : : }
276 : : #define HAVE_EFFICIENT_IRINT
277 : : #endif
278 : :
279 : : #endif /* __GNUCLIKE_ASM */
280 : :
281 : : /*
282 : : * ieee style elementary functions
283 : : *
284 : : * We rename functions here to improve other sources' diffability
285 : : * against fdlibm.
286 : : */
287 : : #define __ieee754_sqrt sqrt
288 : : #define __ieee754_acos acos
289 : : #define __ieee754_acosh acosh
290 : : #define __ieee754_log log
291 : : #define __ieee754_log2 log2
292 : : #define __ieee754_atanh atanh
293 : : #define __ieee754_asin asin
294 : : #define __ieee754_atan2 atan2
295 : : #define __ieee754_exp exp
296 : : #define __ieee754_cosh cosh
297 : : #define __ieee754_fmod fmod
298 : : #define __ieee754_pow pow
299 : : #define __ieee754_lgamma lgamma
300 : : #define __ieee754_lgamma_r lgamma_r
301 : : #define __ieee754_log10 log10
302 : : #define __ieee754_sinh sinh
303 : : #define __ieee754_hypot hypot
304 : : #define __ieee754_j0 j0
305 : : #define __ieee754_j1 j1
306 : : #define __ieee754_y0 y0
307 : : #define __ieee754_y1 y1
308 : : #define __ieee754_jn jn
309 : : #define __ieee754_yn yn
310 : : #define __ieee754_remainder remainder
311 : : #define __ieee754_sqrtf sqrtf
312 : : #define __ieee754_acosf acosf
313 : : #define __ieee754_acoshf acoshf
314 : : #define __ieee754_logf logf
315 : : #define __ieee754_atanhf atanhf
316 : : #define __ieee754_asinf asinf
317 : : #define __ieee754_atan2f atan2f
318 : : #define __ieee754_expf expf
319 : : #define __ieee754_coshf coshf
320 : : #define __ieee754_fmodf fmodf
321 : : #define __ieee754_powf powf
322 : : #define __ieee754_lgammaf lgammaf
323 : : #define __ieee754_lgammaf_r lgammaf_r
324 : : #define __ieee754_log10f log10f
325 : : #define __ieee754_log2f log2f
326 : : #define __ieee754_sinhf sinhf
327 : : #define __ieee754_hypotf hypotf
328 : : #define __ieee754_j0f j0f
329 : : #define __ieee754_j1f j1f
330 : : #define __ieee754_y0f y0f
331 : : #define __ieee754_y1f y1f
332 : : #define __ieee754_jnf jnf
333 : : #define __ieee754_ynf ynf
334 : : #define __ieee754_remainderf remainderf
335 : :
336 : : /* fdlibm kernel function */
337 : : int __kernel_rem_pio2(double*,double*,int,int,int);
338 : :
339 : : /* double precision kernel functions */
340 : : #ifdef INLINE_REM_PIO2
341 : : __inline
342 : : #endif
343 : : int __ieee754_rem_pio2(double,double*);
344 : : double __kernel_sin(double,double,int);
345 : : double __kernel_cos(double,double);
346 : : double __kernel_tan(double,double,int);
347 : : double __ldexp_exp(double,int);
348 : : double complex __ldexp_cexp(double complex,int);
349 : :
350 : : /* float precision kernel functions */
351 : : #ifdef INLINE_REM_PIO2F
352 : : __inline
353 : : #endif
354 : : int __ieee754_rem_pio2f(float,double*);
355 : : #ifdef INLINE_KERNEL_SINDF
356 : : __inline
357 : : #endif
358 : : float __kernel_sindf(double);
359 : : #ifdef INLINE_KERNEL_COSDF
360 : : __inline
361 : : #endif
362 : : float __kernel_cosdf(double);
363 : : #ifdef INLINE_KERNEL_TANDF
364 : : __inline
365 : : #endif
366 : : float __kernel_tandf(double,int);
367 : : float __ldexp_expf(float,int);
368 : : float complex __ldexp_cexpf(float complex,int);
369 : :
370 : : /* long double precision kernel functions */
371 : : long double __kernel_sinl(long double, long double, int);
372 : : long double __kernel_cosl(long double, long double);
373 : : long double __kernel_tanl(long double, long double, int);
374 : :
375 : : #endif /* !_MATH_PRIVATE_H_ */
|