mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-05 13:14:29 +02:00
better sqrt_impl
MUCH bigger range (although still not quitre max -- see comments) no recursion make this example possible: https://godbolt.org/z/tDFkfR
This commit is contained in:
committed by
Mateusz Pusz
parent
d4492524d1
commit
fe998e1eab
@@ -205,18 +205,27 @@ using ratio_pow = detail::ratio_pow_impl<R, N>::type;
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
constexpr std::intmax_t sqrt_impl(std::intmax_t v, std::intmax_t l, std::intmax_t r)
|
// sqrt_impl avoids overflow and recursion
|
||||||
|
// from http://www.codecodex.com/wiki/Calculate_an_integer_square_root#C.2B.2B
|
||||||
|
// if v >= place this will fail (so we can't quite use the last bit)
|
||||||
|
static constexpr std::intmax_t sqrt_impl(std::intmax_t v)
|
||||||
{
|
{
|
||||||
if (l == r) return r;
|
// place = 0x4000 0000 for 32bit
|
||||||
|
// place = 0x4000 0000 0000 0000 for 64bit
|
||||||
|
std::intmax_t place = static_cast<std::intmax_t>(1) << (sizeof(std::intmax_t) * 8 - 2);
|
||||||
|
while (place > v) place /= 4; // optimized by complier as place >>= 2
|
||||||
|
|
||||||
const auto mid = (r + l) / 2;
|
std::intmax_t root = 0;
|
||||||
if (mid * mid >= v)
|
while (place) {
|
||||||
return sqrt_impl(v, l, mid);
|
if (v >= root + place) {
|
||||||
else
|
v -= root + place;
|
||||||
return sqrt_impl(v, mid + 1, r);
|
root += place * 2;
|
||||||
|
}
|
||||||
|
root /= 2;
|
||||||
|
place /= 4;
|
||||||
|
}
|
||||||
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr std::intmax_t sqrt_impl(std::intmax_t v) { return sqrt_impl(v, 1, v); }
|
|
||||||
|
|
||||||
template<Ratio R>
|
template<Ratio R>
|
||||||
constexpr auto make_exp_even()
|
constexpr auto make_exp_even()
|
||||||
|
Reference in New Issue
Block a user