1 | /* GCC Quad-Precision Math Library |
2 | Copyright (C) 2010, 2011 Free Software Foundation, Inc. |
3 | Written by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> |
4 | |
5 | This file is part of the libquadmath library. |
6 | Libquadmath is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Library General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2 of the License, or (at your option) any later version. |
10 | |
11 | Libquadmath is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Library General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Library General Public |
17 | License along with libquadmath; see the file COPYING.LIB. If |
18 | not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, |
19 | Boston, MA 02110-1301, USA. */ |
20 | |
21 | #ifndef QUADMATH_IMP_H |
22 | #define QUADMATH_IMP_H |
23 | |
24 | #include <stdint.h> |
25 | #include <stdlib.h> |
26 | #include "quadmath.h" |
27 | #include "config.h" |
28 | |
29 | |
30 | /* Under IEEE 754, an architecture may determine tininess of |
31 | floating-point results either "before rounding" or "after |
32 | rounding", but must do so in the same way for all operations |
33 | returning binary results. Define TININESS_AFTER_ROUNDING to 1 for |
34 | "after rounding" architectures, 0 for "before rounding" |
35 | architectures. */ |
36 | |
37 | #define TININESS_AFTER_ROUNDING 1 |
38 | |
39 | |
40 | /* Prototypes for internal functions. */ |
41 | extern int32_t __quadmath_rem_pio2q (__float128, __float128 *); |
42 | extern void __quadmath_kernel_sincosq (__float128, __float128, __float128 *, |
43 | __float128 *, int); |
44 | extern __float128 __quadmath_kernel_sinq (__float128, __float128, int); |
45 | extern __float128 __quadmath_kernel_cosq (__float128, __float128); |
46 | extern __float128 __quadmath_x2y2m1q (__float128 x, __float128 y); |
47 | extern int __quadmath_isinf_nsq (__float128 x); |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | /* Frankly, if you have __float128, you have 64-bit integers, right? */ |
54 | #ifndef UINT64_C |
55 | # error "No way!" |
56 | #endif |
57 | |
58 | |
59 | /* Main union type we use to manipulate the floating-point type. */ |
60 | typedef union |
61 | { |
62 | __float128 value; |
63 | |
64 | struct |
65 | #ifdef __MINGW32__ |
66 | /* On mingw targets the ms-bitfields option is active by default. |
67 | Therefore enforce gnu-bitfield style. */ |
68 | __attribute__ ((gcc_struct)) |
69 | #endif |
70 | { |
71 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
72 | unsigned negative:1; |
73 | unsigned exponent:15; |
74 | uint64_t mant_high:48; |
75 | uint64_t mant_low:64; |
76 | #else |
77 | uint64_t mant_low:64; |
78 | uint64_t mant_high:48; |
79 | unsigned exponent:15; |
80 | unsigned negative:1; |
81 | #endif |
82 | } ieee; |
83 | |
84 | struct |
85 | { |
86 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
87 | uint64_t high; |
88 | uint64_t low; |
89 | #else |
90 | uint64_t low; |
91 | uint64_t high; |
92 | #endif |
93 | } words64; |
94 | |
95 | struct |
96 | { |
97 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
98 | uint32_t w0; |
99 | uint32_t w1; |
100 | uint32_t w2; |
101 | uint32_t w3; |
102 | #else |
103 | uint32_t w3; |
104 | uint32_t w2; |
105 | uint32_t w1; |
106 | uint32_t w0; |
107 | #endif |
108 | } words32; |
109 | |
110 | struct |
111 | #ifdef __MINGW32__ |
112 | /* Make sure we are using gnu-style bitfield handling. */ |
113 | __attribute__ ((gcc_struct)) |
114 | #endif |
115 | { |
116 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
117 | unsigned negative:1; |
118 | unsigned exponent:15; |
119 | unsigned quiet_nan:1; |
120 | uint64_t mant_high:47; |
121 | uint64_t mant_low:64; |
122 | #else |
123 | uint64_t mant_low:64; |
124 | uint64_t mant_high:47; |
125 | unsigned quiet_nan:1; |
126 | unsigned exponent:15; |
127 | unsigned negative:1; |
128 | #endif |
129 | } nan; |
130 | |
131 | } ieee854_float128; |
132 | |
133 | |
134 | /* Get two 64 bit ints from a long double. */ |
135 | #define GET_FLT128_WORDS64(ix0,ix1,d) \ |
136 | do { \ |
137 | ieee854_float128 u; \ |
138 | u.value = (d); \ |
139 | (ix0) = u.words64.high; \ |
140 | (ix1) = u.words64.low; \ |
141 | } while (0) |
142 | |
143 | /* Set a long double from two 64 bit ints. */ |
144 | #define SET_FLT128_WORDS64(d,ix0,ix1) \ |
145 | do { \ |
146 | ieee854_float128 u; \ |
147 | u.words64.high = (ix0); \ |
148 | u.words64.low = (ix1); \ |
149 | (d) = u.value; \ |
150 | } while (0) |
151 | |
152 | /* Get the more significant 64 bits of a long double mantissa. */ |
153 | #define GET_FLT128_MSW64(v,d) \ |
154 | do { \ |
155 | ieee854_float128 u; \ |
156 | u.value = (d); \ |
157 | (v) = u.words64.high; \ |
158 | } while (0) |
159 | |
160 | /* Set the more significant 64 bits of a long double mantissa from an int. */ |
161 | #define SET_FLT128_MSW64(d,v) \ |
162 | do { \ |
163 | ieee854_float128 u; \ |
164 | u.value = (d); \ |
165 | u.words64.high = (v); \ |
166 | (d) = u.value; \ |
167 | } while (0) |
168 | |
169 | /* Get the least significant 64 bits of a long double mantissa. */ |
170 | #define GET_FLT128_LSW64(v,d) \ |
171 | do { \ |
172 | ieee854_float128 u; \ |
173 | u.value = (d); \ |
174 | (v) = u.words64.low; \ |
175 | } while (0) |
176 | |
177 | |
178 | #define IEEE854_FLOAT128_BIAS 0x3fff |
179 | |
180 | #define QUADFP_NAN 0 |
181 | #define QUADFP_INFINITE 1 |
182 | #define QUADFP_ZERO 2 |
183 | #define QUADFP_SUBNORMAL 3 |
184 | #define QUADFP_NORMAL 4 |
185 | #define fpclassifyq(x) \ |
186 | __builtin_fpclassify (QUADFP_NAN, QUADFP_INFINITE, QUADFP_NORMAL, \ |
187 | QUADFP_SUBNORMAL, QUADFP_ZERO, x) |
188 | |
189 | #ifndef math_opt_barrier |
190 | # define math_opt_barrier(x) \ |
191 | ({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; }) |
192 | # define math_force_eval(x) \ |
193 | ({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); }) |
194 | #endif |
195 | |
196 | /* math_narrow_eval reduces its floating-point argument to the range |
197 | and precision of its semantic type. (The original evaluation may |
198 | still occur with excess range and precision, so the result may be |
199 | affected by double rounding.) */ |
200 | #define math_narrow_eval(x) (x) |
201 | |
202 | /* If X (which is not a NaN) is subnormal, force an underflow |
203 | exception. */ |
204 | #define math_check_force_underflow(x) \ |
205 | do \ |
206 | { \ |
207 | __float128 force_underflow_tmp = (x); \ |
208 | if (fabsq (force_underflow_tmp) < FLT128_MIN) \ |
209 | { \ |
210 | __float128 force_underflow_tmp2 \ |
211 | = force_underflow_tmp * force_underflow_tmp; \ |
212 | math_force_eval (force_underflow_tmp2); \ |
213 | } \ |
214 | } \ |
215 | while (0) |
216 | /* Likewise, but X is also known to be nonnegative. */ |
217 | #define math_check_force_underflow_nonneg(x) \ |
218 | do \ |
219 | { \ |
220 | __float128 force_underflow_tmp = (x); \ |
221 | if (force_underflow_tmp < FLT128_MIN) \ |
222 | { \ |
223 | __float128 force_underflow_tmp2 \ |
224 | = force_underflow_tmp * force_underflow_tmp; \ |
225 | math_force_eval (force_underflow_tmp2); \ |
226 | } \ |
227 | } \ |
228 | while (0) |
229 | |
230 | #endif |
231 | |