Maybe you could measure also my old code with slightly different
approach (no `constexpr`), at <url:
https://github.com/progrock-libraries/kickstart/blob/master/source/library/kickstart/main_library/core/ns%E2%96%B8language/operations/intpow.hpp>:
#include <assert.h>
#include <type_traits> // is_floating_point_v
// Important to not introduce possible future name conflicts with
<math.h>, hence
// the “lx” (short for “language extension”) ns▸
namespace kickstart::language::lx::_definitions {
using std::is_floating_point_v;
namespace impl
{
// Essentially this is Horner's rule adapted to calculating a
power, so that the
// number of floating point multiplications is at worst O(log₂n).
template< class Number_type >
constexpr inline auto intpow_( const Number_type base, const
int exponent )
-> Number_type
{
Number_type result = 1;
Number_type weight = base;
for( int n = exponent; n != 0; weight *= weight ) {
if( n % 2 != 0 ) {
result *= weight;
}
n /= 2;
}
return result;
}
} // namespace impl
template< class Number_type >
constexpr inline auto intpow( const Number_type base, const int
exponent )
-> Number_type
{
// TODO: proper failure handling
if( exponent < 0 and not is_floating_point_v<Number_type> ) {
assert( "For negative powers the base must be floating
point" and false );
}
return (0?0
: exponent > 0? impl::intpow_<Number_type>( base,
exponent )
: exponent == 0? 1
: Number_type(
1.0/impl::intpow_<Number_type>( base, -exponent ) )
);
}
//-----------------------------------------------------------
@exported:
namespace d = _definitions;
namespace exported_names { using
d::intpow;
} // namespace exported names
} // namespace kickstart::language::lx::_definitions
namespace kickstart::language::lx { using namespace
_definitions::exported_names; }
In the above copy+paste I removed an include of a header that defines a
`bool` replacement type called `Truth`, b/c I can't see that it's used.
The main difference from your code is that I discriminate the different
cases in a public function that just calls the internal implementation
with appropriate adjustments of arguments and result. Also, I use IMO
more clear notation like `/= 2` instead of `>>= 1`. Should yield same
machine code though.
I never measured this so it's interesting how it would stack up to your
code, and MSVC's.
- Alf