passagemath-flint 10.6.1rc10__cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. passagemath_flint-10.6.1rc10.dist-info/METADATA +122 -0
  2. passagemath_flint-10.6.1rc10.dist-info/RECORD +361 -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-aecb9cc5.so.21.0.0 +0 -0
  6. passagemath_flint.libs/libgf2x-a4cdec90.so.3.0.0 +0 -0
  7. passagemath_flint.libs/libgfortran-8f1e9814.so.5.0.0 +0 -0
  8. passagemath_flint.libs/libgmp-6e109695.so.10.5.0 +0 -0
  9. passagemath_flint.libs/libgsl-cda90e79.so.28.0.0 +0 -0
  10. passagemath_flint.libs/libmpfi-e3c25853.so.0.0.0 +0 -0
  11. passagemath_flint.libs/libmpfr-82690d50.so.6.2.1 +0 -0
  12. passagemath_flint.libs/libntl-74e7d9a3.so.44.0.1 +0 -0
  13. passagemath_flint.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
  14. passagemath_flint.libs/libquadmath-828275a7.so.0.0.0 +0 -0
  15. sage/all__sagemath_flint.py +29 -0
  16. sage/combinat/all__sagemath_flint.py +1 -0
  17. sage/combinat/posets/all__sagemath_flint.py +1 -0
  18. sage/combinat/posets/hasse_cython_flint.cpython-311-x86_64-linux-gnu.so +0 -0
  19. sage/combinat/posets/hasse_cython_flint.pyx +194 -0
  20. sage/data_structures/all__sagemath_flint.py +1 -0
  21. sage/data_structures/bounded_integer_sequences.cpython-311-x86_64-linux-gnu.so +0 -0
  22. sage/data_structures/bounded_integer_sequences.pxd +62 -0
  23. sage/data_structures/bounded_integer_sequences.pyx +1418 -0
  24. sage/graphs/all__sagemath_flint.py +1 -0
  25. sage/graphs/chrompoly.cpython-311-x86_64-linux-gnu.so +0 -0
  26. sage/graphs/chrompoly.pyx +555 -0
  27. sage/graphs/matchpoly.cpython-311-x86_64-linux-gnu.so +0 -0
  28. sage/graphs/matchpoly.pyx +412 -0
  29. sage/libs/all__sagemath_flint.py +17 -0
  30. sage/libs/arb/__init__.py +1 -0
  31. sage/libs/arb/acb.pxd +154 -0
  32. sage/libs/arb/acb_calc.pxd +9 -0
  33. sage/libs/arb/acb_elliptic.pxd +25 -0
  34. sage/libs/arb/acb_hypgeom.pxd +74 -0
  35. sage/libs/arb/acb_mat.pxd +62 -0
  36. sage/libs/arb/acb_modular.pxd +17 -0
  37. sage/libs/arb/acb_poly.pxd +216 -0
  38. sage/libs/arb/arb.pxd +240 -0
  39. sage/libs/arb/arb_fmpz_poly.pxd +21 -0
  40. sage/libs/arb/arb_hypgeom.pxd +83 -0
  41. sage/libs/arb/arb_wrap.h +34 -0
  42. sage/libs/arb/arf.pxd +131 -0
  43. sage/libs/arb/arith.cpython-311-x86_64-linux-gnu.so +0 -0
  44. sage/libs/arb/arith.pyx +87 -0
  45. sage/libs/arb/bernoulli.pxd +6 -0
  46. sage/libs/arb/mag.pxd +77 -0
  47. sage/libs/arb/types.pxd +37 -0
  48. sage/libs/flint/__init__.py +1 -0
  49. sage/libs/flint/acb.pxd +270 -0
  50. sage/libs/flint/acb_calc.pxd +22 -0
  51. sage/libs/flint/acb_dft.pxd +51 -0
  52. sage/libs/flint/acb_dirichlet.pxd +112 -0
  53. sage/libs/flint/acb_elliptic.pxd +42 -0
  54. sage/libs/flint/acb_hypgeom.pxd +169 -0
  55. sage/libs/flint/acb_macros.pxd +9 -0
  56. sage/libs/flint/acb_mat.pxd +136 -0
  57. sage/libs/flint/acb_mat_macros.pxd +10 -0
  58. sage/libs/flint/acb_modular.pxd +62 -0
  59. sage/libs/flint/acb_poly.pxd +251 -0
  60. sage/libs/flint/acb_poly_macros.pxd +8 -0
  61. sage/libs/flint/acb_theta.pxd +124 -0
  62. sage/libs/flint/acf.pxd +32 -0
  63. sage/libs/flint/aprcl.pxd +84 -0
  64. sage/libs/flint/arb.pxd +382 -0
  65. sage/libs/flint/arb_calc.pxd +31 -0
  66. sage/libs/flint/arb_fmpz_poly.pxd +34 -0
  67. sage/libs/flint/arb_fpwrap.pxd +215 -0
  68. sage/libs/flint/arb_hypgeom.pxd +147 -0
  69. sage/libs/flint/arb_macros.pxd +9 -0
  70. sage/libs/flint/arb_mat.pxd +140 -0
  71. sage/libs/flint/arb_mat_macros.pxd +10 -0
  72. sage/libs/flint/arb_poly.pxd +237 -0
  73. sage/libs/flint/arf.pxd +167 -0
  74. sage/libs/flint/arith.cpython-311-x86_64-linux-gnu.so +0 -0
  75. sage/libs/flint/arith.pxd +76 -0
  76. sage/libs/flint/arith.pyx +77 -0
  77. sage/libs/flint/arith_sage.cpython-311-x86_64-linux-gnu.so +0 -0
  78. sage/libs/flint/arith_sage.pyx +308 -0
  79. sage/libs/flint/bernoulli.pxd +28 -0
  80. sage/libs/flint/bool_mat.pxd +52 -0
  81. sage/libs/flint/ca.pxd +203 -0
  82. sage/libs/flint/ca_ext.pxd +34 -0
  83. sage/libs/flint/ca_field.pxd +32 -0
  84. sage/libs/flint/ca_mat.pxd +117 -0
  85. sage/libs/flint/ca_poly.pxd +104 -0
  86. sage/libs/flint/ca_vec.pxd +46 -0
  87. sage/libs/flint/calcium.pxd +27 -0
  88. sage/libs/flint/d_mat.pxd +39 -0
  89. sage/libs/flint/d_vec.pxd +32 -0
  90. sage/libs/flint/dirichlet.pxd +57 -0
  91. sage/libs/flint/dlog.pxd +53 -0
  92. sage/libs/flint/double_extras.pxd +24 -0
  93. sage/libs/flint/double_interval.pxd +36 -0
  94. sage/libs/flint/fexpr.pxd +104 -0
  95. sage/libs/flint/fexpr_builtin.pxd +20 -0
  96. sage/libs/flint/fft.pxd +66 -0
  97. sage/libs/flint/flint.pxd +36 -0
  98. sage/libs/flint/flint_ntl_wrap.h +35 -0
  99. sage/libs/flint/flint_sage.cpython-311-x86_64-linux-gnu.so +0 -0
  100. sage/libs/flint/flint_sage.pyx +163 -0
  101. sage/libs/flint/flint_wrap.h +190 -0
  102. sage/libs/flint/fmpq.pxd +137 -0
  103. sage/libs/flint/fmpq_mat.pxd +105 -0
  104. sage/libs/flint/fmpq_mat_macros.pxd +10 -0
  105. sage/libs/flint/fmpq_mpoly.pxd +165 -0
  106. sage/libs/flint/fmpq_mpoly_factor.pxd +30 -0
  107. sage/libs/flint/fmpq_poly.pxd +241 -0
  108. sage/libs/flint/fmpq_poly_macros.pxd +9 -0
  109. sage/libs/flint/fmpq_poly_sage.cpython-311-x86_64-linux-gnu.so +0 -0
  110. sage/libs/flint/fmpq_poly_sage.pxd +31 -0
  111. sage/libs/flint/fmpq_poly_sage.pyx +48 -0
  112. sage/libs/flint/fmpq_vec.pxd +27 -0
  113. sage/libs/flint/fmpz.pxd +256 -0
  114. sage/libs/flint/fmpz_extras.pxd +32 -0
  115. sage/libs/flint/fmpz_factor.pxd +42 -0
  116. sage/libs/flint/fmpz_factor_sage.cpython-311-x86_64-linux-gnu.so +0 -0
  117. sage/libs/flint/fmpz_factor_sage.pxd +4 -0
  118. sage/libs/flint/fmpz_factor_sage.pyx +29 -0
  119. sage/libs/flint/fmpz_lll.pxd +49 -0
  120. sage/libs/flint/fmpz_macros.pxd +8 -0
  121. sage/libs/flint/fmpz_mat.pxd +184 -0
  122. sage/libs/flint/fmpz_mat_macros.pxd +10 -0
  123. sage/libs/flint/fmpz_mod.pxd +46 -0
  124. sage/libs/flint/fmpz_mod_mat.pxd +71 -0
  125. sage/libs/flint/fmpz_mod_mpoly.pxd +161 -0
  126. sage/libs/flint/fmpz_mod_mpoly_factor.pxd +28 -0
  127. sage/libs/flint/fmpz_mod_poly.pxd +249 -0
  128. sage/libs/flint/fmpz_mod_poly_factor.pxd +46 -0
  129. sage/libs/flint/fmpz_mod_vec.pxd +27 -0
  130. sage/libs/flint/fmpz_mpoly.pxd +224 -0
  131. sage/libs/flint/fmpz_mpoly_factor.pxd +29 -0
  132. sage/libs/flint/fmpz_mpoly_q.pxd +57 -0
  133. sage/libs/flint/fmpz_poly.cpython-311-x86_64-linux-gnu.so +0 -0
  134. sage/libs/flint/fmpz_poly.pxd +407 -0
  135. sage/libs/flint/fmpz_poly.pyx +19 -0
  136. sage/libs/flint/fmpz_poly_factor.pxd +33 -0
  137. sage/libs/flint/fmpz_poly_macros.pxd +8 -0
  138. sage/libs/flint/fmpz_poly_mat.pxd +71 -0
  139. sage/libs/flint/fmpz_poly_q.pxd +55 -0
  140. sage/libs/flint/fmpz_poly_sage.cpython-311-x86_64-linux-gnu.so +0 -0
  141. sage/libs/flint/fmpz_poly_sage.pxd +20 -0
  142. sage/libs/flint/fmpz_poly_sage.pyx +500 -0
  143. sage/libs/flint/fmpz_vec.pxd +80 -0
  144. sage/libs/flint/fmpzi.pxd +52 -0
  145. sage/libs/flint/fq.pxd +97 -0
  146. sage/libs/flint/fq_default.pxd +84 -0
  147. sage/libs/flint/fq_default_mat.pxd +70 -0
  148. sage/libs/flint/fq_default_poly.pxd +97 -0
  149. sage/libs/flint/fq_default_poly_factor.pxd +39 -0
  150. sage/libs/flint/fq_embed.pxd +28 -0
  151. sage/libs/flint/fq_mat.pxd +83 -0
  152. sage/libs/flint/fq_nmod.pxd +95 -0
  153. sage/libs/flint/fq_nmod_embed.pxd +28 -0
  154. sage/libs/flint/fq_nmod_mat.pxd +83 -0
  155. sage/libs/flint/fq_nmod_mpoly.pxd +130 -0
  156. sage/libs/flint/fq_nmod_mpoly_factor.pxd +28 -0
  157. sage/libs/flint/fq_nmod_poly.pxd +202 -0
  158. sage/libs/flint/fq_nmod_poly_factor.pxd +47 -0
  159. sage/libs/flint/fq_nmod_vec.pxd +33 -0
  160. sage/libs/flint/fq_poly.pxd +204 -0
  161. sage/libs/flint/fq_poly_factor.pxd +47 -0
  162. sage/libs/flint/fq_vec.pxd +33 -0
  163. sage/libs/flint/fq_zech.pxd +99 -0
  164. sage/libs/flint/fq_zech_embed.pxd +28 -0
  165. sage/libs/flint/fq_zech_mat.pxd +78 -0
  166. sage/libs/flint/fq_zech_poly.pxd +198 -0
  167. sage/libs/flint/fq_zech_poly_factor.pxd +47 -0
  168. sage/libs/flint/fq_zech_vec.pxd +33 -0
  169. sage/libs/flint/gr.pxd +174 -0
  170. sage/libs/flint/gr_generic.pxd +215 -0
  171. sage/libs/flint/gr_mat.pxd +161 -0
  172. sage/libs/flint/gr_mpoly.pxd +68 -0
  173. sage/libs/flint/gr_poly.pxd +276 -0
  174. sage/libs/flint/gr_special.pxd +237 -0
  175. sage/libs/flint/gr_vec.pxd +120 -0
  176. sage/libs/flint/hypgeom.pxd +24 -0
  177. sage/libs/flint/long_extras.pxd +23 -0
  178. sage/libs/flint/mag.pxd +131 -0
  179. sage/libs/flint/mag_macros.pxd +8 -0
  180. sage/libs/flint/mpf_mat.pxd +36 -0
  181. sage/libs/flint/mpf_vec.pxd +34 -0
  182. sage/libs/flint/mpfr_mat.pxd +27 -0
  183. sage/libs/flint/mpfr_vec.pxd +25 -0
  184. sage/libs/flint/mpn_extras.pxd +41 -0
  185. sage/libs/flint/mpoly.pxd +72 -0
  186. sage/libs/flint/nf.pxd +19 -0
  187. sage/libs/flint/nf_elem.pxd +74 -0
  188. sage/libs/flint/nmod.pxd +35 -0
  189. sage/libs/flint/nmod_mat.pxd +104 -0
  190. sage/libs/flint/nmod_mpoly.pxd +144 -0
  191. sage/libs/flint/nmod_mpoly_factor.pxd +28 -0
  192. sage/libs/flint/nmod_poly.pxd +339 -0
  193. sage/libs/flint/nmod_poly_factor.pxd +44 -0
  194. sage/libs/flint/nmod_poly_linkage.pxi +710 -0
  195. sage/libs/flint/nmod_poly_mat.pxd +76 -0
  196. sage/libs/flint/nmod_vec.pxd +40 -0
  197. sage/libs/flint/ntl_interface.pxd +17 -0
  198. sage/libs/flint/padic.pxd +93 -0
  199. sage/libs/flint/padic_mat.pxd +64 -0
  200. sage/libs/flint/padic_poly.pxd +88 -0
  201. sage/libs/flint/partitions.pxd +23 -0
  202. sage/libs/flint/perm.pxd +26 -0
  203. sage/libs/flint/profiler.pxd +24 -0
  204. sage/libs/flint/qadic.pxd +77 -0
  205. sage/libs/flint/qfb.pxd +44 -0
  206. sage/libs/flint/qqbar.pxd +172 -0
  207. sage/libs/flint/qsieve.cpython-311-x86_64-linux-gnu.so +0 -0
  208. sage/libs/flint/qsieve.pxd +41 -0
  209. sage/libs/flint/qsieve.pyx +21 -0
  210. sage/libs/flint/qsieve_sage.cpython-311-x86_64-linux-gnu.so +0 -0
  211. sage/libs/flint/qsieve_sage.pyx +67 -0
  212. sage/libs/flint/thread_pool.pxd +25 -0
  213. sage/libs/flint/types.pxd +2076 -0
  214. sage/libs/flint/ulong_extras.cpython-311-x86_64-linux-gnu.so +0 -0
  215. sage/libs/flint/ulong_extras.pxd +141 -0
  216. sage/libs/flint/ulong_extras.pyx +21 -0
  217. sage/libs/flint/ulong_extras_sage.cpython-311-x86_64-linux-gnu.so +0 -0
  218. sage/libs/flint/ulong_extras_sage.pyx +21 -0
  219. sage/matrix/all__sagemath_flint.py +1 -0
  220. sage/matrix/change_ring.cpython-311-x86_64-linux-gnu.so +0 -0
  221. sage/matrix/change_ring.pyx +43 -0
  222. sage/matrix/matrix_complex_ball_dense.cpython-311-x86_64-linux-gnu.so +0 -0
  223. sage/matrix/matrix_complex_ball_dense.pxd +14 -0
  224. sage/matrix/matrix_complex_ball_dense.pyx +973 -0
  225. sage/matrix/matrix_cyclo_dense.cpython-311-x86_64-linux-gnu.so +0 -0
  226. sage/matrix/matrix_cyclo_dense.pxd +16 -0
  227. sage/matrix/matrix_cyclo_dense.pyx +1761 -0
  228. sage/matrix/matrix_integer_dense.cpython-311-x86_64-linux-gnu.so +0 -0
  229. sage/matrix/matrix_integer_dense.pxd +32 -0
  230. sage/matrix/matrix_integer_dense.pyx +5801 -0
  231. sage/matrix/matrix_integer_dense_hnf.py +1294 -0
  232. sage/matrix/matrix_integer_dense_saturation.py +346 -0
  233. sage/matrix/matrix_integer_sparse.cpython-311-x86_64-linux-gnu.so +0 -0
  234. sage/matrix/matrix_integer_sparse.pxd +9 -0
  235. sage/matrix/matrix_integer_sparse.pyx +1090 -0
  236. sage/matrix/matrix_rational_dense.cpython-311-x86_64-linux-gnu.so +0 -0
  237. sage/matrix/matrix_rational_dense.pxd +23 -0
  238. sage/matrix/matrix_rational_dense.pyx +2995 -0
  239. sage/matrix/matrix_rational_sparse.cpython-311-x86_64-linux-gnu.so +0 -0
  240. sage/matrix/matrix_rational_sparse.pxd +11 -0
  241. sage/matrix/matrix_rational_sparse.pyx +789 -0
  242. sage/matrix/misc_flint.cpython-311-x86_64-linux-gnu.so +0 -0
  243. sage/matrix/misc_flint.pyx +109 -0
  244. sage/modular/all__sagemath_flint.py +1 -0
  245. sage/modular/modform/all__sagemath_flint.py +1 -0
  246. sage/modular/modform/eis_series_cython.cpython-311-x86_64-linux-gnu.so +0 -0
  247. sage/modular/modform/eis_series_cython.pyx +226 -0
  248. sage/modular/modsym/all__sagemath_flint.py +1 -0
  249. sage/modular/modsym/apply.cpython-311-x86_64-linux-gnu.so +0 -0
  250. sage/modular/modsym/apply.pxd +6 -0
  251. sage/modular/modsym/apply.pyx +113 -0
  252. sage/modular/modsym/heilbronn.cpython-311-x86_64-linux-gnu.so +0 -0
  253. sage/modular/modsym/heilbronn.pyx +966 -0
  254. sage/modular/pollack_stevens/all__sagemath_flint.py +1 -0
  255. sage/modular/pollack_stevens/dist.cpython-311-x86_64-linux-gnu.so +0 -0
  256. sage/modular/pollack_stevens/dist.pxd +38 -0
  257. sage/modular/pollack_stevens/dist.pyx +1439 -0
  258. sage/quivers/algebra.py +691 -0
  259. sage/quivers/algebra_elements.cpython-311-x86_64-linux-gnu.so +0 -0
  260. sage/quivers/algebra_elements.pxd +97 -0
  261. sage/quivers/algebra_elements.pxi +1324 -0
  262. sage/quivers/algebra_elements.pyx +1424 -0
  263. sage/quivers/all.py +1 -0
  264. sage/quivers/ar_quiver.py +917 -0
  265. sage/quivers/homspace.py +640 -0
  266. sage/quivers/morphism.py +1282 -0
  267. sage/quivers/path_semigroup.py +1155 -0
  268. sage/quivers/paths.cpython-311-x86_64-linux-gnu.so +0 -0
  269. sage/quivers/paths.pxd +13 -0
  270. sage/quivers/paths.pyx +809 -0
  271. sage/quivers/representation.py +2975 -0
  272. sage/rings/all__sagemath_flint.py +37 -0
  273. sage/rings/cif.py +4 -0
  274. sage/rings/complex_arb.cpython-311-x86_64-linux-gnu.so +0 -0
  275. sage/rings/complex_arb.pxd +29 -0
  276. sage/rings/complex_arb.pyx +5176 -0
  277. sage/rings/complex_interval.cpython-311-x86_64-linux-gnu.so +0 -0
  278. sage/rings/complex_interval.pxd +30 -0
  279. sage/rings/complex_interval.pyx +2475 -0
  280. sage/rings/complex_interval_field.py +711 -0
  281. sage/rings/convert/all.py +1 -0
  282. sage/rings/convert/mpfi.cpython-311-x86_64-linux-gnu.so +0 -0
  283. sage/rings/convert/mpfi.pxd +6 -0
  284. sage/rings/convert/mpfi.pyx +576 -0
  285. sage/rings/factorint_flint.cpython-311-x86_64-linux-gnu.so +0 -0
  286. sage/rings/factorint_flint.pyx +99 -0
  287. sage/rings/fraction_field_FpT.cpython-311-x86_64-linux-gnu.so +0 -0
  288. sage/rings/fraction_field_FpT.pxd +28 -0
  289. sage/rings/fraction_field_FpT.pyx +2043 -0
  290. sage/rings/imaginary_unit.py +5 -0
  291. sage/rings/monomials.py +73 -0
  292. sage/rings/number_field/S_unit_solver.py +2870 -0
  293. sage/rings/number_field/all__sagemath_flint.py +7 -0
  294. sage/rings/number_field/bdd_height.py +664 -0
  295. sage/rings/number_field/class_group.py +762 -0
  296. sage/rings/number_field/galois_group.py +1307 -0
  297. sage/rings/number_field/homset.py +612 -0
  298. sage/rings/number_field/maps.py +687 -0
  299. sage/rings/number_field/morphism.py +272 -0
  300. sage/rings/number_field/number_field.py +12820 -0
  301. sage/rings/number_field/number_field_element.cpython-311-x86_64-linux-gnu.so +0 -0
  302. sage/rings/number_field/number_field_element.pxd +59 -0
  303. sage/rings/number_field/number_field_element.pyx +5735 -0
  304. sage/rings/number_field/number_field_element_quadratic.cpython-311-x86_64-linux-gnu.so +0 -0
  305. sage/rings/number_field/number_field_element_quadratic.pxd +34 -0
  306. sage/rings/number_field/number_field_element_quadratic.pyx +3185 -0
  307. sage/rings/number_field/number_field_ideal_rel.py +925 -0
  308. sage/rings/number_field/number_field_morphisms.cpython-311-x86_64-linux-gnu.so +0 -0
  309. sage/rings/number_field/number_field_morphisms.pyx +781 -0
  310. sage/rings/number_field/number_field_rel.py +2734 -0
  311. sage/rings/number_field/order.py +2981 -0
  312. sage/rings/number_field/order_ideal.py +804 -0
  313. sage/rings/number_field/selmer_group.py +715 -0
  314. sage/rings/number_field/small_primes_of_degree_one.py +242 -0
  315. sage/rings/number_field/splitting_field.py +606 -0
  316. sage/rings/number_field/structure.py +380 -0
  317. sage/rings/number_field/unit_group.py +721 -0
  318. sage/rings/padics/all__sagemath_flint.py +3 -0
  319. sage/rings/polynomial/all__sagemath_flint.py +1 -0
  320. sage/rings/polynomial/complex_roots.py +312 -0
  321. sage/rings/polynomial/evaluation_flint.cpython-311-x86_64-linux-gnu.so +0 -0
  322. sage/rings/polynomial/evaluation_flint.pxd +7 -0
  323. sage/rings/polynomial/evaluation_flint.pyx +68 -0
  324. sage/rings/polynomial/hilbert.cpython-311-x86_64-linux-gnu.so +0 -0
  325. sage/rings/polynomial/hilbert.pyx +602 -0
  326. sage/rings/polynomial/polynomial_complex_arb.cpython-311-x86_64-linux-gnu.so +0 -0
  327. sage/rings/polynomial/polynomial_complex_arb.pxd +7 -0
  328. sage/rings/polynomial/polynomial_complex_arb.pyx +963 -0
  329. sage/rings/polynomial/polynomial_integer_dense_flint.cpython-311-x86_64-linux-gnu.so +0 -0
  330. sage/rings/polynomial/polynomial_integer_dense_flint.pxd +13 -0
  331. sage/rings/polynomial/polynomial_integer_dense_flint.pyx +1881 -0
  332. sage/rings/polynomial/polynomial_number_field.cpython-311-x86_64-linux-gnu.so +0 -0
  333. sage/rings/polynomial/polynomial_number_field.pyx +345 -0
  334. sage/rings/polynomial/polynomial_rational_flint.cpython-311-x86_64-linux-gnu.so +0 -0
  335. sage/rings/polynomial/polynomial_rational_flint.pxd +20 -0
  336. sage/rings/polynomial/polynomial_rational_flint.pyx +2598 -0
  337. sage/rings/polynomial/polynomial_zmod_flint.cpython-311-x86_64-linux-gnu.so +0 -0
  338. sage/rings/polynomial/polynomial_zmod_flint.pxd +20 -0
  339. sage/rings/polynomial/polynomial_zmod_flint.pyx +1063 -0
  340. sage/rings/polynomial/real_roots.cpython-311-x86_64-linux-gnu.so +0 -0
  341. sage/rings/polynomial/real_roots.pxd +81 -0
  342. sage/rings/polynomial/real_roots.pyx +4704 -0
  343. sage/rings/polynomial/refine_root.cpython-311-x86_64-linux-gnu.so +0 -0
  344. sage/rings/polynomial/refine_root.pyx +142 -0
  345. sage/rings/polynomial/weil/all.py +4 -0
  346. sage/rings/polynomial/weil/power_sums.h +46 -0
  347. sage/rings/polynomial/weil/weil_polynomials.cpython-311-x86_64-linux-gnu.so +0 -0
  348. sage/rings/polynomial/weil/weil_polynomials.pyx +596 -0
  349. sage/rings/qqbar.py +9025 -0
  350. sage/rings/real_arb.cpython-311-x86_64-linux-gnu.so +0 -0
  351. sage/rings/real_arb.pxd +21 -0
  352. sage/rings/real_arb.pyx +4065 -0
  353. sage/rings/real_interval_absolute.cpython-311-x86_64-linux-gnu.so +0 -0
  354. sage/rings/real_interval_absolute.pyx +1073 -0
  355. sage/rings/real_mpfi.cpython-311-x86_64-linux-gnu.so +0 -0
  356. sage/rings/real_mpfi.pyx +5428 -0
  357. sage/schemes/all__sagemath_flint.py +1 -0
  358. sage/schemes/elliptic_curves/all__sagemath_flint.py +1 -0
  359. sage/schemes/elliptic_curves/descent_two_isogeny.cpython-311-x86_64-linux-gnu.so +0 -0
  360. sage/schemes/elliptic_curves/descent_two_isogeny.pyx +1387 -0
  361. sage/schemes/elliptic_curves/descent_two_isogeny_pari.pxd +5 -0
