Skip to content

Commit 487663c

Browse files
author
Release Manager
committed
gh-40856: Workaround for linbox charpoly/minpoly issues As in the title. Fix #37068. Can be removed once the upstream issue https://github.com/linbox- team/linbox/issues/53 is fixed. It's possible to do a more expensive check (e.g. check if the matrix satisfy the minpoly with something like Freivalds' algorithm), but I guess this suffice (and it's very cheap). ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [ ] The title is concise and informative. - [ ] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - #12345: short description why this is a dependency --> <!-- - #34567: ... --> URL: #40856 Reported by: user202729 Reviewer(s):
2 parents d25b9f1 + e5ab51a commit 487663c

File tree

2 files changed

+39
-27
lines changed

2 files changed

+39
-27
lines changed

src/sage/matrix/matrix_integer_dense.pyx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,10 +1411,13 @@ cdef class Matrix_integer_dense(Matrix_dense):
14111411
fmpz_mat_charpoly(g._poly, self._matrix)
14121412
sig_off()
14131413
elif algorithm == 'linbox':
1414-
g = (<Polynomial_integer_dense_flint> PolynomialRing(ZZ, names=var).gen())._new()
1415-
sig_on()
1416-
linbox_fmpz_mat_charpoly(g._poly, self._matrix)
1417-
sig_off()
1414+
while True: # linbox is unreliable, see :issue:`37068`
1415+
g = (<Polynomial_integer_dense_flint> PolynomialRing(ZZ, names=var).gen())._new()
1416+
sig_on()
1417+
linbox_fmpz_mat_charpoly(g._poly, self._matrix)
1418+
sig_off()
1419+
if g.lc() == 1:
1420+
break
14181421
elif algorithm == 'generic':
14191422
g = Matrix_dense.charpoly(self, var)
14201423
else:
@@ -1494,10 +1497,13 @@ cdef class Matrix_integer_dense(Matrix_dense):
14941497
return g.change_variable_name(var)
14951498

14961499
if algorithm == 'linbox':
1497-
g = (<Polynomial_integer_dense_flint> PolynomialRing(ZZ, names=var).gen())._new()
1498-
sig_on()
1499-
linbox_fmpz_mat_minpoly(g._poly, self._matrix)
1500-
sig_off()
1500+
while True: # linbox is unreliable, see :issue:`37068`
1501+
g = (<Polynomial_integer_dense_flint> PolynomialRing(ZZ, names=var).gen())._new()
1502+
sig_on()
1503+
linbox_fmpz_mat_minpoly(g._poly, self._matrix)
1504+
sig_off()
1505+
if g.lc() == 1:
1506+
break
15011507
elif algorithm == 'generic':
15021508
g = Matrix_dense.minpoly(self, var)
15031509
else:

src/sage/matrix/matrix_integer_sparse.pyx

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -901,16 +901,19 @@ cdef class Matrix_integer_sparse(Matrix_sparse):
901901
cdef linbox.DensePolynomial_integer * p = new linbox.DensePolynomial_integer(givZZ, <size_t> self._nrows)
902902
cdef Polynomial_integer_dense_flint g = (<Polynomial_integer_dense_flint> R.gen())._new()
903903

904-
sig_on()
905-
linbox.charpoly(p[0], M[0])
906-
sig_off()
904+
while True: # linbox is unreliable, see :issue:`37068`
905+
sig_on()
906+
linbox.charpoly(p[0], M[0])
907+
sig_off()
907908

908-
cdef size_t i
909-
fmpz_poly_fit_length(g._poly, p.size())
910-
for i in range(p.size()):
911-
tmp = p[0][i].get_mpz_const()
912-
fmpz_poly_set_coeff_mpz(g._poly, i, tmp)
913-
_fmpz_poly_set_length(g._poly, p.size())
909+
fmpz_poly_fit_length(g._poly, p.size())
910+
for i in range(p.size()):
911+
tmp = p[0][i].get_mpz_const()
912+
fmpz_poly_set_coeff_mpz(g._poly, i, tmp)
913+
_fmpz_poly_set_length(g._poly, p.size())
914+
915+
if g.lc() == 1:
916+
break
914917

915918
del M
916919
del p
@@ -1000,18 +1003,21 @@ cdef class Matrix_integer_sparse(Matrix_sparse):
10001003
cdef linbox.SparseMatrix_integer * M = new_linbox_matrix_integer_sparse(givZZ, self)
10011004
cdef linbox.DensePolynomial_integer * p = new linbox.DensePolynomial_integer(givZZ, <size_t> self._nrows)
10021005
cdef Polynomial_integer_dense_flint g = (<Polynomial_integer_dense_flint> R.gen())._new()
1006+
cdef mpz_t tmp
10031007

1004-
sig_on()
1005-
linbox.minpoly(p[0], M[0])
1006-
sig_off()
1008+
while True: # linbox is unreliable, see :issue:`37068`
1009+
sig_on()
1010+
linbox.minpoly(p[0], M[0])
1011+
sig_off()
10071012

1008-
cdef size_t i
1009-
cdef mpz_t tmp
1010-
fmpz_poly_fit_length(g._poly, p.size())
1011-
for i in range(p.size()):
1012-
tmp = p[0][i].get_mpz_const()
1013-
fmpz_poly_set_coeff_mpz(g._poly, i, tmp)
1014-
_fmpz_poly_set_length(g._poly, p.size())
1013+
fmpz_poly_fit_length(g._poly, p.size())
1014+
for i in range(p.size()):
1015+
tmp = p[0][i].get_mpz_const()
1016+
fmpz_poly_set_coeff_mpz(g._poly, i, tmp)
1017+
_fmpz_poly_set_length(g._poly, p.size())
1018+
1019+
if g.lc() == 1:
1020+
break
10151021

10161022
del M
10171023
del p

0 commit comments

Comments
 (0)