std::frexp is a function that removes exponent from a floating point variable and puts it into a variable exp of type int. It uses int regardless of how many bits the exponent really needs and according to the linked page:
If the value to be stored in
*expis outside the range ofint, the behavior is unspecified.
So, how do I check whether "*exp is outside the range of int"?
I am thinking about adding a static_assert to my code that compares FLT_MIN_EXP & FLT_MAX_EXP to INT_MIN & INT_MAX.
However, I'm afraid of making an off-by-one error because I don't fully comprehend descriptions of these constants.
FLT_MIN_EXP:
minimum negative integer such that FLT_RADIX raised by power one less than that integer is a normalized
float...
FLT_MAX_EXP:
maximum positive integer such that FLT_RADIX raised by power one less than that integer is a representable finite
float...
(I already have static_assert(FLT_RADIX == 2); in the code so radix equal to 10 is not a concern in my case.)
Assertion 1: This operation usually works fine, and you don't need to worry about anything.
Assertion 2: For peace of mind, if there's every a system where this doesn't work, we want to know about it. We'll revisit a solution when we find one of those systems.
Assertion 3: The largest and smallest exponents returned from
std::frexpcan be represented by the system'sinttype if the operation is reversible.You reverse
std::frexpby its complementstd::ldexp.Note that if
intcannot hold a floating point's exponent, the result is not undefined (it's merely unspecified), so we can rely on the test being well formed.Write a unit test that tests if this is reversible
Can you do better with compile time checks?
Probably, but I'm having trouble understanding the same part of the language you were having trouble with, so I'm optimizing developer speed over compile time checks.
As a first order approximation, may I suggest:
And of course, revisit when you hit a platform where this isn't true.