passagemath-linbox 10.6.32__cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-linbox might be problematic. Click here for more details.
- passagemath_linbox-10.6.32.dist-info/METADATA +100 -0
- passagemath_linbox-10.6.32.dist-info/RECORD +73 -0
- passagemath_linbox-10.6.32.dist-info/WHEEL +6 -0
- passagemath_linbox-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_linbox.libs/libfflas-d452d784.so.1.0.0 +0 -0
- passagemath_linbox.libs/libffpack-32579c9b.so.1.0.0 +0 -0
- passagemath_linbox.libs/libflint-66e12231.so.21.0.0 +0 -0
- passagemath_linbox.libs/libgd-76eb082b.so.3.0.11 +0 -0
- passagemath_linbox.libs/libgfortran-83c28eba.so.5.0.0 +0 -0
- passagemath_linbox.libs/libgivaro-fc554fc9.so.9.2.1 +0 -0
- passagemath_linbox.libs/libgmp-6e109695.so.10.5.0 +0 -0
- passagemath_linbox.libs/libgmpxx-ecb9d6e3.so.4.7.0 +0 -0
- passagemath_linbox.libs/libiml-aeb1d147.so.0.1.1 +0 -0
- passagemath_linbox.libs/liblinbox-f1d24fc1.so.0.0.0 +0 -0
- passagemath_linbox.libs/libm4ri-9da2b874.so.1.0.0 +0 -0
- passagemath_linbox.libs/libm4rie-cf8cc058.so.1.0.0 +0 -0
- passagemath_linbox.libs/libmpfr-82690d50.so.6.2.1 +0 -0
- passagemath_linbox.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
- passagemath_linbox.libs/libpng16-b4a91cd1.so.16.43.0 +0 -0
- passagemath_linbox.libs/libquadmath-2284e583.so.0.0.0 +0 -0
- sage/all__sagemath_linbox.py +2 -0
- sage/geometry/all__sagemath_linbox.py +1 -0
- sage/geometry/integral_points.pxi +1426 -0
- sage/geometry/integral_points_integer_dense.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/geometry/integral_points_integer_dense.pyx +7 -0
- sage/libs/all__sagemath_linbox.py +1 -0
- sage/libs/iml.pxd +10 -0
- sage/libs/linbox/__init__.py +1 -0
- sage/libs/linbox/conversion.pxd +185 -0
- sage/libs/linbox/fflas.pxd +189 -0
- sage/libs/linbox/givaro.pxd +109 -0
- sage/libs/linbox/linbox.pxd +219 -0
- sage/libs/linbox/linbox_flint_interface.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/linbox/linbox_flint_interface.pxd +18 -0
- sage/libs/linbox/linbox_flint_interface.pyx +192 -0
- sage/libs/m4ri.pxd +198 -0
- sage/libs/m4rie.pxd +204 -0
- sage/matrix/all__sagemath_linbox.py +1 -0
- sage/matrix/matrix_cyclo_linbox.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_cyclo_linbox.pyx +361 -0
- sage/matrix/matrix_gf2e_dense.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_gf2e_dense.pxd +15 -0
- sage/matrix/matrix_gf2e_dense.pyx +1573 -0
- sage/matrix/matrix_integer_iml.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_iml.pyx +316 -0
- sage/matrix/matrix_integer_linbox.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_linbox.pxd +5 -0
- sage/matrix/matrix_integer_linbox.pyx +358 -0
- sage/matrix/matrix_integer_sparse_linbox.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_sparse_linbox.pyx +465 -0
- sage/matrix/matrix_mod2_dense.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_mod2_dense.pxd +14 -0
- sage/matrix/matrix_mod2_dense.pyx +2789 -0
- sage/matrix/matrix_modn_dense_double.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_modn_dense_double.pyx +179 -0
- sage/matrix/matrix_modn_dense_float.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_modn_dense_float.pyx +154 -0
- sage/matrix/matrix_modn_sparse.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_modn_sparse.pyx +871 -0
- sage/matrix/matrix_rational_linbox.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_rational_linbox.pyx +36 -0
- sage/matrix/misc.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/misc.pyx +418 -0
- sage/modules/all__sagemath_linbox.py +1 -0
- sage/modules/numpy_util.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/modules/numpy_util.pxd +10 -0
- sage/modules/numpy_util.pyx +136 -0
- sage/modules/vector_mod2_dense.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_mod2_dense.pxd +11 -0
- sage/modules/vector_mod2_dense.pyx +547 -0
- sage/rings/all__sagemath_linbox.py +1 -0
- sage/rings/finite_rings/all__sagemath_linbox.py +1 -0
- sage/rings/polynomial/all__sagemath_linbox.py +1 -0
|
Binary file
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-linbox
|
|
2
|
+
# distutils: libraries = iml
|
|
3
|
+
# sage.doctest: needs sage.libs.flint sage.libs.linbox
|
|
4
|
+
|
|
5
|
+
from cysignals.signals cimport sig_check, sig_on, sig_str, sig_off
|
|
6
|
+
from cysignals.memory cimport sig_malloc, sig_free, check_allocarray
|
|
7
|
+
|
|
8
|
+
from sage.libs.flint.fmpz cimport *
|
|
9
|
+
from sage.libs.flint.fmpz_mat cimport *
|
|
10
|
+
from sage.libs.gmp.mpz cimport *
|
|
11
|
+
from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense
|
|
12
|
+
from sage.misc.verbose import verbose
|
|
13
|
+
from sage.rings.integer cimport Integer
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
########## iml -- integer matrix library ###########
|
|
17
|
+
from sage.libs.iml cimport *
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _rational_kernel_iml(Matrix_integer_dense self):
|
|
21
|
+
"""
|
|
22
|
+
Return the rational (left) kernel of this matrix.
|
|
23
|
+
|
|
24
|
+
OUTPUT:
|
|
25
|
+
|
|
26
|
+
A matrix ``K`` such that ``self * K = 0``, and the number of columns of
|
|
27
|
+
K equals the nullity of ``self``.
|
|
28
|
+
|
|
29
|
+
EXAMPLES::
|
|
30
|
+
|
|
31
|
+
sage: from sage.matrix.matrix_integer_iml import _rational_kernel_iml
|
|
32
|
+
sage: m = matrix(ZZ, 5, 5, [1+i+i^2 for i in range(25)])
|
|
33
|
+
sage: _rational_kernel_iml(m)
|
|
34
|
+
[ 1 3]
|
|
35
|
+
[-3 -8]
|
|
36
|
+
[ 3 6]
|
|
37
|
+
[-1 0]
|
|
38
|
+
[ 0 -1]
|
|
39
|
+
|
|
40
|
+
sage: V1 = _rational_kernel_iml(m).column_space().change_ring(QQ)
|
|
41
|
+
sage: V2 = m._rational_kernel_flint().column_space().change_ring(QQ)
|
|
42
|
+
sage: assert V1 == V2
|
|
43
|
+
"""
|
|
44
|
+
if self._nrows == 0 or self._ncols == 0:
|
|
45
|
+
return self.matrix_space(self._ncols, 0).zero_matrix()
|
|
46
|
+
|
|
47
|
+
cdef long dim
|
|
48
|
+
cdef unsigned long i,j,k
|
|
49
|
+
cdef mpz_t *mp_N
|
|
50
|
+
time = verbose('computing null space of %s x %s matrix using IML' % (self._nrows, self._ncols))
|
|
51
|
+
cdef mpz_t * m = fmpz_mat_to_mpz_array(self._matrix)
|
|
52
|
+
sig_on()
|
|
53
|
+
dim = nullspaceMP(self._nrows, self._ncols, m, &mp_N)
|
|
54
|
+
sig_off()
|
|
55
|
+
# Now read the answer as a matrix.
|
|
56
|
+
cdef Matrix_integer_dense M
|
|
57
|
+
M = self._new(self._ncols, dim)
|
|
58
|
+
k = 0
|
|
59
|
+
for i in range(self._ncols):
|
|
60
|
+
for j in range(dim):
|
|
61
|
+
fmpz_set_mpz(fmpz_mat_entry(M._matrix, i, j), mp_N[k])
|
|
62
|
+
k += 1
|
|
63
|
+
mpz_array_clear(m, self._nrows * self._ncols)
|
|
64
|
+
mpz_array_clear(mp_N, dim * self._ncols)
|
|
65
|
+
verbose("finished computing null space", time)
|
|
66
|
+
return M
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _invert_iml(Matrix_integer_dense self, use_nullspace=False, check_invertible=True):
|
|
70
|
+
"""
|
|
71
|
+
Invert this matrix using IML. The output matrix is an integer
|
|
72
|
+
matrix and a denominator.
|
|
73
|
+
|
|
74
|
+
INPUT:
|
|
75
|
+
|
|
76
|
+
- ``self`` -- an invertible matrix
|
|
77
|
+
|
|
78
|
+
- ``use_nullspace`` -- boolean (default: ``False``); whether to
|
|
79
|
+
use nullspace algorithm, which is slower, but doesn't require
|
|
80
|
+
checking that the matrix is invertible as a precondition
|
|
81
|
+
|
|
82
|
+
- ``check_invertible`` -- boolean (default: ``True``); whether to
|
|
83
|
+
check that the matrix is invertible
|
|
84
|
+
|
|
85
|
+
OUTPUT: `A`, `d` such that ``A*self == d``
|
|
86
|
+
|
|
87
|
+
- ``A`` -- a matrix over ZZ
|
|
88
|
+
|
|
89
|
+
- ``d`` -- integer
|
|
90
|
+
|
|
91
|
+
ALGORITHM: Uses IML's `p`-adic nullspace function.
|
|
92
|
+
|
|
93
|
+
EXAMPLES::
|
|
94
|
+
|
|
95
|
+
sage: from sage.matrix.matrix_integer_iml import _invert_iml
|
|
96
|
+
sage: a = matrix(ZZ,3,[1,2,5, 3,7,8, 2,2,1])
|
|
97
|
+
sage: b, d = _invert_iml(a); b,d
|
|
98
|
+
(
|
|
99
|
+
[ 9 -8 19]
|
|
100
|
+
[-13 9 -7]
|
|
101
|
+
[ 8 -2 -1], 23
|
|
102
|
+
)
|
|
103
|
+
sage: a*b
|
|
104
|
+
[23 0 0]
|
|
105
|
+
[ 0 23 0]
|
|
106
|
+
[ 0 0 23]
|
|
107
|
+
|
|
108
|
+
AUTHORS:
|
|
109
|
+
|
|
110
|
+
- William Stein
|
|
111
|
+
"""
|
|
112
|
+
if self._nrows != self._ncols:
|
|
113
|
+
raise TypeError("self must be a square matrix.")
|
|
114
|
+
|
|
115
|
+
P = self.parent()
|
|
116
|
+
time = verbose('computing inverse of %s x %s matrix using IML' % (self._nrows, self._ncols))
|
|
117
|
+
if use_nullspace:
|
|
118
|
+
A = self.augment(P.identity_matrix())
|
|
119
|
+
K = A._rational_kernel_iml()
|
|
120
|
+
d = -K[self._nrows,0]
|
|
121
|
+
if K.ncols() != self._ncols or d == 0:
|
|
122
|
+
raise ZeroDivisionError("input matrix must be nonsingular")
|
|
123
|
+
B = K[:self._nrows]
|
|
124
|
+
verbose("finished computing inverse using IML", time)
|
|
125
|
+
return B, d
|
|
126
|
+
else:
|
|
127
|
+
if check_invertible and self.rank() != self._nrows:
|
|
128
|
+
raise ZeroDivisionError("input matrix must be nonsingular")
|
|
129
|
+
return _solve_iml(self, P.identity_matrix(), right=True)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _solve_iml(Matrix_integer_dense self, Matrix_integer_dense B, right=True):
|
|
133
|
+
"""
|
|
134
|
+
Let A equal ``self`` be a square matrix. Given B return an integer
|
|
135
|
+
matrix C and an integer d such that ``self`` ``C*A == d*B`` if right is
|
|
136
|
+
False or ``A*C == d*B`` if right is True.
|
|
137
|
+
|
|
138
|
+
OUTPUT:
|
|
139
|
+
|
|
140
|
+
- ``C`` -- integer matrix
|
|
141
|
+
|
|
142
|
+
- ``d`` -- integer denominator
|
|
143
|
+
|
|
144
|
+
EXAMPLES::
|
|
145
|
+
|
|
146
|
+
sage: from sage.matrix.matrix_integer_iml import _solve_iml
|
|
147
|
+
sage: A = matrix(ZZ,4,4,[0, 1, -2, -1, -1, 1, 0, 2, 2, 2, 2, -1, 0, 2, 2, 1])
|
|
148
|
+
sage: B = matrix(ZZ,3,4, [-1, 1, 1, 0, 2, 0, -2, -1, 0, -2, -2, -2])
|
|
149
|
+
sage: C, d = _solve_iml(A, B, right=False); C
|
|
150
|
+
[ 6 -18 -15 27]
|
|
151
|
+
[ 0 24 24 -36]
|
|
152
|
+
[ 4 -12 -6 -2]
|
|
153
|
+
|
|
154
|
+
::
|
|
155
|
+
|
|
156
|
+
sage: d
|
|
157
|
+
12
|
|
158
|
+
|
|
159
|
+
::
|
|
160
|
+
|
|
161
|
+
sage: C*A == d*B
|
|
162
|
+
True
|
|
163
|
+
|
|
164
|
+
::
|
|
165
|
+
|
|
166
|
+
sage: A = matrix(ZZ,4,4,[0, 1, -2, -1, -1, 1, 0, 2, 2, 2, 2, -1, 0, 2, 2, 1])
|
|
167
|
+
sage: B = matrix(ZZ,4,3, [-1, 1, 1, 0, 2, 0, -2, -1, 0, -2, -2, -2])
|
|
168
|
+
sage: C, d = _solve_iml(A, B)
|
|
169
|
+
sage: C
|
|
170
|
+
[ 12 40 28]
|
|
171
|
+
[-12 -4 -4]
|
|
172
|
+
[ -6 -25 -16]
|
|
173
|
+
[ 12 34 16]
|
|
174
|
+
|
|
175
|
+
::
|
|
176
|
+
|
|
177
|
+
sage: d
|
|
178
|
+
12
|
|
179
|
+
|
|
180
|
+
::
|
|
181
|
+
|
|
182
|
+
sage: A*C == d*B
|
|
183
|
+
True
|
|
184
|
+
|
|
185
|
+
Test wrong dimensions::
|
|
186
|
+
|
|
187
|
+
sage: A = random_matrix(ZZ, 4, 4)
|
|
188
|
+
sage: B = random_matrix(ZZ, 2, 3)
|
|
189
|
+
sage: _solve_iml(B, A)
|
|
190
|
+
Traceback (most recent call last):
|
|
191
|
+
...
|
|
192
|
+
ValueError: self must be a square matrix
|
|
193
|
+
sage: _solve_iml(A, B, right=False)
|
|
194
|
+
Traceback (most recent call last):
|
|
195
|
+
...
|
|
196
|
+
ArithmeticError: B's number of columns must match self's number of rows
|
|
197
|
+
sage: _solve_iml(A, B, right=True)
|
|
198
|
+
Traceback (most recent call last):
|
|
199
|
+
...
|
|
200
|
+
ArithmeticError: B's number of rows must match self's number of columns
|
|
201
|
+
|
|
202
|
+
Check that this can be interrupted properly (:issue:`15453`)::
|
|
203
|
+
|
|
204
|
+
sage: A = random_matrix(ZZ, 2000, 2000)
|
|
205
|
+
sage: B = random_matrix(ZZ, 2000, 2000)
|
|
206
|
+
sage: t0 = walltime()
|
|
207
|
+
sage: alarm(2); _solve_iml(A, B) # long time
|
|
208
|
+
Traceback (most recent call last):
|
|
209
|
+
...
|
|
210
|
+
AlarmInterrupt
|
|
211
|
+
sage: t = walltime(t0)
|
|
212
|
+
sage: t < 10 or t
|
|
213
|
+
True
|
|
214
|
+
|
|
215
|
+
ALGORITHM: Uses IML.
|
|
216
|
+
|
|
217
|
+
AUTHORS:
|
|
218
|
+
|
|
219
|
+
- Martin Albrecht
|
|
220
|
+
"""
|
|
221
|
+
cdef unsigned long i, j, k
|
|
222
|
+
cdef mpz_t *mp_N
|
|
223
|
+
cdef mpz_t mp_D
|
|
224
|
+
cdef Matrix_integer_dense M
|
|
225
|
+
cdef Integer D
|
|
226
|
+
|
|
227
|
+
if self._nrows != self._ncols:
|
|
228
|
+
# This is *required* by the IML function we call below.
|
|
229
|
+
raise ValueError("self must be a square matrix")
|
|
230
|
+
|
|
231
|
+
if self._nrows == 1:
|
|
232
|
+
return B, self[0,0]
|
|
233
|
+
|
|
234
|
+
cdef SOLU_POS solu_pos
|
|
235
|
+
|
|
236
|
+
if right:
|
|
237
|
+
if self._ncols != B._nrows:
|
|
238
|
+
raise ArithmeticError("B's number of rows must match self's number of columns")
|
|
239
|
+
|
|
240
|
+
n = self._ncols
|
|
241
|
+
m = B._ncols
|
|
242
|
+
|
|
243
|
+
P = self.matrix_space(n, m)
|
|
244
|
+
if self._nrows == 0 or self._ncols == 0:
|
|
245
|
+
return P.zero_matrix(), Integer(1)
|
|
246
|
+
|
|
247
|
+
if m == 0 or n == 0:
|
|
248
|
+
return self.new_matrix(nrows = n, ncols = m), Integer(1)
|
|
249
|
+
|
|
250
|
+
solu_pos = RightSolu
|
|
251
|
+
|
|
252
|
+
else: # left
|
|
253
|
+
if self._nrows != B._ncols:
|
|
254
|
+
raise ArithmeticError("B's number of columns must match self's number of rows")
|
|
255
|
+
|
|
256
|
+
n = self._ncols
|
|
257
|
+
m = B._nrows
|
|
258
|
+
|
|
259
|
+
P = self.matrix_space(m, n)
|
|
260
|
+
if self._nrows == 0 or self._ncols == 0:
|
|
261
|
+
return P.zero_matrix(), Integer(1)
|
|
262
|
+
|
|
263
|
+
if m == 0 or n == 0:
|
|
264
|
+
return self.new_matrix(nrows = m, ncols = n), Integer(1)
|
|
265
|
+
|
|
266
|
+
solu_pos = LeftSolu
|
|
267
|
+
|
|
268
|
+
sig_check()
|
|
269
|
+
verbose("Initializing mp_N and mp_D")
|
|
270
|
+
mp_N = <mpz_t *> sig_malloc( n * m * sizeof(mpz_t) )
|
|
271
|
+
for i in range(n * m):
|
|
272
|
+
mpz_init(mp_N[i])
|
|
273
|
+
mpz_init(mp_D)
|
|
274
|
+
verbose("Done with initializing mp_N and mp_D")
|
|
275
|
+
cdef mpz_t * mself = fmpz_mat_to_mpz_array(self._matrix)
|
|
276
|
+
cdef mpz_t * mB = fmpz_mat_to_mpz_array(B._matrix)
|
|
277
|
+
try:
|
|
278
|
+
verbose('Calling solver n = %s, m = %s' % (n,m))
|
|
279
|
+
sig_on()
|
|
280
|
+
nonsingSolvLlhsMM(solu_pos, n, m, mself, mB, mp_N, mp_D)
|
|
281
|
+
sig_off()
|
|
282
|
+
M = self._new(P.nrows(), P.ncols())
|
|
283
|
+
k = 0
|
|
284
|
+
for i from 0 <= i < M._nrows:
|
|
285
|
+
for j from 0 <= j < M._ncols:
|
|
286
|
+
fmpz_set_mpz(fmpz_mat_entry(M._matrix,i,j), mp_N[k])
|
|
287
|
+
k += 1
|
|
288
|
+
D = Integer.__new__(Integer)
|
|
289
|
+
mpz_set(D.value, mp_D)
|
|
290
|
+
return M, D
|
|
291
|
+
finally:
|
|
292
|
+
mpz_clear(mp_D)
|
|
293
|
+
mpz_array_clear(mself, self.nrows() * self.ncols())
|
|
294
|
+
mpz_array_clear(mB, B.nrows() * B.ncols())
|
|
295
|
+
mpz_array_clear(mp_N, n*m)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
cdef inline mpz_t * fmpz_mat_to_mpz_array(fmpz_mat_t m) except? NULL:
|
|
299
|
+
cdef mpz_t * entries = <mpz_t *>check_allocarray(fmpz_mat_nrows(m), sizeof(mpz_t) * fmpz_mat_ncols(m))
|
|
300
|
+
cdef size_t i, j
|
|
301
|
+
cdef size_t k = 0
|
|
302
|
+
sig_on()
|
|
303
|
+
for i in range(fmpz_mat_nrows(m)):
|
|
304
|
+
for j in range(fmpz_mat_ncols(m)):
|
|
305
|
+
mpz_init(entries[k])
|
|
306
|
+
fmpz_get_mpz(entries[k], fmpz_mat_entry(m, i, j))
|
|
307
|
+
k += 1
|
|
308
|
+
sig_off()
|
|
309
|
+
return entries
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
cdef inline void mpz_array_clear(mpz_t * a, size_t length) noexcept:
|
|
313
|
+
cdef size_t i
|
|
314
|
+
for i in range(length):
|
|
315
|
+
mpz_clear(a[i])
|
|
316
|
+
sig_free(a)
|
|
Binary file
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-linbox
|
|
2
|
+
# sage.doctest: needs sage.libs.flint sage.libs.linbox
|
|
3
|
+
|
|
4
|
+
from cysignals.signals cimport sig_check, sig_on, sig_str, sig_off
|
|
5
|
+
from cysignals.memory cimport sig_malloc, sig_free, check_allocarray
|
|
6
|
+
|
|
7
|
+
import sage.matrix.matrix_space as matrix_space
|
|
8
|
+
|
|
9
|
+
from sage.arith.multi_modular cimport MultiModularBasis
|
|
10
|
+
from sage.ext.mod_int cimport *
|
|
11
|
+
from sage.ext.stdsage cimport PY_NEW
|
|
12
|
+
from sage.libs.flint.fmpz cimport *
|
|
13
|
+
from sage.libs.flint.fmpz_mat cimport *
|
|
14
|
+
from sage.libs.gmp.mpz cimport *
|
|
15
|
+
from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense
|
|
16
|
+
from sage.matrix.matrix_modn_dense_float cimport Matrix_modn_dense_template
|
|
17
|
+
from sage.matrix.matrix_modn_dense_float cimport Matrix_modn_dense_float
|
|
18
|
+
from sage.matrix.matrix_modn_dense_double cimport Matrix_modn_dense_double
|
|
19
|
+
from sage.misc.timing import cputime
|
|
20
|
+
from sage.misc.verbose import verbose
|
|
21
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
22
|
+
from sage.rings.integer cimport Integer
|
|
23
|
+
from sage.rings.integer_ring import ZZ
|
|
24
|
+
from sage.rings.polynomial.polynomial_integer_dense_flint cimport Polynomial_integer_dense_flint
|
|
25
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
26
|
+
|
|
27
|
+
######### linbox interface ##########
|
|
28
|
+
from sage.libs.linbox.linbox_flint_interface cimport *
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _multiply_linbox(Matrix_integer_dense self, Matrix_integer_dense right):
|
|
32
|
+
"""
|
|
33
|
+
Multiply matrices over ZZ using linbox.
|
|
34
|
+
|
|
35
|
+
.. WARNING::
|
|
36
|
+
|
|
37
|
+
This is very slow right now, i.e., linbox is very slow.
|
|
38
|
+
|
|
39
|
+
EXAMPLES::
|
|
40
|
+
|
|
41
|
+
sage: from sage.matrix.matrix_integer_linbox import _multiply_linbox
|
|
42
|
+
sage: A = matrix(ZZ, 2, 3, range(6))
|
|
43
|
+
sage: A * A.transpose()
|
|
44
|
+
[ 5 14]
|
|
45
|
+
[14 50]
|
|
46
|
+
sage: _multiply_linbox(A, A.transpose())
|
|
47
|
+
[ 5 14]
|
|
48
|
+
[14 50]
|
|
49
|
+
|
|
50
|
+
TESTS:
|
|
51
|
+
|
|
52
|
+
This fixes a bug found in :issue:`17094`::
|
|
53
|
+
|
|
54
|
+
sage: A = identity_matrix(ZZ, 3)
|
|
55
|
+
sage: _multiply_linbox(A, A)
|
|
56
|
+
[1 0 0]
|
|
57
|
+
[0 1 0]
|
|
58
|
+
[0 0 1]
|
|
59
|
+
"""
|
|
60
|
+
cdef Matrix_integer_dense ans
|
|
61
|
+
cdef Matrix_integer_dense left = <Matrix_integer_dense> self
|
|
62
|
+
|
|
63
|
+
ans = self._new(left._nrows, right._ncols)
|
|
64
|
+
|
|
65
|
+
sig_on()
|
|
66
|
+
linbox_fmpz_mat_mul(ans._matrix, left._matrix, right._matrix)
|
|
67
|
+
sig_off()
|
|
68
|
+
|
|
69
|
+
return ans
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _charpoly_linbox(Matrix_integer_dense self, var):
|
|
73
|
+
g = (<Polynomial_integer_dense_flint> PolynomialRing(ZZ, names=var).gen())._new()
|
|
74
|
+
sig_on()
|
|
75
|
+
linbox_fmpz_mat_charpoly(g._poly, self._matrix)
|
|
76
|
+
sig_off()
|
|
77
|
+
return g
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _minpoly_linbox(Matrix_integer_dense self, var):
|
|
81
|
+
g = (<Polynomial_integer_dense_flint> PolynomialRing(ZZ, names=var).gen())._new()
|
|
82
|
+
sig_on()
|
|
83
|
+
linbox_fmpz_mat_minpoly(g._poly, self._matrix)
|
|
84
|
+
sig_off()
|
|
85
|
+
return g
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _rank_linbox(Matrix_integer_dense self):
|
|
89
|
+
"""
|
|
90
|
+
Compute the rank of this matrix using Linbox.
|
|
91
|
+
|
|
92
|
+
TESTS::
|
|
93
|
+
|
|
94
|
+
sage: from sage.matrix.matrix_integer_linbox import _rank_linbox
|
|
95
|
+
sage: _rank_linbox(matrix(ZZ, 4, 6, 0))
|
|
96
|
+
0
|
|
97
|
+
sage: _rank_linbox(matrix(ZZ, 3, 4, range(12)))
|
|
98
|
+
2
|
|
99
|
+
sage: _rank_linbox(matrix(ZZ, 5, 10, [1+i+i^2 for i in range(50)]))
|
|
100
|
+
3
|
|
101
|
+
"""
|
|
102
|
+
sig_on()
|
|
103
|
+
cdef size_t r = linbox_fmpz_mat_rank(self._matrix)
|
|
104
|
+
sig_off()
|
|
105
|
+
return Integer(r)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _det_linbox(Matrix_integer_dense self):
|
|
109
|
+
"""
|
|
110
|
+
Compute the determinant of this matrix using Linbox.
|
|
111
|
+
|
|
112
|
+
TESTS::
|
|
113
|
+
|
|
114
|
+
sage: from sage.matrix.matrix_integer_linbox import _det_linbox
|
|
115
|
+
sage: _det_linbox(matrix(ZZ, 0))
|
|
116
|
+
1
|
|
117
|
+
"""
|
|
118
|
+
if self._nrows != self._ncols:
|
|
119
|
+
raise ArithmeticError("self must be a square matrix")
|
|
120
|
+
if self._nrows == 0:
|
|
121
|
+
return ZZ.one()
|
|
122
|
+
|
|
123
|
+
cdef fmpz_t tmp
|
|
124
|
+
fmpz_init(tmp)
|
|
125
|
+
sig_on()
|
|
126
|
+
linbox_fmpz_mat_det(tmp, self._matrix)
|
|
127
|
+
sig_off()
|
|
128
|
+
|
|
129
|
+
cdef Integer ans = PY_NEW(Integer)
|
|
130
|
+
fmpz_get_mpz(ans.value, tmp)
|
|
131
|
+
fmpz_clear(tmp)
|
|
132
|
+
return ans
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _Matrix_modn_dense_float(Matrix_integer_dense self, mod_int p):
|
|
136
|
+
cdef Py_ssize_t i, j
|
|
137
|
+
|
|
138
|
+
cdef float* res_row_f
|
|
139
|
+
cdef Matrix_modn_dense_float res_f
|
|
140
|
+
|
|
141
|
+
res_f = Matrix_modn_dense_float.__new__(Matrix_modn_dense_float,
|
|
142
|
+
matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None, zeroed_alloc=False)
|
|
143
|
+
for i from 0 <= i < self._nrows:
|
|
144
|
+
res_row_f = res_f._matrix[i]
|
|
145
|
+
for j from 0 <= j < self._ncols:
|
|
146
|
+
res_row_f[j] = <float>fmpz_fdiv_ui(fmpz_mat_entry(self._matrix,i,j), p)
|
|
147
|
+
return res_f
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _Matrix_modn_dense_double(Matrix_integer_dense self, mod_int p):
|
|
151
|
+
cdef Py_ssize_t i, j
|
|
152
|
+
|
|
153
|
+
cdef double* res_row_d
|
|
154
|
+
cdef Matrix_modn_dense_double res_d
|
|
155
|
+
|
|
156
|
+
res_d = Matrix_modn_dense_double.__new__(Matrix_modn_dense_double,
|
|
157
|
+
matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None, zeroed_alloc=False)
|
|
158
|
+
for i from 0 <= i < self._nrows:
|
|
159
|
+
res_row_d = res_d._matrix[i]
|
|
160
|
+
for j from 0 <= j < self._ncols:
|
|
161
|
+
res_row_d[j] = <double>fmpz_fdiv_ui(fmpz_mat_entry(self._matrix,i,j), p)
|
|
162
|
+
return res_d
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _multiply_multi_modular(Matrix_integer_dense self, Matrix_integer_dense right):
|
|
166
|
+
"""
|
|
167
|
+
Multiply this matrix by ``left`` using a multi modular algorithm.
|
|
168
|
+
|
|
169
|
+
EXAMPLES::
|
|
170
|
+
|
|
171
|
+
sage: M = Matrix(ZZ, 2, 3, range(5,11))
|
|
172
|
+
sage: N = Matrix(ZZ, 3, 2, range(15,21))
|
|
173
|
+
sage: M._multiply_multi_modular(N)
|
|
174
|
+
[310 328]
|
|
175
|
+
[463 490]
|
|
176
|
+
sage: M._multiply_multi_modular(-N)
|
|
177
|
+
[-310 -328]
|
|
178
|
+
[-463 -490]
|
|
179
|
+
"""
|
|
180
|
+
cdef Integer h
|
|
181
|
+
cdef Matrix_integer_dense left = <Matrix_integer_dense>self
|
|
182
|
+
cdef Py_ssize_t i, k
|
|
183
|
+
|
|
184
|
+
nr = left._nrows
|
|
185
|
+
nc = right._ncols
|
|
186
|
+
|
|
187
|
+
cdef Matrix_integer_dense result
|
|
188
|
+
|
|
189
|
+
h = left.height() * right.height() * left.ncols()
|
|
190
|
+
verbose('multiplying matrices of height %s and %s' % (left.height(),
|
|
191
|
+
right.height()))
|
|
192
|
+
mm = MultiModularBasis(h)
|
|
193
|
+
res = left._reduce(mm)
|
|
194
|
+
res_right = right._reduce(mm)
|
|
195
|
+
k = len(mm)
|
|
196
|
+
for i in range(k): # yes, I could do this with zip, but to conserve memory...
|
|
197
|
+
t = cputime()
|
|
198
|
+
res[i] *= res_right[i]
|
|
199
|
+
verbose('multiplied matrices modulo a prime (%s/%s)' % (i+1, k), t)
|
|
200
|
+
result = left.new_matrix(nr,nc)
|
|
201
|
+
_lift_crt(result, res, mm) # changes result
|
|
202
|
+
return result
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def _reduce(Matrix_integer_dense self, moduli):
|
|
206
|
+
from sage.matrix.matrix_modn_dense_float import MAX_MODULUS as MAX_MODULUS_FLOAT
|
|
207
|
+
from sage.matrix.matrix_modn_dense_double import MAX_MODULUS as MAX_MODULUS_DOUBLE
|
|
208
|
+
|
|
209
|
+
if isinstance(moduli, (int, Integer)):
|
|
210
|
+
return self._mod_int(moduli)
|
|
211
|
+
elif isinstance(moduli, list):
|
|
212
|
+
moduli = MultiModularBasis(moduli)
|
|
213
|
+
|
|
214
|
+
cdef MultiModularBasis mm
|
|
215
|
+
mm = moduli
|
|
216
|
+
|
|
217
|
+
res = []
|
|
218
|
+
for p in mm:
|
|
219
|
+
if p < MAX_MODULUS_FLOAT:
|
|
220
|
+
res.append( Matrix_modn_dense_float.__new__(Matrix_modn_dense_float,
|
|
221
|
+
matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False),
|
|
222
|
+
None, None, None, zeroed_alloc=False) )
|
|
223
|
+
elif p < MAX_MODULUS_DOUBLE:
|
|
224
|
+
res.append( Matrix_modn_dense_double.__new__(Matrix_modn_dense_double,
|
|
225
|
+
matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False),
|
|
226
|
+
None, None, None, zeroed_alloc=False) )
|
|
227
|
+
else:
|
|
228
|
+
raise ValueError("p=%d too big." % p)
|
|
229
|
+
|
|
230
|
+
cdef size_t i, k, n
|
|
231
|
+
cdef Py_ssize_t nr, nc
|
|
232
|
+
cdef mpz_t tmp
|
|
233
|
+
mpz_init(tmp)
|
|
234
|
+
n = len(mm)
|
|
235
|
+
nr = self._nrows
|
|
236
|
+
nc = self._ncols
|
|
237
|
+
|
|
238
|
+
cdef mod_int *entry_list
|
|
239
|
+
entry_list = <mod_int*>sig_malloc(sizeof(mod_int) * n)
|
|
240
|
+
if entry_list == NULL:
|
|
241
|
+
raise MemoryError("out of memory allocating multi-modular coefficient list")
|
|
242
|
+
|
|
243
|
+
sig_on()
|
|
244
|
+
for i from 0 <= i < nr:
|
|
245
|
+
for j from 0 <= j < nc:
|
|
246
|
+
self.get_unsafe_mpz(i,j,tmp)
|
|
247
|
+
mm.mpz_reduce(tmp, entry_list)
|
|
248
|
+
for k from 0 <= k < n:
|
|
249
|
+
if isinstance(res[k], Matrix_modn_dense_float):
|
|
250
|
+
(<Matrix_modn_dense_float>res[k])._matrix[i][j] = (<float>entry_list[k]) % (<Matrix_modn_dense_float>res[k]).p
|
|
251
|
+
else:
|
|
252
|
+
(<Matrix_modn_dense_double>res[k])._matrix[i][j] = (<double>entry_list[k]) % (<Matrix_modn_dense_double>res[k]).p
|
|
253
|
+
sig_off()
|
|
254
|
+
mpz_clear(tmp)
|
|
255
|
+
sig_free(entry_list)
|
|
256
|
+
return res
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
cpdef _lift_crt(Matrix_integer_dense M, residues, moduli=None):
|
|
260
|
+
"""
|
|
261
|
+
INPUT:
|
|
262
|
+
|
|
263
|
+
- ``M`` -- a ``Matrix_integer_dense``; will be modified to hold
|
|
264
|
+
the output
|
|
265
|
+
|
|
266
|
+
- ``residues`` -- list of ``Matrix_modn_dense_template``; the
|
|
267
|
+
matrix to reconstruct modulo primes
|
|
268
|
+
|
|
269
|
+
OUTPUT: the matrix whose reductions modulo primes are the input ``residues``
|
|
270
|
+
|
|
271
|
+
TESTS::
|
|
272
|
+
|
|
273
|
+
sage: from sage.matrix.matrix_integer_linbox import _lift_crt
|
|
274
|
+
sage: T1 = Matrix(Zmod(5), 4, 4, [1, 4, 4, 0, 2, 0, 1, 4, 2, 0, 4, 1, 1, 4, 0, 3])
|
|
275
|
+
sage: T2 = Matrix(Zmod(7), 4, 4, [1, 4, 6, 0, 2, 0, 1, 2, 4, 0, 6, 6, 1, 6, 0, 5])
|
|
276
|
+
sage: T3 = Matrix(Zmod(11), 4, 4, [1, 4, 10, 0, 2, 0, 1, 9, 8, 0, 10, 6, 1, 10, 0, 9])
|
|
277
|
+
sage: _lift_crt(Matrix(ZZ, 4, 4), [T1, T2, T3])
|
|
278
|
+
[ 1 4 -1 0]
|
|
279
|
+
[ 2 0 1 9]
|
|
280
|
+
[-3 0 -1 6]
|
|
281
|
+
[ 1 -1 0 -2]
|
|
282
|
+
|
|
283
|
+
sage: from sage.arith.multi_modular import MultiModularBasis
|
|
284
|
+
sage: mm = MultiModularBasis([5,7,11])
|
|
285
|
+
sage: _lift_crt(Matrix(ZZ, 4, 4), [T1, T2, T3], mm)
|
|
286
|
+
[ 1 4 -1 0]
|
|
287
|
+
[ 2 0 1 9]
|
|
288
|
+
[-3 0 -1 6]
|
|
289
|
+
[ 1 -1 0 -2]
|
|
290
|
+
|
|
291
|
+
The modulus must be smaller than the maximum for the multi-modular
|
|
292
|
+
reconstruction (using ``mod_int``) and also smaller than the limit
|
|
293
|
+
for ``Matrix_modn_dense_double`` to be able to represent the
|
|
294
|
+
``residues`` ::
|
|
295
|
+
|
|
296
|
+
sage: from sage.arith.multi_modular import MAX_MODULUS as MAX_multi_modular
|
|
297
|
+
sage: from sage.matrix.matrix_modn_dense_double import MAX_MODULUS as MAX_modn_dense_double
|
|
298
|
+
sage: MAX_MODULUS = min(MAX_multi_modular, MAX_modn_dense_double)
|
|
299
|
+
sage: p0 = previous_prime(MAX_MODULUS)
|
|
300
|
+
sage: p1 = previous_prime(p0)
|
|
301
|
+
sage: mmod = [matrix(GF(p0), [[-1, 0, 1, 0, 0, 1, 1, 0, 0, 0, p0-1, p0-2]]),
|
|
302
|
+
....: matrix(GF(p1), [[-1, 0, 1, 0, 0, 1, 1, 0, 0, 0, p1-1, p1-2]])]
|
|
303
|
+
sage: _lift_crt(Matrix(ZZ, 1, 12), mmod)
|
|
304
|
+
[-1 0 1 0 0 1 1 0 0 0 -1 -2]
|
|
305
|
+
"""
|
|
306
|
+
|
|
307
|
+
cdef size_t i, j, k
|
|
308
|
+
cdef Py_ssize_t nr, n
|
|
309
|
+
cdef mpz_t *tmp = <mpz_t *>sig_malloc(sizeof(mpz_t) * M._ncols)
|
|
310
|
+
n = len(residues)
|
|
311
|
+
if n == 0: # special case: obviously residues[0] wouldn't make sense here.
|
|
312
|
+
return M
|
|
313
|
+
nr = residues[0].nrows()
|
|
314
|
+
nc = residues[0].ncols()
|
|
315
|
+
|
|
316
|
+
if moduli is None:
|
|
317
|
+
moduli = MultiModularBasis([m.base_ring().order() for m in residues])
|
|
318
|
+
else:
|
|
319
|
+
if len(residues) != len(moduli):
|
|
320
|
+
raise IndexError("Number of residues (%s) does not match number of moduli (%s)" % (len(residues), len(moduli)))
|
|
321
|
+
|
|
322
|
+
cdef MultiModularBasis mm
|
|
323
|
+
mm = moduli
|
|
324
|
+
|
|
325
|
+
for b in residues:
|
|
326
|
+
if not (isinstance(b, Matrix_modn_dense_float) or
|
|
327
|
+
isinstance(b, Matrix_modn_dense_double)):
|
|
328
|
+
raise TypeError("Can only perform CRT on list of matrices mod n.")
|
|
329
|
+
|
|
330
|
+
cdef mod_int **row_list
|
|
331
|
+
row_list = <mod_int**>sig_malloc(sizeof(mod_int*) * n)
|
|
332
|
+
if row_list == NULL:
|
|
333
|
+
raise MemoryError("out of memory allocating multi-modular coefficient list")
|
|
334
|
+
|
|
335
|
+
sig_on()
|
|
336
|
+
for k in range(n):
|
|
337
|
+
row_list[k] = <mod_int *>sig_malloc(sizeof(mod_int) * nc)
|
|
338
|
+
if row_list[k] == NULL:
|
|
339
|
+
raise MemoryError("out of memory allocating multi-modular coefficient list")
|
|
340
|
+
|
|
341
|
+
for j in range(M._ncols):
|
|
342
|
+
mpz_init(tmp[j])
|
|
343
|
+
|
|
344
|
+
for i in range(nr):
|
|
345
|
+
for k in range(n):
|
|
346
|
+
(<Matrix_modn_dense_template>residues[k])._copy_row_to_mod_int_array(row_list[k],i)
|
|
347
|
+
mm.mpz_crt_vec(tmp, row_list, nc)
|
|
348
|
+
for j in range(nc):
|
|
349
|
+
M.set_unsafe_mpz(i,j,tmp[j])
|
|
350
|
+
|
|
351
|
+
for k in range(n):
|
|
352
|
+
sig_free(row_list[k])
|
|
353
|
+
for j in range(M._ncols):
|
|
354
|
+
mpz_clear(tmp[j])
|
|
355
|
+
sig_free(row_list)
|
|
356
|
+
sig_free(tmp)
|
|
357
|
+
sig_off()
|
|
358
|
+
return M
|
|
Binary file
|