diff --git a/src/lib/rational.hpp b/src/lib/rational.hpp index 909c76539..0c94b7d3b 100644 --- a/src/lib/rational.hpp +++ b/src/lib/rational.hpp @@ -68,13 +68,13 @@ #define LIB_RATIONAL_H +#include "lib/util-quant.hpp" + #include #include #include #include -#include "lib/util-quant.hpp" - namespace util { @@ -87,51 +87,6 @@ namespace util { using uint = unsigned int; - /** - * Integral binary logarithm (disregarding fractional part) - * @return index of the largest bit set in `num`; -1 for `num==0` - * @todo C++20 will provide `std::bit_width(i)` — run a microbenchmark! - * @remark The implementation uses an unrolled loop to break down the given number - * in a logarithmic search, subtracting away the larger powers of 2 first. - * Explained 10/2021 by user «[ToddLehman]» in this [stackoverflow]. - * @note Microbenchmarks indicate that this function and `std::ilogb(double)` perform - * in the same order of magnitude (which is surprising). This function gets - * slightly faster for smaller data types. The naive bitshift-count implementation - * is always significantly slower (8 times for int64_t, 1.6 times for int8_t) - * @see Rational_test::verify_intLog2() - * @see ZoomWindow_test - * - * [ToddLehman]: https://stackoverflow.com/users/267551/todd-lehman - * [stackoverflow]: https://stackoverflow.com/a/24748637 "How to do an integer log2()" - */ - template - inline int - ilog2 (I num) - { - if (num <= 0) - return -1; - const I MAX_POW = sizeof(I)*CHAR_BIT - 1; - int logB{0}; - auto remove_power = [&](I pow) - { - if (pow > MAX_POW) return; - if (num >= I{1} << pow) - { - logB += pow; - num >>= pow; - } - }; - remove_power(32); - remove_power(16); - remove_power (8); - remove_power (4); - remove_power (2); - remove_power (1); - - return logB; - } - - inline bool can_represent_Product (int64_t a, int64_t b) { diff --git a/src/lib/util-quant.hpp b/src/lib/util-quant.hpp index 1f5d94cd0..7da68ffd7 100644 --- a/src/lib/util-quant.hpp +++ b/src/lib/util-quant.hpp @@ -30,6 +30,7 @@ #define LIB_UTIL_QUANT_H #include +#include #include #include @@ -155,5 +156,51 @@ namespace util { } + + /** + * Integral binary logarithm (disregarding fractional part) + * @return index of the largest bit set in `num`; -1 for `num==0` + * @todo C++20 will provide `std::bit_width(i)` — run a microbenchmark! + * @remark The implementation uses an unrolled loop to break down the given number + * in a logarithmic search, subtracting away the larger powers of 2 first. + * Explained 10/2021 by user «[ToddLehman]» in this [stackoverflow]. + * @note Microbenchmarks indicate that this function and `std::ilogb(double)` perform + * in the same order of magnitude (which is surprising). This function gets + * slightly faster for smaller data types. The naive bitshift-count implementation + * is always significantly slower (8 times for int64_t, 1.6 times for int8_t) + * @see Rational_test::verify_intLog2() + * @see ZoomWindow_test + * + * [ToddLehman]: https://stackoverflow.com/users/267551/todd-lehman + * [stackoverflow]: https://stackoverflow.com/a/24748637 "How to do an integer log2()" + */ + template + inline constexpr int + ilog2 (I num) + { + if (num <= 0) + return -1; + const I MAX_POW = sizeof(I)*CHAR_BIT - 1; + int logB{0}; + auto remove_power = [&](I pow) constexpr + { + if (pow > MAX_POW) return; + if (num >= I{1} << pow) + { + logB += pow; + num >>= pow; + } + }; + remove_power(32); + remove_power(16); + remove_power (8); + remove_power (4); + remove_power (2); + remove_power (1); + + return logB; + } + + } // namespace util #endif /*UTIL_QUANT_H*/