I'm writing a compile-time math library using c++20, I already have floor/ceiling/abs/etc. but the method I am currently using to get the floor of a float is n >= 0.0f ? (float)(long long)n : (float)(long long)n - 1.0f;
which is a pretty typical fast floor function. however for floats larger than long long max value this returns junk because I cast to a long long. I know using floorf works for large floats but it isn't constexpr (until c++23 which is still in preview). However I can't just copy what the stl is doing because it calls an intrinsic which itself isn't constexpr. Any information that could point me in the right direction would be much appreciated.
As stated by @chtz and @IgorTandetnik floats large enough to be larger than long long max value can't store a fractional part so just return the input.
For floats:
if(abs(n) > (float)(1 << 23))
{
return n;
}
else
{
return n >= 0.0f ? (float)(long long)n : (float)(long long)n - 1.0f;
}
For doubles:
if(abs(n) > (double)(1i64 << 52))
{
return n;
}
else
{
return n >= 0.0 ? (double)(long long)n : (double)(long long)n - 1.0;
}
Edit: Here is a templated version with concepts:
#include <type_traits>
template <std::floating_point Type>
static constexpr Type FloorF(const Type& n) noexcept
{
static constexpr Type MaxPrecision = 1i64 << (std::numeric_limits<Type>::digits - 1);
return n > MaxPrecision ? n :
n >= (Type)0 ? (Type)(long long)n : (Type)(long long)n - (Type)1;
}