1*2f2c0062Sguenther /* $OpenBSD: math_private.h,v 1.18 2016/09/12 19:47:02 guenther Exp $ */
2df930be7Sderaadt /*
3df930be7Sderaadt * ====================================================
4df930be7Sderaadt * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5df930be7Sderaadt *
6df930be7Sderaadt * Developed at SunPro, a Sun Microsystems, Inc. business.
7df930be7Sderaadt * Permission to use, copy, modify, and distribute this
8df930be7Sderaadt * software is freely granted, provided that this notice
9df930be7Sderaadt * is preserved.
10df930be7Sderaadt * ====================================================
11df930be7Sderaadt */
12df930be7Sderaadt
13df930be7Sderaadt /*
14df930be7Sderaadt * from: @(#)fdlibm.h 5.1 93/09/24
15df930be7Sderaadt */
16df930be7Sderaadt
17df930be7Sderaadt #ifndef _MATH_PRIVATE_H_
18df930be7Sderaadt #define _MATH_PRIVATE_H_
19df930be7Sderaadt
20df930be7Sderaadt #include <sys/types.h>
21df930be7Sderaadt
22df930be7Sderaadt /* The original fdlibm code used statements like:
23df930be7Sderaadt n0 = ((*(int*)&one)>>29)^1; * index of high word *
24df930be7Sderaadt ix0 = *(n0+(int*)&x); * high word of x *
25df930be7Sderaadt ix1 = *((1-n0)+(int*)&x); * low word of x *
26df930be7Sderaadt to dig two 32 bit words out of the 64 bit IEEE floating point
27df930be7Sderaadt value. That is non-ANSI, and, moreover, the gcc instruction
28df930be7Sderaadt scheduler gets it wrong. We instead use the following macros.
29df930be7Sderaadt Unlike the original code, we determine the endianness at compile
30df930be7Sderaadt time, not at run time; I don't see much benefit to selecting
31df930be7Sderaadt endianness at run time. */
32df930be7Sderaadt
33a26ab1d9Smartynas /* A union which permits us to convert between a long double and
34a26ab1d9Smartynas four 32 bit ints. */
35a26ab1d9Smartynas
36a26ab1d9Smartynas #if BYTE_ORDER == BIG_ENDIAN
37a26ab1d9Smartynas
38a26ab1d9Smartynas typedef union
39a26ab1d9Smartynas {
40a26ab1d9Smartynas long double value;
41a26ab1d9Smartynas struct {
42a26ab1d9Smartynas u_int32_t mswhi;
43a26ab1d9Smartynas u_int32_t mswlo;
44a26ab1d9Smartynas u_int32_t lswhi;
45a26ab1d9Smartynas u_int32_t lswlo;
46a26ab1d9Smartynas } parts32;
47a26ab1d9Smartynas struct {
48a26ab1d9Smartynas u_int64_t msw;
49a26ab1d9Smartynas u_int64_t lsw;
50a26ab1d9Smartynas } parts64;
51a26ab1d9Smartynas } ieee_quad_shape_type;
52a26ab1d9Smartynas
53a26ab1d9Smartynas #endif
54a26ab1d9Smartynas
55a26ab1d9Smartynas #if BYTE_ORDER == LITTLE_ENDIAN
56a26ab1d9Smartynas
57a26ab1d9Smartynas typedef union
58a26ab1d9Smartynas {
59a26ab1d9Smartynas long double value;
60a26ab1d9Smartynas struct {
61a26ab1d9Smartynas u_int32_t lswlo;
62a26ab1d9Smartynas u_int32_t lswhi;
63a26ab1d9Smartynas u_int32_t mswlo;
64a26ab1d9Smartynas u_int32_t mswhi;
65a26ab1d9Smartynas } parts32;
66a26ab1d9Smartynas struct {
67a26ab1d9Smartynas u_int64_t lsw;
68a26ab1d9Smartynas u_int64_t msw;
69a26ab1d9Smartynas } parts64;
70a26ab1d9Smartynas } ieee_quad_shape_type;
71a26ab1d9Smartynas
72a26ab1d9Smartynas #endif
73a26ab1d9Smartynas
74a26ab1d9Smartynas /* Get two 64 bit ints from a long double. */
75a26ab1d9Smartynas
76a26ab1d9Smartynas #define GET_LDOUBLE_WORDS64(ix0,ix1,d) \
77a26ab1d9Smartynas do { \
78a26ab1d9Smartynas ieee_quad_shape_type qw_u; \
79a26ab1d9Smartynas qw_u.value = (d); \
80a26ab1d9Smartynas (ix0) = qw_u.parts64.msw; \
81a26ab1d9Smartynas (ix1) = qw_u.parts64.lsw; \
82a26ab1d9Smartynas } while (0)
83a26ab1d9Smartynas
84a26ab1d9Smartynas /* Set a long double from two 64 bit ints. */
85a26ab1d9Smartynas
86a26ab1d9Smartynas #define SET_LDOUBLE_WORDS64(d,ix0,ix1) \
87a26ab1d9Smartynas do { \
88a26ab1d9Smartynas ieee_quad_shape_type qw_u; \
89a26ab1d9Smartynas qw_u.parts64.msw = (ix0); \
90a26ab1d9Smartynas qw_u.parts64.lsw = (ix1); \
91a26ab1d9Smartynas (d) = qw_u.value; \
92a26ab1d9Smartynas } while (0)
93a26ab1d9Smartynas
94a26ab1d9Smartynas /* Get the more significant 64 bits of a long double mantissa. */
95a26ab1d9Smartynas
96a26ab1d9Smartynas #define GET_LDOUBLE_MSW64(v,d) \
97a26ab1d9Smartynas do { \
98a26ab1d9Smartynas ieee_quad_shape_type sh_u; \
99a26ab1d9Smartynas sh_u.value = (d); \
100a26ab1d9Smartynas (v) = sh_u.parts64.msw; \
101a26ab1d9Smartynas } while (0)
102a26ab1d9Smartynas
103a26ab1d9Smartynas /* Set the more significant 64 bits of a long double mantissa from an int. */
104a26ab1d9Smartynas
105a26ab1d9Smartynas #define SET_LDOUBLE_MSW64(d,v) \
106a26ab1d9Smartynas do { \
107a26ab1d9Smartynas ieee_quad_shape_type sh_u; \
108a26ab1d9Smartynas sh_u.value = (d); \
109a26ab1d9Smartynas sh_u.parts64.msw = (v); \
110a26ab1d9Smartynas (d) = sh_u.value; \
111a26ab1d9Smartynas } while (0)
112a26ab1d9Smartynas
113a26ab1d9Smartynas /* Get the least significant 64 bits of a long double mantissa. */
114a26ab1d9Smartynas
115a26ab1d9Smartynas #define GET_LDOUBLE_LSW64(v,d) \
116a26ab1d9Smartynas do { \
117a26ab1d9Smartynas ieee_quad_shape_type sh_u; \
118a26ab1d9Smartynas sh_u.value = (d); \
119a26ab1d9Smartynas (v) = sh_u.parts64.lsw; \
120a26ab1d9Smartynas } while (0)
121a26ab1d9Smartynas
122a26ab1d9Smartynas /* A union which permits us to convert between a long double and
123a26ab1d9Smartynas three 32 bit ints. */
124a26ab1d9Smartynas
125a26ab1d9Smartynas #if BYTE_ORDER == BIG_ENDIAN
126a26ab1d9Smartynas
127a26ab1d9Smartynas typedef union
128a26ab1d9Smartynas {
129a26ab1d9Smartynas long double value;
130a26ab1d9Smartynas struct {
131a26ab1d9Smartynas #ifdef __LP64__
132a26ab1d9Smartynas int padh:32;
133a26ab1d9Smartynas #endif
134a26ab1d9Smartynas int exp:16;
135a26ab1d9Smartynas int padl:16;
136a26ab1d9Smartynas u_int32_t msw;
137a26ab1d9Smartynas u_int32_t lsw;
138a26ab1d9Smartynas } parts;
139a26ab1d9Smartynas } ieee_extended_shape_type;
140a26ab1d9Smartynas
141a26ab1d9Smartynas #endif
142a26ab1d9Smartynas
143a26ab1d9Smartynas #if BYTE_ORDER == LITTLE_ENDIAN
144a26ab1d9Smartynas
145a26ab1d9Smartynas typedef union
146a26ab1d9Smartynas {
147a26ab1d9Smartynas long double value;
148a26ab1d9Smartynas struct {
149a26ab1d9Smartynas u_int32_t lsw;
150a26ab1d9Smartynas u_int32_t msw;
151a26ab1d9Smartynas int exp:16;
152a26ab1d9Smartynas int padl:16;
153a26ab1d9Smartynas #ifdef __LP64__
154a26ab1d9Smartynas int padh:32;
155a26ab1d9Smartynas #endif
156a26ab1d9Smartynas } parts;
157a26ab1d9Smartynas } ieee_extended_shape_type;
158a26ab1d9Smartynas
159a26ab1d9Smartynas #endif
160a26ab1d9Smartynas
161a26ab1d9Smartynas /* Get three 32 bit ints from a double. */
162a26ab1d9Smartynas
16349393c00Smartynas #define GET_LDOUBLE_WORDS(se,ix0,ix1,d) \
164a26ab1d9Smartynas do { \
165a26ab1d9Smartynas ieee_extended_shape_type ew_u; \
166a26ab1d9Smartynas ew_u.value = (d); \
16749393c00Smartynas (se) = ew_u.parts.exp; \
168a26ab1d9Smartynas (ix0) = ew_u.parts.msw; \
169a26ab1d9Smartynas (ix1) = ew_u.parts.lsw; \
170a26ab1d9Smartynas } while (0)
171a26ab1d9Smartynas
172a26ab1d9Smartynas /* Set a double from two 32 bit ints. */
173a26ab1d9Smartynas
17449393c00Smartynas #define SET_LDOUBLE_WORDS(d,se,ix0,ix1) \
175a26ab1d9Smartynas do { \
176a26ab1d9Smartynas ieee_extended_shape_type iw_u; \
17749393c00Smartynas iw_u.parts.exp = (se); \
178a26ab1d9Smartynas iw_u.parts.msw = (ix0); \
179a26ab1d9Smartynas iw_u.parts.lsw = (ix1); \
180a26ab1d9Smartynas (d) = iw_u.value; \
181a26ab1d9Smartynas } while (0)
182a26ab1d9Smartynas
183a26ab1d9Smartynas /* Get the more significant 32 bits of a long double mantissa. */
184a26ab1d9Smartynas
185a26ab1d9Smartynas #define GET_LDOUBLE_MSW(v,d) \
186a26ab1d9Smartynas do { \
187a26ab1d9Smartynas ieee_extended_shape_type sh_u; \
188a26ab1d9Smartynas sh_u.value = (d); \
189a26ab1d9Smartynas (v) = sh_u.parts.msw; \
190a26ab1d9Smartynas } while (0)
191a26ab1d9Smartynas
192a26ab1d9Smartynas /* Set the more significant 32 bits of a long double mantissa from an int. */
193a26ab1d9Smartynas
194a26ab1d9Smartynas #define SET_LDOUBLE_MSW(d,v) \
195a26ab1d9Smartynas do { \
196a26ab1d9Smartynas ieee_extended_shape_type sh_u; \
197a26ab1d9Smartynas sh_u.value = (d); \
198a26ab1d9Smartynas sh_u.parts.msw = (v); \
199a26ab1d9Smartynas (d) = sh_u.value; \
200a26ab1d9Smartynas } while (0)
201a26ab1d9Smartynas
202a26ab1d9Smartynas /* Get int from the exponent of a long double. */
203a26ab1d9Smartynas
20449393c00Smartynas #define GET_LDOUBLE_EXP(se,d) \
205a26ab1d9Smartynas do { \
206a26ab1d9Smartynas ieee_extended_shape_type ge_u; \
207a26ab1d9Smartynas ge_u.value = (d); \
20849393c00Smartynas (se) = ge_u.parts.exp; \
209a26ab1d9Smartynas } while (0)
210a26ab1d9Smartynas
211a26ab1d9Smartynas /* Set exponent of a long double from an int. */
212a26ab1d9Smartynas
21349393c00Smartynas #define SET_LDOUBLE_EXP(d,se) \
214a26ab1d9Smartynas do { \
215a26ab1d9Smartynas ieee_extended_shape_type se_u; \
216a26ab1d9Smartynas se_u.value = (d); \
21749393c00Smartynas se_u.parts.exp = (se); \
218a26ab1d9Smartynas (d) = se_u.value; \
219a26ab1d9Smartynas } while (0)
220a26ab1d9Smartynas
221df930be7Sderaadt /* A union which permits us to convert between a double and two 32 bit
222df930be7Sderaadt ints. */
223df930be7Sderaadt
2245ca6b847Sderaadt /*
22580626675Smartynas * The arm port is little endian except for the FP word order which is
2265ca6b847Sderaadt * big endian.
2275ca6b847Sderaadt */
2285ca6b847Sderaadt
229016765a7Smartynas #if (BYTE_ORDER == BIG_ENDIAN) || (defined(__arm__) && !defined(__VFP_FP__))
230df930be7Sderaadt
231df930be7Sderaadt typedef union
232df930be7Sderaadt {
233df930be7Sderaadt double value;
234df930be7Sderaadt struct
235df930be7Sderaadt {
236df930be7Sderaadt u_int32_t msw;
237df930be7Sderaadt u_int32_t lsw;
238df930be7Sderaadt } parts;
239df930be7Sderaadt } ieee_double_shape_type;
240df930be7Sderaadt
241df930be7Sderaadt #endif
242df930be7Sderaadt
243016765a7Smartynas #if (BYTE_ORDER == LITTLE_ENDIAN) && !(defined(__arm__) && !defined(__VFP_FP__))
244df930be7Sderaadt
245df930be7Sderaadt typedef union
246df930be7Sderaadt {
247df930be7Sderaadt double value;
248df930be7Sderaadt struct
249df930be7Sderaadt {
250df930be7Sderaadt u_int32_t lsw;
251df930be7Sderaadt u_int32_t msw;
252df930be7Sderaadt } parts;
253df930be7Sderaadt } ieee_double_shape_type;
254df930be7Sderaadt
255df930be7Sderaadt #endif
256df930be7Sderaadt
257df930be7Sderaadt /* Get two 32 bit ints from a double. */
258df930be7Sderaadt
259df930be7Sderaadt #define EXTRACT_WORDS(ix0,ix1,d) \
260df930be7Sderaadt do { \
261df930be7Sderaadt ieee_double_shape_type ew_u; \
262df930be7Sderaadt ew_u.value = (d); \
263df930be7Sderaadt (ix0) = ew_u.parts.msw; \
264df930be7Sderaadt (ix1) = ew_u.parts.lsw; \
265df930be7Sderaadt } while (0)
266df930be7Sderaadt
267df930be7Sderaadt /* Get the more significant 32 bit int from a double. */
268df930be7Sderaadt
269df930be7Sderaadt #define GET_HIGH_WORD(i,d) \
270df930be7Sderaadt do { \
271df930be7Sderaadt ieee_double_shape_type gh_u; \
272df930be7Sderaadt gh_u.value = (d); \
273df930be7Sderaadt (i) = gh_u.parts.msw; \
274df930be7Sderaadt } while (0)
275df930be7Sderaadt
276df930be7Sderaadt /* Get the less significant 32 bit int from a double. */
277df930be7Sderaadt
278df930be7Sderaadt #define GET_LOW_WORD(i,d) \
279df930be7Sderaadt do { \
280df930be7Sderaadt ieee_double_shape_type gl_u; \
281df930be7Sderaadt gl_u.value = (d); \
282df930be7Sderaadt (i) = gl_u.parts.lsw; \
283df930be7Sderaadt } while (0)
284df930be7Sderaadt
285df930be7Sderaadt /* Set a double from two 32 bit ints. */
286df930be7Sderaadt
287df930be7Sderaadt #define INSERT_WORDS(d,ix0,ix1) \
288df930be7Sderaadt do { \
289df930be7Sderaadt ieee_double_shape_type iw_u; \
290df930be7Sderaadt iw_u.parts.msw = (ix0); \
291df930be7Sderaadt iw_u.parts.lsw = (ix1); \
292df930be7Sderaadt (d) = iw_u.value; \
293df930be7Sderaadt } while (0)
294df930be7Sderaadt
295df930be7Sderaadt /* Set the more significant 32 bits of a double from an int. */
296df930be7Sderaadt
297df930be7Sderaadt #define SET_HIGH_WORD(d,v) \
298df930be7Sderaadt do { \
299df930be7Sderaadt ieee_double_shape_type sh_u; \
300df930be7Sderaadt sh_u.value = (d); \
301df930be7Sderaadt sh_u.parts.msw = (v); \
302df930be7Sderaadt (d) = sh_u.value; \
303df930be7Sderaadt } while (0)
304df930be7Sderaadt
305df930be7Sderaadt /* Set the less significant 32 bits of a double from an int. */
306df930be7Sderaadt
307df930be7Sderaadt #define SET_LOW_WORD(d,v) \
308df930be7Sderaadt do { \
309df930be7Sderaadt ieee_double_shape_type sl_u; \
310df930be7Sderaadt sl_u.value = (d); \
311df930be7Sderaadt sl_u.parts.lsw = (v); \
312df930be7Sderaadt (d) = sl_u.value; \
313df930be7Sderaadt } while (0)
314df930be7Sderaadt
315df930be7Sderaadt /* A union which permits us to convert between a float and a 32 bit
316df930be7Sderaadt int. */
317df930be7Sderaadt
318df930be7Sderaadt typedef union
319df930be7Sderaadt {
320df930be7Sderaadt float value;
321df930be7Sderaadt u_int32_t word;
322df930be7Sderaadt } ieee_float_shape_type;
323df930be7Sderaadt
324df930be7Sderaadt /* Get a 32 bit int from a float. */
325df930be7Sderaadt
326df930be7Sderaadt #define GET_FLOAT_WORD(i,d) \
327df930be7Sderaadt do { \
328df930be7Sderaadt ieee_float_shape_type gf_u; \
329df930be7Sderaadt gf_u.value = (d); \
330df930be7Sderaadt (i) = gf_u.word; \
331df930be7Sderaadt } while (0)
332df930be7Sderaadt
333df930be7Sderaadt /* Set a float from a 32 bit int. */
334df930be7Sderaadt
335df930be7Sderaadt #define SET_FLOAT_WORD(d,i) \
336df930be7Sderaadt do { \
337df930be7Sderaadt ieee_float_shape_type sf_u; \
338df930be7Sderaadt sf_u.word = (i); \
339df930be7Sderaadt (d) = sf_u.value; \
340df930be7Sderaadt } while (0)
341df930be7Sderaadt
342eac90eaaSmartynas #ifdef FLT_EVAL_METHOD
343eac90eaaSmartynas /*
344eac90eaaSmartynas * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
345eac90eaaSmartynas */
346eac90eaaSmartynas #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
347eac90eaaSmartynas #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
348390c8400Smartynas #else /* FLT_EVAL_METHOD == 0 || __GNUC__ == 0 */
349eac90eaaSmartynas #define STRICT_ASSIGN(type, lval, rval) do { \
350eac90eaaSmartynas volatile type __lval; \
351eac90eaaSmartynas \
3523609bd3bSkettenis if (sizeof(type) >= sizeof(long double)) \
353eac90eaaSmartynas (lval) = (rval); \
354eac90eaaSmartynas else { \
355eac90eaaSmartynas __lval = (rval); \
356eac90eaaSmartynas (lval) = __lval; \
357eac90eaaSmartynas } \
358eac90eaaSmartynas } while (0)
359390c8400Smartynas #endif /* FLT_EVAL_METHOD == 0 || __GNUC__ == 0 */
360390c8400Smartynas #endif /* FLT_EVAL_METHOD */
361eac90eaaSmartynas
362*2f2c0062Sguenther __BEGIN_HIDDEN_DECLS
363df930be7Sderaadt /* fdlibm kernel function */
3647b36286aSmartynas extern int __ieee754_rem_pio2(double,double*);
365c72b5b24Smillert extern double __kernel_sin(double,double,int);
366c72b5b24Smillert extern double __kernel_cos(double,double);
367c72b5b24Smillert extern double __kernel_tan(double,double,int);
368390c8400Smartynas extern int __kernel_rem_pio2(double*,double*,int,int,int);
369df930be7Sderaadt
370df930be7Sderaadt /* float versions of fdlibm kernel functions */
3717b36286aSmartynas extern int __ieee754_rem_pio2f(float,float*);
372c72b5b24Smillert extern float __kernel_sinf(float,float,int);
373c72b5b24Smillert extern float __kernel_cosf(float,float);
374c72b5b24Smillert extern float __kernel_tanf(float,float,int);
375c72b5b24Smillert extern int __kernel_rem_pio2f(float*,float*,int,int,int,const int*);
376df930be7Sderaadt
377390c8400Smartynas /* long double precision kernel functions */
378390c8400Smartynas long double __kernel_sinl(long double, long double, int);
379390c8400Smartynas long double __kernel_cosl(long double, long double);
380390c8400Smartynas long double __kernel_tanl(long double, long double, int);
381390c8400Smartynas
382390c8400Smartynas /*
383390c8400Smartynas * Common routine to process the arguments to nan(), nanf(), and nanl().
384390c8400Smartynas */
385390c8400Smartynas void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
386*2f2c0062Sguenther __END_HIDDEN_DECLS
387390c8400Smartynas
3885b14c9c6Smartynas /*
3895b14c9c6Smartynas * TRUNC() is a macro that sets the trailing 27 bits in the mantissa
3905b14c9c6Smartynas * of an IEEE double variable to zero. It must be expression-like
3915b14c9c6Smartynas * for syntactic reasons, and we implement this expression using
3925b14c9c6Smartynas * an inline function instead of a pure macro to avoid depending
3935b14c9c6Smartynas * on the gcc feature of statement-expressions.
3945b14c9c6Smartynas */
3955b14c9c6Smartynas #define TRUNC(d) (_b_trunc(&(d)))
3965b14c9c6Smartynas
3975b14c9c6Smartynas static __inline void
_b_trunc(volatile double * _dp)3985b14c9c6Smartynas _b_trunc(volatile double *_dp)
3995b14c9c6Smartynas {
4005b14c9c6Smartynas uint32_t _lw;
4015b14c9c6Smartynas
4025b14c9c6Smartynas GET_LOW_WORD(_lw, *_dp);
4035b14c9c6Smartynas SET_LOW_WORD(*_dp, _lw & 0xf8000000);
4045b14c9c6Smartynas }
4055b14c9c6Smartynas
4065b14c9c6Smartynas struct Double {
4075b14c9c6Smartynas double a;
4085b14c9c6Smartynas double b;
4095b14c9c6Smartynas };
4105b14c9c6Smartynas
4115b14c9c6Smartynas /*
4125b14c9c6Smartynas * Functions internal to the math package, yet not static.
4135b14c9c6Smartynas */
414*2f2c0062Sguenther __BEGIN_HIDDEN_DECLS
4155b14c9c6Smartynas double __exp__D(double, double);
4165b14c9c6Smartynas struct Double __log__D(double);
41712129755Smartynas long double __p1evll(long double, void *, int);
41812129755Smartynas long double __polevll(long double, void *, int);
419*2f2c0062Sguenther __END_HIDDEN_DECLS
4205b14c9c6Smartynas
421df930be7Sderaadt #endif /* _MATH_PRIVATE_H_ */
422