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