Reduce expensive(?) accesses to thread_local MantissaRange

This commit is contained in:
Ed Hennis
2026-01-27 16:31:14 -05:00
parent 3d6f57a4df
commit cca92dedca
2 changed files with 180 additions and 59 deletions

View File

@@ -474,6 +474,9 @@ public:
friend Number
root2(Number f);
friend Number
power(Number const& f, unsigned n, unsigned d);
// Thread local rounding control. Default is to_nearest
enum rounding_mode { to_nearest, towards_zero, downward, upward };
static rounding_mode
@@ -569,6 +572,17 @@ private:
// changing the values inside the range.
static thread_local std::reference_wrapper<MantissaRange const> range_;
// And one is needed because it needs to choose between oneSmall and
// oneLarge based on the current range
static Number
one(MantissaRange const& range);
static Number
root(MantissaRange const& range, Number f, unsigned d);
void
normalize(MantissaRange const& range);
void
normalize();
@@ -596,6 +610,9 @@ private:
MantissaRange::rep const& minMantissa,
MantissaRange::rep const& maxMantissa);
bool
isnormal(MantissaRange const& range) const noexcept;
bool
isnormal() const noexcept;
@@ -612,6 +629,15 @@ private:
static internalrep
externalToInternal(rep mantissa);
/** Breaks down the number into components, potentially de-normalizing it.
*
* Ensures that the mantissa always has range_.log digits.
*
*/
template <detail::UnsignedMantissa Rep = internalrep>
std::tuple<bool, Rep, int>
toInternal(MantissaRange const& range) const;
/** Breaks down the number into components, potentially de-normalizing it.
*
* Ensures that the mantissa always has range_.log digits.
@@ -633,6 +659,26 @@ private:
*/
template <bool expectNormal = true, detail::UnsignedMantissa Rep = internalrep>
void
fromInternal(
bool negative,
Rep mantissa,
int exponent,
MantissaRange const* pRange);
/** Rebuilds the number from components.
*
* If "normalized" is true, the values are expected to be normalized - all
* in their valid ranges.
*
* If "normalized" is false, the values are expected to be "near
* normalized", meaning that the mantissa has to be modified at most once to
* bring it back into range.
*
*/
template <
bool expectNormal = true,
detail::UnsignedMantissa Rep = internalrep>
void
fromInternal(bool negative, Rep mantissa, int exponent);
class Guard;
@@ -800,9 +846,8 @@ Number::lowest() noexcept
}
inline bool
Number::isnormal() const noexcept
Number::isnormal(MantissaRange const& range) const noexcept
{
MantissaRange const& range = range_;
auto const abs_m = mantissa_ < 0 ? -mantissa_ : mantissa_;
return *this == Number{} ||
@@ -810,6 +855,12 @@ Number::isnormal() const noexcept
minExponent <= exponent_ && exponent_ <= maxExponent);
}
inline bool
Number::isnormal() const noexcept
{
return isnormal(range_);
}
template <Integral64 T>
std::pair<T, int>
Number::normalizeToRange(T minMantissa, T maxMantissa) const