GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libm/src/math_private.h Lines: 3 3 100.0 %
Date: 2017-11-07 Branches: 0 0 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: math_private.h,v 1.18 2016/09/12 19:47:02 guenther 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 {
42
    u_int32_t mswhi;
43
    u_int32_t mswlo;
44
    u_int32_t lswhi;
45
    u_int32_t lswlo;
46
  } parts32;
47
  struct {
48
    u_int64_t msw;
49
    u_int64_t lsw;
50
  } parts64;
51
} ieee_quad_shape_type;
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;
70
} ieee_quad_shape_type;
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;
136
    u_int32_t msw;
137
    u_int32_t lsw;
138
  } parts;
139
} ieee_extended_shape_type;
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;
157
} ieee_extended_shape_type;
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
  {
236
    u_int32_t msw;
237
    u_int32_t lsw;
238
  } parts;
239
} ieee_double_shape_type;
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;
253
} ieee_double_shape_type;
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;
321
  u_int32_t word;
322
} ieee_float_shape_type;
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
__BEGIN_HIDDEN_DECLS
363
/* fdlibm kernel function */
364
extern int    __ieee754_rem_pio2(double,double*);
365
extern double __kernel_sin(double,double,int);
366
extern double __kernel_cos(double,double);
367
extern double __kernel_tan(double,double,int);
368
extern int    __kernel_rem_pio2(double*,double*,int,int,int);
369
370
/* float versions of fdlibm kernel functions */
371
extern int   __ieee754_rem_pio2f(float,float*);
372
extern float __kernel_sinf(float,float,int);
373
extern float __kernel_cosf(float,float);
374
extern float __kernel_tanf(float,float,int);
375
extern int   __kernel_rem_pio2f(float*,float*,int,int,int,const int*);
376
377
/* long double precision kernel functions */
378
long double __kernel_sinl(long double, long double, int);
379
long double __kernel_cosl(long double, long double);
380
long double __kernel_tanl(long double, long double, int);
381
382
/*
383
 * Common routine to process the arguments to nan(), nanf(), and nanl().
384
 */
385
void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
386
__END_HIDDEN_DECLS
387
388
/*
389
 * TRUNC() is a macro that sets the trailing 27 bits in the mantissa
390
 * of an IEEE double variable to zero.  It must be expression-like
391
 * for syntactic reasons, and we implement this expression using
392
 * an inline function instead of a pure macro to avoid depending
393
 * on the gcc feature of statement-expressions.
394
 */
395
#define TRUNC(d)	(_b_trunc(&(d)))
396
397
static __inline void
398
_b_trunc(volatile double *_dp)
399
{
400
	uint32_t _lw;
401
402
150
	GET_LOW_WORD(_lw, *_dp);
403
75
	SET_LOW_WORD(*_dp, _lw & 0xf8000000);
404
75
}
405
406
struct Double {
407
	double	a;
408
	double	b;
409
};
410
411
/*
412
 * Functions internal to the math package, yet not static.
413
 */
414
__BEGIN_HIDDEN_DECLS
415
double __exp__D(double, double);
416
struct Double __log__D(double);
417
long double __p1evll(long double, void *, int);
418
long double __polevll(long double, void *, int);
419
__END_HIDDEN_DECLS
420
421
#endif /* _MATH_PRIVATE_H_ */