passagemath-flint 10.6.1rc10__cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.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 (360) hide show
  1. passagemath_flint-10.6.1rc10.dist-info/METADATA +122 -0
  2. passagemath_flint-10.6.1rc10.dist-info/RECORD +360 -0
  3. passagemath_flint-10.6.1rc10.dist-info/WHEEL +6 -0
  4. passagemath_flint-10.6.1rc10.dist-info/top_level.txt +2 -0
  5. passagemath_flint.libs/libflint-3701249d.so.21.0.0 +0 -0
  6. passagemath_flint.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
  7. passagemath_flint.libs/libgfortran-8a9a71bc.so.5.0.0 +0 -0
  8. passagemath_flint.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
  9. passagemath_flint.libs/libgsl-e3525837.so.28.0.0 +0 -0
  10. passagemath_flint.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
  11. passagemath_flint.libs/libmpfr-e0f11cf3.so.6.2.1 +0 -0
  12. passagemath_flint.libs/libntl-1004113e.so.44.0.1 +0 -0
  13. passagemath_flint.libs/libopenblasp-r0-4c5b64b1.3.29.so +0 -0
  14. sage/all__sagemath_flint.py +29 -0
  15. sage/combinat/all__sagemath_flint.py +1 -0
  16. sage/combinat/posets/all__sagemath_flint.py +1 -0
  17. sage/combinat/posets/hasse_cython_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  18. sage/combinat/posets/hasse_cython_flint.pyx +194 -0
  19. sage/data_structures/all__sagemath_flint.py +1 -0
  20. sage/data_structures/bounded_integer_sequences.cpython-310-aarch64-linux-gnu.so +0 -0
  21. sage/data_structures/bounded_integer_sequences.pxd +62 -0
  22. sage/data_structures/bounded_integer_sequences.pyx +1418 -0
  23. sage/graphs/all__sagemath_flint.py +1 -0
  24. sage/graphs/chrompoly.cpython-310-aarch64-linux-gnu.so +0 -0
  25. sage/graphs/chrompoly.pyx +555 -0
  26. sage/graphs/matchpoly.cpython-310-aarch64-linux-gnu.so +0 -0
  27. sage/graphs/matchpoly.pyx +412 -0
  28. sage/libs/all__sagemath_flint.py +17 -0
  29. sage/libs/arb/__init__.py +1 -0
  30. sage/libs/arb/acb.pxd +154 -0
  31. sage/libs/arb/acb_calc.pxd +9 -0
  32. sage/libs/arb/acb_elliptic.pxd +25 -0
  33. sage/libs/arb/acb_hypgeom.pxd +74 -0
  34. sage/libs/arb/acb_mat.pxd +62 -0
  35. sage/libs/arb/acb_modular.pxd +17 -0
  36. sage/libs/arb/acb_poly.pxd +216 -0
  37. sage/libs/arb/arb.pxd +240 -0
  38. sage/libs/arb/arb_fmpz_poly.pxd +21 -0
  39. sage/libs/arb/arb_hypgeom.pxd +83 -0
  40. sage/libs/arb/arb_wrap.h +34 -0
  41. sage/libs/arb/arf.pxd +131 -0
  42. sage/libs/arb/arith.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sage/libs/arb/arith.pyx +87 -0
  44. sage/libs/arb/bernoulli.pxd +6 -0
  45. sage/libs/arb/mag.pxd +77 -0
  46. sage/libs/arb/types.pxd +37 -0
  47. sage/libs/flint/__init__.py +1 -0
  48. sage/libs/flint/acb.pxd +270 -0
  49. sage/libs/flint/acb_calc.pxd +22 -0
  50. sage/libs/flint/acb_dft.pxd +51 -0
  51. sage/libs/flint/acb_dirichlet.pxd +112 -0
  52. sage/libs/flint/acb_elliptic.pxd +42 -0
  53. sage/libs/flint/acb_hypgeom.pxd +169 -0
  54. sage/libs/flint/acb_macros.pxd +9 -0
  55. sage/libs/flint/acb_mat.pxd +136 -0
  56. sage/libs/flint/acb_mat_macros.pxd +10 -0
  57. sage/libs/flint/acb_modular.pxd +62 -0
  58. sage/libs/flint/acb_poly.pxd +251 -0
  59. sage/libs/flint/acb_poly_macros.pxd +8 -0
  60. sage/libs/flint/acb_theta.pxd +124 -0
  61. sage/libs/flint/acf.pxd +32 -0
  62. sage/libs/flint/aprcl.pxd +84 -0
  63. sage/libs/flint/arb.pxd +382 -0
  64. sage/libs/flint/arb_calc.pxd +31 -0
  65. sage/libs/flint/arb_fmpz_poly.pxd +34 -0
  66. sage/libs/flint/arb_fpwrap.pxd +215 -0
  67. sage/libs/flint/arb_hypgeom.pxd +147 -0
  68. sage/libs/flint/arb_macros.pxd +9 -0
  69. sage/libs/flint/arb_mat.pxd +140 -0
  70. sage/libs/flint/arb_mat_macros.pxd +10 -0
  71. sage/libs/flint/arb_poly.pxd +237 -0
  72. sage/libs/flint/arf.pxd +167 -0
  73. sage/libs/flint/arith.cpython-310-aarch64-linux-gnu.so +0 -0
  74. sage/libs/flint/arith.pxd +76 -0
  75. sage/libs/flint/arith.pyx +77 -0
  76. sage/libs/flint/arith_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  77. sage/libs/flint/arith_sage.pyx +308 -0
  78. sage/libs/flint/bernoulli.pxd +28 -0
  79. sage/libs/flint/bool_mat.pxd +52 -0
  80. sage/libs/flint/ca.pxd +203 -0
  81. sage/libs/flint/ca_ext.pxd +34 -0
  82. sage/libs/flint/ca_field.pxd +32 -0
  83. sage/libs/flint/ca_mat.pxd +117 -0
  84. sage/libs/flint/ca_poly.pxd +104 -0
  85. sage/libs/flint/ca_vec.pxd +46 -0
  86. sage/libs/flint/calcium.pxd +27 -0
  87. sage/libs/flint/d_mat.pxd +39 -0
  88. sage/libs/flint/d_vec.pxd +32 -0
  89. sage/libs/flint/dirichlet.pxd +57 -0
  90. sage/libs/flint/dlog.pxd +53 -0
  91. sage/libs/flint/double_extras.pxd +24 -0
  92. sage/libs/flint/double_interval.pxd +36 -0
  93. sage/libs/flint/fexpr.pxd +104 -0
  94. sage/libs/flint/fexpr_builtin.pxd +20 -0
  95. sage/libs/flint/fft.pxd +66 -0
  96. sage/libs/flint/flint.pxd +36 -0
  97. sage/libs/flint/flint_ntl_wrap.h +35 -0
  98. sage/libs/flint/flint_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  99. sage/libs/flint/flint_sage.pyx +163 -0
  100. sage/libs/flint/flint_wrap.h +190 -0
  101. sage/libs/flint/fmpq.pxd +137 -0
  102. sage/libs/flint/fmpq_mat.pxd +105 -0
  103. sage/libs/flint/fmpq_mat_macros.pxd +10 -0
  104. sage/libs/flint/fmpq_mpoly.pxd +165 -0
  105. sage/libs/flint/fmpq_mpoly_factor.pxd +30 -0
  106. sage/libs/flint/fmpq_poly.pxd +241 -0
  107. sage/libs/flint/fmpq_poly_macros.pxd +9 -0
  108. sage/libs/flint/fmpq_poly_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  109. sage/libs/flint/fmpq_poly_sage.pxd +31 -0
  110. sage/libs/flint/fmpq_poly_sage.pyx +48 -0
  111. sage/libs/flint/fmpq_vec.pxd +27 -0
  112. sage/libs/flint/fmpz.pxd +256 -0
  113. sage/libs/flint/fmpz_extras.pxd +32 -0
  114. sage/libs/flint/fmpz_factor.pxd +42 -0
  115. sage/libs/flint/fmpz_factor_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  116. sage/libs/flint/fmpz_factor_sage.pxd +4 -0
  117. sage/libs/flint/fmpz_factor_sage.pyx +29 -0
  118. sage/libs/flint/fmpz_lll.pxd +49 -0
  119. sage/libs/flint/fmpz_macros.pxd +8 -0
  120. sage/libs/flint/fmpz_mat.pxd +184 -0
  121. sage/libs/flint/fmpz_mat_macros.pxd +10 -0
  122. sage/libs/flint/fmpz_mod.pxd +46 -0
  123. sage/libs/flint/fmpz_mod_mat.pxd +71 -0
  124. sage/libs/flint/fmpz_mod_mpoly.pxd +161 -0
  125. sage/libs/flint/fmpz_mod_mpoly_factor.pxd +28 -0
  126. sage/libs/flint/fmpz_mod_poly.pxd +249 -0
  127. sage/libs/flint/fmpz_mod_poly_factor.pxd +46 -0
  128. sage/libs/flint/fmpz_mod_vec.pxd +27 -0
  129. sage/libs/flint/fmpz_mpoly.pxd +224 -0
  130. sage/libs/flint/fmpz_mpoly_factor.pxd +29 -0
  131. sage/libs/flint/fmpz_mpoly_q.pxd +57 -0
  132. sage/libs/flint/fmpz_poly.cpython-310-aarch64-linux-gnu.so +0 -0
  133. sage/libs/flint/fmpz_poly.pxd +407 -0
  134. sage/libs/flint/fmpz_poly.pyx +19 -0
  135. sage/libs/flint/fmpz_poly_factor.pxd +33 -0
  136. sage/libs/flint/fmpz_poly_macros.pxd +8 -0
  137. sage/libs/flint/fmpz_poly_mat.pxd +71 -0
  138. sage/libs/flint/fmpz_poly_q.pxd +55 -0
  139. sage/libs/flint/fmpz_poly_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  140. sage/libs/flint/fmpz_poly_sage.pxd +20 -0
  141. sage/libs/flint/fmpz_poly_sage.pyx +500 -0
  142. sage/libs/flint/fmpz_vec.pxd +80 -0
  143. sage/libs/flint/fmpzi.pxd +52 -0
  144. sage/libs/flint/fq.pxd +97 -0
  145. sage/libs/flint/fq_default.pxd +84 -0
  146. sage/libs/flint/fq_default_mat.pxd +70 -0
  147. sage/libs/flint/fq_default_poly.pxd +97 -0
  148. sage/libs/flint/fq_default_poly_factor.pxd +39 -0
  149. sage/libs/flint/fq_embed.pxd +28 -0
  150. sage/libs/flint/fq_mat.pxd +83 -0
  151. sage/libs/flint/fq_nmod.pxd +95 -0
  152. sage/libs/flint/fq_nmod_embed.pxd +28 -0
  153. sage/libs/flint/fq_nmod_mat.pxd +83 -0
  154. sage/libs/flint/fq_nmod_mpoly.pxd +130 -0
  155. sage/libs/flint/fq_nmod_mpoly_factor.pxd +28 -0
  156. sage/libs/flint/fq_nmod_poly.pxd +202 -0
  157. sage/libs/flint/fq_nmod_poly_factor.pxd +47 -0
  158. sage/libs/flint/fq_nmod_vec.pxd +33 -0
  159. sage/libs/flint/fq_poly.pxd +204 -0
  160. sage/libs/flint/fq_poly_factor.pxd +47 -0
  161. sage/libs/flint/fq_vec.pxd +33 -0
  162. sage/libs/flint/fq_zech.pxd +99 -0
  163. sage/libs/flint/fq_zech_embed.pxd +28 -0
  164. sage/libs/flint/fq_zech_mat.pxd +78 -0
  165. sage/libs/flint/fq_zech_poly.pxd +198 -0
  166. sage/libs/flint/fq_zech_poly_factor.pxd +47 -0
  167. sage/libs/flint/fq_zech_vec.pxd +33 -0
  168. sage/libs/flint/gr.pxd +174 -0
  169. sage/libs/flint/gr_generic.pxd +215 -0
  170. sage/libs/flint/gr_mat.pxd +161 -0
  171. sage/libs/flint/gr_mpoly.pxd +68 -0
  172. sage/libs/flint/gr_poly.pxd +276 -0
  173. sage/libs/flint/gr_special.pxd +237 -0
  174. sage/libs/flint/gr_vec.pxd +120 -0
  175. sage/libs/flint/hypgeom.pxd +24 -0
  176. sage/libs/flint/long_extras.pxd +23 -0
  177. sage/libs/flint/mag.pxd +131 -0
  178. sage/libs/flint/mag_macros.pxd +8 -0
  179. sage/libs/flint/mpf_mat.pxd +36 -0
  180. sage/libs/flint/mpf_vec.pxd +34 -0
  181. sage/libs/flint/mpfr_mat.pxd +27 -0
  182. sage/libs/flint/mpfr_vec.pxd +25 -0
  183. sage/libs/flint/mpn_extras.pxd +41 -0
  184. sage/libs/flint/mpoly.pxd +72 -0
  185. sage/libs/flint/nf.pxd +19 -0
  186. sage/libs/flint/nf_elem.pxd +74 -0
  187. sage/libs/flint/nmod.pxd +35 -0
  188. sage/libs/flint/nmod_mat.pxd +104 -0
  189. sage/libs/flint/nmod_mpoly.pxd +144 -0
  190. sage/libs/flint/nmod_mpoly_factor.pxd +28 -0
  191. sage/libs/flint/nmod_poly.pxd +339 -0
  192. sage/libs/flint/nmod_poly_factor.pxd +44 -0
  193. sage/libs/flint/nmod_poly_linkage.pxi +710 -0
  194. sage/libs/flint/nmod_poly_mat.pxd +76 -0
  195. sage/libs/flint/nmod_vec.pxd +40 -0
  196. sage/libs/flint/ntl_interface.pxd +17 -0
  197. sage/libs/flint/padic.pxd +93 -0
  198. sage/libs/flint/padic_mat.pxd +64 -0
  199. sage/libs/flint/padic_poly.pxd +88 -0
  200. sage/libs/flint/partitions.pxd +23 -0
  201. sage/libs/flint/perm.pxd +26 -0
  202. sage/libs/flint/profiler.pxd +24 -0
  203. sage/libs/flint/qadic.pxd +77 -0
  204. sage/libs/flint/qfb.pxd +44 -0
  205. sage/libs/flint/qqbar.pxd +172 -0
  206. sage/libs/flint/qsieve.cpython-310-aarch64-linux-gnu.so +0 -0
  207. sage/libs/flint/qsieve.pxd +41 -0
  208. sage/libs/flint/qsieve.pyx +21 -0
  209. sage/libs/flint/qsieve_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  210. sage/libs/flint/qsieve_sage.pyx +67 -0
  211. sage/libs/flint/thread_pool.pxd +25 -0
  212. sage/libs/flint/types.pxd +2076 -0
  213. sage/libs/flint/ulong_extras.cpython-310-aarch64-linux-gnu.so +0 -0
  214. sage/libs/flint/ulong_extras.pxd +141 -0
  215. sage/libs/flint/ulong_extras.pyx +21 -0
  216. sage/libs/flint/ulong_extras_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  217. sage/libs/flint/ulong_extras_sage.pyx +21 -0
  218. sage/matrix/all__sagemath_flint.py +1 -0
  219. sage/matrix/change_ring.cpython-310-aarch64-linux-gnu.so +0 -0
  220. sage/matrix/change_ring.pyx +43 -0
  221. sage/matrix/matrix_complex_ball_dense.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sage/matrix/matrix_complex_ball_dense.pxd +14 -0
  223. sage/matrix/matrix_complex_ball_dense.pyx +973 -0
  224. sage/matrix/matrix_cyclo_dense.cpython-310-aarch64-linux-gnu.so +0 -0
  225. sage/matrix/matrix_cyclo_dense.pxd +16 -0
  226. sage/matrix/matrix_cyclo_dense.pyx +1761 -0
  227. sage/matrix/matrix_integer_dense.cpython-310-aarch64-linux-gnu.so +0 -0
  228. sage/matrix/matrix_integer_dense.pxd +32 -0
  229. sage/matrix/matrix_integer_dense.pyx +5801 -0
  230. sage/matrix/matrix_integer_dense_hnf.py +1294 -0
  231. sage/matrix/matrix_integer_dense_saturation.py +346 -0
  232. sage/matrix/matrix_integer_sparse.cpython-310-aarch64-linux-gnu.so +0 -0
  233. sage/matrix/matrix_integer_sparse.pxd +9 -0
  234. sage/matrix/matrix_integer_sparse.pyx +1090 -0
  235. sage/matrix/matrix_rational_dense.cpython-310-aarch64-linux-gnu.so +0 -0
  236. sage/matrix/matrix_rational_dense.pxd +23 -0
  237. sage/matrix/matrix_rational_dense.pyx +2995 -0
  238. sage/matrix/matrix_rational_sparse.cpython-310-aarch64-linux-gnu.so +0 -0
  239. sage/matrix/matrix_rational_sparse.pxd +11 -0
  240. sage/matrix/matrix_rational_sparse.pyx +789 -0
  241. sage/matrix/misc_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  242. sage/matrix/misc_flint.pyx +109 -0
  243. sage/modular/all__sagemath_flint.py +1 -0
  244. sage/modular/modform/all__sagemath_flint.py +1 -0
  245. sage/modular/modform/eis_series_cython.cpython-310-aarch64-linux-gnu.so +0 -0
  246. sage/modular/modform/eis_series_cython.pyx +226 -0
  247. sage/modular/modsym/all__sagemath_flint.py +1 -0
  248. sage/modular/modsym/apply.cpython-310-aarch64-linux-gnu.so +0 -0
  249. sage/modular/modsym/apply.pxd +6 -0
  250. sage/modular/modsym/apply.pyx +113 -0
  251. sage/modular/modsym/heilbronn.cpython-310-aarch64-linux-gnu.so +0 -0
  252. sage/modular/modsym/heilbronn.pyx +966 -0
  253. sage/modular/pollack_stevens/all__sagemath_flint.py +1 -0
  254. sage/modular/pollack_stevens/dist.cpython-310-aarch64-linux-gnu.so +0 -0
  255. sage/modular/pollack_stevens/dist.pxd +38 -0
  256. sage/modular/pollack_stevens/dist.pyx +1439 -0
  257. sage/quivers/algebra.py +691 -0
  258. sage/quivers/algebra_elements.cpython-310-aarch64-linux-gnu.so +0 -0
  259. sage/quivers/algebra_elements.pxd +97 -0
  260. sage/quivers/algebra_elements.pxi +1324 -0
  261. sage/quivers/algebra_elements.pyx +1424 -0
  262. sage/quivers/all.py +1 -0
  263. sage/quivers/ar_quiver.py +917 -0
  264. sage/quivers/homspace.py +640 -0
  265. sage/quivers/morphism.py +1282 -0
  266. sage/quivers/path_semigroup.py +1155 -0
  267. sage/quivers/paths.cpython-310-aarch64-linux-gnu.so +0 -0
  268. sage/quivers/paths.pxd +13 -0
  269. sage/quivers/paths.pyx +809 -0
  270. sage/quivers/representation.py +2975 -0
  271. sage/rings/all__sagemath_flint.py +37 -0
  272. sage/rings/cif.py +4 -0
  273. sage/rings/complex_arb.cpython-310-aarch64-linux-gnu.so +0 -0
  274. sage/rings/complex_arb.pxd +29 -0
  275. sage/rings/complex_arb.pyx +5176 -0
  276. sage/rings/complex_interval.cpython-310-aarch64-linux-gnu.so +0 -0
  277. sage/rings/complex_interval.pxd +30 -0
  278. sage/rings/complex_interval.pyx +2475 -0
  279. sage/rings/complex_interval_field.py +711 -0
  280. sage/rings/convert/all.py +1 -0
  281. sage/rings/convert/mpfi.cpython-310-aarch64-linux-gnu.so +0 -0
  282. sage/rings/convert/mpfi.pxd +6 -0
  283. sage/rings/convert/mpfi.pyx +576 -0
  284. sage/rings/factorint_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  285. sage/rings/factorint_flint.pyx +99 -0
  286. sage/rings/fraction_field_FpT.cpython-310-aarch64-linux-gnu.so +0 -0
  287. sage/rings/fraction_field_FpT.pxd +28 -0
  288. sage/rings/fraction_field_FpT.pyx +2043 -0
  289. sage/rings/imaginary_unit.py +5 -0
  290. sage/rings/monomials.py +73 -0
  291. sage/rings/number_field/S_unit_solver.py +2870 -0
  292. sage/rings/number_field/all__sagemath_flint.py +7 -0
  293. sage/rings/number_field/bdd_height.py +664 -0
  294. sage/rings/number_field/class_group.py +762 -0
  295. sage/rings/number_field/galois_group.py +1307 -0
  296. sage/rings/number_field/homset.py +612 -0
  297. sage/rings/number_field/maps.py +687 -0
  298. sage/rings/number_field/morphism.py +272 -0
  299. sage/rings/number_field/number_field.py +12820 -0
  300. sage/rings/number_field/number_field_element.cpython-310-aarch64-linux-gnu.so +0 -0
  301. sage/rings/number_field/number_field_element.pxd +59 -0
  302. sage/rings/number_field/number_field_element.pyx +5735 -0
  303. sage/rings/number_field/number_field_element_quadratic.cpython-310-aarch64-linux-gnu.so +0 -0
  304. sage/rings/number_field/number_field_element_quadratic.pxd +34 -0
  305. sage/rings/number_field/number_field_element_quadratic.pyx +3185 -0
  306. sage/rings/number_field/number_field_ideal_rel.py +925 -0
  307. sage/rings/number_field/number_field_morphisms.cpython-310-aarch64-linux-gnu.so +0 -0
  308. sage/rings/number_field/number_field_morphisms.pyx +781 -0
  309. sage/rings/number_field/number_field_rel.py +2734 -0
  310. sage/rings/number_field/order.py +2981 -0
  311. sage/rings/number_field/order_ideal.py +804 -0
  312. sage/rings/number_field/selmer_group.py +715 -0
  313. sage/rings/number_field/small_primes_of_degree_one.py +242 -0
  314. sage/rings/number_field/splitting_field.py +606 -0
  315. sage/rings/number_field/structure.py +380 -0
  316. sage/rings/number_field/unit_group.py +721 -0
  317. sage/rings/padics/all__sagemath_flint.py +3 -0
  318. sage/rings/polynomial/all__sagemath_flint.py +1 -0
  319. sage/rings/polynomial/complex_roots.py +312 -0
  320. sage/rings/polynomial/evaluation_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  321. sage/rings/polynomial/evaluation_flint.pxd +7 -0
  322. sage/rings/polynomial/evaluation_flint.pyx +68 -0
  323. sage/rings/polynomial/hilbert.cpython-310-aarch64-linux-gnu.so +0 -0
  324. sage/rings/polynomial/hilbert.pyx +602 -0
  325. sage/rings/polynomial/polynomial_complex_arb.cpython-310-aarch64-linux-gnu.so +0 -0
  326. sage/rings/polynomial/polynomial_complex_arb.pxd +7 -0
  327. sage/rings/polynomial/polynomial_complex_arb.pyx +963 -0
  328. sage/rings/polynomial/polynomial_integer_dense_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  329. sage/rings/polynomial/polynomial_integer_dense_flint.pxd +13 -0
  330. sage/rings/polynomial/polynomial_integer_dense_flint.pyx +1881 -0
  331. sage/rings/polynomial/polynomial_number_field.cpython-310-aarch64-linux-gnu.so +0 -0
  332. sage/rings/polynomial/polynomial_number_field.pyx +345 -0
  333. sage/rings/polynomial/polynomial_rational_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  334. sage/rings/polynomial/polynomial_rational_flint.pxd +20 -0
  335. sage/rings/polynomial/polynomial_rational_flint.pyx +2598 -0
  336. sage/rings/polynomial/polynomial_zmod_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  337. sage/rings/polynomial/polynomial_zmod_flint.pxd +20 -0
  338. sage/rings/polynomial/polynomial_zmod_flint.pyx +1063 -0
  339. sage/rings/polynomial/real_roots.cpython-310-aarch64-linux-gnu.so +0 -0
  340. sage/rings/polynomial/real_roots.pxd +81 -0
  341. sage/rings/polynomial/real_roots.pyx +4704 -0
  342. sage/rings/polynomial/refine_root.cpython-310-aarch64-linux-gnu.so +0 -0
  343. sage/rings/polynomial/refine_root.pyx +142 -0
  344. sage/rings/polynomial/weil/all.py +4 -0
  345. sage/rings/polynomial/weil/power_sums.h +46 -0
  346. sage/rings/polynomial/weil/weil_polynomials.cpython-310-aarch64-linux-gnu.so +0 -0
  347. sage/rings/polynomial/weil/weil_polynomials.pyx +596 -0
  348. sage/rings/qqbar.py +9025 -0
  349. sage/rings/real_arb.cpython-310-aarch64-linux-gnu.so +0 -0
  350. sage/rings/real_arb.pxd +21 -0
  351. sage/rings/real_arb.pyx +4065 -0
  352. sage/rings/real_interval_absolute.cpython-310-aarch64-linux-gnu.so +0 -0
  353. sage/rings/real_interval_absolute.pyx +1073 -0
  354. sage/rings/real_mpfi.cpython-310-aarch64-linux-gnu.so +0 -0
  355. sage/rings/real_mpfi.pyx +5428 -0
  356. sage/schemes/all__sagemath_flint.py +1 -0
  357. sage/schemes/elliptic_curves/all__sagemath_flint.py +1 -0
  358. sage/schemes/elliptic_curves/descent_two_isogeny.cpython-310-aarch64-linux-gnu.so +0 -0
  359. sage/schemes/elliptic_curves/descent_two_isogeny.pyx +1387 -0
  360. sage/schemes/elliptic_curves/descent_two_isogeny_pari.pxd +5 -0
