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) << 3; 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 // If a number x is a NAN, then it is a quiet NAN if: 36 // QuietNaNMask & bits(x) != 0 37 // Else, it is a signalling NAN. 38 static constexpr BitsType QUIET_NAN_MASK = 0x00400000U; 39 }; 40 41 template <> struct FloatProperties<double> { 42 typedef uint64_t BitsType; 43 static_assert(sizeof(BitsType) == sizeof(double), 44 "Unexpected size of 'double' type."); 45 46 static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3; 47 48 static constexpr uint32_t MANTISSA_WIDTH = 52; 49 static constexpr uint32_t EXPONENT_WIDTH = 11; 50 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; 51 static constexpr BitsType SIGN_MASK = BitsType(1) 52 << (EXPONENT_WIDTH + MANTISSA_WIDTH); 53 static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK); 54 static constexpr uint32_t EXPONENT_BIAS = 1023; 55 56 // If a number x is a NAN, then it is a quiet NAN if: 57 // QuietNaNMask & bits(x) != 0 58 // Else, it is a signalling NAN. 59 static constexpr BitsType QUIET_NAN_MASK = 0x0008000000000000ULL; 60 }; 61 62 #if defined(LONG_DOUBLE_IS_DOUBLE) 63 // Properties for numbers represented in 64 bits long double on Windows 64 // platform. 65 template <> struct FloatProperties<long double> { 66 typedef uint64_t BitsType; 67 static_assert(sizeof(BitsType) == sizeof(double), 68 "Unexpected size of 'double' type."); 69 70 static constexpr uint32_t BIT_WIDTH = FloatProperties<double>::BIT_WIDTH; 71 72 static constexpr uint32_t MANTISSA_WIDTH = 73 FloatProperties<double>::MANTISSA_WIDTH; 74 static constexpr uint32_t EXPONENT_WIDTH = 75 FloatProperties<double>::EXPONENT_WIDTH; 76 static constexpr BitsType MANTISSA_MASK = 77 FloatProperties<double>::MANTISSA_MASK; 78 static constexpr BitsType SIGN_MASK = FloatProperties<double>::SIGN_MASK; 79 static constexpr BitsType EXPONENT_MASK = 80 FloatProperties<double>::EXPONENT_MASK; 81 static constexpr uint32_t EXPONENT_BIAS = 82 FloatProperties<double>::EXPONENT_BIAS; 83 84 // If a number x is a NAN, then it is a quiet NAN if: 85 // QuietNaNMask & bits(x) != 0 86 // Else, it is a signalling NAN. 87 static constexpr BitsType QUIET_NAN_MASK = 88 FloatProperties<double>::QUIET_NAN_MASK; 89 }; 90 #elif defined(SPECIAL_X86_LONG_DOUBLE) 91 // Properties for numbers represented in 80 bits long double on non-Windows x86 92 // platforms. 93 template <> struct FloatProperties<long double> { 94 typedef __uint128_t BitsType; 95 static_assert(sizeof(BitsType) == sizeof(long double), 96 "Unexpected size of 'long double' type."); 97 98 static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) << 3) - 48; 99 100 static constexpr uint32_t MANTISSA_WIDTH = 63; 101 static constexpr uint32_t EXPONENT_WIDTH = 15; 102 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; 103 static constexpr BitsType SIGN_MASK = 104 BitsType(1) << (EXPONENT_WIDTH + MANTISSA_WIDTH + 1); 105 static constexpr BitsType EXPONENT_MASK = 106 ((BitsType(1) << EXPONENT_WIDTH) - 1) << (MANTISSA_WIDTH + 1); 107 static constexpr uint32_t EXPONENT_BIAS = 16383; 108 109 // If a number x is a NAN, then it is a quiet NAN if: 110 // QuietNaNMask & bits(x) != 0 111 // Else, it is a signalling NAN. 112 static constexpr BitsType QUIET_NAN_MASK = BitsType(1) 113 << (MANTISSA_WIDTH - 1); 114 }; 115 #else 116 // Properties for numbers represented in 128 bits long double on non x86 117 // platform. 118 template <> struct FloatProperties<long double> { 119 typedef __uint128_t BitsType; 120 static_assert(sizeof(BitsType) == sizeof(long double), 121 "Unexpected size of 'long double' type."); 122 123 static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3; 124 125 static constexpr uint32_t MANTISSA_WIDTH = 112; 126 static constexpr uint32_t EXPONENT_WIDTH = 15; 127 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; 128 static constexpr BitsType SIGN_MASK = BitsType(1) 129 << (EXPONENT_WIDTH + MANTISSA_WIDTH); 130 static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK); 131 static constexpr uint32_t EXPONENT_BIAS = 16383; 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 #endif 140 141 // Define the float type corresponding to the BitsType. 142 template <typename BitsType> struct FloatType; 143 144 template <> struct FloatType<uint32_t> { 145 static_assert(sizeof(uint32_t) == sizeof(float), 146 "Unexpected size of 'float' type."); 147 typedef float Type; 148 }; 149 150 template <> struct FloatType<uint64_t> { 151 static_assert(sizeof(uint64_t) == sizeof(double), 152 "Unexpected size of 'double' type."); 153 typedef double Type; 154 }; 155 156 template <typename BitsType> 157 using FloatTypeT = typename FloatType<BitsType>::Type; 158 159 } // namespace fputil 160 } // namespace __llvm_libc 161 162 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H 163