5#include <Common/assertion.h>
15namespace radical_inverse_detail
20template<std::
integral Value, std::
integral Base>
21inline constexpr Value
reverse_limit(
const Value nextDigit,
const Base base)
23 return (std::numeric_limits<Value>::max() - nextDigit) / base;
30template<std::
floating_po
int Result, std::
integral Base>
33 const Result rcpBase = Result(1) / base;
36 Result valueScaler = 1;
37 while(1 - (base - 1) * valueScaler < 1)
40 valueScaler *= rcpBase;
45template<std::
floating_po
int Result, std::
unsigned_
integral Value>
48 constexpr auto numBits =
sizeof(Value) * CHAR_BIT;
49 if constexpr(numBits == 8)
51 return Result(0x1p-8);
53 else if constexpr(numBits == 16)
55 return Result(0x1p-16);
57 else if constexpr(numBits == 32)
59 return Result(0x1p-32);
61 else if constexpr(numBits == 64)
63 return Result(0x1p-64);
67 PH_STATIC_ASSERT_DEPENDENT_FALSE(Result,
68 "Unexpected size of `Value`.");
78template<auto BASE, std::
floating_po
int Result, std::
integral Value>
81 static_assert(std::integral<
decltype(BASE)>,
82 "`BASE` must be an integer.");
83 static_assert(BASE >= 2);
86 if constexpr(BASE == 2 && std::unsigned_integral<Value>)
94 constexpr Result rcpBase = Result(1) / BASE;
101 Value currentValue = value;
102 Value unscaledReversedValue = 0;
104 while(currentValue > 0 && unscaledReversedValue <= maxSafeValue)
106 const Value quotient = currentValue / BASE;
107 const Value remainder = currentValue - quotient * BASE;
109 unscaledReversedValue = unscaledReversedValue * BASE + remainder;
112 currentValue = quotient;
124template<auto BASE, std::
floating_po
int Result, std::
integral Value,
typename DigitPermuter>
127 static_assert(std::integral<
decltype(BASE)>,
128 "`BASE` must be an integer.");
129 static_assert(BASE >= 2);
130 static_assert(
requires (DigitPermuter p)
132 { p.template operator()<BASE>(Value{}, Value{})} -> std::same_as<Value>;
134 "`DigitPermuter` must be callable with `<BASE>(dimIndex, digit)` and return a permuted digit.");
136 constexpr Result rcpBase = Result(1) / BASE;
146 Value currentValue = value;
147 Value unscaledReversedValue = 0;
148 Value numReversedDigits = 0;
150 while(numReversedDigits < maxDigits && unscaledReversedValue <= maxSafeValue)
152 const Value quotient = currentValue / BASE;
153 const Value remainder = currentValue - quotient * BASE;
154 const Value permutedRemainder = permuter.template operator()<BASE>(dimIndex, remainder);
156 unscaledReversedValue = unscaledReversedValue * BASE + permutedRemainder;
160 currentValue = quotient;
Miscellaneous math utilities.
constexpr Value reverse_limit(const Value nextDigit, const Base base)
The max value x such that x * base + nextDigit will not overflow its type.
Definition radical_inverse.h:21
constexpr auto num_meaningful_digits(const Base base)
Number of reversed digits that will have effect on the type Result. Due to the limited precision of f...
Definition radical_inverse.h:31
constexpr Result base_2_scaler()
Definition radical_inverse.h:46
Math functions and utilities.
Definition TransformInfo.h:10
Result radical_inverse(const Value value)
Compute radical inverse of a value.
Definition radical_inverse.h:79
T reverse_bits(const T value)
Get an integral value with reversed bits.
Definition math.h:448
Result radical_inverse_permuted(const Value dimIndex, const Value value, DigitPermuter permuter)
Same as radical_inverse(), with permutation ability. It is guaranteed that no more than radical_inver...
Definition radical_inverse.h:125
T clamp(const T value, const T lowerBound, const T upperBound)
Clamps a value to [lowerBound, upperBound]. None of value, lowerBound and upperBound can be NaN,...
Definition math.h:77