passagemath-flint 10.6.47__cp313-cp313-macosx_13_0_arm64.whl

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