passagemath-modules 10.5.46__cp310-cp310-macosx_14_0_arm64.whl → 10.6.20__cp310-cp310-macosx_14_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.

Potentially problematic release.


This version of passagemath-modules might be problematic. Click here for more details.

Files changed (320) hide show
  1. {passagemath_modules-10.5.46.dist-info → passagemath_modules-10.6.20.dist-info}/METADATA +49 -44
  2. {passagemath_modules-10.5.46.dist-info → passagemath_modules-10.6.20.dist-info}/RECORD +320 -314
  3. passagemath_modules.dylibs/libmpc.3.dylib +0 -0
  4. passagemath_modules.dylibs/libopenblasp-r0.3.29.dylib +0 -0
  5. sage/algebras/clifford_algebra.py +2 -2
  6. sage/algebras/clifford_algebra_element.cpython-310-darwin.so +0 -0
  7. sage/algebras/clifford_algebra_element.pyx +4 -2
  8. sage/algebras/exterior_algebra_groebner.cpython-310-darwin.so +0 -0
  9. sage/algebras/exterior_algebra_groebner.pyx +2 -0
  10. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +83 -5
  11. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-310-darwin.so +0 -0
  12. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +2 -0
  13. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +28 -3
  14. sage/algebras/finite_gca.py +1 -1
  15. sage/algebras/lie_algebras/bgg_dual_module.py +18 -11
  16. sage/algebras/lie_algebras/classical_lie_algebra.py +3 -3
  17. sage/algebras/lie_algebras/examples.py +2 -2
  18. sage/algebras/lie_algebras/free_lie_algebra.py +1 -1
  19. sage/algebras/lie_algebras/heisenberg.py +4 -4
  20. sage/algebras/lie_algebras/lie_algebra.py +1 -1
  21. sage/algebras/lie_algebras/lie_algebra_element.cpython-310-darwin.so +0 -0
  22. sage/algebras/lie_algebras/lie_algebra_element.pyx +63 -27
  23. sage/algebras/lie_algebras/quotient.py +40 -29
  24. sage/algebras/lie_algebras/subalgebra.py +76 -53
  25. sage/algebras/lie_algebras/verma_module.py +1 -3
  26. sage/algebras/octonion_algebra.cpython-310-darwin.so +0 -0
  27. sage/algebras/octonion_algebra.pyx +1 -1
  28. sage/algebras/orlik_solomon.py +4 -4
  29. sage/algebras/orlik_terao.py +4 -4
  30. sage/algebras/steenrod/steenrod_algebra.py +37 -30
  31. sage/algebras/steenrod/steenrod_algebra_bases.py +2 -2
  32. sage/algebras/steenrod/steenrod_algebra_misc.py +4 -4
  33. sage/algebras/steenrod/steenrod_algebra_mult.py +2 -2
  34. sage/all__sagemath_modules.py +1 -0
  35. sage/calculus/integration.cpython-310-darwin.so +0 -0
  36. sage/calculus/integration.pyx +6 -5
  37. sage/calculus/interpolation.cpython-310-darwin.so +0 -0
  38. sage/calculus/interpolators.cpython-310-darwin.so +0 -0
  39. sage/calculus/ode.cpython-310-darwin.so +0 -0
  40. sage/calculus/ode.pxd +2 -2
  41. sage/calculus/ode.pyx +6 -4
  42. sage/calculus/riemann.cpython-310-darwin.so +0 -0
  43. sage/calculus/riemann.pyx +68 -48
  44. sage/calculus/transforms/dwt.cpython-310-darwin.so +0 -0
  45. sage/calculus/transforms/fft.cpython-310-darwin.so +0 -0
  46. sage/coding/ag_code_decoders.cpython-310-darwin.so +0 -0
  47. sage/coding/ag_code_decoders.pyx +31 -31
  48. sage/coding/binary_code.cpython-310-darwin.so +0 -0
  49. sage/coding/binary_code.pxd +6 -6
  50. sage/coding/binary_code.pyx +212 -173
  51. sage/coding/guruswami_sudan/utils.py +3 -5
  52. sage/coding/kasami_codes.cpython-310-darwin.so +0 -0
  53. sage/coding/kasami_codes.pyx +20 -24
  54. sage/coding/linear_code.py +2 -2
  55. sage/coding/linear_code_no_metric.py +5 -5
  56. sage/coding/linear_rank_metric.py +81 -19
  57. sage/combinat/free_module.py +22 -2
  58. sage/combinat/root_system/ambient_space.py +1 -1
  59. sage/combinat/root_system/associahedron.py +4 -4
  60. sage/combinat/root_system/braid_move_calculator.py +1 -1
  61. sage/combinat/root_system/braid_orbit.cpython-310-darwin.so +0 -0
  62. sage/combinat/root_system/branching_rules.py +2 -2
  63. sage/combinat/root_system/cartan_type.py +14 -14
  64. sage/combinat/root_system/coxeter_group.py +2 -2
  65. sage/combinat/root_system/coxeter_type.py +11 -0
  66. sage/combinat/root_system/extended_affine_weyl_group.py +8 -8
  67. sage/combinat/root_system/fundamental_group.py +2 -4
  68. sage/combinat/root_system/hecke_algebra_representation.py +1 -1
  69. sage/combinat/root_system/pieri_factors.py +2 -2
  70. sage/combinat/root_system/root_lattice_realization_algebras.py +1 -1
  71. sage/combinat/root_system/root_lattice_realizations.py +1 -1
  72. sage/combinat/root_system/type_folded.py +3 -3
  73. sage/combinat/root_system/type_reducible.py +8 -7
  74. sage/combinat/root_system/type_super_A.py +2 -2
  75. sage/combinat/root_system/weight_lattice_realizations.py +9 -8
  76. sage/combinat/root_system/weyl_characters.py +1 -1
  77. sage/crypto/__init__.py +1 -0
  78. sage/crypto/block_cipher/des.py +1 -1
  79. sage/crypto/block_cipher/miniaes.py +3 -3
  80. sage/crypto/block_cipher/present.py +3 -3
  81. sage/crypto/block_cipher/sdes.py +3 -3
  82. sage/crypto/boolean_function.cpython-310-darwin.so +0 -0
  83. sage/crypto/boolean_function.pyx +22 -23
  84. sage/crypto/key_exchange/diffie_hellman.py +4 -9
  85. sage/crypto/mq/sr.py +1 -1
  86. sage/crypto/public_key/blum_goldwasser.py +3 -3
  87. sage/crypto/sbox.cpython-310-darwin.so +0 -0
  88. sage/crypto/sbox.pyx +1 -1
  89. sage/crypto/sboxes.py +22 -0
  90. sage/crypto/util.py +4 -6
  91. sage/ext/interpreters/__init__.py +1 -1
  92. sage/ext/interpreters/all__sagemath_modules.py +1 -1
  93. sage/ext/interpreters/wrapper_cc.cpython-310-darwin.so +0 -0
  94. sage/ext/interpreters/wrapper_cc.pxd +5 -5
  95. sage/ext/interpreters/wrapper_cc.pyx +1 -1
  96. sage/ext/interpreters/wrapper_cdf.cpython-310-darwin.so +0 -0
  97. sage/ext/interpreters/wrapper_cdf.pxd +5 -7
  98. sage/ext/interpreters/wrapper_cdf.pyx +4 -10
  99. sage/ext/interpreters/wrapper_rdf.cpython-310-darwin.so +0 -0
  100. sage/ext/interpreters/wrapper_rdf.pxd +1 -1
  101. sage/ext/interpreters/wrapper_rdf.pyx +1 -1
  102. sage/ext/interpreters/wrapper_rr.cpython-310-darwin.so +0 -0
  103. sage/ext/interpreters/wrapper_rr.pxd +5 -5
  104. sage/ext/interpreters/wrapper_rr.pyx +1 -2
  105. sage/geometry/toric_lattice.py +3 -3
  106. sage/geometry/toric_lattice_element.cpython-310-darwin.so +0 -0
  107. sage/groups/additive_abelian/additive_abelian_group.py +1 -1
  108. sage/groups/additive_abelian/qmodnz.py +4 -4
  109. sage/groups/matrix_gps/coxeter_group.py +17 -4
  110. sage/groups/matrix_gps/group_element.cpython-310-darwin.so +0 -0
  111. sage/groups/misc_gps/argument_groups.py +2 -2
  112. sage/groups/misc_gps/imaginary_groups.py +4 -4
  113. sage/groups/perm_gps/partn_ref/refinement_binary.cpython-310-darwin.so +0 -0
  114. sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-310-darwin.so +0 -0
  115. sage/homology/chain_complex.py +0 -2
  116. sage/homology/hochschild_complex.py +3 -3
  117. sage/homology/homology_morphism.py +6 -6
  118. sage/homology/homology_vector_space_with_basis.py +1 -1
  119. sage/libs/gsl/array.cpython-310-darwin.so +0 -0
  120. sage/libs/mpmath/utils.cpython-310-darwin.so +0 -0
  121. sage/matrix/action.cpython-310-darwin.so +0 -0
  122. sage/matrix/args.cpython-310-darwin.so +0 -0
  123. sage/matrix/args.pyx +25 -10
  124. sage/matrix/benchmark.py +8 -4
  125. sage/matrix/compute_J_ideal.py +2 -2
  126. sage/matrix/constructor.cpython-310-darwin.so +0 -0
  127. sage/matrix/echelon_matrix.cpython-310-darwin.so +0 -0
  128. sage/matrix/echelon_matrix.pyx +1 -1
  129. sage/matrix/matrix0.cpython-310-darwin.so +0 -0
  130. sage/matrix/matrix0.pxd +3 -3
  131. sage/matrix/matrix0.pyx +7 -5
  132. sage/matrix/matrix1.cpython-310-darwin.so +0 -0
  133. sage/matrix/matrix1.pyx +87 -48
  134. sage/matrix/matrix2.cpython-310-darwin.so +0 -0
  135. sage/matrix/matrix2.pxd +3 -3
  136. sage/matrix/matrix2.pyx +758 -75
  137. sage/matrix/matrix_cdv.cpython-310-darwin.so +0 -0
  138. sage/matrix/matrix_complex_double_dense.cpython-310-darwin.so +0 -0
  139. sage/matrix/matrix_complex_double_dense.pyx +1 -1
  140. sage/matrix/matrix_dense.cpython-310-darwin.so +0 -0
  141. sage/matrix/matrix_dense.pyx +2 -3
  142. sage/matrix/matrix_double_dense.cpython-310-darwin.so +0 -0
  143. sage/matrix/matrix_double_dense.pyx +11 -5
  144. sage/matrix/matrix_double_sparse.cpython-310-darwin.so +0 -0
  145. sage/matrix/matrix_generic_dense.cpython-310-darwin.so +0 -0
  146. sage/matrix/matrix_generic_sparse.cpython-310-darwin.so +0 -0
  147. sage/matrix/matrix_generic_sparse.pyx +1 -1
  148. sage/matrix/matrix_laurent_mpolynomial_dense.cpython-310-darwin.so +0 -0
  149. sage/matrix/matrix_numpy_dense.cpython-310-darwin.so +0 -0
  150. sage/matrix/matrix_numpy_integer_dense.cpython-310-darwin.so +0 -0
  151. sage/matrix/matrix_polynomial_dense.cpython-310-darwin.so +0 -0
  152. sage/matrix/matrix_polynomial_dense.pyx +952 -261
  153. sage/matrix/matrix_real_double_dense.cpython-310-darwin.so +0 -0
  154. sage/matrix/matrix_sparse.cpython-310-darwin.so +0 -0
  155. sage/matrix/matrix_sparse.pyx +2 -3
  156. sage/matrix/matrix_window.cpython-310-darwin.so +0 -0
  157. sage/matrix/matrix_window.pyx +2 -2
  158. sage/matrix/misc_mpfr.cpython-310-darwin.so +0 -0
  159. sage/matrix/operation_table.py +0 -2
  160. sage/matrix/special.py +4 -0
  161. sage/matrix/strassen.cpython-310-darwin.so +0 -0
  162. sage/matrix/strassen.pyx +1 -1
  163. sage/matroids/basis_exchange_matroid.cpython-310-darwin.so +0 -0
  164. sage/matroids/basis_matroid.cpython-310-darwin.so +0 -0
  165. sage/matroids/chow_ring.py +68 -65
  166. sage/matroids/chow_ring_ideal.py +41 -38
  167. sage/matroids/circuit_closures_matroid.cpython-310-darwin.so +0 -0
  168. sage/matroids/circuits_matroid.cpython-310-darwin.so +0 -0
  169. sage/matroids/database_matroids.py +16 -5
  170. sage/matroids/dual_matroid.py +2 -2
  171. sage/matroids/extension.cpython-310-darwin.so +0 -0
  172. sage/matroids/flats_matroid.cpython-310-darwin.so +0 -0
  173. sage/matroids/gammoid.py +1 -1
  174. sage/matroids/graphic_matroid.cpython-310-darwin.so +0 -0
  175. sage/matroids/graphic_matroid.pyx +3 -3
  176. sage/matroids/lean_matrix.cpython-310-darwin.so +0 -0
  177. sage/matroids/lean_matrix.pyx +22 -22
  178. sage/matroids/linear_matroid.cpython-310-darwin.so +0 -0
  179. sage/matroids/linear_matroid.pyx +13 -13
  180. sage/matroids/matroid.cpython-310-darwin.so +0 -0
  181. sage/matroids/matroid.pyx +15 -15
  182. sage/matroids/matroids_plot_helpers.py +48 -46
  183. sage/matroids/minor_matroid.py +2 -2
  184. sage/matroids/set_system.cpython-310-darwin.so +0 -0
  185. sage/matroids/transversal_matroid.cpython-310-darwin.so +0 -0
  186. sage/matroids/transversal_matroid.pyx +3 -3
  187. sage/matroids/union_matroid.cpython-310-darwin.so +0 -0
  188. sage/matroids/union_matroid.pyx +3 -0
  189. sage/matroids/unpickling.cpython-310-darwin.so +0 -0
  190. sage/matroids/utilities.py +2 -2
  191. sage/misc/c3.cpython-310-darwin.so +0 -0
  192. sage/misc/compat.py +1 -2
  193. sage/misc/pickle_old.cpython-310-darwin.so +0 -0
  194. sage/modules/diamond_cutting.py +117 -30
  195. sage/modules/fg_pid/fgp_module.py +3 -3
  196. sage/modules/filtered_vector_space.py +4 -4
  197. sage/modules/finite_submodule_iter.cpython-310-darwin.so +0 -0
  198. sage/modules/fp_graded/free_module.py +2 -2
  199. sage/modules/fp_graded/module.py +2 -2
  200. sage/modules/fp_graded/morphism.py +4 -4
  201. sage/modules/fp_graded/steenrod/morphism.py +1 -1
  202. sage/modules/free_module.py +144 -15
  203. sage/modules/free_module_element.cpython-310-darwin.so +0 -0
  204. sage/modules/free_module_element.pyx +4 -4
  205. sage/modules/free_module_integer.py +2 -2
  206. sage/modules/free_module_morphism.py +3 -3
  207. sage/modules/free_module_pseudohomspace.py +352 -0
  208. sage/modules/free_module_pseudomorphism.py +578 -0
  209. sage/modules/free_quadratic_module_integer_symmetric.py +24 -13
  210. sage/modules/matrix_morphism.py +9 -9
  211. sage/modules/multi_filtered_vector_space.py +4 -4
  212. sage/modules/ore_module.py +2208 -0
  213. sage/modules/ore_module_element.py +178 -0
  214. sage/modules/ore_module_homspace.py +147 -0
  215. sage/modules/ore_module_morphism.py +968 -0
  216. sage/modules/quotient_module.py +11 -1
  217. sage/modules/submodule.py +1 -1
  218. sage/modules/torsion_quadratic_module.py +1 -1
  219. sage/modules/vector_complex_double_dense.cpython-310-darwin.so +0 -0
  220. sage/modules/vector_double_dense.cpython-310-darwin.so +0 -0
  221. sage/modules/vector_integer_dense.cpython-310-darwin.so +0 -0
  222. sage/modules/vector_integer_sparse.cpython-310-darwin.so +0 -0
  223. sage/modules/vector_integer_sparse.pyx +4 -4
  224. sage/modules/vector_modn_dense.cpython-310-darwin.so +0 -0
  225. sage/modules/vector_modn_sparse.cpython-310-darwin.so +0 -0
  226. sage/modules/vector_numpy_dense.cpython-310-darwin.so +0 -0
  227. sage/modules/vector_numpy_integer_dense.cpython-310-darwin.so +0 -0
  228. sage/modules/vector_rational_dense.cpython-310-darwin.so +0 -0
  229. sage/modules/vector_rational_dense.pyx +1 -1
  230. sage/modules/vector_rational_sparse.cpython-310-darwin.so +0 -0
  231. sage/modules/vector_rational_sparse.pyx +5 -5
  232. sage/modules/vector_real_double_dense.cpython-310-darwin.so +0 -0
  233. sage/modules/vector_space_morphism.py +2 -2
  234. sage/modules/with_basis/cell_module.py +17 -0
  235. sage/modules/with_basis/indexed_element.cpython-310-darwin.so +0 -0
  236. sage/modules/with_basis/indexed_element.pyx +1 -1
  237. sage/modules/with_basis/invariant.py +1 -1
  238. sage/modules/with_basis/representation.py +0 -1
  239. sage/modules/with_basis/subquotient.py +2 -2
  240. sage/numerical/gauss_legendre.cpython-310-darwin.so +0 -0
  241. sage/probability/probability_distribution.cpython-310-darwin.so +0 -0
  242. sage/quadratic_forms/binary_qf.py +7 -7
  243. sage/quadratic_forms/bqf_class_group.py +26 -92
  244. sage/quadratic_forms/count_local_2.cpython-310-darwin.so +0 -0
  245. sage/quadratic_forms/extras.py +1 -1
  246. sage/quadratic_forms/quadratic_form.py +5 -4
  247. sage/quadratic_forms/quadratic_form__equivalence_testing.py +7 -4
  248. sage/quadratic_forms/quadratic_form__evaluate.cpython-310-darwin.so +0 -0
  249. sage/quadratic_forms/quadratic_form__local_field_invariants.py +10 -10
  250. sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +2 -2
  251. sage/quadratic_forms/ternary.cpython-310-darwin.so +0 -0
  252. sage/quadratic_forms/ternary_qf.py +50 -83
  253. sage/rings/complex_conversion.cpython-310-darwin.so +0 -0
  254. sage/rings/complex_double.cpython-310-darwin.so +0 -0
  255. sage/rings/complex_double.pxd +1 -0
  256. sage/rings/complex_double.pyx +37 -32
  257. sage/rings/complex_mpc.cpython-310-darwin.so +0 -0
  258. sage/rings/complex_mpc.pyx +27 -23
  259. sage/rings/complex_mpfr.cpython-310-darwin.so +0 -0
  260. sage/rings/complex_mpfr.pyx +11 -9
  261. sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +277 -21
  262. sage/rings/function_field/drinfeld_modules/drinfeld_module.py +10 -1
  263. sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1 -1
  264. sage/rings/function_field/drinfeld_modules/homset.py +1 -2
  265. sage/rings/function_field/drinfeld_modules/morphism.py +2 -2
  266. sage/rings/function_field/hermite_form_polynomial.cpython-310-darwin.so +0 -0
  267. sage/rings/function_field/khuri_makdisi.cpython-310-darwin.so +0 -0
  268. sage/rings/function_field/khuri_makdisi.pyx +27 -25
  269. sage/rings/invariants/invariant_theory.py +61 -60
  270. sage/rings/invariants/reconstruction.py +8 -8
  271. sage/rings/polynomial/laurent_polynomial_mpair.cpython-310-darwin.so +0 -0
  272. sage/rings/polynomial/ore_function_element.py +1 -1
  273. sage/rings/polynomial/ore_polynomial_element.cpython-310-darwin.so +0 -0
  274. sage/rings/polynomial/ore_polynomial_element.pyx +8 -8
  275. sage/rings/polynomial/ore_polynomial_ring.py +134 -17
  276. sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-310-darwin.so +0 -0
  277. sage/rings/polynomial/skew_polynomial_element.cpython-310-darwin.so +0 -0
  278. sage/rings/polynomial/skew_polynomial_finite_field.cpython-310-darwin.so +0 -0
  279. sage/rings/polynomial/skew_polynomial_finite_field.pyx +3 -4
  280. sage/rings/polynomial/skew_polynomial_finite_order.cpython-310-darwin.so +0 -0
  281. sage/rings/polynomial/skew_polynomial_finite_order.pyx +2 -5
  282. sage/rings/real_double_element_gsl.cpython-310-darwin.so +0 -0
  283. sage/rings/real_mpfr.cpython-310-darwin.so +0 -0
  284. sage/rings/real_mpfr.pyx +25 -7
  285. sage/rings/ring_extension.cpython-310-darwin.so +0 -0
  286. sage/rings/ring_extension.pyx +4 -2
  287. sage/rings/ring_extension_conversion.cpython-310-darwin.so +0 -0
  288. sage/rings/ring_extension_element.cpython-310-darwin.so +0 -0
  289. sage/rings/ring_extension_element.pyx +42 -0
  290. sage/rings/ring_extension_morphism.cpython-310-darwin.so +0 -0
  291. sage/schemes/projective/cohomology.py +2 -2
  292. sage/stats/basic_stats.py +9 -6
  293. sage/stats/distributions/dgs_misc.h +11 -4
  294. sage/stats/distributions/discrete_gaussian_integer.cpython-310-darwin.so +0 -0
  295. sage/stats/distributions/discrete_gaussian_integer.pyx +9 -7
  296. sage/stats/hmm/chmm.cpython-310-darwin.so +0 -0
  297. sage/stats/hmm/chmm.pyx +13 -13
  298. sage/stats/hmm/distributions.cpython-310-darwin.so +0 -0
  299. sage/stats/hmm/distributions.pxd +3 -3
  300. sage/stats/hmm/distributions.pyx +3 -3
  301. sage/stats/hmm/hmm.cpython-310-darwin.so +0 -0
  302. sage/stats/hmm/hmm.pxd +3 -3
  303. sage/stats/hmm/hmm.pyx +6 -6
  304. sage/stats/hmm/util.cpython-310-darwin.so +0 -0
  305. sage/stats/hmm/util.pyx +6 -6
  306. sage/stats/intlist.cpython-310-darwin.so +0 -0
  307. sage/stats/intlist.pxd +3 -3
  308. sage/stats/time_series.cpython-310-darwin.so +0 -0
  309. sage/tensor/modules/alternating_contr_tensor.py +3 -3
  310. sage/tensor/modules/comp.py +3 -3
  311. sage/tensor/modules/ext_pow_free_module.py +3 -3
  312. sage/tensor/modules/format_utilities.py +3 -3
  313. sage/tensor/modules/free_module_linear_group.py +3 -3
  314. sage/tensor/modules/free_module_morphism.py +0 -1
  315. sage/tensor/modules/tensor_free_module.py +3 -3
  316. sage/tensor/modules/tensor_free_submodule.py +1 -1
  317. sage/tensor/modules/tensor_free_submodule_basis.py +1 -1
  318. sage/tensor/modules/tensor_with_indices.py +5 -5
  319. {passagemath_modules-10.5.46.dist-info → passagemath_modules-10.6.20.dist-info}/WHEEL +0 -0
  320. {passagemath_modules-10.5.46.dist-info → passagemath_modules-10.6.20.dist-info}/top_level.txt +0 -0
