diff --git a/maths.hpp b/maths.hpp index 8088a3ff..809bdae9 100644 --- a/maths.hpp +++ b/maths.hpp @@ -341,11 +341,29 @@ namespace util { } - //----------------------------------------------------------------------------- - constexpr - unsigned - digits10 (uint32_t v) noexcept + //------------------------------------------------------------------------- + template < + typename NumericT, + typename = std::enable_if_t< + std::is_integral_v, + void + > + > + constexpr auto + digits10 (NumericT v) noexcept { + // cascading conditionals are faster, but it's super annoying to write + // out for arbitrarily sized types so we use this base case unti + // there's actually a performance reason to use another algorithm. + int tally = 0; + do { + v /= 10; + ++tally; + } while (v); + + return tally; + + /* return (v >= 1000000000) ? 10 : (v >= 100000000) ? 9 : (v >= 10000000) ? 8 : @@ -356,6 +374,7 @@ namespace util { (v >= 100) ? 3 : (v >= 10) ? 2 : 1; + */ } diff --git a/test/maths.cpp b/test/maths.cpp index be27388a..f34947fc 100644 --- a/test/maths.cpp +++ b/test/maths.cpp @@ -159,6 +159,10 @@ main (void) tap.expect_eq (util::min (-2, 0, 2), -2, "variadic min"); tap.expect_eq (util::max (-2, 0, 2), 2, "variadic max"); + tap.expect_eq (util::digits10( 0), 1, "digits10, 0"); + tap.expect_eq (util::digits10( 1), 1, "digits10, 1"); + tap.expect_eq (util::digits10(10), 2, "digits10, 10"); + tap.expect_eq (util::pow2 (4u), 16u, "pow2"); static const float POS_ZERO = 1.f / numeric_limits::infinity ();