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,1847 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.symbolic
3
+ r"""
4
+ Class for computing sums over zeros of motivic `L`-functions
5
+
6
+ All computations are done to double precision.
7
+
8
+ AUTHORS:
9
+
10
+ - Simon Spicer (2014-10): first version
11
+ """
12
+ # ****************************************************************************
13
+ # Copyright (C) 2014 Simon Spicer <mlungu@uw.edu>
14
+ #
15
+ # This program is free software: you can redistribute it and/or modify
16
+ # it under the terms of the GNU General Public License as published by
17
+ # the Free Software Foundation, either version 2 of the License, or
18
+ # (at your option) any later version.
19
+ # https://www.gnu.org/licenses/
20
+ # ****************************************************************************
21
+
22
+ from sage.arith.misc import next_prime
23
+ from sage.functions.log import log, exp
24
+ from sage.functions.other import real, imag
25
+ from sage.libs.flint.ulong_extras cimport n_is_prime
26
+ from sage.misc.verbose import verbose
27
+ from sage.parallel.decorate import parallel
28
+ from sage.parallel.ncpus import ncpus as num_cpus
29
+ from sage.rings.complex_double import CDF
30
+ from sage.rings.infinity import PlusInfinity
31
+ from sage.rings.integer_ring import ZZ
32
+ from sage.rings.real_double import RDF
33
+ from sage.structure.sage_object cimport SageObject
34
+ from sage.symbolic.constants import euler_gamma, pi
35
+
36
+
37
+ cdef extern from "<math.h>":
38
+ double c_exp "exp"(double)
39
+ double c_log "log"(double)
40
+ double c_cos "cos"(double)
41
+ double c_acos "acos"(double)
42
+ double c_sqrt "sqrt"(double)
43
+
44
+ # Global variable determining the number of CPUs to use for parallel computations
45
+ cdef NCPUS
46
+
47
+ cdef class LFunctionZeroSum_abstract(SageObject):
48
+ r"""
49
+ Abstract class for computing certain sums over zeros of a motivic `L`-function
50
+ without having to determine the zeros themselves.
51
+ """
52
+ cdef _pi # Pi to 64 bits
53
+ cdef _euler_gamma # Euler-Mascheroni constant = 0.5772...
54
+ cdef _level # The level of the form attached to self
55
+ cdef _k # The weight of the form attached to self
56
+ cdef _C1 # = log(N)/2 - log(2*pi)
57
+ cdef _C0 # = C1 - euler_gamma
58
+ cdef _ncpus # The number of CPUs to use for parallel computations
59
+
60
+ def ncpus(self, n=None):
61
+ r"""
62
+ Set or return the number of CPUs to be used in parallel computations.
63
+
64
+ If called with no input, the number of CPUs currently set is returned;
65
+ else this value is set to `n`. If `n` is 0 then the number of CPUs is set
66
+ to the max available.
67
+
68
+ INPUT:
69
+
70
+ - ``n`` -- (default: ``None``) if not ``None``, a nonnegative integer
71
+
72
+ OUTPUT: if `n` is not ``None``, returns a positive integer
73
+
74
+ EXAMPLES::
75
+
76
+ sage: Z = LFunctionZeroSum(EllipticCurve("389a"))
77
+ sage: Z.ncpus()
78
+ 1
79
+ sage: Z.ncpus(2)
80
+ sage: Z.ncpus()
81
+ 2
82
+
83
+ The following output will depend on the system that Sage is running on.
84
+
85
+ ::
86
+
87
+ sage: Z.ncpus(0)
88
+ sage: Z.ncpus() # random
89
+ 4
90
+ """
91
+ if n is None:
92
+ return self._ncpus
93
+ elif n < 0:
94
+ raise ValueError("input must be positive integer")
95
+ elif n == 0:
96
+ self._ncpus = num_cpus()
97
+ NCPUS = self._ncpus
98
+ else:
99
+ self._ncpus = n
100
+ NCPUS = self._ncpus
101
+
102
+ def level(self):
103
+ r"""
104
+ Return the level of the form attached to ``self``.
105
+
106
+ If ``self`` was constructed from an elliptic curve,
107
+ then this is equal to the conductor of `E`.
108
+
109
+ EXAMPLES::
110
+
111
+ sage: E = EllipticCurve("389a")
112
+ sage: Z = LFunctionZeroSum(E)
113
+ sage: Z.level()
114
+ 389
115
+ """
116
+ return self._level
117
+
118
+ def weight(self):
119
+ r"""
120
+ Return the weight of the form attached to ``self``.
121
+
122
+ If ``self`` was constructed
123
+ from an elliptic curve, then this is 2.
124
+
125
+ EXAMPLES::
126
+
127
+ sage: E = EllipticCurve("389a")
128
+ sage: Z = LFunctionZeroSum(E)
129
+ sage: Z.weight()
130
+ 2
131
+ """
132
+ return self._k
133
+
134
+ def C0(self, include_euler_gamma=True):
135
+ r"""
136
+ Return the constant term of the logarithmic derivative of the
137
+ completed `L`-function attached to ``self``.
138
+
139
+ This is equal to
140
+ `-\eta + \log(N)/2 - \log(2\pi)`, where `\eta` is the
141
+ Euler-Mascheroni constant `= 0.5772...`
142
+ and `N` is the level of the form attached to ``self``.
143
+
144
+ INPUT:
145
+
146
+ - ``include_euler_gamma`` -- boolean (default: ``True``); if set to
147
+ ``False``, return the constant `\log(N)/2 - \log(2\pi)`, i.e., do
148
+ not subtract the Euler-Mascheroni constant
149
+
150
+ EXAMPLES::
151
+
152
+ sage: E = EllipticCurve("389a")
153
+ sage: Z = LFunctionZeroSum(E)
154
+ sage: Z.C0() # tol 1.0e-13
155
+ 0.5666969404983447
156
+ sage: Z.C0(include_euler_gamma=False) # tol 1.0e-13
157
+ 1.1439126053998776
158
+ """
159
+ # Computed at initialization
160
+ return self._C1 if not include_euler_gamma else self._C0
161
+
162
+ def cnlist(self, n, python_floats=False):
163
+ r"""
164
+ Return a list of Dirichlet coefficient of the logarithmic
165
+ derivative of the `L`-function attached to ``self``, shifted so that
166
+ the critical line lies on the imaginary axis, up to and
167
+ including `n`.
168
+
169
+ The `i`-th element of the returned list is ``a[i]``.
170
+
171
+ INPUT:
172
+
173
+ - ``n`` -- nonnegative integer
174
+
175
+ - ``python_floats`` -- boolean (default: ``False``); if ``True`` return
176
+ a list of Python floats instead of Sage Real Double Field elements
177
+
178
+ OUTPUT: list of real numbers
179
+
180
+ .. SEEALSO::
181
+
182
+ :meth:`~sage.lfunctions.zero_sums.LFunctionZeroSum_EllipticCurve.cn`
183
+
184
+ .. TODO::
185
+
186
+ Speed this up; make more efficient
187
+
188
+ EXAMPLES::
189
+
190
+ sage: E = EllipticCurve("11a")
191
+ sage: Z = LFunctionZeroSum(E)
192
+ sage: cnlist = Z.cnlist(11)
193
+ sage: for n in range(12): print((n, cnlist[n])) # tol 1.0e-13
194
+ (0, 0.0)
195
+ (1, 0.0)
196
+ (2, 0.6931471805599453)
197
+ (3, 0.3662040962227033)
198
+ (4, 0.0)
199
+ (5, -0.32188758248682003)
200
+ (6, 0.0)
201
+ (7, 0.555974328301518)
202
+ (8, -0.34657359027997264)
203
+ (9, 0.6103401603711721)
204
+ (10, 0.0)
205
+ (11, -0.21799047934530644)
206
+ """
207
+ if not python_floats:
208
+ return [self.cn(i) for i in range(n + 1)]
209
+ return [float(self.cn(i)) for i in range(n + 1)]
210
+
211
+ def digamma(self, s, include_constant_term=True):
212
+ r"""
213
+ Return the digamma function `\digamma(s)` on the complex input s.
214
+
215
+ This is given by
216
+ `\digamma(s) = -\eta + \sum_{k=1}^{\infty} \frac{s-1}{k(k+s-1)}`,
217
+ where `\eta` is the Euler-Mascheroni constant `=0.5772156649\ldots`.
218
+
219
+ This function is needed in the computing the logarithmic derivative
220
+ of the `L`-function attached to ``self``.
221
+
222
+ INPUT:
223
+
224
+ - ``s`` -- complex number
225
+
226
+ - ``include_constant_term`` -- boolean (default: ``True``); if set
227
+ to ``False``, only the value of the sum over `k` is returned without
228
+ subtracting the Euler-Mascheroni constant, i.e., the returned value
229
+ is equal to `\sum_{k=1}^{\infty} \frac{s-1}{k(k+s-1)}`
230
+
231
+ OUTPUT:
232
+
233
+ A real double precision number if the input is real and not a negative
234
+ integer; Infinity if the input is a negative integer, and a complex
235
+ number otherwise.
236
+
237
+ EXAMPLES::
238
+
239
+ sage: Z = LFunctionZeroSum(EllipticCurve("37a"))
240
+ sage: Z.digamma(3.2) # tol 1.0e-13
241
+ 0.9988388912865993
242
+ sage: Z.digamma(3.2,include_constant_term=False) # tol 1.0e-13
243
+ 1.576054556188132
244
+ sage: Z.digamma(1+I) # tol 1.0e-13
245
+ 0.09465032062247625 + 1.076674047468581*I
246
+ sage: Z.digamma(-2)
247
+ +Infinity
248
+
249
+ Evaluating the sum without the constant term at the positive integers n
250
+ returns the (n-1)th harmonic number.
251
+
252
+ ::
253
+
254
+ sage: Z.digamma(3,include_constant_term=False)
255
+ 1.5
256
+ sage: Z.digamma(6,include_constant_term=False)
257
+ 2.283333333333333
258
+ """
259
+ # imported here so as to avoid importing Numpy on Sage startup
260
+ from scipy.special import psi
261
+
262
+ if real(s) < 0 and imag(s) == 0:
263
+ try:
264
+ z = ZZ(s)
265
+ return PlusInfinity()
266
+ except Exception:
267
+ pass
268
+
269
+ if imag(s) == 0:
270
+ F = RDF
271
+ else:
272
+ F = CDF
273
+ # Cheating: SciPy already has this function implemented for complex inputs
274
+ z = F(psi(F(s)))
275
+ if include_constant_term:
276
+ return z
277
+ else:
278
+ return z + self._euler_gamma
279
+
280
+ def logarithmic_derivative(self, s, num_terms=10000, as_interval=False):
281
+ r"""
282
+ Compute the value of the logarithmic derivative
283
+ `\frac{L^{\prime}}{L}` at the point s to *low* precision, where `L`
284
+ is the `L`-function attached to ``self``.
285
+
286
+ .. WARNING::
287
+
288
+ The value is computed naively by evaluating the Dirichlet series
289
+ for `\frac{L^{\prime}}{L}`; convergence is controlled by the
290
+ distance of s from the critical strip `0.5<=\Re(s)<=1.5`.
291
+ You may use this method to attempt to compute values inside the
292
+ critical strip; however, results are then *not* guaranteed
293
+ to be correct to any number of digits.
294
+
295
+ INPUT:
296
+
297
+ - ``s`` -- real or complex value
298
+
299
+ - ``num_terms`` -- integer (default: 10000); the maximum number of
300
+ terms summed in the Dirichlet series
301
+
302
+ OUTPUT:
303
+
304
+ A tuple (z,err), where z is the computed value, and err is an
305
+ upper bound on the truncation error in this value introduced
306
+ by truncating the Dirichlet sum.
307
+
308
+ .. NOTE::
309
+
310
+ For the default term cap of 10000, a value accurate to all 53
311
+ bits of a double precision floating point number is only
312
+ guaranteed when `|\Re(s-1)|>4.58`, although in practice inputs
313
+ closer to the critical strip will still yield computed values
314
+ close to the true value.
315
+
316
+ EXAMPLES::
317
+
318
+ sage: E = EllipticCurve([23,100])
319
+ sage: Z = LFunctionZeroSum(E)
320
+ sage: Z.logarithmic_derivative(10) # tol 1.0e-13
321
+ (5.648066742632698e-05, 1.0974102859764345e-34)
322
+ sage: Z.logarithmic_derivative(2.2) # tol 1.0e-13
323
+ (0.5751257063594758, 0.024087912696974387)
324
+
325
+ Increasing the number of terms should see the truncation error
326
+ decrease.
327
+
328
+ ::
329
+
330
+ sage: Z.logarithmic_derivative(2.2,num_terms=50000) # long time # rel tol 1.0e-14
331
+ (0.5751579645060139, 0.008988775519160675)
332
+
333
+ Attempting to compute values inside the critical strip
334
+ gives infinite error.
335
+
336
+ ::
337
+
338
+ sage: Z.logarithmic_derivative(1.3) # tol 1.0e-13
339
+ (5.442994413920786, +Infinity)
340
+
341
+ Complex inputs and inputs to the left of the critical strip
342
+ are allowed.
343
+
344
+ ::
345
+
346
+ sage: Z.logarithmic_derivative(complex(3,-1)) # tol 1.0e-13
347
+ (0.04764548578052381 + 0.16513832809989326*I, 6.584671359095225e-06)
348
+ sage: Z.logarithmic_derivative(complex(-3,-1.1)) # tol 1.0e-13
349
+ (-13.908452173241546 + 2.591443099074753*I, 2.7131584736258447e-14)
350
+
351
+ The logarithmic derivative has poles at the negative integers.
352
+
353
+ ::
354
+
355
+ sage: Z.logarithmic_derivative(-3) # tol 1.0e-13
356
+ (-Infinity, 2.7131584736258447e-14)
357
+ """
358
+ if imag(s) == 0:
359
+ F = RDF
360
+ else:
361
+ F = CDF
362
+ # Inputs left of the critical line are handled via the functional
363
+ # equation of the logarithmic derivative
364
+ if real(s - 1) < 0:
365
+ a = -2 * self._C1 - self.digamma(s) - self.digamma(2 - s)
366
+ b, err = self.logarithmic_derivative(2 - s, num_terms=num_terms)
367
+ return (a + b, err)
368
+
369
+ z = s - 1
370
+ sigma = RDF(real(z))
371
+ # Compute maximum possible Dirichlet series truncation error
372
+ # When s is in the critical strip: no guaranteed precision
373
+ if abs(sigma) <= 0.5:
374
+ err = PlusInfinity()
375
+ else:
376
+ a = RDF(sigma) - RDF(0.5)
377
+ b = log(RDF(num_terms)) * a
378
+ err = (b + 1) * exp(-b) / a**2
379
+
380
+ y = F.zero()
381
+ n = ZZ(2)
382
+ while n <= num_terms:
383
+ if n.is_prime_power():
384
+ cn = self.cn(n)
385
+ y += cn / F(n)**z
386
+ n += 1
387
+
388
+ return (y, err)
389
+
390
+ def completed_logarithmic_derivative(self, s, num_terms=10000):
391
+ r"""
392
+ Compute the value of the completed logarithmic derivative
393
+ `\frac{\Lambda^{\prime}}{\Lambda}` at the point s to *low*
394
+ precision, where `\Lambda = N^{s/2}(2\pi)^s \Gamma(s) L(s)`
395
+ and `L` is the `L`-function attached to ``self``.
396
+
397
+ .. WARNING::
398
+
399
+ This is computed naively by evaluating the Dirichlet series
400
+ for `\frac{L^{\prime}}{L}`; the convergence thereof is
401
+ controlled by the distance of s from the critical strip
402
+ `0.5<=\Re(s)<=1.5`.
403
+ You may use this method to attempt to compute values inside the
404
+ critical strip; however, results are then *not* guaranteed
405
+ to be correct to any number of digits.
406
+
407
+ INPUT:
408
+
409
+ - ``s`` -- real or complex value
410
+
411
+ - ``num_terms`` -- integer (default: 10000); the maximum number of
412
+ terms summed in the Dirichlet series
413
+
414
+ OUTPUT:
415
+
416
+ A tuple (z,err), where z is the computed value, and err is an
417
+ upper bound on the truncation error in this value introduced
418
+ by truncating the Dirichlet sum.
419
+
420
+ .. NOTE::
421
+
422
+ For the default term cap of 10000, a value accurate to all 53
423
+ bits of a double precision floating point number is only
424
+ guaranteed when `|\Re(s-1)|>4.58`, although in practice inputs
425
+ closer to the critical strip will still yield computed values
426
+ close to the true value.
427
+
428
+ .. SEEALSO::
429
+
430
+ :meth:`~sage.lfunctions.zero_sums.LFunctionZeroSum_EllipticCurve.logarithmic_derivative`
431
+
432
+ EXAMPLES::
433
+
434
+ sage: E = EllipticCurve([23,100])
435
+ sage: Z = LFunctionZeroSum(E)
436
+ sage: Z.completed_logarithmic_derivative(3) # tol 1.0e-13
437
+ (6.64372066048195, 6.584671359095225e-06)
438
+
439
+ Complex values are handled. The function is odd about s=1, so
440
+ the value at 2-s should be minus the value at s.
441
+
442
+ ::
443
+
444
+ sage: Z.completed_logarithmic_derivative(complex(-2.2,1)) # tol 1.0e-13
445
+ (-6.898080633125154 + 0.22557015394248361*I, 5.623853049808912e-11)
446
+ sage: Z.completed_logarithmic_derivative(complex(4.2,-1)) # tol 1.0e-13
447
+ (6.898080633125154 - 0.22557015394248361*I, 5.623853049808912e-11)
448
+ """
449
+ if real(s - 1) >= 0:
450
+ Ls = self.logarithmic_derivative(s, num_terms)
451
+ return (self._C1 + self.digamma(s) + Ls[0], Ls[1])
452
+ else:
453
+ Ls = self.logarithmic_derivative(2 - s, num_terms)
454
+ return (-self._C1 - self.digamma(2 - s) - Ls[0], Ls[1])
455
+
456
+ def zerosum(self, Delta=1, tau=0, function='sincsquared_fast', ncpus=None):
457
+ r"""
458
+ Bound from above the analytic rank of the form attached to ``self``.
459
+
460
+ This bound is obtained by computing `\sum_{\gamma} f(\Delta(\gamma-\tau))`,
461
+ where `\gamma` ranges over the imaginary parts of the zeros of `L_E(s)`
462
+ along the critical strip, and `f(x)` is an appropriate even continuous
463
+ `L_2` function such that `f(0)=1`.
464
+
465
+ If `\tau=0`, then as `\Delta` increases this sum converges from above to
466
+ the analytic rank of the `L`-function, as `f(0) = 1` is counted with
467
+ multiplicity `r`, and the other terms all go to 0 uniformly.
468
+
469
+ INPUT:
470
+
471
+ - ``Delta`` -- positive real number (default: 1) parameter denoting the
472
+ tightness of the zero sum
473
+
474
+ - ``tau`` -- real parameter (default: 0) denoting the offset of the sum
475
+ to be computed. When `\tau=0` the sum will converge to the analytic rank
476
+ of the `L`-function as `\Delta` is increased. If `\tau` is the value
477
+ of the imaginary part of a noncentral zero, the limit will be 1
478
+ (assuming the zero is simple); otherwise, the limit will be 0.
479
+ Currently only implemented for the sincsquared and cauchy functions;
480
+ otherwise ignored.
481
+
482
+ - ``function`` -- string (default: ``'sincsquared_fast'``); the function
483
+ `f(x)` as described above. Currently implemented options for `f` are
484
+
485
+ - ``sincsquared`` -- `f(x) = \left(\frac{\sin(\pi x)}{\pi x}\right)^2`
486
+
487
+ - ``gaussian`` -- `f(x) = e^{-x^2}`
488
+
489
+ - ``sincsquared_fast`` -- same as "sincsquared", but implementation
490
+ optimized for elliptic curve `L`-functions, and tau must be 0. self
491
+ must be attached to an elliptic curve over `\QQ` given by its global
492
+ minimal model, otherwise the returned result will be incorrect.
493
+
494
+ - ``sincsquared_parallel`` -- same as "sincsquared_fast", but optimized
495
+ for parallel computation with large (>2.0) `\Delta` values. ``self`` must
496
+ be attached to an elliptic curve over `\QQ` given by its global minimal
497
+ model, otherwise the returned result will be incorrect.
498
+
499
+ - ``cauchy`` -- `f(x) = \frac{1}{1+x^2}`; this is only computable to
500
+ low precision, and only when `\Delta < 2`
501
+
502
+ - ``ncpus`` -- (default: ``None``) if not ``None``, a positive integer
503
+ defining the number of CPUs to be used for the computation. If left as
504
+ ``None``, the maximum available number of CPUs will be used.
505
+ Only implemented for algorithm="sincsquared_parallel"; ignored
506
+ otherwise.
507
+
508
+ .. WARNING::
509
+
510
+ Computation time is exponential in `\Delta`, roughly doubling for
511
+ every increase of 0.1 thereof. Using `\Delta=1` will yield a
512
+ computation time of a few milliseconds; `\Delta=2` takes a few
513
+ seconds, and `\Delta=3` takes upwards of an hour. Increase at your
514
+ own risk beyond this!
515
+
516
+ OUTPUT:
517
+
518
+ A positive real number that bounds from above the number of zeros with
519
+ imaginary part equal to `\tau`. When `\tau=0` this is an upper bound for
520
+ the `L`-function's analytic rank.
521
+
522
+ .. SEEALSO::
523
+
524
+ :meth:`~sage.schemes.elliptic_curves.ell_rational_field.EllipticCurve_rational_field.analytic_rank_bound`
525
+ for more documentation and examples on calling this method on elliptic curve
526
+ `L`-functions.
527
+
528
+ EXAMPLES::
529
+
530
+ sage: E = EllipticCurve("389a"); E.rank()
531
+ 2
532
+ sage: Z = LFunctionZeroSum(E)
533
+ sage: E.lseries().zeros(3)
534
+ [0.000000000, 0.000000000, 2.87609907]
535
+ sage: Z.zerosum(Delta=1,function='sincsquared_fast') # tol 1.0e-13
536
+ 2.037500084595065
537
+ sage: Z.zerosum(Delta=1,function='sincsquared_parallel') # tol 1.0e-11
538
+ 2.037500084595065
539
+ sage: Z.zerosum(Delta=1,function='sincsquared') # tol 1.0e-13
540
+ 2.0375000845950644
541
+ sage: Z.zerosum(Delta=1,tau=2.876,function='sincsquared') # tol 1.0e-13
542
+ 1.075551295651154
543
+ sage: Z.zerosum(Delta=1,tau=1.2,function='sincsquared') # tol 1.0e-13
544
+ 0.10831555377490683
545
+ sage: Z.zerosum(Delta=1,function='gaussian') # tol 1.0e-13
546
+ 2.056890425029435
547
+ """
548
+ # If Delta>6.95, then exp(2*pi*Delta)>sys.maxsize, so we get overflow
549
+ # when summing over the logarithmic derivative coefficients
550
+ if Delta > 6.95:
551
+ raise ValueError("Delta value too large; will result in overflow")
552
+
553
+ if function == "sincsquared_parallel":
554
+ return self._zerosum_sincsquared_parallel(Delta=Delta, ncpus=ncpus)
555
+ elif function == "sincsquared_fast":
556
+ return self._zerosum_sincsquared_fast(Delta=Delta)
557
+ elif function == "sincsquared":
558
+ return self._zerosum_sincsquared(Delta=Delta, tau=tau)
559
+ elif function == "gaussian":
560
+ return self._zerosum_gaussian(Delta=Delta)
561
+ elif function == "cauchy":
562
+ return self._zerosum_cauchy(Delta=Delta, tau=tau)
563
+ else:
564
+ raise ValueError("input function not recognized")
565
+
566
+ def _zerosum_sincsquared(self, Delta=1, tau=0):
567
+ r"""
568
+ Bound from above the analytic rank of the form attached to ``self``.
569
+
570
+ This bound is obtained by computing `\sum_{\gamma} f(\Delta \cdot (\gamma-\tau))`,
571
+ where `\gamma` ranges over the imaginary parts of the zeros of `L_E(s)`
572
+ along the critical strip, and `f(x) = \sin(\pi x)/(\pi x)`
573
+
574
+ If `\tau=0`, then as `\Delta` increases this sum limits from above to
575
+ the analytic rank of the `L`-function, as `f(0) = 1` is counted with
576
+ multiplicity `r`, and the other terms all go to 0 uniformly.
577
+
578
+ INPUT:
579
+
580
+ - ``Delta`` -- positive real number (default: 1) parameter denoting the
581
+ tightness of the zero sum
582
+
583
+ - ``tau`` -- real parameter (default: 0) denoting the offset of the sum
584
+ to be computed. When tau=0 the sum will converge from above to the
585
+ analytic rank of the `L`-function as `\Delta` is increased. If tau
586
+ is the value of the imaginary part of a noncentral zero, the limit
587
+ will be 1 (assuming GRH, the zero is simple); otherwise the limit
588
+ will be 0.
589
+
590
+ .. WARNING::
591
+
592
+ Computation time is exponential in `\Delta`, roughly doubling for
593
+ every increase of 0.1 thereof. Using `\Delta=1` will yield a
594
+ computation time of a few milliseconds; `\Delta=2` takes a few
595
+ seconds, and `\Delta=3` takes upwards of an hour. Increase at your
596
+ own risk beyond this!
597
+
598
+ .. WARNING::
599
+
600
+ This method has *not* been optimized with Cython; as such
601
+ computing with this method is slower than the central sum
602
+ (i.e `\tau=0`) versions of self._zerosum_sincsquared_fast() and
603
+ self._zerosum_sincsquared_parallel().
604
+
605
+ OUTPUT:
606
+
607
+ A positive real number that bounds from above the number of zeros with
608
+ imaginary part equal to tau. When tau=0 this is an upper bound for the
609
+ `L`-function's analytic rank.
610
+
611
+ .. SEEALSO::
612
+
613
+ :meth:`~sage.lfunctions.zero_sums.LFunctionZeroSum_abstract.zerosum`
614
+ for the public method that calls this private method.
615
+
616
+ EXAMPLES::
617
+
618
+ sage: E = EllipticCurve("37a"); E.rank()
619
+ 1
620
+ sage: Z = LFunctionZeroSum(E)
621
+ sage: E.lseries().zeros(2)
622
+ [0.000000000, 5.00317001]
623
+
624
+ E is a rank 1 curve; the lowest noncentral zero has imaginary part
625
+ ~5.003. The zero sum with tau=0 indicates the probable existence of
626
+ a zero at or very close to the central point.
627
+
628
+ ::
629
+
630
+ sage: Z._zerosum_sincsquared(Delta=1,tau=0) # tol 1.0e-13
631
+ 1.0103840698356257
632
+
633
+ The zero sum also detects a zero at or near 5.003, as expected.
634
+
635
+ ::
636
+
637
+ sage: Z._zerosum_sincsquared(Delta=1,tau=5.003) # tol 1.0e-13
638
+ 1.0168124546878288
639
+
640
+ However, there is definitely no zero with imaginary part near 2.5,
641
+ as the sum would have to be at least 1.
642
+
643
+ ::
644
+
645
+ sage: Z._zerosum_sincsquared(Delta=1,tau=2.5) # tol 1.0e-13
646
+ 0.058058210806477814
647
+ """
648
+ npi = self._pi
649
+ twopi = 2 * npi
650
+
651
+ t = RDF(Delta * twopi)
652
+ expt = RDF(exp(t))
653
+
654
+ u = t * self.C0()
655
+
656
+ # No offset: formulae are simpler
657
+ if tau == 0:
658
+ w = npi**2 / 6 - (RDF.one() / expt).dilog()
659
+
660
+ y = RDF(0)
661
+ n = int(1)
662
+ while n < expt:
663
+ cn = self.cn(n)
664
+ if cn != 0:
665
+ logn = RDF(n).log()
666
+ y += cn * (t - logn)
667
+ n += 1
668
+ # When offset is nonzero, the digamma transform (w) must
669
+ # be computed as an infinite sum
670
+ else:
671
+ tau = RDF(tau)
672
+ cos_tau_t = (tau * t).cos()
673
+ sin_tau_t = (tau * t).sin()
674
+ w = RDF.zero()
675
+ for k in range(1, 1001):
676
+ a1 = tau**2 / (k * (k**2 + tau**2))
677
+ a2 = (k**2 - tau**2) / (k**2 + tau**2)**2
678
+ a3 = (2 * k * tau) / (k**2 + tau**2)**2
679
+
680
+ w0 = a1 * t + a2
681
+ w0 -= (a2 * cos_tau_t - a3 * sin_tau_t) * exp(-k * t)
682
+ w += w0
683
+
684
+ y = RDF.zero()
685
+ n = int(1)
686
+ while n < expt:
687
+ cn = self.cn(n)
688
+ if cn != 0:
689
+ logn = RDF(n).log()
690
+ y += cn * (t - logn) * (tau * logn).cos()
691
+ n += 1
692
+
693
+ return (u + w + y) * 2 / (t**2)
694
+
695
+ def _zerosum_gaussian(self, Delta=1):
696
+ r"""
697
+ Return an upper bound on the analytic rank of the `L`-series attached
698
+ to ``self`` by computing `\sum_{\gamma} f(\Delta*\gamma)`,
699
+ where `\gamma` ranges over the imaginary parts of the zeros of `L_E(s)`
700
+ along the critical strip, and `f(x) = \exp(-x^2)`.
701
+
702
+ As `\Delta` increases this sum limits from above to the analytic rank
703
+ of the form, as `f(0) = 1` is counted with multiplicity `r`, and the
704
+ other terms all go to 0 uniformly.
705
+
706
+ INPUT:
707
+
708
+ - ``Delta`` -- positive real number (default: 1) parameter defining the
709
+ tightness of the zero sum, and thus the closeness of the returned
710
+ estimate to the actual analytic rank of the form attached to ``self``.
711
+
712
+ .. WARNING::
713
+
714
+ Computation time is exponential in `\Delta`, roughly doubling for
715
+ every increase of 0.1 thereof. Using `\Delta=1` will yield a
716
+ computation time of a few milliseconds; `\Delta=2` takes a few
717
+ seconds, and `\Delta=3` takes upwards of an hour. Increase at your
718
+ own risk beyond this!
719
+
720
+ OUTPUT:
721
+
722
+ A positive real number that bounds the analytic rank of the modular form
723
+ attached to ``self`` from above.
724
+
725
+ .. SEEALSO::
726
+
727
+ :meth:`~sage.lfunctions.zero_sums.LFunctionZeroSum_abstract.zerosum`
728
+ for the public method that calls this private method.
729
+
730
+ EXAMPLES::
731
+
732
+ sage: E = EllipticCurve("37a"); E.rank()
733
+ 1
734
+ sage: Z = LFunctionZeroSum(E)
735
+ sage: Z._zerosum_gaussian(Delta=1) # tol 1.0e-13
736
+ 1.0563950773441664
737
+ """
738
+ # imported here so as to avoid importing Numpy on Sage startup
739
+ from scipy.special import erfcx
740
+
741
+ npi = self._pi
742
+ Deltasqrtpi = Delta * npi.sqrt()
743
+
744
+ t = RDF(Delta * npi * 2)
745
+ expt = t.exp()
746
+
747
+ u = self.C0()
748
+
749
+ w = RDF.zero()
750
+ for k in range(1, 1001):
751
+ w += RDF.one() / k - erfcx(Delta * k) * Deltasqrtpi
752
+
753
+ y = RDF.zero()
754
+ n = int(1)
755
+
756
+ # TO DO: Error analysis to make sure this bound is good enough to
757
+ # avoid non-negligible truncation error
758
+ while n < expt:
759
+ cn = self.cn(n)
760
+ if cn != 0:
761
+ logn = log(RDF(n))
762
+ y += cn * exp(-(logn / (2 * Delta))**2)
763
+ n += 1
764
+ # y is the truncation of an infinite sum, so we must add a value which
765
+ # exceeds the max amount we could have left out.
766
+ # WARNING: Truncation error analysis has *not* been done; the value of
767
+ # 0.1 is empirical.
768
+ return RDF(u + w + y + 0.1) / Deltasqrtpi
769
+
770
+ def _zerosum_cauchy(self, Delta=1, tau=0, num_terms=None):
771
+ r"""
772
+ Bound from above the analytic rank of the form attached to ``self``
773
+ by computing `\sum_{\gamma} f(\Delta*(\gamma-\tau))`,
774
+ where `\gamma` ranges over the imaginary parts of the zeros of `L_E(s)`
775
+ along the critical strip, and `f(x) = \frac{1}{1+x^2}`.
776
+
777
+ If `\tau=0`, then as `\Delta` increases this sum converges from above
778
+ to the analytic rank of the `L`-function, as `f(0) = 1` is counted
779
+ with multiplicity `r`, and the other terms all go to 0 uniformly.
780
+
781
+ INPUT:
782
+
783
+ - ``Delta`` -- positive real number (default: 1); parameter denoting the
784
+ tightness of the zero sum
785
+
786
+ - ``tau`` -- real parameter (default: 0) denoting the offset of the sum
787
+ to be computed. When tau=0 the sum will converge from above to the
788
+ analytic rank of the `L`-function as `\Delta` is increased. If tau is
789
+ the value of the imaginary part of a noncentral zero, the limit will
790
+ be 1 (assuming GRH, the zero is simple); otherwise the limit will
791
+ be 0.
792
+
793
+ - ``num_terms`` -- positive integer (default: ``None``); the number of
794
+ terms computed in the truncated Dirichlet series for the `L`-function
795
+ attached to ``self``. If left at ``None``, this is set to
796
+ `\ceil(e^{2 \pi \Delta})`, the same number of terms used in the other
797
+ zero sum methods for this value of Delta.
798
+ Increase num_terms to get more accuracy.
799
+
800
+ .. WARNING::
801
+
802
+ This value can only be provably computed when Delta < 2; an error
803
+ will be thrown if a Delta value larger than 2 is supplied.
804
+ Furthermore, beware that computation time is exponential in
805
+ `\Delta`, roughly doubling for every increase of 0.1 thereof.
806
+ Using `\Delta=1` will yield a computation time of a few
807
+ milliseconds, while `\Delta=2` takes a few seconds.
808
+
809
+ OUTPUT:
810
+
811
+ A positive real number that bounds from above the number of zeros with
812
+ imaginary part equal to tau. When tau=0 this is an upper bound for the
813
+ `L`-function's analytic rank.
814
+
815
+ .. SEEALSO::
816
+
817
+ :meth:`~sage.lfunctions.zero_sums.LFunctionZeroSum_abstract.zerosum`
818
+ for the public method that calls this private method.
819
+
820
+ EXAMPLES::
821
+
822
+ sage: E = EllipticCurve("11a")
823
+ sage: zeros = E.lseries().zeros(2)
824
+ sage: zeros[0] # abs tol 1e-8
825
+ 6.36261389
826
+ sage: zeros[1] # abs tol 1e-8
827
+ 8.60353962
828
+
829
+ E is a rank zero curve; the lowest zero has imaginary part ~6.36. The
830
+ zero sum with tau=0 indicates that there are no zeros at the central
831
+ point (otherwise the returned value would be at least 1).
832
+
833
+ ::
834
+
835
+ sage: Z = LFunctionZeroSum(E)
836
+ sage: Z._zerosum_cauchy(Delta=1,tau=0) # tol 1.0e-13
837
+ 0.9701073984459051
838
+
839
+ The zero sum with tau=6.36 indicates there might be a zero in the
840
+ vicinity.
841
+
842
+ ::
843
+
844
+ sage: Z._zerosum_cauchy(Delta=1,tau=6.36261389) # tol 1.0e-13
845
+ 2.180904626331156
846
+
847
+ However, there are no zeros with imaginary part close to 1.5.
848
+
849
+ ::
850
+
851
+ sage: Z._zerosum_cauchy(Delta=1,tau=1.5) # tol 1.0e-13
852
+ 0.9827072037553375
853
+
854
+ Because of the weak convergence of the Dirichlet series close to the
855
+ critical line, the bound will in general get *worse* for larger Delta.
856
+ This can be mitigated somewhat by increasing the number of terms.
857
+
858
+ ::
859
+
860
+ sage: Z._zerosum_cauchy(Delta=1.5) # tol 1.0e-13
861
+ 12.93835258975716
862
+ sage: Z._zerosum_cauchy(Delta=1.5,num_terms=100000) # tol 1.0e-13
863
+ 10.395183960836599
864
+
865
+ An error will be thrown if a Delta value >= 2 is passed.
866
+
867
+ ::
868
+
869
+ sage: Z._zerosum_cauchy(Delta=2)
870
+ Traceback (most recent call last):
871
+ ...
872
+ ValueError: bound not provably computable for Delta >= 2
873
+ """
874
+ if Delta >= 2:
875
+ raise ValueError("bound not provably computable for Delta >= 2")
876
+ Del = RDF(Delta)
877
+ if num_terms is None:
878
+ num_terms = int(exp(2 * self._pi * Del))
879
+
880
+ if tau == 0:
881
+ one = RDF.one()
882
+ s = one / Del + one
883
+ u, err = self.completed_logarithmic_derivative(s, num_terms)
884
+ else:
885
+ one = CDF.one()
886
+ s = CDF(one / Del + one, tau)
887
+ u, err = self.completed_logarithmic_derivative(s, num_terms)
888
+ u = u.real()
889
+
890
+ return (u + err) / Del
891
+
892
+
893
+ cdef class LFunctionZeroSum_EllipticCurve(LFunctionZeroSum_abstract):
894
+ r"""
895
+ Subclass for computing certain sums over zeros of an elliptic curve `L`-function
896
+ without having to determine the zeros themselves.
897
+ """
898
+ cdef _E # The Elliptic curve attached to self
899
+ cdef _e # PARI ellcurve object used to compute a_p values
900
+
901
+ def __init__(self, E, N=None, ncpus=1):
902
+ r"""
903
+ Initialize ``self``.
904
+
905
+ INPUT:
906
+
907
+ - ``E`` -- an elliptic curve defined over the rational numbers
908
+
909
+ - ``N`` -- (default: ``None``) if not ``None``, a positive integer equal to
910
+ the conductor of E. This is passable so that rank estimation
911
+ can be done for curves whose (large) conductor has been precomputed.
912
+
913
+ - ``ncpus`` -- (default: 1) the number of CPUs to use for computations;
914
+ if set to ``None``, the max available amount will be used
915
+
916
+ EXAMPLES::
917
+
918
+ sage: from sage.lfunctions.zero_sums import LFunctionZeroSum_EllipticCurve
919
+ sage: E = EllipticCurve([1,0,0,3,-4])
920
+ sage: Z = LFunctionZeroSum_EllipticCurve(E); Z
921
+ Zero sum estimator for L-function attached to Elliptic Curve defined by y^2 + x*y = x^3 + 3*x - 4 over Rational Field
922
+ sage: E = EllipticCurve("5077a")
923
+ sage: Z = LFunctionZeroSum_EllipticCurve(E); Z
924
+ Zero sum estimator for L-function attached to Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
925
+ """
926
+ self._k = ZZ(2)
927
+ self._E = E
928
+ if N is not None:
929
+ self._level = N
930
+ else:
931
+ self._level = E.conductor()
932
+ # PARI minicurve for computing a_p coefficients
933
+ self._e = E.pari_mincurve()
934
+
935
+ self._pi = RDF(pi)
936
+ self._euler_gamma = RDF(euler_gamma)
937
+
938
+ # These constants feature in most (all?) sums over the L-function's zeros
939
+ self._C1 = RDF(self._level).log() / 2 - log(self._pi * 2)
940
+ self._C0 = self._C1 - self._euler_gamma
941
+
942
+ # Number of CPUs to use for computations
943
+ if ncpus is None:
944
+ self._ncpus = num_cpus()
945
+ NCPUS = self._ncpus
946
+ else:
947
+ self._ncpus = ncpus
948
+ NCPUS = self._ncpus
949
+
950
+ def __repr__(self):
951
+ r"""
952
+ Representation of ``self``.
953
+
954
+ EXAMPLES::
955
+
956
+ sage: Z = LFunctionZeroSum(EllipticCurve("37a")); Z
957
+ Zero sum estimator for L-function attached to Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
958
+ """
959
+ s = "Zero sum estimator for L-function attached to "
960
+ return s + str(self._E)
961
+
962
+ def elliptic_curve(self):
963
+ r"""
964
+ Return the elliptic curve associated with ``self``.
965
+
966
+ EXAMPLES::
967
+
968
+ sage: E = EllipticCurve([23,100])
969
+ sage: Z = LFunctionZeroSum(E)
970
+ sage: Z.elliptic_curve()
971
+ Elliptic Curve defined by y^2 = x^3 + 23*x + 100 over Rational Field
972
+ """
973
+ return self._E
974
+
975
+ def lseries(self):
976
+ r"""
977
+ Return the `L`-series associated with ``self``.
978
+
979
+ EXAMPLES::
980
+
981
+ sage: E = EllipticCurve([23,100])
982
+ sage: Z = LFunctionZeroSum(E)
983
+ sage: Z.lseries()
984
+ Complex L-series of the Elliptic Curve defined by y^2 = x^3 + 23*x + 100 over Rational Field
985
+ """
986
+ return self._E.lseries()
987
+
988
+ def cn(self, n):
989
+ r"""
990
+ Return the `n`-th Dirichlet coefficient of the logarithmic
991
+ derivative of the `L`-function attached to ``self``, shifted so that
992
+ the critical line lies on the imaginary axis.
993
+
994
+ The returned value is
995
+ zero if `n` is not a perfect prime power;
996
+ when `n=p^e` for `p` a prime of bad reduction it is `-a_p^e log(p)/p^e`,
997
+ where `a_p` is `+1, -1` or `0` according to the reduction type of `p`;
998
+ and when `n=p^e` for a prime `p` of good reduction, the value
999
+ is `-(\alpha_p^e + \beta_p^e) \log(p)/p^e`, where `\alpha_p`
1000
+ and `\beta_p` are the two complex roots of the characteristic equation
1001
+ of Frobenius at `p` on `E`.
1002
+
1003
+ INPUT:
1004
+
1005
+ - ``n`` -- nonnegative integer
1006
+
1007
+ OUTPUT:
1008
+
1009
+ A real number which (by Hasse's Theorem) is at
1010
+ most `2\frac{log(n)}{\sqrt{n}}` in magnitude.
1011
+
1012
+ EXAMPLES::
1013
+
1014
+ sage: E = EllipticCurve("11a")
1015
+ sage: Z = LFunctionZeroSum(E)
1016
+ sage: for n in range(12): print((n, Z.cn(n))) # tol 1.0e-13
1017
+ (0, 0.0)
1018
+ (1, 0.0)
1019
+ (2, 0.6931471805599453)
1020
+ (3, 0.3662040962227033)
1021
+ (4, 0.0)
1022
+ (5, -0.32188758248682003)
1023
+ (6, 0.0)
1024
+ (7, 0.555974328301518)
1025
+ (8, -0.34657359027997264)
1026
+ (9, 0.6103401603711721)
1027
+ (10, 0.0)
1028
+ (11, -0.21799047934530644)
1029
+ """
1030
+ n = ZZ(n)
1031
+ if n == 0 or n == 1:
1032
+ return RDF.zero()
1033
+ if not n.is_prime_power():
1034
+ return RDF.zero()
1035
+
1036
+ n_float = RDF(n)
1037
+ if n.is_prime():
1038
+ logn = log(n_float)
1039
+ ap = self._E.ap(n)
1040
+ return -ap * logn / n_float
1041
+ else:
1042
+ p, e = n.perfect_power()
1043
+ ap = self._E.ap(p)
1044
+ logp = RDF(p).log()
1045
+ if p.divides(self._level):
1046
+ return - ap**e * logp / n_float
1047
+ a, b = ap, 2
1048
+ # Coefficients for higher powers obey recursion relation
1049
+ for n in range(2, e + 1):
1050
+ a, b = ap * a - p * b, a
1051
+ return -a * logp / n_float
1052
+
1053
+ cdef double _sincsquared_summand_1(self,
1054
+ unsigned long n,
1055
+ double t,
1056
+ int ap,
1057
+ double p,
1058
+ double logp,
1059
+ double thetap,
1060
+ double sqrtp,
1061
+ double logq,
1062
+ double thetaq,
1063
+ double sqrtq,
1064
+ double z) noexcept:
1065
+ r"""
1066
+ Private cdef method to compute the logarithmic derivative
1067
+ summand for the sinc^2 sum at prime values for when
1068
+ n <= sqrt(bound), bound = exp(t)
1069
+ Called in self._zerosum_sincsquared_fast() method
1070
+ """
1071
+ ap = self._e.ellap(n)
1072
+ p = n
1073
+ sqrtp = c_sqrt(p)
1074
+ thetap = c_acos(ap / (2 * sqrtp))
1075
+ logp = c_log(p)
1076
+
1077
+ sqrtq = 1
1078
+ thetaq = 0
1079
+ logq = logp
1080
+
1081
+ z = 0
1082
+ while logq < t:
1083
+ sqrtq *= sqrtp
1084
+ thetaq += thetap
1085
+ z += 2 * c_cos(thetaq) * (t - logq) / sqrtq
1086
+ logq += logp
1087
+ return -z * logp
1088
+
1089
+ cdef double _sincsquared_summand_2(self,
1090
+ unsigned long n,
1091
+ double t,
1092
+ int ap,
1093
+ double p,
1094
+ double logp) noexcept:
1095
+ r"""
1096
+ Private cdef method to compute the logarithmic derivative
1097
+ summand for the sinc^2 sum at prime values for when
1098
+ sqrt(bound) < n < bound, bound = exp(t)
1099
+ Called in self._zerosum_sincsquared_fast() method
1100
+ """
1101
+ ap = self._e.ellap(n)
1102
+ p = n
1103
+ logp = c_log(p)
1104
+ return -(t - logp) * (logp / p) * ap
1105
+
1106
+ cpdef _zerosum_sincsquared_fast(self, Delta=1, bad_primes=None):
1107
+ r"""
1108
+ A faster cythonized implementation of self._zerosum_sincsquared().
1109
+
1110
+ .. NOTE::
1111
+
1112
+ This will only produce correct output if self._E is given by its
1113
+ global minimal model, i.e., if self._E.is_minimal() is ``True``.
1114
+
1115
+ INPUT:
1116
+
1117
+ - ``Delta`` -- positive real parameter defining the
1118
+ tightness of the zero sum, and thus the closeness of the returned
1119
+ estimate to the actual analytic rank of the form attached to ``self``
1120
+
1121
+ - ``bad_primes`` -- (default: ``None``) if not ``None``, a list of primes dividing
1122
+ the level of the form attached to ``self``. This is passable so that this
1123
+ method can be run on curves whose conductor is large enough to warrant
1124
+ precomputing bad primes.
1125
+
1126
+ OUTPUT:
1127
+
1128
+ A positive real number that bounds the analytic rank of the modular form
1129
+ attached to ``self`` from above.
1130
+
1131
+ .. SEEALSO::
1132
+
1133
+ :meth:`~sage.lfunctions.zero_sums.LFunctionZeroSum_abstract.zerosum_sincsquared`
1134
+ for the more general but slower version of this method.
1135
+
1136
+ :meth:`~sage.lfunctions.zero_sums.LFunctionZeroSum_abstract.zerosum`
1137
+ for the public method that calls this private method.
1138
+
1139
+ EXAMPLES::
1140
+
1141
+ sage: E = EllipticCurve("37a")
1142
+ sage: Z = LFunctionZeroSum(E)
1143
+ sage: print((E.rank(),Z._zerosum_sincsquared_fast(Delta=1))) # tol 1.0e-13
1144
+ (1, 1.0103840698356263)
1145
+ sage: E = EllipticCurve("121a")
1146
+ sage: Z = LFunctionZeroSum(E)
1147
+ sage: print((E.rank(),Z._zerosum_sincsquared_fast(Delta=1.5))) # tol 1.0e-13
1148
+ (0, 0.0104712060086507)
1149
+ """
1150
+ # If Delta>6.619, then we will most likely get overflow: some ap values
1151
+ # will be too large to fit into a c int
1152
+ if Delta > 6.619:
1153
+ raise ValueError("Delta value too large; will result in overflow")
1154
+
1155
+ cdef double npi = self._pi
1156
+ cdef double twopi = npi * 2
1157
+ cdef double eg = self._euler_gamma
1158
+
1159
+ cdef double t, u, w, y, z, expt, bound1, logp, logq
1160
+ cdef double thetap, thetaq, sqrtp, sqrtq, p, q
1161
+ cdef int ap, aq
1162
+
1163
+ cdef unsigned long n
1164
+ cdef double N_double = self._level
1165
+
1166
+ t = twopi * Delta
1167
+ expt = c_exp(t)
1168
+
1169
+ u = t * (-eg + c_log(N_double) / 2 - c_log(twopi))
1170
+ w = npi**2 / 6 - (RDF.one() / expt).dilog()
1171
+
1172
+ y = 0
1173
+ # Do bad primes first. Add correct contributions and subtract
1174
+ # incorrect contribution, since we'll add them back later on.
1175
+ if bad_primes is None:
1176
+ bad_primes = self._level.prime_divisors()
1177
+ bad_primes = [prime for prime in bad_primes if prime < expt]
1178
+ for prime in bad_primes:
1179
+ n = prime
1180
+ ap = self._e.ellap(n)
1181
+ p = n
1182
+ sqrtp = c_sqrt(p)
1183
+ thetap = c_acos(ap / (2 * sqrtp))
1184
+ logp = c_log(p)
1185
+
1186
+ q = 1
1187
+ sqrtq = 1
1188
+ aq = 1
1189
+ thetaq = 0
1190
+ logq = logp
1191
+
1192
+ z = 0
1193
+ while logq < t:
1194
+ q *= p
1195
+ sqrtq *= sqrtp
1196
+ aq *= ap
1197
+ thetaq += thetap
1198
+ # Actual value of this term
1199
+ z += (aq / q) * (t - logq)
1200
+ # Incorrect value of this term to be removed below
1201
+ z -= 2 * c_cos(thetaq) * (t - logq) / sqrtq
1202
+ logq += logp
1203
+ y -= z * logp
1204
+
1205
+ # Good prime case. Bad primes are treated as good primes, but their
1206
+ # contribution here is cancelled out above; this way we don't
1207
+ # have to check if each prime divides the level or not.
1208
+
1209
+ # Must deal with n=2,3,5 separately
1210
+ for m in [2, 3, 5]:
1211
+ n = m
1212
+ if n < expt:
1213
+ y += self._sincsquared_summand_1(n, t, ap, p, logp, thetap,
1214
+ sqrtp, logq, thetaq, sqrtq, z)
1215
+ # Now iterate only over those n that are 1 or 5 mod 6
1216
+ n = 11
1217
+ # First: those n that are <= sqrt(bound)
1218
+ bound1 = c_exp(t / 2)
1219
+ while n <= bound1:
1220
+ if n_is_prime(n - 4):
1221
+ y += self._sincsquared_summand_1(n - 4, t, ap, p, logp, thetap,
1222
+ sqrtp, logq, thetaq, sqrtq, z)
1223
+ if n_is_prime(n):
1224
+ y += self._sincsquared_summand_1(n, t, ap, p, logp, thetap,
1225
+ sqrtp, logq, thetaq, sqrtq, z)
1226
+ n += 6
1227
+ # Unlucky split case where n-4 <= sqrt(bound) but n isn't
1228
+ if n - 4 <= bound1 < n:
1229
+ if n_is_prime(n - 4):
1230
+ y += self._sincsquared_summand_1(n - 4, t, ap, p, logp, thetap,
1231
+ sqrtp, logq, thetaq, sqrtq, z)
1232
+ if n <= expt and n_is_prime(n):
1233
+ y += self._sincsquared_summand_2(n, t, ap, p, logp)
1234
+ n += 6
1235
+ # Now sqrt(bound)< n < bound, so we don't need to consider higher
1236
+ # prime power logarithmic derivative coefficients
1237
+ while n <= expt:
1238
+ if n_is_prime(n - 4):
1239
+ y += self._sincsquared_summand_2(n - 4, t, ap, p, logp)
1240
+ if n_is_prime(n):
1241
+ y += self._sincsquared_summand_2(n, t, ap, p, logp)
1242
+ n += 6
1243
+ # Case where n-4 <= t but n isn't
1244
+ n = n - 4
1245
+ if n <= expt and n_is_prime(n):
1246
+ y += self._sincsquared_summand_2(n, t, ap, p, logp)
1247
+
1248
+ return RDF(2 * (u + w + y) / (t**2))
1249
+
1250
+ def _get_residue_data(self, n):
1251
+ r"""
1252
+ Method called by ``self._zerosum_sincsquared_parallel()`` to determine
1253
+ the optimal residue class breakdown when sieving for primes.
1254
+
1255
+ Return a list of small primes, the product thereof, and a list of
1256
+ residues coprime to the product.
1257
+
1258
+ INPUT:
1259
+
1260
+ - ``n`` -- positive integer denoting the number of required chunks
1261
+
1262
+ OUTPUT:
1263
+
1264
+ A triple ``(small_primes, M, residue_chunks)`` such that
1265
+
1266
+ - ``small_primes`` -- list of small primes
1267
+
1268
+ - ``modulus`` -- the product of the small primes
1269
+
1270
+ - ``residue_chunks`` -- list of lists consisting of all integers
1271
+ less than the modulus that are coprime to it, broken into `n`
1272
+ sublists of approximately equal size
1273
+
1274
+ EXAMPLES::
1275
+
1276
+ sage: E = EllipticCurve("37a"); Z = LFunctionZeroSum(E)
1277
+ sage: Z._get_residue_data(8)
1278
+ ([2, 3, 5, 7],
1279
+ 210,
1280
+ [[1, 37, 71, 107, 143, 179],
1281
+ [11, 41, 73, 109, 149, 181],
1282
+ [13, 43, 79, 113, 151, 187],
1283
+ [17, 47, 83, 121, 157, 191],
1284
+ [19, 53, 89, 127, 163, 193],
1285
+ [23, 59, 97, 131, 167, 197],
1286
+ [29, 61, 101, 137, 169, 199],
1287
+ [31, 67, 103, 139, 173, 209]])
1288
+ """
1289
+ # If n <=48, primes are sieved for modulo 210
1290
+ if n <= 48:
1291
+ small_primes = [2, 3, 5, 7]
1292
+ modulus = 210
1293
+ residue_list = [1, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
1294
+ 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
1295
+ 107, 109, 113, 121, 127, 131, 137, 139, 143, 149,
1296
+ 151, 157, 163, 167, 169, 173, 179, 181, 187, 191,
1297
+ 193, 197, 199, 209]
1298
+ # General case for n > 480
1299
+ else:
1300
+ from sage.rings.finite_rings.integer_mod import mod
1301
+
1302
+ modulus, p = 2, 2
1303
+ small_primes, residue_list = [2], [1]
1304
+ num_residues = 1
1305
+ # Enlarge residue_list by repeatedly applying Chinese Remainder
1306
+ # Theorem
1307
+ while num_residues < n:
1308
+ p = next_prime(p)
1309
+ small_primes.append(p)
1310
+ g, h = (mod(p, modulus)**(-1)).lift(), (mod(modulus, p)**(-1)).lift()
1311
+ residue_list = [(a * p * g + b * modulus * h) % (modulus * p)
1312
+ for a in residue_list
1313
+ for b in range(1, p)]
1314
+ num_residues = num_residues * (p - 1)
1315
+ modulus *= p
1316
+ residue_list.sort()
1317
+
1318
+ # Break residue_list into n chunks
1319
+ residue_chunks = [[residue_list[i] for i in range(len(residue_list))
1320
+ if i % n == k] for k in range(n)]
1321
+
1322
+ return small_primes, modulus, residue_chunks
1323
+
1324
+ @parallel(ncpus=NCPUS)
1325
+ def _sum_over_residues(self, residue_sum_data):
1326
+ r"""
1327
+ Return the p-power sum over residues in a residue chunk
1328
+ """
1329
+ modulus, residues = residue_sum_data[0], residue_sum_data[1]
1330
+
1331
+ cdef double y = 0
1332
+ cdef unsigned long n = residues[0]
1333
+ cdef double t = residue_sum_data[2]
1334
+ cdef double expt = residue_sum_data[3]
1335
+ cdef double bound1 = residue_sum_data[4]
1336
+
1337
+ cdef double z = 0
1338
+ cdef double p = 0
1339
+ cdef double sqrtp = 0
1340
+ cdef double sqrtq = 0
1341
+ cdef double logp = 0
1342
+ cdef double logq = 0
1343
+ cdef double thetap = 0
1344
+ cdef double thetaq = 0
1345
+ cdef int ap = 0
1346
+
1347
+ # Generate a list of increments so that n iterates over integers with
1348
+ # residues in the residue list
1349
+ len_increment_list = len(residues)
1350
+ increments = [residues[i + 1] - residues[i]
1351
+ for i in range(len_increment_list - 1)]
1352
+ increments.append(modulus + residues[0] - residues[-1])
1353
+
1354
+ i = 0
1355
+ # up to bound1=sqrt(expt), higher powers of p must be summed over too
1356
+ while n < bound1:
1357
+ if n_is_prime(n):
1358
+ y += self._sincsquared_summand_1(n, t, ap, p, logp,
1359
+ thetap, sqrtp, logq,
1360
+ thetaq, sqrtq, z)
1361
+ n += increments[i]
1362
+ # cycle over increments
1363
+ i += 1
1364
+ if i >= len_increment_list:
1365
+ i = 0
1366
+
1367
+ # when bound1 <= n < expt, we don't need to consider higher powers of p
1368
+ while n < expt:
1369
+ if n_is_prime(n):
1370
+ y += self._sincsquared_summand_2(n, t, ap, p, logp)
1371
+ n += increments[i]
1372
+ # cycle over increments
1373
+ i += 1
1374
+ if i >= len_increment_list:
1375
+ i = 0
1376
+
1377
+ return y
1378
+
1379
+ def _zerosum_sincsquared_parallel(self,
1380
+ Delta=1,
1381
+ bad_primes=None,
1382
+ ncpus=None):
1383
+ r"""
1384
+ Parallelized implementation of self._zerosum_sincsquared_fast().
1385
+
1386
+ Faster than self._zerosum_sincsquared_fast() when Delta >= ~1.75.
1387
+
1388
+ .. NOTE::
1389
+
1390
+ This will only produce correct output if self._E is given by its
1391
+ global minimal model, i.e. if self._E.is_minimal() is ``True``.
1392
+
1393
+ INPUT:
1394
+
1395
+ - ``Delta`` -- positive real parameter defining the
1396
+ tightness of the zero sum, and thus the closeness of the returned
1397
+ estimate to the actual analytic rank of the form attached to ``self``.
1398
+
1399
+ - ``bad_primes`` -- (default: ``None``) if not ``None``, a list of primes dividing
1400
+ the level of the form attached to ``self``. This is passable so that this
1401
+ method can be run on curves whose conductor is large enough to warrant
1402
+ precomputing bad primes.
1403
+
1404
+ - ``ncpus`` -- (default: ``None``) if not ``None``, a positive integer
1405
+ defining the number of CPUs to be used for the computation. If left as
1406
+ ``None``, the maximum available number of CPUs will be used.
1407
+
1408
+ OUTPUT:
1409
+
1410
+ A positive real number that bounds the analytic rank of the modular form
1411
+ attached to ``self`` from above.
1412
+
1413
+ .. SEEALSO::
1414
+
1415
+ :meth:`~sage.lfunctions.zero_sums.LFunctionZeroSum_abstract.zerosum_sincsquared`
1416
+ for the more general but slower version of this method.
1417
+
1418
+ :meth:`~sage.lfunctions.zero_sums.LFunctionZeroSum_abstract.zerosum`
1419
+ for the public method that calls this private method.
1420
+
1421
+ EXAMPLES::
1422
+
1423
+ sage: E = EllipticCurve("37a"); print(E.rank())
1424
+ 1
1425
+ sage: Z = LFunctionZeroSum(E)
1426
+ sage: print(Z._zerosum_sincsquared_parallel(Delta=1)) # tol 1.0e-11
1427
+ 1.0103840698356263
1428
+ sage: E = EllipticCurve("121a"); print(E.rank())
1429
+ 0
1430
+ sage: Z = LFunctionZeroSum(E)
1431
+ sage: print(Z._zerosum_sincsquared_parallel(Delta=1.5,ncpus=2)) # tol 1.0e-11
1432
+ 0.01047120600865063
1433
+ """
1434
+ # If Delta>6.619, then we will most likely get overflow: some ap values
1435
+ # will be too large to fit into a c int
1436
+ if Delta > 6.619:
1437
+ raise ValueError("Delta value too large; will result in overflow")
1438
+
1439
+ cdef double npi = self._pi
1440
+ cdef double twopi = npi * 2
1441
+ cdef double eg = self._euler_gamma
1442
+ cdef double N_double = self._level
1443
+
1444
+ cdef double t, u, w, y, z, expt, bound1, logp, logq
1445
+ cdef double thetap, thetaq, sqrtp, sqrtq, p, q
1446
+ cdef int ap, aq
1447
+ cdef unsigned long n
1448
+
1449
+ # Compute bounds and smooth part of sum
1450
+ t = twopi * Delta
1451
+ expt = c_exp(t)
1452
+ bound1 = c_exp(t / 2)
1453
+ u = t * (-eg + c_log(N_double) / 2 - c_log(twopi))
1454
+ w = npi**2 / 6 - (RDF.one() / expt).dilog()
1455
+
1456
+ # Oscillating part of sum
1457
+ y = 0
1458
+ # Do bad primes first. Add correct contributions and subtract
1459
+ # incorrect contribution; the latter are added back later on.
1460
+ if bad_primes is None:
1461
+ bad_primes = self._level.prime_divisors()
1462
+ bad_primes = [prime for prime in bad_primes if prime < expt]
1463
+ for prime in bad_primes:
1464
+ n = prime
1465
+ ap = self._e.ellap(n)
1466
+ p = n
1467
+ sqrtp = c_sqrt(p)
1468
+ thetap = c_acos(ap / (2 * sqrtp))
1469
+ logp = c_log(p)
1470
+
1471
+ q = 1
1472
+ sqrtq = 1
1473
+ aq = 1
1474
+ thetaq = 0
1475
+ logq = logp
1476
+
1477
+ z = 0
1478
+ while logq < t:
1479
+ q *= p
1480
+ sqrtq *= sqrtp
1481
+ aq *= ap
1482
+ thetaq += thetap
1483
+ # Actual value of this term
1484
+ z += (aq / q) * (t - logq)
1485
+ # Incorrect value of this term to be removed below
1486
+ z -= 2 * c_cos(thetaq) * (t - logq) / sqrtq
1487
+ logq += logp
1488
+ y -= z * logp
1489
+
1490
+ # Good prime case. Bad primes are treated as good primes, but their
1491
+ # contribution here is cancelled out above; this way we don't
1492
+ # have to check if each prime divides the level or not.
1493
+ if ncpus is not None:
1494
+ self._ncpus = ncpus
1495
+ else:
1496
+ ncpus = self._ncpus
1497
+ small_primes, modulus, residue_chunks = self._get_residue_data(ncpus)
1498
+
1499
+ # We must deal with small primes separately
1500
+ for m in small_primes:
1501
+ n = m
1502
+ if n < expt:
1503
+ y += self._sincsquared_summand_1(n, t, ap, p, logp,
1504
+ thetap, sqrtp, logq,
1505
+ thetaq, sqrtq, z)
1506
+
1507
+ # Now the rest of the sum via _sum_over_residues(), which is parallelized
1508
+ residue_sum_data = []
1509
+ for residues in residue_chunks:
1510
+ residue_sum_data.append([modulus, residues, t, expt, bound1])
1511
+ # residue_data = [[modulus]+residue_chunks[i] for i in range(len(residue_chunks))]
1512
+ # for summand in _sum_over_residues(residue_data):
1513
+ for summand in self._sum_over_residues(residue_sum_data):
1514
+ y += summand[1]
1515
+
1516
+ return RDF(2 * (u + w + y) / (t**2))
1517
+
1518
+ def analytic_rank_upper_bound(self,
1519
+ max_Delta=None,
1520
+ adaptive=True,
1521
+ root_number='compute',
1522
+ bad_primes=None,
1523
+ ncpus=None):
1524
+ r"""
1525
+ Return an upper bound for the analytic rank of the `L`-function
1526
+ `L_E(s)` attached to ``self``, conditional on the Generalized Riemann
1527
+ Hypothesis, via computing the zero sum `\sum_{\gamma} f(\Delta\gamma)`,
1528
+ where `\gamma` ranges over the imaginary parts of the zeros of `L(E,s)`
1529
+ along the critical strip, `f(x) = \left(\frac{\sin(\pi x)}{\pi x}\right)^2`,
1530
+ and `\Delta` is the tightness parameter whose maximum value is
1531
+ specified by max_Delta.
1532
+
1533
+ This computation can be run on curves with
1534
+ very large conductor (so long as the conductor is known or quickly
1535
+ computable) when Delta is not too large (see below).
1536
+
1537
+ Uses Bober's rank bounding method as described in [Bob2013]_.
1538
+
1539
+ INPUT:
1540
+
1541
+ - ``max_Delta`` -- (default: ``None``) if not ``None``, a positive real value
1542
+ specifying the maximum Delta value used in the zero sum; larger
1543
+ values of Delta yield better bounds - but runtime is exponential in
1544
+ Delta. If left as ``None``, Delta is set
1545
+ to `\min\left\{\frac{1}{\pi}\left(\log(N+1000)/2-\log(2\pi)-\eta\right), 2.5\right\}`,
1546
+ where `N` is the conductor of the curve attached to ``self``, and `\eta`
1547
+ is the Euler-Mascheroni constant `= 0.5772...`; the crossover
1548
+ point is at conductor ~8.3*10^8. For the former value, empirical
1549
+ results show that for about 99.7% of all curves the returned value
1550
+ is the actual analytic rank.
1551
+
1552
+ - ``adaptive`` -- boolean (default: ``True``)
1553
+
1554
+ - If ``True``, the computation is first run with small and then
1555
+ successively larger Delta values up to max_Delta. If at any
1556
+ point the computed bound is 0 (or 1 when root_number is -1
1557
+ or ``True``), the computation halts and that value is returned;
1558
+ otherwise the minimum of the computed bounds is returned.
1559
+ - If ``False``, the computation is run a single time with
1560
+ Delta=max_Delta, and the resulting bound returned.
1561
+
1562
+ - ``root_number`` -- (default: ``'compute'``) string or integer
1563
+
1564
+ - ``'compute'`` -- the root number of ``self`` is computed and used to
1565
+ (possibly) lower the analytic rank estimate by 1
1566
+ - ``'ignore'`` -- the above step is omitted
1567
+ - ``1`` -- this value is assumed to be the root number of
1568
+ ``self``. This is passable so that rank estimation can be done for
1569
+ curves whose root number has been precomputed.
1570
+ - ``-1`` -- this value is assumed to be the root number of
1571
+ ``self``. This is passable so that rank estimation can be done for
1572
+ curves whose root number has been precomputed.
1573
+
1574
+ - ``bad_primes`` -- (default: ``None``) if not ``None``, a list of the primes
1575
+ of bad reduction for the curve attached to ``self``. This is passable
1576
+ so that rank estimation can be done for curves of large conductor
1577
+ whose bad primes have been precomputed.
1578
+
1579
+ - ``ncpus`` -- (default: ``None``) if not ``None``, a positive integer
1580
+ defining the maximum number of CPUs to be used for the computation.
1581
+ If left as ``None``, the maximum available number of CPUs will be used.
1582
+ Note: Multiple processors will only be used for Delta values >= 1.75.
1583
+
1584
+ .. NOTE::
1585
+
1586
+ Output will be incorrect if the incorrect root number is specified.
1587
+
1588
+ .. WARNING::
1589
+
1590
+ Zero sum computation time is exponential in the tightness parameter
1591
+ `\Delta`, roughly doubling for every increase of 0.1 thereof.
1592
+ Using `\Delta=1` (and adaptive=False) will yield a runtime of a few
1593
+ milliseconds; `\Delta=2` takes a few seconds, and `\Delta=3` may
1594
+ take upwards of an hour. Increase beyond this at your own risk!
1595
+
1596
+ OUTPUT:
1597
+
1598
+ A nonnegative integer greater than or equal to the analytic rank of
1599
+ ``self``. If the returned value is 0 or 1 (the latter if parity is not
1600
+ ``False``), then this is the true analytic rank of ``self``.
1601
+
1602
+ .. NOTE::
1603
+
1604
+ If you use set_verbose(1), extra information about the computation
1605
+ will be printed.
1606
+
1607
+ .. SEEALSO::
1608
+
1609
+ :func:`LFunctionZeroSum`
1610
+ :meth:`EllipticCurve.root_number`
1611
+ :func:`~sage.misc.verbose.set_verbose`
1612
+
1613
+ EXAMPLES:
1614
+
1615
+ For most elliptic curves with small conductor the central zero(s)
1616
+ of `L_E(s)` are fairly isolated, so small values of `\Delta`
1617
+ will yield tight rank estimates.
1618
+
1619
+ ::
1620
+
1621
+ sage: E = EllipticCurve("11a")
1622
+ sage: E.rank()
1623
+ 0
1624
+ sage: Z = LFunctionZeroSum(E)
1625
+ sage: Z.analytic_rank_upper_bound(max_Delta=1,ncpus=1)
1626
+ 0
1627
+
1628
+ sage: E = EllipticCurve([-39,123])
1629
+ sage: E.rank()
1630
+ 1
1631
+ sage: Z = LFunctionZeroSum(E)
1632
+ sage: Z.analytic_rank_upper_bound(max_Delta=1)
1633
+ 1
1634
+
1635
+ This is especially true for elliptic curves with large rank.
1636
+
1637
+ ::
1638
+
1639
+ sage: for r in range(9):
1640
+ ....: E = elliptic_curves.rank(r)[0]
1641
+ ....: print((r, E.analytic_rank_upper_bound(max_Delta=1,
1642
+ ....: adaptive=False,root_number='ignore')))
1643
+ (0, 0)
1644
+ (1, 1)
1645
+ (2, 2)
1646
+ (3, 3)
1647
+ (4, 4)
1648
+ (5, 5)
1649
+ (6, 6)
1650
+ (7, 7)
1651
+ (8, 8)
1652
+
1653
+ However, some curves have `L`-functions with low-lying zeroes, and for these
1654
+ larger values of `\Delta` must be used to get tight estimates.
1655
+
1656
+ ::
1657
+
1658
+ sage: E = EllipticCurve("974b1")
1659
+ sage: r = E.rank(); r
1660
+ 0
1661
+ sage: Z = LFunctionZeroSum(E)
1662
+ sage: Z.analytic_rank_upper_bound(max_Delta=1,root_number='ignore')
1663
+ 1
1664
+ sage: Z.analytic_rank_upper_bound(max_Delta=1.3,root_number='ignore')
1665
+ 0
1666
+
1667
+ Knowing the root number of E allows us to use smaller Delta values
1668
+ to get tight bounds, thus speeding up runtime considerably.
1669
+
1670
+ ::
1671
+
1672
+ sage: Z.analytic_rank_upper_bound(max_Delta=0.6,root_number='compute')
1673
+ 0
1674
+
1675
+ The are a small number of curves which have pathologically low-lying
1676
+ zeroes. For these curves, this method will produce a bound that is
1677
+ strictly larger than the analytic rank, unless very large values of
1678
+ Delta are used. The following curve ("256944c1" in the Cremona tables)
1679
+ is a rank 0 curve with a zero at 0.0256...; the smallest Delta value
1680
+ for which the zero sum is strictly less than 2 is ~2.815.
1681
+
1682
+ ::
1683
+
1684
+ sage: E = EllipticCurve([0, -1, 0, -7460362000712, -7842981500851012704])
1685
+ sage: N,r = E.conductor(),E.analytic_rank(); N, r
1686
+ (256944, 0)
1687
+ sage: E.analytic_rank_upper_bound(max_Delta=1,adaptive=False)
1688
+ 2
1689
+ sage: E.analytic_rank_upper_bound(max_Delta=2,adaptive=False)
1690
+ 2
1691
+
1692
+ This method is can be called on curves with large conductor.
1693
+
1694
+ ::
1695
+
1696
+ sage: E = EllipticCurve([-2934,19238])
1697
+ sage: Z = LFunctionZeroSum(E)
1698
+ sage: Z.analytic_rank_upper_bound()
1699
+ 1
1700
+
1701
+ And it can bound rank on curves with *very* large conductor, so long as
1702
+ you know beforehand/can easily compute the conductor and primes of bad
1703
+ reduction less than `e^{2\pi\Delta}`. The example below is of the rank
1704
+ 28 curve discovered by Elkies that is the elliptic curve of (currently)
1705
+ largest known rank.
1706
+
1707
+ ::
1708
+
1709
+ sage: a4 = -20067762415575526585033208209338542750930230312178956502
1710
+ sage: a6 = 34481611795030556467032985690390720374855944359319180361266008296291939448732243429
1711
+ sage: E = EllipticCurve([1,-1,1,a4,a6])
1712
+ sage: bad_primes = [2,3,5,7,11,13,17,19,48463]
1713
+ sage: N = 3455601108357547341532253864901605231198511505793733138900595189472144724781456635380154149870961231592352897621963802238155192936274322687070
1714
+ sage: Z = LFunctionZeroSum(E,N)
1715
+ sage: Z.analytic_rank_upper_bound(max_Delta=2.37,adaptive=False, # long time
1716
+ ....: root_number=1,bad_primes=bad_primes,ncpus=2)
1717
+ 32
1718
+ """
1719
+ # Helper function: compute zero sum and apply parity if not False
1720
+ def run_computation(Delta):
1721
+ verbose("Computing zero sum with Delta = %s" % Delta)
1722
+ # Empirically, the non-parallelized zero sum method runs faster
1723
+ # for Delta <= 1.75, regardless of the number of available CPUs.
1724
+ if Delta <= 1.75:
1725
+ bound = self._zerosum_sincsquared_fast(Delta=Delta,
1726
+ bad_primes=bad_primes)
1727
+ else:
1728
+ bound = self._zerosum_sincsquared_parallel(Delta=Delta,
1729
+ bad_primes=bad_primes,
1730
+ ncpus=ncpus)
1731
+ verbose("Sum value is %s" % bound)
1732
+ bound = bound.floor()
1733
+ # parity is set to -1 when we're not taking root number into
1734
+ # account
1735
+ if parity == -1:
1736
+ verbose("Without invoking parity, rank bound is %s" % bound)
1737
+ return bound
1738
+ # parity is 0 if E has even analytic rank, and 1 if odd
1739
+ # analytic rank. The returned value must have the same parity
1740
+ # as the parity parameter.
1741
+ if bound % 2 != parity:
1742
+ bound -= 1
1743
+ verbose("Invoking parity, rank bound is %s" % bound)
1744
+ return bound
1745
+
1746
+ # Get/compute parity
1747
+ if root_number == 1 or root_number == -1:
1748
+ parity = (1 - root_number) // 2
1749
+ verbose("Parity set to %s." % parity)
1750
+ elif root_number == "compute":
1751
+ verbose("Computing curve parity...")
1752
+ parity = (1 - self._e.ellrootno()) // 2
1753
+ verbose("Curve has parity %s." % parity)
1754
+ elif root_number == "ignore":
1755
+ verbose("Curve parity ignored.")
1756
+ parity = -1
1757
+ else:
1758
+ raise ValueError("root_number parameter not recognized")
1759
+ if parity == 1:
1760
+ halt_bound = 1
1761
+ verbose("Computation will halt if at any point bound is <= 1.")
1762
+ else:
1763
+ halt_bound = 0
1764
+ verbose("Computation will halt if at any point bound is 0.")
1765
+
1766
+ # Compute max_Delta if necessary
1767
+ if max_Delta is None:
1768
+ verbose("Computing maximum Delta value")
1769
+ pi, eg = self._pi, self._euler_gamma
1770
+ # 1000 is arbitrary - increases Delta for small N
1771
+ max_Delta = (RDF(self._level + 1000).log() / 2 - log(2 * pi) - eg) / pi
1772
+ if max_Delta > 2.5:
1773
+ max_Delta = 2.5
1774
+ verbose("Computed max Delta value too big; setting to 2.5")
1775
+ else:
1776
+ verbose("Maximum Delta value to be used set at %s" % max_Delta)
1777
+ else:
1778
+ verbose("Maximum Delta value to be used set at %s" % max_Delta)
1779
+
1780
+ # When max_Delta <= 1 it's not worth running the computation
1781
+ # multiple times, as it's so quick anyway
1782
+ if not adaptive or max_Delta <= 1:
1783
+ return run_computation(max_Delta)
1784
+ else:
1785
+ bound_list = []
1786
+ # Find starting value. This loop won't ever take long,
1787
+ # since max_Delta is never > 7.
1788
+ Delta = max_Delta
1789
+ while Delta > 1:
1790
+ Delta -= 0.2
1791
+ # Now go back up the sequence of Deltas
1792
+ while Delta <= max_Delta:
1793
+ bound = run_computation(Delta)
1794
+ if bound <= halt_bound:
1795
+ verbose("computed bound <= halt_bound, so halting")
1796
+ return bound
1797
+ else:
1798
+ bound_list.append(bound)
1799
+ # Incrementing Delta by 0.2 each step means runtime
1800
+ # will increase by a factor of ~3.7
1801
+ Delta += 0.2
1802
+
1803
+ # Since the zero sum is not strictly decreasing in Delta,
1804
+ # the last value is not necessarily the smallest
1805
+ smallest_bound = min(bound_list)
1806
+ verbose("Smallest bound computed is %s" % smallest_bound)
1807
+ return smallest_bound
1808
+
1809
+
1810
+ def LFunctionZeroSum(X, *args, **kwds):
1811
+ r"""
1812
+ Constructor for the LFunctionZeroSum class.
1813
+
1814
+ INPUT:
1815
+
1816
+ - ``X`` -- a motivic object; currently only implemented for X = an elliptic curve
1817
+ over the rational numbers
1818
+
1819
+ OUTPUT: an LFunctionZeroSum object
1820
+
1821
+ EXAMPLES::
1822
+
1823
+ sage: E = EllipticCurve("389a")
1824
+ sage: Z = LFunctionZeroSum(E); Z
1825
+ Zero sum estimator for L-function attached to Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
1826
+
1827
+ TESTS::
1828
+
1829
+ sage: E = EllipticCurve([1.2,3.8])
1830
+ sage: LFunctionZeroSum(E)
1831
+ Traceback (most recent call last):
1832
+ ...
1833
+ NotImplementedError: currently only implemented for elliptic curves over QQ
1834
+
1835
+ sage: f = Newforms(46)[0]
1836
+ sage: LFunctionZeroSum(f)
1837
+ Traceback (most recent call last):
1838
+ ...
1839
+ NotImplementedError: currently only implemented for elliptic curves over QQ
1840
+ """
1841
+ # Here to avoid import recursion
1842
+ from sage.schemes.elliptic_curves.ell_rational_field import EllipticCurve_rational_field
1843
+
1844
+ if isinstance(X, EllipticCurve_rational_field):
1845
+ return LFunctionZeroSum_EllipticCurve(X, *args, **kwds)
1846
+
1847
+ raise NotImplementedError("currently only implemented for elliptic curves over QQ")