Skip to content

Speed up powering a matrix by a large exponent when its minimal polynomial is small - #6495

Open
fingolfin wants to merge 1 commit into
masterfrom
mh/POW_MAT_INT_minpol
Open

Speed up powering a matrix by a large exponent when its minimal polynomial is small#6495
fingolfin wants to merge 1 commit into
masterfrom
mh/POW_MAT_INT_minpol

Conversation

@fingolfin

Copy link
Copy Markdown
Member

Powering a matrix by a large exponent reduces x^n modulo the characteristic polynomial. Doing it modulo the minimal polynomial instead, when that has degree e rather than d, is worth a factor of 2 to 60.

The minimal polynomial of a dense matrix costs about as much as the whole method, so a single spun random vector probes for it first, abandoned once its order polynomial passes the break even point. Depending on e, the reduced polynomial is then evaluated at the matrix itself or at its block companion form.

Break even points measured over dimensions 60 to 2000, GF(2), GF(5), GF(251), GF(257), GF(3^10), minimal polynomial degrees d/30 to d, and exponents 2^20 to 2^1000: 6*e <= d for compressed matrices, 2*e <= d otherwise, where matrix multiplication is far more expensive than polynomial arithmetic. The choice is within a factor of 1.07 of the best of the three methods on every measured cell, and at least 1.5 times faster than before on a third of them.

This also fixes m^n for matrix objects without access to their rows, such as those in IsGenericMatrixRep, which failed with row access unsupported.

AI disclosure: benchmarking, analysis and drafting were done with the AI tool Claude Code; the commit carries a corresponding Co-authored-by: line.

…omial is small

Powering a matrix by a large exponent reduces x^n modulo the
characteristic polynomial, after a base change making the matrix block
companion. If the minimal polynomial has degree e rather than d, both the
Log2(n) polynomial multiplications and the final evaluation work with
degree e, which is worth a factor of 2 to 60.

Computing the minimal polynomial of a dense matrix costs about as much as
the whole characteristic polynomial method, so probe first with a single
spun random vector, abandoned once its order polynomial grows past the
bound where the minimal polynomial stops being worth using. That order
polynomial divides the minimal polynomial, so abandoning settles the
question, and the probe does not show up in the timings.

The break even points were determined over a grid of dimensions from 60
to 2000, representations GF(2), GF(5), GF(251), GF(257) and GF(3^10),
minimal polynomial degrees from d/30 up to d, and exponents from 2^20 to
2^1000. They depend mostly on the representation: 6*e <= d for compressed
matrices, 2*e <= d for the rest, where matrix multiplication is far more
expensive than polynomial arithmetic. The choice is within a factor of
1.07 of the best of the three methods everywhere measured, and at least
1.5 times faster than before on a third of the cells.

Matrix objects without access to their rows, such as those in
IsGenericMatrixRep, now work here at all: the helper evaluating a
polynomial at a matrix tested mutability by looking at the first row.
With the preceding commit they reach the generic methods for the
characteristic and minimal polynomial again, so powering them uses the
polynomial method rather than failing with "row access unsupported".

For this, Matrix_OrderPolynomialInner gained an optional degree bound,
and the helpers of POW_MAT_INT moved out of its body to be shared.

This commit was prepared with assistance from the AI tool Claude Code
(benchmarking, analysis and drafting of the implementation and tests).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@fingolfin fingolfin added release notes: use title For PRs: the title of this PR is suitable for direct use in the release notes kind: enhancement Label for issues suggesting enhancements; and for pull requests implementing enhancements topic: library topic: performance bugs or enhancements related to performance (improvements or regressions) labels Aug 7, 2026
@fingolfin
fingolfin requested a review from frankluebeck August 7, 2026 23:50
@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.52941% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.07%. Comparing base (eeef4dc) to head (40b96b5).

Files with missing lines Patch % Lines
lib/matrix.gi 98.52% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6495      +/-   ##
==========================================
+ Coverage   79.03%   79.07%   +0.03%     
==========================================
  Files         685      685              
  Lines      293804   293856      +52     
  Branches     8664     8641      -23     
==========================================
+ Hits       232214   232368     +154     
+ Misses      59788    59686     -102     
  Partials     1802     1802              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind: enhancement Label for issues suggesting enhancements; and for pull requests implementing enhancements release notes: use title For PRs: the title of this PR is suitable for direct use in the release notes topic: library topic: performance bugs or enhancements related to performance (improvements or regressions)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant