Skip to content

Commit 79e7056

Browse files
author
Matthias Koeppe
committed
sage.matrix.misc: Split by library dependency
1 parent 443b754 commit 79e7056

File tree

7 files changed

+205
-183
lines changed

7 files changed

+205
-183
lines changed

src/sage/matrix/matrix2.pyx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14883,21 +14883,21 @@ cdef class Matrix(Matrix1):
1488314883
12215
1488414884
"""
1488514885
from sage.rings.real_double import RDF
14886-
from sage.rings.real_mpfr import RealField
1488714886
try:
1488814887
A = self.change_ring(RDF)
1488914888
m1 = A._hadamard_row_bound()
1489014889
A = A.transpose()
1489114890
m2 = A._hadamard_row_bound()
1489214891
return min(m1, m2)
1489314892
except (OverflowError, TypeError):
14893+
from sage.rings.real_mpfr import RealField
1489414894
# Try using MPFR, which handles large numbers much better, but is slower.
14895-
from . import misc
14895+
from .misc_mpfr import hadamard_row_bound_mpfr
1489614896
R = RealField(53, rnd='RNDU')
1489714897
A = self.change_ring(R)
14898-
m1 = misc.hadamard_row_bound_mpfr(A)
14898+
m1 = hadamard_row_bound_mpfr(A)
1489914899
A = A.transpose()
14900-
m2 = misc.hadamard_row_bound_mpfr(A)
14900+
m2 = hadamard_row_bound_mpfr(A)
1490114901
return min(m1, m2)
1490214902

1490314903
def find(self,f, indices=False):

src/sage/matrix/matrix_cyclo_dense.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ from .matrix cimport Matrix
6363
from . import matrix_dense
6464
from .matrix_integer_dense cimport _lift_crt
6565
from sage.structure.element cimport Matrix as baseMatrix
66-
from .misc import matrix_integer_dense_rational_reconstruction
66+
from .misc_flint import matrix_integer_dense_rational_reconstruction
6767

6868
from sage.arith.misc import binomial, previous_prime
6969
from sage.rings.rational_field import QQ

src/sage/matrix/matrix_integer_dense.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3410,7 +3410,7 @@ cdef class Matrix_integer_dense(Matrix_dense):
34103410
...
34113411
ZeroDivisionError: The modulus cannot be zero
34123412
"""
3413-
from .misc import matrix_integer_dense_rational_reconstruction
3413+
from .misc_flint import matrix_integer_dense_rational_reconstruction
34143414
return matrix_integer_dense_rational_reconstruction(self, N)
34153415

