passagemath-schemes 10.8.1a4__cp314-cp314t-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.8.1a4.dist-info/METADATA +203 -0
  7. passagemath_schemes-10.8.1a4.dist-info/METADATA.bak +204 -0
  8. passagemath_schemes-10.8.1a4.dist-info/RECORD +312 -0
  9. passagemath_schemes-10.8.1a4.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.8.1a4.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9556 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2578 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +727 -0
  29. sage/lfunctions/pari.py +971 -0
  30. sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5132 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +414 -0
  34. sage/modular/abvar/abvar_newform.py +246 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +187 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +721 -0
  40. sage/modular/abvar/homspace.py +989 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +741 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1406 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +361 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +659 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1491 -0
  57. sage/modular/arithgroup/congroup_generic.py +630 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +266 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1067 -0
  61. sage/modular/arithgroup/tests.py +425 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3736 -0
  64. sage/modular/btquotients/pautomorphicform.py +2564 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1107 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +571 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1076 -0
  77. sage/modular/hecke/algebra.py +725 -0
  78. sage/modular/hecke/all.py +19 -0
  79. sage/modular/hecke/ambient_module.py +994 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +302 -0
  82. sage/modular/hecke/hecke_operator.py +736 -0
  83. sage/modular/hecke/homspace.py +185 -0
  84. sage/modular/hecke/module.py +1744 -0
  85. sage/modular/hecke/morphism.py +139 -0
  86. sage/modular/hecke/submodule.py +970 -0
  87. sage/modular/hypergeometric_misc.cpython-314t-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2020 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1070 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +817 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +120 -0
  101. sage/modular/modform/ambient_g1.py +199 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +487 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4105 -0
  108. sage/modular/modform/half_integral.py +154 -0
  109. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  110. sage/modular/modform/j_invariant.py +47 -0
  111. sage/modular/modform/l_series_gross_zagier.py +127 -0
  112. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314t-darwin.so +0 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  114. sage/modular/modform/notes.py +45 -0
  115. sage/modular/modform/numerical.py +514 -0
  116. sage/modular/modform/periods.py +14 -0
  117. sage/modular/modform/ring.py +1257 -0
  118. sage/modular/modform/space.py +1859 -0
  119. sage/modular/modform/submodule.py +118 -0
  120. sage/modular/modform/tests.py +64 -0
  121. sage/modular/modform/theta.py +110 -0
  122. sage/modular/modform/vm_basis.py +380 -0
  123. sage/modular/modform/weight1.py +221 -0
  124. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  125. sage/modular/modform_hecketriangle/abstract_space.py +2527 -0
  126. sage/modular/modform_hecketriangle/all.py +30 -0
  127. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  128. sage/modular/modform_hecketriangle/constructor.py +416 -0
  129. sage/modular/modform_hecketriangle/element.py +351 -0
  130. sage/modular/modform_hecketriangle/functors.py +752 -0
  131. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  132. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  133. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3349 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1426 -0
  135. sage/modular/modform_hecketriangle/readme.py +1214 -0
  136. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  137. sage/modular/modform_hecketriangle/space.py +1037 -0
  138. sage/modular/modform_hecketriangle/subspace.py +423 -0
  139. sage/modular/modsym/all.py +17 -0
  140. sage/modular/modsym/ambient.py +3844 -0
  141. sage/modular/modsym/boundary.py +1420 -0
  142. sage/modular/modsym/element.py +336 -0
  143. sage/modular/modsym/g1list.py +178 -0
  144. sage/modular/modsym/ghlist.py +182 -0
  145. sage/modular/modsym/hecke_operator.py +73 -0
  146. sage/modular/modsym/manin_symbol.cpython-314t-darwin.so +0 -0
  147. sage/modular/modsym/manin_symbol.pxd +5 -0
  148. sage/modular/modsym/manin_symbol.pyx +497 -0
  149. sage/modular/modsym/manin_symbol_list.py +1291 -0
  150. sage/modular/modsym/modsym.py +400 -0
  151. sage/modular/modsym/modular_symbols.py +384 -0
  152. sage/modular/modsym/p1list_nf.py +1241 -0
  153. sage/modular/modsym/relation_matrix.py +591 -0
  154. sage/modular/modsym/relation_matrix_pyx.cpython-314t-darwin.so +0 -0
  155. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  156. sage/modular/modsym/space.py +2468 -0
  157. sage/modular/modsym/subspace.py +455 -0
  158. sage/modular/modsym/tests.py +376 -0
  159. sage/modular/multiple_zeta.py +2635 -0
  160. sage/modular/multiple_zeta_F_algebra.py +789 -0
  161. sage/modular/overconvergent/all.py +6 -0
  162. sage/modular/overconvergent/genus0.py +1879 -0
  163. sage/modular/overconvergent/hecke_series.py +1187 -0
  164. sage/modular/overconvergent/weightspace.py +776 -0
  165. sage/modular/pollack_stevens/all.py +4 -0
  166. sage/modular/pollack_stevens/distributions.py +874 -0
  167. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  168. sage/modular/pollack_stevens/manin_map.py +856 -0
  169. sage/modular/pollack_stevens/modsym.py +1590 -0
  170. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  171. sage/modular/pollack_stevens/sigma0.py +534 -0
  172. sage/modular/pollack_stevens/space.py +1078 -0
  173. sage/modular/quasimodform/all.py +3 -0
  174. sage/modular/quasimodform/element.py +846 -0
  175. sage/modular/quasimodform/ring.py +826 -0
  176. sage/modular/quatalg/all.py +3 -0
  177. sage/modular/quatalg/brandt.py +1642 -0
  178. sage/modular/ssmod/all.py +8 -0
  179. sage/modular/ssmod/ssmod.py +827 -0
  180. sage/rings/all__sagemath_schemes.py +1 -0
  181. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/binary_form_reduce.py +585 -0
  183. sage/schemes/all.py +41 -0
  184. sage/schemes/berkovich/all.py +6 -0
  185. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  186. sage/schemes/berkovich/berkovich_space.py +700 -0
  187. sage/schemes/curves/affine_curve.py +2924 -0
  188. sage/schemes/curves/all.py +33 -0
  189. sage/schemes/curves/closed_point.py +434 -0
  190. sage/schemes/curves/constructor.py +397 -0
  191. sage/schemes/curves/curve.py +542 -0
  192. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  193. sage/schemes/curves/point.py +463 -0
  194. sage/schemes/curves/projective_curve.py +3203 -0
  195. sage/schemes/curves/weighted_projective_curve.py +106 -0
  196. sage/schemes/curves/zariski_vankampen.py +1931 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +991 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1103 -0
  208. sage/schemes/elliptic_curves/constructor.py +1530 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3971 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +457 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2837 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3249 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4944 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7184 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1663 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7328 -0
  229. sage/schemes/elliptic_curves/height.py +2108 -0
  230. sage/schemes/elliptic_curves/hom.py +1788 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +1084 -0
  232. sage/schemes/elliptic_curves/hom_fractional.py +544 -0
  233. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  234. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  235. sage/schemes/elliptic_curves/hom_sum.py +681 -0
  236. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  237. sage/schemes/elliptic_curves/homset.py +271 -0
  238. sage/schemes/elliptic_curves/isogeny_class.py +1523 -0
  239. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  240. sage/schemes/elliptic_curves/jacobian.py +247 -0
  241. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  242. sage/schemes/elliptic_curves/kraus.py +1014 -0
  243. sage/schemes/elliptic_curves/lseries_ell.py +915 -0
  244. sage/schemes/elliptic_curves/mod5family.py +105 -0
  245. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.cpython-314t-darwin.so +0 -0
  247. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  248. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  249. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  250. sage/schemes/elliptic_curves/padics.py +1816 -0
  251. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.cpython-314t-darwin.so +0 -0
  253. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  254. sage/schemes/elliptic_curves/saturation.py +716 -0
  255. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  256. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  257. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  258. sage/schemes/hyperelliptic_curves/all.py +6 -0
  259. sage/schemes/hyperelliptic_curves/constructor.py +369 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1948 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +936 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  265. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +312 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_generic.py +437 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +878 -0
  271. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  272. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  273. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3863 -0
  274. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  275. sage/schemes/jacobians/all.py +2 -0
  276. sage/schemes/overview.py +161 -0
  277. sage/schemes/plane_conics/all.py +22 -0
  278. sage/schemes/plane_conics/con_field.py +1296 -0
  279. sage/schemes/plane_conics/con_finite_field.py +158 -0
  280. sage/schemes/plane_conics/con_number_field.py +456 -0
  281. sage/schemes/plane_conics/con_rational_field.py +406 -0
  282. sage/schemes/plane_conics/con_rational_function_field.py +581 -0
  283. sage/schemes/plane_conics/constructor.py +249 -0
  284. sage/schemes/plane_quartics/all.py +2 -0
  285. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  286. sage/schemes/plane_quartics/quartic_generic.py +53 -0
  287. sage/schemes/riemann_surfaces/all.py +1 -0
  288. sage/schemes/riemann_surfaces/riemann_surface.py +4177 -0
  289. sage_wheels/share/cremona/cremona_mini.db +0 -0
  290. sage_wheels/share/ellcurves/rank0 +30427 -0
  291. sage_wheels/share/ellcurves/rank1 +31871 -0
  292. sage_wheels/share/ellcurves/rank10 +6 -0
  293. sage_wheels/share/ellcurves/rank11 +6 -0
  294. sage_wheels/share/ellcurves/rank12 +1 -0
  295. sage_wheels/share/ellcurves/rank14 +1 -0
  296. sage_wheels/share/ellcurves/rank15 +1 -0
  297. sage_wheels/share/ellcurves/rank17 +1 -0
  298. sage_wheels/share/ellcurves/rank19 +1 -0
  299. sage_wheels/share/ellcurves/rank2 +2388 -0
  300. sage_wheels/share/ellcurves/rank20 +1 -0
  301. sage_wheels/share/ellcurves/rank21 +1 -0
  302. sage_wheels/share/ellcurves/rank22 +1 -0
  303. sage_wheels/share/ellcurves/rank23 +1 -0
  304. sage_wheels/share/ellcurves/rank24 +1 -0
  305. sage_wheels/share/ellcurves/rank28 +1 -0
  306. sage_wheels/share/ellcurves/rank3 +836 -0
  307. sage_wheels/share/ellcurves/rank4 +10 -0
  308. sage_wheels/share/ellcurves/rank5 +5 -0
  309. sage_wheels/share/ellcurves/rank6 +5 -0
  310. sage_wheels/share/ellcurves/rank7 +5 -0
  311. sage_wheels/share/ellcurves/rank8 +6 -0
  312. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,1723 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs database_cremona_mini_ellcurve
