TDLS 0.2.0
Tiny Device-callable Linear Solvers
Loading...
Searching...
No Matches
structural_real.hpp
Go to the documentation of this file.
1#ifndef TDLS_CORE_STRUCTURAL_REAL_HPP
2#define TDLS_CORE_STRUCTURAL_REAL_HPP
3
4
5
36
37
38
39#include <type_traits>
40
41#include <tdls/core/macros.hpp>
42
43
44
45namespace tdls {
46
47
48
67template<typename T>
69
70 static_assert(std::is_floating_point_v<T>, "tdls::StructuralReal: T must be floating-point");
71
72 long long mantissa = 0;
73 int exponent = 0;
74
76 constexpr StructuralReal() noexcept = default;
77
88 TDLS_HOST_DEVICE constexpr StructuralReal(const long long m, const int e) noexcept
89 : mantissa(m), exponent(e) {
90 }
91
100 TDLS_HOST_DEVICE constexpr StructuralReal(const T v) noexcept {
101 if (v == T(0)) return;
102 // A NaN differs from itself; an infinity is the only non-zero
103 // value unchanged by halving (zero was excluded above). Neither
104 // test produces a NaN, which constant evaluation would reject,
105 // and neither needs a library call, which nvcc would reject in
106 // this host-and-device constructor.
107 if (v != v || v * T(0.5) == v) {
108 // Non-finite sentinel: no finite value yields a zero mantissa
109 // with a non-zero exponent.
110 mantissa = 0;
111 exponent = 1;
112 return;
113 }
114 constexpr T big = T(1LL << 62);
115 T a = v;
116 int e = 0;
117 while (a >= big || a <= -big) {
118 a /= T(2);
119 ++e;
120 }
121 while (T(static_cast<long long>(a)) != a) {
122 // A mantissa wider than 63 bits (long double): the sentinel.
123 if (a >= big || a <= -big) {
124 mantissa = 0;
125 exponent = 1;
126 return;
127 }
128 a *= T(2);
129 --e;
130 }
131 long long m = static_cast<long long>(a);
132 while ((m & 1LL) == 0) {
133 m /= 2;
134 ++e;
135 }
136 mantissa = m;
137 exponent = e;
138 }
139
144 [[nodiscard]] TDLS_HOST_DEVICE constexpr bool is_finite() const noexcept {
145 return !(mantissa == 0 && exponent != 0);
146 }
147
155 [[nodiscard]] TDLS_HOST_DEVICE constexpr operator T() const noexcept {
156 T r = T(mantissa);
157 for (int e = exponent; e > 0; --e)
158 r *= T(2);
159 for (int e = exponent; e < 0; ++e)
160 r /= T(2);
161 return r;
162 }
163};
164
165
166
167} // namespace tdls
168
169
170
171#endif // TDLS_CORE_STRUCTURAL_REAL_HPP
Toolchain detection and portability macros.
#define TDLS_HOST_DEVICE
__host__ __device__ under CUDA, the equivalent attributes under HIP, empty elsewhere.
Definition macros.hpp:45
Floating-point value stored as an odd integer mantissa and a power-of-two exponent,...
Definition structural_real.hpp:68
long long mantissa
odd integer mantissa, 0 for the value zero
Definition structural_real.hpp:72
TDLS_HOST_DEVICE constexpr StructuralReal(const T v) noexcept
Exact decomposition of a finite value into m * 2^e.
Definition structural_real.hpp:100
TDLS_HOST_DEVICE constexpr bool is_finite() const noexcept
Whether the stored value is representable (a NaN, an infinity or a mantissa wider than 63 bits given ...
Definition structural_real.hpp:144
constexpr StructuralReal() noexcept=default
The value zero.
int exponent
power-of-two exponent: value = mantissa * 2^exponent
Definition structural_real.hpp:73