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 113 static constexpr uint32_t MANTISSA_WIDTH = 63; 114 static constexpr uint32_t EXPONENT_WIDTH = 15; 115 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; 116 static constexpr BitsType SIGN_MASK = 117 BitsType(1) << (EXPONENT_WIDTH + MANTISSA_WIDTH + 1); 118 static constexpr BitsType EXPONENT_MASK = 119 ((BitsType(1) << EXPONENT_WIDTH) - 1) << (MANTISSA_WIDTH + 1); 120 static constexpr uint32_t EXPONENT_BIAS = 16383; 121 122 // If a number x is a NAN, then it is a quiet NAN if: 123 // QuietNaNMask & bits(x) != 0 124 // Else, it is a signalling NAN. 125 static constexpr BitsType QUIET_NAN_MASK = BitsType(1) 126 << (MANTISSA_WIDTH - 1); 127 }; 128 #else 129 // Properties for numbers represented in 128 bits long double on non x86 130 // platform. 131 template <> struct FloatProperties<long double> { 132 typedef __uint128_t BitsType; 133 static_assert(sizeof(BitsType) == sizeof(long double), 134 "Unexpected size of 'long double' type."); 135 136 static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3; 137 138 static constexpr uint32_t MANTISSA_WIDTH = 112; 139 static constexpr uint32_t EXPONENT_WIDTH = 15; 140 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; 141 static constexpr BitsType SIGN_MASK = BitsType(1) 142 << (EXPONENT_WIDTH + MANTISSA_WIDTH); 143 static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK); 144 static constexpr uint32_t EXPONENT_BIAS = 16383; 145 146 static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK; 147 static_assert(EXP_MANT_MASK == ~SIGN_MASK, 148 "Exponent and mantissa masks are not as expected."); 149 150 // If a number x is a NAN, then it is a quiet NAN if: 151 // QuietNaNMask & bits(x) != 0 152 // Else, it is a signalling NAN. 153 static constexpr BitsType QUIET_NAN_MASK = BitsType(1) 154 << (MANTISSA_WIDTH - 1); 155 }; 156 #endif 157 158 // Define the float type corresponding to the BitsType. 159 template <typename BitsType> struct FloatType; 160 161 template <> struct FloatType<uint32_t> { 162 static_assert(sizeof(uint32_t) == sizeof(float), 163 "Unexpected size of 'float' type."); 164 typedef float Type; 165 }; 166 167 template <> struct FloatType<uint64_t> { 168 static_assert(sizeof(uint64_t) == sizeof(double), 169 "Unexpected size of 'double' type."); 170 typedef double Type; 171 }; 172 173 template <typename BitsType> 174 using FloatTypeT = typename FloatType<BitsType>::Type; 175 176 } // namespace fputil 177 } // namespace __llvm_libc 178 179 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H 180