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 #endif 190