@@ -0,0 +1,1387 @@
1
+ # sage_setup: distribution = sagemath-flint
2
+ # sage.doctest: needs sage.libs.ntl sage.libs.pari
3
+ r"""
4
+ Descent on elliptic curves over `\QQ` with a 2-isogeny
5
+ """
6
+
7
+ # ***************************************************************************
8
+ # Copyright (C) 2009 Robert L. Miller <rlmillster@gmail.com>
9
+ #
10
+ # This program is free software: you can redistribute it and/or modify
11
+ # it under the terms of the GNU General Public License as published by
12
+ # the Free Software Foundation, either version 2 of the License, or
13
+ # (at your option) any later version.
14
+ # https://www.gnu.org/licenses/
15
+ # ***************************************************************************
16
+
17
+ from cysignals.memory cimport sig_malloc, sig_free
18
+
19
+ from sage.rings.integer_ring import ZZ
20
+ from sage.rings.polynomial.polynomial_ring import polygen
21
+ cdef object x_ZZ = polygen(ZZ)
22
+ from sage.rings.polynomial.real_roots import real_roots
23
+ from sage.arith.misc import prime_divisors
24
+ import sage.libs.ntl.all as ntl
25
+
26
+ from sage.rings.integer cimport Integer
27
+ from sage.libs.gmp.mpz cimport *
28
+ from sage.libs.flint.fmpz_poly cimport *
29
+ from sage.libs.flint.fmpz_poly_sage cimport *
30
+ from sage.libs.flint.nmod_poly cimport *
31
+ from sage.libs.flint.nmod_poly_factor cimport *
32
+ from sage.libs.flint.ulong_extras cimport *
33
+
34
+ from sage.schemes.elliptic_curves.descent_two_isogeny_pari cimport ratpoints_mpz_exists_only
35
+
36
+ DEF N_RES_CLASSES_BSD = 10
37
+
38
+
39
+ cdef unsigned long valuation(mpz_t a, mpz_t p) noexcept:
40
+ """
41
+ Return the number of times p divides a.
42
+ """
43
+ cdef mpz_t aa
44
+ cdef unsigned long v
45
+ mpz_init(aa)
46
+ v = mpz_remove(aa, a, p)
47
+ mpz_clear(aa)
48
+ return v
49
+
50
+
51
+ def test_valuation(a, p):
52
+ """
53
+ Doctest function for cdef long valuation(mpz_t, mpz_t).
54
+
55
+ EXAMPLES::
56
+
57
+ sage: from sage.schemes.elliptic_curves.descent_two_isogeny import test_valuation as tv
58
+ sage: for i in [1..20]:
59
+ ....: print('{:>10} {} {} {}'.format(str(factor(i)), tv(i,2), tv(i,3), tv(i,5)))
60
+ 1 0 0 0
61
+ 2 1 0 0
62
+ 3 0 1 0
63
+ 2^2 2 0 0
64
+ 5 0 0 1
65
+ 2 * 3 1 1 0
66
+ 7 0 0 0
67
+ 2^3 3 0 0
68
+ 3^2 0 2 0
69
+ 2 * 5 1 0 1
70
+ 11 0 0 0
71
+ 2^2 * 3 2 1 0
72
+ 13 0 0 0
73
+ 2 * 7 1 0 0
74
+ 3 * 5 0 1 1
75
+ 2^4 4 0 0
76
+ 17 0 0 0
77
+ 2 * 3^2 1 2 0
78
+ 19 0 0 0
79
+ 2^2 * 5 2 0 1
80
+ """
81
+ cdef Integer A = Integer(a)
82
+ cdef Integer P = Integer(p)
83
+ return valuation(A.value, P.value)
84
+
85
+
86
+ cdef int padic_square(mpz_t a, mpz_t p) noexcept:
87
+ """
88
+ Test if a is a `p`-adic square.
89
+ """
90
+ cdef unsigned long v
91
+ cdef mpz_t aa
92
+ cdef int result
93
+
94
+ if mpz_sgn(a) == 0:
95
+ return 1
96
+
97
+ v = valuation(a, p)
98
+ if v & 1:
99
+ return 0
100
+
101
+ mpz_init_set(aa, a)
102
+ while v:
103
+ v -= 1
104
+ mpz_divexact(aa, aa, p)
105
+ if mpz_cmp_ui(p, 2) == 0:
106
+ result = bool(mpz_fdiv_ui(aa, 8) == 1)
107
+ else:
108
+ result = bool(mpz_legendre(aa, p) == 1)
109
+ mpz_clear(aa)
110
+ return result
111
+
112
+
113
+ def test_padic_square(a, p):
114
+ """
115
+ Doctest function for cdef int padic_square(mpz_t, unsigned long).
116
+
117
+ EXAMPLES::
118
+
119
+ sage: from sage.schemes.elliptic_curves.descent_two_isogeny import test_padic_square as ps
120
+ sage: for i in [1..300]:
121
+ ....: for p in prime_range(100):
122
+ ....: if Qp(p)(i).is_square() != bool(ps(i,p)):
123
+ ....: print(i, p)
124
+ """
125
+ cdef Integer A = Integer(a)
126
+ cdef Integer P = Integer(p)
127
+ return padic_square(A.value, P.value)
128
+
129
+
130
+ cdef int lemma6(mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t e,
131
+ mpz_t x, mpz_t p, unsigned long nu) noexcept:
132
+ """
133
+ Implement Lemma 6 of BSD's "Notes on elliptic curves, I" for odd `p`.
134
+
135
+ Returns -1 for insoluble, 0 for undecided, +1 for soluble.
136
+ """
137
+ cdef mpz_t g_of_x, g_prime_of_x
138
+ cdef unsigned long lambd, mu
139
+ cdef int result = -1
140
+
141
+ mpz_init(g_of_x)
142
+ mpz_mul(g_of_x, a, x)
143
+ mpz_add(g_of_x, g_of_x, b)
144
+ mpz_mul(g_of_x, g_of_x, x)
145
+ mpz_add(g_of_x, g_of_x, c)
146
+ mpz_mul(g_of_x, g_of_x, x)
147
+ mpz_add(g_of_x, g_of_x, d)
148
+ mpz_mul(g_of_x, g_of_x, x)
149
+ mpz_add(g_of_x, g_of_x, e)
150
+
151
+ if padic_square(g_of_x, p):
152
+ mpz_clear(g_of_x)
153
+ return +1 # soluble
154
+
155
+ mpz_init_set(g_prime_of_x, x)
156
+ mpz_mul(g_prime_of_x, a, x)
157
+ mpz_mul_ui(g_prime_of_x, g_prime_of_x, 4)
158
+ mpz_addmul_ui(g_prime_of_x, b, 3)
159
+ mpz_mul(g_prime_of_x, g_prime_of_x, x)
160
+ mpz_addmul_ui(g_prime_of_x, c, 2)
161
+ mpz_mul(g_prime_of_x, g_prime_of_x, x)
162
+ mpz_add(g_prime_of_x, g_prime_of_x, d)
163
+
164
+ lambd = valuation(g_of_x, p)
165
+ if mpz_sgn(g_prime_of_x) == 0:
166
+ if lambd >= 2*nu:
167
+ result = 0 # undecided
168
+ else:
169
+ mu = valuation(g_prime_of_x, p)
170
+ if lambd > 2*mu:
171
+ result = 1 # soluble
172
+ elif lambd >= 2*nu and mu >= nu:
173
+ result = 0 # undecided
174
+
175
+ mpz_clear(g_prime_of_x)
176
+ mpz_clear(g_of_x)
177
+ return result
178
+
179
+
180
+ cdef int lemma7(mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t e,
181
+ mpz_t x, mpz_t p, unsigned long nu) noexcept:
182
+ """
183
+ Implement Lemma 7 of BSD's "Notes on elliptic curves, I" for `p=2`.
184
+
185
+ Returns -1 for insoluble, 0 for undecided, +1 for soluble.
186
+ """
187
+ cdef mpz_t g_of_x, g_prime_of_x, g_of_x_odd_part
188
+ cdef unsigned long lambd, mu, g_of_x_odd_part_mod_4
189
+ cdef int result = -1
190
+
191
+ mpz_init(g_of_x)
192
+ mpz_mul(g_of_x, a, x)
193
+ mpz_add(g_of_x, g_of_x, b)
194
+ mpz_mul(g_of_x, g_of_x, x)
195
+ mpz_add(g_of_x, g_of_x, c)
196
+ mpz_mul(g_of_x, g_of_x, x)
197
+ mpz_add(g_of_x, g_of_x, d)
198
+ mpz_mul(g_of_x, g_of_x, x)
199
+ mpz_add(g_of_x, g_of_x, e)
200
+
201
+ if padic_square(g_of_x, p):
202
+ mpz_clear(g_of_x)
203
+ return +1 # soluble
204
+
205
+ mpz_init_set(g_prime_of_x, x)
206
+ mpz_mul(g_prime_of_x, a, x)
207
+ mpz_mul_ui(g_prime_of_x, g_prime_of_x, 4)
208
+ mpz_addmul_ui(g_prime_of_x, b, 3)
209
+ mpz_mul(g_prime_of_x, g_prime_of_x, x)
210
+ mpz_addmul_ui(g_prime_of_x, c, 2)
211
+ mpz_mul(g_prime_of_x, g_prime_of_x, x)
212
+ mpz_add(g_prime_of_x, g_prime_of_x, d)
213
+
214
+ lambd = valuation(g_of_x, p)
215
+ mpz_init_set(g_of_x_odd_part, g_of_x)
216
+ while mpz_even_p(g_of_x_odd_part):
217
+ mpz_divexact_ui(g_of_x_odd_part, g_of_x_odd_part, 2)
218
+ g_of_x_odd_part_mod_4 = mpz_fdiv_ui(g_of_x_odd_part, 4)
219
+ if mpz_sgn(g_prime_of_x) == 0:
220
+ if lambd >= 2*nu:
221
+ result = 0 # undecided
222
+ elif lambd == 2*nu-2 and g_of_x_odd_part_mod_4==1:
223
+ result = 0 # undecided
224
+ else:
225
+ mu = valuation(g_prime_of_x, p)
226
+ if lambd > 2*mu:
227
+ result = 1 # soluble
228
+ elif nu > mu:
229
+ if lambd >= mu+nu:
230
+ result = 1 # soluble
231
+ elif lambd+1 == mu+nu and (lambd & 1) == 0:
232
+ result = 1 # soluble
233
+ elif lambd+2 == mu+nu and (lambd & 1) == 0 and g_of_x_odd_part_mod_4 == 1:
234
+ result = 1 # soluble
235
+ else: # nu <= mu
236
+ if lambd >= 2*nu:
237
+ result = 0 # undecided
238
+ elif lambd+2 == 2*nu and g_of_x_odd_part_mod_4==1:
239
+ result = 0 # undecided
240
+
241
+ mpz_clear(g_prime_of_x)
242
+ mpz_clear(g_of_x)
243
+ return result
244
+
245
+
246
+ cdef int Zp_soluble_BSD(mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t e,
247
+ mpz_t x_k, mpz_t p, unsigned long k) noexcept:
248
+ """
249
+ Uses the approach of BSD's "Notes on elliptic curves, I" to test for
250
+ solubility of y^2 == ax^4 + bx^3 + cx^2 + dx + e over Zp, with
251
+ x=x_k (mod p^k).
252
+ """
253
+ # returns solubility of y^2 = ax^4 + bx^3 + cx^2 + dx + e
254
+ # in Zp with x=x_k (mod p^k)
255
+ cdef int code
256
+ cdef unsigned long t
257
+ cdef mpz_t s
258
+
259
+ if mpz_cmp_ui(p, 2) == 0:
260
+ code = lemma7(a, b, c, d, e, x_k, p, k)
261
+ else:
262
+ code = lemma6(a, b, c, d, e, x_k, p, k)
263
+ if code == 1:
264
+ return 1
265
+ if code == -1:
266
+ return 0
267
+
268
+ # now code == 0
269
+ t = 0
270
+ mpz_init(s)
271
+ while code == 0 and mpz_cmp_ui(p, t) > 0 and t < N_RES_CLASSES_BSD:
272
+ mpz_pow_ui(s, p, k)
273
+ mpz_mul_ui(s, s, t)
274
+ mpz_add(s, s, x_k)
275
+ code = Zp_soluble_BSD(a, b, c, d, e, s, p, k+1)
276
+ t += 1
277
+ mpz_clear(s)
278
+ return code
279
+
280
+
281
+ cdef bint Zp_soluble_siksek(mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t e,
282
+ mpz_t pp, unsigned long pp_ui,
283
+ nmod_poly_factor_t f_factzn, nmod_poly_t f,
284
+ fmpz_poly_t f1, fmpz_poly_t linear) noexcept:
285
+ """
286
+ Uses the approach of Algorithm 5.3.1 of Siksek's thesis to test for
287
+ solubility of y^2 == ax^4 + bx^3 + cx^2 + dx + e over Zp.
288
+ """
289
+ cdef unsigned long v_min, v
290
+ cdef unsigned long roots[4]
291
+ cdef int i, j, has_roots, has_single_roots
292
+ cdef bint result
293
+
294
+ cdef mpz_t aa, bb, cc, dd, ee
295
+ cdef mpz_t aaa, bbb, ccc, ddd, eee
296
+ cdef unsigned long qq
297
+ cdef unsigned long rr, ss
298
+ cdef mpz_t tt
299
+
300
+ # Step 0: divide out all common p from the quartic
301
+ v_min = valuation(a, pp)
302
+ if mpz_cmp_ui(b, 0) != 0:
303
+ v = valuation(b, pp)
304
+ if v < v_min:
305
+ v_min = v
306
+ if mpz_cmp_ui(c, 0) != 0:
307
+ v = valuation(c, pp)
308
+ if v < v_min:
309
+ v_min = v
310
+ if mpz_cmp_ui(d, 0) != 0:
311
+ v = valuation(d, pp)
312
+ if v < v_min:
313
+ v_min = v
314
+ if mpz_cmp_ui(e, 0) != 0:
315
+ v = valuation(e, pp)
316
+ if v < v_min:
317
+ v_min = v
318
+ for v in range(v_min):
319
+ mpz_divexact(a, a, pp)
320
+ mpz_divexact(b, b, pp)
321
+ mpz_divexact(c, c, pp)
322
+ mpz_divexact(d, d, pp)
323
+ mpz_divexact(e, e, pp)
324
+
325
+ if not v_min % 2:
326
+ # Step I in Alg. 5.3.1 of Siksek's thesis
327
+ nmod_poly_set_coeff_ui(f, 0, mpz_fdiv_ui(e, pp_ui))
328
+ nmod_poly_set_coeff_ui(f, 1, mpz_fdiv_ui(d, pp_ui))
329
+ nmod_poly_set_coeff_ui(f, 2, mpz_fdiv_ui(c, pp_ui))
330
+ nmod_poly_set_coeff_ui(f, 3, mpz_fdiv_ui(b, pp_ui))
331
+ nmod_poly_set_coeff_ui(f, 4, mpz_fdiv_ui(a, pp_ui))
332
+
333
+ result = 0
334
+ (<nmod_poly_factor_struct *>f_factzn)[0].num = 0 # reset data struct
335
+ qq = nmod_poly_factor(f_factzn, f)
336
+ for i in range(f_factzn.num):
337
+ if f_factzn.exp[i]&1:
338
+ result = 1
339
+ break
340
+ if result == 0 and n_jacobi(qq, pp_ui) == 1:
341
+ result = 1
342
+ if result:
343
+ return 1
344
+
345
+ nmod_poly_zero(f)
346
+ nmod_poly_set_coeff_ui(f, 0, 1)
347
+ for i in range(f_factzn.num):
348
+ for j in range(f_factzn.exp[i]>>1):
349
+ nmod_poly_mul(f, f, &f_factzn.p[i])
350
+
351
+ (<nmod_poly_factor_struct *>f_factzn)[0].num = 0 # reset data struct
352
+ nmod_poly_factor(f_factzn, f)
353
+ has_roots = 0
354
+ j = 0
355
+ for i in range(f_factzn.num):
356
+ if nmod_poly_degree(&f_factzn.p[i]) == 1 and 0 != nmod_poly_get_coeff_ui(&f_factzn.p[i], 1):
357
+ has_roots = 1
358
+ roots[j] = pp_ui - nmod_poly_get_coeff_ui(&f_factzn.p[i], 0)
359
+ j += 1
360
+ if not has_roots:
361
+ return 0
362
+
363
+ i = nmod_poly_degree(f)
364
+ mpz_init(aaa)
365
+ mpz_init(bbb)
366
+ mpz_init(ccc)
367
+ mpz_init(ddd)
368
+ mpz_init(eee)
369
+
370
+ if i == 0: # g == 1
371
+ mpz_set(aaa, a)
372
+ mpz_set(bbb, b)
373
+ mpz_set(ccc, c)
374
+ mpz_set(ddd, d)
375
+ mpz_sub_ui(eee, e, qq)
376
+ elif i == 1: # g == x + rr
377
+ mpz_set(aaa, a)
378
+ mpz_set(bbb, b)
379
+ mpz_sub_ui(ccc, c, qq)
380
+ rr = nmod_poly_get_coeff_ui(f, 0)
381
+ ss = rr*qq
382
+ mpz_set(ddd,d)
383
+ mpz_sub_ui(ddd, ddd, ss*2)
384
+ mpz_set(eee,e)
385
+ mpz_sub_ui(eee, eee, ss*rr)
386
+ elif i == 2: # g == x^2 + rr*x + ss
387
+ mpz_sub_ui(aaa, a, qq)
388
+ rr = nmod_poly_get_coeff_ui(f, 1)
389
+ mpz_init(tt)
390
+ mpz_set_ui(tt, rr*qq)
391
+ mpz_set(bbb,b)
392
+ mpz_submul_ui(bbb, tt, 2)
393
+ mpz_set(ccc,c)
394
+ mpz_submul_ui(ccc, tt, rr)
395
+ ss = nmod_poly_get_coeff_ui(f, 0)
396
+ mpz_set_ui(tt, ss*qq)
397
+ mpz_set(eee,e)
398
+ mpz_submul_ui(eee, tt, ss)
399
+ mpz_mul_ui(tt, tt, 2)
400
+ mpz_sub(ccc, ccc, tt)
401
+ mpz_set(ddd,d)
402
+ mpz_submul_ui(ddd, tt, rr)
403
+ mpz_clear(tt)
404
+ mpz_divexact(aaa, aaa, pp)
405
+ mpz_divexact(bbb, bbb, pp)
406
+ mpz_divexact(ccc, ccc, pp)
407
+ mpz_divexact(ddd, ddd, pp)
408
+ mpz_divexact(eee, eee, pp)
409
+ # now aaa, bbb, ccc, ddd, eee represents h(x)
410
+
411
+ result = 0
412
+ mpz_init(tt)
413
+ for i in range(j):
414
+ mpz_mul_ui(tt, aaa, roots[i])
415
+ mpz_add(tt, tt, bbb)
416
+ mpz_mul_ui(tt, tt, roots[i])
417
+ mpz_add(tt, tt, ccc)
418
+ mpz_mul_ui(tt, tt, roots[i])
419
+ mpz_add(tt, tt, ddd)
420
+ mpz_mul_ui(tt, tt, roots[i])
421
+ mpz_add(tt, tt, eee)
422
+ # tt == h(r) mod p
423
+ mpz_mod(tt, tt, pp)
424
+ if mpz_sgn(tt) == 0:
425
+ fmpz_poly_zero(f1)
426
+ fmpz_poly_zero(linear)
427
+ fmpz_poly_set_coeff_mpz(f1, 0, e)
428
+ fmpz_poly_set_coeff_mpz(f1, 1, d)
429
+ fmpz_poly_set_coeff_mpz(f1, 2, c)
430
+ fmpz_poly_set_coeff_mpz(f1, 3, b)
431
+ fmpz_poly_set_coeff_mpz(f1, 4, a)
432
+ fmpz_poly_set_coeff_ui(linear, 0, roots[i])
433
+ fmpz_poly_set_coeff_mpz(linear, 1, pp)
434
+ fmpz_poly_compose(f1, f1, linear)
435
+ fmpz_poly_scalar_fdiv_ui(f1, f1, pp_ui)
436
+ fmpz_poly_scalar_fdiv_ui(f1, f1, pp_ui)
437
+ mpz_init(aa)
438
+ mpz_init(bb)
439
+ mpz_init(cc)
440
+ mpz_init(dd)
441
+ mpz_init(ee)
442
+ fmpz_poly_get_coeff_mpz(aa, f1, 4)
443
+ fmpz_poly_get_coeff_mpz(bb, f1, 3)
444
+ fmpz_poly_get_coeff_mpz(cc, f1, 2)
445
+ fmpz_poly_get_coeff_mpz(dd, f1, 1)
446
+ fmpz_poly_get_coeff_mpz(ee, f1, 0)
447
+ result = Zp_soluble_siksek(aa, bb, cc, dd, ee, pp, pp_ui, f_factzn, f, f1, linear)
448
+ mpz_clear(aa)
449
+ mpz_clear(bb)
450
+ mpz_clear(cc)
451
+ mpz_clear(dd)
452
+ mpz_clear(ee)
453
+ if result == 1:
454
+ break
455
+ mpz_clear(aaa)
456
+ mpz_clear(bbb)
457
+ mpz_clear(ccc)
458
+ mpz_clear(ddd)
459
+ mpz_clear(eee)
460
+ mpz_clear(tt)
461
+ return result
462
+ else:
463
+ # Step II in Alg. 5.3.1 of Siksek's thesis
464
+ nmod_poly_set_coeff_ui(f, 0, mpz_fdiv_ui(e, pp_ui))
465
+ nmod_poly_set_coeff_ui(f, 1, mpz_fdiv_ui(d, pp_ui))
466
+ nmod_poly_set_coeff_ui(f, 2, mpz_fdiv_ui(c, pp_ui))
467
+ nmod_poly_set_coeff_ui(f, 3, mpz_fdiv_ui(b, pp_ui))
468
+ nmod_poly_set_coeff_ui(f, 4, mpz_fdiv_ui(a, pp_ui))
469
+ (<nmod_poly_factor_struct *>f_factzn)[0].num = 0 # reset data struct
470
+ nmod_poly_factor(f_factzn, f)
471
+ has_roots = 0
472
+ has_single_roots = 0
473
+ j = 0
474
+ for i in range(f_factzn.num):
475
+ if nmod_poly_degree(&f_factzn.p[i]) == 1 and 0 != nmod_poly_get_coeff_ui(&f_factzn.p[i], 1):
476
+ has_roots = 1
477
+ if f_factzn.exp[i] == 1:
478
+ has_single_roots = 1
479
+ break
480
+ roots[j] = pp_ui - nmod_poly_get_coeff_ui(&f_factzn.p[i], 0)
481
+ j += 1
482
+
483
+ if not has_roots:
484
+ return 0
485
+ if has_single_roots:
486
+ return 1
487
+
488
+ result = 0
489
+ if j > 0:
490
+ mpz_init(aa)
491
+ mpz_init(bb)
492
+ mpz_init(cc)
493
+ mpz_init(dd)
494
+ mpz_init(ee)
495
+ for i in range(j):
496
+ fmpz_poly_zero(f1)
497
+ fmpz_poly_zero(linear)
498
+ fmpz_poly_set_coeff_mpz(f1, 0, e)
499
+ fmpz_poly_set_coeff_mpz(f1, 1, d)
500
+ fmpz_poly_set_coeff_mpz(f1, 2, c)
501
+ fmpz_poly_set_coeff_mpz(f1, 3, b)
502
+ fmpz_poly_set_coeff_mpz(f1, 4, a)
503
+ fmpz_poly_set_coeff_ui(linear, 0, roots[i])
504
+ fmpz_poly_set_coeff_mpz(linear, 1, pp)
505
+ fmpz_poly_compose(f1, f1, linear)
506
+ fmpz_poly_scalar_fdiv_ui(f1, f1, pp_ui)
507
+ fmpz_poly_get_coeff_mpz(aa, f1, 4)
508
+ fmpz_poly_get_coeff_mpz(bb, f1, 3)
509
+ fmpz_poly_get_coeff_mpz(cc, f1, 2)
510
+ fmpz_poly_get_coeff_mpz(dd, f1, 1)
511
+ fmpz_poly_get_coeff_mpz(ee, f1, 0)
512
+ result = Zp_soluble_siksek(aa, bb, cc, dd, ee, pp, pp_ui, f_factzn, f, f1, linear)
513
+ if result == 1:
514
+ break
515
+ if j > 0:
516
+ mpz_clear(aa)
517
+ mpz_clear(bb)
518
+ mpz_clear(cc)
519
+ mpz_clear(dd)
520
+ mpz_clear(ee)
521
+ return result
522
+
523
+ cdef bint Zp_soluble_siksek_large_p(mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t e, mpz_t pp,
524
+ fmpz_poly_t f1, fmpz_poly_t linear) noexcept:
525
+ """
526
+ Uses the approach of Algorithm 5.3.1 of Siksek's thesis to test for
527
+ solubility of y^2 == ax^4 + bx^3 + cx^2 + dx + e over Zp.
528
+ """
529
+ cdef unsigned long v_min, v
530
+ cdef mpz_t roots[4]
531
+ cdef int i, j, has_roots, has_single_roots
532
+ cdef bint result
533
+
534
+ cdef mpz_t aa, bb, cc, dd, ee
535
+ cdef mpz_t aaa, bbb, ccc, ddd, eee
536
+ cdef mpz_t qq, rr, ss, tt
537
+ cdef Integer A, B, C, D, E, P
538
+
539
+ # Step 0: divide out all common p from the quartic
540
+ v_min = valuation(a, pp)
541
+ if mpz_cmp_ui(b, 0) != 0:
542
+ v = valuation(b, pp)
543
+ if v < v_min:
544
+ v_min = v
545
+ if mpz_cmp_ui(c, 0) != 0:
546
+ v = valuation(c, pp)
547
+ if v < v_min:
548
+ v_min = v
549
+ if mpz_cmp_ui(d, 0) != 0:
550
+ v = valuation(d, pp)
551
+ if v < v_min:
552
+ v_min = v
553
+ if mpz_cmp_ui(e, 0) != 0:
554
+ v = valuation(e, pp)
555
+ if v < v_min:
556
+ v_min = v
557
+ for v in range(v_min):
558
+ mpz_divexact(a, a, pp)
559
+ mpz_divexact(b, b, pp)
560
+ mpz_divexact(c, c, pp)
561
+ mpz_divexact(d, d, pp)
562
+ mpz_divexact(e, e, pp)
563
+
564
+ if not v_min % 2:
565
+ # Step I in Alg. 5.3.1 of Siksek's thesis
566
+ A = Integer(0)
567
+ B = Integer(0)
568
+ C = Integer(0)
569
+ D = Integer(0)
570
+ E = Integer(0)
571
+ P = Integer(0)
572
+ mpz_set(A.value, a)
573
+ mpz_set(B.value, b)
574
+ mpz_set(C.value, c)
575
+ mpz_set(D.value, d)
576
+ mpz_set(E.value, e)
577
+ mpz_set(P.value, pp)
578
+ f = ntl.ZZ_pX([E, D, C, B, A], P)
579
+ f /= ntl.ZZ_pX([A], P) # now f is monic, and we are done with A,B,C,D,E
580
+ mpz_set(qq, A.value) # qq is the leading coefficient of the polynomial
581
+ f_factzn = f.factor()
582
+ result = 0
583
+ for factor, exponent in f_factzn:
584
+ if exponent&1:
585
+ result = 1
586
+ break
587
+ if result == 0 and mpz_legendre(qq, pp) == 1:
588
+ result = 1
589
+ if result:
590
+ return 1
591
+
592
+ f = ntl.ZZ_pX([1], P)
593
+ for factor, exponent in f_factzn:
594
+ for j in range(exponent // 2):
595
+ f *= factor
596
+
597
+ f /= f.leading_coefficient()
598
+ f_factzn = f.factor()
599
+
600
+ has_roots = 0
601
+ j = 0
602
+ for factor, exponent in f_factzn:
603
+ if factor.degree() == 1:
604
+ has_roots = 1
605
+ A = P - Integer(factor[0])
606
+ mpz_set(roots[j], A.value)
607
+ j += 1
608
+ if not has_roots:
609
+ return 0
610
+
611
+ i = f.degree()
612
+ mpz_init(aaa)
613
+ mpz_init(bbb)
614
+ mpz_init(ccc)
615
+ mpz_init(ddd)
616
+ mpz_init(eee)
617
+
618
+ if i == 0: # g == 1
619
+ mpz_set(aaa, a)
620
+ mpz_set(bbb, b)
621
+ mpz_set(ccc, c)
622
+ mpz_set(ddd, d)
623
+ mpz_sub(eee, e, qq)
624
+ elif i == 1: # g == x + rr
625
+ mpz_set(aaa, a)
626
+ mpz_set(bbb, b)
627
+ mpz_sub(ccc, c, qq)
628
+ A = Integer(f[0])
629
+ mpz_set(rr, A.value)
630
+ mpz_mul(ss, rr, qq)
631
+ mpz_set(ddd,d)
632
+ mpz_sub(ddd, ddd, ss)
633
+ mpz_sub(ddd, ddd, ss)
634
+ mpz_set(eee,e)
635
+ mpz_mul(ss, ss, rr)
636
+ mpz_sub(eee, eee, ss)
637
+ mpz_divexact(ss, ss, rr)
638
+ elif i == 2: # g == x^2 + rr*x + ss
639
+ mpz_sub(aaa, a, qq)
640
+ A = Integer(f[1])
641
+ mpz_set(rr, A.value)
642
+ mpz_init(tt)
643
+ mpz_mul(tt, rr, qq)
644
+ mpz_set(bbb,b)
645
+ mpz_submul_ui(bbb, tt, 2)
646
+ mpz_set(ccc,c)
647
+ mpz_submul(ccc, tt, rr)
648
+ A = Integer(f[0])
649
+ mpz_set(ss, A.value)
650
+ mpz_mul(tt, ss, qq)
651
+ mpz_set(eee,e)
652
+ mpz_submul(eee, tt, ss)
653
+ mpz_mul_ui(tt, tt, 2)
654
+ mpz_sub(ccc, ccc, tt)
655
+ mpz_set(ddd,d)
656
+ mpz_submul(ddd, tt, rr)
657
+ mpz_clear(tt)
658
+ mpz_divexact(aaa, aaa, pp)
659
+ mpz_divexact(bbb, bbb, pp)
660
+ mpz_divexact(ccc, ccc, pp)
661
+ mpz_divexact(ddd, ddd, pp)
662
+ mpz_divexact(eee, eee, pp)
663
+ # now aaa, bbb, ccc, ddd, eee represents h(x)
664
+
665
+ result = 0
666
+ mpz_init(tt)
667
+ for i in range(j):
668
+ mpz_mul(tt, aaa, roots[i])
669
+ mpz_add(tt, tt, bbb)
670
+ mpz_mul(tt, tt, roots[i])
671
+ mpz_add(tt, tt, ccc)
672
+ mpz_mul(tt, tt, roots[i])
673
+ mpz_add(tt, tt, ddd)
674
+ mpz_mul(tt, tt, roots[i])
675
+ mpz_add(tt, tt, eee)
676
+ # tt == h(r) mod p
677
+ mpz_mod(tt, tt, pp)
678
+ if mpz_sgn(tt) == 0:
679
+ fmpz_poly_zero(f1)
680
+ fmpz_poly_zero(linear)
681
+ fmpz_poly_set_coeff_mpz(f1, 0, e)
682
+ fmpz_poly_set_coeff_mpz(f1, 1, d)
683
+ fmpz_poly_set_coeff_mpz(f1, 2, c)
684
+ fmpz_poly_set_coeff_mpz(f1, 3, b)
685
+ fmpz_poly_set_coeff_mpz(f1, 4, a)
686
+ fmpz_poly_set_coeff_mpz(linear, 0, roots[i])
687
+ fmpz_poly_set_coeff_mpz(linear, 1, pp)
688
+ fmpz_poly_compose(f1, f1, linear)
689
+ fmpz_poly_scalar_fdiv_mpz(f1, f1, pp)
690
+ fmpz_poly_scalar_fdiv_mpz(f1, f1, pp)
691
+
692
+ mpz_init(aa)
693
+ mpz_init(bb)
694
+ mpz_init(cc)
695
+ mpz_init(dd)
696
+ mpz_init(ee)
697
+ fmpz_poly_get_coeff_mpz(aa, f1, 4)
698
+ fmpz_poly_get_coeff_mpz(bb, f1, 3)
699
+ fmpz_poly_get_coeff_mpz(cc, f1, 2)
700
+ fmpz_poly_get_coeff_mpz(dd, f1, 1)
701
+ fmpz_poly_get_coeff_mpz(ee, f1, 0)
702
+ result = Zp_soluble_siksek_large_p(aa, bb, cc, dd, ee, pp, f1, linear)
703
+ mpz_clear(aa)
704
+ mpz_clear(bb)
705
+ mpz_clear(cc)
706
+ mpz_clear(dd)
707
+ mpz_clear(ee)
708
+ if result == 1:
709
+ break
710
+ mpz_clear(aaa)
711
+ mpz_clear(bbb)
712
+ mpz_clear(ccc)
713
+ mpz_clear(ddd)
714
+ mpz_clear(eee)
715
+ mpz_clear(tt)
716
+ return result
717
+ else:
718
+ # Step II in Alg. 5.3.1 of Siksek's thesis
719
+ A = Integer(0)
720
+ B = Integer(0)
721
+ C = Integer(0)
722
+ D = Integer(0)
723
+ E = Integer(0)
724
+ P = Integer(0)
725
+ mpz_set(A.value, a)
726
+ mpz_set(B.value, b)
727
+ mpz_set(C.value, c)
728
+ mpz_set(D.value, d)
729
+ mpz_set(E.value, e)
730
+ mpz_set(P.value, pp)
731
+ f = ntl.ZZ_pX([E, D, C, B, A], P)
732
+ f /= ntl.ZZ_pX([A], P) # now f is monic
733
+ f_factzn = f.factor()
734
+
735
+ has_roots = 0
736
+ has_single_roots = 0
737
+ j = 0
738
+ for factor, exponent in f_factzn:
739
+ if factor.degree() == 1:
740
+ has_roots = 1
741
+ if exponent == 1:
742
+ has_single_roots = 1
743
+ break
744
+ A = P - Integer(factor[0])
745
+ mpz_set(roots[j], A.value)
746
+ j += 1
747
+
748
+ if not has_roots:
749
+ return 0
750
+ if has_single_roots:
751
+ return 1
752
+
753
+ result = 0
754
+ if j > 0:
755
+ mpz_init(aa)
756
+ mpz_init(bb)
757
+ mpz_init(cc)
758
+ mpz_init(dd)
759
+ mpz_init(ee)
760
+ for i in range(j):
761
+ fmpz_poly_zero(f1)
762
+ fmpz_poly_zero(linear)
763
+ fmpz_poly_set_coeff_mpz(f1, 0, e)
764
+ fmpz_poly_set_coeff_mpz(f1, 1, d)
765
+ fmpz_poly_set_coeff_mpz(f1, 2, c)
766
+ fmpz_poly_set_coeff_mpz(f1, 3, b)
767
+ fmpz_poly_set_coeff_mpz(f1, 4, a)
768
+ fmpz_poly_set_coeff_mpz(linear, 0, roots[i])
769
+ fmpz_poly_set_coeff_mpz(linear, 1, pp)
770
+ fmpz_poly_compose(f1, f1, linear)
771
+ fmpz_poly_scalar_fdiv_mpz(f1, f1, pp)
772
+ fmpz_poly_get_coeff_mpz(aa, f1, 4)
773
+ fmpz_poly_get_coeff_mpz(bb, f1, 3)
774
+ fmpz_poly_get_coeff_mpz(cc, f1, 2)
775
+ fmpz_poly_get_coeff_mpz(dd, f1, 1)
776
+ fmpz_poly_get_coeff_mpz(ee, f1, 0)
777
+ result = Zp_soluble_siksek_large_p(aa, bb, cc, dd, ee, pp, f1, linear)
778
+ if result == 1:
779
+ break
780
+ if j > 0:
781
+ mpz_clear(aa)
782
+ mpz_clear(bb)
783
+ mpz_clear(cc)
784
+ mpz_clear(dd)
785
+ mpz_clear(ee)
786
+ return result
787
+
788
+ cdef bint Qp_soluble_siksek(mpz_t A, mpz_t B, mpz_t C, mpz_t D, mpz_t E,
789
+ mpz_t p, unsigned long P,
790
+ nmod_poly_factor_t f_factzn, fmpz_poly_t f1,
791
+ fmpz_poly_t linear) noexcept:
792
+ """
793
+ Uses Samir Siksek's thesis results to determine whether the quartic is
794
+ locally soluble at p.
795
+ """
796
+ cdef int result = 0
797
+ cdef mpz_t a, b, c, d, e
798
+ cdef nmod_poly_t f
799
+ nmod_poly_init(f, P)
800
+
801
+ mpz_init_set(a, A)
802
+ mpz_init_set(b, B)
803
+ mpz_init_set(c, C)
804
+ mpz_init_set(d, D)
805
+ mpz_init_set(e, E)
806
+
807
+ if Zp_soluble_siksek(a, b, c, d, e,
808
+ p, P, f_factzn, f, f1, linear):
809
+ result = 1
810
+ else:
811
+ mpz_set(a, A)
812
+ mpz_set(b, B)
813
+ mpz_set(c, C)
814
+ mpz_set(d, D)
815
+ mpz_set(e, E)
816
+ if Zp_soluble_siksek(e, d, c, b, a,
817
+ p, P,f_factzn, f, f1, linear):
818
+ result = 1
819
+
820
+ mpz_clear(a)
821
+ mpz_clear(b)
822
+ mpz_clear(c)
823
+ mpz_clear(d)
824
+ mpz_clear(e)
825
+ nmod_poly_clear(f)
826
+ return result
827
+
828
+
829
+ cdef bint Qp_soluble_siksek_large_p(mpz_t A, mpz_t B, mpz_t C, mpz_t D, mpz_t E,
830
+ mpz_t p, fmpz_poly_t f1, fmpz_poly_t linear) noexcept:
831
+ """
832
+ Uses Samir Siksek's thesis results to determine whether the quartic is
833
+ locally soluble at p, when p is bigger than wordsize, and we can't use
834
+ FLINT.
835
+ """
836
+ cdef int result = 0
837
+ cdef mpz_t a, b, c, d, e
838
+
839
+ mpz_init_set(a,A)
840
+ mpz_init_set(b,B)
841
+ mpz_init_set(c,C)
842
+ mpz_init_set(d,D)
843
+ mpz_init_set(e,E)
844
+
845
+ if Zp_soluble_siksek_large_p(a, b, c, d, e,
846
+ p, f1, linear):
847
+ result = 1
848
+ else:
849
+ mpz_set(a,A)
850
+ mpz_set(b,B)
851
+ mpz_set(c,C)
852
+ mpz_set(d,D)
853
+ mpz_set(e,E)
854
+ if Zp_soluble_siksek_large_p(e,d,c,b,a,p,f1,linear):
855
+ result = 1
856
+
857
+ mpz_clear(a)
858
+ mpz_clear(b)
859
+ mpz_clear(c)
860
+ mpz_clear(d)
861
+ mpz_clear(e)
862
+ return result
863
+
864
+ cdef bint Qp_soluble_BSD(mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t e, mpz_t p) noexcept:
865
+ """
866
+ Uses the original test of Birch and Swinnerton-Dyer to test for local
867
+ solubility of the quartic at p.
868
+ """
869
+ cdef mpz_t zero
870
+ cdef int result = 0
871
+ mpz_init_set_ui(zero, 0)
872
+ if Zp_soluble_BSD(a, b, c, d, e,
873
+ zero, p, 0):
874
+ result = 1
875
+ elif Zp_soluble_BSD(e, d, c, b, a,
876
+ zero, p, 1):
877
+ result = 1
878
+ mpz_clear(zero)
879
+ return result
880
+
881
+ cdef bint Qp_soluble(mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t e, mpz_t p) noexcept:
882
+ """
883
+ Try the BSD approach for a few residue classes and if no solution is found,
884
+ switch to Siksek to try to prove insolubility.
885
+ """
886
+ cdef int bsd_sol, sik_sol
887
+ cdef unsigned long pp
888
+ cdef fmpz_poly_t f1, linear
889
+ cdef nmod_poly_factor_t f_factzn
890
+ bsd_sol = Qp_soluble_BSD(a, b, c, d, e, p)
891
+ if mpz_cmp_ui(p,N_RES_CLASSES_BSD)>0 and not bsd_sol:
892
+ fmpz_poly_init(f1)
893
+ fmpz_poly_init(linear)
894
+ if mpz_fits_ulong_p(p):
895
+ nmod_poly_factor_init(f_factzn)
896
+ pp = mpz_get_ui(p)
897
+ sik_sol = Qp_soluble_siksek(a, b, c, d, e,
898
+ p, pp, f_factzn, f1,linear)
899
+ nmod_poly_factor_clear(f_factzn)
900
+ else:
901
+ sik_sol = Qp_soluble_siksek_large_p(a, b, c, d, e,
902
+ p, f1, linear)
903
+ fmpz_poly_clear(f1)
904
+ fmpz_poly_clear(linear)
905
+ else:
906
+ sik_sol = bsd_sol
907
+ return sik_sol
908
+
909
+
910
+ def test_qpls(a, b, c, d, e, p):
911
+ """
912
+ Testing function for Qp_soluble.
913
+
914
+ EXAMPLES::
915
+
916
+ sage: from sage.schemes.elliptic_curves.descent_two_isogeny import test_qpls as tq
917
+ sage: tq(1,2,3,4,5,7)
918
+ 1
919
+ """
920
+ cdef Integer A, B, C, D, E, P
921
+ cdef int result
922
+ cdef mpz_t aa, bb, cc, dd, ee, pp
923
+ A = Integer(a)
924
+ B = Integer(b)
925
+ C = Integer(c)
926
+ D = Integer(d)
927
+ E = Integer(e)
928
+ P = Integer(p)
929
+ mpz_init_set(aa, A.value)
930
+ mpz_init_set(bb, B.value)
931
+ mpz_init_set(cc, C.value)
932
+ mpz_init_set(dd, D.value)
933
+ mpz_init_set(ee, E.value)
934
+ mpz_init_set(pp, P.value)
935
+ result = Qp_soluble(aa, bb, cc, dd, ee, pp)
936
+ mpz_clear(aa)
937
+ mpz_clear(bb)
938
+ mpz_clear(cc)
939
+ mpz_clear(dd)
940
+ mpz_clear(ee)
941
+ mpz_clear(pp)
942
+ return result
943
+
944
+
945
+ cdef int everywhere_locally_soluble(mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t e) except -1:
946
+ """
947
+ Return whether the quartic has local solutions at all primes `p`.
948
+ """
949
+ cdef Integer A, B, C, D, E, Delta,p
950
+ cdef mpz_t mpz_2
951
+ A = Integer(0)
952
+ B = Integer(0)
953
+ C = Integer(0)
954
+ D = Integer(0)
955
+ E = Integer(0)
956
+ mpz_set(A.value, a)
957
+ mpz_set(B.value, b)
958
+ mpz_set(C.value, c)
959
+ mpz_set(D.value, d)
960
+ mpz_set(E.value, e)
961
+ f = (((A*x_ZZ + B)*x_ZZ + C)*x_ZZ + D)*x_ZZ + E
962
+
963
+ # RR soluble:
964
+ if mpz_sgn(a) != 1:
965
+ if not real_roots(f):
966
+ return 0
967
+
968
+ # Q2 soluble:
969
+ mpz_init_set_ui(mpz_2, 2)
970
+ if not Qp_soluble(a, b, c, d, e, mpz_2):
971
+ mpz_clear(mpz_2)
972
+ return 0
973
+ mpz_clear(mpz_2)
974
+
975
+ # Odd finite primes
976
+ Delta = f.discriminant()
977
+ if not Delta:
978
+ raise ValueError("the curve is singular, Delta is zero")
979
+ for p in prime_divisors(Delta):
980
+ if p == 2:
981
+ continue
982
+ if not Qp_soluble(a, b, c, d, e, p.value):
983
+ return 0
984
+
985
+ return 1
986
+
987
+
988
+ def test_els(a, b, c, d, e):
989
+ """
990
+ Doctest function for cdef int everywhere_locally_soluble(mpz_t, mpz_t, mpz_t, mpz_t, mpz_t).
991
+
992
+ EXAMPLES::
993
+
994
+ sage: from sage.schemes.elliptic_curves.descent_two_isogeny import test_els
995
+ sage: for _ in range(1000):
996
+ ....: a,b,c,d,e = randint(1,1000), randint(1,1000), randint(1,1000), randint(1,1000), randint(1,1000)
997
+ ....: if pari.Pol([a,b,c,d,e]).hyperellratpoints(1000, 1):
998
+ ....: try:
999
+ ....: if not test_els(a,b,c,d,e):
1000
+ ....: print("This never happened", a, b, c, d, e)
1001
+ ....: except ValueError:
1002
+ ....: continue
1003
+
1004
+ TESTS:
1005
+
1006
+ Check that :issue:`39864` is fixed::
1007
+
1008
+ sage: test_els(194, 617, 846, 617, 194)
1009
+ Traceback (most recent call last):
1010
+ ...
1011
+ ValueError: the curve is singular, Delta is zero
1012
+ """
1013
+ cdef Integer A, B, C, D, E
1014
+ A = Integer(a)
1015
+ B = Integer(b)
1016
+ C = Integer(c)
1017
+ D = Integer(d)
1018
+ E = Integer(e)
1019
+ return everywhere_locally_soluble(A.value, B.value, C.value, D.value, E.value)
1020
+
1021
+
1022
+ cdef int count(mpz_t c_mpz, mpz_t d_mpz, mpz_t *p_list, unsigned long p_list_len,
1023
+ int global_limit_small, int global_limit_large,
1024
+ int verbosity, bint selmer_only, mpz_t n1, mpz_t n2) except -1:
1025
+ """
1026
+ Count the number of els/gls quartic 2-covers of E.
1027
+ """
1028
+ cdef unsigned long n_primes, i
1029
+ cdef bint found_global_points, els, check_negs, verbose = (verbosity > 4)
1030
+ cdef Integer a_Int, c_Int, e_Int
1031
+ cdef mpz_t c_sq_mpz, d_prime_mpz
1032
+ cdef mpz_t n_divisors, j
1033
+
1034
+ mpz_init(c_sq_mpz)
1035
+ mpz_mul(c_sq_mpz, c_mpz, c_mpz)
1036
+ mpz_init_set(d_prime_mpz, c_sq_mpz)
1037
+ mpz_submul_ui(d_prime_mpz, d_mpz, 4)
1038
+ check_negs = 0
1039
+ if mpz_sgn(d_prime_mpz) > 0:
1040
+ if mpz_sgn(c_mpz) >= 0 or mpz_cmp(c_sq_mpz, d_prime_mpz) <= 0:
1041
+ check_negs = 1
1042
+ mpz_clear(c_sq_mpz)
1043
+ mpz_clear(d_prime_mpz)
1044
+
1045
+ # Set up coefficient array, and static variables
1046
+ cdef mpz_t *coeffs = <mpz_t *> sig_malloc(5 * sizeof(mpz_t))
1047
+ for i in range(5):
1048
+ mpz_init(coeffs[i])
1049
+ mpz_set_ui(coeffs[1], 0) #
1050
+ mpz_set(coeffs[2], c_mpz) # These never change
1051
+ mpz_set_ui(coeffs[3], 0) #
1052
+
1053
+ # Get prime divisors, and put them in an mpz_t array
1054
+ # (this block, by setting check_negs, takes care of
1055
+ # local solubility over RR)
1056
+ cdef mpz_t *p_div_d_mpz = <mpz_t *> sig_malloc((p_list_len+1) * sizeof(mpz_t))
1057
+ n_primes = 0
1058
+ for i in range(p_list_len):
1059
+ if mpz_divisible_p(d_mpz, p_list[i]):
1060
+ mpz_init(p_div_d_mpz[n_primes])
1061
+ mpz_set(p_div_d_mpz[n_primes], p_list[i])
1062
+ n_primes += 1
1063
+ if check_negs:
1064
+ mpz_init(p_div_d_mpz[n_primes])
1065
+ mpz_set_si(p_div_d_mpz[n_primes], -1)
1066
+ n_primes += 1
1067
+ mpz_init_set_ui(n_divisors, 1)
1068
+ mpz_mul_2exp(n_divisors, n_divisors, n_primes)
1069
+
1070
+ mpz_init_set_ui(j, 0)
1071
+ if not selmer_only:
1072
+ mpz_set_ui(n1, 0)
1073
+ mpz_set_ui(n2, 0)
1074
+ while mpz_cmp(j, n_divisors) < 0:
1075
+ mpz_set_ui(coeffs[4], 1)
1076
+ for i in range(n_primes):
1077
+ if mpz_tstbit(j, i):
1078
+ mpz_mul(coeffs[4], coeffs[4], p_div_d_mpz[i])
1079
+ if verbosity > 3:
1080
+ a_Int = Integer(0)
1081
+ mpz_set(a_Int.value, coeffs[4])
1082
+ print('\nSquarefree divisor:', a_Int)
1083
+ mpz_divexact(coeffs[0], d_mpz, coeffs[4])
1084
+ found_global_points = 0
1085
+ if not selmer_only:
1086
+ if verbose:
1087
+ print("\nCalling ratpoints for small point search")
1088
+ found_global_points = ratpoints_mpz_exists_only(coeffs, 4, global_limit_small)
1089
+ if found_global_points:
1090
+ if verbosity > 2:
1091
+ a_Int = Integer(0)
1092
+ mpz_set(a_Int.value, coeffs[4])
1093
+ c_Int = Integer(0)
1094
+ mpz_set(c_Int.value, coeffs[2])
1095
+ e_Int = Integer(0)
1096
+ mpz_set(e_Int.value, coeffs[0])
1097
+ print('Found small global point, quartic (%d,%d,%d,%d,%d)' % (a_Int, 0, c_Int, 0, e_Int))
1098
+ mpz_add_ui(n1, n1, 1)
1099
+ mpz_add_ui(n2, n2, 1)
1100
+ if verbose:
1101
+ print("\nDone calling ratpoints for small point search")
1102
+ if not found_global_points:
1103
+ # Test whether the quartic is everywhere locally soluble:
1104
+ els = 1
1105
+ for i in range(p_list_len):
1106
+ if not Qp_soluble(coeffs[4], coeffs[3], coeffs[2], coeffs[1], coeffs[0], p_list[i]):
1107
+ els = 0
1108
+ break
1109
+ if els:
1110
+ if verbosity > 2:
1111
+ a_Int = Integer(0)
1112
+ mpz_set(a_Int.value, coeffs[4])
1113
+ c_Int = Integer(0)
1114
+ mpz_set(c_Int.value, coeffs[2])
1115
+ e_Int = Integer(0)
1116
+ mpz_set(e_Int.value, coeffs[0])
1117
+ print('ELS without small global points, quartic (%d,%d,%d,%d,%d)' % (a_Int, 0, c_Int, 0, e_Int))
1118
+ mpz_add_ui(n2, n2, 1)
1119
+ if not selmer_only:
1120
+ if verbose:
1121
+ print("\nCalling ratpoints for large point search")
1122
+ found_global_points = ratpoints_mpz_exists_only(coeffs, 4, global_limit_large)
1123
+ if found_global_points:
1124
+ if verbosity > 2:
1125
+ print(' -- Found large global point.')
1126
+ mpz_add_ui(n1, n1, 1)
1127
+ if verbose:
1128
+ print("\nDone calling ratpoints for large point search")
1129
+ mpz_add_ui(j, j, 1)
1130
+ mpz_clear(j)
1131
+ for i in range(n_primes):
1132
+ mpz_clear(p_div_d_mpz[i])
1133
+ sig_free(p_div_d_mpz)
1134
+ mpz_clear(n_divisors)
1135
+ for i in range(5):
1136
+ mpz_clear(coeffs[i])
1137
+ sig_free(coeffs)
1138
+ return 0
1139
+
1140
+
1141
+ def two_descent_by_two_isogeny(E,
1142
+ int global_limit_small=10,
1143
+ int global_limit_large=10000,
1144
+ int verbosity=0,
1145
+ bint selmer_only=0, bint proof=1):
1146
+ """
1147
+ Given an elliptic curve E with a two-isogeny phi : E --> E' and dual isogeny
1148
+ phi', runs a two-isogeny descent on E, returning n1, n2, n1' and n2'. Here
1149
+ n1 is the number of quartic covers found with a rational point, and n2 is
1150
+ the number which are ELS.
1151
+
1152
+ EXAMPLES::
1153
+
1154
+ sage: # needs sage.schemes
1155
+ sage: from sage.schemes.elliptic_curves.descent_two_isogeny import two_descent_by_two_isogeny
1156
+ sage: E = EllipticCurve('14a')
1157
+ sage: n1, n2, n1_prime, n2_prime = two_descent_by_two_isogeny(E)
1158
+ sage: log(n1,2) + log(n1_prime,2) - 2 # the rank
1159
+ 0
1160
+ sage: E = EllipticCurve('65a')
1161
+ sage: n1, n2, n1_prime, n2_prime = two_descent_by_two_isogeny(E)
1162
+ sage: log(n1,2) + log(n1_prime,2) - 2 # the rank
1163
+ 1
1164
+
1165
+ sage: # needs sage.schemes sage.symbolic
1166
+ sage: x,y = var('x,y')
1167
+ sage: E = EllipticCurve(y^2 == x^3 + x^2 - 25*x + 39)
1168
+ sage: n1, n2, n1_prime, n2_prime = two_descent_by_two_isogeny(E)
1169
+ sage: log(n1,2) + log(n1_prime,2) - 2 # the rank
1170
+ 2
1171
+ sage: E = EllipticCurve(y^2 + x*y + y == x^3 - 131*x + 558)
1172
+ sage: n1, n2, n1_prime, n2_prime = two_descent_by_two_isogeny(E)
1173
+ sage: log(n1,2) + log(n1_prime,2) - 2 # the rank
1174
+ 3
1175
+
1176
+ Using the verbosity option::
1177
+
1178
+ sage: # needs sage.schemes
1179
+ sage: E = EllipticCurve('14a')
1180
+ sage: two_descent_by_two_isogeny(E, verbosity=1)
1181
+ 2-isogeny
1182
+ Results:
1183
+ 2 <= #E(Q)/phi'(E'(Q)) <= 2
1184
+ 2 <= #E'(Q)/phi(E(Q)) <= 2
1185
+ #Sel^(phi')(E'/Q) = 2
1186
+ #Sel^(phi)(E/Q) = 2
1187
+ 1 <= #Sha(E'/Q)[phi'] <= 1
1188
+ 1 <= #Sha(E/Q)[phi] <= 1
1189
+ 1 <= #Sha(E/Q)[2], #Sha(E'/Q)[2] <= 1
1190
+ 0 <= rank of E(Q) = rank of E'(Q) <= 0
1191
+ (2, 2, 2, 2)
1192
+
1193
+ Handling curves whose discriminants involve larger than wordsize primes::
1194
+
1195
+ sage: # needs sage.schemes
1196
+ sage: E = EllipticCurve('14a')
1197
+ sage: E = E.quadratic_twist(next_prime(10^20))
1198
+ sage: E
1199
+ Elliptic Curve defined by y^2 = x^3 + x^2 + 716666666666666667225666666666666666775672*x - 391925925925925926384240370370370370549019837037037037060249356 over Rational Field
1200
+ sage: E.discriminant().factor()
1201
+ -1 * 2^18 * 7^3 * 100000000000000000039^6
1202
+ sage: log(100000000000000000039.0, 2.0)
1203
+ 66.438...
1204
+ sage: n1, n2, n1_prime, n2_prime = two_descent_by_two_isogeny(E)
1205
+ sage: log(n1,2) + log(n1_prime,2) - 2 # the rank
1206
+ 0
1207
+
1208
+ TESTS:
1209
+
1210
+ Here we contrive an example to demonstrate that a keyboard interrupt
1211
+ is caught. Here we let `E` be the smallest optimal curve with two-torsion
1212
+ and nontrivial `Sha[2]`. This ensures that the two-descent will be looking
1213
+ for rational points which do not exist, and by setting global_limit_large
1214
+ to a very high bound, it will still be working when we simulate a ``CTRL-C``::
1215
+
1216
+ sage: # needs sage.schemes
1217
+ sage: from sage.schemes.elliptic_curves.descent_two_isogeny import two_descent_by_two_isogeny
1218
+ sage: E = EllipticCurve('960d'); E
1219
+ Elliptic Curve defined by y^2 = x^3 - x^2 - 900*x - 10098 over Rational Field
1220
+ sage: E.sha().an()
1221
+ 4
1222
+ sage: from sage.doctest.util import ensure_interruptible_after
1223
+ sage: with ensure_interruptible_after(0.5): two_descent_by_two_isogeny(E, global_limit_large=10^8)
1224
+ """
1225
+ cdef Integer a1, a2, a3, a4, a6, s2, s4, s6
1226
+ cdef Integer c, d, x0
1227
+ cdef list x_list
1228
+ assert E.torsion_order() % 2 == 0, 'Need rational two-torsion for isogeny descent.'
1229
+ if verbosity > 0:
1230
+ print('\n2-isogeny')
1231
+ if verbosity > 1:
1232
+ print('\nchanging coordinates')
1233
+ a1 = Integer(E.a1())
1234
+ a2 = Integer(E.a2())
1235
+ a3 = Integer(E.a3())
1236
+ a4 = Integer(E.a4())
1237
+ a6 = Integer(E.a6())
1238
+ if a1 == 0 == a3:
1239
+ s2 = a2
1240
+ s4 = a4
1241
+ s6 = a6
1242
+ else:
1243
+ s2 = a1*a1+4*a2
1244
+ s4 = 8*(a1*a3+2*a4)
1245
+ s6 = 16*(a3*a3+4*a6)
1246
+ f = ((x_ZZ + s2)*x_ZZ + s4)*x_ZZ + s6
1247
+ x_list = f.roots() # over ZZ -- use FLINT directly?
1248
+ x0 = x_list[0][0]
1249
+ c = 3*x0+s2
1250
+ d = (c+s2)*x0+s4
1251
+ return two_descent_by_two_isogeny_work(c, d,
1252
+ global_limit_small,
1253
+ global_limit_large, verbosity,
1254
+ selmer_only, proof)
1255
+
1256
+
1257
+ def two_descent_by_two_isogeny_work(Integer c, Integer d,
1258
+ int global_limit_small=10,
1259
+ int global_limit_large=10000,
1260
+ int verbosity=0, bint selmer_only=0,
1261
+ bint proof=1):
1262
+ """
1263
+ Do all the work in doing a two-isogeny descent.
1264
+
1265
+ EXAMPLES::
1266
+
1267
+ sage: from sage.schemes.elliptic_curves.descent_two_isogeny import two_descent_by_two_isogeny_work
1268
+ sage: n1, n2, n1_prime, n2_prime = two_descent_by_two_isogeny_work(13,128)
1269
+ sage: log(n1,2) + log(n1_prime,2) - 2 # the rank
1270
+ 0
1271
+ sage: n1, n2, n1_prime, n2_prime = two_descent_by_two_isogeny_work(1,-16)
1272
+ sage: log(n1,2) + log(n1_prime,2) - 2 # the rank
1273
+ 1
1274
+ sage: n1, n2, n1_prime, n2_prime = two_descent_by_two_isogeny_work(10,8)
1275
+ sage: log(n1,2) + log(n1_prime,2) - 2 # the rank
1276
+ 2
1277
+ sage: n1, n2, n1_prime, n2_prime = two_descent_by_two_isogeny_work(85,320)
1278
+ sage: log(n1,2) + log(n1_prime,2) - 2 # the rank
1279
+ 3
1280
+ """
1281
+ cdef mpz_t c_mpz, d_mpz, c_prime_mpz, d_prime_mpz
1282
+ cdef mpz_t *p_list_mpz
1283
+ cdef unsigned long i, j, p, p_list_len
1284
+ cdef Integer P, n1, n2, n1_prime, n2_prime, c_prime, d_prime
1285
+ cdef object PO
1286
+ cdef bint found, d_neg, d_prime_neg
1287
+ cdef n_factor_t fact
1288
+ cdef list primes
1289
+ mpz_init_set(c_mpz, c.value)
1290
+ mpz_init_set(d_mpz, d.value)
1291
+ mpz_init(c_prime_mpz)
1292
+ mpz_init(d_prime_mpz)
1293
+ mpz_mul_si(c_prime_mpz, c_mpz, -2)
1294
+ mpz_mul(d_prime_mpz, c_mpz, c_mpz)
1295
+ mpz_submul_ui(d_prime_mpz, d_mpz, 4)
1296
+
1297
+ d_neg = 0
1298
+ d_prime_neg = 0
1299
+ if mpz_sgn(d_mpz) < 0:
1300
+ d_neg = 1
1301
+ mpz_neg(d_mpz, d_mpz)
1302
+ if mpz_sgn(d_prime_mpz) < 0:
1303
+ d_prime_neg = 1
1304
+ mpz_neg(d_prime_mpz, d_prime_mpz)
1305
+ if mpz_fits_ulong_p(d_mpz) and mpz_fits_ulong_p(d_prime_mpz):
1306
+ # Factor very quickly using FLINT.
1307
+ p_list_mpz = <mpz_t *> sig_malloc(20 * sizeof(mpz_t))
1308
+ mpz_init_set_ui(p_list_mpz[0], 2)
1309
+ p_list_len = 1
1310
+ n_factor_init(&fact)
1311
+ n_factor(&fact, mpz_get_ui(d_mpz), proof)
1312
+ for i in range(fact.num):
1313
+ p = fact.p[i]
1314
+ if p != 2:
1315
+ mpz_init_set_ui(p_list_mpz[p_list_len], p)
1316
+ p_list_len += 1
1317
+ n_factor(&fact, mpz_get_ui(d_prime_mpz), proof)
1318
+ for i in range(fact.num):
1319
+ p = fact.p[i]
1320
+ found = 0
1321
+ for j in range(p_list_len):
1322
+ if mpz_cmp_ui(p_list_mpz[j], p) == 0:
1323
+ found = 1
1324
+ break
1325
+ if not found:
1326
+ mpz_init_set_ui(p_list_mpz[p_list_len], p)
1327
+ p_list_len += 1
1328
+ else:
1329
+ # Factor more slowly using Pari via Python.
1330
+ from sage.libs.pari import pari
1331
+ d = Integer(0)
1332
+ mpz_set(d.value, d_mpz)
1333
+ primes = list(pari(d).factor()[0])
1334
+ d_prime = Integer(0)
1335
+ mpz_set(d_prime.value, d_prime_mpz)
1336
+ for PO in pari(d_prime).factor()[0]:
1337
+ if PO not in primes:
1338
+ primes.append(PO)
1339
+ P = Integer(2)
1340
+ if P not in primes:
1341
+ primes.append(P)
1342
+ p_list_len = len(primes)
1343
+ p_list_mpz = <mpz_t *> sig_malloc(p_list_len * sizeof(mpz_t))
1344
+ for i in range(p_list_len):
1345
+ P = Integer(primes[i])
1346
+ mpz_init_set(p_list_mpz[i], P.value)
1347
+ if d_neg:
1348
+ mpz_neg(d_mpz, d_mpz)
1349
+ if d_prime_neg:
1350
+ mpz_neg(d_prime_mpz, d_prime_mpz)
1351
+
1352
+ if verbosity > 1:
1353
+ c_prime = -2*c
1354
+ d_prime = c*c-4*d
1355
+ print('\nnew curve is y^2 == x( x^2 + (%d)x + (%d) )' % (int(c), int(d)))
1356
+ print('new isogenous curve is' +
1357
+ ' y^2 == x( x^2 + (%d)x + (%d) )' % (int(c_prime), int(d_prime)))
1358
+
1359
+ n1 = Integer(0)
1360
+ n2 = Integer(0)
1361
+ n1_prime = Integer(0)
1362
+ n2_prime = Integer(0)
1363
+ count(c.value, d.value, p_list_mpz, p_list_len,
1364
+ global_limit_small, global_limit_large, verbosity, selmer_only,
1365
+ n1.value, n2.value)
1366
+ count(c_prime_mpz, d_prime_mpz, p_list_mpz, p_list_len,
1367
+ global_limit_small, global_limit_large, verbosity, selmer_only,
1368
+ n1_prime.value, n2_prime.value)
1369
+
1370
+ for i in range(p_list_len):
1371
+ mpz_clear(p_list_mpz[i])
1372
+ sig_free(p_list_mpz)
1373
+
1374
+ if verbosity > 0:
1375
+ print("\nResults:")
1376
+ print(n1, "<= #E(Q)/phi'(E'(Q)) <=", n2)
1377
+ print(n1_prime, "<= #E'(Q)/phi(E(Q)) <=", n2_prime)
1378
+ print("#Sel^(phi')(E'/Q) =", n2)
1379
+ print("#Sel^(phi)(E/Q) =", n2_prime)
1380
+ print("1 <= #Sha(E'/Q)[phi'] <=", n2/n1)
1381
+ print("1 <= #Sha(E/Q)[phi] <=", n2_prime/n1_prime)
1382
+ print("1 <= #Sha(E/Q)[2], #Sha(E'/Q)[2] <=", (n2_prime/n1_prime)*(n2/n1))
1383
+ a = Integer(n1*n1_prime).log(Integer(2))
1384
+ e = Integer(n2*n2_prime).log(Integer(2))
1385
+ print(a - 2, "<= rank of E(Q) = rank of E'(Q) <=", e - 2)
1386
+
1387
+ return n1, n2, n1_prime, n2_prime