sage/matrix/matrix2.pyx CHANGED
@@ -1545,13 +1545,11 @@ cdef class Matrix(Matrix1):
1545
1545
  m = self._nrows
1546
1546
  n = self._ncols
1547
1547
  if not m <= n:
1548
- raise ValueError("must have m <= n, but m (=%s) and n (=%s)"%(m, n))
1548
+ raise ValueError(f"must have m <= n, but m (={m}) and n (={n})")
1549
1549
 
1550
1550
  for r from 1 <= r < m+1:
1551
1551
  lst = _choose(n, r)
1552
- tmp = []
1553
- for cols in lst:
1554
- tmp.append(self.prod_of_row_sums(cols))
1552
+ tmp = [self.prod_of_row_sums(cols) for cols in lst]
1555
1553
  s = sum(tmp)
1556
1554
  # sn = (-1)^(m-r)
1557
1555
  if (m - r) % 2 == 0:
@@ -1889,7 +1887,7 @@ cdef class Matrix(Matrix1):
1889
1887
 
1890
1888
  The number of derangements of length `n` is the permanent
1891
1889
  of a matrix with 0 on the diagonal and 1 elsewhere;
1892
- for `n=21` it is `18795307255050944540` (see :oeis:`A000166`):
1890
+ for `n=21` it is `18795307255050944540` (see :oeis:`A000166`)::
1893
1891
 
