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 bitWidth = sizeof(BitsType) << 3; 26 27 static constexpr uint32_t mantissaWidth = 23; 28 static constexpr uint32_t exponentWidth = 8; 29 static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1; 30 static constexpr BitsType signMask = BitsType(1) 31 << (exponentWidth + mantissaWidth); 32 static constexpr BitsType exponentMask = ~(signMask | mantissaMask); 33 static constexpr uint32_t exponentBias = 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 quietNaNMask = 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 bitWidth = sizeof(BitsType) << 3; 47 48 static constexpr uint32_t mantissaWidth = 52; 49 static constexpr uint32_t exponentWidth = 11; 50 static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1; 51 static constexpr BitsType signMask = BitsType(1) 52 << (exponentWidth + mantissaWidth); 53 static constexpr BitsType exponentMask = ~(signMask | mantissaMask); 54 static constexpr uint32_t exponentBias = 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 quietNaNMask = 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 bitWidth = FloatProperties<double>::bitWidth; 71 72 static constexpr uint32_t mantissaWidth = 73 FloatProperties<double>::mantissaWidth; 74 static constexpr uint32_t exponentWidth = 75 FloatProperties<double>::exponentWidth; 76 static constexpr BitsType mantissaMask = 77 FloatProperties<double>::mantissaMask; 78 static constexpr BitsType signMask = FloatProperties<double>::signMask; 79 static constexpr BitsType exponentMask = 80 FloatProperties<double>::exponentMask; 81 static constexpr uint32_t exponentBias = 82 FloatProperties<double>::exponentBias; 83 }; 84 #elif defined(SPECIAL_X86_LONG_DOUBLE) 85 // Properties for numbers represented in 80 bits long double on non-Windows x86 86 // platforms. 87 template <> struct FloatProperties<long double> { 88 typedef __uint128_t BitsType; 89 static_assert(sizeof(BitsType) == sizeof(long double), 90 "Unexpected size of 'long double' type."); 91 92 static constexpr uint32_t bitWidth = (sizeof(BitsType) << 3) - 48; 93 94 static constexpr uint32_t mantissaWidth = 63; 95 static constexpr uint32_t exponentWidth = 15; 96 static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1; 97 static constexpr BitsType signMask = BitsType(1) 98 << (exponentWidth + mantissaWidth + 1); 99 static constexpr BitsType exponentMask = ((BitsType(1) << exponentWidth) - 1) 100 << (mantissaWidth + 1); 101 static constexpr uint32_t exponentBias = 16383; 102 }; 103 #else 104 // Properties for numbers represented in 128 bits long double on non x86 105 // platform. 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 bitWidth = sizeof(BitsType) << 3; 112 113 static constexpr uint32_t mantissaWidth = 112; 114 static constexpr uint32_t exponentWidth = 15; 115 static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1; 116 static constexpr BitsType signMask = BitsType(1) 117 << (exponentWidth + mantissaWidth); 118 static constexpr BitsType exponentMask = ~(signMask | mantissaMask); 119 static constexpr uint32_t exponentBias = 16383; 120 }; 121 #endif 122 123 // Define the float type corresponding to the BitsType. 124 template <typename BitsType> struct FloatType; 125 126 template <> struct FloatType<uint32_t> { 127 static_assert(sizeof(uint32_t) == sizeof(float), 128 "Unexpected size of 'float' type."); 129 typedef float Type; 130 }; 131 132 template <> struct FloatType<uint64_t> { 133 static_assert(sizeof(uint64_t) == sizeof(double), 134 "Unexpected size of 'double' type."); 135 typedef double Type; 136 }; 137 138 template <typename BitsType> 139 using FloatTypeT = typename FloatType<BitsType>::Type; 140 141 } // namespace fputil 142 } // namespace __llvm_libc 143 144 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H 145