// power.hpp // 汎用冪乗関数(右向きバイナリ法) // // 移植元: lib++20 基本関数.h Pow() // 任意の乗法を持つ型(整数, 浮動小数点, ModularInt, 多項式, 行列, etc.)に対応 // // Copyright (C) 2026 Kiyotsugu Arai (新井清嗣) // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once #include #include #include #include namespace calx { // T(1) で乗法単位元を取得できる型向け // 整数, 浮動小数点, ModularInt, 多項式 等 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; // 右向きバイナリ法(MSB から LSB へ走査) // 左向きバイナリ法より約3倍高速(lib++20 実測値) 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; } // 乗法単位元を明示指定するバージョン // T(1) が使えない型(Matrix 等)向け 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 calx