1894
1892
  sage: A = identity_matrix(21)
1895
1893
  sage: A.rook_vector(complement=True)[-1]
@@ -3291,6 +3289,16 @@ cdef class Matrix(Matrix1):
3291
3289
  sage: A._charpoly_df()
3292
3290
  x^3 + 8*x^2 + 10*x + 1
3293
3291
 
3292
+ .. NOTE::
3293
+
3294
+ The key feature of this implementation is that it is division-free.
3295
+ This means that it can be used as a generic implementation for any
3296
+ ring (commutative and with multiplicative identity). The algorithm
3297
+ is described in full detail as Algorithm 3.1 in [Sei2002]_.
3298
+
3299
+ Note that there is a missing minus sign in front of the last term in
3300
+ the penultimate line of Algorithm 3.1.
3301
+
3294
3302
  TESTS::
3295
3303
 
3296
3304
  sage: A = matrix(ZZ, 0, 0)
@@ -3309,15 +3317,11 @@ cdef class Matrix(Matrix1):
3309
3317
  sage: matrix(4, 4, lambda i, j: R.an_element())._charpoly_df() # needs sage.combinat
3310
3318
  B[1]*x^4 - 4*B[u]*x^3
3311
3319
 
3312
- .. NOTE::
3320
+ Test that the function is interruptible::
3313
3321
 
3314
- The key feature of this implementation is that it is division-free.
3315
- This means that it can be used as a generic implementation for any
3316
- ring (commutative and with multiplicative identity). The algorithm
3317
- is described in full detail as Algorithm 3.1 in [Sei2002]_.
3318
-
3319
- Note that there is a missing minus sign in front of the last term in
3320
- the penultimate line of Algorithm 3.1.
3322
+ sage: m = matrix.random(RR, 128)
3323
+ sage: from sage.doctest.util import ensure_interruptible_after
3324
+ sage: with ensure_interruptible_after(1): m.charpoly()
3321
3325
  """
3322
3326
 
3323
3327
  # Validate assertions
@@ -3374,6 +3378,7 @@ cdef class Matrix(Matrix1):
3374
3378
  for j in range(t+1):
3375
3379
  s = s + M.get_unsafe(i, j) * a.get_unsafe(p-1, j)
3376
3380
  a.set_unsafe(p, i, s)
3381
+ sig_check()
3377
3382
 
3378
3383
  # Set A[p, t] to be the (t)th entry in a[p, t]
3379
3384
  A[p] = a.get_unsafe(p, t)
@@ -3480,10 +3485,17 @@ cdef class Matrix(Matrix1):
3480
3485
  raise TypeError("lcm function not defined for elements of the base ring")
3481
3486
  return d
3482
3487
 
3483
- def diagonal(self):
3488
+ def diagonal(self, offset=0):
3484
3489
  r"""
3485
3490
  Return the diagonal entries of ``self``.
3486
3491
 
3492
+ INPUT:
3493
+
3494
+ - ``offset`` -- integer (default: ``0``); parameter pointing diagonal
3495
+ parallel to the main diagonal. The main diagonal is the one with
3496
+ offset 0. The diagonals above have positive offsets and the diagonals
3497
+ below have negative offsets.
3498
+
3487
3499
  OUTPUT:
3488
3500
 
3489
3501
  A list containing the entries of the matrix that
@@ -3506,6 +3518,16 @@ cdef class Matrix(Matrix1):
3506
3518
  [14 15 16 17 18 19 20]
3507
3519
  sage: B.diagonal()
3508
3520
  [0, 8, 16]
3521
+ sage: B.diagonal(1)
3522
+ [1, 9, 17]
3523
+ sage: B.diagonal(-1)
3524
+ [7, 15]
3525
+ sage: B.diagonal(-2)
3526
+ [14]
3527
+ sage: B.diagonal(100) # when idx out of range
3528
+ []
3529
+ sage: B.diagonal(-100)
3530
+ []
3509
3531
 
3510
3532
  sage: C = matrix(3, 2, range(6)); C
3511
3533
  [0 1]
@@ -3513,6 +3535,10 @@ cdef class Matrix(Matrix1):
3513
3535
  [4 5]
3514
3536
  sage: C.diagonal()
3515
3537
  [0, 3]
3538
+ sage: C.diagonal(-1)
3539
+ [2, 5]
3540
+ sage: C.diagonal(1)
3541
+ [1]
3516
3542
 
3517
3543
  Empty matrices behave properly. ::
3518
3544
 
@@ -3521,8 +3547,11 @@ cdef class Matrix(Matrix1):
3521
3547
  sage: E.diagonal()
3522
3548
  []
3523
3549
  """
3524
- n = min(self.nrows(), self.ncols())
3525
- return [self[i, i] for i in range(n)]
3550
+ if offset >= 0:
3551
+ n = min(self.nrows(), self.ncols() - offset)
3552
+ return [self[i, i + offset] for i in range(n)]
3553
+ n = min(self.nrows() + offset, self.ncols())
3554
+ return [self[i - offset, i] for i in range(n)]
3526
3555
 
3527
3556
  def trace(self):
3528
3557
  """
@@ -3579,6 +3608,42 @@ cdef class Matrix(Matrix1):
3579
3608
  s += self.get_unsafe(i, j) * other.get_unsafe(j, i)
3580
3609
  return s
3581
3610
 
3611
+ def get_bandwidth(self):
3612
+ """
3613
+ Return the bandwidth of ``self``, which is the maximum `i` such that
3614
+ the `i` superdiagonal or subdiagonal contains a nonzero entry.
3615
+
3616
+ EXAMPLES::
3617
+
3618
+ sage: A = matrix([[1,0,0],[0,1,0],[0,0,1]]); A
3619
+ [1 0 0]
3620
+ [0 1 0]
3621
+ [0 0 1]
3622
+ sage: A.get_bandwidth()
3623
+ 0
3624
+
3625
+ sage: B = matrix([[1,2,3],[0,4,5],[0,0,6]]); B
3626
+ [1 2 3]
3627
+ [0 4 5]
3628
+ [0 0 6]
3629
+ sage: B.get_bandwidth()
3630
+ 2
3631
+
3632
+ sage: C = matrix(3, 2, range(6)); C
3633
+ [0 1]
3634
+ [2 3]
3635
+ [4 5]
3636
+ sage: C.get_bandwidth()
3637
+ 2
3638
+ """
3639
+ cdef Py_ssize_t i
3640
+ diag_range = max(self.nrows(), self.ncols()) - 1
3641
+
3642
+ for i in range(diag_range, 0, -1):
3643
+ if any(self.diagonal(i)) or any(self.diagonal(-i)):
3644
+ return ZZ(i)
3645
+ return ZZ.zero()
3646
+
3582
3647
  #####################################################################################
3583
3648
  # Generic Hessenberg Form and charpoly algorithm
3584
3649
  #####################################################################################
@@ -3615,7 +3680,7 @@ cdef class Matrix(Matrix1):
3615
3680
  H = self.change_ring(K)
3616
3681
  H.hessenbergize()
3617
3682
  except TypeError as msg:
3618
- raise TypeError("%s\nHessenberg form only possible for matrices over a field"%msg)
3683
+ raise TypeError("%s\nHessenberg form only possible for matrices over a field" % msg)
3619
3684
  else:
3620
3685
  H = self.__copy__()
3621
3686
  H.hessenbergize()
@@ -4596,6 +4661,7 @@ cdef class Matrix(Matrix1):
4596
4661
  The "usual" quaternions are a non-commutative ring and computations
4597
4662
  of kernels over these rings are not implemented. ::
4598
4663
 
4664
+ sage: # needs sage.libs.singular
4599
4665
  sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1)
4600
4666
  sage: A = matrix(Q, 2, [i,j,-1,k])
4601
4667
  sage: A.right_kernel_matrix()
@@ -5046,6 +5112,7 @@ cdef class Matrix(Matrix1):
5046
5112
  Matrices over non-commutative rings are not a good idea either.
5047
5113
  These are the "usual" quaternions. ::
5048
5114
 
5115
+ sage: # needs sage.libs.singular
5049
5116
  sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1)
