1 /* _Float128 IEEE like macros. 2 Copyright (C) 2017-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 #ifndef _IEEE754_FLOAT128_H 19 #define _IEEE754_FLOAT128_H 20 21 #include <endian.h> 22 #include <stdint.h> 23 24 # if __FLOAT_WORD_ORDER == BIG_ENDIAN 25 # define __FLT_EORDER2(t, a, b) t a; t b; 26 # define __FLT_EORDER4(t, a, b, c, d) \ 27 t a; t b; t c; t d; 28 # define __FLT_EORDER6(t, a, b, c, d, e, f) \ 29 t a; t b; t c; t d; t e; t f; 30 # define __FLT_EORDER7(t, a, b, c, d, e, f, g) \ 31 t a; t b; t c; t d; t e; t f; t g; 32 # else 33 # define __FLT_EORDER2(t, a, b) \ 34 t b; t a; 35 # define __FLT_EORDER4(t, a, b, c, d) \ 36 t d; t c; t b; t a; 37 # define __FLT_EORDER6(t, a, b, c, d, e, f) \ 38 t f; t e; t d; t c; t b; t a; 39 # define __FLT_EORDER7(t, a, b, c, d, e, f, g) \ 40 t g; t f; t e; t d; t c; t b; t a; 41 # endif 42 43 /* A union which permits us to convert between _Float128 and 44 four 32 bit ints or two 64 bit ints. */ 45 46 typedef union 47 { 48 _Float128 value; 49 struct 50 { 51 __FLT_EORDER2 (uint64_t, msw, lsw); 52 } parts64; 53 struct 54 { 55 __FLT_EORDER4 (uint32_t, w0, w1, w2, w3); 56 } parts32; 57 } ieee854_float128_shape_type; 58 59 /* Get two 64 bit ints from a _Float128. */ 60 61 # define GET_FLOAT128_WORDS64(ix0,ix1,d) \ 62 do { \ 63 ieee854_float128_shape_type qw_u; \ 64 qw_u.value = (d); \ 65 (ix0) = qw_u.parts64.msw; \ 66 (ix1) = qw_u.parts64.lsw; \ 67 } while (0) 68 69 /* Set a _Float128 from two 64 bit ints. */ 70 71 # define SET_FLOAT128_WORDS64(d,ix0,ix1) \ 72 do { \ 73 ieee854_float128_shape_type qw_u; \ 74 qw_u.parts64.msw = (ix0); \ 75 qw_u.parts64.lsw = (ix1); \ 76 (d) = qw_u.value; \ 77 } while (0) 78 79 /* Get the more significant 64 bits of a _Float128 mantissa. */ 80 81 # define GET_FLOAT128_MSW64(v,d) \ 82 do { \ 83 ieee854_float128_shape_type sh_u; \ 84 sh_u.value = (d); \ 85 (v) = sh_u.parts64.msw; \ 86 } while (0) 87 88 /* Set the more significant 64 bits of a _Float128 mantissa from an int. */ 89 90 # define SET_FLOAT128_MSW64(d,v) \ 91 do { \ 92 ieee854_float128_shape_type sh_u; \ 93 sh_u.value = (d); \ 94 sh_u.parts64.msw = (v); \ 95 (d) = sh_u.value; \ 96 } while (0) 97 98 /* Get the least significant 64 bits of a _Float128 mantissa. */ 99 100 # define GET_FLOAT128_LSW64(v,d) \ 101 do { \ 102 ieee854_float128_shape_type sh_u; \ 103 sh_u.value = (d); \ 104 (v) = sh_u.parts64.lsw; \ 105 } while (0) 106 107 /* Likewise, some helper macros which are exposed via ieee754.h for 108 C99 real types, but not _Float128. */ 109 110 union ieee854_float128 111 { 112 _Float128 d; 113 114 /* This is the IEEE 854 quad-precision format. */ 115 struct 116 { 117 __FLT_EORDER6 (unsigned int, negative:1, 118 exponent:15, 119 mantissa0:16, 120 mantissa1:32, 121 mantissa2:32, 122 mantissa3:32) 123 } ieee; 124 125 /* This format makes it easier to see if a NaN is a signalling NaN. */ 126 struct 127 { 128 __FLT_EORDER7 (unsigned int, negative:1, 129 exponent:15, 130 quiet_nan:1, 131 mantissa0:15, 132 mantissa1:32, 133 mantissa2:32, 134 mantissa3:32) 135 } ieee_nan; 136 }; 137 138 #define IEEE854_FLOAT128_BIAS 0x3fff /* Added to exponent. */ 139 140 #endif 141