passagemath-pari 10.6.32__cp314-cp314-musllinux_1_2_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.

Potentially problematic release.


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

Files changed (331) hide show
  1. PARIKernel/__init__.py +2 -0
  2. PARIKernel/__main__.py +5 -0
  3. PARIKernel/io.cpython-314-x86_64-linux-musl.so +0 -0
  4. PARIKernel/io.pxd +7 -0
  5. PARIKernel/io.pyx +84 -0
  6. PARIKernel/kernel.cpython-314-x86_64-linux-musl.so +0 -0
  7. PARIKernel/kernel.pyx +260 -0
  8. PARIKernel/paridecl.pxd +95 -0
  9. PARIKernel/svg.cpython-314-x86_64-linux-musl.so +0 -0
  10. PARIKernel/svg.pyx +52 -0
  11. cypari2/__init__.py +8 -0
  12. cypari2/auto_paridecl.pxd +1070 -0
  13. cypari2/closure.cpython-314-x86_64-linux-musl.so +0 -0
  14. cypari2/closure.pxd +5 -0
  15. cypari2/closure.pyx +246 -0
  16. cypari2/convert.cpython-314-x86_64-linux-musl.so +0 -0
  17. cypari2/convert.pxd +80 -0
  18. cypari2/convert.pyx +613 -0
  19. cypari2/custom_block.cpython-314-x86_64-linux-musl.so +0 -0
  20. cypari2/custom_block.pyx +30 -0
  21. cypari2/cypari.h +13 -0
  22. cypari2/gen.cpython-314-x86_64-linux-musl.so +0 -0
  23. cypari2/gen.pxd +69 -0
  24. cypari2/gen.pyx +4819 -0
  25. cypari2/handle_error.cpython-314-x86_64-linux-musl.so +0 -0
  26. cypari2/handle_error.pxd +7 -0
  27. cypari2/handle_error.pyx +232 -0
  28. cypari2/pari_instance.cpython-314-x86_64-linux-musl.so +0 -0
  29. cypari2/pari_instance.pxd +27 -0
  30. cypari2/pari_instance.pyx +1438 -0
  31. cypari2/paridecl.pxd +5353 -0
  32. cypari2/paripriv.pxd +34 -0
  33. cypari2/pycore_long.h +98 -0
  34. cypari2/pycore_long.pxd +9 -0
  35. cypari2/stack.cpython-314-x86_64-linux-musl.so +0 -0
  36. cypari2/stack.pxd +27 -0
  37. cypari2/stack.pyx +278 -0
  38. cypari2/string_utils.cpython-314-x86_64-linux-musl.so +0 -0
  39. cypari2/string_utils.pxd +29 -0
  40. cypari2/string_utils.pyx +65 -0
  41. cypari2/types.pxd +147 -0
  42. passagemath_pari-10.6.32.data/data/etc/jupyter/nbconfig/notebook.d/gp-mode.json +5 -0
  43. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.js +28 -0
  44. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.json +6 -0
  45. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/logo-64x64.png +0 -0
  46. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/kernel.json +13 -0
  47. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-32x32.png +0 -0
  48. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-64x64.png +0 -0
  49. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-svg.svg +75 -0
  50. passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/gp.js +284 -0
  51. passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/main.js +15 -0
  52. passagemath_pari-10.6.32.dist-info/METADATA +209 -0
  53. passagemath_pari-10.6.32.dist-info/RECORD +331 -0
  54. passagemath_pari-10.6.32.dist-info/WHEEL +5 -0
  55. passagemath_pari-10.6.32.dist-info/top_level.txt +4 -0
  56. passagemath_pari.libs/libcrypto-f04afe95.so.3 +0 -0
  57. passagemath_pari.libs/libflint-fd6f12fc.so.21.0.0 +0 -0
  58. passagemath_pari.libs/libgcc_s-0cd532bd.so.1 +0 -0
  59. passagemath_pari.libs/libgf2x-9e30c3e3.so.3.0.0 +0 -0
  60. passagemath_pari.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
  61. passagemath_pari.libs/libgivaro-9a94c711.so.9.2.1 +0 -0
  62. passagemath_pari.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  63. passagemath_pari.libs/libgmpxx-9e08595c.so.4.7.0 +0 -0
  64. passagemath_pari.libs/libgsl-42cda06f.so.28.0.0 +0 -0
  65. passagemath_pari.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
  66. passagemath_pari.libs/libncursesw-9c9e32c3.so.6.5 +0 -0
  67. passagemath_pari.libs/libntl-26885ca2.so.44.0.1 +0 -0
  68. passagemath_pari.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
  69. passagemath_pari.libs/libpari-gmp-tls-f31f908f.so.2.17.2 +0 -0
  70. passagemath_pari.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
  71. passagemath_pari.libs/libreadline-06542304.so.8.2 +0 -0
  72. passagemath_pari.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
  73. passagemath_pari.libs/libuuid-f3770415.so.1.3.0 +0 -0
  74. passagemath_pari.libs/libxeus-735780ff.so.13.1.0 +0 -0
  75. passagemath_pari.libs/libxeus-zmq-c68577b4.so.6.0.1 +0 -0
  76. passagemath_pari.libs/libzmq-1ba9a3da.so.5.2.5 +0 -0
  77. sage/all__sagemath_pari.py +26 -0
  78. sage/databases/all__sagemath_pari.py +7 -0
  79. sage/databases/conway.py +274 -0
  80. sage/ext/all__sagemath_pari.py +1 -0
  81. sage/ext/memory.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/ext/memory.pyx +98 -0
  83. sage/ext_data/pari/buzzard/DimensionSk.g +286 -0
  84. sage/ext_data/pari/buzzard/Tpprog.g +179 -0
  85. sage/ext_data/pari/buzzard/genusn.g +129 -0
  86. sage/ext_data/pari/dokchitser/computel.gp +740 -0
  87. sage/ext_data/pari/dokchitser/computel.gp.template +740 -0
  88. sage/ext_data/pari/dokchitser/ex-bsw +43 -0
  89. sage/ext_data/pari/dokchitser/ex-chgen +48 -0
  90. sage/ext_data/pari/dokchitser/ex-chqua +37 -0
  91. sage/ext_data/pari/dokchitser/ex-delta +35 -0
  92. sage/ext_data/pari/dokchitser/ex-eisen +30 -0
  93. sage/ext_data/pari/dokchitser/ex-gen2 +38 -0
  94. sage/ext_data/pari/dokchitser/ex-gen3 +49 -0
  95. sage/ext_data/pari/dokchitser/ex-gen4 +54 -0
  96. sage/ext_data/pari/dokchitser/ex-nf +48 -0
  97. sage/ext_data/pari/dokchitser/ex-shin +50 -0
  98. sage/ext_data/pari/dokchitser/ex-tau2 +30 -0
  99. sage/ext_data/pari/dokchitser/ex-zeta +27 -0
  100. sage/ext_data/pari/dokchitser/ex-zeta2 +47 -0
  101. sage/ext_data/pari/dokchitser/testall +13 -0
  102. sage/ext_data/pari/simon/ell.gp +2129 -0
  103. sage/ext_data/pari/simon/ellQ.gp +2151 -0
  104. sage/ext_data/pari/simon/ellcommon.gp +126 -0
  105. sage/ext_data/pari/simon/qfsolve.gp +722 -0
  106. sage/ext_data/pari/simon/resultant3.gp +306 -0
  107. sage/groups/all__sagemath_pari.py +3 -0
  108. sage/groups/pari_group.py +175 -0
  109. sage/interfaces/all__sagemath_pari.py +1 -0
  110. sage/interfaces/genus2reduction.py +464 -0
  111. sage/interfaces/gp.py +1114 -0
  112. sage/libs/all__sagemath_pari.py +2 -0
  113. sage/libs/linkages/__init__.py +1 -0
  114. sage/libs/linkages/padics/API.pxi +617 -0
  115. sage/libs/linkages/padics/Polynomial_ram.pxi +388 -0
  116. sage/libs/linkages/padics/Polynomial_shared.pxi +554 -0
  117. sage/libs/linkages/padics/__init__.py +1 -0
  118. sage/libs/linkages/padics/fmpz_poly_unram.pxi +869 -0
  119. sage/libs/linkages/padics/mpz.pxi +691 -0
  120. sage/libs/linkages/padics/relaxed/API.pxi +518 -0
  121. sage/libs/linkages/padics/relaxed/__init__.py +1 -0
  122. sage/libs/linkages/padics/relaxed/flint.pxi +543 -0
  123. sage/libs/linkages/padics/unram_shared.pxi +247 -0
  124. sage/libs/pari/__init__.py +210 -0
  125. sage/libs/pari/all.py +5 -0
  126. sage/libs/pari/convert_flint.cpython-314-x86_64-linux-musl.so +0 -0
  127. sage/libs/pari/convert_flint.pxd +14 -0
  128. sage/libs/pari/convert_flint.pyx +159 -0
  129. sage/libs/pari/convert_gmp.cpython-314-x86_64-linux-musl.so +0 -0
  130. sage/libs/pari/convert_gmp.pxd +14 -0
  131. sage/libs/pari/convert_gmp.pyx +210 -0
  132. sage/libs/pari/convert_sage.cpython-314-x86_64-linux-musl.so +0 -0
  133. sage/libs/pari/convert_sage.pxd +16 -0
  134. sage/libs/pari/convert_sage.pyx +588 -0
  135. sage/libs/pari/convert_sage_complex_double.cpython-314-x86_64-linux-musl.so +0 -0
  136. sage/libs/pari/convert_sage_complex_double.pxd +14 -0
  137. sage/libs/pari/convert_sage_complex_double.pyx +132 -0
  138. sage/libs/pari/convert_sage_matrix.cpython-314-x86_64-linux-musl.so +0 -0
  139. sage/libs/pari/convert_sage_matrix.pyx +106 -0
  140. sage/libs/pari/convert_sage_real_double.cpython-314-x86_64-linux-musl.so +0 -0
  141. sage/libs/pari/convert_sage_real_double.pxd +5 -0
  142. sage/libs/pari/convert_sage_real_double.pyx +14 -0
  143. sage/libs/pari/convert_sage_real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  144. sage/libs/pari/convert_sage_real_mpfr.pxd +7 -0
  145. sage/libs/pari/convert_sage_real_mpfr.pyx +108 -0
  146. sage/libs/pari/misc.cpython-314-x86_64-linux-musl.so +0 -0
  147. sage/libs/pari/misc.pxd +4 -0
  148. sage/libs/pari/misc.pyx +26 -0
  149. sage/libs/pari/tests.py +1848 -0
  150. sage/matrix/all__sagemath_pari.py +1 -0
  151. sage/matrix/matrix_integer_pari.cpython-314-x86_64-linux-musl.so +0 -0
  152. sage/matrix/matrix_integer_pari.pyx +187 -0
  153. sage/matrix/matrix_rational_pari.cpython-314-x86_64-linux-musl.so +0 -0
  154. sage/matrix/matrix_rational_pari.pyx +160 -0
  155. sage/quadratic_forms/all__sagemath_pari.py +10 -0
  156. sage/quadratic_forms/genera/all.py +9 -0
  157. sage/quadratic_forms/genera/genus.py +3506 -0
  158. sage/quadratic_forms/genera/normal_form.py +1519 -0
  159. sage/quadratic_forms/genera/spinor_genus.py +243 -0
  160. sage/quadratic_forms/qfsolve.py +255 -0
  161. sage/quadratic_forms/quadratic_form__automorphisms.py +427 -0
  162. sage/quadratic_forms/quadratic_form__genus.py +141 -0
  163. sage/quadratic_forms/quadratic_form__local_density_interfaces.py +140 -0
  164. sage/quadratic_forms/quadratic_form__local_normal_form.py +421 -0
  165. sage/quadratic_forms/quadratic_form__local_representation_conditions.py +889 -0
  166. sage/quadratic_forms/quadratic_form__mass.py +69 -0
  167. sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +663 -0
  168. sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py +373 -0
  169. sage/quadratic_forms/quadratic_form__siegel_product.py +198 -0
  170. sage/quadratic_forms/special_values.py +323 -0
  171. sage/rings/all__sagemath_pari.py +15 -0
  172. sage/rings/factorint_pari.cpython-314-x86_64-linux-musl.so +0 -0
  173. sage/rings/factorint_pari.pyx +80 -0
  174. sage/rings/finite_rings/all__sagemath_pari.py +1 -0
  175. sage/rings/finite_rings/element_givaro.cpython-314-x86_64-linux-musl.so +0 -0
  176. sage/rings/finite_rings/element_givaro.pxd +91 -0
  177. sage/rings/finite_rings/element_givaro.pyx +1769 -0
  178. sage/rings/finite_rings/element_ntl_gf2e.cpython-314-x86_64-linux-musl.so +0 -0
  179. sage/rings/finite_rings/element_ntl_gf2e.pxd +22 -0
  180. sage/rings/finite_rings/element_ntl_gf2e.pyx +1333 -0
  181. sage/rings/finite_rings/element_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
  182. sage/rings/finite_rings/element_pari_ffelt.pxd +13 -0
  183. sage/rings/finite_rings/element_pari_ffelt.pyx +1441 -0
  184. sage/rings/finite_rings/finite_field_givaro.py +612 -0
  185. sage/rings/finite_rings/finite_field_pari_ffelt.py +238 -0
  186. sage/rings/finite_rings/hom_finite_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
  187. sage/rings/finite_rings/hom_finite_field_givaro.pxd +28 -0
  188. sage/rings/finite_rings/hom_finite_field_givaro.pyx +280 -0
  189. sage/rings/finite_rings/residue_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
  190. sage/rings/finite_rings/residue_field_givaro.pyx +133 -0
  191. sage/rings/finite_rings/residue_field_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
  192. sage/rings/finite_rings/residue_field_pari_ffelt.pyx +128 -0
  193. sage/rings/function_field/all__sagemath_pari.py +1 -0
  194. sage/rings/function_field/valuation.py +1450 -0
  195. sage/rings/function_field/valuation_ring.py +212 -0
  196. sage/rings/number_field/all__sagemath_pari.py +14 -0
  197. sage/rings/number_field/totallyreal.cpython-314-x86_64-linux-musl.so +0 -0
  198. sage/rings/number_field/totallyreal.pyx +509 -0
  199. sage/rings/number_field/totallyreal_data.cpython-314-x86_64-linux-musl.so +0 -0
  200. sage/rings/number_field/totallyreal_data.pxd +26 -0
  201. sage/rings/number_field/totallyreal_data.pyx +928 -0
  202. sage/rings/number_field/totallyreal_phc.py +144 -0
  203. sage/rings/number_field/totallyreal_rel.py +1018 -0
  204. sage/rings/padics/CA_template.pxi +1847 -0
  205. sage/rings/padics/CA_template_header.pxi +50 -0
  206. sage/rings/padics/CR_template.pxi +2563 -0
  207. sage/rings/padics/CR_template_header.pxi +57 -0
  208. sage/rings/padics/FM_template.pxi +1575 -0
  209. sage/rings/padics/FM_template_header.pxi +50 -0
  210. sage/rings/padics/FP_template.pxi +2176 -0
  211. sage/rings/padics/FP_template_header.pxi +57 -0
  212. sage/rings/padics/all.py +3 -0
  213. sage/rings/padics/all__sagemath_pari.py +11 -0
  214. sage/rings/padics/common_conversion.cpython-314-x86_64-linux-musl.so +0 -0
  215. sage/rings/padics/common_conversion.pxd +15 -0
  216. sage/rings/padics/common_conversion.pyx +508 -0
  217. sage/rings/padics/eisenstein_extension_generic.py +232 -0
  218. sage/rings/padics/factory.py +3623 -0
  219. sage/rings/padics/generic_nodes.py +1615 -0
  220. sage/rings/padics/lattice_precision.py +2889 -0
  221. sage/rings/padics/morphism.cpython-314-x86_64-linux-musl.so +0 -0
  222. sage/rings/padics/morphism.pxd +11 -0
  223. sage/rings/padics/morphism.pyx +366 -0
  224. sage/rings/padics/padic_base_generic.py +467 -0
  225. sage/rings/padics/padic_base_leaves.py +1235 -0
  226. sage/rings/padics/padic_capped_absolute_element.cpython-314-x86_64-linux-musl.so +0 -0
  227. sage/rings/padics/padic_capped_absolute_element.pxd +15 -0
  228. sage/rings/padics/padic_capped_absolute_element.pyx +520 -0
  229. sage/rings/padics/padic_capped_relative_element.cpython-314-x86_64-linux-musl.so +0 -0
  230. sage/rings/padics/padic_capped_relative_element.pxd +14 -0
  231. sage/rings/padics/padic_capped_relative_element.pyx +614 -0
  232. sage/rings/padics/padic_extension_generic.py +990 -0
  233. sage/rings/padics/padic_extension_leaves.py +738 -0
  234. sage/rings/padics/padic_fixed_mod_element.cpython-314-x86_64-linux-musl.so +0 -0
  235. sage/rings/padics/padic_fixed_mod_element.pxd +15 -0
  236. sage/rings/padics/padic_fixed_mod_element.pyx +584 -0
  237. sage/rings/padics/padic_floating_point_element.cpython-314-x86_64-linux-musl.so +0 -0
  238. sage/rings/padics/padic_floating_point_element.pxd +14 -0
  239. sage/rings/padics/padic_floating_point_element.pyx +447 -0
  240. sage/rings/padics/padic_generic_element.cpython-314-x86_64-linux-musl.so +0 -0
  241. sage/rings/padics/padic_generic_element.pxd +48 -0
  242. sage/rings/padics/padic_generic_element.pyx +4642 -0
  243. sage/rings/padics/padic_lattice_element.py +1342 -0
  244. sage/rings/padics/padic_printing.cpython-314-x86_64-linux-musl.so +0 -0
  245. sage/rings/padics/padic_printing.pxd +38 -0
  246. sage/rings/padics/padic_printing.pyx +1505 -0
  247. sage/rings/padics/padic_relaxed_element.cpython-314-x86_64-linux-musl.so +0 -0
  248. sage/rings/padics/padic_relaxed_element.pxd +56 -0
  249. sage/rings/padics/padic_relaxed_element.pyx +18 -0
  250. sage/rings/padics/padic_relaxed_errors.cpython-314-x86_64-linux-musl.so +0 -0
  251. sage/rings/padics/padic_relaxed_errors.pxd +11 -0
  252. sage/rings/padics/padic_relaxed_errors.pyx +71 -0
  253. sage/rings/padics/padic_template_element.pxi +1212 -0
  254. sage/rings/padics/padic_template_element_header.pxi +50 -0
  255. sage/rings/padics/padic_valuation.py +1423 -0
  256. sage/rings/padics/pow_computer_flint.cpython-314-x86_64-linux-musl.so +0 -0
  257. sage/rings/padics/pow_computer_flint.pxd +38 -0
  258. sage/rings/padics/pow_computer_flint.pyx +641 -0
  259. sage/rings/padics/pow_computer_relative.cpython-314-x86_64-linux-musl.so +0 -0
  260. sage/rings/padics/pow_computer_relative.pxd +29 -0
  261. sage/rings/padics/pow_computer_relative.pyx +415 -0
  262. sage/rings/padics/qadic_flint_CA.cpython-314-x86_64-linux-musl.so +0 -0
  263. sage/rings/padics/qadic_flint_CA.pxd +21 -0
  264. sage/rings/padics/qadic_flint_CA.pyx +130 -0
  265. sage/rings/padics/qadic_flint_CR.cpython-314-x86_64-linux-musl.so +0 -0
  266. sage/rings/padics/qadic_flint_CR.pxd +13 -0
  267. sage/rings/padics/qadic_flint_CR.pyx +172 -0
  268. sage/rings/padics/qadic_flint_FM.cpython-314-x86_64-linux-musl.so +0 -0
  269. sage/rings/padics/qadic_flint_FM.pxd +14 -0
  270. sage/rings/padics/qadic_flint_FM.pyx +111 -0
  271. sage/rings/padics/qadic_flint_FP.cpython-314-x86_64-linux-musl.so +0 -0
  272. sage/rings/padics/qadic_flint_FP.pxd +12 -0
  273. sage/rings/padics/qadic_flint_FP.pyx +165 -0
  274. sage/rings/padics/relative_extension_leaves.py +429 -0
  275. sage/rings/padics/relative_ramified_CA.cpython-314-x86_64-linux-musl.so +0 -0
  276. sage/rings/padics/relative_ramified_CA.pxd +9 -0
  277. sage/rings/padics/relative_ramified_CA.pyx +33 -0
  278. sage/rings/padics/relative_ramified_CR.cpython-314-x86_64-linux-musl.so +0 -0
  279. sage/rings/padics/relative_ramified_CR.pxd +8 -0
  280. sage/rings/padics/relative_ramified_CR.pyx +33 -0
  281. sage/rings/padics/relative_ramified_FM.cpython-314-x86_64-linux-musl.so +0 -0
  282. sage/rings/padics/relative_ramified_FM.pxd +9 -0
  283. sage/rings/padics/relative_ramified_FM.pyx +33 -0
  284. sage/rings/padics/relative_ramified_FP.cpython-314-x86_64-linux-musl.so +0 -0
  285. sage/rings/padics/relative_ramified_FP.pxd +8 -0
  286. sage/rings/padics/relative_ramified_FP.pyx +33 -0
  287. sage/rings/padics/relaxed_template.pxi +4229 -0
  288. sage/rings/padics/relaxed_template_header.pxi +160 -0
  289. sage/rings/padics/tests.py +35 -0
  290. sage/rings/padics/tutorial.py +341 -0
  291. sage/rings/padics/unramified_extension_generic.py +335 -0
  292. sage/rings/padics/witt_vector.py +917 -0
  293. sage/rings/padics/witt_vector_ring.py +934 -0
  294. sage/rings/pari_ring.py +235 -0
  295. sage/rings/polynomial/all__sagemath_pari.py +1 -0
  296. sage/rings/polynomial/padics/all.py +1 -0
  297. sage/rings/polynomial/padics/polynomial_padic.py +360 -0
  298. sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +1324 -0
  299. sage/rings/polynomial/padics/polynomial_padic_flat.py +72 -0
  300. sage/rings/power_series_pari.cpython-314-x86_64-linux-musl.so +0 -0
  301. sage/rings/power_series_pari.pxd +6 -0
  302. sage/rings/power_series_pari.pyx +934 -0
  303. sage/rings/tate_algebra.py +1282 -0
  304. sage/rings/tate_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  305. sage/rings/tate_algebra_element.pxd +49 -0
  306. sage/rings/tate_algebra_element.pyx +3464 -0
  307. sage/rings/tate_algebra_ideal.cpython-314-x86_64-linux-musl.so +0 -0
  308. sage/rings/tate_algebra_ideal.pxd +7 -0
  309. sage/rings/tate_algebra_ideal.pyx +1307 -0
  310. sage/rings/valuation/all.py +7 -0
  311. sage/rings/valuation/augmented_valuation.py +2118 -0
  312. sage/rings/valuation/developing_valuation.py +362 -0
  313. sage/rings/valuation/gauss_valuation.py +812 -0
  314. sage/rings/valuation/inductive_valuation.py +1686 -0
  315. sage/rings/valuation/limit_valuation.py +946 -0
  316. sage/rings/valuation/mapped_valuation.py +656 -0
  317. sage/rings/valuation/scaled_valuation.py +322 -0
  318. sage/rings/valuation/trivial_valuation.py +382 -0
  319. sage/rings/valuation/valuation.py +1119 -0
  320. sage/rings/valuation/valuation_space.py +1615 -0
  321. sage/rings/valuation/valuations_catalog.py +10 -0
  322. sage/rings/valuation/value_group.py +697 -0
  323. sage/schemes/all__sagemath_pari.py +1 -0
  324. sage/schemes/elliptic_curves/all__sagemath_pari.py +1 -0
  325. sage/schemes/elliptic_curves/descent_two_isogeny_pari.cpython-314-x86_64-linux-musl.so +0 -0
  326. sage/schemes/elliptic_curves/descent_two_isogeny_pari.pyx +46 -0
  327. sage_wheels/bin/gp +0 -0
  328. sage_wheels/bin/gp2c +0 -0
  329. sage_wheels/bin/gp2c-run +57 -0
  330. sage_wheels/bin/xeus-gp +0 -0
  331. sage_wheels/share/gp2c/func.dsc +18414 -0
