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