@@ -0,0 +1,1294 @@
1
+ # sage_setup: distribution = sagemath-flint
2
+ # sage.doctest: needs sage.libs.pari
3
+ """
4
+ Modular algorithm to compute Hermite normal forms of integer matrices
5
+
6
+ AUTHORS:
7
+
8
+ - Clement Pernet and William Stein (2008-02-07): initial version
9
+ """
10
+
11
+ from copy import copy
12
+
13
+ from sage.arith.misc import CRT_list, previous_prime
14
+ from sage.matrix.constructor import identity_matrix, matrix, random_matrix
15
+ from sage.misc.timing import cputime
16
+ from sage.misc.verbose import verbose
17
+ from sage.rings.integer import Integer
18
+ from sage.rings.integer_ring import ZZ
19
+ from sage.rings.real_mpfr import RR
20
+
21
+
22
+ def max_det_prime(n):
23
+ """
24
+ Return the largest prime so that it is reasonably efficient to
25
+ compute modulo that prime with n x n matrices in LinBox.
26
+
27
+ INPUT:
28
+
29
+ - ``n`` -- positive integer
30
+
31
+ OUTPUT: a prime number
32
+
33
+ EXAMPLES::
34
+
35
+ sage: from sage.matrix.matrix_integer_dense_hnf import max_det_prime
36
+ sage: max_det_prime(10000)
37
+ 8388593
38
+ sage: max_det_prime(1000)
39
+ 8388593
40
+ sage: max_det_prime(10)
41
+ 8388593
42
+ """
43
+ # See #14032: LinBox now uses a constant bound of 2^23.
44
+ # This is the largest prime less than that bound.
45
+ return Integer(8388593)
46
+
47
+
48
+ def det_from_modp_and_divisor(A, d, p, z_mod, moduli, z_so_far=ZZ(1), N_so_far=ZZ(1)):
49
+ """
50
+ This is used for internal purposes for computing determinants
51
+ quickly (with the hybrid `p`-adic / multimodular algorithm).
52
+
53
+ INPUT:
54
+
55
+ - ``A`` -- a square matrix
56
+ - ``d`` -- a divisor of the determinant of A
57
+ - ``p`` -- a prime
58
+ - ``z_mod`` -- values of det/d (mod ...)
59
+ - ``moduli`` -- the moduli so far
60
+ - ``z_so_far`` -- for a modulus p in the list moduli,
61
+ (z_so_far mod p) is the determinant of A modulo p
62
+ - ``N_so_far`` -- N_so_far is the product over the primes in the list moduli
63
+
64
+ OUTPUT:
65
+
66
+ - A triple (det bound, new z_so_far, new N_so_far).
67
+
68
+ EXAMPLES::
69
+
70
+ sage: a = matrix(ZZ, 3, [6, 1, 2, -56, -2, -1, -11, 2, -3])
71
+ sage: factor(a.det())
72
+ -1 * 13 * 29
73
+ sage: d = 13
74
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
75
+ sage: matrix_integer_dense_hnf.det_from_modp_and_divisor(a, d, 97, [], [])
76
+ (-377, -29, 97)
77
+ sage: a.det()
78
+ -377
79
+ """
80
+ tm = verbose("Multimodular stage of det calculation -- using p = %s" % p, level=2)
81
+ z = A.mod(p).det() / d
82
+ z = z.lift()
83
+ z_mod.append(z)
84
+ moduli.append(p)
85
+ z = CRT_list([z_so_far, z], [N_so_far, p])
86
+ N = N_so_far*p
87
+
88
+ if z > N // 2:
89
+ z -= N
90
+ verbose("Finished multimodular det for p = %s" % p, tm, level=2)
91
+ return (d * z, z, N)
92
+
93
+
94
+ def det_given_divisor(A, d, proof=True, stabilize=2):
95
+ """
96
+ Given a divisor d of the determinant of A, compute the determinant of A.
97
+
98
+ INPUT:
99
+
100
+ - ``A`` -- square integer matrix
101
+ - ``d`` -- nonzero integer that is assumed to divide the determinant of A
102
+ - ``proof`` -- boolean (default: ``True``); compute det modulo enough primes
103
+ so that the determinant is computed provably correctly (via the
104
+ Hadamard bound). It would be VERY hard for ``det()`` to fail even
105
+ when ``proof`` is ``False``.
106
+ - ``stabilize`` -- integer (default: 2); if proof = False, then compute
107
+ the determinant modulo `p` until ``stabilize`` successive modulo
108
+ determinant computations stabilize.
109
+
110
+ OUTPUT: integer; determinant
111
+
112
+ EXAMPLES::
113
+
114
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
115
+ sage: a = matrix(ZZ,3,[-1, -1, -1, -20, 4, 1, -1, 1, 2])
116
+ sage: matrix_integer_dense_hnf.det_given_divisor(a, 3)
117
+ -30
118
+ sage: matrix_integer_dense_hnf.det_given_divisor(a, 3, proof=False)
119
+ -30
120
+ sage: matrix_integer_dense_hnf.det_given_divisor(a, 3, proof=False, stabilize=1)
121
+ -30
122
+ sage: a.det()
123
+ -30
124
+
125
+ Here we illustrate proof=False giving a wrong answer::
126
+
127
+ sage: p = matrix_integer_dense_hnf.max_det_prime(2)
128
+ sage: q = previous_prime(p)
129
+ sage: a = matrix(ZZ, 2, [p, 0, 0, q])
130
+ sage: p * q
131
+ 70368442188091
132
+ sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=2)
133
+ 0
134
+
135
+ This still works, because we do not work modulo primes that divide
136
+ the determinant bound, which is found using a `p`-adic algorithm::
137
+
138
+ sage: a.det(proof=False, stabilize=2)
139
+ 70368442188091
140
+
141
+ 3 primes is enough::
142
+
143
+ sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=3)
144
+ 70368442188091
145
+ sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=5)
146
+ 70368442188091
147
+ sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=True)
148
+ 70368442188091
149
+
150
+ TESTS::
151
+
152
+ sage: m = diagonal_matrix(ZZ, 68, [2]*66 + [1,1])
153
+ sage: m.det()
154
+ 73786976294838206464
155
+ """
156
+ p = max_det_prime(A.nrows())
157
+ z_mod = []
158
+ moduli = []
159
+ assert d != 0
160
+ z_so_far = 1
161
+ N_so_far = 1
162
+ if proof:
163
+ N = 1
164
+ B = (2 * 10**A.hadamard_bound()) // d + 1
165
+ dd = d
166
+ # bad verbose statement, since computing the log overflows!
167
+ est = int(RR(B).log() / RR(p).log()) + 1
168
+ cnt = 1
169
+ verbose("Multimodular det -- need to use about %s primes." % est,
170
+ level=1)
171
+ while N < B:
172
+ if d % p != 0:
173
+ tm = cputime()
174
+ dd, z_so_far, N_so_far = det_from_modp_and_divisor(A, d, p, z_mod, moduli, z_so_far, N_so_far)
175
+ N *= p
176
+ verbose("computed det mod p=%s which is %s (of about %s)" % (p, cnt, est), tm)
177
+ p = previous_prime(p)
178
+ cnt += 1
179
+ return dd
180
+ else:
181
+ val = []
182
+ while True:
183
+ if d % p:
184
+ tm = cputime()
185
+ dd, z_so_far, N_so_far = det_from_modp_and_divisor(A, d, p, z_mod, moduli, z_so_far, N_so_far)
186
+ verbose("computed det mod %s" % p, tm)
187
+ val.append(dd)
188
+ if len(val) >= stabilize and len(set(val[-stabilize:])) == 1:
189
+ return val[-1]
190
+ p = previous_prime(p)
191
+
192
+
193
+ def det_padic(A, proof=True, stabilize=2):
194
+ """
195
+ Return the determinant of A, computed using a `p`-adic/multimodular
196
+ algorithm.
197
+
198
+ INPUT:
199
+
200
+ - ``A`` -- a square matrix
201
+
202
+ - ``proof`` -- boolean
203
+
204
+ - ``stabilize`` -- (default: 2) if proof False, number of successive primes so that
205
+ CRT det must stabilize
206
+
207
+ EXAMPLES::
208
+
209
+ sage: import sage.matrix.matrix_integer_dense_hnf as h
210
+ sage: a = matrix(ZZ, 3, [1..9])
211
+ sage: h.det_padic(a)
212
+ 0
213
+ sage: a = matrix(ZZ, 3, [1,2,5,-7,8,10,192,5,18])
214
+ sage: h.det_padic(a)
215
+ -3669
216
+ sage: a.determinant(algorithm='ntl')
217
+ -3669
218
+ """
219
+ if not A.is_square():
220
+ raise ValueError("A must be a square matrix")
221
+ r = A.rank()
222
+ if r < A.nrows():
223
+ return ZZ.zero()
224
+ v = random_matrix(ZZ, A.nrows(), 1)
225
+ d = A._solve_right_nonsingular_square(v, check_rank=False).denominator()
226
+ return det_given_divisor(A, d, proof=proof, stabilize=stabilize)
227
+
228
+
229
+ def double_det(A, b, c, proof):
230
+ """
231
+ Compute the determinants of the stacked integer matrices
232
+ A.stack(b) and A.stack(c).
233
+
234
+ INPUT:
235
+
236
+ - ``A`` -- an (n-1) x n matrix
237
+ - ``b`` -- a 1 x n matrix
238
+ - ``c`` -- a 1 x n matrix
239
+ - ``proof`` -- whether or not to compute the det modulo enough times to
240
+ provably compute the determinant
241
+
242
+ OUTPUT: a pair of two integers
243
+
244
+ EXAMPLES::
245
+
246
+ sage: from sage.matrix.matrix_integer_dense_hnf import double_det
247
+ sage: A = matrix(ZZ, 2, 3, [1,2,3, 4,-2,5])
248
+ sage: b = matrix(ZZ, 1, 3, [1,-2,5])
249
+ sage: c = matrix(ZZ, 1, 3, [8,2,10])
250
+ sage: A.stack(b).det()
251
+ -48
252
+ sage: A.stack(c).det()
253
+ 42
254
+ sage: double_det(A, b, c, False)
255
+ (-48, 42)
256
+ """
257
+ # We use the "two for the price of one" algorithm, which I made up. (William Stein)
258
+
259
+ # This is a clever trick! First we transpose everything. Then
260
+ # we use that if [A|b]*v = c then [A|c]*w = b with w easy to write down!
261
+ # In fact w is got from v by dividing all entries by -v[n], where n is the
262
+ # number of rows of v, and *also* dividing the last entry of w by v[n] again.
263
+ # See this as an algebra exercise where you have to think of matrix vector
264
+ # multiply as "linear combination of columns".
265
+ A = A.transpose()
266
+ b = b.transpose()
267
+ c = c.transpose()
268
+ t = verbose('starting double det')
269
+ B = A.augment(b)
270
+ v = B.solve_right(-c)
271
+
272
+ db = det_given_divisor(B, v.denominator(), proof=proof)
273
+
274
+ n = v.nrows()
275
+ vn = v[n - 1, 0]
276
+ w = (-1 / vn) * v
277
+ w[n - 1] = w[n - 1] / vn
278
+ dc = det_given_divisor(A.augment(c), w.denominator(), proof=proof)
279
+
280
+ verbose('finished double det', t)
281
+
282
+ return (db, dc)
283
+
284
+
285
+ def add_column_fallback(B, a, proof):
286
+ """
287
+ Simplistic version of add_column, in case the powerful clever one
288
+ fails (e.g., B is singular).
289
+
290
+ INPUT:
291
+
292
+ - ``B`` -- a square matrix (may be singular)
293
+ - ``a`` -- an n x 1 matrix, where B has n rows
294
+ - ``proof`` -- boolean; whether to prove result correct
295
+
296
+ OUTPUT: x; a vector such that ``H' = H_B.augment(x)`` is the HNF of
297
+ ``A = B.augment(a)``
298
+
299
+ EXAMPLES::
300
+
301
+ sage: B = matrix(ZZ,3, [-1, -1, 1, -3, 8, -2, -1, -1, -1])
302
+ sage: a = matrix(ZZ,3,1, [1,2,3])
303
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
304
+ sage: matrix_integer_dense_hnf.add_column_fallback(B, a, True)
305
+ [-3]
306
+ [-7]
307
+ [-2]
308
+ sage: matrix_integer_dense_hnf.add_column_fallback(B, a, False)
309
+ [-3]
310
+ [-7]
311
+ [-2]
312
+ sage: B.augment(a).hermite_form()
313
+ [ 1 1 1 -3]
314
+ [ 0 11 1 -7]
315
+ [ 0 0 2 -2]
316
+ """
317
+ tt = verbose('add column fallback...')
318
+ W = B.augment(matrix(ZZ,B.nrows(),a.list()))
319
+ H, _ = hnf(W, proof)
320
+ C = H.matrix_from_columns([H.ncols()-1])
321
+ verbose('finished add column fallback', tt)
322
+ return C
323
+
324
+
325
+ def solve_system_with_difficult_last_row(B, a):
326
+ """
327
+ Solve ``B*x = a`` when the last row of `B` contains huge entries using
328
+ a clever trick that reduces the problem to solve ``C*x = a`` where `C`
329
+ is `B` but with the last row replaced by something small, along
330
+ with one easy null space computation. The latter are both solved
331
+ `p`-adically.
332
+
333
+ INPUT:
334
+
335
+ - ``B`` -- a square n x n nonsingular matrix with painful big bottom row
336
+ - ``a`` -- an n x 1 column matrix
337
+
338
+ OUTPUT: the unique solution to ``B*x = a``
339
+
340
+ EXAMPLES::
341
+
342
+ sage: from sage.matrix.matrix_integer_dense_hnf import solve_system_with_difficult_last_row
343
+ sage: B = matrix(ZZ, 3, [1,2,4, 3,-4,7, 939082,2930982,132902384098234])
344
+ sage: a = matrix(ZZ,3,1, [1,2,5])
345
+ sage: z = solve_system_with_difficult_last_row(B, a)
346
+ sage: z
347
+ [ 106321906985474/132902379815497]
348
+ [132902385037291/1329023798154970]
349
+ [ -5221794/664511899077485]
350
+ sage: B*z
351
+ [1]
352
+ [2]
353
+ [5]
354
+ """
355
+ # Here's how:
356
+ # 1. We make a copy of B but with the last *nasty* row of B replaced
357
+ # by a random very nice row.
358
+ C = copy(B)
359
+ while True:
360
+ C[C.nrows()-1] = random_matrix(ZZ,1,C.ncols()).row(0)
361
+ # 2. Then we find the unique solution to C * x = a
362
+ try:
363
+ x = C.solve_right(a)
364
+ except ValueError:
365
+ verbose("Try difficult solve again with different random vector")
366
+ else:
367
+ break
368
+
369
+ # 3. We next delete the last row of B and find a basis vector k
370
+ # for the 1-dimensional kernel.
371
+ D = B.matrix_from_rows(range(C.nrows()-1))
372
+ from .matrix_integer_iml import _rational_kernel_iml
373
+ N = _rational_kernel_iml(D)
374
+ if N.ncols() != 1:
375
+ verbose("Try difficult solve again with different random vector")
376
+ return solve_system_with_difficult_last_row(B, a)
377
+
378
+ k = N.matrix_from_columns([0])
379
+
380
+ # 4. The sought for solution z to B*z = a is some linear combination
381
+ #
382
+ # z = x + alpha*k
383
+ #
384
+ # of x and k, where k is the above fixed basis for the kernel of D.
385
+ # Setting w to be the last row of B, this column vector z satisfies
386
+ #
387
+ # w * z = a'
388
+ #
389
+ # where a' is the last entry of a. Thus
390
+ #
391
+ # w * (x + alpha*k) = a'
392
+ #
393
+ # so w * x + alpha*w*k = a'
394
+ # so alpha*w*k = a' - w*x.
395
+
396
+ w = B[-1] # last row of B
397
+ a_prime = a[-1]
398
+ lhs = w*k
399
+ rhs = a_prime - w * x
400
+
401
+ if lhs[0] == 0:
402
+ verbose("Try difficult solve again with different random vector")
403
+ return solve_system_with_difficult_last_row(B, a)
404
+
405
+ alpha = rhs[0] / lhs[0]
406
+ z = x + alpha*k
407
+ return z
408
+
409
+
410
+ def add_column(B, H_B, a, proof):
411
+ """
412
+ The add column procedure.
413
+
414
+ INPUT:
415
+
416
+ - ``B`` -- a square matrix (may be singular)
417
+ - ``H_B`` -- the Hermite normal form of B
418
+ - ``a`` -- an n x 1 matrix, where B has n rows
419
+ - ``proof`` -- boolean; whether to prove result correct, in case we use fallback method
420
+
421
+ OUTPUT:
422
+
423
+ - x -- a vector such that H' = H_B.augment(x) is the HNF of A = B.augment(a)
424
+
425
+ EXAMPLES::
426
+
427
+ sage: B = matrix(ZZ, 3, 3, [1,2,5, 0,-5,3, 1,1,2])
428
+ sage: H_B = B.echelon_form()
429
+ sage: a = matrix(ZZ, 3, 1, [1,8,-2])
430
+ sage: import sage.matrix.matrix_integer_dense_hnf as hnf
431
+ sage: x = hnf.add_column(B, H_B, a, True); x
432
+ [18]
433
+ [ 3]
434
+ [23]
435
+ sage: H_B.augment(x)
436
+ [ 1 0 17 18]
437
+ [ 0 1 3 3]
438
+ [ 0 0 18 23]
439
+ sage: B.augment(a).echelon_form()
440
+ [ 1 0 17 18]
441
+ [ 0 1 3 3]
442
+ [ 0 0 18 23]
443
+ """
444
+ verbose('starting add_column')
445
+
446
+ if B.rank() < B.nrows():
447
+ return add_column_fallback(B, a, proof)
448
+ else:
449
+ z = solve_system_with_difficult_last_row(B, a)
450
+
451
+ zd, d = z._clear_denom()
452
+ x = H_B * zd
453
+ if d != 1:
454
+ for i in range(x.nrows()):
455
+ x[i, 0] = x[i, 0] / d
456
+
457
+ return x
458
+
459
+
460
+ def add_row(A, b, pivots, include_zero_rows):
461
+ """
462
+ The add row procedure.
463
+
464
+ INPUT:
465
+
466
+ - ``A`` -- a matrix in Hermite normal form with n column
467
+ - ``b`` -- an n x 1 row matrix
468
+ - ``pivots`` -- sorted list of integers; the pivot positions of A
469
+
470
+ OUTPUT:
471
+
472
+ - ``H`` -- the Hermite normal form of A.stack(b)
473
+ - ``new_pivots`` -- the pivot columns of H
474
+
475
+ EXAMPLES::
476
+
477
+ sage: import sage.matrix.matrix_integer_dense_hnf as hnf
478
+ sage: A = matrix(ZZ, 2, 3, [-21, -7, 5, 1,20,-7])
479
+ sage: b = matrix(ZZ, 1,3, [-1,1,-1])
480
+ sage: hnf.add_row(A, b, A.pivots(), True)
481
+ (
482
+ [ 1 6 29]
483
+ [ 0 7 28]
484
+ [ 0 0 46], [0, 1, 2]
485
+ )
486
+ sage: A.stack(b).echelon_form()
487
+ [ 1 6 29]
488
+ [ 0 7 28]
489
+ [ 0 0 46]
490
+ """
491
+ t = verbose('add hnf row')
492
+ H, pivs = A._add_row_and_maintain_echelon_form(b.row(0), pivots)
493
+ if include_zero_rows and H.nrows() != A.nrows() + 1:
494
+ H = H.matrix_from_rows(range(A.nrows() + 1))
495
+ verbose('finished add hnf row', t)
496
+ return H, pivs
497
+
498
+
499
+ def pivots_of_hnf_matrix(H):
500
+ """
501
+ Return the pivot columns of a matrix H assumed to be in HNF.
502
+
503
+ INPUT:
504
+
505
+ - ``H`` -- a matrix that must be HNF
506
+
507
+ OUTPUT: list of pivots
508
+
509
+ EXAMPLES::
510
+
511
+ sage: H = matrix(ZZ, 3, 5, [1, 0, 0, 45, -36, 0, 1, 0, 131, -107, 0, 0, 0, 178, -145]); H
512
+ [ 1 0 0 45 -36]
513
+ [ 0 1 0 131 -107]
514
+ [ 0 0 0 178 -145]
515
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
516
+ sage: matrix_integer_dense_hnf.pivots_of_hnf_matrix(H)
517
+ [0, 1, 3]
518
+ """
519
+ pivots = []
520
+ r = -1
521
+ for j in range(H.ncols()):
522
+ # Find first nonzero position (counting from bottom) in the j-th column
523
+ for i in reversed(range(H.nrows())):
524
+ if H[i, j]:
525
+ if i > r:
526
+ pivots.append(j)
527
+ r = i
528
+ else:
529
+ break
530
+ return pivots
531
+
532
+
533
+ def hnf_square(A, proof):
534
+ """
535
+ INPUT:
536
+
537
+ - ``A`` -- a nonsingular n x n matrix over the integers
538
+
539
+ OUTPUT: the Hermite normal form of A
540
+
541
+ EXAMPLES::
542
+
543
+ sage: import sage.matrix.matrix_integer_dense_hnf as hnf
544
+ sage: A = matrix(ZZ, 3, [-21, -7, 5, 1,20,-7, -1,1,-1])
545
+ sage: hnf.hnf_square(A, False)
546
+ [ 1 6 29]
547
+ [ 0 7 28]
548
+ [ 0 0 46]
549
+ sage: A.echelon_form()
550
+ [ 1 6 29]
551
+ [ 0 7 28]
552
+ [ 0 0 46]
553
+ """
554
+ n = A.nrows()
555
+ m = A.ncols()
556
+ if n != m:
557
+ raise ValueError("A must be square.")
558
+
559
+ # Small cases -- do not use this algorithm
560
+ if n <= 3:
561
+ return A.echelon_form(algorithm='pari')
562
+
563
+ if A.rank() < A.nrows():
564
+ raise ValueError("matrix must have full rank")
565
+
566
+ t = verbose("starting slicings")
567
+ B = A.matrix_from_rows(range(m-2)).matrix_from_columns(range(n-1))
568
+ c = A.matrix_from_rows([m-2]).matrix_from_columns(range(n-1))
569
+ d = A.matrix_from_rows([m-1]).matrix_from_columns(range(n-1))
570
+ b = A.matrix_from_columns([n-1]).matrix_from_rows(range(m-2))
571
+ verbose("done slicing", t)
572
+
573
+ try:
574
+ d1, d2 = double_det(B, c, d, proof=proof)
575
+ except (ValueError, ZeroDivisionError):
576
+ d1 = B.stack(c).det(proof=proof)
577
+ d2 = B.stack(d).det(proof=proof)
578
+
579
+ g, k, l = d1._xgcd(d2, minimal=True)
580
+
581
+ W = B.stack(k * c + l * d)
582
+ verbose("submatrix det: g=%s" % g)
583
+ CUTOFF = 2147483647 # 2^31-1
584
+ if g == 0:
585
+ # Big trouble -- matrix is not invertible
586
+ # Since we have no good conditioning code at present,
587
+ # in this case we just fall back to using pari.
588
+ H = W.echelon_form(algorithm='pari')
589
+ elif 2 * g > CUTOFF:
590
+ # Unlikely that g will be large on even slightly random input
591
+ # if it is, we fallback to the traditional algorithm.
592
+ # A nasty example is A = n*random_matrix(ZZ,m), where
593
+ # this algorithm gets killed. This is not random input though.
594
+ f = W.gcd()
595
+ g = g / (f**W.nrows())
596
+ if 2 * g <= CUTOFF:
597
+ verbose("Found common factor of %s -- dividing out; get new g = %s" % (f, g))
598
+ W0 = (W / f).change_ring(ZZ)
599
+ H = W0._hnf_mod(2 * g)
600
+ H *= f
601
+ else:
602
+ verbose("Falling back to PARI HNF since input matrix is ill conditioned for p-adic hnf algorithm.")
603
+ # We need more clever preconditioning?
604
+ # It is important to *not* just do the submatrix, since
605
+ # the whole rest of the algorithm will likely be very slow in
606
+ # weird cases where the det is large.
607
+ # E.g., matrix all of whose rows but 1 are multiplied by some
608
+ # fixed scalar n.
609
+ raise NotImplementedError("fallback to PARI")
610
+ # H = W.hermite_form(algorithm='pari')
611
+ else:
612
+ H = W._hnf_mod(2 * g)
613
+
614
+ x = add_column(W, H, b.stack(matrix(1, 1,
615
+ [k*A[m-2,m-1] + l*A[m-1,m-1]])),
616
+ proof)
617
+ Hprime = H.augment(x)
618
+ pivots = pivots_of_hnf_matrix(Hprime)
619
+
620
+ Hprime, pivots = add_row(Hprime, A.matrix_from_rows([m - 2]),
621
+ pivots, include_zero_rows=False)
622
+ Hprime, pivots = add_row(Hprime, A.matrix_from_rows([m - 1]),
623
+ pivots, include_zero_rows=False)
624
+ return Hprime.matrix_from_rows(range(m))
625
+
626
+
627
+ def interleave_matrices(A, B, cols1, cols2):
628
+ """
629
+ INPUT:
630
+
631
+ - A, B -- matrices with the same number of rows
632
+ - cols1, cols2 -- disjoint lists of integers
633
+
634
+ OUTPUT:
635
+
636
+ construct a new matrix C by sticking the columns
637
+ of A at the positions specified by cols1 and the
638
+ columns of B at the positions specified by cols2.
639
+
640
+ EXAMPLES::
641
+
642
+ sage: A = matrix(ZZ, 2, [1,2,3,4]); B = matrix(ZZ, 2, [-1,5,2,3])
643
+ sage: A
644
+ [1 2]
645
+ [3 4]
646
+ sage: B
647
+ [-1 5]
648
+ [ 2 3]
649
+ sage: import sage.matrix.matrix_integer_dense_hnf as hnf
650
+ sage: hnf.interleave_matrices(A, B, [1,3], [0,2])
651
+ [-1 1 5 2]
652
+ [ 2 3 3 4]
653
+ """
654
+ D = A.augment(B)
655
+ w = cols1 + cols2
656
+ v = [w.index(i) for i in range(len(cols1) + len(cols2))]
657
+ return D.matrix_from_columns(v)
658
+
659
+
660
+ def probable_pivot_rows(A):
661
+ """
662
+ Return rows of A that are very likely to be pivots.
663
+
664
+ This really finds the pivots of A modulo a random prime.
665
+
666
+ INPUT:
667
+
668
+ - ``A`` -- a matrix
669
+
670
+ OUTPUT: a tuple of integers
671
+
672
+ EXAMPLES::
673
+
674
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
675
+ sage: a = matrix(ZZ,3,[0, -1, -1, 0, -20, 1, 0, 1, 2])
676
+ sage: a
677
+ [ 0 -1 -1]
678
+ [ 0 -20 1]
679
+ [ 0 1 2]
680
+ sage: matrix_integer_dense_hnf.probable_pivot_rows(a)
681
+ (0, 1)
682
+ """
683
+ return probable_pivot_columns(A.transpose())
684
+
685
+
686
+ def probable_pivot_columns(A):
687
+ """
688
+ INPUT:
689
+
690
+ - ``A`` -- a matrix
691
+
692
+ OUTPUT: a tuple of integers
693
+
694
+ EXAMPLES::
695
+
696
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
697
+ sage: a = matrix(ZZ,3,[0, -1, -1, 0, -20, 1, 0, 1, 2])
698
+ sage: a
699
+ [ 0 -1 -1]
700
+ [ 0 -20 1]
701
+ [ 0 1 2]
702
+ sage: matrix_integer_dense_hnf.probable_pivot_columns(a)
703
+ (1, 2)
704
+ """
705
+ p = ZZ.random_element(10007, 46000).next_prime()
706
+ return A._reduce(p).pivots()
707
+
708
+
709
+ def ones(H, pivots):
710
+ """
711
+ Find all 1 pivot columns of the matrix H in Hermite form, along
712
+ with the corresponding rows, and also the non 1 pivot columns and
713
+ non-pivot rows. Here a 1 pivot column is a pivot column so that
714
+ the leading bottom entry is 1.
715
+
716
+ INPUT:
717
+
718
+ - ``H`` -- matrix in Hermite form
719
+ - ``pivots`` -- list of integers (all pivot positions of H)
720
+
721
+ OUTPUT:
722
+
723
+ 4-tuple of integer lists: onecol, onerow, non_oneol, non_onerow
724
+
725
+ EXAMPLES::
726
+
727
+ sage: H = matrix(ZZ, 3, 5, [1, 0, 0, 45, -36, 0, 1, 0, 131, -107, 0, 0, 0, 178, -145]); H
728
+ [ 1 0 0 45 -36]
729
+ [ 0 1 0 131 -107]
730
+ [ 0 0 0 178 -145]
731
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
732
+ sage: matrix_integer_dense_hnf.ones(H, [0,1,3])
733
+ ([0, 1], [0, 1], [2], [2])
734
+ """
735
+ # Find the "onecol" pivot columns of H, i.e., the columns
736
+ # that contain exactly one "1" entry and all other entries 0.
737
+ onecol = []
738
+ onerow = []
739
+ i = 0
740
+ for c in pivots:
741
+ if H[i, c] == 1:
742
+ onecol.append(c)
743
+ onerow.append(i)
744
+ i += 1
745
+ onecol_set = set(onecol)
746
+ non_onerow = [j for j in range(len(pivots)) if j not in onerow]
747
+ non_onecol = [j for j in range(H.ncols()) if j not in onecol_set][:len(non_onerow)]
748
+ return onecol, onerow, non_onecol, non_onerow
749
+
750
+
751
+ def extract_ones_data(H, pivots):
752
+ """
753
+ Compute ones data and corresponding submatrices of H.
754
+
755
+ This is used to optimized the :func:`add_row` function.
756
+
757
+ INPUT:
758
+
759
+ - ``H`` -- a matrix in HNF
760
+ - ``pivots`` -- list of all pivot column positions of H
761
+
762
+ OUTPUT:
763
+
764
+ C, D, E, onecol, onerow, non_onecol, non_onerow
765
+ where onecol, onerow, non_onecol, non_onerow are as for
766
+ the ones function, and C, D, E are matrices:
767
+
768
+ - ``C`` -- submatrix of all non-onecol columns and onecol rows
769
+ - ``D`` -- all non-onecol columns and other rows
770
+ - ``E`` -- inverse of D
771
+
772
+ If D is not invertible or there are 0 or more than 2 non onecols,
773
+ then C, D, and E are set to None.
774
+
775
+ EXAMPLES::
776
+
777
+ sage: H = matrix(ZZ, 3, 4, [1, 0, 0, 7, 0, 1, 5, 2, 0, 0, 6, 6])
778
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
779
+ sage: matrix_integer_dense_hnf.extract_ones_data(H, [0,1,2])
780
+ (
781
+ [0]
782
+ [5], [6], [1/6], [0, 1], [0, 1], [2], [2]
783
+ )
784
+
785
+ Here we get None's since the (2,2) position submatrix is not invertible.
786
+ sage: H = matrix(ZZ, 3, 5, [1, 0, 0, 45, -36, 0, 1, 0, 131, -107, 0, 0, 0, 178, -145]); H
787
+ [ 1 0 0 45 -36]
788
+ [ 0 1 0 131 -107]
789
+ [ 0 0 0 178 -145]
790
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
791
+ sage: matrix_integer_dense_hnf.extract_ones_data(H, [0,1,3])
792
+ (None, None, None, [0, 1], [0, 1], [2], [2])
793
+ """
794
+ onecol, onerow, non_onecol, non_onerow = ones(H, pivots)
795
+ verbose('extract_ones -- got submatrix of size %s' % len(non_onecol))
796
+ if len(non_onecol) in [1, 2]:
797
+ # Extract submatrix of all non-onecol columns and onecol rows
798
+ C = H.matrix_from_rows_and_columns(onerow, non_onecol)
799
+ # Extract submatrix of all non-onecol columns and other rows
800
+ D = H.matrix_from_rows_and_columns(non_onerow, non_onecol).transpose()
801
+ tt = verbose("extract ones -- INVERT %s x %s" % (len(non_onerow), len(non_onecol)), level=1)
802
+ try:
803
+ E = D**(-1)
804
+ except ZeroDivisionError:
805
+ C = D = E = None
806
+ verbose("done inverting", tt, level=1)
807
+ return C, D, E, onecol, onerow, non_onecol, non_onerow
808
+ else:
809
+ return None, None, None, onecol, onerow, non_onecol, non_onerow
810
+
811
+
812
+ def is_in_hnf_form(H, pivots):
813
+ """
814
+ Return whether the matrix ``H`` is in Hermite normal form
815
+ with given pivot columns.
816
+
817
+ INPUT:
818
+
819
+ - ``H`` -- matrix
820
+ - ``pivots`` -- sorted list of integers
821
+
822
+ OUTPUT: boolean
823
+
824
+ EXAMPLES::
825
+
826
+ sage: a = matrix(ZZ,3,5,[-2, -6, -3, -17, -1, 2, -1, -1, -2, -1, -2, -2, -6, 9, 2])
827
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
828
+ sage: matrix_integer_dense_hnf.is_in_hnf_form(a,range(3))
829
+ False
830
+ sage: e = a.hermite_form(); p = a.pivots()
831
+ sage: matrix_integer_dense_hnf.is_in_hnf_form(e, p)
832
+ True
833
+ """
834
+ tt = verbose('testing if matrix is in HNF')
835
+ r = 0
836
+ pivots_set = set(pivots)
837
+ for j in range(H.ncols()):
838
+ if j in pivots_set:
839
+ for i in range(r + 1, H.nrows()):
840
+ if H[i, j]:
841
+ verbose('not HNF because nonzeros below pivot position',tt)
842
+ return False
843
+ for i in range(r):
844
+ if H[i, j] < 0 or H[i, j] >= H[r, j]:
845
+ verbose('not HNF because negative or too big above pivot position',tt)
846
+ return False
847
+ r += 1
848
+ else:
849
+ for i in range(r, H.nrows()):
850
+ if H[i, j]:
851
+ verbose('not HNF nonzero in wrong place in nonpivot column',tt)
852
+ return False
853
+ verbose('done verifying in HNF -- yes', tt)
854
+ return True
855
+
856
+
857
+ def probable_hnf(A, include_zero_rows, proof):
858
+ """
859
+ Return the HNF of A or raise an exception if something involving
860
+ the randomized nature of the algorithm goes wrong along the way.
861
+
862
+ Calling this function again a few times should result it in it
863
+ working, at least if proof=True.
864
+
865
+ INPUT:
866
+
867
+ - ``A`` -- a matrix
868
+ - ``include_zero_rows`` -- boolean
869
+ - ``proof`` -- boolean
870
+
871
+ OUTPUT:
872
+
873
+ the Hermite normal form of A.
874
+ cols -- pivot columns
875
+
876
+ EXAMPLES::
877
+
878
+ sage: a = matrix(ZZ,4,3,[-1, -1, -1, -20, 4, 1, -1, 1, 2,1,2,3])
879
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
880
+ sage: matrix_integer_dense_hnf.probable_hnf(a, True, True)
881
+ (
882
+ [1 0 0]
883
+ [0 1 0]
884
+ [0 0 1]
885
+ [0 0 0], [0, 1, 2]
886
+ )
887
+ sage: matrix_integer_dense_hnf.probable_hnf(a, False, True)
888
+ (
889
+ [1 0 0]
890
+ [0 1 0]
891
+ [0 0 1], [0, 1, 2]
892
+ )
893
+ sage: matrix_integer_dense_hnf.probable_hnf(a, False, False)
894
+ (
895
+ [1 0 0]
896
+ [0 1 0]
897
+ [0 0 1], [0, 1, 2]
898
+ )
899
+ """
900
+ # Find left-most full rank submatrix by working modulo a prime
901
+ rows = list(probable_pivot_rows(A))
902
+ B = A.matrix_from_rows(rows)
903
+ cols = list(probable_pivot_columns(B))
904
+ C = B.matrix_from_columns(cols)
905
+ # Now C is a submatrix of A that has full rank and is square.
906
+
907
+ # We compute the HNF of C, which is a square nonsingular matrix.
908
+ try:
909
+ H = hnf_square(C, proof=proof)
910
+ except NotImplementedError:
911
+ # raise
912
+ # this signals that we must fallback to PARI
913
+ verbose("generic random modular HNF algorithm failed -- we fall back to PARI")
914
+ H = A.hermite_form(algorithm='pari', include_zero_rows=include_zero_rows, proof=proof)
915
+ return H, H.pivots()
916
+
917
+ # The transformation matrix to HNF is the unique
918
+ # matrix U such that U * C = H, i.e., U = H*C^(-1).
919
+
920
+ if len(cols) < B.ncols():
921
+ # We compute the HNF of B by multiplying the matrix D
922
+ # got from the columns not in C by U:
923
+ # We want to compute X = U*D. But U = H*C^(-1),
924
+ # so X = U*D = H*C^(-1)*D.
925
+ # So C*H^(-1)*X = D
926
+
927
+ # find y s.t C*y = D
928
+ # H^(-1)*X = y ===> X = H*y
929
+ #
930
+ cols_set = set(cols)
931
+ cols2 = [i for i in range(B.ncols()) if i not in cols_set]
932
+ D = B.matrix_from_columns(cols2)
933
+ Y = C.solve_right(D)
934
+ H2 = H * Y
935
+ H2 = H2.change_ring(ZZ)
936
+
937
+ # The HNF of B is got by assembling together
938
+ # the matrices H and H2.
939
+ H = interleave_matrices(H, H2, cols, cols2)
940
+
941
+ pivots = pivots_of_hnf_matrix(H)
942
+
943
+ # Now H is the HNF of the matrix B.
944
+ # Finally we add all remaining rows of A to H using
945
+ # the add_row function.
946
+
947
+ C, D, E, onecol, onerow, non_onecol, non_onerow = extract_ones_data(H, cols)
948
+ if not proof and len(non_onecol) == 0:
949
+ # Identity matrix -- done
950
+ verbose("hnf -- got identity matrix -- early abort (0)")
951
+ if include_zero_rows:
952
+ H = pad_zeros(H, A.nrows())
953
+ return H, pivots
954
+
955
+ rows_set = set(rows)
956
+ for i in range(A.nrows()):
957
+ if i not in rows_set:
958
+ v = A.matrix_from_rows([i])
959
+ if v == 0:
960
+ continue
961
+ if E is None:
962
+ H, pivots = add_row(H, v, pivots, include_zero_rows=False)
963
+ C, D, E, onecol, onerow, non_onecol, non_onerow = extract_ones_data(H, pivots)
964
+ if not proof and len(non_onecol) == 0:
965
+ # Identity matrix -- done
966
+ verbose("hnf -- got identity matrix -- early abort (1)")
967
+ if include_zero_rows:
968
+ H = pad_zeros(H, A.nrows())
969
+ return H, pivots
970
+ else:
971
+ z = A.matrix_from_rows_and_columns([i], non_onecol)
972
+ w = A.matrix_from_rows_and_columns([i], onecol)
973
+ tt = verbose("checking denom (%s x %s)" % (D.nrows(),
974
+ D.ncols()))
975
+ Y = (z - w * C).transpose()
976
+ k = E * Y
977
+ verbose("done checking denom",tt)
978
+ if k.denominator() != 1:
979
+ H, pivots = add_row(H, v, pivots, include_zero_rows=False)
980
+ D = H.matrix_from_rows_and_columns(non_onerow, non_onecol).transpose()
981
+ nn = ones(H, pivots)
982
+ if not proof and len(nn[2]) == 0:
983
+ verbose("hnf -- got identity matrix -- early abort (2)")
984
+ if include_zero_rows:
985
+ H = pad_zeros(H, A.nrows())
986
+ return H, pivots
987
+
988
+ if include_zero_rows:
989
+ H = pad_zeros(H, A.nrows())
990
+ return H, pivots
991
+
992
+
993
+ def pad_zeros(A, nrows):
994
+ """
995
+ Add zeros to the bottom of A so that the resulting matrix has nrows.
996
+
997
+ INPUT:
998
+
999
+ - ``A`` -- a matrix
1000
+ - ``nrows`` -- integer that is at least as big as the number of rows of A
1001
+
1002
+ OUTPUT: a matrix with nrows rows
1003
+
1004
+ EXAMPLES::
1005
+
1006
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
1007
+ sage: a = matrix(ZZ, 2, 4, [1, 0, 0, 7, 0, 1, 5, 2])
1008
+ sage: matrix_integer_dense_hnf.pad_zeros(a, 4)
1009
+ [1 0 0 7]
1010
+ [0 1 5 2]
1011
+ [0 0 0 0]
1012
+ [0 0 0 0]
1013
+ sage: matrix_integer_dense_hnf.pad_zeros(a, 2)
1014
+ [1 0 0 7]
1015
+ [0 1 5 2]
1016
+ """
1017
+ nz = nrows - A.nrows()
1018
+ if nz == 0:
1019
+ return A
1020
+ if nz < 0:
1021
+ return A.matrix_from_rows(range(nrows))
1022
+ return A.stack(matrix(ZZ, nz, A.ncols()))
1023
+
1024
+
1025
+ def hnf(A, include_zero_rows=True, proof=True):
1026
+ """
1027
+ Return the Hermite Normal Form of a general integer matrix A,
1028
+ along with the pivot columns.
1029
+
1030
+ INPUT:
1031
+
1032
+ - ``A`` -- an n x m matrix A over the integers
1033
+ - ``include_zero_rows`` -- boolean (default: ``True``); whether or not to include zero
1034
+ rows in the output matrix
1035
+ - ``proof`` -- whether or not to prove the result correct
1036
+
1037
+ OUTPUT: tuple of:
1038
+
1039
+ - ``matrix`` -- the Hermite normal form of A
1040
+ - ``pivots`` -- the pivot column positions of A
1041
+
1042
+ EXAMPLES::
1043
+
1044
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
1045
+ sage: a = matrix(ZZ,3,5,[-2, -6, -3, -17, -1, 2, -1, -1, -2, -1, -2, -2, -6, 9, 2])
1046
+ sage: matrix_integer_dense_hnf.hnf(a)
1047
+ (
1048
+ [ 2 0 26 -75 -10]
1049
+ [ 0 1 27 -73 -9]
1050
+ [ 0 0 37 -106 -13], [0, 1, 2]
1051
+ )
1052
+ sage: matrix_integer_dense_hnf.hnf(a.transpose())
1053
+ (
1054
+ [1 0 0]
1055
+ [0 1 0]
1056
+ [0 0 1]
1057
+ [0 0 0]
1058
+ [0 0 0], [0, 1, 2]
1059
+ )
1060
+ sage: matrix_integer_dense_hnf.hnf(a.transpose(), include_zero_rows=False)
1061
+ (
1062
+ [1 0 0]
1063
+ [0 1 0]
1064
+ [0 0 1], [0, 1, 2]
1065
+ )
1066
+ """
1067
+ if A.nrows() <= 1:
1068
+ np = A.nonzero_positions()
1069
+ if not np:
1070
+ pivots = []
1071
+ if not include_zero_rows:
1072
+ A = A.new_matrix(0) # 0 rows
1073
+ else:
1074
+ i,j = np[0]
1075
+ if A[i,j] < 0:
1076
+ A = -A
1077
+ pivots = [j]
1078
+ return A, pivots
1079
+
1080
+ if not proof:
1081
+ H, pivots = probable_hnf(A, include_zero_rows=include_zero_rows,
1082
+ proof=False)
1083
+ if not include_zero_rows and len(pivots) > H.nrows():
1084
+ return H.matrix_from_rows(range(len(pivots))), pivots
1085
+
1086
+ while True:
1087
+ try:
1088
+ H, pivots = probable_hnf(A, include_zero_rows=include_zero_rows,
1089
+ proof=True)
1090
+ except ValueError:
1091
+ verbose("The attempt failed since the pivots must have been wrong. We try again.")
1092
+ continue
1093
+
1094
+ if is_in_hnf_form(H, pivots):
1095
+ if not include_zero_rows and len(pivots) > H.nrows():
1096
+ H = H.matrix_from_rows(range(len(pivots)))
1097
+ return H, pivots
1098
+ verbose("After attempt the return matrix is not in HNF form since pivots must have been wrong. We try again.")
1099
+
1100
+
1101
+ def hnf_with_transformation(A, proof=True):
1102
+ """
1103
+ Compute the HNF H of A along with a transformation matrix U
1104
+ such that U*A = H.
1105
+
1106
+ INPUT:
1107
+
1108
+ - ``A`` -- an n x m matrix A over the integers
1109
+ - ``proof`` -- whether or not to prove the result correct
1110
+
1111
+ OUTPUT: tuple of:
1112
+
1113
+ - ``matrix`` -- the Hermite normal form H of A
1114
+ - ``U`` -- a unimodular matrix such that U * A = H
1115
+
1116
+ EXAMPLES::
1117
+
1118
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
1119
+ sage: A = matrix(ZZ, 2, [1, -5, -10, 1, 3, 197]); A
1120
+ [ 1 -5 -10]
1121
+ [ 1 3 197]
1122
+ sage: H, U = matrix_integer_dense_hnf.hnf_with_transformation(A)
1123
+ sage: H
1124
+ [ 1 3 197]
1125
+ [ 0 8 207]
1126
+ sage: U
1127
+ [ 0 1]
1128
+ [-1 1]
1129
+ sage: U*A
1130
+ [ 1 3 197]
1131
+ [ 0 8 207]
1132
+ """
1133
+ # All we do is augment the input matrix with the identity matrix of the appropriate rank on the right.
1134
+ C = A.augment(identity_matrix(ZZ, A.nrows()))
1135
+ H, _ = hnf(C, include_zero_rows=True, proof=proof)
1136
+ U = H.matrix_from_columns(range(A.ncols(), H.ncols()))
1137
+ H2 = H.matrix_from_columns(range(A.ncols()))
1138
+ return H2, U
1139
+
1140
+
1141
+ def hnf_with_transformation_tests(n=10, m=5, trials=10):
1142
+ """
1143
+ Use this to randomly test that hnf with transformation matrix
1144
+ is working.
1145
+
1146
+ EXAMPLES::
1147
+
1148
+ sage: from sage.matrix.matrix_integer_dense_hnf import hnf_with_transformation_tests
1149
+ sage: hnf_with_transformation_tests(n=15, m=10, trials=10)
1150
+ 0 1 2 3 4 5 6 7 8 9
1151
+ """
1152
+ for i in range(trials):
1153
+ print(i, end=" ")
1154
+ A = random_matrix(ZZ, n, m)
1155
+ H, U = hnf_with_transformation(A)
1156
+ assert H == U * A
1157
+ H, U = hnf_with_transformation(A, proof=False)
1158
+ assert H == U * A
1159
+
1160
+
1161
+ # -----------------------------------------------------------------------------
1162
+ # Code for testing and benchmarking
1163
+ # ------------------------------------------------------------------------------
1164
+
1165
+
1166
+ def benchmark_hnf(nrange, bits=4):
1167
+ """
1168
+ Run benchmark program.
1169
+
1170
+ EXAMPLES::
1171
+
1172
+ sage: import sage.matrix.matrix_integer_dense_hnf as hnf
1173
+ sage: hnf.benchmark_hnf([10,25],32)
1174
+ ('sage', 10, 32, ...),
1175
+ ('sage', 25, 32, ...),
1176
+ """
1177
+ b = 2**bits
1178
+ for n in nrange:
1179
+ a = random_matrix(ZZ, n, x=-b, y=b)
1180
+ t = cputime()
1181
+ h, _ = hnf(a, proof=False)
1182
+ tm = cputime(t)
1183
+ print('%s,' % (('sage', n, bits, tm),))
1184
+
1185
+
1186
+ def benchmark_magma_hnf(nrange, bits=4):
1187
+ """
1188
+ EXAMPLES::
1189
+
1190
+ sage: import sage.matrix.matrix_integer_dense_hnf as hnf
1191
+ sage: hnf.benchmark_magma_hnf([50,100],32) # optional - magma
1192
+ ('magma', 50, 32, ...),
1193
+ ('magma', 100, 32, ...),
1194
+ """
1195
+ from sage.interfaces.magma import magma
1196
+ b = 2**bits
1197
+ for n in nrange:
1198
+ a = magma('MatrixAlgebra(IntegerRing(),%s)![Random(%s,%s) : i in [1..%s]]' % (n, -b, b, n**2))
1199
+ t = magma.cputime()
1200
+ a.EchelonForm()
1201
+ tm = magma.cputime(t)
1202
+ print('%s,' % (('magma', n, bits, tm),))
1203
+
1204
+
1205
+ def sanity_checks(times=50, n=8, m=5, proof=True, stabilize=2,
1206
+ check_using_magma=True):
1207
+ """
1208
+ Run random sanity checks on the modular `p`-adic HNF with tall and wide matrices
1209
+ both dense and sparse.
1210
+
1211
+ INPUT:
1212
+
1213
+ - ``times`` -- number of times to randomly try matrices with each shape
1214
+ - ``n`` -- number of rows
1215
+ - ``m`` -- number of columns
1216
+ - ``proof`` -- test with proof true
1217
+ - ``stabilize`` -- parameter to pass to hnf algorithm when proof is False
1218
+ - ``check_using_magma`` -- if ``True`` use Magma instead of PARI to check
1219
+ correctness of computed HNF's. Since PARI's HNF is buggy and slow (as of
1220
+ 2008-02-16 non-pivot entries sometimes are not normalized to be
1221
+ nonnegative) the default is Magma.
1222
+
1223
+ EXAMPLES::
1224
+
1225
+ sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
1226
+ sage: matrix_integer_dense_hnf.sanity_checks(times=5, check_using_magma=False)
1227
+ small 8 x 5
1228
+ 0 1 2 3 4 (done)
1229
+ big 8 x 5
1230
+ 0 1 2 3 4 (done)
1231
+ small 5 x 8
1232
+ 0 1 2 3 4 (done)
1233
+ big 5 x 8
1234
+ 0 1 2 3 4 (done)
1235
+ sparse 8 x 5
1236
+ 0 1 2 3 4 (done)
1237
+ sparse 5 x 8
1238
+ 0 1 2 3 4 (done)
1239
+ ill conditioned -- 1000*A -- 8 x 5
1240
+ 0 1 2 3 4 (done)
1241
+ ill conditioned -- 1000*A but one row -- 8 x 5
1242
+ 0 1 2 3 4 (done)
1243
+ """
1244
+ if check_using_magma:
1245
+ from sage.interfaces.magma import magma
1246
+
1247
+ def __do_check(v):
1248
+ """
1249
+ This is used internally by the sanity check code.
1250
+ """
1251
+ for i, a in enumerate(v):
1252
+ global sanity
1253
+ sanity = a
1254
+ print(i, end=" ")
1255
+ if check_using_magma:
1256
+ if magma(hnf(a)[0]) != magma(a).EchelonForm():
1257
+ print("bug computing hnf of a matrix")
1258
+ print('a = matrix(ZZ, %s, %s, %s)' % (a.nrows(), a.ncols(),
1259
+ a.list()))
1260
+ return
1261
+ else:
1262
+ if hnf(a)[0] != a.echelon_form(algorithm='pari'):
1263
+ print("bug computing hnf of a matrix")
1264
+ print('a = matrix(ZZ, %s, %s, %s)' % (a.nrows(), a.ncols(),
1265
+ a.list()))
1266
+ return
1267
+ print(" (done)")
1268
+ print("small %s x %s" % (n, m))
1269
+ __do_check([random_matrix(ZZ, n, m, x=-1, y=1) for _ in range(times)])
1270
+ print("big %s x %s" % (n, m))
1271
+ __do_check([random_matrix(ZZ, n, m, x=-2**32, y=2**32)
1272
+ for _ in range(times)])
1273
+
1274
+ print("small %s x %s" % (m, n))
1275
+ __do_check([random_matrix(ZZ, m, n, x=-1, y=1) for _ in range(times)])
1276
+ print("big %s x %s" % (m, n))
1277
+ __do_check([random_matrix(ZZ, m, n, x=-2**32,y=2**32)
1278
+ for _ in range(times)])
1279
+
1280
+ print("sparse %s x %s" % (n, m))
1281
+ __do_check([random_matrix(ZZ, n, m, density=0.1) for _ in range(times)])
1282
+ print("sparse %s x %s" % (m, n))
1283
+ __do_check([random_matrix(ZZ, m, n, density=0.1) for _ in range(times)])
1284
+
1285
+ print("ill conditioned -- 1000*A -- %s x %s" % (n, m))
1286
+ __do_check([1000*random_matrix(ZZ, n, m, x=-1, y=1) for _ in range(times)])
1287
+
1288
+ print("ill conditioned -- 1000*A but one row -- %s x %s" % (n, m))
1289
+ v = []
1290
+ for _ in range(times):
1291
+ a = 1000 * random_matrix(ZZ, n, m, x=-1, y=1)
1292
+ a[a.nrows() - 1] = a[a.nrows() - 1] / 1000
1293
+ v.append(a)
1294
+ __do_check(v)