5050
5117
  sage: A = matrix(Q, 2, [i,j,-1,k])
5051
5118
  sage: A.right_kernel()
@@ -5690,7 +5757,7 @@ cdef class Matrix(Matrix1):
5690
5757
  return X, Y
5691
5758
  return X
5692
5759
  else:
5693
- raise ValueError("no algorithm '%s'"%algorithm)
5760
+ raise ValueError("no algorithm '%s'" % algorithm)
5694
5761
 
5695
5762
  def _decomposition_spin_generic(self, is_diagonalizable=False):
5696
5763
  r"""
@@ -5753,14 +5820,16 @@ cdef class Matrix(Matrix1):
5753
5820
  v = h.list()
5754
5821
 
5755
5822
  while len(S) < tries:
5756
- t = verbose('%s-spinning %s-th random vector'%(num_iterates, len(S)), level=2, caller_name='generic spin decomp')
5823
+ t = verbose('%s-spinning %s-th random vector' % (num_iterates, len(S)),
5824
+ level=2, caller_name='generic spin decomp')
5757
5825
  S.append(self.iterates(V.random_element(), num_iterates))
5758
- verbose('done spinning', level=2, t=t, caller_name='generic spin decomp')
5826
+ verbose('done spinning',
5827
+ level=2, t=t, caller_name='generic spin decomp')
5759
5828
 
5760
5829
  for j in range(0 if W is None else W.nrows() // g.degree(), len(S)):
5761
5830
  # Compute one element of the kernel of g(A)**m.
5762
- t = verbose('compute element of kernel of g(A), for g of degree %s'%g.degree(), level=2,
5763
- caller_name='generic spin decomp')
5831
+ t = verbose('compute element of kernel of g(A), for g of degree %s' % g.degree(),
5832
+ level=2, caller_name='generic spin decomp')
5764
5833
  w = S[j].linear_combination_of_rows(h.list())
5765
5834
  t = verbose('done computing element of kernel of g(A)', t=t, level=2, caller_name='generic spin decomp')
5766
5835
 
@@ -5779,7 +5848,7 @@ cdef class Matrix(Matrix1):
5779
5848
  verbose('computed row space', level=2, t=t, caller_name='generic spin decomp')
5780
5849
  break
5781
5850
  else:
5782
- verbose('we have not yet generated all the kernel (rank so far=%s, target rank=%s)'%(
5851
+ verbose('we have not yet generated all the kernel (rank so far=%s, target rank=%s)' % (
5783
5852
  W.rank(), m*g.degree()), level=2, caller_name='generic spin decomp')
5784
5853
  tries += 1
5785
5854
  if tries > 1000*m: # avoid an insanely long infinite loop
@@ -5815,12 +5884,13 @@ cdef class Matrix(Matrix1):
5815
5884
  return decomp_seq([(V, m==1)])
5816
5885
  F.sort()
5817
5886
  for g, m in f.factor():
5818
- t = verbose('decomposition -- Computing g(self) for an irreducible factor g of degree %s'%g.degree(), level=2)
5887
+ t = verbose('decomposition -- Computing g(self) for an irreducible factor g of degree %s' % g.degree(), level=2)
5819
5888
  if is_diagonalizable:
5820
5889
  B = g(self)
5821
5890
  else:
5822
5891
  B = g(self)
5823
- t2 = verbose('decomposition -- raising g(self) to the power %s'%m, level=2)
5892
+ t2 = verbose('decomposition -- raising g(self) to the power %s' % m,
5893
+ level=2)
5824
5894
  B = B ** m
5825
5895
  verbose('done powering', level=2, t=t2)
5826
5896
  t = verbose('decomposition -- done computing g(self)', level=2, t=t)
@@ -5911,7 +5981,7 @@ cdef class Matrix(Matrix1):
5911
5981
  if not self.is_square():
5912
5982
  raise ArithmeticError("self must be a square matrix")
5913
5983
  if M.base_ring() != self.base_ring():
5914
- raise ArithmeticError("base rings must be the same, but self is over %s and module is over %s"%(
5984
+ raise ArithmeticError("base rings must be the same, but self is over %s and module is over %s" % (
5915
5985
  self.base_ring(), M.base_ring()))
5916
5986
  if M.degree() != self.ncols():
5917
5987
  raise ArithmeticError("M must be a subspace of an %s-dimensional space" % self.ncols())
@@ -5928,7 +5998,7 @@ cdef class Matrix(Matrix1):
5928
5998
  sum_dim = sum([A.dimension() for A, _ in D])
5929
5999
  assert sum_dim == M.dimension(), \
5930
6000
  "bug in decomposition; " + \
5931
- "the sum of the dimensions (=%s) of the factors must equal the dimension (%s) of the acted on space:\nFactors found: %s\nSpace: %s"%(sum_dim, M.dimension(), D, M)
6001
+ "the sum of the dimensions (=%s) of the factors must equal the dimension (%s) of the acted on space:\nFactors found: %s\nSpace: %s" % (sum_dim, M.dimension(), D, M)
5932
6002
 
5933
6003
  # 3. Lift decomposition to subspaces of ambient vector space.
5934
6004
  # Each basis vector for an element of D defines a linear
@@ -6475,12 +6545,22 @@ cdef class Matrix(Matrix1):
6475
6545
  matrices with symbolic entries. ::
6476
6546
 
6477
6547
  sage: A = matrix(QQ, 3, 3, range(9))
6478
- sage: A.change_ring(RR).eigenspaces_left()
6479
- Traceback (most recent call last):
6480
- ...
6481
- NotImplementedError: eigenspaces cannot be computed reliably
6482
- for inexact rings such as Real Field with 53 bits of precision,
6548
+ sage: A.change_ring(RR).eigenspaces_left() # needs sage.rings.number_field
6549
+ doctest:warning...
6550
+ UserWarning: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
6483
6551
  consult numerical or symbolic matrix classes for other options
6552
+ [(13.3484692283495,
6553
+ Vector space of degree 3 and dimension 0 over Real Field with 53 bits of precision
6554
+ User basis matrix:
6555
+ []),
6556
+ (-0.000000000000000,
6557
+ Vector space of degree 3 and dimension 1 over Real Field with 53 bits of precision
6558
+ User basis matrix:
6559
+ [ 1.00000000000000 -2.00000000000000 1.00000000000000]),
6560
+ (-1.34846922834953,
6561
+ Vector space of degree 3 and dimension 0 over Real Field with 53 bits of precision
6562
+ User basis matrix:
6563
+ [])]
6484
6564
 
6485
6565
  sage: # needs scipy
6486
6566
  sage: em = A.change_ring(RDF).eigenmatrix_left()
@@ -6556,9 +6636,10 @@ cdef class Matrix(Matrix1):
6556
6636
  msg = 'matrix must be square, not {0} x {1}'
6557
6637
  raise TypeError(msg.format(self.nrows(), self.ncols()))
6558
6638
  if not self.base_ring().is_exact():
6639
+ from warnings import warn
6559
6640
  msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n",
6560
6641
  "consult numerical or symbolic matrix classes for other options")
6561
- raise NotImplementedError(''.join(msg).format(self.base_ring()))
6642
+ warn(''.join(msg).format(self.base_ring()))
6562
6643
 
6563
6644
  format = self._eigenspace_format(format)
6564
6645
 
@@ -6830,13 +6911,21 @@ cdef class Matrix(Matrix1):
6830
6911
 
6831
6912
  right_eigenspaces = eigenspaces_right
6832
6913
 
6833
- def eigenvalues(self, extend=True):
6914
+ def eigenvalues(self, extend=True, algorithm=None) -> Sequence:
6834
6915
  r"""
6835
6916
  Return a sequence of the eigenvalues of a matrix, with
6836
6917
  multiplicity. If the eigenvalues are roots of polynomials in ``QQ``,
6837
6918
  then ``QQbar`` elements are returned that represent each separate
6838
6919
  root.
6839
6920
 
6921
+ INPUT:
6922
+
6923
+ - ``extend`` -- (default: ``True``); see below
6924
+ - ``algorithm`` -- (default: ``None``); algorithm to use,
6925
+ supported values are ``'sage'``, ``'flint'``, ``'mpmath'``, ``'pari'``
6926
+ (passed to :meth:`eigenvectors_left`), or ``'pari_charpoly'``; if ``None``,
6927
+ the algorithm is chosen automatically
6928
+
6840
6929
  If the option ``extend`` is set to ``False``, only eigenvalues in the base
6841
6930
  ring are considered.
6842
6931
 
@@ -6927,6 +7016,96 @@ cdef class Matrix(Matrix1):
6927
7016
  From: Finite Field in z3 of size 3^3
6928
7017
  To: Algebraic closure of Finite Field of size 3
6929
7018
  Defn: z3 |--> z3)