3
+ """
4
+ Cremona's tables of elliptic curves
5
+
6
+ Sage includes John Cremona's tables of elliptic curves in an
7
+ easy-to-use format. An instance of the class CremonaDatabase()
8
+ gives access to the database.
9
+
10
+ If the optional full CremonaDatabase is not installed, a mini-version
11
+ is included by default with Sage. It contains Weierstrass equations,
12
+ rank, and torsion for curves up to conductor 10000.
13
+
14
+ The large database includes all curves in John Cremona's tables. It also
15
+ includes data related to the BSD conjecture and modular degrees for all of
16
+ these curves, and generators for the Mordell-Weil groups. To install it via the
17
+ optional :ref:`database_cremona_ellcurve <spkg_database_cremona_ellcurve>`
18
+ package, run the following command in the shell ::
19
+
20
+ sage -i database_cremona_ellcurve
21
+
22
+ This causes the latest version of the database to be downloaded from
23
+ the internet.
24
+
25
+ Both the mini and full versions of John Cremona's tables are stored
26
+ as SQLite databases. The mini version has the layout::
27
+
28
+ CREATE TABLE t_class(conductor INTEGER, class TEXT PRIMARY KEY, rank INTEGER);
29
+ CREATE TABLE t_curve(class TEXT, curve TEXT PRIMARY KEY, eqn TEXT UNIQUE, tors INTEGER);
30
+ CREATE INDEX i_t_class_conductor ON t_class(conductor);
31
+ CREATE INDEX i_t_curve_class ON t_curve(class);
32
+
33
+ while the full version has the layout::
34
+
35
+ CREATE TABLE t_class(conductor INTEGER, class TEXT PRIMARY KEY, rank INTEGER, L REAL, deg INTEGER);
36
+ CREATE TABLE t_curve(class TEXT, curve TEXT PRIMARY KEY, eqn TEXT UNIQUE, gens TEXT, tors INTEGER, cp INTEGER, om REAL, reg REAL, sha);
37
+ CREATE INDEX i_t_class_conductor ON t_class(conductor);
38
+ CREATE INDEX i_t_curve_class ON t_curve(class);
39
+ """
40
+ # ****************************************************************************
41
+ # Copyright (C) 2014 John Cremona <john.cremona@gmail.com>
42
+ # Copyright (C) 2011 R. Andrew Ohana <andrew.ohana@gmail.com>
43
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
44
+ #
45
+ # Distributed under the terms of the GNU General Public License (GPL)
46
+ # as published by the Free Software Foundation; either version 2 of
47
+ # the License, or (at your option) any later version.
48
+ # https://www.gnu.org/licenses/
49
+ # ****************************************************************************
50
+
51
+ import os
52
+ from sage.misc.prandom import randint
53
+
54
+ import sage.schemes.elliptic_curves.constructor as elliptic
55
+ from .sql_db import SQLDatabase, verify_column
56
+ from sage.features.databases import DatabaseCremona
57
+ from sage.misc.timing import walltime
58
+
59
+ import re
60
+ import string
61
+
62
+ _cremonaSkeleton = {
63
+ 't_class': {
64
+ 'conductor': {'sql':'INTEGER', 'index':True},
65
+ 'class': {'sql':'TEXT', 'primary_key':True},
66
+ 'rank': {'sql':'INTEGER'},
67
+ 'L': {'sql':'REAL'},
68
+ 'deg': {'sql':'INTEGER'}
69
+ },
70
+ 't_curve': {
71
+ 'class': {'sql':'TEXT', 'index':True},
72
+ 'curve': {'sql':'TEXT', 'primary_key':True},
73
+ 'eqn': {'sql':'TEXT', 'unique':True},
74
+ 'gens': {'sql':'TEXT'},
75
+ 'tors': {'sql':'INTEGER'},
76
+ 'cp': {'sql':'INTEGER'},
77
+ 'om': {'sql':'REAL'},
78
+ 'reg': {'sql':'REAL'},
79
+ 'sha': {'sql':'NOTYPE'}
80
+ }
81
+ }
82
+ _miniCremonaSkeleton = {
83
+ 't_class': {
84
+ 'conductor': {'sql':'INTEGER', 'index':True},
85
+ 'class': {'sql':'TEXT', 'primary_key':True},
86
+ 'rank': {'sql':'INTEGER'}
87
+ },
88
+ 't_curve': {
89
+ 'class': {'sql':'TEXT', 'index':True},
90
+ 'curve': {'sql':'TEXT', 'primary_key':True},
91
+ 'eqn': {'sql':'TEXT', 'unique':True},
92
+ 'tors': {'sql':'INTEGER'}
93
+ }
94
+ }
95
+
96
+ for t in _cremonaSkeleton:
97
+ for c in _cremonaSkeleton[t]:
98
+ _cremonaSkeleton[t][c] = verify_column(_cremonaSkeleton[t][c])
99
+ for c in _miniCremonaSkeleton[t]:
100
+ _miniCremonaSkeleton[t][c] = verify_column(_miniCremonaSkeleton[t][c])
101
+
102
+
103
+ def build(name, data_tgz, largest_conductor=0, mini=False, decompress=True):
104
+ """
105
+ Build the CremonaDatabase with given name from scratch
106
+ using the data_tgz tarball.
107
+
108
+ .. NOTE::
109
+
110
+ For data up to level 350000, this function takes about
111
+ 3m40s. The resulting database occupies 426MB disk space.
112
+
113
+ To create the large Cremona database from Cremona's data_tgz
114
+ tarball, obtainable from
115
+ http://homepages.warwick.ac.uk/staff/J.E.Cremona/ftp/data/, run
116
+ the following command::
117
+
118
+ sage: d = sage.databases.cremona.build('cremona','ecdata.tgz') # not tested
119
+ """
120
+ from sage.env import DOT_SAGE
121
+ db_path = os.path.join(DOT_SAGE, 'db', 'cremona', name.replace(' ','_')+'.db')
122
+ if os.path.exists(db_path):
123
+ raise RuntimeError('Please (re)move %s before building ' % db_path
124
+ + 'database')
125
+ if not os.path.exists(data_tgz):
126
+ raise OSError("The data file is not at %s" % data_tgz)
127
+ t = walltime()
128
+
129
+ if decompress:
130
+ cmd = "tar zxf {} ecdata/allcurves ecdata/allbsd ecdata/degphi ecdata/allgens".format(data_tgz)
131
+ print("Extracting files from {}...".format(data_tgz))
132
+ n = os.system(cmd)
133
+ if n:
134
+ raise RuntimeError("Error extracting tarball.")
135
+ else:
136
+ print("...finished file extraction")
137
+ if mini:
138
+ c = MiniCremonaDatabase(name,False,True)
139
+ else:
140
+ c = LargeCremonaDatabase(name,False,True)
141
+ # The following line assumes that the tarball extracts to a
142
+ # directory called 'ecdata'
143
+ c._init_from_ftpdata('ecdata', largest_conductor)
144
+ print("Total time: ", walltime(t))
145
+
146
+
147
+ def is_optimal_id(id):
148
+ """
149
+ Return ``True`` if the Cremona id refers to an optimal curve, and
150
+ ``False`` otherwise.
151
+
152
+ The curve is optimal if the id, which is of the
153
+ form [letter code][number] has number 1.
154
+
155
+ .. NOTE::
156
+
157
+ 990h3 is the optimal curve in that class, so doesn't obey
158
+ this rule.
159
+
160
+ INPUT:
161
+
162
+ - ``id`` -- string of form letter code followed by an
163
+ integer, e.g., a3, bb5, etc.
164
+
165
+ OUTPUT: boolean
166
+
167
+ EXAMPLES::
168
+
169
+ sage: from sage.databases.cremona import is_optimal_id
170
+ sage: is_optimal_id('b1')
171
+ True
172
+ sage: is_optimal_id('bb1')
173
+ True
174
+ sage: is_optimal_id('c1')
175
+ True
176
+ sage: is_optimal_id('c2')
177
+ False
178
+ """
179
+ return id[-1] == '1' and not id[-2].isdigit()
180
+
181
+
182
+ def cremona_letter_code(n) -> str:
183
+ """
184
+ Return the Cremona letter code corresponding to an integer.
185
+
186
+ For example, 0 - a 25 - z 26 - ba 51 - bz 52 - ca 53 - cb etc.
187
+
188
+ .. NOTE::
189
+
190
+ This is just the base 26 representation of n, where a=0, b=1,
191
+ ..., z=25. This extends the old Cremona notation (counting from
192
+ 0) for the first 26 classes, and is different for classes above
193
+ 26.
194
+
195
+ INPUT:
196
+
197
+ - ``n`` -- nonnegative integer
198
+
199
+ OUTPUT: string
200
+
201
+ EXAMPLES::
202
+
203
+ sage: from sage.databases.cremona import cremona_letter_code
204
+ sage: cremona_letter_code(0)
205
+ 'a'
206
+ sage: cremona_letter_code(26)
207
+ 'ba'
208
+ sage: cremona_letter_code(27)
209
+ 'bb'
210
+ sage: cremona_letter_code(521)
211
+ 'ub'
212
+ sage: cremona_letter_code(53)
213
+ 'cb'
214
+ sage: cremona_letter_code(2005)
215
+ 'czd'
216
+
217
+ TESTS::
218
+
219
+ sage: cremona_letter_code(QQ)
220
+ Traceback (most recent call last):
221
+ ...
222
+ ValueError: Cremona letter codes are only defined for nonnegative integers
223
+ sage: cremona_letter_code(x) # needs sage.symbolic
224
+ Traceback (most recent call last):
225
+ ...
226
+ ValueError: Cremona letter codes are only defined for nonnegative integers
227
+ sage: cremona_letter_code(-1)
228
+ Traceback (most recent call last):
229
+ ...
230
+ ValueError: Cremona letter codes are only defined for nonnegative integers
231
+ sage: cremona_letter_code(3.14159)
232
+ Traceback (most recent call last):
233
+ ...
234
+ ValueError: Cremona letter codes are only defined for nonnegative integers
235
+ """
236
+ try:
237
+ m = int(n)
238
+ if n == m:
239
+ n = m
240
+ else:
241
+ n = -1
242
+ except (ValueError, TypeError):
243
+ n = -1
244
+
245
+ if n < 0:
246
+ raise ValueError("Cremona letter codes are only defined for nonnegative integers")
247
+
248
+ if n == 0:
249
+ return "a"
250
+ s = ""
251
+ while n != 0:
252
+ s = chr(n % 26+97) + s
253
+ n //= 26
254
+ return s
255
+
256
+
257
+ def old_cremona_letter_code(n) -> str:
258
+ r"""
259
+ Return the *old* Cremona letter code corresponding to an integer.
260
+
261
+ For example::
262
+
263
+ 1 --> A
264
+ 26 --> Z
265
+ 27 --> AA
266
+ 52 --> ZZ
267
+ 53 --> AAA
268
+ etc.
269
+
270
+ INPUT:
271
+
272
+ - ``n`` -- integer
273
+
274
+ OUTPUT: string
275
+
276
+ EXAMPLES::
277
+
278
+ sage: from sage.databases.cremona import old_cremona_letter_code
279
+ sage: old_cremona_letter_code(1)
280
+ 'A'
281
+ sage: old_cremona_letter_code(26)
282
+ 'Z'
283
+ sage: old_cremona_letter_code(27)
284
+ 'AA'
285
+ sage: old_cremona_letter_code(521)
286
+ 'AAAAAAAAAAAAAAAAAAAAA'
287
+ sage: old_cremona_letter_code(53)
288
+ 'AAA'
289
+ sage: old_cremona_letter_code(2005)
290
+ 'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC'
291
+ """
292
+ n -= 1
293
+ k = n % 26 + 65
294
+ label = chr(k)*int(n//26 + 1)
295
+ return label
296
+
297
+
298
+ old_cremona_label_regex = re.compile(r'(\d+)([A-Z]*)(\d*)$')
299
+ cremona_label_regex = re.compile(r'(\d+)([a-z]*)(\d*)$')
300
+ lmfdb_label_regex = re.compile(r'(\d+)\.([a-z]+)(\d*)$')
301
+
302
+
303
+ def parse_cremona_label(label, numerical_class_code=False):
304
+ """
305
+ Given a Cremona label that defines an elliptic
306
+ curve, e.g., 11a1 or 37b3, parse the label and return the
307
+ conductor, isogeny class label, and number.
308
+
309
+ For this function, the curve number may be omitted, in which case
310
+ it defaults to 1. If the curve number and isogeny class are both
311
+ omitted (label is just a string representing a conductor), then
312
+ the isogeny class defaults to 'a' and the number to 1. Valid
313
+ labels consist of one or more digits, followed by zero or more
314
+ letters (either all in upper case for an old Cremona label, or all
315
+ in lower case), followed by zero or more digits.
316
+
317
+ INPUT:
318
+
319
+ - ``label`` -- string; a valid Cremona elliptic curve label
320
+
321
+ - ``numerical_class_code`` -- boolean (default: ``False``); if ``True``,
322
+ convert the isogeny class label from a letter code in base 26
323
+ to an integer. This is useful for sorting.
324
+
325
+ OUTPUT:
326
+
327
+ - integer; the conductor
328
+ - string or integer; the isogeny class label
329
+ - integer; the number
330
+
331
+ EXAMPLES::
332
+
333
+ sage: from sage.databases.cremona import parse_cremona_label
334
+ sage: parse_cremona_label('37a2')
335
+ (37, 'a', 2)
336
+ sage: parse_cremona_label('37b1')
337
+ (37, 'b', 1)
338
+ sage: parse_cremona_label('10bb2')
339
+ (10, 'bb', 2)
340
+ sage: parse_cremona_label('11a')
341
+ (11, 'a', 1)
342
+ sage: parse_cremona_label('11')
343
+ (11, 'a', 1)
344
+
345
+ Valid old Cremona labels are allowed::
346
+
347
+ sage: parse_cremona_label('17CCCC')
348
+ (17, 'dc', 1)
349
+ sage: parse_cremona_label('5AB2')
350
+ Traceback (most recent call last):
351
+ ...
352
+ ValueError: 5AB2 is not a valid Cremona label
353
+
354
+ When ``numerical_class_code`` is ``True``, the output is a triple of integers::
355
+
356
+ sage: from sage.databases.cremona import parse_cremona_label
357
+ sage: parse_cremona_label('100800hj2')
358
+ (100800, 'hj', 2)
359
+ sage: parse_cremona_label('100800hj2', numerical_class_code=True)
360
+ (100800, 191, 2)
361
+
362
+ TESTS::
363
+
364
+ sage: from sage.databases.cremona import parse_cremona_label
365
+ sage: parse_cremona_label('x11')
366
+ Traceback (most recent call last):
367
+ ...
368
+ ValueError: x11 is not a valid Cremona label
369
+ """
370
+ m = cremona_label_regex.match(str(label))
371
+ if m is None:
372
+ m = old_cremona_label_regex.match(str(label))
373
+ if m is None:
374
+ raise ValueError(label + " is not a valid Cremona label")
375
+
376
+ conductor, iso, num = m.groups()
377
+ if len(iso) == 0:
378
+ iso = "a"
379
+ if len(num) == 0:
380
+ num = "1"
381
+
382
+ # convert old cremona labels to new ones
383
+ if iso.upper() == iso and iso[0]*len(iso) == iso:
384
+ iso = cremona_letter_code((len(iso)-1)*26+ord(iso[0])-ord('A'))
385
+
386
+ # verify cremona label is valid
387
+ if iso.lower() != iso:
388
+ raise ValueError('%s is not a valid Cremona label' % label)
389
+
390
+ # convert class label to an int if requested
391
+ if numerical_class_code:
392
+ iso = class_to_int(iso)
393
+
394
+ return int(conductor), iso, int(num)
395
+
396
+
397
+ def parse_lmfdb_label(label, numerical_class_code=False):
398
+ """
399
+ Given an LMFDB label that defines an elliptic curve, e.g., 11.a1
400
+ or 37.b3, parse the label and return the conductor, isogeny class
401
+ label, and number.
402
+
403
+ The LMFDB label (named after the `L`-functions and modular forms
404
+ database), is determined by the following two orders:
405
+
406
+ - Isogeny classes with the same conductor are ordered
407
+ lexicographically by the coefficients in the `q`-expansion of the
408
+ associated modular form.
409
+
410
+ - Curves within the same isogeny class are ordered
411
+ lexicographically by the a-invariants of the minimal model.
412
+
413
+ The format is <conductor>.<iso><curve>, where the isogeny class is
414
+ encoded using the same base-26 encoding into letters used in
415
+ Cremona's labels. For example, 990.h3 is the same as Cremona's 990j1
416
+
417
+ For this function, the curve number may be omitted, in which case
418
+ it defaults to 1. If the curve number and isogeny class are both
419
+ omitted (label is just a string representing a conductor), then
420
+ the isogeny class defaults to 'a' and the number to 1.
421
+
422
+ INPUT:
423
+
424
+ - ``label`` -- str
425
+
426
+ - ``numerical_class_code`` -- boolean (default: ``False``); if ``True``,
427
+ convert the isogeny class label from a letter code in base 26
428
+ to an integer. This is useful for sorting.
429
+
430
+ OUTPUT:
431
+
432
+ - ``int`` -- the conductor
433
+ - ``str`` or ``int`` -- the isogeny class label
434
+ - ``int`` -- the number
435
+
436
+ EXAMPLES::
437
+
438
+ sage: from sage.databases.cremona import parse_lmfdb_label
439
+ sage: parse_lmfdb_label('37.a2')
440
+ (37, 'a', 2)
441
+ sage: parse_lmfdb_label('37.b')
442
+ (37, 'b', 1)
443
+ sage: parse_lmfdb_label('10.bb2')
444
+ (10, 'bb', 2)
445
+
446
+ When ``numerical_class_code`` is ``True``, the output is a triple of integers::
447
+
448
+ sage: from sage.databases.cremona import parse_lmfdb_label
449
+ sage: parse_lmfdb_label('100800.bg4')
450
+ (100800, 'bg', 4)
451
+ sage: parse_lmfdb_label('100800.bg4', numerical_class_code=True)
452
+ (100800, 32, 4)
453
+ """
454
+ m = lmfdb_label_regex.match(str(label).lower())
455
+ if m is None:
456
+ raise ValueError(label + " is not a valid LMFDB label")
457
+ conductor, iso, num = m.groups()
458
+ if len(iso) == 0:
459
+ iso = "a"
460
+ if len(num) == 0:
461
+ num = "1"
462
+ # convert class label to an int if requested
463
+ if numerical_class_code:
464
+ iso = class_to_int(iso)
465
+
466
+ return int(conductor), iso, int(num)
467
+
468
+
469
+ _class_curve_re = re.compile(r'(?P<class>[a-z]+)(?P<curve>\d+)')
470
+
471
+
472
+ def split_code(key):
473
+ """
474
+ Split class + curve id string into its two parts.
475
+
476
+ EXAMPLES::
477
+
478
+ sage: import sage.databases.cremona as cremona
479
+ sage: cremona.split_code('ba2')
480
+ ('ba', '2')
481
+ sage: cremona.split_code('42')
482
+ Traceback (most recent call last):
483
+ ...
484
+ ValueError: invalid curve ID: '42'
485
+ """
486
+ m = _class_curve_re.match(key)
487
+
488
+ if not m:
489
+ raise ValueError("invalid curve ID: '{0}'".format(key))
490
+
491
+ return (m.group('class'), m.group('curve'))
492
+
493
+
494
+ def class_to_int(k):
495
+ """
496
+ Convert class id string into an integer.
497
+
498
+ Note that this is the inverse of :func:`cremona_letter_code`.
499
+
500
+ EXAMPLES::
501
+
502
+ sage: import sage.databases.cremona as cremona
503
+ sage: cremona.class_to_int('ba')
504
+ 26
505
+ sage: cremona.class_to_int('cremona')
506
+ 821863562
507
+ sage: cremona.cremona_letter_code(821863562)
508
+ 'cremona'
509
+ """
510
+ kk = [string.ascii_lowercase.index(ch) for ch in list(k)]
511
+ kk.reverse()
512
+ return sum(kk[i] * 26 ** i for i in range(len(kk)))
513
+
514
+
515
+ def sort_key(key1):
516
+ """
517
+ Comparison key for curve id strings.
518
+
519
+ .. NOTE::
520
+
521
+ Not the same as standard lexicographic order!
522
+
523
+ EXAMPLES::
524
+
525
+ sage: from sage.databases.cremona import sort_key
526
+ sage: l = ['ba1', 'z1']
527
+ sage: sorted(l, key=sort_key)
528
+ ['z1', 'ba1']
529
+ """
530
+ cl1, cu1 = split_code(key1)
531
+ return (class_to_int(cl1), cu1)
532
+
533
+
534
+ def cremona_to_lmfdb(cremona_label, CDB=None):
535
+ """
536
+ Convert a Cremona label into an LMFDB label.
537
+
538
+ See :func:`parse_lmfdb_label` for an explanation of LMFDB labels.
539
+
540
+ INPUT:
541
+
542
+ - ``cremona_label`` -- string, the Cremona label of a curve; this can be
543
+ the label of a curve (e.g. '990j1') or of an isogeny class (e.g. '990j')
544
+ - ``CDB`` -- the Cremona database in which to look up the isogeny
545
+ classes of the same conductor
546
+
547
+ OUTPUT: ``lmfdb_label``; string, the corresponding LMFDB label
548
+
549
+ EXAMPLES::
550
+
551
+ sage: from sage.databases.cremona import cremona_to_lmfdb, lmfdb_to_cremona
552
+ sage: cremona_to_lmfdb('990j1')
553
+ '990.h3'
554
+ sage: lmfdb_to_cremona('990.h3')
555
+ '990j1'
556
+
557
+ TESTS::
558
+
559
+ sage: for label in ['5077a1','66a3','102b','420c2']:
560
+ ....: assert(lmfdb_to_cremona(cremona_to_lmfdb(label)) == label)
561
+ sage: for label in ['438.c2','306.b','462.f3']:
562
+ ....: assert(cremona_to_lmfdb(lmfdb_to_cremona(label)) == label)
563
+ """
564
+ from sage.libs.pari import pari
565
+ m = cremona_label_regex.match(cremona_label)
566
+ if m is None:
567
+ raise ValueError("Invalid Cremona label")
568
+ N, cremona_iso, cremona_number = m.groups()
569
+ if CDB is None:
570
+ CDB = CremonaDatabase()
571
+ classes = CDB.isogeny_classes(N)
572
+ ft = 53
573
+ tff = 255 # This should be enough to distinguish between curves (using heuristics from Sato-Tate for example)
574
+ isos = []
575
+ for i, iso in enumerate(classes):
576
+ alist = iso[0][0]
577
+ E = pari(alist).ellinit(precision=ft)
578
+ isos.append((E.ellan(tff, python_ints=True), cremona_letter_code(i)))
579
+ isos.sort()
580
+ sorted_letters = [iso[1] for iso in isos]
581
+ lmfdb_iso = cremona_letter_code(sorted_letters.index(cremona_iso))
582
+ if len(cremona_number) > 0:
583
+ iso_class = sorted([(curve[0],str(i+1)) for i,curve in enumerate(classes[class_to_int(cremona_iso)])])
584
+ sorted_numbers = [curve[1] for curve in iso_class]
585
+ lmfdb_number = str(sorted_numbers.index(cremona_number)+1)
586
+ return N + '.' + lmfdb_iso + lmfdb_number
587
+ else:
588
+ return N + '.' + lmfdb_iso
589
+
590
+
591
+ def lmfdb_to_cremona(lmfdb_label, CDB=None):
592
+ """
593
+ Convert an LMFDB label into a Cremona label.
594
+
595
+ See :func:`parse_lmfdb_label` for an explanation of LMFDB labels.
596
+
597
+ INPUT:
598
+
599
+ - ``lmfdb_label`` -- string, the LMFDB label of a curve; this can be the
600
+ label of a curve (e.g. '990.j1') or of an isogeny class (e.g. '990.j')
601
+ - ``CDB`` -- the Cremona database in which to look up the isogeny
602
+ classes of the same conductor
603
+
604
+ OUTPUT: ``cremona_label``; a string, the corresponding Cremona label
605
+
606
+ EXAMPLES::
607
+
608
+ sage: from sage.databases.cremona import cremona_to_lmfdb, lmfdb_to_cremona
609
+ sage: lmfdb_to_cremona('990.h3')
610
+ '990j1'
611
+ sage: cremona_to_lmfdb('990j1')
612
+ '990.h3'
613
+ """
614
+ from sage.libs.pari import pari
615
+ m = lmfdb_label_regex.match(lmfdb_label)
616
+ if m is None:
617
+ raise ValueError("Invalid LMFDB label")
618
+ N, lmfdb_iso, lmfdb_number = m.groups()
619
+ if CDB is None:
620
+ CDB = CremonaDatabase()
621
+ classes = CDB.isogeny_classes(N)
622
+ ft = 53
623
+ tff = 255 # This should be enough to distinguish between curves (using heuristics from Sato-Tate for example)
624
+ isos = []
625
+ for i, iso in enumerate(classes):
626
+ alist = iso[0][0]
627
+ E = pari(alist).ellinit(precision=ft)
628
+ isos.append((E.ellan(tff, python_ints=True), cremona_letter_code(i)))
629
+ isos.sort()
630
+ cremona_iso = isos[class_to_int(lmfdb_iso)][1]
631
+ if len(lmfdb_number) > 0:
632
+ iso_class = sorted([(curve[0],i+1) for i,curve in enumerate(classes[class_to_int(cremona_iso)])])
633
+ cremona_number = str(iso_class[int(lmfdb_number)-1][1])
634
+ return N + cremona_iso + cremona_number
635
+ else:
636
+ return N + cremona_iso
637
+
638
+
639
+ class MiniCremonaDatabase(SQLDatabase):
640
+ """
641
+ The Cremona database of elliptic curves.
642
+
643
+ EXAMPLES::
644
+
645
+ sage: c = CremonaDatabase()
646
+ sage: c.allcurves(11)
647
+ {'a1': [[0, -1, 1, -10, -20], 0, 5],
648
+ 'a2': [[0, -1, 1, -7820, -263580], 0, 1],
649
+ 'a3': [[0, -1, 1, 0, 0], 0, 5]}
650
+ """
651
+ _expected_skeleton = _miniCremonaSkeleton
652
+
653
+ def __init__(self, name, read_only=True, build=False):
654
+ """
655
+ Initialize the database.
656
+
657
+ TESTS::
658
+
659
+ sage: c = CremonaDatabase('cremona mini')
660
+ sage: c.name
661
+ 'cremona mini'
662
+ sage: c = CremonaDatabase('cremona') # optional - database_cremona_ellcurve
663
+ sage: c.name # optional - database_cremona_ellcurve
664
+ 'cremona'
665
+ """
666
+ self.name = name
667
+ name = name.replace(' ', '_')
668
+ db_path = DatabaseCremona(name=name).absolute_filename()
669
+ if build:
670
+ if read_only:
671
+ raise RuntimeError('The database must not be read_only.')
672
+ SQLDatabase.__init__(self, db_path, read_only=read_only,
673
+ skeleton=self._expected_skeleton)
674
+ return
675
+ SQLDatabase.__init__(self, db_path, read_only=read_only)
676
+ if self.get_skeleton() != self._expected_skeleton:
677
+ raise RuntimeError('Database at %s does ' % (self.__dblocation__)
678
+ + 'not appear to be a valid SQL Cremona database.')
679
+
680
+ def __iter__(self):
681
+ """
682
+ Return an iterator through all EllipticCurve objects in the
683
+ Cremona database.
684
+
685
+ TESTS::
686
+
687
+ sage: it = CremonaDatabase().__iter__()
688
+ sage: next(it).label()
689
+ '11a1'
690
+ sage: next(it).label()
691
+ '11a2'
692
+ sage: next(it).label()
693
+ '11a3'
694
+ sage: next(it).label()
695
+ '14a1'
696
+ sage: skip = [next(it) for _ in range(100)]
697
+ sage: next(it).label()
698
+ '45a3'
699
+ """
700
+ query = "SELECT curve FROM t_curve,t_class USING(class) ORDER BY conductor"
701
+ for c in self.__connection__.cursor().execute(query):
702
+ yield self.elliptic_curve(c[0])
703
+
704
+ def __getitem__(self, N):
705
+ """
706
+ If `N` is an integer, return all data about level `N` in the database.
707
+ If `N` is a string it must be a Cremona label, in which case return
708
+ the corresponding elliptic curve, if it is in the database.
709
+
710
+ INPUT:
711
+
712
+ - ``N`` -- integer or string
713
+
714
+ OUTPUT: dictionary (if `N` is an integer) or EllipticCurve (if `N` is
715
+ a string)
716
+
717
+ TESTS::
718
+
719
+ sage: c = CremonaDatabase()
720
+ sage: c[11]['allcurves']['a2']
721
+ [[0, -1, 1, -7820, -263580], 0, 1]
722
+ sage: c['11a2']
723
+ Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field
724
+ """
725
+ if isinstance(N, str):
726
+ return self.elliptic_curve(N)
727
+
728
+ try:
729
+ N = int(N)
730
+ except ValueError:
731
+ raise KeyError("N (=%s) must be a string or positive integer." % N)
732
+
733
+ if N <= 0:
734
+ raise KeyError("N (=%s) must be a string or positive integer." % N)
735
+
736
+ ret = {'allcurves': self.allcurves(N)}
737
+ if hasattr(self, 'allbsd'):
738
+ ret['allbsd'] = self.allbsd(N)
739
+ if hasattr(self, 'degphi'):
740
+ ret['degphi'] = self.degphi(N)
741
+ if hasattr(self, 'allgens'):
742
+ ret['allgens'] = self.allgens(N)
743
+ return ret
744
+
745
+ def __repr__(self):
746
+ """
747
+ String representation of this database.
748
+
749
+ TESTS::
750
+
751
+ sage: c = CremonaDatabase('cremona mini')
752
+ sage: c.__repr__()
753
+ "Cremona's database of elliptic curves with conductor at most 9999"
754
+ """
755
+ return "Cremona's database of elliptic curves with conductor at most "\
756
+ + str(self.largest_conductor())
757
+
758
+ def allcurves(self, N):
759
+ """
760
+ Return the allcurves table of curves of conductor N.
761
+
762
+ INPUT:
763
+
764
+ - ``N`` -- integer; the conductor
765
+
766
+ OUTPUT: dictionary; id:[ainvs, rank, tor], ...
767
+
768
+ EXAMPLES::
769
+
770
+ sage: c = CremonaDatabase()
771
+ sage: c.allcurves(11)['a3']
772
+ [[0, -1, 1, 0, 0], 0, 5]
773
+ sage: c.allcurves(12)
774
+ {}
775
+ sage: c.allcurves(12001)['a1'] # optional - database_cremona_ellcurve
776
+ [[1, 0, 0, -101, 382], 1, 1]
777
+ """
778
+ ret = {}
779
+ for c in self.__connection__.cursor().execute('SELECT curve,eqn,'
780
+ + 'rank,tors FROM t_curve,t_class USING(class) WHERE '
781
+ + 'conductor=?', (int(N),)):
782
+ N,iso,num = parse_cremona_label(c[0])
783
+ ret[iso+str(num)] = [eval(c[1]), c[2], c[3]]
784
+ return ret
785
+
786
+ def curves(self, N):
787
+ """
788
+ Return the curves table of all *optimal* curves of conductor N.
789
+
790
+ INPUT:
791
+
792
+ - ``N`` -- integer; the conductor
793
+
794
+ OUTPUT: dictionary; id:[ainvs, rank, tor], ...
795
+
796
+ EXAMPLES:
797
+
798
+ Optimal curves of conductor 37::
799
+
800
+ sage: CremonaDatabase().curves(37)
801
+ {'a1': [[0, 0, 1, -1, 0], 1, 1], 'b1': [[0, 1, 1, -23, -50], 0, 3]}
802
+
803
+ Note the 'h3', which is the unique case in the tables where
804
+ the optimal curve doesn't have label ending in 1::
805
+
806
+ sage: sorted(CremonaDatabase().curves(990))
807
+ ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h3', 'i1', 'j1', 'k1', 'l1']
808
+
809
+ TESTS::
810
+
811
+ sage: c = CremonaDatabase()
812
+ sage: c.curves(12001)['a1'] # optional - database_cremona_ellcurve
813
+ [[1, 0, 0, -101, 382], 1, 1]
814
+ """
815
+ ret = {}
816
+ for c in self.__connection__.cursor().execute('SELECT curve,eqn,'
817
+ + 'rank,tors FROM t_curve,t_class USING(class) WHERE '
818
+ + 'curve=class||1 AND conductor=?',(int(N),)):
819
+ N,iso,num = parse_cremona_label(c[0])
820
+ ret[iso+str(num)] = [eval(c[1]),c[2],c[3]]
821
+ if N == 990:
822
+ del ret['h1']
823
+ ret['h3'] = [[1,-1,1,-1568,-4669],1,6]
824
+ return ret
825
+
826
+ def coefficients_and_data(self, label):
827
+ """
828
+ Return the Weierstrass coefficients and other data for the
829
+ curve with given label.
830
+
831
+ EXAMPLES::
832
+
833
+ sage: c, d = CremonaDatabase().coefficients_and_data('144b1')
834
+ sage: c
835
+ [0, 0, 0, 6, 7]
836
+ sage: d['conductor']
837
+ 144
838
+ sage: d['cremona_label']
839
+ '144b1'
840
+ sage: d['rank']
841
+ 0
842
+ sage: d['torsion_order']
843
+ 2
844
+
845
+ Check that :issue:`17904` is fixed::
846
+
847
+ sage: 'gens' in CremonaDatabase().coefficients_and_data('100467a2')[1] # optional - database_cremona_ellcurve
848
+ True
849
+ """
850
+ # There are two possible strings: the Cremona label and the LMFDB label.
851
+ # They are distinguished by the presence of a period.
852
+ if label.find('.') == -1:
853
+ cremona_label = label
854
+ lmfdb_label = None
855
+ else:
856
+ cremona_label = lmfdb_to_cremona(label)
857
+ lmfdb_label = label
858
+
859
+ N, iso, num = parse_cremona_label(cremona_label)
860
+ label = str(N)+iso+str(num)
861
+ if self.get_skeleton() == _miniCremonaSkeleton:
862
+ q = self.__connection__.cursor().execute("SELECT eqn,rank,tors "
863
+ + 'FROM t_curve,t_class USING(class) WHERE curve=?', (label,))
864
+ else:
865
+ q = self.__connection__.cursor().execute("SELECT eqn,rank,tors,"
866
+ + "deg,gens,cp,om,L,reg,sha FROM t_curve,t_class "
867
+ + "USING(class) WHERE curve=?",(label,))
868
+ try:
869
+ c = next(q)
870
+ except StopIteration:
871
+ if N < self.largest_conductor():
872
+ message = "There is no elliptic curve with label " + label \
873
+ + " in the database"
874
+ elif DatabaseCremona().is_present():
875
+ message = "There is no elliptic curve with label " + label \
876
+ + " in the currently available databases"
877
+ else:
878
+ message = "There is no elliptic curve with label " \
879
+ + label + " in the default database; try installing " \
880
+ + "the optional package database_cremona_ellcurve which " \
881
+ + "contains the complete Cremona database"
882
+ raise ValueError(message)
883
+ ainvs = eval(c[0])
884
+ data = {'cremona_label': label,
885
+ 'rank': c[1],
886
+ 'torsion_order': c[2],
887
+ 'conductor': N}
888
+ if lmfdb_label:
889
+ data['lmfdb_label'] = lmfdb_label
890
+ if len(c) > 3:
891
+ data['modular_degree'] = (c[3])
892
+ data['gens'] = eval(c[4])
893
+ data['db_extra'] = list(c[5:])
894
+ return ainvs, data
895
+
896
+ def data_from_coefficients(self, ainvs):
897
+ """
898
+ Return elliptic curve data for the curve with given
899
+ Weierstrass coefficients.
900
+
901
+ EXAMPLES::
902
+
903
+ sage: d = CremonaDatabase().data_from_coefficients([1, -1, 1, 31, 128])
904
+ sage: d['conductor']
905
+ 1953
906
+ sage: d['cremona_label']
907
+ '1953c1'
908
+ sage: d['rank']
909
+ 1
910
+ sage: d['torsion_order']
911
+ 2
912
+
913
+ Check that :issue:`17904` is fixed::
914
+
915
+ sage: ai = EllipticCurve('100467a2').ainvs() # optional - database_cremona_ellcurve
916
+ sage: 'gens' in CremonaDatabase().data_from_coefficients(ai) # optional - database_cremona_ellcurve
917
+ True
918
+ """
919
+ ainvs = str(list(ainvs))
920
+ if self.get_skeleton() == _miniCremonaSkeleton:
921
+ q = self.__connection__.cursor().execute("SELECT curve,rank,tors "
922
+ + 'FROM t_curve,t_class USING(class) WHERE eqn=?',
923
+ (ainvs.replace(' ', ''),))
924
+ else:
925
+ q = self.__connection__.cursor().execute("SELECT curve,rank,tors,"
926
+ + "deg,gens,cp,om,L,reg,sha FROM t_curve,t_class "
927
+ + "USING(class) WHERE eqn=?",
928
+ (ainvs.replace(' ', ''),))
929
+ try:
930
+ c = next(q)
931
+ except StopIteration:
932
+ raise RuntimeError("There is no elliptic curve with coefficients "
933
+ + ainvs + " in the database")
934
+ label = str(c[0])
935
+ N, iso, num = parse_cremona_label(label)
936
+ data = {'cremona_label': label,
937
+ 'rank': c[1],
938
+ 'torsion_order': c[2],
939
+ 'conductor': N}
940
+ if len(c) > 3:
941
+ data['modular_degree'] = (c[3])
942
+ data['gens'] = eval(c[4])
943
+ data['db_extra'] = list(c[5:])
944
+ return data
945
+
946
+ def elliptic_curve_from_ainvs(self, ainvs):
947
+ """
948
+ Return the elliptic curve in the database of with minimal ``ainvs``
949
+ if it exists.
950
+
951
+ This raises a :exc:`RuntimeError` exception otherwise.
952
+
953
+ INPUT:
954
+
955
+ - ``ainvs`` -- list (5-tuple of int's); the minimal
956
+ Weierstrass model for an elliptic curve
957
+
958
+ OUTPUT: EllipticCurve
959
+
960
+ EXAMPLES::
961
+
962
+ sage: c = CremonaDatabase()
963
+ sage: c.elliptic_curve_from_ainvs([0, -1, 1, -10, -20])
964
+ Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
965
+ sage: c.elliptic_curve_from_ainvs([1, 0, 0, -101, 382]) # optional - database_cremona_ellcurve
966
+ Elliptic Curve defined by y^2 + x*y = x^3 - 101*x + 382 over Rational Field
967
+
968
+ Old (pre-2006) Cremona labels are also allowed::
969
+
970
+ sage: c.elliptic_curve('9450KKKK1')
971
+ Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 5*x + 7 over Rational Field
972
+
973
+ Make sure :issue:`12565` is fixed::
974
+
975
+ sage: c.elliptic_curve('10a1')
976
+ Traceback (most recent call last):
977
+ ...
978
+ ValueError: There is no elliptic curve with label 10a1 in the database
979
+ """
980
+ data = self.data_from_coefficients(ainvs)
981
+ return elliptic.EllipticCurve(ainvs, **data)
982
+
983
+ def elliptic_curve(self, label):
984
+ """
985
+ Return an elliptic curve with given label with some data about it
986
+ from the database pre-filled in.
987
+
988
+ INPUT:
989
+
990
+ - ``label`` -- string (Cremona or LMFDB label)
991
+
992
+ OUTPUT: an :class:`sage.schemes.elliptic_curves.ell_rational_field.EllipticCurve_rational_field`
993
+
994
+ .. NOTE::
995
+
996
+ For more details on LMFDB labels see :func:`parse_lmfdb_label`.
997
+
998
+ EXAMPLES::
999
+
1000
+ sage: c = CremonaDatabase()
1001
+ sage: c.elliptic_curve('11a1')
1002
+ Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
1003
+ sage: c.elliptic_curve('12001a1') # optional - database_cremona_ellcurve
1004
+ Elliptic Curve defined by y^2 + x*y = x^3 - 101*x + 382 over Rational Field
1005
+ sage: c.elliptic_curve('48c1')
1006
+ Traceback (most recent call last):
1007
+ ...
1008
+ ValueError: There is no elliptic curve with label 48c1 in the database
1009
+
1010
+ You can also use LMFDB labels::
1011
+
1012
+ sage: c.elliptic_curve('462.f3')
1013
+ Elliptic Curve defined by y^2 + x*y = x^3 - 363*x + 1305 over Rational Field
1014
+ """
1015
+ ainvs, data = self.coefficients_and_data(label)
1016
+ return elliptic.EllipticCurve(ainvs, **data)
1017
+
1018
+ def iter(self, conductors):
1019
+ """
1020
+ Return an iterator through all curves in the database with given
1021
+ conductors.
1022
+
1023
+ INPUT:
1024
+
1025
+ - ``conductors`` -- list or generator of ints
1026
+
1027
+ OUTPUT: generator that iterates over EllipticCurve objects
1028
+
1029
+ EXAMPLES::
1030
+
1031
+ sage: [e.cremona_label() for e in CremonaDatabase().iter([11..15])]
1032
+ ['11a1', '11a2', '11a3', '14a1', '14a2', '14a3', '14a4', '14a5',
1033
+ '14a6', '15a1', '15a2', '15a3', '15a4', '15a5', '15a6', '15a7', '15a8']
1034
+ """
1035
+ for N in conductors:
1036
+ for c in self.__connection__.cursor().execute('SELECT curve '
1037
+ + 'FROM t_curve,t_class USING(class) WHERE conductor=?',
1038
+ (int(N),)):
1039
+ yield self.elliptic_curve(c[0])
1040
+
1041
+ def isogeny_classes(self, conductor):
1042
+ """
1043
+ Return the allcurves data (ainvariants, rank and torsion) for the
1044
+ elliptic curves in the database of given conductor as a list of
1045
+ lists, one for each isogeny class. The curve with number 1 is
1046
+ always listed first.
1047
+
1048
+ EXAMPLES::
1049
+
1050
+ sage: c = CremonaDatabase()
1051
+ sage: c.isogeny_classes(11)
1052
+ [[[[0, -1, 1, -10, -20], 0, 5],
1053
+ [[0, -1, 1, -7820, -263580], 0, 1],
1054
+ [[0, -1, 1, 0, 0], 0, 5]]]
1055
+ sage: c.isogeny_classes(12001) # optional - database_cremona_ellcurve
1056
+ [[[[1, 0, 0, -101, 382], 1, 1]],
1057
+ [[[0, 0, 1, -247, 1494], 1, 1]],
1058
+ [[[0, 0, 1, -4, -18], 1, 1]],
1059
+ [[[0, 1, 1, -10, 18], 1, 1]]]
1060
+ """
1061
+ conductor = int(conductor)
1062
+ classes = []
1063
+ A = self.allcurves(conductor)
1064
+ K = sorted(A, key=sort_key)
1065
+ for k in K:
1066
+ v = A[k]
1067
+ # test if not first curve in class
1068
+ if not (k[-1] == '1' and k[-2].isalpha()):
1069
+ classes[len(classes)-1].append(v)
1070
+ else:
1071
+ classes.append([v])
1072
+ return classes
1073
+
1074
+ def isogeny_class(self, label):
1075
+ """
1076
+ Return the isogeny class of elliptic curves that are
1077
+ isogenous to the curve with given Cremona label.
1078
+
1079
+ INPUT:
1080
+
1081
+ - ``label`` -- string
1082
+
1083
+ OUTPUT: list of EllipticCurve objects
1084
+
1085
+ EXAMPLES::
1086
+
1087
+ sage: c = CremonaDatabase()
1088
+ sage: c.isogeny_class('11a1')
1089
+ [Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field,
1090
+ Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field,
1091
+ Elliptic Curve defined by y^2 + y = x^3 - x^2 over Rational Field]
1092
+ sage: c.isogeny_class('12001a1') # optional - database_cremona_ellcurve
1093
+ [Elliptic Curve defined by y^2 + x*y = x^3 - 101*x + 382 over Rational Field]
1094
+ """
1095
+ conductor, iso, num = parse_cremona_label(label)
1096
+ q = self.__connection__.cursor().execute("SELECT curve FROM t_curve "
1097
+ + "WHERE class=?",(str(conductor)+iso,))
1098
+ return [self.elliptic_curve(c[0]) for c in q]
1099
+
1100
+ def iter_optimal(self, conductors):
1101
+ """
1102
+ Return an iterator through all optimal curves in the database
1103
+ with given conductors.
1104
+
1105
+ INPUT:
1106
+
1107
+ - ``conductors`` -- list or generator of ints
1108
+
1109
+ OUTPUT: generator that iterates over EllipticCurve objects
1110
+
1111
+ EXAMPLES:
1112
+
1113
+ We list optimal curves with conductor up to 20::
1114
+
1115
+ sage: [e.cremona_label() for e in CremonaDatabase().iter_optimal([11..20])]
1116
+ ['11a1', '14a1', '15a1', '17a1', '19a1', '20a1']
1117
+
1118
+ Note the unfortunate 990h3 special case::
1119
+
1120
+ sage: [e.cremona_label() for e in CremonaDatabase().iter_optimal([990])]
1121
+ ['990a1', '990b1', '990c1', '990d1', '990e1', '990f1', '990g1', '990h3', '990i1', '990j1', '990k1', '990l1']
1122
+ """
1123
+ for N in conductors:
1124
+ if N == 990:
1125
+ for c in self.__connection__.cursor().execute('SELECT class '
1126
+ + 'FROM t_class WHERE conductor=990'):
1127
+ if c[0][-1] == 'h':
1128
+ yield self.elliptic_curve(c[0]+'3')
1129
+ else:
1130
+ yield self.elliptic_curve(c[0]+'1')
1131
+ continue
1132
+ for c in self.__connection__.cursor().execute('SELECT curve '
1133
+ + 'FROM t_curve,t_class USING(class) WHERE curve=class||1 '
1134
+ + 'AND conductor=?',(int(N),)):
1135
+ yield self.elliptic_curve(c[0])
1136
+
1137
+ def list(self, conductors):
1138
+ """
1139
+ Return a list of all curves with given conductors.
1140
+
1141
+ INPUT:
1142
+
1143
+ - ``conductors`` -- list or generator of ints
1144
+
1145
+ OUTPUT: list of EllipticCurve objects
1146
+
1147
+ EXAMPLES::
1148
+
1149
+ sage: CremonaDatabase().list([37])
1150
+ [Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field,
1151
+ Elliptic Curve defined by y^2 + y = x^3 + x^2 - 23*x - 50 over Rational Field,
1152
+ Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field,
1153
+ Elliptic Curve defined by y^2 + y = x^3 + x^2 - 3*x + 1 over Rational Field]
1154
+ """
1155
+ return list(self.iter(conductors))
1156
+
1157
+ def list_optimal(self, conductors):
1158
+ """
1159
+ Return a list of all optimal curves with given conductors.
1160
+
1161
+ INPUT:
1162
+
1163
+ - ``conductors`` -- list or generator of ints list of EllipticCurve
1164
+ objects
1165
+
1166
+ OUTPUT: list of EllipticCurve objects
1167
+
1168
+ EXAMPLES::
1169
+
1170
+ sage: CremonaDatabase().list_optimal([37])
1171
+ [Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field,
1172
+ Elliptic Curve defined by y^2 + y = x^3 + x^2 - 23*x - 50 over Rational Field]
1173
+ """
1174
+ return list(self.iter_optimal(conductors))
1175
+
1176
+ def largest_conductor(self):
1177
+ """
1178
+ The largest conductor for which the database is complete.
1179
+
1180
+ OUTPUT: integer; largest conductor
1181
+
1182
+ EXAMPLES::
1183
+
1184
+ sage: c = CremonaDatabase('cremona mini')
1185
+ sage: c.largest_conductor()
1186
+ 9999
1187
+ """
1188
+ if hasattr(self, '__largest_conductor__'):
1189
+ return self.__largest_conductor__
1190
+ q = self.__connection__.cursor().execute('SELECT conductor FROM '
1191
+ + 't_class ORDER BY conductor DESC LIMIT 1')
1192
+ self.__largest_conductor__ = next(q)[0]
1193
+ return self.__largest_conductor__
1194
+
1195
+ def smallest_conductor(self):
1196
+ """
1197
+ The smallest conductor for which the database is complete: always 1.
1198
+
1199
+ OUTPUT: integer; smallest conductor
1200
+
1201
+ .. NOTE::
1202
+
1203
+ This always returns the integer 1, since that is the
1204
+ smallest conductor for which the database is complete,
1205
+ although there are no elliptic curves of conductor 1. The
1206
+ smallest conductor of a curve in the database is 11.
1207
+
1208
+ EXAMPLES::
1209
+
1210
+ sage: CremonaDatabase().smallest_conductor()
1211
+ 1
1212
+ """
1213
+ return 1
1214
+
1215
+ def conductor_range(self):
1216
+ """
1217
+ Return the range of conductors that are covered by the database.
1218
+
1219
+ OUTPUT: tuple of ints (N1,N2+1) where N1 is the smallest and
1220
+ N2 the largest conductor for which the database is complete.
1221
+
1222
+ EXAMPLES::
1223
+
1224
+ sage: c = CremonaDatabase('cremona mini')
1225
+ sage: c.conductor_range()
1226
+ (1, 10000)
1227
+ """
1228
+ return 1, self.largest_conductor()+1
1229
+
1230
+ def number_of_curves(self, N=0, i=0):
1231
+ """
1232
+ Return the number of curves stored in the database with conductor
1233
+ `N`. If `N = 0`, returns the total number of curves in the database.
1234
+
1235
+ If `i` is nonzero, returns the number of curves in the `i`-th isogeny
1236
+ class. If `i` is a Cremona letter code, e.g., 'a' or 'bc', it is
1237
+ converted to the corresponding number.
1238
+
1239
+ INPUT:
1240
+
1241
+ - ``N`` -- integer
1242
+ - ``i`` -- integer or string
1243
+
1244
+ OUTPUT: integer
1245
+
1246
+ EXAMPLES::
1247
+
1248
+ sage: c = CremonaDatabase()
1249
+ sage: c.number_of_curves(11)
1250
+ 3
1251
+ sage: c.number_of_curves(37)
1252
+ 4
1253
+ sage: c.number_of_curves(990)
1254
+ 42
1255
+ sage: num = c.number_of_curves()
1256
+ """
1257
+ if N == 0:
1258
+ if hasattr(self, '__number_of_curves__'):
1259
+ return self.__number_of_curves__
1260
+ q = self.__connection__.cursor().execute('SELECT COUNT(curve) '
1261
+ + 'FROM t_curve')
1262
+ self.__number_of_curves__ = next(q)[0]
1263
+ return self.__number_of_curves__
1264
+ if i == 0:
1265
+ q = self.__connection__.cursor().execute('SELECT COUNT(curve) '
1266
+ + 'FROM t_curve,t_class USING(class) WHERE conductor=?',
1267
+ (int(N),))
1268
+ return next(q)[0]
1269
+ if not isinstance(i, str):
1270
+ i = cremona_letter_code(i)
1271
+ q = self.__connection__.cursor().execute('SELECT COUNT(curve) FROM '
1272
+ + 't_curve WHERE class=?',(str(N)+i,))
1273
+ return next(q)[0]
1274
+
1275
+ def number_of_isogeny_classes(self, N=0):
1276
+ """
1277
+ Return the number of isogeny classes of curves in the database of
1278
+ conductor N. If N is 0, return the total number of isogeny classes
1279
+ of curves in the database.
1280
+
1281
+ INPUT:
1282
+
1283
+ - ``N`` -- integer
1284
+
1285
+ OUTPUT: integer
1286
+
1287
+ EXAMPLES::
1288
+
1289
+ sage: c = CremonaDatabase()
1290
+ sage: c.number_of_isogeny_classes(11)
1291
+ 1
1292
+ sage: c.number_of_isogeny_classes(37)
1293
+ 2
1294
+ sage: num = c.number_of_isogeny_classes()
1295
+ """
1296
+ if N == 0:
1297
+ if hasattr(self, '__number_of_isogeny_classes__'):
1298
+ return self.__number_of_isogeny_classes__
1299
+ q = self.__connection__.cursor().execute('SELECT COUNT(class) '
1300
+ + 'FROM t_class')
1301
+ self.__number_of_isogeny_classes__ = next(q)[0]
1302
+ return self.__number_of_isogeny_classes__
1303
+ q = self.__connection__.cursor().execute('SELECT COUNT(class) FROM '
1304
+ + 't_class WHERE conductor=?',(int(N),))
1305
+ return next(q)[0]
1306
+
1307
+ def random(self):
1308
+ """
1309
+ Return a random curve from the database.
1310
+
1311
+ EXAMPLES::
1312
+
1313
+ sage: CremonaDatabase().random() # random -- depends on database installed
1314
+ Elliptic Curve defined by y^2 + x*y = x^3 - x^2 - 224*x + 3072 over Rational Field
1315
+ """
1316
+ N = randint(11, self.largest_conductor())
1317
+ q = self.__connection__.cursor().execute('SELECT conductor FROM '
1318
+ + 't_class WHERE conductor>=? ORDER BY conductor',(int(N),))
1319
+ try:
1320
+ N = next(q)[0]
1321
+ except StopIteration:
1322
+ N = 11
1323
+ iso = randint(0, self.number_of_isogeny_classes(N)-1)
1324
+ iso = cremona_letter_code(iso)
1325
+ num = randint(1, self.number_of_curves(N,iso))
1326
+ return self.elliptic_curve(str(N)+iso+str(num))
1327
+
1328
+ ###############################################################################
1329
+ # Functions for loading data from Cremona's ftpdata directory.
1330
+ ###############################################################################
1331
+ def _init_from_ftpdata(self, ftpdata, largest_conductor=0):
1332
+ """Create the SQL Cremona Database from the Cremona elliptic curve
1333
+ data repository ecdata, which is available from
1334
+ https://github.com/JohnCremona/ecdata.
1335
+
1336
+ To create the large database from Cremona's text files, see
1337
+ sage.databases.cremona.build. Alternatively:
1338
+
1339
+ If the Cremona database has already been installed, remove
1340
+ `SAGE_DATA/cremona/cremona.db`. Then run::
1341
+
1342
+ sage: C = sage.databases.cremona.LargeCremonaDatabase('cremona',False, True) # not tested
1343
+ sage: C._init_from_ftpdata('path/to/ecdata/',0) # not tested
1344
+
1345
+ EXAMPLES::
1346
+
1347
+ sage: d = sage.databases.cremona.MiniCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1348
+ sage: d._init_from_ftpdata('/home/jec/ecdata') # not tested
1349
+ """
1350
+ if self.__read_only__:
1351
+ raise RuntimeError("The database must not be read_only.")
1352
+
1353
+ if not os.path.exists(ftpdata):
1354
+ raise RuntimeError("The cremona ftpdata directory '" + ftpdata
1355
+ + "' does not exist.")
1356
+
1357
+ if largest_conductor:
1358
+ print("largest conductor =", largest_conductor)
1359
+ self.__largest_conductor__ = largest_conductor
1360
+
1361
+ # Since July 2014 the data files have been arranged in
1362
+ # subdirectories (see trac #16903).
1363
+ allcurves_dir = os.path.join(ftpdata,'allcurves')
1364
+ allbsd_dir = os.path.join(ftpdata,'allbsd')
1365
+ allgens_dir = os.path.join(ftpdata,'allgens')
1366
+ degphi_dir = os.path.join(ftpdata,'degphi')
1367
+ num_curves, num_iso_classes = self._init_allcurves(allcurves_dir, largest_conductor)
1368
+ self.__number_of_curves__ = num_curves
1369
+ self.__number_of_isogeny_classes__ = num_iso_classes
1370
+ if hasattr(self, 'degphi'):
1371
+ self._init_degphi(degphi_dir, largest_conductor)
1372
+ if hasattr(self, 'allbsd'):
1373
+ self._init_allbsd(allbsd_dir, largest_conductor)
1374
+ if hasattr(self, 'allgens'):
1375
+ self._init_allgens(allgens_dir, largest_conductor)
1376
+ self.vacuum()
1377
+
1378
+ def _init_allcurves(self, ftpdata, largest_conductor=0):
1379
+ """
1380
+ Initialize the allcurves table by reading the corresponding ftpdata
1381
+ files and importing them into the database.
1382
+
1383
+ To create the large database from Cremona's text files, see
1384
+ sage.databases.cremona.build, do NOT run this method directly.
1385
+
1386
+ INPUT:
1387
+
1388
+ - ``ftpdata`` -- string; the name of the directory in which the data is
1389
+
1390
+ - ``largest_conductor`` -- integer (default: 0); if 0,
1391
+ then only include data up to that conductor
1392
+
1393
+ OUTPUT:
1394
+
1395
+ - integer; number_of_curves
1396
+ - integer; number_of_isogeny_classes
1397
+
1398
+ EXAMPLES::
1399
+
1400
+ sage: d = sage.databases.cremona.MiniCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1401
+ sage: d._init_allcurves('.', 11) # not tested
1402
+ (3, 1)
1403
+ """
1404
+ if self.__read_only__:
1405
+ raise RuntimeError("The database must not be read_only.")
1406
+ files = sorted(os.listdir(ftpdata))
1407
+ name = 'allcurves'
1408
+ num_curves = 0
1409
+ num_iso_classes = 0
1410
+ con = self.get_connection()
1411
+ for F in files:
1412
+ if not F[:len(name)] == name:
1413
+ continue
1414
+ print("Inserting", F)
1415
+ class_data = []
1416
+ curve_data = []
1417
+ for L in open(ftpdata + "/" + F).readlines():
1418
+ N, iso, num, ainvs, r, tor = L.split()
1419
+ if largest_conductor and int(N) > largest_conductor:
1420
+ break
1421
+ cls = N+iso
1422
+ cur = cls+num
1423
+ if num == "1":
1424
+ class_data.append((N,cls,r))
1425
+ num_iso_classes += 1
1426
+ curve_data.append((cur,cls,ainvs,tor))
1427
+ num_curves += 1
1428
+ con.executemany('INSERT INTO t_class (conductor,class,rank) '
1429
+ + 'VALUES (?,?,?)', class_data)
1430
+ con.executemany('INSERT INTO t_curve (curve,class,eqn,tors) '
1431
+ + 'VALUES (?,?,?,?)', curve_data)
1432
+ print("Committing...")
1433
+ print("num_iso_classes =", num_iso_classes)
1434
+ self.commit()
1435
+ if largest_conductor and int(N) > largest_conductor:
1436
+ break
1437
+ return num_curves, num_iso_classes
1438
+
1439
+
1440
+ class LargeCremonaDatabase(MiniCremonaDatabase):
1441
+ """
1442
+ The Cremona database of elliptic curves.
1443
+
1444
+ EXAMPLES::
1445
+
1446
+ sage: c = CremonaDatabase('cremona') # optional - database_cremona_ellcurve
1447
+ sage: c.allcurves(11) # optional - database_cremona_ellcurve
1448
+ {'a1': [[0, -1, 1, -10, -20], 0, 5],
1449
+ 'a2': [[0, -1, 1, -7820, -263580], 0, 1],
1450
+ 'a3': [[0, -1, 1, 0, 0], 0, 5]}
1451
+ """
1452
+ _expected_skeleton = _cremonaSkeleton
1453
+
1454
+ def allbsd(self, N):
1455
+ r"""
1456
+ Return the allbsd table for conductor N. The entries are::
1457
+
1458
+ [id, tamagawa_product, Omega_E, L, Reg_E, Sha_an(E)]
1459
+
1460
+ where id is the isogeny class (letter) followed by a number, e.g.,
1461
+ b3, and L is `L^r(E,1)/r!`, where E has rank r.
1462
+
1463
+ INPUT:
1464
+
1465
+ - ``N`` -- integer; the conductor
1466
+
1467
+ OUTPUT: dictionary containing the allbsd table for each isogeny class
1468
+ in conductor N
1469
+
1470
+ EXAMPLES::
1471
+
1472
+ sage: c = CremonaDatabase()
1473
+ sage: c.allbsd(12) # optional - database_cremona_ellcurve
1474
+ {}
1475
+ sage: c.allbsd(19)['a3'] # optional - database_cremona_ellcurve
1476
+ [1, 4.07927920046493, 0.453253244496104, 1.0, 1]
1477
+ sage: c.allbsd(12001)['a1'] # optional - database_cremona_ellcurve
1478
+ [2, 3.27608135248722, 1.54910143090506, 0.236425971187952, 1.0]
1479
+ """
1480
+ ret = {}
1481
+ for c in self.__connection__.cursor().execute('SELECT curve,cp,om,L,'
1482
+ + 'reg,sha FROM t_curve,t_class USING(class) WHERE conductor=?',
1483
+ (int(N),)):
1484
+ N,iso,num = parse_cremona_label(c[0])
1485
+ ret[iso+str(num)] = list(c[1:])
1486
+ return ret
1487
+
1488
+ def allgens(self, N):
1489
+ """
1490
+ Return the allgens table for conductor N.
1491
+
1492
+ INPUT:
1493
+
1494
+ - ``N`` -- integer; the conductor
1495
+
1496
+ OUTPUT: dictionary; id:[points, ...], ...
1497
+
1498
+ EXAMPLES::
1499
+
1500
+ sage: c = CremonaDatabase()
1501
+ sage: c.allgens(12) # optional - database_cremona_ellcurve
1502
+ {}
1503
+ sage: c.allgens(1001)['a1'] # optional - database_cremona_ellcurve
1504
+ [[61, 181, 1]]
1505
+ sage: c.allgens(12001)['a1'] # optional - database_cremona_ellcurve
1506
+ [[7, 2, 1]]
1507
+ """
1508
+ ret = {}
1509
+ for c in self.__connection__.cursor().execute('SELECT curve,gens '
1510
+ + 'FROM t_curve,t_class USING(class) WHERE conductor=?',(int(N),)):
1511
+ N,iso,num = parse_cremona_label(c[0])
1512
+ ret[iso+str(num)] = eval(c[1])
1513
+ return ret
1514
+
1515
+ def degphi(self, N):
1516
+ """
1517
+ Return the degphi table for conductor N.
1518
+
1519
+ INPUT:
1520
+
1521
+ - ``N`` -- integer; the conductor
1522
+
1523
+ OUTPUT: dictionary; id:degphi, ...
1524
+
1525
+ EXAMPLES::
1526
+
1527
+ sage: c = CremonaDatabase()
1528
+ sage: c.degphi(11) # optional - database_cremona_ellcurve
1529
+ {'a1': 1}
1530
+ sage: c.degphi(12001)['c1'] # optional - database_cremona_ellcurve
1531
+ 1640
1532
+ """
1533
+ ret = {}
1534
+ for c in self.__connection__.cursor().execute('SELECT curve,deg FROM'
1535
+ + ' t_curve,t_class USING(class) WHERE curve=class||1 AND '
1536
+ + 'conductor=?', (int(N),)):
1537
+ N,iso,num = parse_cremona_label(c[0])
1538
+ ret[iso+str(num)] = c[1]
1539
+ return ret
1540
+
1541
+ def _init_degphi(self, ftpdata, largest_conductor=0):
1542
+ """
1543
+ Initialize the degphi table by reading the corresponding ftpdata
1544
+ files and importing them into the database.
1545
+
1546
+ To create the large database from Cremona's text files, see
1547
+ sage.databases.cremona.build, do NOT run this method directly.
1548
+
1549
+ EXAMPLES::
1550
+
1551
+ sage: d = sage.databases.cremona.LargeCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1552
+ sage: d._init_degphi('.') # not tested
1553
+ """
1554
+ if self.__read_only__:
1555
+ raise RuntimeError("The database must not be read_only.")
1556
+ files = sorted(os.listdir(ftpdata))
1557
+ name = "degphi"
1558
+ con = self.get_connection()
1559
+ for F in files:
1560
+ if not F[:len(name)] == name:
1561
+ continue
1562
+ print("Inserting", F)
1563
+ class_data = []
1564
+ for L in open(ftpdata + "/" + F).readlines():
1565
+ N, iso, num, degree, primes, curve = L.split()
1566
+ if largest_conductor and int(N) > largest_conductor:
1567
+ break
1568
+ class_data.append((degree,N+iso))
1569
+ con.executemany('UPDATE t_class SET deg=? WHERE class=?',
1570
+ class_data)
1571
+ print("Committing...")
1572
+ self.commit()
1573
+ if largest_conductor and int(N) > largest_conductor:
1574
+ break
1575
+
1576
+ def _init_allbsd(self, ftpdata, largest_conductor=0):
1577
+ """
1578
+ Initialize the allbsd table by reading the corresponding ftpdata
1579
+ files and importing them into the database.
1580
+
1581
+ To create the large database from Cremona's text files, see
1582
+ sage.databases.cremona.build, do NOT run this method directly.
1583
+
1584
+ EXAMPLES::
1585
+
1586
+ sage: d = sage.databases.cremona.LargeCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1587
+ sage: d._init_allbsd('.') # not tested
1588
+ """
1589
+ if self.__read_only__:
1590
+ raise RuntimeError("The database must not be read_only.")
1591
+ files = sorted(os.listdir(ftpdata))
1592
+ name = "allbsd"
1593
+ con = self.get_connection()
1594
+ for F in files:
1595
+ if not F[:len(name)] == name:
1596
+ continue
1597
+ print("Inserting", F)
1598
+ curve_data = []
1599
+ class_data = []
1600
+ for L in open(ftpdata + "/" + F).readlines():
1601
+ N, iso, num, eqn, rank, tor, cp, om, L, reg, sha = L.split()
1602
+ if largest_conductor and int(N) > largest_conductor:
1603
+ break
1604
+ cls = N+iso
1605
+ if num == "1":
1606
+ class_data.append((L,cls))
1607
+ curve_data.append((cp,om,reg,eval(sha),cls+num))
1608
+ con.executemany("UPDATE t_class SET L=? WHERE class=?", class_data)
1609
+ con.executemany("UPDATE t_curve SET cp=?,om=?,reg=?,sha=? WHERE "
1610
+ + "curve=?", curve_data)
1611
+ print("Committing...")
1612
+ self.commit()
1613
+ if largest_conductor and int(N) > largest_conductor:
1614
+ break
1615
+
1616
+ def _init_allgens(self, ftpdata, largest_conductor=0):
1617
+ """
1618
+ Initialize the allgens table by reading the corresponding ftpdata
1619
+ files and importing them into the database.
1620
+
1621
+ To create the large database from Cremona's text files, see
1622
+ sage.databases.cremona.build, do NOT run this method directly.
1623
+
1624
+ EXAMPLES::
1625
+
1626
+ sage: d = sage.databases.cremona.LargeCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1627
+ sage: d._init_allgens('.') # not tested
1628
+ """
1629
+ if self.__read_only__:
1630
+ raise RuntimeError("The database must not be read_only.")
1631
+ files = sorted(os.listdir(ftpdata))
1632
+ name = "allgens"
1633
+ con = self.get_connection()
1634
+ for F in files:
1635
+ if not F[:len(name)] == name:
1636
+ continue
1637
+ print("Inserting", F)
1638
+ curve_data = []
1639
+ for L in open(ftpdata + "/" + F).readlines():
1640
+ v = L.split()
1641
+ if largest_conductor and int(v[0]) > largest_conductor:
1642
+ break
1643
+ gens = '['+','.join(v[6:6+int(v[4])]).replace(':',',')+']'
1644
+ curve_data.append((gens,''.join(v[:3])))
1645
+ con.executemany("UPDATE t_curve SET gens=? WHERE curve=?",
1646
+ curve_data)
1647
+ print("Committing...")
1648
+ self.commit()
1649
+ if largest_conductor and int(v[0]) > largest_conductor:
1650
+ break
1651
+
1652
+
1653
+ _db = None
1654
+
1655
+
1656
+ def CremonaDatabase(name=None, mini=None):
1657
+ """
1658
+ Initialize the Cremona database with name ``name``.
1659
+
1660
+ If ``name`` is
1661
+ ``None`` it instead initializes large Cremona database (named 'cremona'),
1662
+ if available or default mini Cremona database (named 'cremona mini').
1663
+
1664
+ If the Cremona database in question is in the format of the mini database,
1665
+ you must set ``mini=True``, otherwise it must be set to ``False``.
1666
+
1667
+ TESTS::
1668
+
1669
+ sage: c = CremonaDatabase()
1670
+ sage: isinstance(c, sage.databases.cremona.MiniCremonaDatabase)
1671
+ True
1672
+ sage: isinstance(c, sage.databases.cremona.LargeCremonaDatabase) # optional - database_cremona_ellcurve
1673
+ True
1674
+
1675
+ Verify that :issue:`12341` has been resolved::
1676
+
1677
+ sage: c = CremonaDatabase('should not exist', mini=True)
1678
+ Traceback (most recent call last):
1679
+ ...
1680
+ FeatureNotPresentError: database_should_not_exist_ellcurve is not available.
1681
+ '...db' not found in any of [...]
1682
+ ...Further installation instructions might be available at https://github.com/JohnCremona/ecdata.
1683
+ sage: c = CremonaDatabase('should not exist',mini=False)
1684
+ Traceback (most recent call last):
1685
+ ...
1686
+ FeatureNotPresentError: database_should_not_exist_ellcurve is not available.
1687
+ '...db' not found in any of [...]
1688
+ ...Further installation instructions might be available at https://github.com/JohnCremona/ecdata.
1689
+
1690
+ Verify that :issue:`39072` has been resolved::
1691
+
1692
+ sage: C = CremonaDatabase(mini=False) # optional - !database_cremona_ellcurve
1693
+ Traceback (most recent call last):
1694
+ ...
1695
+ ValueError: the full Cremona database is not available; consider using the mini Cremona database by setting mini=True
1696
+ """
1697
+ if name is None:
1698
+ if mini is None:
1699
+ if DatabaseCremona().is_present():
1700
+ name = 'cremona'
1701
+ mini = False
1702
+ else:
1703
+ name = 'cremona mini'
1704
+ mini = True
1705
+ elif mini:
1706
+ name = 'cremona mini'
1707
+ else:
1708
+ if not DatabaseCremona().is_present():
1709
+ raise ValueError('the full Cremona database is not available; '
1710
+ 'consider using the mini Cremona database by setting mini=True')
1711
+ name = 'cremona'
1712
+ elif name == 'cremona mini':
1713
+ mini = True
1714
+ elif name == 'cremona':
1715
+ mini = False
1716
+ else:
1717
+ if mini is None:
1718
+ raise ValueError('the mini option must be set to True or False')
1719
+
1720
+ if mini:
1721
+ return MiniCremonaDatabase(name)
1722
+ else:
1723
+ return LargeCremonaDatabase(name)