passagemath-linbox 10.6.43__cp313-cp313-macosx_13_0_arm64.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.
Files changed (75) hide show
  1. passagemath_linbox/.dylibs/libfflas.1.dylib +0 -0
  2. passagemath_linbox/.dylibs/libffpack.1.dylib +0 -0
  3. passagemath_linbox/.dylibs/libflint.22.0.dylib +0 -0
  4. passagemath_linbox/.dylibs/libgd.3.dylib +0 -0
  5. passagemath_linbox/.dylibs/libgfortran.5.dylib +0 -0
  6. passagemath_linbox/.dylibs/libgivaro.9.dylib +0 -0
  7. passagemath_linbox/.dylibs/libgmp.10.dylib +0 -0
  8. passagemath_linbox/.dylibs/libgmpxx.4.dylib +0 -0
  9. passagemath_linbox/.dylibs/libiml.0.dylib +0 -0
  10. passagemath_linbox/.dylibs/liblinbox.0.dylib +0 -0
  11. passagemath_linbox/.dylibs/libm4ri.1.dylib +0 -0
  12. passagemath_linbox/.dylibs/libm4rie.1.dylib +0 -0
  13. passagemath_linbox/.dylibs/libmpfr.6.dylib +0 -0
  14. passagemath_linbox/.dylibs/libopenblasp-r0.3.29.dylib +0 -0
  15. passagemath_linbox/.dylibs/libpng16.16.dylib +0 -0
  16. passagemath_linbox/.dylibs/libquadmath.0.dylib +0 -0
  17. passagemath_linbox/.dylibs/libz.1.3.1.dylib +0 -0
  18. passagemath_linbox/__init__.py +3 -0
  19. passagemath_linbox-10.6.43.dist-info/METADATA +100 -0
  20. passagemath_linbox-10.6.43.dist-info/RECORD +75 -0
  21. passagemath_linbox-10.6.43.dist-info/WHEEL +6 -0
  22. passagemath_linbox-10.6.43.dist-info/top_level.txt +3 -0
  23. sage/all__sagemath_linbox.py +2 -0
  24. sage/geometry/all__sagemath_linbox.py +1 -0
  25. sage/geometry/integral_points.pxi +1426 -0
  26. sage/geometry/integral_points_integer_dense.cpython-313-darwin.so +0 -0
  27. sage/geometry/integral_points_integer_dense.pyx +7 -0
  28. sage/libs/all__sagemath_linbox.py +1 -0
  29. sage/libs/iml.pxd +10 -0
  30. sage/libs/linbox/__init__.py +1 -0
  31. sage/libs/linbox/conversion.pxd +185 -0
  32. sage/libs/linbox/fflas.pxd +189 -0
  33. sage/libs/linbox/givaro.pxd +109 -0
  34. sage/libs/linbox/linbox.pxd +219 -0
  35. sage/libs/linbox/linbox_flint_interface.cpython-313-darwin.so +0 -0
  36. sage/libs/linbox/linbox_flint_interface.pxd +18 -0
  37. sage/libs/linbox/linbox_flint_interface.pyx +192 -0
  38. sage/libs/m4ri.pxd +198 -0
  39. sage/libs/m4rie.pxd +204 -0
  40. sage/matrix/all__sagemath_linbox.py +1 -0
  41. sage/matrix/matrix_cyclo_linbox.cpython-313-darwin.so +0 -0
  42. sage/matrix/matrix_cyclo_linbox.pyx +361 -0
  43. sage/matrix/matrix_gf2e_dense.cpython-313-darwin.so +0 -0
  44. sage/matrix/matrix_gf2e_dense.pxd +15 -0
  45. sage/matrix/matrix_gf2e_dense.pyx +1573 -0
  46. sage/matrix/matrix_integer_iml.cpython-313-darwin.so +0 -0
  47. sage/matrix/matrix_integer_iml.pyx +316 -0
  48. sage/matrix/matrix_integer_linbox.cpython-313-darwin.so +0 -0
  49. sage/matrix/matrix_integer_linbox.pxd +5 -0
  50. sage/matrix/matrix_integer_linbox.pyx +358 -0
  51. sage/matrix/matrix_integer_sparse_linbox.cpython-313-darwin.so +0 -0
  52. sage/matrix/matrix_integer_sparse_linbox.pyx +465 -0
  53. sage/matrix/matrix_mod2_dense.cpython-313-darwin.so +0 -0
  54. sage/matrix/matrix_mod2_dense.pxd +14 -0
  55. sage/matrix/matrix_mod2_dense.pyx +2789 -0
  56. sage/matrix/matrix_modn_dense_double.cpython-313-darwin.so +0 -0
  57. sage/matrix/matrix_modn_dense_double.pyx +179 -0
  58. sage/matrix/matrix_modn_dense_float.cpython-313-darwin.so +0 -0
  59. sage/matrix/matrix_modn_dense_float.pyx +154 -0
  60. sage/matrix/matrix_modn_sparse.cpython-313-darwin.so +0 -0
  61. sage/matrix/matrix_modn_sparse.pyx +871 -0
  62. sage/matrix/matrix_rational_linbox.cpython-313-darwin.so +0 -0
  63. sage/matrix/matrix_rational_linbox.pyx +36 -0
  64. sage/matrix/misc.cpython-313-darwin.so +0 -0
  65. sage/matrix/misc.pyx +418 -0
  66. sage/modules/all__sagemath_linbox.py +1 -0
  67. sage/modules/numpy_util.cpython-313-darwin.so +0 -0
  68. sage/modules/numpy_util.pxd +10 -0
  69. sage/modules/numpy_util.pyx +136 -0
  70. sage/modules/vector_mod2_dense.cpython-313-darwin.so +0 -0
  71. sage/modules/vector_mod2_dense.pxd +11 -0
  72. sage/modules/vector_mod2_dense.pyx +547 -0
  73. sage/rings/all__sagemath_linbox.py +1 -0
  74. sage/rings/finite_rings/all__sagemath_linbox.py +1 -0
  75. sage/rings/polynomial/all__sagemath_linbox.py +1 -0
