Elements 6.3.3
A C++ base framework for the Euclid Software.
Loading...
Searching...
No Matches
Real.tpp
Go to the documentation of this file.
1
20
21// IWYU pragma: private, include "ElementsKernel/Real.h"
22
23#ifndef ELEMENTSKERNEL_ELEMENTSKERNEL_REAL_IMPL_
24#error "This file should not be included directly! Use ElementsKernel/Real.h instead"
25#else
26
27#include "ElementsKernel/Unused.h" // for ELEMENTS_UNUSED
28#include <cstring> // for size_t, memcpy
29
30namespace Elements {
31
32template <typename RawType>
33constexpr std::size_t defaultMaxUlps() {
35}
36
37template <>
38constexpr std::size_t defaultMaxUlps<float>() {
40}
41
42template <>
43constexpr std::size_t defaultMaxUlps<double>() {
45}
46
47template <typename RawType>
49 m_u.m_value = x;
50}
51
52template <typename RawType>
53RawType FloatingPoint<RawType>::ReinterpretBits(const Bits& bits) {
54 FloatingPoint fp(0);
55 fp.m_u.m_bits = bits;
56 return fp.m_u.m_value;
57}
58
59template <typename RawType>
61 return ReinterpretBits(s_exponent_bitmask);
62}
63
64template <typename RawType>
66 return m_u.m_bits;
67}
68
69template <typename RawType>
71 return s_exponent_bitmask & m_u.m_bits;
72}
73
74template <typename RawType>
76 return s_fraction_bitmask & m_u.m_bits;
77}
78
79template <typename RawType>
81 return s_sign_bitmask & m_u.m_bits;
82}
83
84template <typename RawType>
86 // It's a NAN if the exponent bits are all ones and the fraction
87 // bits are not entirely zeros.
88 return (exponentBits() == s_exponent_bitmask) && (fractionBits() != 0);
89}
90
91template <typename RawType>
93 // The IEEE standard says that any comparison operation involving
94 // a NAN must return false.
95 if (isNan() || rhs.isNan()) {
96 return false;
97 }
98 return distanceBetweenSignAndMagnitudeNumbers(m_u.m_bits, rhs.m_u.m_bits) <= m_max_ulps;
99}
100
101template <typename RawType>
103 if (s_sign_bitmask & sam) {
104 // sam represents a negative number.
105 return ~sam + 1;
106 } else {
107 // sam represents a positive number.
108 return s_sign_bitmask | sam;
109 }
110}
111
112template <typename RawType>
114 const Bits& sam2) {
115 const Bits biased1 = signAndMagnitudeToBiased(sam1);
116 const Bits biased2 = signAndMagnitudeToBiased(sam2);
117 return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
118}
119
120template <typename FloatType>
121bool almostEqual2sComplement(ELEMENTS_UNUSED const FloatType& a, ELEMENTS_UNUSED const FloatType& b,
122 ELEMENTS_UNUSED const std::size_t& max_ulps) {
123 return false;
124}
125
126template <typename RawType>
127bool isNan(const RawType& x) {
128
129 using Bits = typename TypeWithSize<sizeof(RawType)>::UInt;
130 Bits x_bits;
131 std::memcpy(&x_bits, &x, sizeof(x_bits));
132
133 Bits x_exp_bits = FloatingPoint<RawType>::s_exponent_bitmask & x_bits;
134 Bits x_frac_bits = FloatingPoint<RawType>::s_fraction_bitmask & x_bits;
135
136 return (x_exp_bits == FloatingPoint<RawType>::s_exponent_bitmask) && (x_frac_bits != 0);
137}
138
139template <typename RawType, std::size_t max_ulps>
140bool isEqual(const RawType& left, const RawType& right) {
141
142 bool is_equal{false};
143
144 if (not(isNan<RawType>(left) or isNan<RawType>(right))) {
145 using Bits = typename TypeWithSize<sizeof(RawType)>::UInt;
146 Bits l_bits;
147 Bits r_bits;
148 std::memcpy(&l_bits, &left, sizeof(l_bits));
149 std::memcpy(&r_bits, &right, sizeof(r_bits));
150 is_equal = (FloatingPoint<RawType>::distanceBetweenSignAndMagnitudeNumbers(l_bits, r_bits) <= max_ulps);
151 }
152
153 return is_equal;
154}
155
156template <std::size_t max_ulps>
157inline bool isEqual(const float& left, const float& right) {
158 return (isEqual<float, max_ulps>(left, right));
159}
160
161template <std::size_t max_ulps>
162inline bool isEqual(const double& left, const double& right) {
163 return (isEqual<double, max_ulps>(left, right));
164}
165
166template <typename RawType, std::size_t max_ulps>
167inline bool isNotEqual(const RawType& left, const RawType& right) {
168 return (not isEqual<RawType, max_ulps>(left, right));
169}
170
171template <std::size_t max_ulps>
172inline bool isNotEqual(const float& left, const float& right) {
173 return (isNotEqual<float, max_ulps>(left, right));
174}
175
176template <std::size_t max_ulps>
177inline bool isNotEqual(const double& left, const double& right) {
178 return (isNotEqual<double, max_ulps>(left, right));
179}
180
181template <typename RawType, std::size_t max_ulps>
182bool isLess(const RawType& left, const RawType& right) {
183 bool is_less{false};
184
185 if (left < right && (not isEqual<RawType, max_ulps>(left, right))) {
186 is_less = true;
187 }
188
189 return is_less;
190}
191
192template <std::size_t max_ulps>
193inline bool isLess(const float& left, const float& right) {
194 return (isLess<float, max_ulps>(left, right));
195}
196
197template <std::size_t max_ulps>
198inline bool isLess(const double& left, const double& right) {
199 return (isLess<double, max_ulps>(left, right));
200}
201
202template <typename RawType, std::size_t max_ulps>
203bool isGreater(const RawType& left, const RawType& right) {
204 bool is_greater{false};
205
206 if (left > right && (not isEqual<RawType, max_ulps>(left, right))) {
207 is_greater = true;
208 }
209
210 return is_greater;
211}
212
213template <std::size_t max_ulps>
214inline bool isGreater(const float& left, const float& right) {
215 return (isGreater<float, max_ulps>(left, right));
216}
217
218template <std::size_t max_ulps>
219inline bool isGreater(const double& left, const double& right) {
220 return (isGreater<double, max_ulps>(left, right));
221}
222
223template <typename RawType, std::size_t max_ulps>
224bool isLessOrEqual(const RawType& left, const RawType& right) {
225 bool is_loe{false};
226
227 if (not isGreater<RawType, max_ulps>(left, right)) {
228 is_loe = true;
229 }
230
231 return is_loe;
232}
233
234template <std::size_t max_ulps>
235inline bool isLessOrEqual(const float& left, const float& right) {
236 return (isLessOrEqual<float, max_ulps>(left, right));
237}
238
239template <std::size_t max_ulps>
240inline bool isLessOrEqual(const double& left, const double& right) {
241 return (isLessOrEqual<double, max_ulps>(left, right));
242}
243
244template <typename RawType, std::size_t max_ulps>
245bool isGreaterOrEqual(const RawType& left, const RawType& right) {
246 bool is_goe{false};
247
248 if (not isLess<RawType, max_ulps>(left, right)) {
249 is_goe = true;
250 }
251
252 return is_goe;
253}
254
255template <std::size_t max_ulps>
256inline bool isGreaterOrEqual(const float& left, const float& right) {
257 return (isGreaterOrEqual<float, max_ulps>(left, right));
258}
259
260template <std::size_t max_ulps>
261inline bool isGreaterOrEqual(const double& left, const double& right) {
262 return (isGreaterOrEqual<double, max_ulps>(left, right));
263}
264
265template <typename RawType>
266bool realBitWiseEqual(const RawType& left, const RawType& right) {
267#pragma GCC diagnostic push
268#pragma GCC diagnostic ignored "-Wfloat-equal"
269 return (left == right);
270#pragma GCC diagnostic pop
271}
272
273} // namespace Elements
274
275#endif // ELEMENTSKERNEL_ELEMENTSKERNEL_REAL_IMPL_
Macro to silence unused variables warnings from the compiler.
Bits fractionBits() const
static const Bits s_fraction_bitmask
Definition Real.h:183
typename TypeWithSize< sizeof(RawType)>::UInt Bits
Definition Real.h:166
static RawType ReinterpretBits(const Bits &bits)
FloatingPoint(const RawType &x)
static Bits distanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, const Bits &sam2)
static const Bits s_exponent_bitmask
Definition Real.h:186
static Bits signAndMagnitudeToBiased(const Bits &sam)
static RawType Infinity()
bool AlmostEquals(const FloatingPoint &rhs) const
Bits exponentBits() const
const Bits & bits() const
#define ELEMENTS_UNUSED
Definition Unused.h:39
T memcpy(T... args)
ELEMENTS_API bool isLess(const RawType &left, const RawType &right)
ELEMENTS_API bool isNotEqual(const RawType &left, const RawType &right)
ELEMENTS_API bool isGreater(const RawType &left, const RawType &right)
constexpr std::size_t FLT_DEFAULT_MAX_ULPS
Single precision float default maximum unit in the last place.
Definition Real.h:84
ELEMENTS_API bool isNan(const RawType &x)
ELEMENTS_API bool isEqual(const RawType &left, const RawType &right)
ELEMENTS_API bool isLessOrEqual(const RawType &left, const RawType &right)
constexpr std::size_t DBL_DEFAULT_MAX_ULPS
Double precision float default maximum unit in the last place.
Definition Real.h:86
ELEMENTS_API bool realBitWiseEqual(const RawType &left, const RawType &right)
This function compares 2 floating point numbers bitwise. These are the strict equivalent of the "=="....
ELEMENTS_API constexpr std::size_t defaultMaxUlps< double >()
ELEMENTS_API constexpr std::size_t defaultMaxUlps< float >()
ELEMENTS_API bool almostEqual2sComplement(ELEMENTS_UNUSED const FloatType &a, ELEMENTS_UNUSED const FloatType &b, ELEMENTS_UNUSED const std::size_t &max_ulps=0)
ELEMENTS_API bool isGreaterOrEqual(const RawType &left, const RawType &right)
ELEMENTS_API constexpr std::size_t defaultMaxUlps()