34163416
def randomize(self, density=1, x=None, y=None, distribution=None,

src/sage/matrix/matrix_integer_sparse.pyx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -399,13 +399,15 @@ cdef class Matrix_integer_sparse(Matrix_sparse):
399399

400400
def rational_reconstruction(self, N):
401401
"""
402-
Use rational reconstruction to lift self to a matrix over the
403-
rational numbers (if possible), where we view self as a matrix
404-
modulo N.
402+
Use rational reconstruction to lift ``self`` to a matrix over the
403+
rational numbers (if possible), where we view ``self`` as a matrix
404+
modulo `N`.
405405
406406
EXAMPLES::
407407
408-
sage: A = matrix(ZZ, 3, 4, [(1/3)%500, 2, 3, (-4)%500, 7, 2, 2, 3, 4, 3, 4, (5/7)%500], sparse=True)
408+
sage: A = matrix(ZZ, 3, 4, [(1/3)%500, 2, 3, (-4)%500,
409+
....: 7, 2, 2, 3,
410+
....: 4, 3, 4, (5/7)%500], sparse=True)
409411
sage: A.rational_reconstruction(500)
410412
[1/3 2 3 -4]
411413
[ 7 2 2 3]
@@ -415,7 +417,7 @@ cdef class Matrix_integer_sparse(Matrix_sparse):
415417
416418
Check that :trac:`9345` is fixed::
417419
418-
sage: A = random_matrix(ZZ, 3, 3, sparse = True)
420+
sage: A = random_matrix(ZZ, 3, 3, sparse=True)
419421
sage: A.rational_reconstruction(0)
420422
Traceback (most recent call last):
421423
...

src/sage/matrix/misc.pyx

Lines changed: 7 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,33 @@
11
"""
22
Misc matrix algorithms
3-
4-
Code goes here mainly when it needs access to the internal structure
5-
of several classes, and we want to avoid circular cimports.
6-
7-
NOTE: The whole problem of avoiding circular imports -- the reason for
8-
existence of this file -- is now a non-issue, since some bugs in
9-
Cython were fixed. Probably all this code should be moved into the
10-
relevant classes and this file deleted.
113
"""
124

135
from cysignals.signals cimport sig_check
146

15-
cimport sage.rings.abc
16-
177
from sage.arith.misc import CRT_basis, previous_prime
188
from sage.arith.rational_reconstruction cimport mpq_rational_reconstruction
199
from sage.data_structures.binary_search cimport *
2010
from sage.ext.mod_int cimport *
21-
from sage.libs.flint.fmpq cimport fmpq_set_mpq, fmpq_canonicalise
22-
from sage.libs.flint.fmpq_mat cimport fmpq_mat_entry_num, fmpq_mat_entry_den, fmpq_mat_entry
23-
from sage.libs.flint.fmpz cimport fmpz_set_mpz, fmpz_one
2411
from sage.libs.gmp.mpq cimport *
2512
from sage.libs.gmp.mpz cimport *
26-
from sage.libs.mpfr cimport *
13+
from sage.misc.lazy_import import LazyImport
2714
from sage.misc.verbose import verbose
2815
from sage.modules.vector_integer_sparse cimport *
2916
from sage.modules.vector_modn_sparse cimport *
3017
from sage.modules.vector_rational_sparse cimport *
3118
from sage.rings.integer cimport Integer
3219
from sage.rings.rational_field import QQ
33-
from sage.rings.real_mpfr cimport RealNumber
3420

3521
from .matrix0 cimport Matrix
36-
from .matrix_integer_dense cimport Matrix_integer_dense
3722
from .matrix_integer_sparse cimport Matrix_integer_sparse
38-
from .matrix_rational_dense cimport Matrix_rational_dense
3923
from .matrix_rational_sparse cimport Matrix_rational_sparse
4024

41-
42-
def matrix_integer_dense_rational_reconstruction(Matrix_integer_dense A, Integer N):
43-
"""
44-
Given a matrix over the integers and an integer modulus, do
45-
rational reconstruction on all entries of the matrix, viewed as
46-
numbers mod N. This is done efficiently by assuming there is a
47-
large common factor dividing the denominators.
48-
49-
INPUT:
50-
51-
A -- matrix
52-
N -- an integer
53-
54-
EXAMPLES::
55-
56-
sage: B = ((matrix(ZZ, 3,4, [1,2,3,-4,7,2,18,3,4,3,4,5])/3)%500).change_ring(ZZ)
57-
sage: sage.matrix.misc.matrix_integer_dense_rational_reconstruction(B, 500)
58-
[ 1/3 2/3 1 -4/3]
59-
[ 7/3 2/3 6 1]
60-
[ 4/3 1 4/3 5/3]
61-
62-
TESTS:
63-
64-
Check that :trac:`9345` is fixed::
65-
66-
sage: A = random_matrix(ZZ, 3)
67-
sage: sage.matrix.misc.matrix_integer_dense_rational_reconstruction(A, 0)
68-
Traceback (most recent call last):
69-
...
70-
ZeroDivisionError: The modulus cannot be zero
71-
"""
72-
if not N:
73-
raise ZeroDivisionError("The modulus cannot be zero")
74-
cdef Matrix_rational_dense R
75-
R = Matrix_rational_dense.__new__(Matrix_rational_dense,
76-
A.parent().change_ring(QQ), 0,0,0)
77-
78-
cdef mpz_t a, bnd, other_bnd, denom, tmp
79-
cdef mpq_t qtmp
80-
cdef Integer _bnd
81-
cdef Py_ssize_t i, j
82-
cdef int do_it
83-
84-
mpz_init_set_si(denom, 1)
85-
mpz_init(a)
86-
mpz_init(tmp)
87-
mpz_init(other_bnd)
88-
mpq_init(qtmp)
89-
90-
_bnd = (N//2).isqrt()
91-
mpz_init_set(bnd, _bnd.value)
92-
mpz_sub(other_bnd, N.value, bnd)
93-
94-
for i in range(A._nrows):
95-
for j in range(A._ncols):
96-
sig_check()
97-
A.get_unsafe_mpz(i, j, a)
98-
if mpz_cmp_ui(denom, 1) != 0:
99-
mpz_mul(a, a, denom)
100-
mpz_fdiv_r(a, a, N.value)
101-
do_it = 0
102-
if mpz_cmp(a, bnd) <= 0:
103-
do_it = 1
104-
elif mpz_cmp(a, other_bnd) >= 0:
105-
mpz_sub(a, a, N.value)
106-
do_it = 1
107-
if do_it:
108-
fmpz_set_mpz(fmpq_mat_entry_num(R._matrix, i, j), a)
109-
if mpz_cmp_ui(denom, 1) != 0:
110-
fmpz_set_mpz(fmpq_mat_entry_den(R._matrix, i, j), denom)
111-
fmpq_canonicalise(fmpq_mat_entry(R._matrix, i, j))
112-
else:
113-
fmpz_one(fmpq_mat_entry_den(R._matrix, i, j))
114-
else:
115-
# Otherwise have to do it the hard way
116-
A.get_unsafe_mpz(i, j, tmp)
117-
mpq_rational_reconstruction(qtmp, tmp, N.value)
118-
mpz_lcm(denom, denom, mpq_denref(qtmp))
119-
fmpq_set_mpq(fmpq_mat_entry(R._matrix, i, j), qtmp)
120-
121-
mpz_clear(denom)
122-
mpz_clear(a)
123-
mpz_clear(tmp)
124-
mpz_clear(other_bnd)
125-
mpz_clear(bnd)
126-
mpq_clear(qtmp)
127-
128-
return R
25+
matrix_integer_dense_rational_reconstruction = \
26+
LazyImport('sage.matrix.misc_flint', 'matrix_integer_dense_rational_reconstruction',
27+
deprecation=99999)
28+
hadamard_row_bound_mpfr = \
29+
LazyImport('sage.matrix.misc_mpfr', 'hadamard_row_bound_mpfr',
30+
deprecation=99999)
12931

13032

13133
def matrix_integer_sparse_rational_reconstruction(Matrix_integer_sparse A, Integer N):
@@ -464,70 +366,3 @@ def cmp_pivots(x, y):
464366
return 0
465367
else:
466368
return -1
467-
468-
469-
def hadamard_row_bound_mpfr(Matrix A):
470-
"""
471-
Given a matrix A with entries that coerce to RR, compute the row
472-
Hadamard bound on the determinant.
473-
474-
INPUT:
475-
476-
A -- a matrix over RR
477-
478-
OUTPUT:
479-
480-
integer -- an integer n such that the absolute value of the
481-
determinant of this matrix is at most $10^n$.
482-
483-
EXAMPLES:
484-
485-
We create a very large matrix, compute the row Hadamard bound,
486-
and also compute the row Hadamard bound of the transpose, which
487-
happens to be sharp. ::
488-
489-
sage: a = matrix(ZZ, 2, [2^10000,3^10000,2^50,3^19292])
490-
sage: import sage.matrix.misc
491-
sage: sage.matrix.misc.hadamard_row_bound_mpfr(a.change_ring(RR))
492-
13976
493-
sage: len(str(a.det()))
494-
12215
495-
sage: sage.matrix.misc.hadamard_row_bound_mpfr(a.transpose().change_ring(RR))
496-
12215
497-
498-
Note that in the above example using RDF would overflow::
499-
500-
sage: b = a.change_ring(RDF)
501-
sage: b._hadamard_row_bound()
502-
Traceback (most recent call last):
503-
...
504-
OverflowError: cannot convert float infinity to integer
505-
"""
506-
if not isinstance(A.base_ring(), sage.rings.abc.RealField):
507-
raise TypeError("A must have base field an mpfr real field.")
508-
509-
cdef RealNumber a, b
510-
cdef mpfr_t s, d, pr
511-
cdef Py_ssize_t i, j
512-
513-
mpfr_init(s)
514-
mpfr_init(d)
515-
mpfr_init(pr)
516-
mpfr_set_si(d, 0, MPFR_RNDU)
517-
518-
for i in range(A._nrows):
519-
mpfr_set_si(s, 0, MPFR_RNDU)
520-
for j in range(A._ncols):
521-
sig_check()
522-
a = A.get_unsafe(i, j)
523-
mpfr_mul(pr, a.value, a.value, MPFR_RNDU)
524-
mpfr_add(s, s, pr, MPFR_RNDU)
525-
mpfr_log10(s, s, MPFR_RNDU)
526-
mpfr_add(d, d, s, MPFR_RNDU)
527-
b = a._new()
528-
mpfr_set(b.value, d, MPFR_RNDU)
529-
b /= 2
530-
mpfr_clear(s)
531-
mpfr_clear(d)
532-
mpfr_clear(pr)
533-
return b.ceil()

src/sage/matrix/misc_flint.pyx

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
r"""
2+
Misc matrix algorithms using FLINT
3+
"""
4+
5+
from cysignals.signals cimport sig_check
6+
7+
from sage.arith.rational_reconstruction cimport mpq_rational_reconstruction
8+
from sage.libs.gmp.mpq cimport *
9+
from sage.libs.gmp.mpz cimport *
10+
from sage.libs.flint.fmpq cimport fmpq_set_mpq, fmpq_canonicalise
11+
from sage.libs.flint.fmpq_mat cimport fmpq_mat_entry_num, fmpq_mat_entry_den, fmpq_mat_entry
12+
from sage.libs.flint.fmpz cimport fmpz_set_mpz, fmpz_one
13+
from sage.rings.integer cimport Integer
14+
from sage.rings.rational_field import QQ
15+
16+
from .matrix_integer_dense cimport Matrix_integer_dense
17+
from .matrix_rational_dense cimport Matrix_rational_dense
18+
19+
20+
def matrix_integer_dense_rational_reconstruction(Matrix_integer_dense A, Integer N):
21+
"""
22+
Given a matrix over the integers and an integer modulus, do
23+
rational reconstruction on all entries of the matrix, viewed as
24+
numbers mod N. This is done efficiently by assuming there is a
25+
large common factor dividing the denominators.
26+
27+
INPUT:
28+
29+
A -- matrix
30+
N -- an integer
31+
32+
EXAMPLES::
33+
34+
sage: B = ((matrix(ZZ, 3,4, [1,2,3,-4,7,2,18,3,4,3,4,5])/3)%500).change_ring(ZZ)
35+
sage: sage.matrix.misc.matrix_integer_dense_rational_reconstruction(B, 500)
36+
[ 1/3 2/3 1 -4/3]
37+
[ 7/3 2/3 6 1]
38+
[ 4/3 1 4/3 5/3]
39+
40+
TESTS:
41+
42+
Check that :trac:`9345` is fixed::
43+
44+
sage: A = random_matrix(ZZ, 3)
45+
sage: sage.matrix.misc.matrix_integer_dense_rational_reconstruction(A, 0)
46+
Traceback (most recent call last):
47+
...
48+
ZeroDivisionError: The modulus cannot be zero
49+
"""
50+
if not N:
51+
raise ZeroDivisionError("The modulus cannot be zero")
52+
cdef Matrix_rational_dense R
53+
R = Matrix_rational_dense.__new__(Matrix_rational_dense,
54+
A.parent().change_ring(QQ), 0,0,0)
55+
56+
cdef mpz_t a, bnd, other_bnd, denom, tmp
57+
cdef mpq_t qtmp
58+
cdef Integer _bnd
59+
cdef Py_ssize_t i, j
60+
cdef int do_it
61+
62+
mpz_init_set_si(denom, 1)
63+
mpz_init(a)
64+
mpz_init(tmp)
65+
mpz_init(other_bnd)
66+
mpq_init(qtmp)
67+
68+
_bnd = (N//2).isqrt()
69+
mpz_init_set(bnd, _bnd.value)
70+
mpz_sub(other_bnd, N.value, bnd)
71+
72+
for i in range(A._nrows):
73+
for j in range(A._ncols):
74+
sig_check()
75+
A.get_unsafe_mpz(i, j, a)
76+
if mpz_cmp_ui(denom, 1) != 0:
77+
mpz_mul(a, a, denom)
78+
mpz_fdiv_r(a, a, N.value)
79+
do_it = 0
80+
if mpz_cmp(a, bnd) <= 0:
81+
do_it = 1
82+
elif mpz_cmp(a, other_bnd) >= 0:
83+
mpz_sub(a, a, N.value)
84+
do_it = 1
85+
if do_it:
86+
fmpz_set_mpz(fmpq_mat_entry_num(R._matrix, i, j), a)
87+
if mpz_cmp_ui(denom, 1) != 0:
88+
fmpz_set_mpz(fmpq_mat_entry_den(R._matrix, i, j), denom)
89+
fmpq_canonicalise(fmpq_mat_entry(R._matrix, i, j))
90+
else:
91+
fmpz_one(fmpq_mat_entry_den(R._matrix, i, j))
92+
else:
93+
# Otherwise have to do it the hard way
94+
A.get_unsafe_mpz(i, j, tmp)
95+
mpq_rational_reconstruction(qtmp, tmp, N.value)
96+
mpz_lcm(denom, denom, mpq_denref(qtmp))
97+
fmpq_set_mpq(fmpq_mat_entry(R._matrix, i, j), qtmp)
98+
99+
mpz_clear(denom)
100+
mpz_clear(a)
101+
mpz_clear(tmp)
102+
mpz_clear(other_bnd)
103+
mpz_clear(bnd)
104+
mpq_clear(qtmp)
105+
106+
return R

0 commit comments

Comments
 (0)