T fast_power_0(T a, I n, Op op) { assert(!is_negative(n)); T result = identity_element(op); while (!is_zero(n)) { if (is_odd(n)) result = op(result, a); a = op(a, a); halve_non_negative(n); } return result; }
TR fast_power_0(TR tr, IN in, OP op) { assert(!is_negative(in)); TR result = identity_element(op); while (!is_zero(in)) { if (is_odd(in)) result = op(result, tr); tr = op(tr, tr); halve_non_negative(in); } return result; }
friend matrix operator*(const matrix& x, const matrix& y) { matrix result; Multiply mult = Multiply{}; Plus plus = Plus{}; for (std::size_t i = 0; i < N; ++i) { for (std::size_t j = 0; j < N; ++j) { result.data[i][j] = identity_element(plus); for (std::size_t k = 0; k < N; ++k) { result.data[i][j] = plus(result.data[i][j], mult(x.data[i][k], y.data[k][j])); } } } return result; }
T power(T x, N n, O op) { if (n == 0) { return identity_element(op); } while ((n & 1) == 0) { n >>= 1; x = op(x, x); } T result = x; n >>= 1; while (n != 0) { x = op(x, x); if ((n & 1) != 0) { result = op(result, x); } n >>= 1; } return result; }