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 |