@@ -0,0 +1,2151 @@
1
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2
+ \\ Copyright (C) 2014 Denis Simon
3
+ \\
4
+ \\ Distributed under the terms of the GNU General Public License (GPL)
5
+ \\
6
+ \\ This code is distributed in the hope that it will be useful,
7
+ \\ but WITHOUT ANY WARRANTY; without even the implied warranty of
8
+ \\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9
+ \\ General Public License for more details.
10
+ \\
11
+ \\ The full text of the GPL is available at:
12
+ \\
13
+ \\ http://www.gnu.org/licenses/
14
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
15
+
16
+ /*
17
+ Auteur :
18
+ Denis SIMON -> simon@math.unicaen.fr
19
+ adresse du fichier :
20
+ www.math.unicaen.fr/~simon/ellQ.gp
21
+
22
+ *********************************************
23
+ * VERSION 13/01/2014 *
24
+ *********************************************
25
+
26
+
27
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
28
+ \\ English \\
29
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
30
+
31
+ This package provides functions to compute the rank of elliptic
32
+ curves over Q using 2-descent.
33
+ This package requires the other package qfsolve.gp downloadable at
34
+ www.math.unicaen.fr/~simon/qfsolve.gp
35
+ It also requires the package ellcommon.gp downloadable at
36
+ www.math.unicaen.fr/~simon/ellcommon.gp
37
+
38
+ They can be run under GP by the commands
39
+ gp > \r qfsolve.gp
40
+ gp > \r ellcommon.gp
41
+ gp > \r ellQ.gp
42
+
43
+ The main function is ellQ_ellrank(), which takes as an argument
44
+ any elliptic curve in the form [a1,a2,a3,a4,a6]
45
+ the result is a vector [r,s,v], where
46
+ r is a lower bound for the rank,
47
+ s is the rank of the 2-Selmer group
48
+ v is a set of independant points in E(Q)/2E(Q).
49
+
50
+ Example:
51
+
52
+ gp > ell = [1,2,3,4,5];
53
+ gp > ellQ_ellrank(ell)
54
+ %1 = [1, 1, [[1,2]]
55
+ In this example, the rank is exactly 1, and [1,2] has infinite order.
56
+
57
+ more details on the computations may be obtained by setting
58
+ DEBUGLEVEL_ell = 1 (the higher value, the more details)
59
+
60
+ Other functions:
61
+
62
+ ell2descent_complete, ell2descent_gen, ell2descent_viaisog,
63
+ ellhalf, ellredgen, ellsort, elltors2, elltorseven,
64
+ locallysoluble, ratpoint, redquartic,
65
+ bnfpSelmer, reducemodsquares
66
+
67
+ Quick information is obtained by typing
68
+ gp > ?NameOfTheFunction
69
+
70
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
71
+ \\ Comment utiliser ce programme ? \\
72
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
73
+
74
+ Ce module contient des fonctions pour calculer le rang des courbes
75
+ elliptiques sur Q, en utilisant la 2-descente.
76
+ langage : GP
77
+
78
+ Ce module utilise les modules complementaires suivants :
79
+ qfsolve.gp
80
+ ellcommon.gp
81
+ qui sont disponibles a l'adresse
82
+ www.math.unicaen.fr/~simon/qfsolve.gp
83
+ www.math.unicaen.fr/~simon/ellcommon.gp
84
+
85
+ Pour l'utiliser, lancer gp, puis taper
86
+ \r qfsolve.gp
87
+ \r ellcommon.gp
88
+ \r ellQ.gp
89
+
90
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
91
+ \\ Description des principales fonctions \\
92
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
93
+
94
+ Explications succintes :
95
+ La fonction ellQ_ellrank() accepte toutes les courbes sous la forme
96
+ [a1,a2,a3,a4,a6]
97
+ Les coefficients peuvent etre entiers ou non.
98
+ L'algorithme utilise est celui de la 2-descente.
99
+ La 2-torsion peut etre quelconque.
100
+ Il suffit de taper :
101
+
102
+ gp > ell = [a1,a2,a3,a4,a6];
103
+ gp > ellQ_ellrank(ell)
104
+
105
+ Retourne un vecteur [r,s,v] ou
106
+ r est le rang probable (c'est toujours une minoration du rang),
107
+ s est le 2-rang du groupe de Selmer,
108
+ v est une liste de points independants dans E(Q)/2E(Q).
109
+
110
+ Exemple :
111
+
112
+ gp > ell = [1,2,3,4,5];
113
+ gp > ellQ_ellrank(ell)
114
+ %1 = [1, 1, [[1,2]]
115
+ Ici, le rang est exactement 1, et le point [1,2] est d'ordre infini.
116
+
117
+ Courbes de la forme : k*y^2 = x^3+A*x^2+B*x+C
118
+ sans 2-torsion, A,B,C entiers.
119
+ gp > bnf = bnfinit(x^3+A*x^2+B*x+C);
120
+ gp > ell = ellinit([0,A,0,B,C]);
121
+ gp > rank = ell2descent_gen(ell,bnf,k);
122
+
123
+ Courbes avec #E[2](Q) >= 2 :
124
+ ell doit etre sous la forme
125
+ y^2 = x^3 + A*x^2 + B*x
126
+ avec A et B entiers.
127
+ gp > ell = [0,A,0,B,0]
128
+ gp > ell2descent_viaisog(ell)
129
+ = algorithme de la 2-descente par isogenies
130
+ Attention A et B doivent etre entiers
131
+
132
+ Courbes avec #E[2](Q) = 4 : y^2 = (x-e1)*(x-e2)*(x-e3)
133
+ gp > ell2descent_complete(e1,e2,e3)
134
+ = algorithme de la 2-descente complete
135
+ Attention : les ei doivent etre entiers.
136
+
137
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
138
+ \\ Autres fonctions utiles \\
139
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
140
+
141
+ elltors2(E) : determine le groupe E[2](Q)
142
+ elltorseven(E) : determine le groupe E[2^*](Q)
143
+ ellhalf(E,P) : liste les points Q tels que 2Q = P
144
+ ellredgen(E,v) : reduction des points de v sur E
145
+
146
+ locallysoluble(pol): teste si y^2=pol(x) est ELS
147
+ ratpoint(pol,lim): cherche un point sur y^2=pol(x)
148
+ redquartic(pol): reduction de la quartique pol
149
+
150
+
151
+ Aide en ligne :
152
+ ?NomDeLaFonction
153
+
154
+
155
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
156
+ \\ Affichage des calculs \\
157
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
158
+
159
+ On peut avoir plus ou moins de details de calculs avec
160
+ DEBUGLEVEL_ell = 0;
161
+ DEBUGLEVEL_ell = 1; 2; 3;...
162
+
163
+ */
164
+
165
+ \\
166
+ \\ Usual global variables
167
+ \\
168
+
169
+ global(DEBUGLEVEL_ell, LIM1, LIM3, LIMTRIV, ELLREDGENFLAG, COMPLETE):small;
170
+
171
+ DEBUGLEVEL_ell = 0; \\ From 0 to 5: choose a higher value to have
172
+ \\ more details printed.
173
+ LIM1 = 5; \\ Limit for the search of trivial points on quartics
174
+ LIM3 = 50; \\ Limit for the search of points on ELS quartics
175
+ LIMTRIV = 3; \\ Limit for the search of trivial points on the elliptic curve
176
+ ELLREDGENFLAG = 1; \\ to reduce the generators at the end
177
+ COMPLETE = 0; \\ Use Complete 2-descent when full 2-torsion,
178
+ \\ otherwise 2-descent via isogenies.
179
+
180
+ \\
181
+ \\ Technical global variables
182
+ \\
183
+
184
+ global(MAXPROB, LIMBIGPRIME):small;
185
+
186
+ MAXPROB = 20;
187
+ LIMBIGPRIME = 30; \\ for primes larger than this limit: use a probabilistic test
188
+ \\ LIMBIGPRIME = 0 means: only deterministic tests
189
+
190
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
191
+ \\ SCRIPT \\
192
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
193
+
194
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
195
+ \\ MANIPULATION OF GLOBAL VARIABLES \\
196
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
197
+
198
+ {default_ellQ(
199
+ DEBUGLEVEL_ell_val:small = 0,
200
+ LIM1_val:small = 5,
201
+ LIM3_val:small = 50,
202
+ LIMTRIV_val:small = 3,
203
+ ELLREDGENFLAG_val:small = 1,
204
+ COMPLETE_val:small = 0,
205
+ MAXPROB_val:small = 20,
206
+ LIMBIGPRIME_val:small = 30
207
+ ) =
208
+
209
+ DEBUGLEVEL_ell = DEBUGLEVEL_ell_val;
210
+ print(" DEBUGLEVEL_ell = ",DEBUGLEVEL_ell);
211
+
212
+ LIM1 = LIM1_val;
213
+ print(" LIM1 = ",LIM1);
214
+
215
+ LIM3 = LIM3_val;
216
+ print(" LIM3 = ",LIM3);
217
+
218
+ LIMTRIV = LIMTRIV_val;
219
+ print(" LIMTRIV = ",LIMTRIV);
220
+
221
+ ELLREDGENFLAG = ELLREDGENFLAG_val;
222
+ print(" ELLREDGENFLAG = ",ELLREDGENFLAG);
223
+
224
+ COMPLETE = COMPLETE_val;
225
+ print(" COMPLETE = ",COMPLETE);
226
+
227
+ MAXPROB = MAXPROB_val;
228
+ print(" MAXPROB = ",MAXPROB);
229
+
230
+ LIMBIGPRIME = LIMBIGPRIME_val;
231
+ print(" LIMBIGPRIME = ",LIMBIGPRIME);
232
+ }
233
+
234
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
235
+ \\ FUNCTIONS FOR POLYNOMIALS \\
236
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
237
+
238
+ {ratpoint( pol, lim:small = 1, singlepoint = 1, infinity = 1) =
239
+ \\ Search for points on y^2=pol(x).
240
+ \\ The coeff of pol must be integers.
241
+ \\ If singlepoint >= 1, stop after a first point is found.
242
+
243
+ my(listpoints,point1,odd,deg4,pol16,tab16,pol9,tab9,pol5,tab5,pol0,vecz,vecx,lead,zz,xx,evpol,iz,factpol,deg,vz,epsmax);
244
+
245
+ if( DEBUGLEVEL_ell >= 4,
246
+ print(" Starting ratpoint with pol = ",pol);
247
+ print(" lim = ",lim););
248
+
249
+ if( !singlepoint, listpoints = []);
250
+ point1 = [];
251
+
252
+ \\
253
+ \\ trivial solutions
254
+ \\
255
+
256
+ \\ the leading coeff is a square
257
+ if( infinity && issquare(pollead(pol)),
258
+ point1 = [ 1, sqrtrat(pollead(pol)), 0];
259
+ if( DEBUGLEVEL_ell >= 3, print(" trivial solution: lead(pol) is a square"));
260
+ if( singlepoint,
261
+ if( DEBUGLEVEL_ell >= 4, print(" end of ratpoint"));
262
+ return(point1));
263
+ listpoints = concat(listpoints,[point1]));
264
+
265
+ \\ the constant coeff is a square
266
+ if( issquare(polcoeff(pol,0)),
267
+ point1 = [ 0, sqrtrat(polcoeff(pol,0)) ];
268
+ if( DEBUGLEVEL_ell >= 3, print(" trivial solution: pol(0) is a square"));
269
+ if( singlepoint,
270
+ if( DEBUGLEVEL_ell >= 4, print(" end of ratpoint"));
271
+ return(point1));
272
+ listpoints = concat(listpoints,[point1]));
273
+
274
+ \\ roots of pol ?
275
+ factpol = nfroots(,pol);
276
+ if( #factpol,
277
+ if( DEBUGLEVEL_ell >= 3, print(" trivial solution: roots of pol",factpol));
278
+ if( singlepoint,
279
+ if( DEBUGLEVEL_ell >= 4, print(" end of ratpoint"));
280
+ return([factpol[1],0]));
281
+ listpoints = concat(listpoints,vector(#factpol,i,[factpol[i],0]))
282
+ );
283
+
284
+ \\
285
+ \\ Sieve
286
+ \\
287
+
288
+ \\ initialisation of the sieve modulo 16, 9 and 5
289
+ \\ used only with even degree when lim is large
290
+
291
+ deg = poldegree(pol);
292
+ odd = deg%2;
293
+ deg4 = ( !odd && lim > 20);
294
+ if( deg4,
295
+
296
+ pol16 = (Vec(pol)*Mod(1,16))~;
297
+ tab16 = matrix(16,16);
298
+ for(xx = 0, 16-1,
299
+ for(zz = 0, 16-1,
300
+ tab16[xx+1,zz+1] = !issquare(vector(deg+1,i,xx^(deg+1-i)*zz^(i-1))*pol16)));
301
+ pol9 = (Vec(pol)~)*Mod(1,9);
302
+ tab9 = matrix(9,9);
303
+ for(xx = 0, 9-1,
304
+ for(zz = 0, 9-1,
305
+ tab9[xx+1,zz+1] = !issquare(vector(deg+1,i,xx^(deg+1-i)*zz^(i-1))*pol9)));
306
+ pol5 = (Vec(pol)~)*Mod(1,5);
307
+ tab5 = matrix(5,5);
308
+ for(xx = 0, 5-1,
309
+ for(zz = 0, 5-1,
310
+ tab5[xx+1,zz+1] = !issquare(vector(deg+1,i,xx^(deg+1-i)*zz^(i-1))*pol5)));
311
+ );
312
+
313
+ \\ if the degree is odd, search only for square denominators
314
+ if( odd,
315
+ vecz = vector(lim,i,i^2);
316
+ ,
317
+ \\ if the degree is even, the leading coeff must be
318
+ \\ a square modulo zz.
319
+ lead = pollead(pol);
320
+ vecz = vector(lim);
321
+ zz = 0;
322
+ for( i = 1, lim,
323
+ zz++; while( !issquare(Mod(lead,zz)),zz++); vecz[i] = zz
324
+ ));
325
+
326
+ \\ the constant coeff must be a square modulo xx.
327
+ pol0 = polcoeff(pol,0);
328
+ vecx = vector(lim);
329
+ xx = 0;
330
+ for( i = 1, lim,
331
+ xx++; while( !issquare(Mod(pol0,xx)),xx++); vecx[i] = xx);
332
+
333
+ if( DEBUGLEVEL_ell >= 4, print(" xmax = ",vecx[lim]));
334
+ if( DEBUGLEVEL_ell >= 4, print(" zmax = ",vecz[lim]));
335
+
336
+ if( DEBUGLEVEL_ell >= 5, print(" vecx = ",vecx));
337
+ if( DEBUGLEVEL_ell >= 5, print(" vecz = ",vecz));
338
+
339
+ if( deg4,
340
+ vz = vector(lim,i,Pol(
341
+ vector(deg+1,j,polcoeff(pol,deg+1-j)*vecz[i]^(j-1))));
342
+ );
343
+
344
+ \\ if deg is even and pol has no odd terms,
345
+ \\ it is enough to consider xx > 0
346
+ if( !odd && subst(pol,x,-x)==pol, epsmax = 1, epsmax = 2);
347
+
348
+ \\ loop over x = xx/zz
349
+ \\ the loop on [xx,zz] is done diagonally
350
+ \\ to start with the smallest values of both xx and zz.
351
+ for( somme = 2, 2*lim,
352
+ for( ix = max(1,somme-lim), min(lim,somme-1),
353
+ xx = vecx[ix]; iz = somme-ix; zz = vecz[iz];
354
+ if( gcd(zz,xx) != 1, next);
355
+ for( eps = 1, epsmax,
356
+ \\ when eps = 1, xx > 0; when eps = 2, xx < 0.
357
+ if( deg4,
358
+ if( tab16[xx%16+1,zz%16+1], xx=-xx;next);
359
+ if( tab9[xx%9+1,zz%9+1], xx=-xx;next);
360
+ if( tab5[xx%5+1,zz%5+1], xx=-xx;next);
361
+ evpol = subst(vz[iz],'x,xx)
362
+ ,
363
+ evpol = subst(pol,variable(pol),xx/zz)
364
+ );
365
+ if( issquare(evpol),
366
+ point1 = [xx/zz,sqrtrat(subst(pol,variable(pol),xx/zz))];
367
+ if( DEBUGLEVEL_ell >= 4, print(" point found by ratpoint = ",point1));
368
+ if( singlepoint, break(3));
369
+ listpoints = concat(listpoints,[point1])
370
+ );
371
+ xx = -xx
372
+ )));
373
+
374
+ if( point1 != [],
375
+ if( DEBUGLEVEL_ell >= 3, print(" point found by ratpoint = ",point1));
376
+ if( DEBUGLEVEL_ell >= 4, print(" end of ratpoint "));
377
+ if( singlepoint, return(point1), return(listpoints))
378
+ );
379
+
380
+ return([]);
381
+ }
382
+ {redquartic(pol) =
383
+ \\ reduction of the quartic polynomial.
384
+ \\ (also works with other degrees)
385
+ my(local_prec,prec0,d,disc2,test,r,normderiv,disc2v,q,M);
386
+
387
+ if( DEBUGLEVEL_ell >= 4, print(" starting redquartic"));
388
+ if( DEBUGLEVEL_ell >= 3, print(" reduction of the quartic ",pol));
389
+
390
+ \\ choice of the real precision used in the computation
391
+ local_prec = prec0 = default(realprecision);
392
+ d = poldegree(pol);
393
+ disc2 = poldisc(pol)^2;
394
+ test = 0;
395
+ while( test == 0,
396
+ if( DEBUGLEVEL_ell >= 4, print(" precision = ",local_prec));
397
+ r = polroots(pol);
398
+ normderiv = vector( d, i, norm(subst(pol',variable(pol),r[i])));
399
+ disc2v = prod( i = 1, d, normderiv[i]) * pollead(pol)^(2*d-4);
400
+ test = abs(disc2v-disc2) < 10^(-local_prec\2);
401
+ if( !test, default(realprecision, local_prec *= 2))
402
+ );
403
+
404
+ \\ former choice of the quadratic form
405
+ \\ q = Vec(sum( i = 1, d, norm(x-r[i])));
406
+ \\ Now, uses the quadratic form normalized as in Cremona-Stoll
407
+ q = Vec(sum( i = 1, d, norm('x-r[i]) / normderiv[i]^(1/(d-2))));
408
+ M = qfbreduce([q[1],q[2]/2;q[2]/2,q[3]]);
409
+ pol = subst(pol,variable(pol),Pol(M[1,])/Pol(M[2,]))*Pol(M[2,])^poldegree(pol);
410
+
411
+ if( local_prec != prec0, default(realprecision,prec0));
412
+
413
+ if( DEBUGLEVEL_ell >= 3, print(" reduced quartic = ",pol));
414
+ if( DEBUGLEVEL_ell >= 4, print(" end of redquartic"));
415
+
416
+ return([pol,M]);
417
+ }
418
+ {listratpoint( pol, redflag = 0) =
419
+ my(list,i,K,ff,C,p,M,U,newpol,factpol,ll,listf,rr);
420
+
421
+ if( DEBUGLEVEL_ell >= 5, print(" Starting listratpoint with ",pol));
422
+ list = [[pol,matid(2),1,1]];
423
+ i = 1;
424
+ while( i <= #list,
425
+
426
+ pol = list[i][1];
427
+
428
+ K = abs(content(pol));
429
+ if( K != 1,
430
+ pol = (list[i][1] /= K);
431
+ list[i][3] *= K
432
+ );
433
+
434
+ K = list[i][3];
435
+ if( K == 1, i++; next);
436
+
437
+ ff = factor(K);
438
+ if( vecmax(ff[,2]) > 1,
439
+ ff[,2] \= 2;
440
+ C = factorback(ff);
441
+ list[i][4] *= C;
442
+ K = ( list[i][3] /= C^2);
443
+ if( K == 1, i++; next);
444
+ ff = factor(K);
445
+ );
446
+
447
+ p = ff[1,1];
448
+ M = list[i][2];
449
+ C = list[i][4];
450
+
451
+ if( pollead(pol)%p == 0,
452
+ U = M*[1,0;0,p];
453
+ if( content(U) == 1,
454
+ newpol = subst(pol,'x,'x/p)*p^(poldegree(pol)-1);
455
+ list = concat(list, [[newpol,U,K/p,C*p]])
456
+ )
457
+ );
458
+
459
+ factpol = centerlift(polrootsmod(pol,p));
460
+ for( j = 1, #factpol,
461
+ U = M*[p,factpol[j];0,1];
462
+ if( content(U) == 1,
463
+ newpol = subst(pol,'x,p*'x+factpol[j])/p;
464
+ list = concat(list, [[newpol,U,K/p,C*p]])
465
+ ));
466
+
467
+ i++;
468
+ );
469
+
470
+ ll = sum( i = 1, #list, list[i][3] == 1);
471
+ listf = vector(ll);
472
+ i = 1;
473
+ for( j = 1, #list,
474
+ if( list[j][3] == 1,
475
+ listf[i] = list[j]; i++));
476
+
477
+ if( redflag,
478
+ for( i = 1, #listf,
479
+ rr = redquartic(listf[i][1]);
480
+ listf[i][1] = rr[1];
481
+ listf[i][2] = listf[i][2]*rr[2]
482
+ )
483
+ );
484
+
485
+ if( DEBUGLEVEL_ell >= 5, print(" Output of listratpoint = ",listf));
486
+
487
+ return(listf);
488
+ }
489
+ {ratpoint2( pol, lim:small = 1, singlepoint = 1, redflag = 0) =
490
+ my(listpoints,list,rr,y2,aux);
491
+
492
+ listpoints = [];
493
+ list = listratpoint(pol,redflag);
494
+ for( i = 1, #list,
495
+ rr = ratpoint(list[i][1],lim,singlepoint);
496
+ if( singlepoint && #rr, rr=[rr]);
497
+ for( j = 1, #rr,
498
+ y2 = rr[j][2]*list[i][4];
499
+ if( #rr[j] == 2,
500
+ aux = [rr[j][1],1]~
501
+ , aux = [rr[j][1],rr[j][3]]~
502
+ );
503
+ aux = list[i][2] * aux;
504
+ if( aux[2] == 0,
505
+ rr[j] = [aux[1],y2,0]
506
+ , rr[j] = [aux[1]/aux[2],y2/aux[2]^(poldegree(pol)\2)]
507
+ );
508
+ );
509
+ if( singlepoint && #rr, return(rr[1]));
510
+ listpoints = concat(listpoints,rr);
511
+ );
512
+ listpoints = vecsort(listpoints,,2);
513
+ return(listpoints);
514
+ }
515
+ {polrealrootsisolate(pol) =
516
+ \\ pol is a squarefree polynomial in Z[x].
517
+ \\ Returns a list of vectors [a,b] with a and b rationals
518
+ \\ such that the intervals ]a,b] are disjoint and contain
519
+ \\ all the real roots of pol, and exactly one in each interval.
520
+ my(st,a,res,ind,b,c,stab,stac);
521
+
522
+ if( DEBUGLEVEL_ell >= 5, print(" starting polrealrootsisolate with pol = ",pol));
523
+ st = polsturm(pol);
524
+ if( !st, return([]));
525
+ a = 1;
526
+ while( polsturm(pol,-a,a) < st, a <<= 1);
527
+ res = [[-a,a,st]];
528
+ ind = 1;
529
+ while( #res < st,
530
+ while( res[ind][3] == 1, ind++);
531
+ a = res[ind][1]; b = res[ind][2]; stab = res[ind][3];
532
+ c = (a+b)/2;
533
+ stac = polsturm(pol,a,c);
534
+ if( stac == 0, res[ind][1] = c; next);
535
+ if( stac == stab, res[ind][2] = c; next);
536
+ res[ind] = [a,c,stac];
537
+ res = concat(res,[[c,b,stab-stac]]);
538
+ );
539
+ res = vector(st,i,[res[i][1],res[i][2]]);
540
+ res = vecsort(res,1);
541
+ if( DEBUGLEVEL_ell >= 5, print(" end of polrealrootsisolate with res = ",res));
542
+ return(res);
543
+ }
544
+ {polrealrootsimprove(pol,v) =
545
+ \\ pol is a polynomial and v is a vector v=[a,b]
546
+ \\ such that pol contains exactly one root in the interval ]a,b].
547
+ \\ Returns another interval with the same property, but with half length.
548
+ \\ (dichotomy)
549
+ my(c,v2,vc);
550
+
551
+ c = (v[1]+v[2])/2;
552
+ v2 = subst(pol,variable(pol),v[2]);
553
+ if( v2 == 0, return([c,v[2]]));
554
+ vc = subst(pol,variable(pol),c);
555
+ if( sign(v2)*sign(vc) >= 0, v[2] = c, v[1] = c);
556
+ return(v);
557
+ }
558
+ {polrootsmodpn(pol,p) =
559
+ \\ Compute a list v. Each element of v is of the form
560
+ \\ [a,b], with maximal b <= valuation(poldisc(pol),p)
561
+ \\ and a is a root of pol modulo p^b.
562
+ my(vd,rac,i,pol2,r,newrac);
563
+
564
+ if( DEBUGLEVEL_ell >= 5, print(" starting polrootsmodpn ",p,":",pol));
565
+
566
+ vd = valuation(poldisc(pol),p);
567
+ rac = [[0,0]];
568
+ i = 1;
569
+ while (i <= #rac,
570
+ \\ if( rac[i][2] > vd, i++; next);
571
+ if( rac[i][2] >= vd, i++; next);
572
+ pol2 = subst(pol,'x,rac[i][1]+'x*p^rac[i][2]);
573
+ pol2 /= content(pol2);
574
+ r = lift(polrootsmod(pol2,p));
575
+ if( #r == 0, i++; next);
576
+ newrac = vector(#r,j,[rac[i][1] + p^rac[i][2]*r[j],rac[i][2]+1]);
577
+ rac = concat(rac, vector(#r-1,j,newrac[j+1]));
578
+ rac[i] = newrac[1];
579
+ );
580
+ if( DEBUGLEVEL_ell >= 5, print(" end of polrootsmodpn ",rac));
581
+ return(rac);
582
+ }
583
+
584
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
585
+ \\ FUNCTIONS FOR LOCAL COMPUTATIONS \\
586
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
587
+
588
+ {ppinit( nf, p) =
589
+ \\ a little more structure than idealprimedec()
590
+ my(pdec,pp);
591
+
592
+ pdec = idealprimedec(nf,p);
593
+ pp = vector(#pdec,i,
594
+ [ pdec[i]
595
+ , nfbasistoalg(nf,pdec[i][2])
596
+ , if( p == 2, idealstar(nf,idealpow(nf,pdec[i],1+2*pdec[i].e)),0)
597
+ , nfmodprinit(nf,pdec[i])
598
+ ]);
599
+ return(pp);
600
+ }
601
+ {nfpsquareodd( nf, a, pr) =
602
+ \\ pr is a prime ideal of nf as output by nfmodprinit
603
+ \\ a is an element of nf.
604
+ \\ Returns 1 if a is a square in the p-adics, 0 otherwise
605
+ \\ works only for p odd.
606
+ my(p,v,ap,den,norme);
607
+
608
+ if( DEBUGLEVEL_ell >= 5, print(" starting nfpsquareodd(",a,",",pr));
609
+ if( a == 0,
610
+ if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
611
+ return(1));
612
+
613
+ p = pr[3];
614
+ v = idealval(nf,lift(a),p);
615
+ if( v%2,
616
+ if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
617
+ return(0));
618
+ ap = nfalgtobasis(nf,a/nfbasistoalg(nf,p[2])^v);
619
+ den = valuation(denominator(content(ap)),p.p);
620
+ if( den,
621
+ den += den%2;
622
+ ap = p.p^den*nfeltmul(nf,ap,nfeltpow(nf,p[2],-den*p.e))
623
+ );
624
+
625
+ norme = (p.p^p.f-1)/2;
626
+ ap = nfeltpowmodpr(nf,ap,norme,pr);
627
+ ap[1] -= 1;
628
+ if( ap == 0,
629
+ if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
630
+ return(1));
631
+ if( idealval(nf,ap,p) > 0,
632
+ if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
633
+ return(1));
634
+ if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
635
+ return(0);
636
+ }
637
+ {psquare( a, p) =
638
+ \\ a is an integer.
639
+ \\ p is a prime integer.
640
+ \\ Returns 1 if a is a square in the p-adics, 0 otherwise.
641
+ my(v,ap);
642
+
643
+ if( DEBUGLEVEL_ell >= 5, print(" starting psquare ",[a,p]));
644
+
645
+ if( a == 0,
646
+ if( DEBUGLEVEL_ell >= 5, print(" end of psquare 1"));
647
+ return(1));
648
+
649
+ v = valuation(a,p);
650
+ if( v%2,
651
+ if( DEBUGLEVEL_ell >= 5, print(" end of psquare 0"));
652
+ return(0));
653
+ if( p == 2,
654
+ ap = (a>>v)%8-1,
655
+ ap = kronecker(a/p^v,p)-1
656
+ );
657
+ if( DEBUGLEVEL_ell >= 5, print(" end of psquare ", !ap));
658
+ return(!ap);
659
+ }
660
+ {lemma6(pol, p, nu, xx) =
661
+ \\ technical lemma for local solubility of quartics
662
+ \\ Only for p <> 2.
663
+ my(gx,gpx,lambda,mu);
664
+
665
+ gx = subst( pol, variable(pol), xx);
666
+ if( psquare(gx,p), return(1));
667
+ gpx = subst( pol', variable(pol), xx);
668
+ lambda = valuation(gx,p); mu = valuation(gpx,p);
669
+
670
+ if( gpx != 0 && lambda > 2*mu, return(1));
671
+ \\ if( (lambda >= mu+nu) && (nu > mu), return(1));
672
+ if( (lambda >= 2*nu) && (mu >= nu), return(0));
673
+ return(-1);
674
+ }
675
+ {lemma7( pol, nu, xx) =
676
+ \\ technical lemma for local solubility of quartics
677
+ \\ at p = 2.
678
+ my(gx,gpx,lambda,mu,q);
679
+
680
+ gx = subst( pol, variable(pol), xx);
681
+ if( psquare(gx,2), return(1));
682
+ gpx = subst( pol', variable(pol), xx);
683
+ lambda = valuation(gx,2); mu = valuation(gpx,2);
684
+ if( gpx != 0 && lambda > 2*mu, return(1));
685
+ if( nu > mu,
686
+ if( lambda%2, return(-1));
687
+ q = mu+nu-lambda;
688
+ if( q == 1, return(1));
689
+ if( q == 2 && (gx>>lambda)%4 == 1, return(1));
690
+ return(-1));
691
+ q = lambda-2*nu;
692
+ if( q >= 0, return(0));
693
+ if( q == -2 && (gx>>lambda)%4 == 1, return(0));
694
+ return(-1);
695
+ }
696
+ {zp_soluble(pol, p, nu, pnu, x0, pnup) =
697
+ my(result,pol2,fact,x1);
698
+
699
+ if( DEBUGLEVEL_ell >= 5, print(" starting zp_soluble ",[pol,p,x0,nu]));
700
+ if( p == 2,
701
+ result = lemma7(pol,nu,x0),
702
+ result = lemma6(pol,p,nu,x0));
703
+ if( result == +1,
704
+ if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble 1 lemma"));
705
+ return(1));
706
+ if( result == -1,
707
+ if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble 0 lemma"));
708
+ return(0));
709
+ pnup = pnu*p;
710
+ nu++;
711
+ if( p < LIMBIGPRIME || !LIMBIGPRIME,
712
+ for( i = 0, p-1,
713
+ if( zp_soluble(pol,p,nu,pnup,x0+pnu*i),
714
+ if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble"));
715
+ return(1)))
716
+ ,
717
+ pol2 = subst(pol,variable(pol),x0+pnu*variable(pol));
718
+ pol2 /= content(pol2);
719
+ pol2 = pol2*Mod(1,p);
720
+ if( !poldegree(pol2), return(0));
721
+ fact = factormod(pol2,p)[,1];
722
+ for( i = 1, #fact,
723
+ x1 = -centerlift(polcoeff(fact[i],0));
724
+ if( zp_soluble(pol,p,nu,pnup,x0+pnu*x1),
725
+ if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble"));
726
+ return(1)));
727
+ for( i = 1, MAXPROB,
728
+ x1 = random(p);
729
+ if( zp_soluble(pol,p,nu,pnup,x0+pnu*x1),
730
+ if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble"));
731
+ return(1)))
732
+ );
733
+ if( DEBUGLEVEL_ell >= 2,
734
+ if( p >= LIMBIGPRIME,
735
+ print(" ******* probabilistic test at p = ",p,"*******")));
736
+ if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble"));
737
+ return(0);
738
+ }
739
+ {qp_soluble(pol, p) =
740
+ if( DEBUGLEVEL_ell >= 5,
741
+ print(" starting qp_soluble ",p);
742
+ print(" pol = ",pol));
743
+ if( psquare(pollead(pol),p),
744
+ if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 1"));
745
+ return(1));
746
+ if( psquare(polcoeff(pol,0),p),
747
+ if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 1"));
748
+ return(1));
749
+ if( zp_soluble(pol,p,0,1,0),
750
+ if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 1"));
751
+ return(1));
752
+ if( zp_soluble(polrecip(pol),p,1,p,0),
753
+ if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 1"));
754
+ return(1));
755
+ if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 0"));
756
+ return(0);
757
+ }
758
+ {locallysoluble(pol) =
759
+ \\ Determines if y^2 = pol(x,z) is everywhere locally soluble
760
+ my(c,disc0,plist,p,vc);
761
+
762
+ if( DEBUGLEVEL_ell >= 4, print(" starting locallysoluble: ",pol));
763
+
764
+ \\ real place
765
+ if( !(poldegree(pol)%2) && sign(pollead(pol)) < 0
766
+ && sign(polcoeff(pol,0)) < 0 && polsturm(pol) == 0,
767
+ if( DEBUGLEVEL_ell >= 3, print(" not ELS at infinity"));
768
+ if( DEBUGLEVEL_ell >= 4, print(" end of locallysoluble"));
769
+ return(0));
770
+
771
+ \\
772
+ \\ finite places
773
+ \\
774
+ pol *= denominator(content(pol))^2;
775
+ c = content(pol);
776
+
777
+ disc0 = poldisc(pol);
778
+ plist = factor (abs(2*disc0));
779
+ if( DEBUGLEVEL_ell >= 4, print(" list of bad primes = ",plist));
780
+ for( i = 1, #plist[,1],
781
+ p = plist[i,1];
782
+ if( DEBUGLEVEL_ell >= 4, print(" p = ",p));
783
+ vc = valuation(c,p);
784
+ if( vc >= 2,
785
+ pol /= p^(2*(vc\2));
786
+ plist[i,2] -= 2*(vc\2)*(2*poldegree(pol)-2)
787
+ );
788
+ if( poldegree(pol) == 4 && p != 2 && plist[i,2] < 2, next);
789
+ if( !qp_soluble(pol,p),
790
+ if( DEBUGLEVEL_ell >= 3, print(" not ELS at ",p));
791
+ if( DEBUGLEVEL_ell >= 4, print(" end of locallysoluble"));
792
+ return(0)));
793
+
794
+ if( DEBUGLEVEL_ell >= 2, print(" quartic ELS: Y^2 = ",pol));
795
+ if( DEBUGLEVEL_ell >= 4, print(" end of locallysoluble"));
796
+ return(1);
797
+ }
798
+ {LS2localimage(nf,gen,pp) =
799
+ my(p,LS2image,ph,ival,delta);
800
+
801
+ if( DEBUGLEVEL_ell >= 4, print(" starting LS2localimage"));
802
+
803
+ p = pp[1][1].p;
804
+ LS2image = matrix( if( p == 2, sum(i=1,#pp,1+#pp[i][3].cyc), 2*#pp), #gen);
805
+
806
+ for( j = 1, #gen,
807
+ ph = [];
808
+ for( i = 1, #pp,
809
+ ival = idealval(nf,gen[j],pp[i][1]);
810
+ ph = concat(ph,[ival]);
811
+ delta = gen[j]/pp[i][2]^ival;
812
+ if( p == 2,
813
+ ph = concat(ph,ideallog(nf,delta,pp[i][3])~);
814
+ , ph = concat(ph,[1-nfpsquareodd(nf,delta,pp[i][4])]);
815
+ )
816
+ );
817
+ LS2image[,j] = ph~
818
+ );
819
+ LS2image *= Mod(1,2);
820
+
821
+ if( DEBUGLEVEL_ell >= 4, print(" LS2image = ",lift(LS2image)));
822
+ if( DEBUGLEVEL_ell >= 4, print(" end of LS2localimage"));
823
+ return(LS2image);
824
+ }
825
+
826
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
827
+ \\ GENERIC FUNCTIONS FOR ELLIPTIC CURVES \\
828
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
829
+
830
+ {ellhalf(ell,P)=
831
+ \\ returns all the points Q on ell such that 2Q = P.
832
+ my(pol2,ratroots,half,x2,y2,P2);
833
+
834
+ if(#ell < 13, ell=ellinit(ell));
835
+
836
+ pol2 = Pol([4,ell.b2,2*ell.b4,ell.b6]); \\ 2-division polynomial
837
+
838
+ if( P == [0],
839
+ ratroots = nfroots(,pol2);
840
+ half = vector(#ratroots,i,[ratroots[i],-(ell.a1*ratroots[i]+ell.a3)/2]);
841
+ half = concat( [[0]], half);
842
+ return(half)
843
+ );
844
+
845
+ x2 = Pol([1,0,-ell.b4,-2*ell.b6,-ell.b8]); \\ x(2P) = x2/pol2
846
+
847
+ half = [];
848
+ ratroots = nfroots(,x2-P[1]*pol2);
849
+ if( #ratroots == 0, return(half));
850
+ for( i = 1, #ratroots,
851
+ y2 = ellordinate(ell,ratroots[i]);
852
+ for( j = 1, #y2,
853
+ P2 = [ratroots[i],y2[j]];
854
+ if( ellpow(ell,P2,2) == P, half = concat(half,[P2]))
855
+ )
856
+ );
857
+
858
+ return(half);
859
+ }
860
+ {elltors2(ell)=
861
+ \\ Compute the 2-torsion subgroup of the elliptic curve ell.
862
+ my(tors2);
863
+
864
+ if( DEBUGLEVEL_ell >= 3, print(" computing the 2-torsion"));
865
+
866
+ tors2 = ellhalf(ell,[0]);
867
+ if( #tors2 == 1,
868
+ tors2 = [1, [], []],
869
+ if( #tors2 == 2,
870
+ tors2 = [2, [2], [tors2[2]]]
871
+ , tors2 = [4, [2,2], [tors2[2],tors2[3]]]
872
+ ));
873
+ if( DEBUGLEVEL_ell >= 3, print(" E[2] = ",tors2));
874
+ return(tors2);
875
+ }
876
+ {elltorseven(ell)=
877
+ \\ Compute the 2-Sylow subgroup of the torsion of the elliptic curve ell.
878
+ my(torseven,P2);
879
+
880
+ if( DEBUGLEVEL_ell >= 4, print(" computing the 2^n-torsion"));
881
+ if(#ell < 13, ell=ellinit(ell));
882
+ torseven = elltors2(ell);
883
+
884
+ while( torseven[1] != 1,
885
+ P2 = ellhalf(ell,torseven[3][1]);
886
+ if( #P2 > 0,
887
+ torseven[1] *= 2;
888
+ torseven[2][1] *= 2;
889
+ torseven[3][1] = P2[1];
890
+ next
891
+ );
892
+ if( #torseven[3] == 1, break());
893
+
894
+ P2 = ellhalf(ell,torseven[3][2]);
895
+ if( #P2 > 0,
896
+ torseven[1] *= 2;
897
+ torseven[2][2] *= 2;
898
+ torseven[3][2] = P2[1];
899
+ next
900
+ );
901
+ P2 = ellhalf(ell,elladd(ell,torseven[3][1],torseven[3][2]));
902
+ if( #P2 > 0,
903
+ torseven[1] *= 2;
904
+ torseven[2][1] *= 2;
905
+ torseven[3][1] = P2[1];
906
+ next
907
+ );
908
+ break()
909
+ );
910
+
911
+ if( DEBUGLEVEL_ell >= 4, print(" E[2^n] = ",torseven));
912
+ return(torseven);
913
+ }
914
+ {ellsort(listpts) =
915
+ \\ Sorting the points listpts on an elliptic curve
916
+ \\ using the naive height.
917
+ my(n,v,aux,ord);
918
+
919
+ v = vector(n = #listpts);
920
+ for( i = 1, n,
921
+ if( listpts[i] == [0], v[i] = [0,0,0]; next);
922
+ aux = denominator(listpts[i][2])/denominator(listpts[i][1]);
923
+ v[i] = vecsort(abs([listpts[i][1]*aux^2, listpts[i][2]*aux^3,aux]),,4);
924
+ );
925
+ ord = Vec(vecsort(v,,3)); \\ ord = vecsort(v,,3);
926
+ return(vector(n,i,listpts[ord[i]]));
927
+ }
928
+ {ellremovetorsion(ell,listgen) =
929
+ \\ Extracting the points of infinite order from listgen
930
+ my(d,extra);
931
+
932
+ if( DEBUGLEVEL_ell >= 5, print(" removing torsion from ",listgen));
933
+ d = #listgen;
934
+ extra = 0;
935
+ for( i = 1, d,
936
+ \\ points of order 1 or 2
937
+ if( listgen[i] == [0]
938
+ || listgen[i] == ellpow(ell,listgen[i],-1)
939
+ , extra += 1<<(i-1);
940
+ next
941
+ );
942
+ \\ detection of infinite order points by looking at
943
+ \\ 8*9*5*7*P modulo the prime 1048583
944
+ if( ell.disc%1048583 != 0
945
+ && denominator(listgen[i])%1048583 != 0
946
+ && ellpow(ell,listgen[i]*Mod(1,1048583),2520) != [0]
947
+ , next
948
+ );
949
+ \\ detection of torsion points by ellorder()
950
+ if( ellorder(ell,listgen[i]),
951
+ extra += 1<<(i-1)
952
+ )
953
+ );
954
+ if( extra,
955
+ listgen = vecextract(listgen,1<<#listgen-1-extra);
956
+ );
957
+ if( DEBUGLEVEL_ell >= 5, print(" without torsion = ",listgen));
958
+ return(listgen);
959
+ }
960
+ {ellredgen(ell0,listgen,K=1) =
961
+ \\ reduction of the generators of points in listgen
962
+ \\ on the elliptic curve ell = [a1,a2,a3,a4,a6]
963
+ \\ or K*y^2 = x^3 + a2*x^2 + a4*x + a6 (when a1 = a3 = 0);
964
+ \\ using the canonical height.
965
+ my(d,ell=ell0,sqrtK,urst,extra,M,U,listgen2,tors2,vt);
966
+
967
+ if( DEBUGLEVEL_ell >= 3, print(" Reduction of the generators ",listgen));
968
+ if( DEBUGLEVEL_ell >= 5, print(" ell=",ell));
969
+ d = #listgen;
970
+ if( d == 0, return([]));
971
+
972
+ \\ removing torsion points from listgen
973
+ listgen = ellremovetorsion(ell0,listgen);
974
+ d = #listgen;
975
+ if( d == 0, return([]));
976
+
977
+ if( #ell < 13, ell = ellinit(ell));
978
+
979
+ if( K != 1,
980
+ if( ell.a1 != 0 || ell.a3 != 0, error(" ellredgen: a1*a3 != 0"));
981
+ ell[2] *= K; ell[4] *= K^2; ell[5] *= K^3;
982
+ ell[6] *= K; ell[7] *= K^2; ell[8] *= K^3; ell[9] *= K^4;
983
+ ell[10] *= K^2; ell[11] *= K^3; ell[12] *= K^6;
984
+ sqrtK = sqrt(K);
985
+ if( #ell == 19,
986
+ ell[14] *= K;
987
+ ell[15] /= sqrtK; ell[16] /= sqrtK;
988
+ ell[17] *= sqrtK; ell[18] *= sqrtK;
989
+ ell[19] /= K
990
+ );
991
+
992
+ for( i = 1, d,
993
+ for( j = 1, #listgen[i],
994
+ listgen[i][j] *= K^j))
995
+ );
996
+
997
+ if( d == 1,
998
+ urst = [1,0,0,0];
999
+ ,
1000
+ if( #ell < 19, ell = ellinit(ell));
1001
+ ell = ellminimalmodel(ell,&urst);
1002
+ listgen = ellchangepoint(listgen,urst);
1003
+ if( DEBUGLEVEL_ell >= 5, print(" ell = ",ell));
1004
+ if( DEBUGLEVEL_ell >= 5, print(" listgen = ",listgen));
1005
+
1006
+ \\ Looking for relations between the points in listgen
1007
+ \\ using LLL on the height matrix
1008
+
1009
+ extra = 1;
1010
+ while( extra,
1011
+ M = ellheightmatrix(ell,listgen);
1012
+ if( DEBUGLEVEL_ell >= 4, print(" height matrix = ",M));
1013
+ if( abs(matdet(M)) > 10^(-default(realprecision)+10),break);
1014
+ U = qflll(round(M*10^(default(realprecision)-10)),4);
1015
+ U = concat(U[1],U[2]);
1016
+ if( DEBUGLEVEL_ell >= 4, print(" change of basis proposed by LLL = ",U));
1017
+ \\ the columns of U that have very small coefficients
1018
+ \\ are either exact relations or reductions (coeff <= 20)
1019
+ \\ the other ones are irrelevant.
1020
+ extra = 0;
1021
+ for( i = 1, d,
1022
+ if( vecmax(abs(U[,i])) > 20, extra += 1<<(i-1))
1023
+ );
1024
+ U = vecextract(U,1<<d-1-extra);
1025
+ U = completebasis(U);
1026
+ if( DEBUGLEVEL_ell >= 4, print(" change of basis 1 = ",U));
1027
+
1028
+ listgen2 = vector(d);
1029
+ for( i = 1, d,
1030
+ listgen2[i] = [0];
1031
+ for( j = 1, d,
1032
+ listgen2[i] = elladd(ell,listgen2[i],ellpow(ell,listgen[j],U[j,i]))));
1033
+ listgen = listgen2;
1034
+ );
1035
+
1036
+ \\ Extracting the points of infinite order
1037
+
1038
+ \\ removing torsion points from listgen
1039
+ listgen = ellremovetorsion(ell,listgen);
1040
+ d = #listgen;
1041
+ if( d == 0, return([]));
1042
+ );
1043
+
1044
+ if( DEBUGLEVEL_ell >= 3, print(" infinite order points = ",listgen));
1045
+
1046
+ \\ Now, the points should be of infinite order and independant
1047
+ \\ Reducing the points of infinite order
1048
+
1049
+ if( d > 1,
1050
+ M = ellheightmatrix(ell,listgen);
1051
+ if( DEBUGLEVEL_ell >= 4, print(" height matrix = ",M));
1052
+ U = qflllgram(M);
1053
+ if( DEBUGLEVEL_ell >= 4, print(" change of basis 2 = ",U));
1054
+
1055
+ listgen2 = vector(d);
1056
+ for( i = 1, d,
1057
+ listgen2[i] = [0];
1058
+ for( j = 1, d,
1059
+ listgen2[i] = elladd(ell,listgen2[i],ellpow(ell,listgen[j],U[j,i]))));
1060
+ listgen = listgen2;
1061
+ );
1062
+
1063
+ if( DEBUGLEVEL_ell >= 3, print(" infinite order points = ",listgen));
1064
+
1065
+ listgen = ellchangepoint(listgen,ellinverturst(urst));
1066
+
1067
+ \\ Reducing modulo the 2-torsion
1068
+
1069
+ tors2 = elltorseven(ell0);
1070
+ if( tors2[1] > 1,
1071
+ vt = vector(tors2[2][1],j,ellpow(ell0,tors2[3][1],j-1));
1072
+ if( #tors2[2] == 2,
1073
+ vt = concat(vt,vector(#vt,j,elladd(ell0,vt[j],tors2[3][2])))
1074
+ );
1075
+ for( i = 1, d,
1076
+ listgen[i] = ellsort(vector(#vt,j,elladd(ell0,listgen[i],vt[j])))[1];
1077
+ );
1078
+ );
1079
+
1080
+ if( DEBUGLEVEL_ell >= 3, print(" infinite order points = ",listgen));
1081
+
1082
+ if( K != 1,
1083
+ for( i = 1, d,
1084
+ for( j = 1, 2,
1085
+ listgen[i][j] /= K^j)));
1086
+
1087
+ \\ keep only the points (x,y) with y >= 0
1088
+
1089
+ if( ell0.a1 == 0 && ell0.a3 == 0,
1090
+ for( i = 1, d,
1091
+ if( #listgen[i] == 2,
1092
+ listgen[i][2] = abs(listgen[i][2]))));
1093
+
1094
+ if( DEBUGLEVEL_ell >= 2, print(" reduced generators = ",listgen));
1095
+ return(listgen);
1096
+ }
1097
+
1098
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1099
+ \\ FUNCTIONS FOR NUMBER FIELDS \\
1100
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1101
+
1102
+ {reducemodsquares(delta,d) =
1103
+ \\ Uses LLL to find z such that delta*z^2 has a small coefficient in x^d.
1104
+ \\ delta must be a t_POLMOD
1105
+ my(deg,xx,z,qd,Qd,reduc);
1106
+
1107
+ deg = poldegree(component(delta,1)); \\ deg = poldegree(delta.mod);
1108
+ xx = Mod('x,component(delta,1)); \\ xx = Mod(x,delta.mod);
1109
+ z = subst(Pol(vector(deg,i,eval(Str("a"i)))),'x,xx);
1110
+ qd = polcoeff(lift(delta*z^2),d,'x);
1111
+ Qd = simplify(matrix(deg,deg,i,j,deriv(deriv(qd,eval(Str("a"i))),eval(Str("a"j)))/2));
1112
+
1113
+ reduc = qflllgram_indef(Qd);
1114
+ if( #reduc == 2, reduc = reduc[2][,1]);
1115
+
1116
+ return(delta*subst(Pol(reduc),'x,xx)^2);
1117
+ }
1118
+ {bnfpSelmer(bnf,S=1,p) =
1119
+ \\ p is a prime integer and bnf a big number field.
1120
+ \\ Compute the p-Selmer group of the number field bnf
1121
+ \\ relative to the prime ideals dividing S.
1122
+ \\ This group is denoted by LS2 in the sequel.
1123
+ \\ Returns [gen,S'] where gen is a vector containing the generators
1124
+ \\ of the p-Selmer group, represented has elements of bnf modulo p-powers,
1125
+ \\ and S' is the support of gen.
1126
+ my(S1,oddclass,multS,Slist,LS2gen,newprimes,newprimesval,kerval);
1127
+
1128
+ if( DEBUGLEVEL_ell >= 3, print(" Constructing the field Selmer group: L(S,",p,")"));
1129
+ S1 = idealhnf(bnf,S);
1130
+
1131
+ oddclass = 0; multS = 1;
1132
+ while( !oddclass,
1133
+ if( multS != 1, S1 = idealmul(bnf,S1,multS));
1134
+ Slist = idealfactor(bnf,S1)[,1]~;
1135
+ if( DEBUGLEVEL_ell >= 4, print(" constructing the S-units "));
1136
+ if( DEBUGLEVEL_ell >= 4, print(" S1 = ",Slist));
1137
+ LS2gen = bnfsunit(bnf,Slist);
1138
+
1139
+ \\ If the class group is divisible by p,
1140
+ \\ need to enlarge S1.
1141
+ oddclass = LS2gen[5].no % p;
1142
+ if( !oddclass,
1143
+ if( DEBUGLEVEL_ell >= 4, print(" class group divisible by p = ",LS2gen[5].no));
1144
+ multS = idealmul(bnf,S,LS2gen[5].gen[1]);
1145
+ )
1146
+ );
1147
+ LS2gen = Mod(LS2gen[1],bnf.pol);
1148
+
1149
+ \\ The valuation of the generators must be divisible by p outside S.
1150
+ newprimes = [];
1151
+ for( i = 1, #Slist,
1152
+ if( idealadd(bnf,S,Slist[i]) == 1,
1153
+ newprimes = concat(newprimes,[Slist[i]])));
1154
+ if( DEBUGLEVEL_ell >= 4, print(" newprimes = ",newprimes));
1155
+ newprimesval = matrix(#newprimes,#LS2gen,i,j,
1156
+ idealval(bnf,LS2gen[j],newprimes[i]));
1157
+ if( DEBUGLEVEL_ell >= 4, print(" newprimesval = ",newprimesval));
1158
+ kerval = lift(matker(newprimesval*Mod(1,p)));
1159
+ if( DEBUGLEVEL_ell >= 4, print(" kerval = ",kerval));
1160
+ LS2gen = vector(#kerval,i,
1161
+ prod( j = 1, #LS2gen,
1162
+ LS2gen[j]^kerval[j,i]));
1163
+
1164
+ \\ Add the units
1165
+ LS2gen = concat(bnf.fu,LS2gen); \\ LS2gen = concat(bnf.fu,LS2gen);
1166
+ \\ Add also the torsion unit if its order is divisible by p.
1167
+ if( bnf[8][4][1]%p == 0, \\ if( bnf.tu[1]%p == 0,
1168
+ LS2gen = concat( [Mod(bnf[8][4][2],bnf.pol)], LS2gen)); \\ LS2gen = concat( [Mod(bnf.tu[2],bnf.pol)], LS2gen));
1169
+ if( DEBUGLEVEL_ell >= 3, print(" #LS2gen = ",#LS2gen));
1170
+ if( DEBUGLEVEL_ell >= 4, print(" LS2gen = ",LS2gen));
1171
+ return([LS2gen,Slist]);
1172
+ }
1173
+ {kersign(gen,rootapprox) =
1174
+ \\ Determine the kernel of the sign map
1175
+ \\ restricted to the subgroup generated by gen,
1176
+ \\ and relative to the real embedding corresponding to
1177
+ \\ the root of pol contained in the interval rootapprox.
1178
+ my(signs,elt,elt2,d,st,kers,compt);
1179
+
1180
+ if( DEBUGLEVEL_ell >= 3, print(" Computing the kernel of the sign ",rootapprox));
1181
+
1182
+ \\ determination of the signs
1183
+
1184
+ signs = vector(#gen);
1185
+ for( i = 1, #gen,
1186
+ elt = lift(gen[i]);
1187
+ if( DEBUGLEVEL_ell >= 5, print(" Computing the sign of elt = ",elt));
1188
+ if( poldegree(elt) == 0, signs[i] = sign(simplify(elt)) < 0; next);
1189
+ d = poldisc(elt);
1190
+ if( poldegree(elt) == 2,
1191
+ if( d <= 0, signs[i] = sign(pollead(elt)) < 0; next));
1192
+ elt2 = if( d == 0, elt/gcd(elt,elt'), elt);
1193
+ st = 1;
1194
+ compt = 0;
1195
+ while( st,
1196
+ st = polsturm(elt2,rootapprox[1],rootapprox[2]);
1197
+ if( st,
1198
+ rootapprox = polrealrootsimprove(component(gen[i],1),rootapprox);
1199
+ \\ rootapprox = polrealrootsimprove(gen[i].mod,rootapprox);
1200
+ \\ if the sign of elt is too difficult to determine,
1201
+ \\ try a reduction modulo squares
1202
+ if( compt++ == 5, gen[i] = reducemodsquares(gen[i]); i--; next(2));
1203
+ \\ if the sign of elt is still too difficult to determine,
1204
+ \\ try the sign of 1/elt.
1205
+ if( compt%5 == 0, gen[i] = 1/gen[i]; i--; next(2))
1206
+ ));
1207
+ signs[i] = sign(subst(elt,variable(elt),rootapprox[2])) < 0
1208
+ );
1209
+ if( DEBUGLEVEL_ell >= 4, print(" signs = ",signs));
1210
+
1211
+ \\ construction of the kernel
1212
+ kers = matker(Mat(signs*Mod(1,2)))*Mod(1,2);
1213
+ if( DEBUGLEVEL_ell >= 4, print(" kers = ",lift(kers)));
1214
+ return(kers);
1215
+ }
1216
+ {kernorm(gen,S,p) =
1217
+ \\ gen is a generating set for a subgroup of K^* / K^p.
1218
+ \\ Compute the kernel of the norm map.
1219
+ \\ Uses the fact that all valuations are 0 mod p,
1220
+ \\ except maybe at primes in S.
1221
+ my(normgen,normmap,kern);
1222
+
1223
+ if( DEBUGLEVEL_ell >= 3, print(" Computing the kernel of the norm map"));
1224
+
1225
+ if( p == 2, S = concat([-1],S));
1226
+ normgen = norm(gen);
1227
+ if( DEBUGLEVEL_ell >= 4, print(" normgen = ",normgen));
1228
+
1229
+ \\ matrix of the norm map
1230
+ normmap = matrix(#S,#normgen,i,j,
1231
+ if( i == 1 && p == 2,
1232
+ sign(normgen[j]) < 0
1233
+ , valuation(normgen[j],S[i])));
1234
+ if( DEBUGLEVEL_ell >= 4, print(" normmap = ",normmap));
1235
+
1236
+ \\ construction of the kernel
1237
+ kern = matker(normmap*Mod(1,p))*Mod(1,p);
1238
+ if( DEBUGLEVEL_ell >= 4, print(" ker = ",lift(kern)));
1239
+ return(kern);
1240
+ }
1241
+
1242
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1243
+ \\ FUNCTIONS FOR 2-DESCENT \\
1244
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1245
+
1246
+ {elllocalimage( nf, pp, K = 1) =
1247
+ \\ pol is the cubic polynomial defining the elliptic curve,
1248
+ \\ nf is nfinit(pol),
1249
+ \\ p is a prime integer, and pp = ppinit(p).
1250
+ \\ Returns the image of the p-adic points
1251
+ \\ E(Qp)/2E(Qp) in Kp/Kp^2.
1252
+ \\ The algorithm consists of choosing random p-adic points in E(Qp)
1253
+ \\ until the number of images is equal to #E(Qp)[2] / |2|_p
1254
+ my(X,p,prank,rac,pts,bound,essai,mrank,r,xx,delta,ph,delta2,local_prec,ival);
1255
+
1256
+ if( DEBUGLEVEL_ell >= 4, print(" starting elllocalimage"));
1257
+
1258
+ X = Mod('x,nf.pol);
1259
+ p = pp[1][1][1];
1260
+ prank = #pp - (p != 2);
1261
+ if( DEBUGLEVEL_ell >= 4, print(" prank = ",prank));
1262
+
1263
+ rac = polrootsmodpn(K*nf.pol,p);
1264
+ if( DEBUGLEVEL_ell >= 5, print(" rac = ",rac));
1265
+
1266
+ pts = matrix(0,0);
1267
+ bound = p+6;
1268
+ essai = 0;
1269
+ mrank = 0;
1270
+ while( mrank < prank,
1271
+
1272
+ essai ++;
1273
+ if( essai%16 == 0,
1274
+ pts = matimage(pts);
1275
+ bound *= p;
1276
+ );
1277
+
1278
+ r = random(#rac)+1; local_prec = random(rac[r][2]+3)-2;
1279
+ xx = rac[r][1]+p^local_prec*random(bound);
1280
+ if( DEBUGLEVEL_ell >= 5, print(" xx = ",xx));
1281
+ delta = K*(xx-X);
1282
+
1283
+ \\ rem: K*pol(xx) = norm(delta) ( = y^2 for a point on the elliptic curve)
1284
+ if( !psquare(K*subst(nf.pol,'x,xx),p), next);
1285
+ ph = [];
1286
+ for( i = 1, #pp,
1287
+ ph = concat(ph,[ ival = idealval(nf,delta,pp[i][1])]);
1288
+ delta2 = delta/pp[i][2]^ival;
1289
+ if( p == 2,
1290
+ ph = concat(ph,ideallog(nf,delta2,pp[i][3])~);
1291
+ , ph = concat(ph,[1-nfpsquareodd(nf,delta2,pp[i][4])])
1292
+ )
1293
+ );
1294
+ if( DEBUGLEVEL_ell >= 5, print(" ph = ",ph));
1295
+
1296
+ pts = concat(pts,ph~*Mod(1,2));
1297
+ mrank = matrank(pts*Mod(1,2));
1298
+ if( DEBUGLEVEL_ell >= 5, print(" pts = ",lift(pts)));
1299
+ if( DEBUGLEVEL_ell >= 5, print(" matrank = ",mrank));
1300
+ );
1301
+
1302
+ pts = matimage(pts);
1303
+ if( DEBUGLEVEL_ell >= 5, print(" essai = ",essai));
1304
+ if( DEBUGLEVEL_ell >= 4, print(" end of elllocalimage"));
1305
+ return(pts);
1306
+ }
1307
+ {ell2descent_gen(ell,bnf,K=1,help=[],redflag=0) =
1308
+ \\ This algorithm performs 2-descent on the elliptic curve ell
1309
+ \\ when ell has trivial 2-torsion.
1310
+
1311
+ \\ ell must be of the form K*y^2=x^3+A*x^2+B*x+C
1312
+ \\ ie ell=[0,A,0,B,C], with K,A,B,C integers.
1313
+ \\ bnf is bnfinit(x^3+A*x^2+B*x+C,1).
1314
+
1315
+ \\
1316
+ \\ help is a list of known points (maybe empty) on ell.
1317
+ \\ if redflag != 0, reduces the elements
1318
+ \\ of the field Selmer group modulo squares.
1319
+
1320
+ my(A,B,C,polrel,polprime,ttheta,badprimes,S,LS2,selmer,rootapprox,p,pp,locimage,LS2image,listpointstriv,listpoints,iwhile,expo,zc,liftzc,den,point,idealfactorzc,idealzc,baseidealzc,q2,sol,param,q1,pol,redq,q0,pointxx,point2,rang);
1321
+
1322
+ if( DEBUGLEVEL_ell >= 4, print(" starting ell2descent_gen"));
1323
+
1324
+ if( #ell < 13, ell = ellinit(ell));
1325
+
1326
+ if( ell.a1 != 0 || ell.a3 != 0,
1327
+ error(" ell2descent_gen: the curve is not of the form [0,a,0,b,c]"));
1328
+ if( denominator(ell.a2) > 1 || denominator(ell.a4) > 1 || denominator(ell.a6) >1,
1329
+ error(" ell2descent_gen: non integral coefficients"));
1330
+
1331
+ A = ell.a2; if( DEBUGLEVEL_ell >= 2, print(" A = ",A));
1332
+ B = ell.a4; if( DEBUGLEVEL_ell >= 2, print(" B = ",B));
1333
+ C = ell.a6; if( DEBUGLEVEL_ell >= 2, print(" C = ",C));
1334
+
1335
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1336
+ \\ Construction of L(S,2) \\
1337
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1338
+
1339
+ if( DEBUGLEVEL_ell >= 2, print(); print(" Computing L(S,2)"));
1340
+
1341
+ polrel = Pol([1,A,B,C]);
1342
+ polprime = polrel';
1343
+ ttheta = Mod('x,polrel);
1344
+
1345
+ if( !bnf,
1346
+ if( DEBUGLEVEL_ell >= 3, print(" bnfinit(",polrel,")"));
1347
+ bnf = bnfinit(polrel,1));
1348
+
1349
+ badprimes = abs(K*idealadd(bnf,polprime,bnf.index));
1350
+ if( DEBUGLEVEL_ell >= 5, print(" badprimes = ",badprimes[1,1]));
1351
+ S = bnfpSelmer(bnf,badprimes,2);
1352
+ LS2 = S[1]; S = S[2];
1353
+
1354
+ if( DEBUGLEVEL_ell >= 2, print(" L(S,2) = ",LS2));
1355
+
1356
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1357
+ \\ Construction of the Selmer group \\
1358
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1359
+
1360
+ if( DEBUGLEVEL_ell >= 2, print(); print(" Computing the Selmer group"));
1361
+
1362
+ \\ elements with square norm
1363
+ selmer = kernorm(LS2,vector(#S,i,S[i].p),2);
1364
+ if( DEBUGLEVEL_ell >= 3, print(" selmer = ",lift(selmer)));
1365
+
1366
+ \\ the first real embedding must be > 0
1367
+ \\ since the norm is a square, this is automatic
1368
+ \\ if there is a single real embedding.
1369
+ if( bnf.r1 == 3,
1370
+ rootapprox = polrealrootsisolate(polrel)[1];
1371
+ selmer = matintersect(selmer,kersign(LS2,rootapprox))*Mod(1,2);
1372
+ if( DEBUGLEVEL_ell >= 3, print(" selmer = ",lift(selmer)));
1373
+ );
1374
+
1375
+ \\ p-adic points
1376
+ if( DEBUGLEVEL_ell >= 3, print(" p-adic points"));
1377
+ badprimes = factorint(badprimes[1,1]*2)[,1];
1378
+ if( DEBUGLEVEL_ell >= 2, print(" badprimes = ",badprimes));
1379
+ for( i = 1, #badprimes,
1380
+ p = badprimes[i];
1381
+ if( DEBUGLEVEL_ell >= 4, print(" p = ",p));
1382
+ pp = ppinit(bnf.nf,p);
1383
+ locimage = elllocalimage(bnf.nf,pp,K);
1384
+ LS2image = LS2localimage(bnf.nf,LS2,pp);
1385
+ locimage = matintersect(LS2image,locimage);
1386
+ selmer = matintersect(
1387
+ selmer,
1388
+ concat(
1389
+ matker(LS2image),
1390
+ matinverseimage(LS2image,locimage)*Mod(1,2)));
1391
+ selmer = matimage(selmer*Mod(1,2));
1392
+ if( DEBUGLEVEL_ell >= 4, print(" selmer = ",lift(selmer)));
1393
+ if( !#selmer, break);
1394
+ );
1395
+
1396
+ if( DEBUGLEVEL_ell >= 2, print(" selmer = ",lift(selmer)));
1397
+ if( DEBUGLEVEL_ell >= 2, print(" Selmer rank = ",#selmer));
1398
+
1399
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1400
+ \\ Search for trivial points \\
1401
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1402
+
1403
+ if( #selmer,
1404
+ if( DEBUGLEVEL_ell >= 2, print(); print(" Search for trivial points on the curve"));
1405
+ listpointstriv = ratpoint(K^3*subst(polrel,'x,'x/K),LIMTRIV,0);
1406
+ for( i = 1, #listpointstriv,
1407
+ if( #listpointstriv[i] == 3,
1408
+ listpointstriv[i] = [0]
1409
+ , for( j = 1, 2, listpointstriv[i][j] /= K^j))
1410
+ );
1411
+ listpointstriv = concat(help,listpointstriv);
1412
+ if( DEBUGLEVEL_ell >= 2, print(" Trivial points on the curve = ",listpointstriv));
1413
+ );
1414
+
1415
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1416
+ \\ Run through the Selmer group \\
1417
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1418
+
1419
+ if( DEBUGLEVEL_ell >= 2, print(); print(" Run through the Selmer group"));
1420
+
1421
+ listpoints = [];
1422
+ selmer = lift(selmer);
1423
+ iwhile = 1;
1424
+ while( iwhile < 1<<#selmer,
1425
+ if( DEBUGLEVEL_ell >= 2, print());
1426
+ if( DEBUGLEVEL_ell >= 4, print(" iwhile = ",iwhile));
1427
+
1428
+ \\ the next element zc as an algebraic number modulo squares
1429
+
1430
+ expo = selmer*vectorv(#selmer,i,bittest(iwhile,i-1));
1431
+ zc = prod( i = 1, #LS2, LS2[i]^expo[i]);
1432
+ if( DEBUGLEVEL_ell >= 2, print(" zc = ",zc));
1433
+ liftzc = lift(zc);
1434
+
1435
+ \\ Reduction modulo squares
1436
+
1437
+ if( redflag,
1438
+ zc = reducemodsquares(zc,2);
1439
+ liftzc = lift(zc);
1440
+ den = denominator(content(liftzc))^2;
1441
+ zc *= den; liftzc *= den;
1442
+ if( DEBUGLEVEL_ell >= 2, print(" zc reduced = ",zc))
1443
+ );
1444
+
1445
+ \\ Does it come from a trivial point ?
1446
+
1447
+ for( i = 1, #listpointstriv,
1448
+ point = listpointstriv[i];
1449
+ if( #point == 2,
1450
+ if( nfissquare(bnf.nf,K*(point[1]-'x)*liftzc),
1451
+ if( DEBUGLEVEL_ell >= 2, print(" comes from the trivial point ",point));
1452
+ listpoints = concat(listpoints,[point]);
1453
+ iwhile = 1 << (degre(iwhile)+1);
1454
+ next(2)
1455
+ )));
1456
+
1457
+ if( DEBUGLEVEL_ell >= 2, print(" does not come from a trivial point"));
1458
+
1459
+ \\ Construction of the quadratic form q2
1460
+ \\ Change the basis using the square factors of zc
1461
+
1462
+ idealfactorzc = idealfactor(bnf,zc);
1463
+ idealfactorzc[,2] *= -1;
1464
+ idealfactorzc[,2] \= 2;
1465
+ \\ idealzc = idealfactorback(bnf,idealfactorzc);
1466
+ idealzc = matid(3);
1467
+ for( i = 1, #idealfactorzc[,1],
1468
+ idealzc = idealmul(bnf,idealzc,idealpow(bnf,idealfactorzc[i,1],idealfactorzc[i,2]));
1469
+ );
1470
+ baseidealzc = vector(3,i,nfbasistoalg(bnf,idealzc[,i]));
1471
+ q2 = matrix(3,3,i,j,trace(zc*baseidealzc[i]*baseidealzc[j]/polprime));
1472
+ if( DEBUGLEVEL_ell >= 4, print(" q2 = ",q2));
1473
+ if( DEBUGLEVEL_ell >= 4, print(" q2/content(q2) = ",q2/content(q2)));
1474
+
1475
+ \\ Solution of the quadratic equation q2=0
1476
+
1477
+ sol = qfsolve(q2/content(q2));
1478
+ if( DEBUGLEVEL_ell >= 4,print(" sol = ",sol));
1479
+ if( type(sol) == "t_INT",
1480
+ error(" ell2descent_gen: WRONG ELEMENT IN THE SELMER GROUP, please report"));
1481
+
1482
+
1483
+ \\ Parametrizing the solutions of q2=0
1484
+
1485
+ param = qfparam(q2,sol,3)*['x^2,'x,1]~;
1486
+ param /= content(param);
1487
+
1488
+ \\ Construction of the quartic
1489
+
1490
+ q1 = -matrix(3,3,i,j,trace(zc*baseidealzc[i]*baseidealzc[j]*(ttheta+A)/polprime));
1491
+ pol = param~*q1*param;
1492
+ if( DEBUGLEVEL_ell >= 2, print(" quartic: ",K,"*Y^2 = ",pol));
1493
+ redq = redquartic(pol);
1494
+ pol = redq[1];
1495
+ den = denominator(content(K*pol));
1496
+ pol *= den^2;
1497
+ if( DEBUGLEVEL_ell >= 2, print(" reduced: ",K,"*Y^2 = ",pol));
1498
+
1499
+ \\ Search for points on the quartic
1500
+
1501
+ point = ratpoint(K*pol,LIM1,1);
1502
+ if( point == [], point = ratpoint2(K*pol,LIM3,1));
1503
+ if( point == [], iwhile ++; next );
1504
+
1505
+ if( #point == 2, point = concat(point,[1]));
1506
+ if( DEBUGLEVEL_ell >= 2, print(" point on the reduced quartic = ",point));
1507
+ point = concat(redq[2]*[point[1],point[3]]~,[point[2]/den]~);
1508
+ if( DEBUGLEVEL_ell >= 2, print(" point on the quartic = ",point));
1509
+
1510
+ \\ Construction of the point on the elliptic curve from the point on the quartic
1511
+
1512
+ param = subst(param,'x,'x/'y)*'y^2;
1513
+ param = subst(subst(param,'x,point[1]),'y,point[2]);
1514
+ param *= K/point[3];
1515
+ if( DEBUGLEVEL_ell >= 3, print(" reconstruction of the point on the curve"));
1516
+ q0 = matrix(3,3,i,j,trace(zc*baseidealzc[i]*baseidealzc[j]*(ttheta^2+A*ttheta+B)/polprime));
1517
+ pointxx = param~*q0*param/K;
1518
+ point2 = [ pointxx, sqrtrat(subst(polrel,'x,pointxx)/K)];
1519
+ if( DEBUGLEVEL_ell >= 1, print(" point on the curve = ",point2));
1520
+ listpoints = concat(listpoints,[point2]);
1521
+ iwhile = 1 << (degre(iwhile)+1)
1522
+ );
1523
+
1524
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1525
+ \\ Conclusion report \\
1526
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1527
+
1528
+ rang = #listpoints;
1529
+
1530
+ if( DEBUGLEVEL_ell >= 2,
1531
+ print();
1532
+ print(" rank of found points = ",#listpoints);
1533
+ print(" rank of the Selmer group = ",#selmer));
1534
+
1535
+ if( DEBUGLEVEL_ell >= 1, afficheselmer(rang,#selmer));
1536
+
1537
+ if( (#selmer - rang)%2,
1538
+ rang ++;
1539
+ if( DEBUGLEVEL_ell >= 1,
1540
+ print(" III should be a square, hence ");
1541
+ afficheselmer(rang,#selmer));
1542
+ );
1543
+
1544
+ \\ Verification
1545
+
1546
+ if( DEBUGLEVEL_ell >= 1, print("listpoints = ",listpoints));
1547
+ for( i = 1, #listpoints,
1548
+ if( subst(polrel,'x,listpoints[i][1])-K*listpoints[i][2]^2,
1549
+ error(" ell2descent_gen: WRONG POINT = ",listpoints[i]," please report")));
1550
+
1551
+ \\ Reduction of the points
1552
+
1553
+ listpoints = vecsort(listpoints,,2);
1554
+ if( #listpoints >= 2 && ELLREDGENFLAG,
1555
+ listpoints = ellredgen(ell,listpoints,K));
1556
+
1557
+ if( DEBUGLEVEL_ell >= 4, print(" end of ell2descent_gen"));
1558
+ return([rang,#selmer,listpoints]);
1559
+ }
1560
+ {afficheselmer(m1,m2,tors2) =
1561
+
1562
+ print("#E(Q)[2] = ",1<<tors2);
1563
+ print("#S(E/Q)[2] = ",1<<m2);
1564
+ if( m1+tors2 == m2,
1565
+ print("#E(Q)/2E(Q) = ",1<<(m1+tors2));
1566
+ print("#III(E/Q)[2] = 1");
1567
+ print("rank(E/Q) = ",m1);
1568
+ ,
1569
+ print("#E(Q)/2E(Q) >= ",1<<(m1+tors2));
1570
+ print("#III(E/Q)[2] <= ",1<<(m2-m1-tors2));
1571
+ print("rank(E/Q) >= ",m1)
1572
+ );
1573
+ }
1574
+ {ellQ_ellrank(ell,help=[]) =
1575
+ \\ Algorithm of 2-descent on the elliptic curve ell.
1576
+ \\ help is a list of known points on ell.
1577
+ my(urst,urst1,den,eqell,tors2,bnf,rang,time1);
1578
+
1579
+ if( DEBUGLEVEL_ell >= 3, print(" starting ellQ_ellrank"));
1580
+ if( #ell < 13, ell = ellinit(ell));
1581
+
1582
+ \\ kill the coefficients a1 and a3
1583
+ urst = [1,0,0,0];
1584
+ if( ell.a1 != 0 || ell.a3 != 0,
1585
+ urst1 = [1,0,-ell.a1/2,-ell.a3/2];
1586
+ ell = ellchangecurve(ell,urst1);
1587
+ urst = ellcomposeurst(urst,urst1)
1588
+ );
1589
+
1590
+ \\ kill denominators
1591
+ while( (den = denominator([ell.a2,ell.a4,ell.a6])) > 1,
1592
+ den = factor(den); den[,2] = vectorv(#den[,2],i,1);
1593
+ den = factorback(den);
1594
+ urst1 = [1/den,0,0,0];
1595
+ ell = ellchangecurve(ell,urst1);
1596
+ urst = ellcomposeurst(urst,urst1)
1597
+ );
1598
+
1599
+ help = ellchangepoint(help,urst);
1600
+ eqell = Pol([1,ell.a2,ell.a4,ell.a6]);
1601
+ if( DEBUGLEVEL_ell >= 1, print(" Elliptic curve: Y^2 = ",eqell));
1602
+
1603
+ \\ Choice of the algorithm depending on the 2-torsion structure
1604
+
1605
+ tors2 = ellhalf(ell,[0]);
1606
+ if( DEBUGLEVEL_ell >= 1, print(" E[2] = ",tors2));
1607
+
1608
+ if( #tors2 == 1, \\ case 1: 2-torsion trivial
1609
+ if( DEBUGLEVEL_ell >= 3, print1(" bnfinit(",eqell,")"));
1610
+ if( DEBUGLEVEL_ell >= 4, gettime());
1611
+ bnf = bnfinit(eqell,1);
1612
+ if( DEBUGLEVEL_ell >= 4, time1 = gettime());
1613
+ if( DEBUGLEVEL_ell >= 3, print(" done"));
1614
+ rang = ell2descent_gen(ell,bnf,1,help);
1615
+ if( DEBUGLEVEL_ell >= 4, print(" time for bnfinit = ",time1));
1616
+ if( DEBUGLEVEL_ell >= 4, print(" time for the rest = ",gettime()));
1617
+ ,
1618
+ if( #tors2 == 2 || !COMPLETE, \\ case 2: 2-torsion >= Z/2Z
1619
+ if( ell.a6 != 0,
1620
+ urst1 = [1,tors2[2][1],0,0];
1621
+ ell = ellchangecurve(ell,urst1);
1622
+ urst = ellcomposeurst(urst,urst1)
1623
+ );
1624
+ eqell = Pol([1,ell.a2,ell.a4,ell.a6]);
1625
+ if( DEBUGLEVEL_ell >= 1, print(" Elliptic curve: Y^2 = ",eqell));
1626
+
1627
+ rang = ell2descent_viaisog(ell,help)
1628
+ , \\ case 3: 2-torsion = Z/2Z*Z/2Z
1629
+ rang = ell2descent_complete(tors2[2][1],tors2[3][1],tors2[4][1])
1630
+ ));
1631
+
1632
+ rang[3] = ellchangepoint(rang[3],ellinverturst(urst));
1633
+ if( DEBUGLEVEL_ell >= 3, print(" end of ellQ_ellrank"));
1634
+
1635
+ return(rang);
1636
+ }
1637
+ {ell2descent_complete(e1,e2,e3,help) =
1638
+ \\ Compute the rank of the elliptic curve
1639
+ \\ E: Y^2 = (x-e1)*(x-e2)*(x-e3)
1640
+ \\ using the complete 2-descent algorithm (see J.Silverman).
1641
+ \\ Returns [r,s,v] with
1642
+ \\ r is a lower bound for the rank of E(Q)
1643
+ \\ s is the rank of Selmer[2]
1644
+ \\ v is a system of independant points on E(Q)/2E(Q)
1645
+
1646
+ \\ e1, e2, e3 must be integers.
1647
+ \\ help is a list of known points on E.
1648
+
1649
+ my(ee,d32,d31,d21,G1,G2,G3,vect1,vect2,vect3,selmer,rang,listpoints,b1,b2,q1,sol1,param1,param1x,quart,point,z1,solx,soly,strange,ell);
1650
+
1651
+ if( DEBUGLEVEL_ell >= 2, print(" Algorithm of complete 2-descent"));
1652
+
1653
+ \\ sort the integers e1, e2, e3 in increasing order
1654
+
1655
+ ee = vecsort([e1,e2,e3]);
1656
+ e1 = ee[1]; e2 = ee[2]; e3 = ee[3];
1657
+
1658
+ \\ Computation of the groups G1 and G2
1659
+
1660
+ d32 = e3-e2; d31 = e3-e1; d21 = e2-e1;
1661
+ G1 = factor(d31*d21)[,1]; \\ (G1 > 0)
1662
+ G2 = factor(-d32*d21)[,1]; \\ (G2 < 0)
1663
+ G3 = d31*d32;
1664
+
1665
+ if( DEBUGLEVEL_ell >= 3, print(" G1 = ",G1));
1666
+ if( DEBUGLEVEL_ell >= 3, print(" G2 = ",G2));
1667
+
1668
+ \\ Run through G1*G2
1669
+
1670
+ vect1 = vector(#G1,i,[0,1]);
1671
+ vect2 = vector(#G2,i,[0,1]);
1672
+ selmer = 0;
1673
+ rang = 0;
1674
+ listpoints = [];
1675
+
1676
+ forvec( X = vect1,
1677
+ b1 = prod( i = 1, #G1, G1[i]^X[i]);
1678
+
1679
+ \\ b1*b2*b3 must be a square, where b3 is a divisor of d32*d31
1680
+ vect3 = vect2;
1681
+ for( i = 2, #G2,
1682
+ if( G3%G2[i] !=0,
1683
+ vect3[i] = [1,1]*valuation(b1,G2[i])));
1684
+
1685
+ forvec( Y = vect3,
1686
+ b2 = prod( i = 1, #G2, G2[i]^Y[i]);
1687
+
1688
+ if( DEBUGLEVEL_ell >= 3, print(" [b1,b2] = ",lift([b1,b2])));
1689
+
1690
+ \\ Trivial points coming from the 2-torsion
1691
+
1692
+ if( b1==1 && b2==1,
1693
+ if( DEBUGLEVEL_ell >= 4, print(" trivial point [0]"));
1694
+ selmer++; rang++; next);
1695
+ if( issquare(-d21*b2) && issquare(d31*d21*b1),
1696
+ if( DEBUGLEVEL_ell >= 3, print(" trivial point [e1,0]"));
1697
+ selmer++; rang++; listpoints = concat(listpoints,[[e1,0]]); next);
1698
+ if( issquare(d21*b1) && issquare(-d32*d21*b2),
1699
+ if( DEBUGLEVEL_ell >= 3, print(" trivial point [e2,0]"));
1700
+ selmer++; rang++; listpoints = concat(listpoints,[[e2,0]]); next);
1701
+ if( issquare(d31*b1) && issquare(d32*b2),
1702
+ if( DEBUGLEVEL_ell >= 3, print(" trivial point [e3,0]"));
1703
+ selmer++; rang++; listpoints = concat(listpoints,[[e3,0]]); next);
1704
+
1705
+ \\ Trivial points coming from help
1706
+
1707
+ for( i = 1, #help,
1708
+ if( #help[i] != 2 || help[i][2] == 0, next);
1709
+ if( issquare(b1*(help[i][1]-e1)) && issquare(b2*(help[i][1]-e2)),
1710
+ if( DEBUGLEVEL_ell >= 3, print(" trivial point from help ",help[i]));
1711
+ selmer++; rang++;
1712
+ listpoints = concat(listpoints,[help[i]]); next(2));
1713
+ );
1714
+
1715
+ \\ If one can solve 2 quadratic equations
1716
+ \\ (1) q1: b1*z1^2-b2*z2^2 = e2-e1
1717
+ \\ (2) q2: b1*z1^2-b1*b2*z3^2 = e3-e1
1718
+ \\ then (x,y) = (b1*z1^2+e1,b1*b2*z1*z2*z3) is a point on E
1719
+ \\ we also have
1720
+ \\ (3) q3 = q1-q2: b1*b2*z3^2-b2*z2^2=e2-e3
1721
+
1722
+ \\ Solution of the q1
1723
+
1724
+ q1 = matdiagonal([b1,-b2,-d21]);
1725
+ if( DEBUGLEVEL_ell >= 3, print(" q1 = ",q1));
1726
+ sol1 = qfsolve(q1);
1727
+ if( type(sol1) == "t_INT",
1728
+ if( DEBUGLEVEL_ell >= 3, print(" q1 not ELS at ",sol1));
1729
+ next);
1730
+ if( DEBUGLEVEL_ell >= 3, print(" solution of q1 = ",sol1));
1731
+ param1 = qfparam(q1,sol1,1);
1732
+ param1 /= content(param1);
1733
+ if( DEBUGLEVEL_ell >= 3, print(" parametrization of q1 = ",param1));
1734
+ param1x = param1*['x^2,'x,1]~;
1735
+
1736
+ \\ Solution of the q2
1737
+ \\ only useful to detect local non solubility
1738
+
1739
+ \\ my(q2,sol2);
1740
+ \\ q2 = matdiagonal([b1,-b1*b2,-d31]);
1741
+ \\if( DEBUGLEVEL_ell >= 3, print(" q2 = ",q2));
1742
+ \\ sol2 = qfsolve(q2);
1743
+ \\ if( type(sol2) == "t_INT",
1744
+ \\if( DEBUGLEVEL_ell >= 3, print(" q2 not ELS at ",sol2));
1745
+ \\ next);
1746
+
1747
+ \\ Construction of the quartic
1748
+
1749
+ quart = b1*b2/gcd(b1,b2)^2*(b1*param1x[1]^2-d31*param1x[3]^2);
1750
+ if( DEBUGLEVEL_ell >= 3, print(" quart = ",quart));
1751
+
1752
+ \\ Search for trivial points on the quartic
1753
+
1754
+ point = [];
1755
+ \\ point = ratpoint(quart,LIM1,1);
1756
+
1757
+ \\ Local solubility of the quartic
1758
+
1759
+ if( point == [] && !locallysoluble(quart),
1760
+ if( DEBUGLEVEL_ell >= 3, print(" quartic not ELS "));
1761
+ next);
1762
+ if( DEBUGLEVEL_ell >= 2, print(" y^2 = ",quart));
1763
+ selmer++;
1764
+
1765
+ \\ Search for points on the quartic
1766
+
1767
+ if( point == [], point = ratpoint2(quart,LIM3,1));
1768
+ if( point != [],
1769
+ if( DEBUGLEVEL_ell >= 2, print(" point found on the quartic !!"));
1770
+ if( DEBUGLEVEL_ell >= 3, print(" ",point));
1771
+ if( #point == 2,
1772
+ z1 = subst(param1x[1],'x,point[1])/subst(param1x[3],'x,point[1])
1773
+ , z1 = param1[1,1]/param1[3,1]);
1774
+ solx = b1*z1^2+e1;
1775
+ soly = sqrtrat((solx-e1)*(solx-e2)*(solx-e3));
1776
+ listpoints = concat(listpoints,[[solx,soly]]);
1777
+ if( DEBUGLEVEL_ell >= 1, print(" point on the elliptic curve = ",[solx,soly]));
1778
+ rang++
1779
+ ,
1780
+ if( DEBUGLEVEL_ell >= 2, print(" no point found on the quartic"))
1781
+ )
1782
+ )
1783
+ );
1784
+
1785
+ \\ end
1786
+
1787
+ if( DEBUGLEVEL_ell >= 1,
1788
+ print("#S^(2) = ",selmer));
1789
+ if( rang > selmer/2, rang = selmer);
1790
+ if( DEBUGLEVEL_ell >= 1,
1791
+ strange = rang != selmer;
1792
+ if( strange,
1793
+ print("#E[K]/2E[K]>= ",rang)
1794
+ , print("#E[K]/2E[K] = ",rang));
1795
+ print("#E[2] = 4");
1796
+ );
1797
+ rang = ceil(log(rang)/log(2))-2;
1798
+ selmer = valuation(selmer,2);
1799
+ if( DEBUGLEVEL_ell >= 1,
1800
+ if( strange,
1801
+ print(selmer-2," >= rank >= ",rang)
1802
+ , print("rank = ",rang));
1803
+ if( rang, print("points = ",listpoints));
1804
+ );
1805
+ ell = ellinit([0,-(e1+e2+e3),0,e1*e2+e2*e3+e3*e1,-e1*e2*e3],1);
1806
+ listpoints = vecsort(listpoints,,2);
1807
+ if( ELLREDGENFLAG, listpoints = ellredgen(ell,listpoints));
1808
+ listpoints = concat(ellsort(elltorseven(ell)[3]),listpoints);
1809
+
1810
+ return([rang,selmer,listpoints]);
1811
+ }
1812
+ {ellcount( c, d, KS2gen, listpointstriv=[]) =
1813
+ my(found,listgen,listpointscount,m1,m2,lastloc,mask,i,d1,iaux,j,triv,pol,point,qf,solqf,para,point1,v);
1814
+
1815
+ if( DEBUGLEVEL_ell >= 4, print(" starting ellcount ",[c,d]));
1816
+ if( DEBUGLEVEL_ell >= 4, print(" KS2gen = ",KS2gen));
1817
+ if( DEBUGLEVEL_ell >= 4, print(" listpointstriv = ",listpointstriv));
1818
+
1819
+ found = 0;
1820
+ listgen = KS2gen;
1821
+ listpointscount = [];
1822
+
1823
+ m1 = m2 = 0; lastloc = -1;
1824
+
1825
+ mask = 1 << #KS2gen;
1826
+ i = 1;
1827
+ while( i < mask,
1828
+ d1 = 1; iaux = i; j = 1;
1829
+ while( iaux,
1830
+ if( iaux%2, d1 *= listgen[j]);
1831
+ iaux >>= 1; j++);
1832
+ if( DEBUGLEVEL_ell >= 3, print(" d1 = ",d1));
1833
+ triv = 0;
1834
+ for( j = 1, #listpointstriv,
1835
+ if( listpointstriv[j][1] && issquare(d1*listpointstriv[j][1]),
1836
+ listpointscount = concat(listpointscount,[listpointstriv[j]]);
1837
+ if( DEBUGLEVEL_ell >= 2, print(" trivial point"));
1838
+ triv = 1; m1++;
1839
+ if( degre(i) > lastloc, m2++);
1840
+ found = 1; lastloc = -1; break));
1841
+ if( !triv,
1842
+ pol = Pol([d1,0,c,0,d/d1]);
1843
+ if( DEBUGLEVEL_ell >= 3, print(" quartic = y^2 = ",pol));
1844
+ point = ratpoint(pol,LIM1,1);
1845
+ if( point != [],
1846
+ if( DEBUGLEVEL_ell >= 2, print(" point on the quartic"));
1847
+ if( DEBUGLEVEL_ell >= 3, print( point));
1848
+ m1++;
1849
+ listpointscount = concat(listpointscount,[d1*point[1]*point]);
1850
+ if( degre(i) > lastloc, m2++);
1851
+ found = 1; lastloc = -1
1852
+ ,
1853
+ if( locallysoluble(pol),
1854
+ if( degre(i) > lastloc, m2++; lastloc = degre(i));
1855
+ \\ point = ratpoint2(pol,LIM3,1);
1856
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1857
+ \\ Instead of solving directly y^2 = d1*x^4+c*x^2+d/d1,
1858
+ \\ we solve first y^2 = d1*X^2+c*X+d/d1, then solve the quartic X = x^2
1859
+ \\ which gives a new quartic
1860
+ qf = 2*[d1,c/2,0;c/2,d/d1,0;0,0,-1];
1861
+ solqf = qfsolve(qf);
1862
+ para = qfparam(qf,solqf,2)*['x^2,'x,1]~;
1863
+ if( DEBUGLEVEL_ell >= 3,
1864
+ print(" the conic y^2 = ",Pol([d1,c,d/d1]));
1865
+ print(" is parametrized by [x,y] = "subst([para[1]/para[2],para[3]/para[2]],'x,'t)));
1866
+ point1 = ratpoint2(para[1]*para[2],LIM3,1);
1867
+ if( point1 != [],
1868
+ if(#point1 == 2,
1869
+ para = subst(para,'x,point1[1])
1870
+ , point1 = [1,point1[2]/point1[1]^2,0];
1871
+ para = vector(3,ii,polcoeff(para[ii],2))
1872
+ );
1873
+ point = [point1[2]/para[2],para[3]/para[2]];
1874
+ , point = [];
1875
+ );
1876
+ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1877
+ if( point != [],
1878
+ if( DEBUGLEVEL_ell >= 2, print(" point on the quartic"));
1879
+ if( DEBUGLEVEL_ell >= 3, print( point));
1880
+ m1++;
1881
+ listpointscount = concat(listpointscount,[d1*point[1]*point]);
1882
+ if( degre(i) > lastloc, m2++);
1883
+ found = 1; lastloc = -1
1884
+ ,
1885
+ if( DEBUGLEVEL_ell >= 2, print(" no point found on the quartic"))
1886
+ ))));
1887
+ if( found,
1888
+ found = 0;
1889
+ v = 0; iaux = (i>>1);
1890
+ while( iaux, iaux >>= 1; v++);
1891
+ mask >>= 1;
1892
+ listgen = vecextract(listgen,(1<<#listgen)-(1<<v)-1);
1893
+ i = (1<<v)
1894
+ , i++)
1895
+ );
1896
+
1897
+ for( i = 1, #listpointscount,
1898
+ if( #listpointscount[i] > 1,
1899
+ if( subst('x^3+c*'x^2+d*'x,'x,listpointscount[i][1])-listpointscount[i][2]^2 != 0,
1900
+ error(" ellcount: WRONG POINT, please report ",i))));
1901
+ if( DEBUGLEVEL_ell >= 4, print(" end of ellcount"));
1902
+
1903
+ return([listpointscount,[m1,m2]]);
1904
+ }
1905
+ {ell2descent_viaisog(ell,help=[]) =
1906
+ \\ Computation of the rank of the elliptic curve ell
1907
+ \\ having rational 2-torsion, using the algorithm via 2-isogenies.
1908
+ \\
1909
+ \\ ell must be on the form
1910
+ \\ y^2=x^3+ax^2+bx -> ell = [0,a,0,b,0]
1911
+ \\ with a and b integers.
1912
+
1913
+ my(P,Pfact,tors,listpointstriv,KS2prod,KS2gen,listpoints,pointgen,n1,n2,certain,apinit,bpinit,np1,np2,listpoints2,aux1,aux2,certainp,rang,strange);
1914
+
1915
+ if( DEBUGLEVEL_ell >= 2, print(" Algorithm of 2-descent via isogenies"));
1916
+ if( #ell < 13, ell = ellinit(ell));
1917
+
1918
+ if( ell.disc == 0,
1919
+ error(" ell2descent_viaisog: singular curve !!"));
1920
+ if( ell.a1 != 0 || ell.a3 != 0 || ell.a6 != 0,
1921
+ error(" ell2descent_viaisog: the curve is not on the form [0,a,0,b,0]"));
1922
+ if( denominator(ell.a2) > 1 || denominator(ell.a4) > 1,
1923
+ error(" ell2descent_viaisog: non-integral coefficients"));
1924
+
1925
+ \\
1926
+ \\ Working with the initial curve
1927
+ \\
1928
+
1929
+ \\ Construction of trivial points: torsion
1930
+
1931
+ P = Pol([1,ell.a2,ell.a4]);
1932
+ Pfact = factor(P)[,1];
1933
+ tors = #Pfact;
1934
+ listpointstriv = concat(help,elltorseven(ell)[3]);
1935
+
1936
+ \\ Construction of trivial points: small naive height
1937
+
1938
+ if( DEBUGLEVEL_ell >= 3, print(" Search for trivial points on the curve"));
1939
+ P *= 'x;
1940
+ if( DEBUGLEVEL_ell >= 3, print(" Y^2 = ",P));
1941
+ listpointstriv = concat( listpointstriv, ratpoint(P,LIMTRIV,0));
1942
+ if( DEBUGLEVEL_ell >= 1, print(" trivial points on E(Q) = ",listpointstriv); print());
1943
+
1944
+ KS2prod = -abs(ell.a4);
1945
+ if( ell.a2^2-4*ell.a4 < 0, KS2prod *= -1);
1946
+ KS2gen = factor(KS2prod)[,1];
1947
+
1948
+ if( DEBUGLEVEL_ell >= 2,
1949
+ print(" #K(b,2)gen = ",#KS2gen);
1950
+ print(" K(b,2)gen = ",KS2gen));
1951
+
1952
+ listpoints = ellcount(ell.a2,ell.a4,KS2gen,listpointstriv);
1953
+ pointgen = listpoints[1];
1954
+ if( DEBUGLEVEL_ell >= 1, print(" points on E(Q) = ",pointgen); print());
1955
+ n1 = listpoints[2][1]; n2 = listpoints[2][2];
1956
+
1957
+ certain = (n1 == n2);
1958
+ if( DEBUGLEVEL_ell >= 1,
1959
+ if( certain,
1960
+ print("[E(Q):phi'(E'(Q))] = ",1<<n1);
1961
+ print("#S^(phi')(E'/Q) = ",1<<n2);
1962
+ print("#III(E'/Q)[phi'] = 1"); print()
1963
+ ,
1964
+ print("[E(Q):phi'(E'(Q))] >= ",1<<n1);
1965
+ print("#S^(phi')(E'/Q) = ",1<<n2);
1966
+ print("#III(E'/Q)[phi'] <= ",1<<(n2-n1)); print())
1967
+ );
1968
+
1969
+ \\
1970
+ \\ Working with the isogeneous curve
1971
+ \\
1972
+
1973
+ apinit = -2*ell.a2; bpinit = ell.a2^2-4*ell.a4;
1974
+ KS2prod = -abs(bpinit);
1975
+ if( ell.a4 < 0, KS2prod *= -1);
1976
+ KS2gen = factor(KS2prod)[,1];
1977
+
1978
+ if( DEBUGLEVEL_ell >= 2,
1979
+ print(" #K(a^2-4b,2)gen = ",#KS2gen);
1980
+ print(" K(a^2-4b,2)gen = ",KS2gen));
1981
+
1982
+ \\ Construction of trivial points: torsion
1983
+
1984
+ P = Pol([1,apinit,bpinit]);
1985
+ listpointstriv = elltorseven([0,apinit,0,bpinit,0])[3];
1986
+
1987
+ \\ Construction of trivial points: small naive height
1988
+
1989
+ if( DEBUGLEVEL_ell >= 3, print(" Search for trivial points on the curve"));
1990
+ P *= 'x;
1991
+ if( DEBUGLEVEL_ell >= 3, print(" Y^2 = ",P));
1992
+ listpointstriv = concat( listpointstriv, ratpoint(P,LIMTRIV,0));
1993
+ if( DEBUGLEVEL_ell >= 1, print(" trivial points on E'(Q) = ",listpointstriv); print());
1994
+
1995
+ listpoints = ellcount(apinit,bpinit,KS2gen,listpointstriv);
1996
+
1997
+ if( DEBUGLEVEL_ell >= 1, print(" points on E'(Q) = ",listpoints[1]));
1998
+ np1 = listpoints[2][1]; np2 = listpoints[2][2];
1999
+ listpoints2 = vector(#listpoints[1],i,0);
2000
+ for( i = 1, #listpoints[1],
2001
+ listpoints2[i] = [0,0];
2002
+ aux1 = listpoints[1][i][1]^2;
2003
+ if( aux1 != 0,
2004
+ aux2 = listpoints[1][i][2];
2005
+ listpoints2[i][1] = aux2^2/aux1/4;
2006
+ listpoints2[i][2] = aux2*(bpinit-aux1)/aux1/8
2007
+ , listpoints2[i] = listpoints[1][i]));
2008
+ if( DEBUGLEVEL_ell >= 1, print(" points on E(Q) = ",listpoints2); print());
2009
+ pointgen = concat(pointgen,listpoints2);
2010
+
2011
+ certainp = (np1 == np2);
2012
+ if( DEBUGLEVEL_ell >= 1,
2013
+ if( certainp,
2014
+ print("[E'(Q):phi(E(Q))] = ",1<<np1);
2015
+ print("#S^(phi)(E/Q) = ",1<<np2);
2016
+ print("#III(E/Q)[phi] = 1"); print()
2017
+ ,
2018
+ print("[E'(Q):phi(E(Q))] >= ",1<<np1);
2019
+ print("#S^(phi)(E/Q) = ",1<<np2);
2020
+ print("#III(E/Q)[phi] <= ",1<<(np2-np1)); print());
2021
+
2022
+ if( !certain && (np2 > np1), print1(1<<(np2-np1)," <= "));
2023
+ print1("#III(E/Q)[2] ");
2024
+ if( certain && certainp, print1(" "), print1("<"));
2025
+ print("= ",1<<(n2+np2-n1-np1));
2026
+
2027
+ print("#E(Q)[2] = ",1<<tors);
2028
+ );
2029
+ rang = n1+np1-2;
2030
+ if( DEBUGLEVEL_ell >= 1,
2031
+ if( certain && certainp,
2032
+ print("#E(Q)/2E(Q) = ",(1<<(rang+tors)));
2033
+ print("rank = ",rang); print()
2034
+ ,
2035
+ print("#E(Q)/2E(Q) >= ",(1<<(rang+tors))); print();
2036
+ print("",rang," <= rank <= ",n2+np2-2); print()
2037
+ ));
2038
+
2039
+ strange = (n2+np2-n1-np1)%2;
2040
+ if( strange,
2041
+ if( DEBUGLEVEL_ell >= 1,
2042
+ print(" !!! III should be a square !!!"); print("hence"));
2043
+ if( certain,
2044
+ np1++;
2045
+ certainp = (np1 == np2);
2046
+ if( DEBUGLEVEL_ell >= 1,
2047
+ if( certainp,
2048
+ print("[E'(Q):phi(E(Q))] = ",1<<np1);
2049
+ print("#S^(phi)(E/Q) = ",1<<np2);
2050
+ print("#III(E/Q)[phi] = 1"); print()
2051
+ ,
2052
+ print("[E'(Q):phi(E(Q))] >= ",1<<np1);
2053
+ print("#S^(phi)(E/Q) = ",1<<np2);
2054
+ print("#III(E/Q)[phi] <= ",1<<(np2-np1)); print())
2055
+ )
2056
+ ,
2057
+ if( certainp,
2058
+ n1++;
2059
+ certain = (n1 == n2);
2060
+ if( DEBUGLEVEL_ell >= 1,
2061
+ if( certain,
2062
+ print("[E(Q):phi'(E'(Q))] = ",1<<n1);
2063
+ print("#S^(phi')(E'/Q) = ",1<<n2);
2064
+ print("#III(E'/Q)[phi'] = 1"); print()
2065
+ ,
2066
+ print("[E(Q):phi'(E'(Q))] >= ",1<<n1);
2067
+ print("#S^(phi')(E'/Q) = ",1<<n2);
2068
+ print("#III(E'/Q)[phi'] <= ",1<<(n2-n1)); print())
2069
+ )
2070
+ , n1++)
2071
+ );
2072
+
2073
+ if( DEBUGLEVEL_ell >= 1,
2074
+ print("#S^(2)(E/Q) = ",1<<(n2+np2-1));
2075
+ if( !certain && (np2 > np1), print1(" ",1<<(np2-np1)," <= "));
2076
+ print1("#III(E/Q)[2] ");
2077
+ if( certain && certainp, print1(" "), print1("<"));
2078
+ print("= ",1<<(n2+np2-n1-np1));
2079
+ print("#E(Q)[2] = ",1<<tors);
2080
+ );
2081
+ rang = n1+np1-2;
2082
+ if( DEBUGLEVEL_ell >= 1,
2083
+ if( certain && certainp,
2084
+ print("#E(Q)/2E(Q) = ",(1<<(rang+tors))); print();
2085
+ print("rank = ",rang); print()
2086
+ ,
2087
+ print("#E(Q)/2E(Q) >= ",(1<<(rang+tors))); print();
2088
+ print(rang," <= rank <= ",n2+np2-2); print())
2089
+ ));
2090
+
2091
+ \\ end of strange
2092
+
2093
+ pointgen = vecsort(pointgen,,2);
2094
+ if( ELLREDGENFLAG, pointgen = ellredgen(ell,pointgen));
2095
+ pointgen = concat(ellsort(elltorseven(ell)[3]),pointgen);
2096
+ if( DEBUGLEVEL_ell >= 1, print("points = ",pointgen));
2097
+ if( DEBUGLEVEL_ell >= 3, print(" end of ell2descent_viaisog"));
2098
+
2099
+ return([rang,n2+np2-2+tors,pointgen]);
2100
+ }
2101
+
2102
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2103
+ \\ HELP MESSAGES \\
2104
+ \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2105
+
2106
+ {
2107
+ \\ functions for elliptic curves
2108
+ addhelp(ell2descent_complete,
2109
+ "ell2descent_complete(e1,e2,e3): Performs a complete 2-descent on the elliptic curve y^2 = (x-e1)*(x-e2)*(x-e3). See ?ellQ_ellrank for the format of the output.");
2110
+ addhelp(ell2descent_gen,
2111
+ "ell2descent_gen((E,bnf,k=1,help=[]): E is a vector of the form [0,A,0,B,C], (or the result of ellinit of such a vector) A,B,C integers such that x^3+A*x^2+B*x+C; bnf is the corresponding bnfinit(,1); Performs 2-descent on the elliptic curve Ek: k*y^2=x^3+A*x^2+B*x+C. See ?ellQ_ellrank for the format of the output.");
2112
+ addhelp(ell2descent_viaisog,
2113
+ "ell2descent_viaisog(E,help=[]): E is an elliptic curve of the form [0,a,0,b,0], with a, b integers. Performs a 2-descent via isogeny on E. See ?ellQ_ellrank for the format of the output.");
2114
+ addhelp(ellQ_ellrank,
2115
+ "ellQ_ellrank(E,help=[]): E is any elliptic curve defined over Q. Returns a vector [r,s,v], where r is a lower bound for the rank of E, s is the rank of its 2-Selmer group and v is a list of independant points in E(Q)/2E(Q). If help is a vector of nontrivial points on E, the result might be faster. This function might be used in conjunction with elltors2(E). See also ?default_ellQ");
2116
+ addhelp(ellhalf,
2117
+ "ellhalf(E,P): returns the vector of all points Q on the elliptic curve E such that 2Q = P");
2118
+ addhelp(ellredgen,
2119
+ "ellredgen(E,v): returns a vector of smallest possible points on the elliptic curve E generating the same subgroup as v, up to torsion.");
2120
+ addhelp(ellsort,
2121
+ "ellsort(v): v being a vector of points on some elliptic curve, returns the vector v sorted according to the naive height.");
2122
+ addhelp(elltors2,
2123
+ "elltors2(E): for an elliptic curve E, returns the group E(K)[2], where K is the field of definition of the coefficients of E (Q, R, Qp or Fp).");
2124
+ addhelp(elltorseven,
2125
+ "elltorseven(E): for an elliptic curve E, returns 2-Sylow subgroup of E(K)_tors, where K is the field of definition of the coefficients of E: (Q, R, Qp or Fp).");
2126
+
2127
+
2128
+ \\ functions for polynomials
2129
+ addhelp(locallysoluble,
2130
+ "locallysoluble(pol): returns 1 if y^2=pol(x) is everywhere locally soluble, 0 otherwise.");
2131
+ addhelp(ratpoint,
2132
+ "ratpoint(pol,lim=1,singlepoint=1): search for rational points on y^2=pol(x), for about within the bounds given by lim. The coefficients of pol must be integral. If singlepoint=1, returns at most one point, otherwise as many as possible.");
2133
+ addhelp(redquartic,
2134
+ "redquartic(pol): reduction of the quartic pol using Cremona-Stoll algorithm. Returns [p,M], where p is the reduced quartic and M is the GL2(Z) transformation. Also works with other degree polynomials.");
2135
+
2136
+
2137
+ \\ functions for number fields
2138
+ addhelp(bnfpSelmer,
2139
+ "bnfpSelmer(K,S,p): K being a number field given by bnfinit, S an ideal of K, and p a prime number, computes a set of generators of the group K(S,p) = { x in K^* / K^*^p, v_P(x) = 0 (mod p) for all P coprime to S}");
2140
+ addhelp(reducemodsquares,
2141
+ "reducemodsquares(delta,d): delta being a t_POLMOD, returns another delta'=delta*z^2, such that delta' has a small coefficient in x^d.");
2142
+
2143
+
2144
+ \\ others
2145
+ addhelp(default_ellQ,
2146
+ "default_ellQ(DEBUGLEVEL_ell, LIM1, LIM3, LIMTRIV, ELLREDGENFLAG, COMPLETE, MAXPROB, LIMBIGPRIME): set the value of the global variables used for ellQ_ellrank() and other related functions. DEBUGLEVEL_ell: 0-5: choose the quantity of information printed during the computation (default=0: print nothing); LIM1 (resp LIM3): search limit for easy (resp hard) points on quartics; LIMTRIV: search limit for trivial points on elliptic curves; ELLREDGENFLAG: if != 0, try to reduce the generators at the end; COMPLETE: if != 0 and full 2-torsion, use complete 2-descent, otherwise via 2-isogeny; MAXPROB, LIMBIGPRIME: technical.");
2147
+ /* addhelp(DEBUGLEVEL_ell,
2148
+ "DEBUGLEVEL_ell: Choose a higher value of this global variable to have more details of the computations printed during the 2-descent algorithm. 0 = don't print anything; 1 = (default) just print the result; 2 = print more details including the Selmer group and the nontrivial quartics.");
2149
+ */
2150
+ }
2151
+