|
TDLS 0.2.0
Tiny Device-callable Linear Solvers
|
Floating-point value stored as an odd integer mantissa and a power-of-two exponent, admissible as a template argument on every compiler supporting class-type non-type template parameters. More...
#include <structural_real.hpp>
Public Member Functions | |
| constexpr | StructuralReal () noexcept=default |
| The value zero. | |
| TDLS_HOST_DEVICE constexpr | StructuralReal (const long long m, const int e) noexcept |
| Member-wise form, m * 2^e taken as is (no normalization). | |
| TDLS_HOST_DEVICE constexpr | StructuralReal (const T v) noexcept |
| Exact decomposition of a finite value into m * 2^e. | |
| 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 to the constructor is stored as a sentinel instead). | |
| TDLS_HOST_DEVICE constexpr | operator T () const noexcept |
| The stored value, reconstructed exactly. | |
Public Attributes | |
| long long | mantissa = 0 |
| odd integer mantissa, 0 for the value zero | |
| int | exponent = 0 |
| power-of-two exponent: value = mantissa * 2^exponent | |
Floating-point value stored as an odd integer mantissa and a power-of-two exponent, admissible as a template argument on every compiler supporting class-type non-type template parameters.
Built implicitly from a value of the scalar type and converted back implicitly, so a designated initializer such as .oot_threshold = 1e-10 needs no wrapper. Only finite values whose odd mantissa fits 63 bits are representable: every float and double, and the long double values built from double literals. A NaN, an infinity or a wider long double mantissa is stored as a sentinel that is_finite() reports, and the solvers reject at compile time.
The member-wise constructor exists for the CUDA toolchain: when nvcc re-emits a translation unit for the host compiler, it spells every class-type template argument as a brace list of its members, nested classes included, so {mantissa, exponent} must be an accepted initialization of this type.
| T | scalar type (float, double or long double) |
|
inlineconstexprnoexcept |
Member-wise form, m * 2^e taken as is (no normalization).
Required by the host-side re-emission of nvcc (see the class documentation); also the natural way to write an exact power of two. Two configurations only name the same solver instantiation when their members are equal, so a non-canonical mantissa (even, or with a different exponent) names a distinct instantiation of the same numerical value.
| [in] | m | integer mantissa |
| [in] | e | power-of-two exponent |
|
inlineconstexprnoexcept |
Exact decomposition of a finite value into m * 2^e.
The magnitude is first halved below 2^62 (exact on a normal number), then doubled until integral (exact, and stopped by the sentinel below 2^63), and the integer mantissa is finally reduced to its odd part. Signed zeros both map to (0, 0): thresholds are magnitudes, the sign of zero carries nothing.
| [in] | v | the value to store |
|
inlinenodiscardconstexprnoexcept |
Whether the stored value is representable (a NaN, an infinity or a mantissa wider than 63 bits given to the constructor is stored as a sentinel instead).
|
inlinenodiscardconstexprnoexcept |
The stored value, reconstructed exactly.
Scaling by a power of two one step at a time is exact at every step: intermediate values carry at least as much precision as the representable end value. The non-finite sentinel converts to zero; the solvers reject it before any conversion.