Numworks Epsilon  1.4.1
Graphing Calculator Operating System
math_private.h
Go to the documentation of this file.
1 /* $OpenBSD: math_private.h,v 1.17 2014/06/02 19:31:17 kettenis Exp $ */
2 /*
3  * ====================================================
4  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5  *
6  * Developed at SunPro, a Sun Microsystems, Inc. business.
7  * Permission to use, copy, modify, and distribute this
8  * software is freely granted, provided that this notice
9  * is preserved.
10  * ====================================================
11  */
12 
13 /*
14  * from: @(#)fdlibm.h 5.1 93/09/24
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 long double and
34  four 32 bit ints. */
35 
36 #if BYTE_ORDER == BIG_ENDIAN
37 
38 typedef union
39 {
40  long double value;
41  struct {
46  } parts32;
47  struct {
50  } parts64;
52 
53 #endif
54 
55 #if BYTE_ORDER == LITTLE_ENDIAN
56 
57 typedef union
58 {
59  long double value;
60  struct {
61  u_int32_t lswlo;
62  u_int32_t lswhi;
63  u_int32_t mswlo;
64  u_int32_t mswhi;
65  } parts32;
66  struct {
67  u_int64_t lsw;
68  u_int64_t msw;
69  } parts64;
71 
72 #endif
73 
74 /* Get two 64 bit ints from a long double. */
75 
76 #define GET_LDOUBLE_WORDS64(ix0,ix1,d) \
77 do { \
78  ieee_quad_shape_type qw_u; \
79  qw_u.value = (d); \
80  (ix0) = qw_u.parts64.msw; \
81  (ix1) = qw_u.parts64.lsw; \
82 } while (0)
83 
84 /* Set a long double from two 64 bit ints. */
85 
86 #define SET_LDOUBLE_WORDS64(d,ix0,ix1) \
87 do { \
88  ieee_quad_shape_type qw_u; \
89  qw_u.parts64.msw = (ix0); \
90  qw_u.parts64.lsw = (ix1); \
91  (d) = qw_u.value; \
92 } while (0)
93 
94 /* Get the more significant 64 bits of a long double mantissa. */
95 
96 #define GET_LDOUBLE_MSW64(v,d) \
97 do { \
98  ieee_quad_shape_type sh_u; \
99  sh_u.value = (d); \
100  (v) = sh_u.parts64.msw; \
101 } while (0)
102 
103 /* Set the more significant 64 bits of a long double mantissa from an int. */
104 
105 #define SET_LDOUBLE_MSW64(d,v) \
106 do { \
107  ieee_quad_shape_type sh_u; \
108  sh_u.value = (d); \
109  sh_u.parts64.msw = (v); \
110  (d) = sh_u.value; \
111 } while (0)
112 
113 /* Get the least significant 64 bits of a long double mantissa. */
114 
115 #define GET_LDOUBLE_LSW64(v,d) \
116 do { \
117  ieee_quad_shape_type sh_u; \
118  sh_u.value = (d); \
119  (v) = sh_u.parts64.lsw; \
120 } while (0)
121 
122 /* A union which permits us to convert between a long double and
123  three 32 bit ints. */
124 
125 #if BYTE_ORDER == BIG_ENDIAN
126 
127 typedef union
128 {
129  long double value;
130  struct {
131 #ifdef __LP64__
132  int padh:32;
133 #endif
134  int exp:16;
135  int padl:16;
138  } parts;
140 
141 #endif
142 
143 #if BYTE_ORDER == LITTLE_ENDIAN
144 
145 typedef union
146 {
147  long double value;
148  struct {
149  u_int32_t lsw;
150  u_int32_t msw;
151  int exp:16;
152  int padl:16;
153 #ifdef __LP64__
154  int padh:32;
155 #endif
156  } parts;
158 
159 #endif
160 
161 /* Get three 32 bit ints from a double. */
162 
163 #define GET_LDOUBLE_WORDS(se,ix0,ix1,d) \
164 do { \
165  ieee_extended_shape_type ew_u; \
166  ew_u.value = (d); \
167  (se) = ew_u.parts.exp; \
168  (ix0) = ew_u.parts.msw; \
169  (ix1) = ew_u.parts.lsw; \
170 } while (0)
171 
172 /* Set a double from two 32 bit ints. */
173 
174 #define SET_LDOUBLE_WORDS(d,se,ix0,ix1) \
175 do { \
176  ieee_extended_shape_type iw_u; \
177  iw_u.parts.exp = (se); \
178  iw_u.parts.msw = (ix0); \
179  iw_u.parts.lsw = (ix1); \
180  (d) = iw_u.value; \
181 } while (0)
182 
183 /* Get the more significant 32 bits of a long double mantissa. */
184 
185 #define GET_LDOUBLE_MSW(v,d) \
186 do { \
187  ieee_extended_shape_type sh_u; \
188  sh_u.value = (d); \
189  (v) = sh_u.parts.msw; \
190 } while (0)
191 
192 /* Set the more significant 32 bits of a long double mantissa from an int. */
193 
194 #define SET_LDOUBLE_MSW(d,v) \
195 do { \
196  ieee_extended_shape_type sh_u; \
197  sh_u.value = (d); \
198  sh_u.parts.msw = (v); \
199  (d) = sh_u.value; \
200 } while (0)
201 
202 /* Get int from the exponent of a long double. */
203 
204 #define GET_LDOUBLE_EXP(se,d) \
205 do { \
206  ieee_extended_shape_type ge_u; \
207  ge_u.value = (d); \
208  (se) = ge_u.parts.exp; \
209 } while (0)
210 
211 /* Set exponent of a long double from an int. */
212 
213 #define SET_LDOUBLE_EXP(d,se) \
214 do { \
215  ieee_extended_shape_type se_u; \
216  se_u.value = (d); \
217  se_u.parts.exp = (se); \
218  (d) = se_u.value; \
219 } while (0)
220 
221 /* A union which permits us to convert between a double and two 32 bit
222  ints. */
223 
224 /*
225  * The arm port is little endian except for the FP word order which is
226  * big endian.
227  */
228 
229 #if (BYTE_ORDER == BIG_ENDIAN) || (defined(__arm__) && !defined(__VFP_FP__))
230 
231 typedef union
232 {
233  double value;
234  struct
235  {
238  } parts;
240 
241 #endif
242 
243 #if (BYTE_ORDER == LITTLE_ENDIAN) && !(defined(__arm__) && !defined(__VFP_FP__))
244 
245 typedef union
246 {
247  double value;
248  struct
249  {
250  u_int32_t lsw;
251  u_int32_t msw;
252  } parts;
254 
255 #endif
256 
257 /* Get two 32 bit ints from a double. */
258 
259 #define EXTRACT_WORDS(ix0,ix1,d) \
260 do { \
261  ieee_double_shape_type ew_u; \
262  ew_u.value = (d); \
263  (ix0) = ew_u.parts.msw; \
264  (ix1) = ew_u.parts.lsw; \
265 } while (0)
266 
267 /* Get the more significant 32 bit int from a double. */
268 
269 #define GET_HIGH_WORD(i,d) \
270 do { \
271  ieee_double_shape_type gh_u; \
272  gh_u.value = (d); \
273  (i) = gh_u.parts.msw; \
274 } while (0)
275 
276 /* Get the less significant 32 bit int from a double. */
277 
278 #define GET_LOW_WORD(i,d) \
279 do { \
280  ieee_double_shape_type gl_u; \
281  gl_u.value = (d); \
282  (i) = gl_u.parts.lsw; \
283 } while (0)
284 
285 /* Set a double from two 32 bit ints. */
286 
287 #define INSERT_WORDS(d,ix0,ix1) \
288 do { \
289  ieee_double_shape_type iw_u; \
290  iw_u.parts.msw = (ix0); \
291  iw_u.parts.lsw = (ix1); \
292  (d) = iw_u.value; \
293 } while (0)
294 
295 /* Set the more significant 32 bits of a double from an int. */
296 
297 #define SET_HIGH_WORD(d,v) \
298 do { \
299  ieee_double_shape_type sh_u; \
300  sh_u.value = (d); \
301  sh_u.parts.msw = (v); \
302  (d) = sh_u.value; \
303 } while (0)
304 
305 /* Set the less significant 32 bits of a double from an int. */
306 
307 #define SET_LOW_WORD(d,v) \
308 do { \
309  ieee_double_shape_type sl_u; \
310  sl_u.value = (d); \
311  sl_u.parts.lsw = (v); \
312  (d) = sl_u.value; \
313 } while (0)
314 
315 /* A union which permits us to convert between a float and a 32 bit
316  int. */
317 
318 typedef union
319 {
320  float value;
323 
324 /* Get a 32 bit int from a float. */
325 
326 #define GET_FLOAT_WORD(i,d) \
327 do { \
328  ieee_float_shape_type gf_u; \
329  gf_u.value = (d); \
330  (i) = gf_u.word; \
331 } while (0)
332 
333 /* Set a float from a 32 bit int. */
334 
335 #define SET_FLOAT_WORD(d,i) \
336 do { \
337  ieee_float_shape_type sf_u; \
338  sf_u.word = (i); \
339  (d) = sf_u.value; \
340 } while (0)
341 
342 #ifdef FLT_EVAL_METHOD
343 /*
344  * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
345  */
346 #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
347 #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
348 #else /* FLT_EVAL_METHOD == 0 || __GNUC__ == 0 */
349 #define STRICT_ASSIGN(type, lval, rval) do { \
350  volatile type __lval; \
351  \
352  if (sizeof(type) >= sizeof(long double)) \
353  (lval) = (rval); \
354  else { \
355  __lval = (rval); \
356  (lval) = __lval; \
357  } \
358 } while (0)
359 #endif /* FLT_EVAL_METHOD == 0 || __GNUC__ == 0 */
360 #endif /* FLT_EVAL_METHOD */
361 
362 /* fdlibm kernel function */
363 extern int __ieee754_rem_pio2(double,double*);
364 extern double __kernel_sin(double,double,int);
365 extern double __kernel_cos(double,double);
366 extern double __kernel_tan(double,double,int);
367 extern int __kernel_rem_pio2(double*,double*,int,int,int);
368 
369 /* float versions of fdlibm kernel functions */
370 extern int __ieee754_rem_pio2f(float,float*);
371 extern float __kernel_sinf(float,float,int);
372 extern float __kernel_cosf(float,float);
373 extern float __kernel_tanf(float,float,int);
374 extern int __kernel_rem_pio2f(float*,float*,int,int,int,const int*);
375 
376 /* long double precision kernel functions */
377 long double __kernel_sinl(long double, long double, int);
378 long double __kernel_cosl(long double, long double);
379 long double __kernel_tanl(long double, long double, int);
380 
381 /*
382  * Common routine to process the arguments to nan(), nanf(), and nanl().
383  */
384 void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
385 
386 /*
387  * TRUNC() is a macro that sets the trailing 27 bits in the mantissa
388  * of an IEEE double variable to zero. It must be expression-like
389  * for syntactic reasons, and we implement this expression using
390  * an inline function instead of a pure macro to avoid depending
391  * on the gcc feature of statement-expressions.
392  */
393 #define TRUNC(d) (_b_trunc(&(d)))
394 
395 static __inline void
396 _b_trunc(volatile double *_dp)
397 {
398  uint32_t _lw;
399 
400  GET_LOW_WORD(_lw, *_dp);
401  SET_LOW_WORD(*_dp, _lw & 0xf8000000);
402 }
403 
404 struct Double {
405  double a;
406  double b;
407 };
408 
409 /*
410  * Functions internal to the math package, yet not static.
411  */
412 double __exp__D(double, double);
413 struct Double __log__D(double);
414 long double __p1evll(long double, void *, int);
415 long double __polevll(long double, void *, int);
416 
417 #endif /* _MATH_PRIVATE_H_ */
int __ieee754_rem_pio2f(float, float *)
Definition: e_rem_pio2f.c:87
int __kernel_rem_pio2(double *, double *, int, int, int)
Definition: k_rem_pio2.c:285
#define exp(x)
Definition: math.h:176
float __kernel_tanf(float, float, int)
Definition: k_tanf.c:40
long double __kernel_tanl(long double, long double, int)
int __kernel_rem_pio2f(float *, float *, int, int, int, const int *)
uint32_t u_int32_t
Definition: types.h:10
double __kernel_tan(double, double, int)
Definition: k_tan.c:74
unsigned int uint32_t
Definition: stdint.h:6
#define SET_LOW_WORD(d, v)
Definition: math_private.h:307
double a
Definition: math_private.h:405
double __exp__D(double, double)
Definition: b_exp__D.c:84
void _scan_nan(uint32_t *__words, int __num_words, const char *__s)
struct Double __log__D(double)
Definition: b_log__D.c:354
double __kernel_sin(double, double, int)
Definition: k_sin.c:54
long double __p1evll(long double, void *, int)
long double __polevll(long double, void *, int)
#define GET_LOW_WORD(i, d)
Definition: math_private.h:278
float __kernel_cosf(float, float)
Definition: k_cosf.c:29
float __kernel_sinf(float, float, int)
Definition: k_sinf.c:29
long double __kernel_sinl(long double, long double, int)
uint64_t u_int64_t
Definition: types.h:11
int __ieee754_rem_pio2(double, double *)
Definition: e_rem_pio2.c:54
double __kernel_cos(double, double)
Definition: k_cos.c:61
double b
Definition: math_private.h:406
long double __kernel_cosl(long double, long double)