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