@@ -0,0 +1,36 @@
1
+ # sage_setup: distribution = sagemath-linbox
2
+
3
+ from sage.arith.rational_reconstruction cimport mpq_rational_reconstruction
4
+ from sage.libs.flint.fmpq cimport fmpq_is_zero, fmpq_set_mpq, fmpq_canonicalise
5
+ from sage.libs.flint.fmpq_mat cimport fmpq_mat_entry_num, fmpq_mat_entry_den, fmpq_mat_entry
6
+ from sage.libs.flint.fmpz cimport fmpz_init, fmpz_clear, fmpz_set_mpz, fmpz_one, fmpz_get_mpz, fmpz_add, fmpz_mul, fmpz_sub, fmpz_mul_si, fmpz_mul_si, fmpz_mul_si, fmpz_divexact, fmpz_lcm
7
+ from sage.libs.flint.fmpz_mat cimport *
8
+ from sage.libs.gmp.mpz cimport mpz_init, mpz_clear, mpz_cmp_si
9
+ from sage.libs.gmp.mpq cimport mpq_init, mpq_clear, mpq_set_si, mpq_mul, mpq_add, mpq_set
10
+ from sage.libs.gmp.types cimport mpz_t, mpq_t
11
+ from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense
12
+ from sage.matrix.matrix_rational_dense cimport Matrix_rational_dense
13
+ from sage.matrix.matrix_integer_linbox cimport _lift_crt
14
+ from sage.rings.integer cimport Integer
15
+
16
+
17
+ def _lift_crt_rr(Matrix_rational_dense self, res, mm):
18
+ cdef Integer m
19
+ cdef Matrix_integer_dense ZA
20
+ cdef Matrix_rational_dense QA
21
+ cdef Py_ssize_t i, j
22
+ cdef mpz_t tmp
23
+ cdef mpq_t tmp2
24
+ mpz_init(tmp)
25
+ mpq_init(tmp2)
26
+ ZA = _lift_crt(res, mm)
27
+ QA = Matrix_rational_dense.__new__(Matrix_rational_dense, self.parent(), None, None, None)
28
+ m = mm.prod()
29
+ for i in range(ZA._nrows):
30
+ for j in range(ZA._ncols):
31
+ fmpz_get_mpz(tmp, fmpz_mat_entry(ZA._matrix,i,j))
32
+ mpq_rational_reconstruction(tmp2, tmp, m.value)
33
+ fmpq_set_mpq(fmpq_mat_entry(QA._matrix, i, j), tmp2)
34
+ mpz_clear(tmp)
35
+ mpq_clear(tmp2)
36
+ return QA
Binary file
sage/matrix/misc.pyx ADDED
@@ -0,0 +1,418 @@
1
+ # sage_setup: distribution = sagemath-linbox
2
+ # sage.doctest: needs sage.libs.flint
3
+ """
4
+ Misc matrix algorithms
5
+ """
6
+
7
+ from cysignals.signals cimport sig_check
8
+
9
+ from sage.arith.misc import CRT_basis, previous_prime
10
+ from sage.arith.rational_reconstruction cimport mpq_rational_reconstruction
11
+ from sage.data_structures.binary_search cimport *
12
+ from sage.ext.mod_int cimport *
13
+ from sage.libs.gmp.mpq cimport *
14
+ from sage.libs.gmp.mpz cimport *
15
+ from sage.misc.lazy_import import LazyImport
16
+ from sage.misc.verbose import verbose
17
+ from sage.modules.vector_integer_sparse cimport *
18
+ from sage.modules.vector_modn_sparse cimport *
19
+ from sage.modules.vector_rational_sparse cimport *
20
+ from sage.rings.integer cimport Integer
21
+ from sage.rings.rational_field import QQ
22
+
23
+ from sage.matrix.matrix0 cimport Matrix
24
+ from sage.matrix.matrix_integer_sparse cimport Matrix_integer_sparse
25
+ from sage.matrix.matrix_rational_sparse cimport Matrix_rational_sparse
26
+
27
+ matrix_integer_dense_rational_reconstruction = \
28
+ LazyImport('sage.matrix.misc_flint', 'matrix_integer_dense_rational_reconstruction',
29
+ deprecation=35758)
30
+ hadamard_row_bound_mpfr = \
31
+ LazyImport('sage.matrix.misc_mpfr', 'hadamard_row_bound_mpfr',
32
+ deprecation=35758)
33
+
34
+
35
+ def matrix_integer_sparse_rational_reconstruction(Matrix_integer_sparse A, Integer N):
36
+ r"""
37
+ Given a sparse matrix over the integers and an integer modulus, do
38
+ rational reconstruction on all entries of the matrix, viewed as
39
+ numbers mod `N`.
40
+
41
+ EXAMPLES::
42
+
43
+ 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)
44
+ sage: from sage.matrix.misc import matrix_integer_sparse_rational_reconstruction
45
+ sage: matrix_integer_sparse_rational_reconstruction(A, 500)
46
+ [1/3 2 3 -4]
47
+ [ 7 2 2 3]
48
+ [ 4 3 4 5/7]
49
+
50
+ TESTS:
51
+
52
+ Check that :issue:`9345` is fixed::
53
+
54
+ sage: A = random_matrix(ZZ, 3, sparse=True)
55
+ sage: sage.matrix.misc.matrix_integer_sparse_rational_reconstruction(A, 0)
56
+ Traceback (most recent call last):
57
+ ...
58
+ ZeroDivisionError: The modulus cannot be zero
59
+ """
60
+ if not N:
61
+ raise ZeroDivisionError("The modulus cannot be zero")
62
+ cdef Matrix_rational_sparse R
63
+ R = Matrix_rational_sparse.__new__(Matrix_rational_sparse,
64
+ A.parent().change_ring(QQ), 0,0,0)
65
+
66
+ cdef mpq_t t
67
+ cdef mpz_t a, bnd, other_bnd, denom
68
+ cdef Integer _bnd
69
+ cdef Py_ssize_t i, j
70
+ cdef int do_it
71
+ cdef mpz_vector* A_row
72
+ cdef mpq_vector* R_row
73
+
74
+ mpq_init(t)
75
+ mpz_init_set_si(denom, 1)
76
+ mpz_init(a)
77
+ mpz_init(other_bnd)
78
+
79
+ _bnd = (N//2).isqrt()
80
+ mpz_init_set(bnd, _bnd.value)
81
+ mpz_sub(other_bnd, N.value, bnd)
82
+
83
+ for i in range(A._nrows):
84
+ sig_check()
85
+ A_row = &A._matrix[i]
86
+ R_row = &R._matrix[i]
87
+ reallocate_mpq_vector(R_row, A_row.num_nonzero)
88
+ R_row.num_nonzero = A_row.num_nonzero
89
+ R_row.degree = A_row.degree
90
+ for j in range(A_row.num_nonzero):
91
+ sig_check()
92
+ mpz_set(a, A_row.entries[j])
93
+ if mpz_cmp_ui(denom, 1) != 0:
94
+ mpz_mul(a, a, denom)
95
+ mpz_fdiv_r(a, a, N.value)
96
+ do_it = 0
97
+ if mpz_cmp(a, bnd) <= 0:
98
+ do_it = 1
99
+ elif mpz_cmp(a, other_bnd) >= 0:
100
+ mpz_sub(a, a, N.value)
101
+ do_it = 1
102
+ if do_it:
103
+ mpz_set(mpq_numref(t), a)
104
+ if mpz_cmp_ui(denom, 1) != 0:
105
+ mpz_set(mpq_denref(t), denom)
106
+ mpq_canonicalize(t)
107
+ else:
108
+ mpz_set_si(mpq_denref(t), 1)
109
+ mpq_set(R_row.entries[j], t)
110
+ R_row.positions[j] = A_row.positions[j]
111
+ else:
112
+ # Otherwise have to do it the hard way
113
+ mpq_rational_reconstruction(t, A_row.entries[j], N.value)
114
+ mpq_set(R_row.entries[j], t)
115
+ R_row.positions[j] = A_row.positions[j]
116
+ mpz_lcm(denom, denom, mpq_denref(t))
117
+
118
+ mpq_clear(t)
119
+ mpz_clear(denom)
120
+ mpz_clear(a)
121
+ mpz_clear(other_bnd)
122
+ mpz_clear(bnd)
123
+
124
+ return R
125
+
126
+
127
+ def matrix_rational_echelon_form_multimodular(Matrix self, height_guess=None, proof=None):
128
+ """
129
+ Return reduced row-echelon form using a multi-modular
130
+ algorithm. Does not change ``self``.
131
+
132
+ REFERENCE: Chapter 7 of Stein's "Explicitly Computing Modular Forms".
133
+
134
+ INPUT:
135
+
136
+ - ``height_guess`` -- integer or ``None``
137
+ - ``proof`` -- boolean or ``None`` (default: ``None``, see
138
+ ``proof.linear_algebra`` or ``sage.structure.proof``). Note that the
139
+ global Sage default is proof=True
140
+
141
+ OUTPUT: a pair consisting of a matrix in echelon form and a tuple of pivot
142
+ positions.
143
+
144
+ ALGORITHM:
145
+
146
+ The following is a modular algorithm for computing the echelon
147
+ form. Define the height of a matrix to be the max of the
148
+ absolute values of the entries.
149
+
150
+ Given Matrix A with n columns (self).
151
+
152
+ 0. Rescale input matrix A to have integer entries. This does
153
+ not change echelon form and makes reduction modulo lots of
154
+ primes significantly easier if there were denominators.
155
+ Henceforth we assume A has integer entries.
156
+
157
+ 1. Let c be a guess for the height of the echelon form. E.g.,
158
+ c=1000, e.g., if matrix is very sparse and application is to
159
+ computing modular symbols.
160
+
161
+ 2. Let M = n * c * H(A) + 1,
162
+ where n is the number of columns of A.
163
+
164
+ 3. List primes p_1, p_2, ..., such that the product of
165
+ the p_i is at least M.
166
+
167
+ 4. Try to compute the rational reconstruction CRT echelon form
168
+ of A mod the product of the p_i. If rational
169
+ reconstruction fails, compute 1 more echelon forms mod the
170
+ next prime, and attempt again. Make sure to keep the
171
+ result of CRT on the primes from before, so we don't have
172
+ to do that computation again. Let E be this matrix.
173
+
174
+ 5. Compute the denominator d of E.
175
+ Attempt to prove that result is correct by checking that
176
+
177
+ H(d*E)*ncols(A)*H(A) < (prod of reduction primes)
178
+
179
+ where H denotes the height. If this fails, do step 4 with
180
+ a few more primes.
181
+
182
+ EXAMPLES::
183
+
184
+ sage: A = matrix(QQ, 3, 7, [1..21])
185
+ sage: from sage.matrix.misc import matrix_rational_echelon_form_multimodular
186
+ sage: E, pivots = matrix_rational_echelon_form_multimodular(A)
187
+ sage: E
188
+ [ 1 0 -1 -2 -3 -4 -5]
189
+ [ 0 1 2 3 4 5 6]
190
+ [ 0 0 0 0 0 0 0]
191
+ sage: pivots
192
+ (0, 1)
193
+
194
+ sage: A = matrix(QQ, 3, 4, [0,0] + [1..9] + [-1/2^20])
195
+ sage: E, pivots = matrix_rational_echelon_form_multimodular(A)
196
+ sage: E
197
+ [ 1 0 0 -10485761/1048576]
198
+ [ 0 1 0 27262979/4194304]
199
+ [ 0 0 1 2]
200
+ sage: pivots
201
+ (0, 1, 2)
202
+
203
+ sage: A.echelon_form()
204
+ [ 1 0 0 -10485761/1048576]
205
+ [ 0 1 0 27262979/4194304]
206
+ [ 0 0 1 2]
207
+ sage: A.pivots()
208
+ (0, 1, 2)
209
+
210
+ A small benchmark, showing that flint fraction-free multimodular algorithm
211
+ is always faster than the fraction-free multimodular algorithm implemented in Python::
212
+
213
+ sage: import copy
214
+ sage: def benchmark(num_row, num_col, entry_size, timeout=2, integer_coefficient=True):
215
+ ....: A = matrix(QQ, [[
216
+ ....: randint(1, 2^entry_size) if integer_coefficient else ZZ(randint(1, 2^entry_size))/randint(1, 2^entry_size)
217
+ ....: for col in range(num_col)] for row in range(num_row)])
218
+ ....: data=[]
219
+ ....: for algorithm in ("flint:fflu", "flint:multimodular", "padic", "multimodular"):
220
+ ....: # classical is too slow
221
+ ....: B = copy.copy(A)
222
+ ....: t = walltime()
223
+ ....: alarm(timeout)
224
+ ....: try:
225
+ ....: B.echelonize(algorithm=algorithm)
226
+ ....: except AlarmInterrupt:
227
+ ....: pass
228
+ ....: finally:
229
+ ....: cancel_alarm()
230
+ ....: data.append((round(walltime(t), 4), algorithm))
231
+ ....: return sorted(data)
232
+ sage: benchmark(20, 20, 10000) # long time
233
+ [...'flint:multimodular'...'multimodular'...'flint:fflu'...]
234
+ sage: benchmark(39, 40, 200) # long time
235
+ [...'flint:multimodular'...'flint:fflu'...'multimodular'...]
236
+
237
+ In older versions of flint
238
+ before this `issue <https://github.com/flintlib/flint/issues/2129>`_
239
+ is fixed, ``algorithm='flint'`` (automatic choice) may be slower than
240
+ ``algorithm='flint:multimodular'``.
241
+
242
+ In this case, there are more columns than rows, which means the resulting
243
+ matrix has height much higher than the input matrix. We check that the function
244
+ does not take too long::
245
+
246
+ sage: A = matrix(QQ, [[randint(1, 2^500) for col in range(40)] for row in range(20)])
247
+ sage: t = walltime()
248
+ sage: A.echelonize(algorithm="multimodular") # long time
249
+ sage: t = walltime(t) # long time
250
+ sage: (t < 10, t) # long time
251
+ (True, ...)
252
+ """
253
+ if proof is None:
254
+ from sage.structure.proof.proof import get_flag
255
+ proof = get_flag(proof, "linear_algebra")
256
+
257
+ verbose("Multimodular echelon algorithm on %s x %s matrix" % (self._nrows, self._ncols), caller_name="multimod echelon")
258
+ cdef Matrix E
259
+ if self._nrows == 0 or self._ncols == 0:
260
+ return self, ()
261
+
262
+ B, _ = self._clear_denom()
263
+
264
+ height = self.height()
265
+ if height_guess is None:
266
+ height_guess = 10000000*(height+100)
267
+ tm = verbose("height_guess = %s" % height_guess, level=2, caller_name="multimod echelon")
268
+
269
+ cdef Integer M
270
+ from sage.arith.misc import integer_floor as floor
271
+ if proof:
272
+ M = floor(max(1, self._ncols * height_guess * height + 1))
273
+ else:
274
+ M = floor(max(1, height_guess + 1))
275
+
276
+ if self.is_sparse():
277
+ from sage.matrix.matrix_modn_sparse import MAX_MODULUS
278
+ p = MAX_MODULUS + 1
279
+ else:
280
+ from sage.matrix.matrix_modn_dense_double import MAX_MODULUS
281
+ p = MAX_MODULUS + 1
282
+ t = None
283
+ X = []
284
+ best_pivots = []
285
+ prod = 1
286
+ problem = 0
287
+ lifts = {}
288
+ while True:
289
+ p = previous_prime(p)
290
+ while prod < M:
291
+ problem = problem + 1
292
+ if problem > 50:
293
+ verbose("echelon multi-modular possibly not converging?", caller_name="multimod echelon")
294
+ t = verbose("echelon modulo p=%s (%.2f%% done)" % (
295
+ p, 100*float(len(str(prod))) / len(str(M))), level=2, caller_name="multimod echelon")
296
+
297
+ # We use denoms=False, since we made self integral by calling clear_denom above.
298
+ A = B._mod_int(p)
299
+ t = verbose("time to reduce matrix mod p:",t, level=2, caller_name="multimod echelon")
300
+ A.echelonize()
301
+ t = verbose("time to put reduced matrix in echelon form:",t, level=2, caller_name="multimod echelon")
302
+
303
+ # a worthwhile check / shortcut.
304
+ if self._nrows >= self._ncols and self._nrows == len(A.pivots()):
305
+ verbose("done: the echelon form mod p is the identity matrix and possibly some 0 rows", caller_name="multimod echelon")
306
+ E = self.parent()(0)
307
+ one = self.base_ring().one()
308
+ for i in range(self._nrows):
309
+ E.set_unsafe(i, i, one)
310
+ return E, tuple(range(self._nrows))
311
+
312
+ c = cmp_pivots(best_pivots, A.pivots())
313
+ if c <= 0:
314
+ best_pivots = A.pivots()
315
+ X.append(A)
316
+ prod = prod * p
317
+ else:
318
+ # do not save A since it is bad.
319
+ verbose("Excluding this prime (bad pivots).", caller_name="multimod echelon")
320
+ t = verbose("time for pivot compare", t, level=2, caller_name="multimod echelon")
321
+ p = previous_prime(p)
322
+ # Find set of best matrices.
323
+ Y = []
324
+ # recompute product, since may drop bad matrices
325
+ prod = 1
326
+ t = verbose("now comparing pivots and dropping any bad ones", level=2, t=t, caller_name="multimod echelon")
327
+ for i in range(len(X)):
328
+ if cmp_pivots(best_pivots, X[i].pivots()) <= 0:
329
+ p = X[i].base_ring().order()
330
+ if p not in lifts:
331
+ t0 = verbose("Lifting a good matrix", level=2, caller_name="multimod echelon")
332
+ lift = X[i].lift()
333
+ lifts[p] = (lift, p)
334
+ verbose("Finished lift", level=2, caller_name="multimod echelon", t=t0)
335
+ Y.append(lifts[p])
336
+ prod = prod * X[i].base_ring().order()
337
+ verbose("finished comparing pivots", level=2, t=t, caller_name="multimod echelon")
338
+ try:
339
+ if not Y:
340
+ raise ValueError("not enough primes")
341
+ t = verbose("start crt linear combination", level=2, caller_name="multimod echelon")
342
+ a = CRT_basis([w[1] for w in Y])
343
+ t = verbose('got crt basis', level=2, t=t, caller_name="multimod echelon")
344
+
345
+ # take the linear combination of the lifts of the elements
346
+ # of Y times coefficients in a
347
+ L = a[0]*(Y[0][0])
348
+ assert Y[0][0].is_sparse() == L.is_sparse()
349
+ for j in range(1,len(Y)):
350
+ L += a[j]*(Y[j][0])
351
+ verbose("time to take linear combination of matrices over ZZ is",t, level=2, caller_name="multimod echelon")
352
+ t = verbose("now doing rational reconstruction", level=2, caller_name="multimod echelon")
353
+ E = L.rational_reconstruction(prod)
354
+ L = 0 # free memory
355
+ verbose('rational reconstruction completed', t, level=2, caller_name="multimod echelon")
356
+ except ValueError as msg:
357
+ verbose(msg, level=2)
358
+ verbose("Not enough primes to do CRT lift; redoing with several more primes.", level=2, caller_name="multimod echelon")
359
+ M <<= M.bit_length() // 5 + 1
360
+ continue
361
+
362
+ if not proof:
363
+ verbose("Not checking validity of result (since proof=False).", level=2, caller_name="multimod echelon")
364
+ break
365
+ d = E.denominator()
366
+ hdE = int((d*E).height())
367
+ if hdE * self.ncols() * height < prod:
368
+ verbose("Validity of result checked.", level=2, caller_name="multimod echelon")
369
+ break
370
+ verbose("Validity failed; trying again with more primes.", level=2, caller_name="multimod echelon")
371
+ M <<= M.bit_length() // 5 + 1
372
+ #end while
373
+ verbose("total time",tm, level=2, caller_name="multimod echelon")
374
+ return E, tuple(best_pivots)
375
+
376
+
377
+ def cmp_pivots(x, y):
378
+ r"""
379
+ Compare two sequences of pivot columns.
380
+
381
+ If `x` is shorter than `y`, return `-1`, i.e., `x < y`, "not as good".
382
+ If `x` is longer than `y`, then `x > y`, so "better" and return `+1`.
383
+ If the length is the same, then `x` is better, i.e., `x > y`
384
+ if the entries of `x` are correspondingly `\leq` those of `y` with
385
+ one being strictly less.
386
+
387
+ INPUT:
388
+
389
+ - ``x``, ``y`` -- lists or tuples of integers
390
+
391
+ EXAMPLES:
392
+
393
+ We illustrate each of the above comparisons. ::
394
+
395
+ sage: from sage.matrix.misc import cmp_pivots
396
+ sage: cmp_pivots([1,2,3], [4,5,6,7])
397
+ -1
398
+ sage: cmp_pivots([1,2,3,5], [4,5,6])
399
+ 1
400
+ sage: cmp_pivots([1,2,4], [1,2,3])
401
+ -1
402
+ sage: cmp_pivots([1,2,3], [1,2,3])
403
+ 0
404
+ sage: cmp_pivots([1,2,3], [1,2,4])
405
+ 1
406
+ """
407
+ x = tuple(x)
408
+ y = tuple(y)
409
+ if len(x) < len(y):
410
+ return -1
411
+ if len(x) > len(y):
412
+ return 1
413
+ if x < y:
414
+ return 1
415
+ elif x == y:
416
+ return 0
417
+ else:
418
+ return -1
@@ -0,0 +1 @@
1
+ # sage_setup: distribution = sagemath-linbox
@@ -0,0 +1,10 @@
1
+ # sage_setup: distribution = sagemath-linbox
2
+ from libc.stdint cimport uintptr_t
3
+ from sage.libs.m4ri cimport *
4
+ from sage.matrix.matrix_mod2_dense cimport Matrix_mod2_dense
5
+
6
+ cpdef int set_matrix_mod2_from_numpy(Matrix_mod2_dense a, b) except -1
7
+
8
+ cpdef int set_mzd_from_numpy(uintptr_t entries_addr, Py_ssize_t degree, x) except -1
9
+ # Note: we don't actually need ``cimport`` to work, which means this header file is not used in practice
10
+ # neither do we need ``cpdef`` (``def`` is sufficient)
@@ -0,0 +1,136 @@
1
+ # sage_setup: distribution = sagemath-linbox
2
+ # sage.doctest: optional - numpy
3
+ # cython: fast_getattr=False
4
+ # https://github.com/cython/cython/issues/6442
5
+ r"""
6
+ Utility functions for numpy.
7
+ """
8
+
9
+ cimport numpy as np
10
+ import numpy as np
11
+
12
+
13
+ ctypedef fused numpy_integral:
14
+ np.int8_t
15
+ np.int32_t
16
+ np.int64_t
17
+
18
+
19
+ cdef set_mzd_from_numpy_unsafe(mzd_t* entries, np.ndarray[numpy_integral, ndim=1] x):
20
+ """
21
+ Internal function.
22
+ Caller are responsible for checking the two arrays have the same length.
23
+ """
24
+ for i in range(len(x)):
25
+ mzd_write_bit(entries, 0, i, x[i] & 1)
26
+
27
+
28
+ cpdef int set_mzd_from_numpy(uintptr_t entries_addr, Py_ssize_t degree, x) except -1:
29
+ """
30
+ Set the entries in ``<mzd_t*>entries_addr`` from numpy array ``x``.
31
+
32
+ INPUT:
33
+
34
+ - ``entries_addr`` -- must be a ``mzd_t*`` casted to ``uintptr_t``; the casting
35
+ is necessary to pass it through Python boundary because of lazy import.
36
+ Do not pass arbitrary integer value here, will crash the program.
37
+
38
+ - ``degree`` -- the length of the array
39
+
40
+ - ``x`` -- a numpy array of integers or booleans, or any other object (in which
41
+ case this function will return ``False``)
42
+
43
+ OUTPUT: ``True`` if successful, ``False`` otherwise. May throw ``ValueError``.
44
+ """
45
+ cdef Py_ssize_t i
46
+ cdef np.ndarray[np.npy_bool, ndim=1] x_bool
47
+ cdef mzd_t* entries = <mzd_t*>entries_addr
48
+ if isinstance(x, np.ndarray):
49
+ if x.ndim != 1:
50
+ raise ValueError("numpy array must have dimension 1")
51
+ if x.shape[0] != degree:
52
+ raise ValueError("numpy array must have the right length")
53
+ if x.dtype == np.int8:
54
+ set_mzd_from_numpy_unsafe(entries, <np.ndarray[np.int8_t, ndim=1]>x)
55
+ return True
56
+ if x.dtype == np.int32:
57
+ set_mzd_from_numpy_unsafe(entries, <np.ndarray[np.int32_t, ndim=1]>x)
58
+ return True
59
+ if x.dtype == np.int64:
60
+ set_mzd_from_numpy_unsafe(entries, <np.ndarray[np.int64_t, ndim=1]>x)
61
+ return True
62
+ if x.dtype == np.bool_:
63
+ x_bool = x
64
+ for i in range(degree):
65
+ mzd_write_bit(entries, 0, i, x_bool[i])
66
+ return True
67
+ return False
68
+
69
+
70
+ cpdef int _set_matrix_mod2_from_numpy_helper(Matrix_mod2_dense a, np.ndarray[numpy_integral, ndim=2] b) except -1:
71
+ """
72
+ Internal function, helper for :func:`set_matrix_mod2_from_numpy`.
73
+
74
+ TESTS::
75
+
76
+ sage: from sage.modules.numpy_util import _set_matrix_mod2_from_numpy_helper
77
+ sage: import numpy as np
78
+ sage: a = matrix(GF(2), 2, 3)
79
+ sage: b = np.array([[1, 0, 1], [0, 1, 0]], dtype=np.int8)
80
+ sage: _set_matrix_mod2_from_numpy_helper(a, b)
81
+ 1
82
+ sage: a
83
+ [1 0 1]
84
+ [0 1 0]
85
+ sage: _set_matrix_mod2_from_numpy_helper(a, np.array([[1, 0], [0, 1]], dtype=np.int8))
86
+ Traceback (most recent call last):
87
+ ...
88
+ ValueError: shape mismatch
89
+ """
90
+ if not (a.nrows() == b.shape[0] and a.ncols() == b.shape[1]):
91
+ raise ValueError("shape mismatch")
92
+ for i in range(b.shape[0]):
93
+ for j in range(b.shape[1]):
94
+ a.set_unsafe_int(i, j, b[i, j] & 1)
95
+ return True
96
+
97
+
98
+ cpdef int set_matrix_mod2_from_numpy(Matrix_mod2_dense a, b) except -1:
99
+ """
100
+ Try to set the entries of a matrix from a numpy array.
101
+
102
+ INPUT:
103
+
104
+ - ``a`` -- the destination matrix
105
+ - ``b`` -- a numpy array, must have dimension 2 and the same shape as ``a``
106
+
107
+ OUTPUT: ``True`` (when used as bool) if successful, ``False`` otherwise. May throw ``ValueError``.
108
+
109
+ The exact type of the return value is not guaranteed, in the actual current implementation
110
+ it is ``1`` for success and ``0`` for failure.
111
+
112
+ TESTS::
113
+
114
+ sage: from sage.modules.numpy_util import set_matrix_mod2_from_numpy
115
+ sage: import numpy as np
116
+ sage: a = matrix(GF(2), 2, 3)
117
+ sage: b = np.array([[1, 0, 1], [0, 1, 0]], dtype=np.int8)
118
+ sage: set_matrix_mod2_from_numpy(a, b)
119
+ 1
120
+ sage: a
121
+ [1 0 1]
122
+ [0 1 0]
123
+ sage: set_matrix_mod2_from_numpy(a, np.array([[1, 0], [0, 1]], dtype=np.int8))
124
+ Traceback (most recent call last):
125
+ ...
126
+ ValueError: shape mismatch
127
+ sage: # unsupported type (may be supported in the future)
128
+ sage: set_matrix_mod2_from_numpy(a, np.array([[1, 1, 0], [0, 1, 0]], dtype=np.float64))
129
+ 0
130
+ sage: set_matrix_mod2_from_numpy(a, np.array([1, 0, 0], dtype=np.int8)) # wrong number of dimensions
131
+ 0
132
+ """
133
+ try:
134
+ return (<object>_set_matrix_mod2_from_numpy_helper)(a, b) # https://github.com/cython/cython/issues/6588
135
+ except TypeError:
136
+ return False
@@ -0,0 +1,11 @@
1
+ # sage_setup: distribution = sagemath-linbox
2
+ from sage.modules.free_module_element cimport FreeModuleElement
3
+ from sage.libs.m4ri cimport mzd_t
4
+
5
+
6
+ cdef class Vector_mod2_dense(FreeModuleElement):
7
+ cdef mzd_t* _entries
8
+ cdef object _base_ring
9
+
10
+ cdef _new_c(self)
11
+ cdef _init(self, Py_ssize_t degree, parent)