7019
+
7020
+ TESTS::
7021
+
7022
+ sage: import warnings
7023
+ sage: warnings.simplefilter("always")
7024
+ sage: m = matrix(RR, [[0, 1], [-2, 0]])
7025
+
7026
+ Test different algorithms::
7027
+
7028
+ sage: m.eigenvalues(algorithm="sage") # needs sage.libs.pari
7029
+ doctest:warning...
7030
+ UserWarning: Using generic algorithm for an inexact ring,
7031
+ which will probably give incorrect results due to numerical precision issues.
7032
+ [-1.41421356237310*I, 1.41421356237310*I]
7033
+ sage: m.eigenvalues(algorithm="flint") # needs sage.libs.flint
7034
+ doctest:warning...
7035
+ FutureWarning: This class/method/function is marked as experimental.
7036
+ It, its functionality or its interface might change without a formal deprecation.
7037
+ See https://github.com/sagemath/sage/issues/30393 for details.
7038
+ [-1.41421356237309*I, 1.41421356237310*I]
7039
+ sage: m.eigenvalues(algorithm="mpmath") # abs tol 1e-14
7040
+ [-1.41421356237309*I, 1.41421356237309*I]
7041
+ sage: m.eigenvalues(algorithm="pari") # abs tol 1e-14 # needs sage.libs.pari
7042
+ [-1.4142135623730950487637880730318329370*I,
7043
+ 1.4142135623730950487637880730318329370*I]
7044
+ sage: m.eigenvalues(algorithm="pari_charpoly") # abs tol 1e-14 # needs sage.libs.pari
7045
+ [-1.41421356237309505*I, 1.41421356237309505*I]
7046
+ sage: m.eigenvalues()
7047
+ [-1.41421356237309505*I, 1.41421356237309505*I]
7048
+ sage: type(m.eigenvalues())
7049
+ <class 'sage.structure.sequence.Sequence_generic'>
7050
+ """
7051
+ if algorithm is None:
7052
+ from sage.rings.abc import RealField, ComplexField
7053
+ R = self.base_ring()
7054
+ if isinstance(R, (RealField, ComplexField)):
7055
+ algorithm = "pari_charpoly"
7056
+ else:
7057
+ algorithm = "sage"
7058
+ if algorithm == "sage":
7059
+ return self._eigenvalues_sage(extend=extend)
7060
+ elif algorithm == "pari_charpoly":
7061
+ from sage.libs.pari import pari
7062
+ return Sequence(pari(self).charpoly().polroots().sage())
7063
+ else:
7064
+ return self._eigenvectors_result_to_eigenvalues(
7065
+ self._eigenvectors_left(
7066
+ extend=extend, algorithm=algorithm,
7067
+ suppress_future_warning=False))
7068
+
7069
+ def _eigenvectors_result_to_eigenvalues(self, eigenvectors: list) -> Sequence:
7070
+ """
7071
+ Convert the result of :meth:`eigenvectors_left` to a sequence of eigenvalues
7072
+ suitable to be returned by :meth:`eigenvalues`.
7073
+
7074
+ INPUT:
7075
+
7076
+ - ``eigenvectors`` -- a list of tuples of the form ``(e,V,n)``
7077
+ as returned by :meth:`eigenvectors_left`
7078
+
7079
+ OUTPUT: a :class:`Sequence` of eigenvalues
7080
+
7081
+ TESTS::
7082
+
7083
+ sage: # needs sage.rings.number_field
7084
+ sage: A = matrix(QQ, [[1, 2], [3, 4]])
7085
+ sage: l = A.eigenvectors_left(); l
7086
+ [(-0.3722813232690144?, [(1, -0.4574271077563382?)], 1),
7087
+ (5.372281323269015?, [(1, 1.457427107756339?)], 1)]
7088
+ sage: A._eigenvectors_result_to_eigenvalues(l)
7089
+ [-0.3722813232690144?, 5.372281323269015?]
7090
+ """
7091
+ return Sequence([e for e, _, _ in eigenvectors])
7092
+
7093
+ def _eigenvalues_sage(self, extend=True) -> Sequence:
7094
+ """
7095
+ Compute the eigenvalues of a matrix using algorithm implemented in Sage.
7096
+
7097
+ INPUT:
7098
+
7099
+ - ``extend`` -- boolean (default: ``True``)
7100
+
7101
+ TESTS::
7102
+
7103
+ sage: # needs sage.rings.number_field
7104
+ sage: A = matrix(QQ, [[1, 2], [3, 4]])
7105
+ sage: A.eigenvalues(algorithm="sage") # indirect doctest
7106
+ [-0.3722813232690144?, 5.372281323269015?]
7107
+ sage: A._eigenvalues_sage()
7108
+ [-0.3722813232690144?, 5.372281323269015?]
6930
7109
  """
6931
7110
  x = self.fetch('eigenvalues')
6932
7111
  if x is not None:
@@ -6966,7 +7145,7 @@ cdef class Matrix(Matrix1):
6966
7145
  self.cache('eigenvalues', eigenvalues)
6967
7146
  return eigenvalues
6968
7147
 
6969
- def eigenvectors_left(self, other=None, *, extend=True):
7148
+ def eigenvectors_left(self, other=None, *, extend=True, algorithm=None) -> list:
6970
7149
  r"""
6971
7150
  Compute the left eigenvectors of a matrix.
6972
7151
 
@@ -6979,14 +7158,25 @@ cdef class Matrix(Matrix1):
6979
7158
 
6980
7159
  - ``extend`` -- boolean (default: ``True``)
6981
7160
 
7161
+ - ``algorithm`` -- string (default: ``None``); if ``None``, then it is
7162
+ chosen automatically; options are:
7163
+
7164
+ * ``'sage'``
7165
+ * ``'flint'``
7166
+ * ``'mpmath'``
7167
+ * ``'pari'``
7168
+ * ``'scipy'`` - only supported for matrices over :class:`RDF <sage.rings.real_double.RealDoubleField_class>`
7169
+ and :class:`CDF <sage.rings.complex_double.ComplexDoubleField_class>`
7170
+
6982
7171
  OUTPUT:
6983
7172
 
6984
- For each distinct eigenvalue, returns a list of the form (e,V,n)
6985
- where e is the eigenvalue, V is a list of eigenvectors forming a
6986
- basis for the corresponding left eigenspace, and n is the algebraic
7173
+ Returns a list of tuples of the form ``(e,V,n)``,
7174
+ each tuple corresponds to a distinct eigenvalue,
7175
+ where ``e`` is the eigenvalue, ``V`` is a list of eigenvectors forming a
7176
+ basis for the corresponding left eigenspace, and ``n`` is the algebraic
6987
7177
  multiplicity of the eigenvalue.
6988
7178
 
6989
- If the option extend is set to False, then only the eigenvalues that
7179
+ If the option ``extend`` is set to ``False``, then only the eigenvalues that
6990
7180
  live in the base ring are considered.
6991
7181
 
6992
7182
  EXAMPLES:
@@ -7042,6 +7232,22 @@ cdef class Matrix(Matrix1):
7042
7232
  sage: K.<i> = QuadraticField(-1)
7043
7233
  sage: m = matrix(K, 4, [2,4*i,-i,0, -4*i,2,-1,0, 2*i,-2,0,0, 4*i+4, 4*i-4,1-i,-2])
7044
7234
  sage: assert all(m*v == e*v for e, vs, _ in m.eigenvectors_right() for v in vs)
7235
+
7236
+ The following currently uses ``algorithm="flint"`` under the hood,
7237
+ but ``FutureWarning`` must not be raised. This is because the internal
7238
+ implementation may change in the future to keep the external interface.
7239
+
7240
+ ::
7241
+
7242
+ sage: # needs sage.libs.flint
7243
+ sage: import warnings
7244
+ sage: warnings.simplefilter("always")
7245
+ sage: m = matrix(RR, [[0, 1], [-2, 0]])
7246
+ sage: m.eigenvectors_left()
7247
+ [(-1.41421356237309*I, [(-0.816496580927726, -0.577350269189626*I)], 1),
7248
+ (1.41421356237310*I, [(-0.866025403784438*I, -0.612372435695794)], 1)]
7249
+ sage: m.eigenvectors_left(extend=False)
7250
+ []
7045
7251
  """
7046
7252
  if other is not None:
7047
7253
  if isinstance(other, bool):
@@ -7057,15 +7263,77 @@ cdef class Matrix(Matrix1):
7057
7263
  'for RDF and CDF, but not for %s'
7058
7264
  % self.base_ring())
7059
7265
 
7060
- x = self.fetch('eigenvectors_left')
7061
- if x is not None:
7062
- return x
7266
+ if algorithm is None:
7267
+ R = self.base_ring()
7268
+ from sage.rings.abc import RealField, ComplexField
7269
+ if isinstance(R, (RealField, ComplexField)):
7270
+ return self._eigenvectors_left(
7271
+ other, extend=extend, algorithm='flint', suppress_future_warning=True)
7272
+ else:
7273
+ algorithm = 'sage'
7274
+ return self._eigenvectors_left(
7275
+ other, extend=extend, algorithm=algorithm, suppress_future_warning=False)
7276
+
7277
+ def _eigenvectors_left(self, other=None, *, extend: bool, algorithm: str,
7278
+ suppress_future_warning: bool) -> list:
7279
+ """
7280
+ Do the same thing as :meth:`eigenvectors_left`, but ``algorithm``
7281
+ cannot be ``None``, and ``suppress_future_warning`` is provided
7282
+ to suppress the ``FutureWarning`` raised by the flint method.
7063
7283
 
