]>
Commit | Line | Data |
---|---|---|
545a5cb6 | 1 | /* GCC Quad-Precision Math Library |
1b78544f | 2 | Copyright (C) 2010, 2011 Free Software Foundation, Inc. |
545a5cb6 TB |
3 | Written by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> |
4 | ||
b5d4b580 TB |
5 | This file is part of the libquadmath library. |
6 | Libquadmath is free software; you can redistribute it and/or | |
545a5cb6 TB |
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 | ||
b5d4b580 | 11 | Libquadmath is distributed in the hope that it will be useful, |
545a5cb6 TB |
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 | |
b5d4b580 | 17 | License along with libquadmath; see the file COPYING.LIB. If |
545a5cb6 TB |
18 | not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, |
19 | Boston, MA 02110-1301, USA. */ | |
20 | ||
1ec601bf FXC |
21 | #ifndef QUADMATH_IMP_H |
22 | #define QUADMATH_IMP_H | |
23 | ||
24 | #include <stdint.h> | |
25 | #include <stdlib.h> | |
26 | #include "quadmath.h" | |
e8d42d28 | 27 | #include "config.h" |
1ec601bf FXC |
28 | |
29 | ||
f029f4be TB |
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 | ||
b5d4b580 | 40 | /* Prototypes for internal functions. */ |
f0c2df63 TB |
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); | |
f029f4be TB |
46 | extern __float128 __quadmath_x2y2m1q (__float128 x, __float128 y); |
47 | extern int __quadmath_isinf_nsq (__float128 x); | |
48 | ||
49 | ||
1ec601bf FXC |
50 | |
51 | ||
52 | ||
b5d4b580 | 53 | /* Frankly, if you have __float128, you have 64-bit integers, right? */ |
1ec601bf FXC |
54 | #ifndef UINT64_C |
55 | # error "No way!" | |
56 | #endif | |
57 | ||
58 | ||
b5d4b580 | 59 | /* Main union type we use to manipulate the floating-point type. */ |
1ec601bf FXC |
60 | typedef union |
61 | { | |
62 | __float128 value; | |
63 | ||
64 | struct | |
744bbef1 KT |
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 | |
1ec601bf | 70 | { |
dbc9f6c6 | 71 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
1ec601bf FXC |
72 | unsigned negative:1; |
73 | unsigned exponent:15; | |
74 | uint64_t mant_high:48; | |
75 | uint64_t mant_low:64; | |
dbc9f6c6 | 76 | #else |
1ec601bf FXC |
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 | { | |
dbc9f6c6 | 86 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
1ec601bf FXC |
87 | uint64_t high; |
88 | uint64_t low; | |
dbc9f6c6 | 89 | #else |
1ec601bf FXC |
90 | uint64_t low; |
91 | uint64_t high; | |
92 | #endif | |
93 | } words64; | |
94 | ||
95 | struct | |
96 | { | |
dbc9f6c6 | 97 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
1ec601bf FXC |
98 | uint32_t w0; |
99 | uint32_t w1; | |
100 | uint32_t w2; | |
101 | uint32_t w3; | |
dbc9f6c6 | 102 | #else |
1ec601bf FXC |
103 | uint32_t w3; |
104 | uint32_t w2; | |
105 | uint32_t w1; | |
106 | uint32_t w0; | |
107 | #endif | |
108 | } words32; | |
109 | ||
110 | struct | |
744bbef1 KT |
111 | #ifdef __MINGW32__ |
112 | /* Make sure we are using gnu-style bitfield handling. */ | |
113 | __attribute__ ((gcc_struct)) | |
114 | #endif | |
1ec601bf | 115 | { |
dbc9f6c6 | 116 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
1ec601bf FXC |
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; | |
dbc9f6c6 | 122 | #else |
1ec601bf FXC |
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 | ||
fa23b182 JJ |
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) | |
1ec601bf | 188 | |
1eba0867 JJ |
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 | ||
1ec601bf | 230 | #endif |