1a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
2a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * ====================================================
3a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
4a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes *
5a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Developed at SunPro, a Sun Microsystems, Inc. business.
6a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Permission to use, copy, modify, and distribute this
7a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * software is freely granted, provided that this notice
8a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * is preserved.
9a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * ====================================================
10a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
11a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
12a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
13a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * from: @(#)fdlibm.h 5.1 93/09/24
148cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes * $FreeBSD: head/lib/msun/src/math_private.h 276176 2014-12-24 10:13:53Z ed $
15a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
16a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
17a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifndef _MATH_PRIVATE_H_
18a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	_MATH_PRIVATE_H_
19a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
20a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <sys/types.h>
21a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <machine/endian.h>
22a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
23a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
24a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * The original fdlibm code used statements like:
25a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes *	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
26a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes *	ix0 = *(n0+(int*)&x);			* high word of x *
27a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
28a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * to dig two 32 bit words out of the 64 bit IEEE floating point
29a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * value.  That is non-ANSI, and, moreover, the gcc instruction
30a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * scheduler gets it wrong.  We instead use the following macros.
31a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Unlike the original code, we determine the endianness at compile
32a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * time, not at run time; I don't see much benefit to selecting
33a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * endianness at run time.
34a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
35a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
36a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
37a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * A union which permits us to convert between a double and two 32 bit
38a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * ints.
39a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
40a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
41a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef __arm__
42bd3155dc5ddf09647388ad7f8fdbe6df123fbd6aCalin Juravle#if defined(__VFP_FP__) || defined(__ARM_EABI__)
43a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	IEEE_WORD_ORDER	BYTE_ORDER
44a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#else
45a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	IEEE_WORD_ORDER	BIG_ENDIAN
46a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
47a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#else /* __arm__ */
48a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	IEEE_WORD_ORDER	BYTE_ORDER
49a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
50a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
51a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#if IEEE_WORD_ORDER == BIG_ENDIAN
52a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
53a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughestypedef union
54a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
55a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  double value;
56a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  struct
57a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  {
58a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes    u_int32_t msw;
59a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes    u_int32_t lsw;
60a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  } parts;
61a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  struct
62a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  {
63a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes    u_int64_t w;
64a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  } xparts;
65a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} ieee_double_shape_type;
66a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
67a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
68a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
69a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#if IEEE_WORD_ORDER == LITTLE_ENDIAN
70a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
71a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughestypedef union
72a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
73a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  double value;
74a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  struct
75a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  {
76a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes    u_int32_t lsw;
77a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes    u_int32_t msw;
78a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  } parts;
79a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  struct
80a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  {
81a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes    u_int64_t w;
82a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  } xparts;
83a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} ieee_double_shape_type;
84a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
85a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
86a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
87a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Get two 32 bit ints from a double.  */
88a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
89a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define EXTRACT_WORDS(ix0,ix1,d)				\
90a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
91a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_double_shape_type ew_u;					\
92a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ew_u.value = (d);						\
93a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (ix0) = ew_u.parts.msw;					\
94a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (ix1) = ew_u.parts.lsw;					\
95a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
96a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
97a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Get a 64-bit int from a double. */
98a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define EXTRACT_WORD64(ix,d)					\
99a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
100a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_double_shape_type ew_u;					\
101a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ew_u.value = (d);						\
102a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (ix) = ew_u.xparts.w;						\
103a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
104a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
105a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Get the more significant 32 bit int from a double.  */
106a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
107a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define GET_HIGH_WORD(i,d)					\
108a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
109a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_double_shape_type gh_u;					\
110a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  gh_u.value = (d);						\
111a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (i) = gh_u.parts.msw;						\
112a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
113a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
114a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Get the less significant 32 bit int from a double.  */
115a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
116a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define GET_LOW_WORD(i,d)					\
117a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
118a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_double_shape_type gl_u;					\
119a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  gl_u.value = (d);						\
120a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (i) = gl_u.parts.lsw;						\
121a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
122a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
123a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Set a double from two 32 bit ints.  */
124a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
125a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define INSERT_WORDS(d,ix0,ix1)					\
126a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
127a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_double_shape_type iw_u;					\
128a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  iw_u.parts.msw = (ix0);					\
129a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  iw_u.parts.lsw = (ix1);					\
130a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (d) = iw_u.value;						\
131a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
132a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
133a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Set a double from a 64-bit int. */
134a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define INSERT_WORD64(d,ix)					\
135a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
136a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_double_shape_type iw_u;					\
137a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  iw_u.xparts.w = (ix);						\
138a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (d) = iw_u.value;						\
139a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
140a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
141a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Set the more significant 32 bits of a double from an int.  */
142a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
143a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define SET_HIGH_WORD(d,v)					\
144a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
145a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_double_shape_type sh_u;					\
146a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  sh_u.value = (d);						\
147a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  sh_u.parts.msw = (v);						\
148a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (d) = sh_u.value;						\
149a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
150a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
151a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Set the less significant 32 bits of a double from an int.  */
152a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
153a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define SET_LOW_WORD(d,v)					\
154a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
155a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_double_shape_type sl_u;					\
156a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  sl_u.value = (d);						\
157a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  sl_u.parts.lsw = (v);						\
158a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (d) = sl_u.value;						\
159a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
160a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
161a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
162a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * A union which permits us to convert between a float and a 32 bit
163a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * int.
164a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
165a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
166a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughestypedef union
167a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
168a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  float value;
169a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  /* FIXME: Assumes 32 bit int.  */
170a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  unsigned int word;
171a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} ieee_float_shape_type;
172a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
173a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Get a 32 bit int from a float.  */
174a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
175a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define GET_FLOAT_WORD(i,d)					\
176a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
177a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_float_shape_type gf_u;					\
178a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  gf_u.value = (d);						\
179a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (i) = gf_u.word;						\
180a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
181a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
182a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Set a float from a 32 bit int.  */
183a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
184a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define SET_FLOAT_WORD(d,i)					\
185a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
186a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ieee_float_shape_type sf_u;					\
187a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  sf_u.word = (i);						\
188a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (d) = sf_u.value;						\
189a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
190a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
19178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes/*
19278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * Get expsign and mantissa as 16 bit and 64 bit ints from an 80 bit long
19378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * double.
19478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes */
19578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
19678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	EXTRACT_LDBL80_WORDS(ix0,ix1,d)				\
19778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughesdo {								\
19878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  union IEEEl2bits ew_u;					\
19978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  ew_u.e = (d);							\
20078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  (ix0) = ew_u.xbits.expsign;					\
20178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  (ix1) = ew_u.xbits.man;					\
20278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
20378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
20478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes/*
20578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * Get expsign and mantissa as one 16 bit and two 64 bit ints from a 128 bit
20678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * long double.
20778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes */
20878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
20978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	EXTRACT_LDBL128_WORDS(ix0,ix1,ix2,d)			\
21078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughesdo {								\
21178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  union IEEEl2bits ew_u;					\
21278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  ew_u.e = (d);							\
21378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  (ix0) = ew_u.xbits.expsign;					\
21478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  (ix1) = ew_u.xbits.manh;					\
21578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  (ix2) = ew_u.xbits.manl;					\
21678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
21778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
218a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Get expsign as a 16 bit int from a long double.  */
219a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
220a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	GET_LDBL_EXPSIGN(i,d)					\
221a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
222a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  union IEEEl2bits ge_u;					\
223a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  ge_u.e = (d);							\
224a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (i) = ge_u.xbits.expsign;					\
225a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
226a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
22778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes/*
22878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * Set an 80 bit long double from a 16 bit int expsign and a 64 bit int
22978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * mantissa.
23078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes */
23178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
23278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	INSERT_LDBL80_WORDS(d,ix0,ix1)				\
23378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughesdo {								\
23478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  union IEEEl2bits iw_u;					\
23578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  iw_u.xbits.expsign = (ix0);					\
23678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  iw_u.xbits.man = (ix1);					\
23778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  (d) = iw_u.e;							\
23878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
23978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
24078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes/*
24178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * Set a 128 bit long double from a 16 bit int expsign and two 64 bit ints
24278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * comprising the mantissa.
24378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes */
24478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
24578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	INSERT_LDBL128_WORDS(d,ix0,ix1,ix2)			\
24678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughesdo {								\
24778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  union IEEEl2bits iw_u;					\
24878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  iw_u.xbits.expsign = (ix0);					\
24978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  iw_u.xbits.manh = (ix1);					\
25078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  iw_u.xbits.manl = (ix2);					\
25178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes  (d) = iw_u.e;							\
25278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
25378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
254a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Set expsign of a long double from a 16 bit int.  */
255a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
256a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	SET_LDBL_EXPSIGN(d,v)					\
257a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdo {								\
258a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  union IEEEl2bits se_u;					\
259a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  se_u.e = (d);							\
260a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  se_u.xbits.expsign = (v);					\
261a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes  (d) = se_u.e;							\
262a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
263a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
264a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef __i386__
265a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Long double constants are broken on i386. */
266a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	LD80C(m, ex, v) {						\
267a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	.xbits.man = __CONCAT(m, ULL),					\
268a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	.xbits.expsign = (0x3fff + (ex)) | ((v) < 0 ? 0x8000 : 0),	\
269a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes}
270a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#else
271a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* The above works on non-i386 too, but we use this to check v. */
272a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	LD80C(m, ex, v)	{ .e = (v), }
273a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
274a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
275a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef FLT_EVAL_METHOD
276a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
277a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
278a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
279a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
280a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	STRICT_ASSIGN(type, lval, rval)	((lval) = (rval))
281a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#else
282a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	STRICT_ASSIGN(type, lval, rval) do {	\
283a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	volatile type __lval;			\
284a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes						\
285a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	if (sizeof(type) >= sizeof(long double))	\
286a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		(lval) = (rval);		\
287a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	else {					\
288a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		__lval = (rval);		\
289a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		(lval) = __lval;		\
290a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	}					\
291a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
292a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
293a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif /* FLT_EVAL_METHOD */
294a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
295a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Support switching the mode to FP_PE if necessary. */
296a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#if defined(__i386__) && !defined(NO_FPSETPREC)
297a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	ENTERI()				\
298a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	long double __retval;			\
299a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	fp_prec_t __oprec;			\
300a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes						\
301a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	if ((__oprec = fpgetprec()) != FP_PE)	\
302a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		fpsetprec(FP_PE)
303a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	RETURNI(x) do {				\
304a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	__retval = (x);				\
305a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	if (__oprec != FP_PE)			\
306a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		fpsetprec(__oprec);		\
307a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	RETURNF(__retval);			\
308a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} while (0)
309a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#else
310a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	ENTERI(x)
311a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	RETURNI(x)	RETURNF(x)
312a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
313a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
314a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Default return statement if hack*_t() is not used. */
315a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define      RETURNF(v)      return (v)
316a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
317a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
31878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * 2sum gives the same result as 2sumF without requiring |a| >= |b| or
31978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * a == 0, but is slower.
32078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes */
32178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	_2sum(a, b) do {	\
32278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__typeof(a) __s, __w;	\
32378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes				\
32478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__w = (a) + (b);	\
32578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__s = __w - (a);	\
32678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	(b) = ((a) - (__w - __s)) + ((b) - __s); \
32778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	(a) = __w;		\
32878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
32978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
33078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes/*
33178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * 2sumF algorithm.
33278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes *
33378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * "Normalize" the terms in the infinite-precision expression a + b for
33478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * the sum of 2 floating point values so that b is as small as possible
33578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * relative to 'a'.  (The resulting 'a' is the value of the expression in
33678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * the same precision as 'a' and the resulting b is the rounding error.)
33778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * |a| must be >= |b| or 0, b's type must be no larger than 'a's type, and
33878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * exponent overflow or underflow must not occur.  This uses a Theorem of
33978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * Dekker (1971).  See Knuth (1981) 4.2.2 Theorem C.  The name "TwoSum"
34078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * is apparently due to Skewchuk (1997).
34178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes *
34278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * For this to always work, assignment of a + b to 'a' must not retain any
34378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * extra precision in a + b.  This is required by C standards but broken
34478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * in many compilers.  The brokenness cannot be worked around using
34578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * STRICT_ASSIGN() like we do elsewhere, since the efficiency of this
34678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * algorithm would be destroyed by non-null strict assignments.  (The
34778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * compilers are correct to be broken -- the efficiency of all floating
34878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * point code calculations would be destroyed similarly if they forced the
34978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * conversions.)
35078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes *
35178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * Fortunately, a case that works well can usually be arranged by building
35278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * any extra precision into the type of 'a' -- 'a' should have type float_t,
35378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * double_t or long double.  b's type should be no larger than 'a's type.
35478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * Callers should use these types with scopes as large as possible, to
35578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * reduce their own extra-precision and efficiciency problems.  In
35678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * particular, they shouldn't convert back and forth just to call here.
35778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes */
35878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#ifdef DEBUG
35978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	_2sumF(a, b) do {				\
36078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__typeof(a) __w;				\
36178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	volatile __typeof(a) __ia, __ib, __r, __vw;	\
36278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes							\
36378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__ia = (a);					\
36478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__ib = (b);					\
36578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	assert(__ia == 0 || fabsl(__ia) >= fabsl(__ib));	\
36678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes							\
36778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__w = (a) + (b);				\
36878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	(b) = ((a) - __w) + (b);			\
36978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	(a) = __w;					\
37078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes							\
37178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	/* The next 2 assertions are weak if (a) is already long double. */ \
37278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	assert((long double)__ia + __ib == (long double)(a) + (b));	\
37378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__vw = __ia + __ib;				\
37478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__r = __ia - __vw;				\
37578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__r += __ib;					\
37678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	assert(__vw == (a) && __r == (b));		\
37778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
37878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#else /* !DEBUG */
37978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	_2sumF(a, b) do {	\
38078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__typeof(a) __w;	\
38178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes				\
38278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__w = (a) + (b);	\
38378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	(b) = ((a) - __w) + (b); \
38478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	(a) = __w;		\
38578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
38678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#endif /* DEBUG */
38778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
38878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes/*
38978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * Set x += c, where x is represented in extra precision as a + b.
39078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * x must be sufficiently normalized and sufficiently larger than c,
39178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * and the result is then sufficiently normalized.
39278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes *
39378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * The details of ordering are that |a| must be >= |c| (so that (a, c)
39478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * can be normalized without extra work to swap 'a' with c).  The details of
39578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * the normalization are that b must be small relative to the normalized 'a'.
39678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * Normalization of (a, c) makes the normalized c tiny relative to the
39778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * normalized a, so b remains small relative to 'a' in the result.  However,
39878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * b need not ever be tiny relative to 'a'.  For example, b might be about
39978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * 2**20 times smaller than 'a' to give about 20 extra bits of precision.
40078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * That is usually enough, and adding c (which by normalization is about
40178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * 2**53 times smaller than a) cannot change b significantly.  However,
40278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * cancellation of 'a' with c in normalization of (a, c) may reduce 'a'
40378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * significantly relative to b.  The caller must ensure that significant
40478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * cancellation doesn't occur, either by having c of the same sign as 'a',
40578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * or by having |c| a few percent smaller than |a|.  Pre-normalization of
40678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * (a, b) may help.
40778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes *
40878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * This is is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2
40978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * exercise 19).  We gain considerable efficiency by requiring the terms to
41078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes * be sufficiently normalized and sufficiently increasing.
41178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes */
41278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	_3sumF(a, b, c) do {	\
41378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__typeof(a) __tmp;	\
41478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes				\
41578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__tmp = (c);		\
41678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	_2sumF(__tmp, (a));	\
41778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	(b) += (a);		\
41878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	(a) = __tmp;		\
41978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
42078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
42178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes/*
422a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Common routine to process the arguments to nan(), nanf(), and nanl().
423a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
424a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesvoid _scan_nan(uint32_t *__words, int __num_words, const char *__s);
425a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
426a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef _COMPLEX_H
427a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
428a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
429a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * C99 specifies that complex numbers have the same representation as
430a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * an array of two elements, where the first element is the real part
431a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * and the second element is the imaginary part.
432a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
433a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughestypedef union {
434a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	float complex f;
435a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	float a[2];
436a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} float_complex;
437a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughestypedef union {
438a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	double complex f;
439a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	double a[2];
440a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} double_complex;
441a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughestypedef union {
442a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	long double complex f;
443a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	long double a[2];
444a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} long_double_complex;
445a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	REALPART(z)	((z).a[0])
446a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	IMAGPART(z)	((z).a[1])
447a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
448a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
449a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Inline functions that can be used to construct complex values.
450a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes *
451a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * The C99 standard intends x+I*y to be used for this, but x+I*y is
452a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * currently unusable in general since gcc introduces many overflow,
453a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * underflow, sign and efficiency bugs by rewriting I*y as
454a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
455a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
456a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * to -0.0+I*0.0.
4578cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes *
4588cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes * The C11 standard introduced the macros CMPLX(), CMPLXF() and CMPLXL()
4598cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes * to construct complex values.  Compilers that conform to the C99
4608cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes * standard require the following functions to avoid the above issues.
461a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
4628cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes
4638cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes#ifndef CMPLXF
464a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesstatic __inline float complex
4658cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott HughesCMPLXF(float x, float y)
466a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
467a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	float_complex z;
468a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
469a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	REALPART(z) = x;
470a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	IMAGPART(z) = y;
471a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	return (z.f);
472a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes}
4738cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes#endif
474a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
4758cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes#ifndef CMPLX
476a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesstatic __inline double complex
4778cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott HughesCMPLX(double x, double y)
478a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
479a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	double_complex z;
480a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
481a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	REALPART(z) = x;
482a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	IMAGPART(z) = y;
483a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	return (z.f);
484a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes}
4858cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes#endif
486a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
4878cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes#ifndef CMPLXL
488a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesstatic __inline long double complex
4898cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott HughesCMPLXL(long double x, long double y)
490a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
491a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	long_double_complex z;
492a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
493a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	REALPART(z) = x;
494a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	IMAGPART(z) = y;
495a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	return (z.f);
496a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes}
4978cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes#endif
4988cff2f95d8673b4b9002292d50ce8caa6efb98b6Elliott Hughes
499a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif /* _COMPLEX_H */
500a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
501a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef __GNUCLIKE_ASM
502a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
503a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* Asm versions of some functions. */
504a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
505a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef __amd64__
506a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesstatic __inline int
507a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesirint(double x)
508a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
509a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	int n;
510a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
511a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	asm("cvtsd2si %1,%0" : "=r" (n) : "x" (x));
512a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	return (n);
513a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes}
514a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	HAVE_EFFICIENT_IRINT
515a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
516a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
517a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef __i386__
518a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesstatic __inline int
519a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesirint(double x)
520a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
521a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	int n;
522a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
523a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	asm("fistl %0" : "=m" (n) : "t" (x));
524a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	return (n);
525a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes}
526a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	HAVE_EFFICIENT_IRINT
527a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
528a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
529a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#if defined(__amd64__) || defined(__i386__)
530a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesstatic __inline int
531a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesirintl(long double x)
532a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{
533a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	int n;
534a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
535a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	asm("fistl %0" : "=m" (n) : "t" (x));
536a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	return (n);
537a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes}
538a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	HAVE_EFFICIENT_IRINTL
539a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
540a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
541a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif /* __GNUCLIKE_ASM */
542a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
54378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#ifdef DEBUG
54478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#if defined(__amd64__) || defined(__i386__)
54578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	breakpoint()	asm("int $3")
54678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#else
54778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#include <signal.h>
54878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
54978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	breakpoint()	raise(SIGTRAP)
55078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#endif
55178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#endif
55278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
55378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes/* Write a pari script to test things externally. */
55478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#ifdef DOPRINT
55578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#include <stdio.h>
55678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
55778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#ifndef DOPRINT_SWIZZLE
55878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_SWIZZLE		0
55978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#endif
56078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
56178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#ifdef DOPRINT_LD80
56278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
56378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_START(xp) do {						\
56478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	uint64_t __lx;							\
56578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	uint16_t __hx;							\
56678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes									\
56778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	/* Hack to give more-problematic args. */			\
56878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	EXTRACT_LDBL80_WORDS(__hx, __lx, *xp);				\
56978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__lx ^= DOPRINT_SWIZZLE;					\
57078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	INSERT_LDBL80_WORDS(*xp, __hx, __lx);				\
57178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("x = %.21Lg; ", (long double)*xp);			\
57278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
57378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END1(v)							\
57478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v))
57578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END2(hi, lo)						\
57678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n",		\
57778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	    (long double)(hi), (long double)(lo))
57878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
57978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#elif defined(DOPRINT_D64)
58078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
58178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_START(xp) do {						\
58278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	uint32_t __hx, __lx;						\
58378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes									\
58478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	EXTRACT_WORDS(__hx, __lx, *xp);					\
58578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__lx ^= DOPRINT_SWIZZLE;					\
58678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	INSERT_WORDS(*xp, __hx, __lx);					\
58778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("x = %.21Lg; ", (long double)*xp);			\
58878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
58978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END1(v)							\
59078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v))
59178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END2(hi, lo)						\
59278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n",		\
59378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	    (long double)(hi), (long double)(lo))
59478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
59578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#elif defined(DOPRINT_F32)
59678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
59778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_START(xp) do {						\
59878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	uint32_t __hx;							\
59978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes									\
60078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	GET_FLOAT_WORD(__hx, *xp);					\
60178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__hx ^= DOPRINT_SWIZZLE;					\
60278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	SET_FLOAT_WORD(*xp, __hx);					\
60378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("x = %.21Lg; ", (long double)*xp);			\
60478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
60578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END1(v)							\
60678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v))
60778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END2(hi, lo)						\
60878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n",		\
60978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	    (long double)(hi), (long double)(lo))
61078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
61178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#else /* !DOPRINT_LD80 && !DOPRINT_D64 (LD128 only) */
61278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
61378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#ifndef DOPRINT_SWIZZLE_HIGH
61478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_SWIZZLE_HIGH	0
61578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#endif
61678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
61778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_START(xp) do {						\
61878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	uint64_t __lx, __llx;						\
61978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	uint16_t __hx;							\
62078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes									\
62178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	EXTRACT_LDBL128_WORDS(__hx, __lx, __llx, *xp);			\
62278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__llx ^= DOPRINT_SWIZZLE;					\
62378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__lx ^= DOPRINT_SWIZZLE_HIGH;					\
62478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	INSERT_LDBL128_WORDS(*xp, __hx, __lx, __llx);			\
62578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("x = %.36Lg; ", (long double)*xp);					\
62678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
62778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END1(v)							\
62878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("y = %.36Lg; z = 0; show(x, y, z);\n", (long double)(v))
62978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END2(hi, lo)						\
63078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	printf("y = %.36Lg; z = %.36Lg; show(x, y, z);\n",		\
63178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	    (long double)(hi), (long double)(lo))
63278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
63378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#endif /* DOPRINT_LD80 */
63478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
63578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#else /* !DOPRINT */
63678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_START(xp)
63778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END1(v)
63878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	DOPRINT_END2(hi, lo)
63978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#endif /* DOPRINT */
64078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
64178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	RETURNP(x) do {			\
64278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	DOPRINT_END1(x);		\
64378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	RETURNF(x);			\
64478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
64578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	RETURNPI(x) do {		\
64678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	DOPRINT_END1(x);		\
64778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	RETURNI(x);			\
64878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
64978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	RETURN2P(x, y) do {		\
65078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	DOPRINT_END2((x), (y));		\
65178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	RETURNF((x) + (y));		\
65278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
65378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	RETURN2PI(x, y) do {		\
65478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	DOPRINT_END2((x), (y));		\
65578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	RETURNI((x) + (y));		\
65678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
65778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#ifdef STRUCT_RETURN
65878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	RETURNSP(rp) do {		\
65978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	if (!(rp)->lo_set)		\
66078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes		RETURNP((rp)->hi);	\
66178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	RETURN2P((rp)->hi, (rp)->lo);	\
66278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
66378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	RETURNSPI(rp) do {		\
66478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	if (!(rp)->lo_set)		\
66578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes		RETURNPI((rp)->hi);	\
66678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	RETURN2PI((rp)->hi, (rp)->lo);	\
66778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes} while (0)
66878419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#endif
66978419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes#define	SUM2P(x, y) ({			\
67078419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	const __typeof (x) __x = (x);	\
67178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	const __typeof (y) __y = (y);	\
67278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes					\
67378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	DOPRINT_END2(__x, __y);		\
67478419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes	__x + __y;			\
67578419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes})
67678419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes
677a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*
678a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * ieee style elementary functions
679a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes *
680a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * We rename functions here to improve other sources' diffability
681a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * against fdlibm.
682a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */
683a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_sqrt	sqrt
684a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_acos	acos
685a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_acosh	acosh
686a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_log	log
687a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_log2	log2
688a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_atanh	atanh
689a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_asin	asin
690a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_atan2	atan2
691a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_exp	exp
692a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_cosh	cosh
693a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_fmod	fmod
694a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_pow	pow
695a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_lgamma lgamma
696a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_gamma	gamma
697a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_lgamma_r lgamma_r
698a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_gamma_r gamma_r
699a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_log10	log10
700a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_sinh	sinh
701a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_hypot	hypot
702a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_j0	j0
703a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_j1	j1
704a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_y0	y0
705a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_y1	y1
706a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_jn	jn
707a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_yn	yn
708a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_remainder remainder
709a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_scalb	scalb
710a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_sqrtf	sqrtf
711a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_acosf	acosf
712a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_acoshf acoshf
713a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_logf	logf
714a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_atanhf atanhf
715a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_asinf	asinf
716a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_atan2f atan2f
717a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_expf	expf
718a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_coshf	coshf
719a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_fmodf	fmodf
720a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_powf	powf
721a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_lgammaf lgammaf
722a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_gammaf gammaf
723a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_lgammaf_r lgammaf_r
724a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_gammaf_r gammaf_r
725a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_log10f log10f
726a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_log2f log2f
727a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_sinhf	sinhf
728a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_hypotf hypotf
729a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_j0f	j0f
730a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_j1f	j1f
731a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_y0f	y0f
732a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_y1f	y1f
733a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_jnf	jnf
734a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_ynf	ynf
735a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_remainderf remainderf
736a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define	__ieee754_scalbf scalbf
737a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
738a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* fdlibm kernel function */
739a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesint	__kernel_rem_pio2(double*,double*,int,int,int);
740a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
741a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* double precision kernel functions */
742a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifndef INLINE_REM_PIO2
743a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesint	__ieee754_rem_pio2(double,double*);
744a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
745a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdouble	__kernel_sin(double,double,int);
746a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdouble	__kernel_cos(double,double);
747a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdouble	__kernel_tan(double,double,int);
748a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdouble	__ldexp_exp(double,int);
749a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef _COMPLEX_H
750a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesdouble complex __ldexp_cexp(double complex,int);
751a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
752a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
753a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* float precision kernel functions */
754a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifndef INLINE_REM_PIO2F
755a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesint	__ieee754_rem_pio2f(float,double*);
756a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
757a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifndef INLINE_KERNEL_SINDF
758a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesfloat	__kernel_sindf(double);
759a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
760a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifndef INLINE_KERNEL_COSDF
761a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesfloat	__kernel_cosdf(double);
762a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
763a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifndef INLINE_KERNEL_TANDF
764a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesfloat	__kernel_tandf(double,int);
765a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
766a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesfloat	__ldexp_expf(float,int);
767a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef _COMPLEX_H
768a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesfloat complex __ldexp_cexpf(float complex,int);
769a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif
770a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
771a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* long double precision kernel functions */
772a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hugheslong double __kernel_sinl(long double, long double, int);
773a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hugheslong double __kernel_cosl(long double, long double);
774a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hugheslong double __kernel_tanl(long double, long double, int);
775a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes
776a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif /* !_MATH_PRIVATE_H_ */
777