7284
+ TESTS::
7285
+
7286
+ sage: # needs sage.libs.flint
7287
+ sage: m = matrix(RR, [[0, 1], [-2, 0]])
7288
+ sage: m._eigenvectors_left(extend=False, algorithm="flint", suppress_future_warning=True)
7289
+ []
7290
+ """
7291
+ if algorithm == 'sage':
7292
+ return self._eigenvectors_left_sage(extend=extend)
7293
+ elif algorithm == 'flint':
7294
+ return self._fix_eigenvectors_extend(self._eigenvectors_left_flint(suppress_future_warning), extend)
7295
+ elif algorithm == 'mpmath':
7296
+ return self._fix_eigenvectors_extend(self._eigenvectors_left_mpmath(), extend)
7297
+ elif algorithm == 'pari':
7298
+ return self._fix_eigenvectors_extend(self._eigenvectors_left_pari(), extend)
7299
+ else:
7300
+ raise ValueError('algorithm value not recognized')
7301
+
7302
+ def _eigenvectors_left_sage(self, *, extend=True) -> list:
7303
+ """
7304
+ Compute the left eigenvectors of a matrix
7305
+ using a generic algorithm implemented in Sage.
7306
+
7307
+ INPUT:
7308
+
7309
+ - ``extend`` -- boolean (default: ``True``)
7310
+
7311
+ OUTPUT:
7312
+
7313
+ See :meth:`eigenvectors_left`.
7314
+
7315
+ TESTS::
7316
+
7317
+ sage: # needs sage.rings.number_field
7318
+ sage: import warnings
7319
+ sage: warnings.simplefilter("always")
7320
+ sage: m = matrix(RR, [[0, 1], [-2, 0]])
7321
+ sage: m.eigenvectors_left(algorithm="sage")
7322
+ doctest:warning...
7323
+ UserWarning: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
7324
+ consult numerical or symbolic matrix classes for other options
7325
+ [(-1.41421356237310*I, [(1.00000000000000, 0.707106781186548*I)], 1),
7326
+ (1.41421356237310*I, [(1.00000000000000, -0.707106781186548*I)], 1)]
7327
+ sage: m.eigenvectors_left(algorithm="sage", extend=False)
7328
+ doctest:warning...
7329
+ UserWarning: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
7330
+ consult numerical or symbolic matrix classes for other options
7331
+ []
7332
+ """
7064
7333
  if not self.base_ring().is_exact():
7065
7334
  from warnings import warn
7066
7335
  warn("Using generic algorithm for an inexact ring, which may result in garbage from numerical precision issues.")
7067
7336
 
7068
- from sage.categories.homset import hom
7069
7337
  eigenspaces = self.eigenspaces_left(format='galois', algebraic_multiplicity=True)
7070
7338
  evec_list = []
7071
7339
  n = self._nrows
@@ -7079,20 +7347,169 @@ cdef class Matrix(Matrix1):
7079
7347
  if eigval.parent().fraction_field() == F:
7080
7348
  evec_eval_list.append((eigval, eigbasis, eigmult))
7081
7349
  else:
7082
- try:
7083
- from sage.rings.qqbar import QQbar
7084
- eigval_conj = eigval.galois_conjugates(QQbar)
7085
- except AttributeError:
7086
- raise NotImplementedError("eigenvectors are not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar")
7350
+ from sage.categories.homset import Hom
7351
+ from sage.rings.abc import RealField
7352
+ if isinstance(self.base_ring(), RealField):
7353
+ # then eigval is an element of RR[x]/f(x)
7354
+ # find all morphism of that ring into CC
7355
+ f = eigval.parent().modulus()
7356
+ rs = f.roots(self.base_ring().complex_field(), multiplicities=False)
7357
+ g = eigval.lift()
7358
+ eigval_conj = [g(r) for r in rs]
7359
+ else:
7360
+ try:
7361
+ from sage.rings.qqbar import QQbar
7362
+ eigval_conj = eigval.galois_conjugates(QQbar)
7363
+ except AttributeError:
7364
+ raise NotImplementedError("eigenvectors are not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar")
7087
7365
 
7088
7366
  for e in eigval_conj:
7089
- m = hom(eigval.parent(), e.parent(), e)
7367
+ m = Hom(eigval.parent(), e.parent())(e, check=False)
7368
+ # check=False because the base_ring may not be exact
7090
7369
  space = (e.parent())**n
7091
7370
  evec_list = [(space)([m(i) for i in v]) for v in eigbasis]
7092
7371
  evec_eval_list.append((e, evec_list, eigmult))
7093
7372
 
7094
7373
  return evec_eval_list
7095
7374
 
7375
+ def _fix_eigenvectors_extend(self, eigenvectors: list, extend: bool) -> list:
7376
+ """
7377
+ Fix the eigenvectors if the extend option is set to ``False``.
7378
+
7379
+ INPUT:
7380
+
7381
+ - ``eigenvectors`` -- a list of tuples of the form ``(e,V,n)``
7382
+ as returned by :meth:`eigenvectors_left`
7383
+ - ``extend`` -- boolean
7384
+
7385
+ OUTPUT:
7386
+
7387
+ If ``extend`` is ``True``, return ``eigenvectors`` unchanged.
7388
+ Otherwise, return a new list with only the eigenvalues that live in the base ring.
7389
+
7390
+ TESTS::
7391
+
7392
+ sage: m = matrix(RR, [[0, 1], [-2, 0]])
7393
+ sage: l = m.eigenvectors_left(algorithm="pari"); l # abs tol 1e-14 # needs sage.libs.pari
7394
+ [(-1.4142135623730950487637880730318329370*I,
7395
+ [(0.707106781186547524*I, 1.00000000000000000)],
7396
+ 1),
7397
+ (1.4142135623730950487637880730318329370*I,
7398
+ [(-0.707106781186547524*I, 1.00000000000000000)],
7399
+ 1)]
7400
+ sage: m._fix_eigenvectors_extend(l, extend=True) # abs tol 1e-14 # needs sage.libs.pari
7401
+ [(-1.4142135623730950487637880730318329370*I,
7402
+ [(0.707106781186547524*I, 1.00000000000000000)],
7403
+ 1),
7404
+ (1.4142135623730950487637880730318329370*I,
7405
+ [(-0.707106781186547524*I, 1.00000000000000000)],
7406
+ 1)]
7407
+ sage: m._fix_eigenvectors_extend(l, extend=False) # needs sage.libs.pari
7408
+ []
7409
+ """
7410
+ if extend:
7411
+ return eigenvectors
7412
+ R = self.base_ring()
7413
+ try:
7414
+ if R.algebraic_closure() is R:
7415
+ return eigenvectors
7416
+ except (AttributeError, NotImplementedError):
7417
+ pass
7418
+ return [(e, V, n) for e, V, n in eigenvectors if e in R]
7419
+
7420
+ def _eigenvectors_left_flint(self, suppress_future_warning: bool) -> list:
7421
+ """
7422
+ Compute the left eigenvectors of a matrix
7423
+ using the FLINT library.
7424
+
7425
+ Only works for matrices over ``RealField`` or ``ComplexField``.
7426
+
7427
+ INPUT:
7428
+
7429
+ - ``suppress_future_warning`` -- boolean; whether to suppress
7430
+ the ``FutureWarning``
7431
+
7432
+ OUTPUT:
7433
+
7434
+ See :meth:`eigenvectors_left`.
7435
+
7436
+ TESTS:
7437
+
7438
+ This method is supposed to raise a ``FutureWarning`` but
7439
+ the implementation in :class:`sage.misc.superseded.experimental`
7440
+ only raises the warning at most once, because of doctest ordering
7441
+ the warning is not seen below. See :issue:`39811`. ::
7442
+
7443
+ sage: # needs sage.libs.flint
7444
+ sage: m = matrix(RR, [[0, 1], [-2, 0]])
7445
+ sage: m.eigenvectors_left(algorithm="flint") # indirect doctest
7446
+ [(-1.41421356237309*I, [(-0.816496580927726, -0.577350269189626*I)], 1),
7447
+ (1.41421356237310*I, [(-0.866025403784438*I, -0.612372435695794)], 1)]
7448
+ sage: m.eigenvectors_left(algorithm="flint", extend=False)
7449
+ []
7450
+ """
7451
+ if suppress_future_warning:
7452
+ import warnings
7453
+ with warnings.catch_warnings():
7454
+ warnings.simplefilter("ignore", category=FutureWarning)
7455
+ result = self._eigenvectors_left_flint(False)
7456
+ return result
7457
+ from sage.rings.complex_arb import ComplexBallField
7458
+ from sage.rings.complex_mpfr import ComplexField
7459
+ C = ComplexField(self.base_ring().precision())
7460
+ return [(C(e), [v.change_ring(C) for v in V], n) for e, V, n in
7461
+ self.change_ring(ComplexBallField(self.base_ring().precision())).eigenvectors_left()]
7462
+
7463
+ def _eigenvectors_left_mpmath(self) -> list:
7464
+ """
7465
+ Compute the left eigenvectors of a matrix
7466
+ using ``mpmath``.
7467
+
7468
+ Only works for matrices over ``RealField`` or ``ComplexField``.
7469
+
7470
+ sage: m = matrix(RR, [[0, 1], [-2, 0]])
7471
+ sage: m.eigenvectors_left(algorithm="mpmath")
7472
+ [(-1.41421356237309*I, [(-0.866025403784439, -0.612372435695794*I)], 1),
7473
+ (1.41421356237309*I, [(-0.816496580927726*I, -0.577350269189626)], 1)]
7474
+ sage: m.eigenvectors_left(algorithm="mpmath", extend=False)
7475
+ []
7476
+ """
7477
+ from mpmath import mp
7478
+ eigenvalues, eigenvectors = mp.eig(self._mpmath_(), left=True, right=False)
7479
+ from sage.rings.complex_mpfr import ComplexField
7480
+ C = ComplexField(self.base_ring().precision())
7481
+ from sage.modules.free_module_element import vector
7482
+ return [
7483
+ (C(e), [vector(C, V)], 1)
7484
+ for e, V in zip(eigenvalues, eigenvectors.tolist())
7485
+ ]
7486
+
7487
+ def _eigenvectors_left_pari(self) -> list:
7488
+ """
7489
+ Compute the left eigenvectors of a matrix
7490
+ using the PARI library.
7491
+
7492
+ Only works for matrices over ``RealField`` or ``ComplexField``.
7493
+
7494
+ sage: # needs sage.libs.pari
7495
+ sage: m = matrix(RR, [[0, 1], [-2, 0]])
7496
+ sage: m.eigenvectors_left(algorithm="pari") # abs tol 1e-14
7497
+ [(-1.4142135623730950487637880730318329370*I,
7498
+ [(0.707106781186547524*I, 1.00000000000000000)],
7499
+ 1),
7500
+ (1.4142135623730950487637880730318329370*I,
7501
+ [(-0.707106781186547524*I, 1.00000000000000000)],
7502
+ 1)]
7503
+ sage: m.eigenvectors_left(algorithm="pari", extend=False)
7504
+ []
7505
+ """
7506
+ from sage.libs.pari import pari
7507
+ eigenvalues, eigenvectors = pari(self).mateigen(flag=1, precision=self.base_ring().precision()).sage()
7508
+ return [
7509
+ (e, [V], 1)
7510
+ for e, V in zip(eigenvalues, eigenvectors.columns())
7511
+ ]
7512
+
7096
7513
  left_eigenvectors = eigenvectors_left
7097
7514
 
7098
7515
  def eigenvectors_right(self, other=None, *, extend=True):
@@ -7780,7 +8197,7 @@ cdef class Matrix(Matrix1):
7780
8197
  try:
7781
8198
  a, d, p = self._echelon_form_PID()
7782
8199
  except TypeError as msg:
7783
- raise NotImplementedError("%s\nechelon form over %s not yet implemented"%(msg, self.base_ring()))
8200
+ raise NotImplementedError("%s\nechelon form over %s not yet implemented" % (msg, self.base_ring()))
7784
8201
 
7785
8202
  for c from 0 <= c < self.ncols():
7786
8203
  for r from 0 <= r < self.nrows():
@@ -7984,7 +8401,7 @@ cdef class Matrix(Matrix1):
7984
8401
  kwds['algorithm'] = algorithm
7985
8402
  return self._echelonize_ring(**kwds)
7986
8403
  except ArithmeticError as msg:
7987
- raise NotImplementedError("%s\nEchelon form not implemented over '%s'."%(msg, basring))
8404
+ raise NotImplementedError("%s\nEchelon form not implemented over '%s'." % (msg, basring))
7988
8405
 
7989
8406
  def echelon_form(self, algorithm='default', cutoff=0, **kwds):
7990
8407
  r"""
@@ -8970,7 +9387,8 @@ cdef class Matrix(Matrix1):
8970
9387
  [ 0 0 0 0]
8971
9388
  [ 0 0 0 0]
8972
9389
  """
8973
- tm = verbose('strassen echelon of %s x %s matrix'%(self._nrows, self._ncols), level=2)
9390
+ tm = verbose('strassen echelon of %s x %s matrix' % (self._nrows, self._ncols),
9391
+ level=2)
8974
9392
 
8975
9393
  self.check_mutability()
8976
9394
 
@@ -9248,7 +9666,7 @@ cdef class Matrix(Matrix1):
9248
9666
  """
9249
9667
  if self._subdivisions is None:
9250
9668
  self._subdivisions = ([0, self._nrows], [0, self._ncols])
9251
- key = "subdivision %s %s"%(i, j)
9669
+ key = "subdivision %s %s" % (i, j)
9252
9670
  sd = self.fetch(key)
9253
9671
  if sd is None:
