1 //===-- Properties of floating point numbers --------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H 10 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H 11 12 #include "PlatformDefs.h" 13 #include <stdint.h> 14 15 namespace __llvm_libc { 16 namespace fputil { 17 18 template <typename T> struct FloatProperties {}; 19 20 template <> struct FloatProperties<float> { 21 typedef uint32_t BitsType; 22 static_assert(sizeof(BitsType) == sizeof(float), 23 "Unexpected size of 'float' type."); 24 25 static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8; 26 27 static constexpr uint32_t MANTISSA_WIDTH = 23; 28 static constexpr uint32_t EXPONENT_WIDTH = 8; 29 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; 30 static constexpr BitsType SIGN_MASK = BitsType(1) 31 << (EXPONENT_WIDTH + MANTISSA_WIDTH); 32 static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK); 33 static constexpr uint32_t EXPONENT_BIAS = 127; 34 35 static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK; 36 static_assert(EXP_MANT_MASK == ~SIGN_MASK, 37 "Exponent and mantissa masks are not as expected."); 38 39 // If a number x is a NAN, then it is a quiet NAN if: 40 // QuietNaNMask & bits(x) != 0 41 // Else, it is a signalling NAN. 42 static constexpr BitsType QUIET_NAN_MASK = 0x00400000U; 43 }; 44 45 template <> struct FloatProperties<double> { 46 typedef uint64_t BitsType; 47 static_assert(sizeof(BitsType) == sizeof(double), 48 "Unexpected size of 'double' type."); 49 50 static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8; 51 52 static constexpr uint32_t MANTISSA_WIDTH = 52; 53 static constexpr uint32_t EXPONENT_WIDTH = 11; 54 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; 55 static constexpr BitsType SIGN_MASK = BitsType(1) 56 << (EXPONENT_WIDTH + MANTISSA_WIDTH); 57 static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK); 58 static constexpr uint32_t EXPONENT_BIAS = 1023; 59 60 static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK; 61 static_assert(EXP_MANT_MASK == ~SIGN_MASK, 62 "Exponent and mantissa masks are not as expected."); 63 64 // If a number x is a NAN, then it is a quiet NAN if: 65 // QuietNaNMask & bits(x) != 0 66 // Else, it is a signalling NAN. 67 static constexpr BitsType QUIET_NAN_MASK = 0x0008000000000000ULL; 68 }; 69 70 #if defined(LONG_DOUBLE_IS_DOUBLE) 71 // Properties for numbers represented in 64 bits long double on Windows 72 // platform. 73 template <> struct FloatProperties<long double> { 74 typedef uint64_t BitsType; 75 static_assert(sizeof(BitsType) == sizeof(double), 76 "Unexpected size of 'double' type."); 77 78 static constexpr uint32_t BIT_WIDTH = FloatProperties<double>::BIT_WIDTH; 79 80 static constexpr uint32_t MANTISSA_WIDTH = 81 FloatProperties<double>::MANTISSA_WIDTH; 82 static constexpr uint32_t EXPONENT_WIDTH = 83 FloatProperties<double>::EXPONENT_WIDTH; 84 static constexpr BitsType MANTISSA_MASK = 85 FloatProperties<double>::MANTISSA_MASK; 86 static constexpr BitsType SIGN_MASK = FloatProperties<double>::SIGN_MASK; 87 static constexpr BitsType EXPONENT_MASK = 88 FloatProperties<double>::EXPONENT_MASK; 89 static constexpr uint32_t EXPONENT_BIAS = 90 FloatProperties<double>::EXPONENT_BIAS; 91 92 static constexpr BitsType EXP_MANT_MASK = 93 FloatProperties<double>::EXP_MANT_MASK; 94 static_assert(EXP_MANT_MASK == ~SIGN_MASK, 95 "Exponent and mantissa masks are not as expected."); 96 97 // If a number x is a NAN, then it is a quiet NAN if: 98 // QuietNaNMask & bits(x) != 0 99 // Else, it is a signalling NAN. 100 static constexpr BitsType QUIET_NAN_MASK = 101 FloatProperties<double>::QUIET_NAN_MASK; 102 }; 103 #elif defined(SPECIAL_X86_LONG_DOUBLE) 104 // Properties for numbers represented in 80 bits long double on non-Windows x86 105 // platforms. 106 template <> struct FloatProperties<long double> { 107 typedef __uint128_t BitsType; 108 static_assert(sizeof(BitsType) == sizeof(long double), 109 "Unexpected size of 'long double' type."); 110 111 static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) * 8) - 48; 112 static constexpr BitsType FULL_WIDTH_MASK = ((BitsType(1) << BIT_WIDTH) - 1); 113 114 static constexpr uint32_t MANTISSA_WIDTH = 63; 115 static constexpr uint32_t EXPONENT_WIDTH = 15; 116 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; 117 118 // The x86 80 bit float represents the leading digit of the mantissa 119 // explicitly. This is the mask for that bit. 120 static constexpr BitsType EXPLICIT_BIT_MASK = (BitsType(1) << MANTISSA_WIDTH); 121 122 static constexpr BitsType SIGN_MASK = 123 BitsType(1) << (EXPONENT_WIDTH + MANTISSA_WIDTH + 1); 124 static constexpr BitsType EXPONENT_MASK = 125 ((BitsType(1) << EXPONENT_WIDTH) - 1) << (MANTISSA_WIDTH + 1); 126 static constexpr uint32_t EXPONENT_BIAS = 16383; 127 128 static constexpr BitsType EXP_MANT_MASK = 129 MANTISSA_MASK + EXPLICIT_BIT_MASK + EXPONENT_MASK; 130 static_assert(EXP_MANT_MASK == (~SIGN_MASK & FULL_WIDTH_MASK), 131 "Exponent and mantissa masks are not as expected."); 132 133 // If a number x is a NAN, then it is a quiet NAN if: 134 // QuietNaNMask & bits(x) != 0 135 // Else, it is a signalling NAN. 136 static constexpr BitsType QUIET_NAN_MASK = BitsType(1) 137 << (MANTISSA_WIDTH - 1); 138 }; 139 #else 140 // Properties for numbers represented in 128 bits long double on non x86 141 // platform. 142 template <> struct FloatProperties<long double> { 143 typedef __uint128_t BitsType; 144 static_assert(sizeof(BitsType) == sizeof(long double), 145 "Unexpected size of 'long double' type."); 146 147 static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3; 148 149 static constexpr uint32_t MANTISSA_WIDTH = 112; 150 static constexpr uint32_t EXPONENT_WIDTH = 15; 151 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; 152 static constexpr BitsType SIGN_MASK = BitsType(1) 153 << (EXPONENT_WIDTH + MANTISSA_WIDTH); 154 static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK); 155 static constexpr uint32_t EXPONENT_BIAS = 16383; 156 157 static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK; 158 static_assert(EXP_MANT_MASK == ~SIGN_MASK, 159 "Exponent and mantissa masks are not as expected."); 160 161 // If a number x is a NAN, then it is a quiet NAN if: 162 // QuietNaNMask & bits(x) != 0 163 // Else, it is a signalling NAN. 164 static constexpr BitsType QUIET_NAN_MASK = BitsType(1) 165 << (MANTISSA_WIDTH - 1); 166 }; 167 #endif 168 169 // Define the float type corresponding to the BitsType. 170 template <typename BitsType> struct FloatType; 171 172 template <> struct FloatType<uint32_t> { 173 static_assert(sizeof(uint32_t) == sizeof(float), 174 "Unexpected size of 'float' type."); 175 typedef float Type; 176 }; 177 178 template <> struct FloatType<uint64_t> { 179 static_assert(sizeof(uint64_t) == sizeof(double), 180 "Unexpected size of 'double' type."); 181 typedef double Type; 182 }; 183 184 template <typename BitsType> 185 using FloatTypeT = typename FloatType<BitsType>::Type; 186 187 } // namespace fputil 188 } // namespace __llvm_libc 189 190 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H 191