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