9254
9672
  sd = self[self._subdivisions[0][i]:self._subdivisions[0][i+1],
@@ -9296,10 +9714,10 @@ cdef class Matrix(Matrix1):
9296
9714
  if not i and not j:
9297
9715
  return self[x, y]
9298
9716
  else:
9299
- raise IndexError("No such submatrix %s, %s"%(i, j))
9717
+ raise IndexError("No such submatrix %s, %s" % (i, j))
9300
9718
  if x >= self._subdivisions[0][i+1]-self._subdivisions[0][i] or \
9301
9719
  y >= self._subdivisions[1][j+1]-self._subdivisions[1][j]:
9302
- raise IndexError("Submatrix %s,%s has no entry %s,%s"%(i, j, x, y))
9720
+ raise IndexError("Submatrix %s,%s has no entry %s,%s" % (i, j, x, y))
9303
9721
  return self[self._subdivisions[0][i] + x, self._subdivisions[1][j] + y]
9304
9722
 
9305
9723
  def _subdivide_on_augment(self, left, right):
@@ -10246,7 +10664,7 @@ cdef class Matrix(Matrix1):
10246
10664
  sage: a.density()
10247
10665
  0
10248
10666
  """
10249
- cdef int x, y, k
10667
+ cdef Py_ssize_t x, y, k
10250
10668
  k = 0
10251
10669
  nr = self.nrows()
10252
10670
  nc = self.ncols()
@@ -10478,7 +10896,7 @@ cdef class Matrix(Matrix1):
10478
10896
  raise ValueError("self must be a square matrix")
10479
10897
 
10480
10898
  A = self.charpoly().shift(-1)(self)
10481
- return A if n%2 else -A
10899
+ return A if n % 2 else -A
10482
10900
 
10483
10901
  def QR(self, full=True):
10484
10902
  r"""
@@ -12955,7 +13373,188 @@ cdef class Matrix(Matrix1):
12955
13373
  else:
12956
13374
  return subspace
12957
13375
 
12958
- def cholesky(self):
13376
+ def _cholesky_extended_ff(self):
13377
+ r"""
13378
+ Performs the extended Cholesky decomposition of a Hermitian matrix over a finite field of square order.
13379
+
13380
+ INPUT:
13381
+
13382
+ - ``self`` -- a square matrix with entries from a finite field of square order
13383
+
13384
+ .. SEEALSO::
13385
+
13386
+ :meth:`cholesky()`
13387
+
13388
+ OUTPUT:
13389
+
13390
+ For a Hermitian matrix `A` the routine returns a matrix `B` such that,
13391
+
13392
+ .. MATH::
13393
+
13394
+ A = B B^*,
13395
+
13396
+ where `B^*` is the conjugate-transpose.
13397
+
13398
+ ALGORITHM:
13399
+
13400
+ First, we ensure the matrix is square and defined over a finite field of square order. Then we can perform the conjugate-symmetric
13401
+ version of Gaussian elimination, but the resulting decomposition matrix `L` might not be lower triangular.
13402
+
13403
+ This is a translation of ``BaseChangeToCanonical`` from the GAP ``forms`` package (for a Hermitian form).
13404
+
13405
+ EXAMPLES:
13406
+
13407
+ Here we use the extended decomposition, where the result may not be a lower triangular matrix::
13408
+
13409
+ sage: # needs sage.rings.finite_rings
13410
+ sage: U = matrix(GF(17**2),[[0,1],[1,0]])
13411
+ sage: B = U._cholesky_extended_ff(); B
13412
+ [13*z2 + 6 3*z2 + 16]
13413
+ [13*z2 + 6 14*z2 + 1]
13414
+ sage: U == B * B.H
13415
+ True
13416
+ sage: U = matrix(GF(13**2),[[1,4,7],[4,1,4],[7,4,1]])
13417
+ sage: B = U._cholesky_extended_ff(); B
13418
+ [ 1 0 0]
13419
+ [ 4 7*z2 + 3 0]
13420
+ [ 7 6*z2 + 10 12*z2 + 6]
13421
+ sage: U == B * B.H
13422
+ True
13423
+ sage: U = matrix(GF(7**2), [[0, 1, 2], [1, 0, 1], [2, 1, 0]])
13424
+ sage: B = U._cholesky_extended_ff(); B
13425
+ [4*z2 + 2 6*z2 0]
13426
+ [4*z2 + 2 z2 0]
13427
+ [5*z2 + 6 z2 z2]
13428
+ sage: U == B * B.H
13429
+ True
13430
+
13431
+ TESTS:
13432
+
13433
+ If the matrix is not full rank, we compute the rank and throw an exception.
13434
+
13435
+ sage: # needs sage.rings.finite_rings
13436
+ sage: U = matrix(GF(3**2),[[1,4,7],[4,1,4],[7,4,1]])
13437
+ sage: U._cholesky_extended_ff()
13438
+ Traceback (most recent call last):
13439
+ ...
13440
+ ValueError: matrix is not full rank
13441
+ sage: U = matrix(GF(3**2),[[0,4,7],[4,1,4],[7,4,1]])
13442
+ sage: U._cholesky_extended_ff()
13443
+ Traceback (most recent call last):
13444
+ ...
13445
+ ValueError: matrix is not full rank
13446
+ """
13447
+ from sage.matrix.constructor import identity_matrix
13448
+
13449
+ if not self.is_hermitian():
13450
+ raise ValueError("matrix is not Hermitian")
13451
+
13452
+ F = self._base_ring
13453
+ n = self.nrows()
13454
+ if self.fetch("rank") not in [n, None]:
13455
+ raise ValueError("matrix is not full rank")
13456
+ if not (F.is_finite() and F.order().is_square()):
13457
+ raise ValueError("the base ring must be a finite field of square order")
13458
+
13459
+ q = F.order().sqrt(extend=False)
13460
+
13461
+ def conj_square_root(u):
13462
+ if u == 0:
13463
+ return 0
13464
+ z = F.multiplicative_generator()
13465
+ k = u.log(z)
13466
+ if k % (q + 1) != 0:
13467
+ raise ValueError(f"unable to factor: {u} is not in base field GF({q})")
13468
+ return z ** (k//(q+1))
13469
+
13470
+ if self.nrows() == 1 and self.ncols() == 1:
13471
+ return self.__class__(F, [conj_square_root(self[0][0])])
13472
+
13473
+ A = copy(self)
13474
+ D = identity_matrix(F, n)
13475
+ row = -1
13476
+
13477
+ # Diagonalize A
13478
+ while row != n - 1:
13479
+ row += 1
13480
+
13481
+ # Look for a non-zero element on the main diagonal, starting from `row`
13482
+ i = row
13483
+ while i < n and A[i, i].is_zero():
13484
+ i += 1
13485
+
13486
+ if i == row:
13487
+ # Do nothing since A[row, row] != 0
13488
+ pass
13489
+ elif i < n:
13490
+ # Swap to ensure A[row, row] != 0
13491
+ A.swap_rows(row, i)
13492
+ A.swap_columns(row, i)
13493
+ D.swap_rows(row, i)
13494
+ else:
13495
+ # All entries on the main diagonal are zero; look for an off-diagonal element
13496
+ i = row
13497
+ while i < n - 1:
13498
+ k = i + 1
13499
+ while k < n and A[i, k].is_zero():
13500
+ k += 1
13501
+ if k == n:
13502
+ i += 1
13503
+ else:
13504
+ break
13505
+
13506
+ if i == n - 1:
13507
+ # All elements are zero; terminate
13508
+ row -= 1
13509
+ r = row + 1
13510
+ break
13511
+
13512
+ # Fetch the non-zero element and place it at A[row, row + 1]
13513
+ if i != row:
13514
+ A.swap_rows(row, i)
13515
+ A.swap_columns(row, i)
13516
+ D.swap_rows(row, i)
13517
+
13518
+ A.swap_rows(row + 1, k)
13519
+ A.swap_columns(row + 1, k)
13520
+ D.swap_rows(row + 1, k)
13521
+
13522
+ b = ~A[row + 1, row]
13523
+ A.add_multiple_of_column(row, row + 1, b**q)
13524
+ A.add_multiple_of_row(row, row + 1, b)
13525
+ D.add_multiple_of_row(row, row + 1, b)
13526
+
13527
+ # Eliminate below-diagonal entries in the current column
13528
+ a = ~(-A[row, row])
13529
+ for i in range(row + 1, n):
13530
+ b = A[i, row] * a
13531
+ if not b.is_zero():
13532
+ A.add_multiple_of_column(i, row, b**q)
13533
+ A.add_multiple_of_row(i, row, b)
13534
+ D.add_multiple_of_row(i, row, b)
13535
+
13536
+ # Count how many variables have been used
13537
+ if row == n - 1:
13538
+ if A[n - 1, n - 1]: # nonzero entry
13539
+ r = n
13540
+ else:
13541
+ r = n - 1
13542
+
13543
+ if r < n:
13544
+ self.cache('rank', r)
13545
+ raise ValueError("matrix is not full rank")
13546
+
13547
+ # Normalize diagonal elements to 1
13548
+ for i in range(r):
13549
+ a = A[i, i]
13550
+ if not a.is_one():
13551
+ # Find an element `b` such that `a = b*b^q = b^(q+1)`
13552
+ b = conj_square_root(a)
13553
+ D.rescale_row(i, 1 / b)
13554
+
13555
+ return D.inverse()
13556
+
13557
+ def cholesky(self, extended=False):
12959
13558
  r"""
12960
13559
  Return the Cholesky decomposition of a Hermitian matrix.
12961
13560
 
@@ -13001,6 +13600,15 @@ cdef class Matrix(Matrix1):
13001
13600
  closure or the algebraic reals, depending on whether or not
13002
13601
  imaginary numbers are required.
13003
13602
 
13603
+ Over finite fields, the Cholesky decomposition might
13604
+ not exist, but when the field has square order (i.e.,
13605
+ `\GF{q^2}`), then we can perform the conjugate-symmetric
13606
+ version of Gaussian elimination, but the resulting
13607
+ decomposition matrix `L` might not be lower triangular.
13608
+
13609
+ This is a translation of ``BaseChangeToCanonical`` from
13610
+ the GAP ``forms`` package (for a Hermitian form).
13611
+
13004
13612
  EXAMPLES:
13005
13613
 
13006
13614
  This simple example has a result with entries that remain
@@ -13171,6 +13779,31 @@ cdef class Matrix(Matrix1):
13171
13779
  ...
13172
13780
  ValueError: matrix is not positive definite
13173
13781
 
13782
+ Here we use the extended decomposition, where the result
13783
+ may not be a lower triangular matrix::
13784
+
13785
+ sage: # needs sage.rings.finite_rings
13786
+ sage: U = matrix(GF(5**2),[[0,1],[1,0]])
13787
+ sage: B = U.cholesky(extended=True); B
13788
+ [3*z2 4*z2]
13789
+ [3*z2 z2]
13790
+ sage: U == B * B.H
13791
+ True
13792
+ sage: U = matrix(GF(11**2),[[1,4,7],[4,1,4],[7,4,1]])
13793
+ sage: B = U.cholesky(extended=True); B
13794
+ [ 1 0 0]
13795
+ [ 4 9*z2 + 2 0]
13796
+ [ 7 10*z2 + 1 3*z2 + 3]
13797
+ sage: U == B * B.H
13798
+ True
13799
+ sage: U = matrix(GF(3**2), [[0, 1, 2], [1, 0, 1], [2, 1, 0]])
13800
+ sage: B = U.cholesky(extended=True); B
13801
+ [2*z2 2 0]
13802
+ [2*z2 1 0]
13803
+ [ 0 1 z2]
13804
+ sage: U == B * B.H
13805
+ True
13806
+
13174
13807
  TESTS:
13175
13808
 
13176
13809
  This verifies that :issue:`11274` is resolved::
@@ -13217,7 +13850,22 @@ cdef class Matrix(Matrix1):
13217
13850
  sage: all( matrix(R,[]).cholesky().is_immutable() # needs sage.rings.number_field
13218
13851
  ....: for R in (RR,CC,RDF,CDF,ZZ,QQ,AA,QQbar) )
13219
13852
  True
13853
+
13854
+ Perform the extended decomposition over finite fields, which may result in non upper/lower triangular matrices::
13855
+
13856
+ sage: # needs sage.rings.finite_rings
13857
+ sage: A = matrix(GF(11**2),[[1,4,7],[4,1,4],[7,4,1]])
13858
+ sage: B = A.cholesky(extended=True)
13859
+ sage: A == B * B.H
13860
+ True
13861
+ sage: A = matrix(GF(3**2), [[0, 1, 2], [1, 0, 1], [2, 1, 0]])
13862
+ sage: B = A.cholesky(extended=True)
13863
+ sage: A == B * B.H
13864
+ True
13220
13865
  """
13866
+ if extended:
13867
+ return self._cholesky_extended_ff()
13868
+
13221
13869
  cdef Matrix C # output matrix
13222
13870
  C = self.fetch('cholesky')
13223
13871
  if C is not None:
@@ -15476,6 +16124,10 @@ cdef class Matrix(Matrix1):
15476
16124
  Return the conjugate of self, i.e. the matrix whose entries are the
15477
16125
  conjugates of the entries of ``self``.
15478
16126
 
16127
+ .. SEEALSO::
16128
+
16129
+ :attr:`C`
16130
+
15479
16131
  EXAMPLES::
15480
16132
 
15481
16133
  sage: # needs sage.rings.complex_double sage.symbolic
@@ -15531,6 +16183,10 @@ cdef class Matrix(Matrix1):
15531
16183
  though there is substantial variation and some confusion with
15532
16184
  the use of that term.
15533
16185
 
16186
+ .. SEEALSO::
16187
+
16188
+ :meth:`conjugate`, :meth:`~.Matrix_dense.transpose`, :attr:`H`
16189
+
15534
16190
  OUTPUT:
15535
16191
 
15536
16192
  A matrix formed by taking the complex conjugate of every entry
@@ -15958,7 +16614,11 @@ cdef class Matrix(Matrix1):
15958
16614
  """
15959
16615
  d = self.smith_form(transformation=False)
15960
16616
  r = min(self.nrows(), self.ncols())
15961
- return [d[i, i] for i in range(r)]
16617
+ ed = [d[i, i] for i in range(r)]
16618
+ try:
16619
+ return [x.canonical_associate()[0] for x in ed]
16620
+ except (AttributeError, TypeError):
16621
+ return ed
15962
16622
 
15963
16623
  def smith_form(self, transformation=True, integral=None, exact=True):
15964
16624
  r"""
@@ -16138,7 +16798,7 @@ cdef class Matrix(Matrix1):
16138
16798
  sage: d, u, v = m.smith_form(); u * m * v == d
16139
16799
  True
16140
16800
 
16141
- Over local fields, we can request the transformation matrices to be integral:;
16801
+ Over local fields, we can request the transformation matrices to be integral::
16142
16802
 
16143
16803
  sage: K = Qp(2, 5, print_mode='terse') # needs sage.rings.padics
16144
16804
  sage: M = matrix(K, 2, 3, [1/2, 1, 2, 1/3, 1, 3]) # needs sage.rings.padics
@@ -18229,11 +18889,11 @@ cdef class Matrix(Matrix1):
18229
18889
  the greatest common divisor of the determinants of all `r`-by-`r`
18230
18890
  submatrices of `B` is `1`. [Sch1986]_, Ch. 21.4.
18231
18891
 
18232
- .. SEEALSO:: :meth:`is_k_equimodular`, :meth:`is_strongly_unimodular`, :meth:`is_totally_unimodular`
18233
-
18234
- See :meth:`~sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_unimodular` for
18892
+ See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_unimodular` for
18235
18893
  the detailed documentation.
18236
18894
 
18895
+ .. SEEALSO:: :meth:`is_k_equimodular`, :meth:`is_strongly_unimodular`, :meth:`is_totally_unimodular`
18896
+
18237
18897
  EXAMPLES::
18238
18898
 
18239
18899
  sage: # needs sage.libs.cmr
@@ -18256,7 +18916,10 @@ cdef class Matrix(Matrix1):
18256
18916
 
18257
18917
  A matrix is strongly unimodular if ``self`` and ``self.transpose()`` are both unimodular.
18258
18918
 
18259
- .. SEEALSO:: meth:`is_unimodular`, :meth:`is_strongly_k_equimodular`
18919
+ See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_strongly_unimodular` for
18920
+ the detailed documentation.
18921
+
18922
+ .. SEEALSO:: :meth:`is_unimodular`, :meth:`is_strongly_k_equimodular`
18260
18923
 
18261
18924
  EXAMPLES::
18262
18925
 
@@ -18295,6 +18958,9 @@ cdef class Matrix(Matrix1):
18295
18958
  - ``k``: ``self`` is equimodular with determinant gcd `k`
18296
18959
  - ``None``: ``self`` is not equimodular for any `k`
18297
18960
 
18961
+ See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.equimodulus` for
18962
+ the detailed documentation.
18963
+
18298
18964
  .. SEEALSO:: :meth:`is_k_equimodular`, :meth:`strong_equimodulus`
18299
18965
 
18300
18966
  EXAMPLES::
@@ -18336,6 +19002,9 @@ cdef class Matrix(Matrix1):
18336
19002
  - ``k``: ``self`` is `k`-equimodular
18337
19003
  - ``None``: ``self`` is not `k`-equimodular for any `k`
18338
19004
 
19005
+ See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.strong_equimodulus` for
19006
+ the detailed documentation.
19007
+
18339
19008
  .. SEEALSO:: :meth:`is_strongly_k_equimodular`, :meth:`equimodulus`
18340
19009
 
18341
19010
  EXAMPLES::
@@ -18374,6 +19043,9 @@ cdef class Matrix(Matrix1):
18374
19043
  In parts of the literature, a matrix with the above properties
18375
19044
  is called *strictly* `k`-modular.
18376
19045
 
19046
+ See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_k_equimodular` for
19047
+ the detailed documentation.
19048
+
18377
19049
  .. SEEALSO:: :meth:`is_unimodular`, :meth:`is_strongly_k_equimodular`,
18378
19050
  :meth:`equimodulus`
18379
19051
 
@@ -18403,6 +19075,9 @@ cdef class Matrix(Matrix1):
18403
19075
  A matrix is strongly `k`-equimodular if ``self`` and ``self.transpose()``
18404
19076
  are both `k`-equimodular.
18405
19077
 
19078
+ See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_strongly_k_equimodular` for
19079
+ the detailed documentation.
19080
+
18406
19081
  .. SEEALSO:: :meth:`is_k_equimodular`, :meth:`is_strongly_unimodular`,
18407
19082
  :meth:`strong_equimodulus`
18408
19083
 
@@ -18452,6 +19127,9 @@ cdef class Matrix(Matrix1):
18452
19127
  the support matrix of `M` for being graphic and
18453
19128
  uses camion for testing whether `M` is signed correctly.
18454
19129
 
19130
+ See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_network_matrix` for
19131
+ the detailed documentation.
19132
+
18455
19133
  EXAMPLES::
18456
19134
 
18457
19135
  sage: # needs sage.libs.cmr
@@ -18523,11 +19201,14 @@ cdef class Matrix(Matrix1):
18523
19201
 
18524
19202
  def is_conetwork_matrix(self, *args, **kwds):
18525
19203
  r"""
18526
- Return whether the matrix ``self`` over `\GF{3}` or `QQ` is a conetwork matrix.
19204
+ Return whether the matrix ``self`` over `\GF{3}` or `\QQ` is a conetwork matrix.
18527
19205
 
18528
- A matrix is conetwork if and only if its transpose is network.
19206
+ A matrix is a conetwork matrix if and only if its transpose is a network matrix.
19207
+
19208
+ See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_conetwork_matrix` for
19209
+ the detailed documentation.
18529
19210
 
18530
- .. SEEALSO:: :meth:`is_network_matrix`,
19211
+ .. SEEALSO:: :meth:`is_network_matrix`
18531
19212
 
18532
19213
  EXAMPLES::
18533
19214
 
@@ -18586,14 +19267,15 @@ cdef class Matrix(Matrix1):
18586
19267
  - ``stop_when_nonTU`` -- boolean (default: ``True``);
18587
19268
  whether to stop decomposing once not TU is determined.
18588
19269
 
18589
- For a description of other parameters, see :meth:`_set_cmr_seymour_parameters`
18590
-
18591
19270
  - ``row_keys`` -- a finite or enumerated family of arbitrary objects
18592
19271
  that index the rows of the matrix
18593
19272
 
18594
19273
  - ``column_keys`` -- a finite or enumerated family of arbitrary objects
18595
19274
  that index the columns of the matrix
18596
19275
 
19276
+ See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_totally_unimodular` for
19277
+ the detailed documentation.
19278
+
18597
19279
  EXAMPLES::
18598
19280
 
18599
19281
  sage: # needs sage.libs.cmr
@@ -18667,8 +19349,8 @@ cdef class Matrix(Matrix1):
18667
19349
  │ │
18668
19350
  GraphicNode (5×4) CographicNode (4×5)
18669
19351
 
18670
- This is test ``TreeFlagsNorecurse``, ``TreeFlagsStopNoncographic``,
18671
- and ``TreeFlagsStopNongraphic`` in CMR's ``test_regular.cpp``,
19352
+ These are tests ``TreeFlagsNorecurse``, ``TreeFlagsStopNoncographic``,
19353
+ and ``TreeFlagsStopNongraphic`` in CMR's ``test_regular.cpp``;
18672
19354
  the underlying binary linear matroid is regular,
18673
19355
  but the matrix is not totally unimodular::
18674
19356
 
@@ -18701,9 +19383,6 @@ cdef class Matrix(Matrix1):
18701
19383
  """
18702
19384
  return self._matrix_cmr().is_totally_unimodular(*args, **kwds)
18703
19385
 
18704
- def is_complement_totally_unimodular(self, *args, **kwds):
18705
- return self._matrix_cmr().is_complement_totally_unimodular(*args, **kwds)
18706
-
18707
19386
  def LLL_gram(self, flag=0):
18708
19387
  """
18709
19388
  Return the LLL transformation matrix for this Gram matrix.
@@ -18865,6 +19544,10 @@ cdef class Matrix(Matrix1):
18865
19544
  r"""
18866
19545
  Return the conjugate-transpose (Hermitian) matrix.
18867
19546
 
19547
+ .. SEEALSO::
19548
+
19549
+ :meth:`conjugate_transpose`
19550
+
18868
19551
  EXAMPLES::
18869
19552
 
18870
19553
  sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I], # needs sage.rings.number_field
@@ -18875,7 +19558,7 @@ cdef class Matrix(Matrix1):
18875
19558
  [ 5 + 3*I -1 - 6*I -3 - 6*I]
18876
19559
  [ 7 + 4*I 3 - 5*I 5 - 1*I]
18877
19560
  """
18878
- return self.conjugate().transpose()
19561
+ return self.conjugate_transpose()
18879
19562
 
18880
19563
 
18881
19564
  def _smith_diag(d, transformation=True):