[libc][NFC] Move aligned access implementations to separate header
[llvm-project.git] / libc / src / __support / FPUtil / FloatProperties.h
blobb463441847a3077ff501d00c5b94a2f0a8a1b00c
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 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H
10 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H
12 #include "PlatformDefs.h"
14 #include "src/__support/UInt128.h"
16 #include <stdint.h>
18 namespace __llvm_libc {
19 namespace fputil {
21 template <typename T> struct FloatProperties {};
23 template <> struct FloatProperties<float> {
24 typedef uint32_t BitsType;
25 static_assert(sizeof(BitsType) == sizeof(float),
26 "Unexpected size of 'float' type.");
28 static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8;
30 static constexpr uint32_t MANTISSA_WIDTH = 23;
31 // The mantissa precision includes the implicit bit.
32 static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
33 static constexpr uint32_t EXPONENT_WIDTH = 8;
34 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
35 static constexpr BitsType SIGN_MASK = BitsType(1)
36 << (EXPONENT_WIDTH + MANTISSA_WIDTH);
37 static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
38 static constexpr uint32_t EXPONENT_BIAS = 127;
40 static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
41 static_assert(EXP_MANT_MASK == ~SIGN_MASK,
42 "Exponent and mantissa masks are not as expected.");
44 // If a number x is a NAN, then it is a quiet NAN if:
45 // QuietNaNMask & bits(x) != 0
46 // Else, it is a signalling NAN.
47 static constexpr BitsType QUIET_NAN_MASK = 0x00400000U;
50 template <> struct FloatProperties<double> {
51 typedef uint64_t BitsType;
52 static_assert(sizeof(BitsType) == sizeof(double),
53 "Unexpected size of 'double' type.");
55 static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8;
57 static constexpr uint32_t MANTISSA_WIDTH = 52;
58 static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
59 static constexpr uint32_t EXPONENT_WIDTH = 11;
60 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
61 static constexpr BitsType SIGN_MASK = BitsType(1)
62 << (EXPONENT_WIDTH + MANTISSA_WIDTH);
63 static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
64 static constexpr uint32_t EXPONENT_BIAS = 1023;
66 static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
67 static_assert(EXP_MANT_MASK == ~SIGN_MASK,
68 "Exponent and mantissa masks are not as expected.");
70 // If a number x is a NAN, then it is a quiet NAN if:
71 // QuietNaNMask & bits(x) != 0
72 // Else, it is a signalling NAN.
73 static constexpr BitsType QUIET_NAN_MASK = 0x0008000000000000ULL;
76 #if defined(LONG_DOUBLE_IS_DOUBLE)
77 // Properties for numbers represented in 64 bits long double on Windows
78 // platform.
79 template <> struct FloatProperties<long double> {
80 typedef uint64_t BitsType;
81 static_assert(sizeof(BitsType) == sizeof(double),
82 "Unexpected size of 'double' type.");
84 static constexpr uint32_t BIT_WIDTH = FloatProperties<double>::BIT_WIDTH;
86 static constexpr uint32_t MANTISSA_WIDTH =
87 FloatProperties<double>::MANTISSA_WIDTH;
88 static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
89 static constexpr uint32_t EXPONENT_WIDTH =
90 FloatProperties<double>::EXPONENT_WIDTH;
91 static constexpr BitsType MANTISSA_MASK =
92 FloatProperties<double>::MANTISSA_MASK;
93 static constexpr BitsType SIGN_MASK = FloatProperties<double>::SIGN_MASK;
94 static constexpr BitsType EXPONENT_MASK =
95 FloatProperties<double>::EXPONENT_MASK;
96 static constexpr uint32_t EXPONENT_BIAS =
97 FloatProperties<double>::EXPONENT_BIAS;
99 static constexpr BitsType EXP_MANT_MASK =
100 FloatProperties<double>::EXP_MANT_MASK;
101 static_assert(EXP_MANT_MASK == ~SIGN_MASK,
102 "Exponent and mantissa masks are not as expected.");
104 // If a number x is a NAN, then it is a quiet NAN if:
105 // QuietNaNMask & bits(x) != 0
106 // Else, it is a signalling NAN.
107 static constexpr BitsType QUIET_NAN_MASK =
108 FloatProperties<double>::QUIET_NAN_MASK;
110 #elif defined(SPECIAL_X86_LONG_DOUBLE)
111 // Properties for numbers represented in 80 bits long double on non-Windows x86
112 // platforms.
113 template <> struct FloatProperties<long double> {
114 typedef UInt128 BitsType;
115 static_assert(sizeof(BitsType) == sizeof(long double),
116 "Unexpected size of 'long double' type.");
118 static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) * 8) - 48;
119 static constexpr BitsType FULL_WIDTH_MASK = ((BitsType(1) << BIT_WIDTH) - 1);
121 static constexpr uint32_t MANTISSA_WIDTH = 63;
122 static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
123 static constexpr uint32_t EXPONENT_WIDTH = 15;
124 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
126 // The x86 80 bit float represents the leading digit of the mantissa
127 // explicitly. This is the mask for that bit.
128 static constexpr BitsType EXPLICIT_BIT_MASK = (BitsType(1) << MANTISSA_WIDTH);
130 static constexpr BitsType SIGN_MASK =
131 BitsType(1) << (EXPONENT_WIDTH + MANTISSA_WIDTH + 1);
132 static constexpr BitsType EXPONENT_MASK =
133 ((BitsType(1) << EXPONENT_WIDTH) - 1) << (MANTISSA_WIDTH + 1);
134 static constexpr uint32_t EXPONENT_BIAS = 16383;
136 static constexpr BitsType EXP_MANT_MASK =
137 MANTISSA_MASK | EXPLICIT_BIT_MASK | EXPONENT_MASK;
138 static_assert(EXP_MANT_MASK == (~SIGN_MASK & FULL_WIDTH_MASK),
139 "Exponent and mantissa masks are not as expected.");
141 // If a number x is a NAN, then it is a quiet NAN if:
142 // QuietNaNMask & bits(x) != 0
143 // Else, it is a signalling NAN.
144 static constexpr BitsType QUIET_NAN_MASK = BitsType(1)
145 << (MANTISSA_WIDTH - 1);
147 #else
148 // Properties for numbers represented in 128 bits long double on non x86
149 // platform.
150 template <> struct FloatProperties<long double> {
151 typedef UInt128 BitsType;
152 static_assert(sizeof(BitsType) == sizeof(long double),
153 "Unexpected size of 'long double' type.");
155 static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;
157 static constexpr uint32_t MANTISSA_WIDTH = 112;
158 static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
159 static constexpr uint32_t EXPONENT_WIDTH = 15;
160 static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
161 static constexpr BitsType SIGN_MASK = BitsType(1)
162 << (EXPONENT_WIDTH + MANTISSA_WIDTH);
163 static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
164 static constexpr uint32_t EXPONENT_BIAS = 16383;
166 static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK | EXPONENT_MASK;
167 static_assert(EXP_MANT_MASK == ~SIGN_MASK,
168 "Exponent and mantissa masks are not as expected.");
170 // If a number x is a NAN, then it is a quiet NAN if:
171 // QuietNaNMask & bits(x) != 0
172 // Else, it is a signalling NAN.
173 static constexpr BitsType QUIET_NAN_MASK = BitsType(1)
174 << (MANTISSA_WIDTH - 1);
176 #endif
178 // Define the float type corresponding to the BitsType.
179 template <typename BitsType> struct FloatType;
181 template <> struct FloatType<uint32_t> {
182 static_assert(sizeof(uint32_t) == sizeof(float),
183 "Unexpected size of 'float' type.");
184 typedef float Type;
187 template <> struct FloatType<uint64_t> {
188 static_assert(sizeof(uint64_t) == sizeof(double),
189 "Unexpected size of 'double' type.");
190 typedef double Type;
193 template <typename BitsType>
194 using FloatTypeT = typename FloatType<BitsType>::Type;
196 } // namespace fputil
197 } // namespace __llvm_libc
199 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H