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