numerics 0.1.0
Loading...
Searching...
No Matches
integer_pow.hpp
Go to the documentation of this file.
1/// @file integer_pow.hpp
2/// @brief Compile-time integer exponentiation via repeated squaring
3///
4/// @par Algorithm (CS theory: exponentiation by squaring)
5///
6/// Naive loop: x^N needs N-1 multiplications.
7/// Squaring: x^N needs ceil(log2(N)) squarings + popcount(N)-1
8/// multiplications
9/// = O(log N) total -- for N=7: 4 mults vs 6 naive.
10///
11/// The recursion:
12/// ipow<0>(x) = 1
13/// ipow<1>(x) = x
14/// ipow<N>(x) = ipow<N/2>(x)^2 if N even
15/// ipow<N>(x) = x * ipow<N-1>(x) if N odd
16///
17/// The compiler evaluates the N/2 branch once (stores in a temp) and
18/// squares it, so ipow<6> compiles to exactly 3 multiplications:
19/// t = x*x (x^2)
20/// t2 = t*x (x^3)
21/// return t2*t2 (x^6)
22/// and ipow<7> adds one more:
23/// return x * ipow<6>(x) (x^7 in 4 mults total)
24///
25/// @par Primary use: Tait EOS with gamma=7
26/// float r_pow = num::ipow<7>(ratio); // 4 mults, zero branching
27#pragma once
28
29namespace num {
30
31/// @brief Compute x^N at compile time via repeated squaring.
32/// @tparam N Non-negative integer exponent (must be a compile-time constant).
33/// @tparam T Arithmetic type (float, double, int, ...).
34template <int N, typename T> constexpr T ipow(T x) noexcept {
35 static_assert(N >= 0, "ipow: exponent must be non-negative");
36 if constexpr (N == 0)
37 return T(1);
38 if constexpr (N == 1)
39 return x;
40 if constexpr (N % 2 == 0) {
41 const T half = ipow<N / 2>(x);
42 return half * half;
43 } else {
44 return x * ipow<N - 1>(x);
45 }
46}
47
48} // namespace num
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.