// power.hpp // Generic exponentiation function (right-to-left binary method) // // Supports any type with multiplication (integers, floating point, ModularInt, polynomials, matrices, etc.) // // Copyright (C) 2026 Kiyotsugu Arai // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once #include #include #include #include namespace sangi { // For types where the multiplicative identity can be obtained via T(1) // (integers, floating point, ModularInt, polynomials, etc.) template requires requires(T a, const T& b) { a = a * b; } [[nodiscard]] T power(const T& base, unsigned int exponent) { if (exponent == 0) return T(1); if (exponent == 1) return base; // Right-to-left binary method (scan from MSB to LSB) // About 3x faster than left-to-right binary method (sangi measurement) T y(1); unsigned int bit = std::bit_width(exponent) - 1; while (true) { y = y * y; if ((exponent >> bit) & 1u) { y = y * base; } if (bit == 0) break; --bit; } return y; } // Version that takes the multiplicative identity explicitly // For types where T(1) is unavailable (Matrix, etc.) template requires requires(T a, const T& b) { a = a * b; } [[nodiscard]] T power(const T& base, unsigned int exponent, const T& identity) { if (exponent == 0) return identity; if (exponent == 1) return base; T y = identity; unsigned int bit = std::bit_width(exponent) - 1; while (true) { y = y * y; if ((exponent >> bit) & 1u) { y = y * base; } if (bit == 0) break; --bit; } return y; } } // namespace sangi