Skip to content

Fix fmpz_mat_snf hanging on non-square and singular matrices#2596

Merged
fredrik-johansson merged 5 commits intoflintlib:mainfrom
edgarcosta:hnf_before_snf
Mar 9, 2026
Merged

Fix fmpz_mat_snf hanging on non-square and singular matrices#2596
fredrik-johansson merged 5 commits intoflintlib:mainfrom
edgarcosta:hnf_before_snf

Conversation

@edgarcosta
Copy link
Member

For non-square matrices and square matrices with zero determinant, fmpz_mat_snf previously used the Kannan-Bachem algorithm which suffers from intermediate coefficient explosion, causing it to hang on certain inputs (e.g. the 27x25 matrix from issue #2592).

The fix computes HNF first (which is fast), extracts the nonzero rows (to avoid Iliopoulos returning gcd(0, mod) = mod for zero invariant factors), and applies the modular Iliopoulos algorithm using the product of HNF pivot entries as the modulus.

Add comprehensive tests for fmpz_mat_snf including 22 hardcoded cases verified against Magma: the issue #2592 reproducer, tall/wide non-square matrices, square singular matrices, matrices with nontrivial invariant factors, and edge cases (zero, 1x1, single row/column).

Fixes #2592

At some point I might implement SNF via iterative HNF, but I wanted to get this in first

For non-square matrices and square matrices with zero determinant,
fmpz_mat_snf previously used the Kannan-Bachem algorithm which suffers
from intermediate coefficient explosion, causing it to hang on certain
inputs (e.g. the 27x25 matrix from issue flintlib#2592).

The fix computes HNF first (which is fast), extracts the nonzero rows
(to avoid Iliopoulos returning gcd(0, mod) = mod for zero invariant
factors), and applies the modular Iliopoulos algorithm using the product
of HNF pivot entries as the modulus.

Add comprehensive tests for fmpz_mat_snf including 22 hardcoded cases
verified against Magma: the issue flintlib#2592 reproducer, tall/wide non-square
matrices, square singular matrices, matrices with nontrivial invariant
factors, and edge cases (zero, 1x1, single row/column).

Fixes flintlib#2592
- Add fmpz_abs on modulus before calling Iliopoulos as a safeguard
- Remove unused state parameter from _test_snf_case helper
- Clarify comment explaining why HNF pivot product is a valid modulus
The previous cross-check called fmpz_mat_snf (dispatcher) which routed
small matrices to kannan_bachem, so it was comparing KB vs KB. Now call
both implementations directly on small square nonsingular matrices.
- Test aliasing fmpz_mat_snf(A, A) in the main randomized loop
- Verify SNF rank matches fmpz_mat_rank(A) in all randomized loops
- Add explicit edge cases for 0x0, 0xn, mx0 matrices
- Add dedicated loop for square nonsingular matrices above cutoff
  (exercises the det + Iliopoulos dispatcher path)
- Add hardcoded square nonsingular cases with nontrivial invariant
  factors (10x10 and 12x12, verified with Magma)
@fredrik-johansson
Copy link
Collaborator

Fantastic! Thanks!

@fredrik-johansson fredrik-johansson merged commit 383453d into flintlib:main Mar 9, 2026
12 checks passed
@antieau
Copy link

antieau commented Mar 9, 2026

@edgarcosta I have an undergraduate student who already has working code for SNF via iterated HNF and is just working on making it better. I am hoping he will be submitting this to FLINT soon.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fmpz_mat.snf randomly hangs

3 participants