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,1103 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ """
3
+ Complex multiplication for elliptic curves
4
+
5
+ This module implements the functions
6
+
7
+ - ``hilbert_class_polynomial``
8
+ - ``is_HCP``
9
+ - ``cm_j_invariants``
10
+ - ``cm_orders``
11
+ - ``discriminants_with_bounded_class_number``
12
+ - ``cm_j_invariants_and_orders``
13
+ - ``largest_fundamental_disc_with_class_number``
14
+ - ``is_cm_j_invariant``
15
+
16
+ AUTHORS:
17
+
18
+ - Robert Bradshaw
19
+ - John Cremona
20
+ - William Stein
21
+ """
22
+
23
+ # ****************************************************************************
24
+ # Copyright (C) 2005-2012 William Stein <wstein@gmail.com>
25
+ #
26
+ # Distributed under the terms of the GNU General Public License (GPL)
27
+ #
28
+ # This code is distributed in the hope that it will be useful,
29
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
30
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31
+ # General Public License for more details.
32
+ #
33
+ # The full text of the GPL is available at:
34
+ #
35
+ # https://www.gnu.org/licenses/
36
+ # ****************************************************************************
37
+
38
+ from sage.rings.integer import Integer
39
+ from sage.rings.rational_field import QQ
40
+ from sage.rings.integer_ring import ZZ
41
+ from sage.rings.integer_ring import IntegerRing
42
+
43
+ from sage.misc.cachefunc import cached_function
44
+ from sage.rings.number_field.number_field_element_base import NumberFieldElement_base
45
+
46
+
47
+ @cached_function
48
+ def hilbert_class_polynomial(D, algorithm=None):
49
+ r"""
50
+ Return the Hilbert class polynomial for discriminant `D`.
51
+
52
+ INPUT:
53
+
54
+ - ``D`` -- negative integer congruent to 0 or 1 modulo 4
55
+
56
+ - ``algorithm`` -- string (default: ``None``)
57
+
58
+ OUTPUT:
59
+
60
+ (integer polynomial) The Hilbert class polynomial for the
61
+ discriminant `D`.
62
+
63
+ ALGORITHM:
64
+
65
+ - If ``algorithm`` = "arb" (default): Use FLINT's implementation inherited
66
+ from Arb which uses complex interval arithmetic.
67
+
68
+ - If ``algorithm`` = "sage": Use complex approximations to the roots.
69
+
70
+ - If ``algorithm`` = "magma": Call the appropriate Magma function (if available).
71
+
72
+ AUTHORS:
73
+
74
+ - Sage implementation originally by Eduardo Ocampo Alvarez and
75
+ AndreyTimofeev
76
+
77
+ - Sage implementation corrected by John Cremona (using corrected precision bounds from Andreas Enge)
78
+
79
+ - Magma implementation by David Kohel
80
+
81
+ EXAMPLES::
82
+
83
+ sage: # needs sage.libs.flint
84
+ sage: hilbert_class_polynomial(-4)
85
+ x - 1728
86
+ sage: hilbert_class_polynomial(-7)
87
+ x + 3375
88
+ sage: hilbert_class_polynomial(-23)
89
+ x^3 + 3491750*x^2 - 5151296875*x + 12771880859375
90
+ sage: hilbert_class_polynomial(-37*4)
91
+ x^2 - 39660183801072000*x - 7898242515936467904000000
92
+ sage: hilbert_class_polynomial(-37*4, algorithm='magma') # optional - magma
93
+ x^2 - 39660183801072000*x - 7898242515936467904000000
94
+ sage: hilbert_class_polynomial(-163)
95
+ x + 262537412640768000
96
+ sage: hilbert_class_polynomial(-163, algorithm='sage')
97
+ x + 262537412640768000
98
+ sage: hilbert_class_polynomial(-163, algorithm='magma') # optional - magma
99
+ x + 262537412640768000
100
+
101
+ TESTS::
102
+
103
+ sage: all(hilbert_class_polynomial(d, algorithm='arb') ==
104
+ ....: hilbert_class_polynomial(d, algorithm='sage')
105
+ ....: for d in range(-1,-100,-1) if d % 4 in [0, 1])
106
+ True
107
+ """
108
+ if algorithm is None:
109
+ algorithm = "arb"
110
+
111
+ D = Integer(D)
112
+ if D >= 0:
113
+ raise ValueError("D (=%s) must be negative" % D)
114
+ if (D % 4) not in [0, 1]:
115
+ raise ValueError("D (=%s) must be a discriminant" % D)
116
+
117
+ if algorithm == "arb":
118
+ import sage.libs.arb.arith
119
+ return sage.libs.arb.arith.hilbert_class_polynomial(D)
120
+
121
+ if algorithm == "magma":
122
+ from sage.interfaces.magma import magma
123
+ magma.eval("R<x> := PolynomialRing(IntegerRing())")
124
+ f = str(magma.eval("HilbertClassPolynomial(%s)" % D))
125
+ return IntegerRing()['x'](f)
126
+
127
+ if algorithm != "sage":
128
+ raise ValueError("%s is not a valid algorithm" % algorithm)
129
+
130
+ from sage.quadratic_forms.binary_qf import BinaryQF_reduced_representatives
131
+ from sage.rings.real_mpfr import RR
132
+ from sage.rings.complex_mpfr import ComplexField
133
+ from sage.functions.special import elliptic_j
134
+
135
+ # get all primitive reduced quadratic forms, (necessary to exclude
136
+ # imprimitive forms when D is not a fundamental discriminant):
137
+
138
+ rqf = BinaryQF_reduced_representatives(D, primitive_only=True)
139
+
140
+ # compute needed precision
141
+ #
142
+ # NB: [https://arxiv.org/abs/0802.0979v1], quoting Enge (2006), is
143
+ # incorrect. Enge writes (2009-04-20 email to John Cremona) "The
144
+ # source is my paper on class polynomials
145
+ # [https://hal.inria.fr/inria-00001040] It was pointed out to me by
146
+ # the referee after ANTS that the constant given there was
147
+ # wrong. The final version contains a corrected constant on p.7
148
+ # which is consistent with your example. It says:
149
+
150
+ # "The logarithm of the absolute value of the coefficient in front
151
+ # of X^j is bounded above by
152
+ #
153
+ # log (2*k_2) * h + pi * sqrt(|D|) * sum (1/A_i)
154
+ #
155
+ # independently of j", where k_2 \approx 10.163.
156
+
157
+ h = len(rqf) # class number
158
+ c1 = 3.05682737291380 # log(2*10.63)
159
+ c2 = sum([1/RR(qf[0]) for qf in rqf], RR(0))
160
+ prec = c2 * RR(3.142) * RR(D).abs().sqrt() + h * c1 # bound on log
161
+ prec = prec * 1.45 # bound on log_2 (1/log(2) = 1.44..)
162
+ prec = 10 + prec.ceil() # allow for rounding error
163
+
164
+ # set appropriate precision for further computing
165
+
166
+ Dsqrt = D.sqrt(prec=prec)
167
+ R = ComplexField(prec)['t']
168
+ t = R.gen()
169
+ pol = R(1)
170
+ for qf in rqf:
171
+ a, b, c = list(qf)
172
+ tau = (b + Dsqrt) / (a << 1)
173
+ pol *= (t - elliptic_j(tau))
174
+
175
+ coeffs = [cof.real().round() for cof in pol.coefficients(sparse=False)]
176
+ return IntegerRing()['x'](coeffs)
177
+
178
+
179
+ def is_HCP(f, check_monic_irreducible=True):
180
+ r"""
181
+ Determine whether a polynomial is a Hilbert Class Polynomial.
182
+
183
+ INPUT:
184
+
185
+ - ``f`` -- a polynomial in `\ZZ[X]`
186
+ - ``check_monic_irreducible`` -- boolean (default: ``True``); if ``True``,
187
+ check that ``f`` is a monic, irreducible, integer polynomial
188
+
189
+ OUTPUT:
190
+
191
+ (integer) -- either `D` if ``f`` is the Hilbert Class Polynomial
192
+ `H_D` for discriminant `D`, or `0` if not an HCP.
193
+
194
+ ALGORITHM:
195
+
196
+ Cremona and Sutherland: Algorithm 2 of [CreSuth2023]_.
197
+
198
+ EXAMPLES:
199
+
200
+ Even for large degrees this is fast. We test the largest
201
+ discriminant of class number 100, for which the HCP has coefficients
202
+ with thousands of digits::
203
+
204
+ sage: from sage.schemes.elliptic_curves.cm import is_HCP
205
+ sage: D = -1856563
206
+ sage: D.class_number() # needs sage.libs.pari
207
+ 100
208
+
209
+ sage: # needs sage.libs.flint
210
+ sage: H = hilbert_class_polynomial(D)
211
+ sage: H.degree()
212
+ 100
213
+ sage: max(H).ndigits()
214
+ 2774
215
+ sage: is_HCP(H)
216
+ -1856563
217
+
218
+ Testing polynomials which are not HCPs is faster::
219
+
220
+ sage: is_HCP(H+1) # needs sage.libs.flint
221
+ 0
222
+
223
+
224
+ TESTS::
225
+
226
+ sage: # needs sage.libs.flint
227
+ sage: from sage.schemes.elliptic_curves.cm import is_HCP
228
+ sage: all(is_HCP(hilbert_class_polynomial(D)) == D
229
+ ....: for D in srange(-4,-100,-1) if D.is_discriminant())
230
+ True
231
+ sage: all(not is_HCP(hilbert_class_polynomial(D) + 1)
232
+ ....: for D in srange(-4,-100,-1) if D.is_discriminant())
233
+ True
234
+
235
+ Ensure that :issue:`37471` is fixed::
236
+
237
+ sage: from sage.schemes.elliptic_curves.cm import is_HCP
238
+ sage: set_random_seed(297388353221545796156853787333338705098)
239
+ sage: is_HCP(hilbert_class_polynomial(-55))
240
+ -55
241
+ """
242
+ zero = ZZ(0)
243
+ # optional check that input is monic and irreducible
244
+ if check_monic_irreducible:
245
+ try:
246
+ if not (all(c in ZZ for c in f) and f.is_monic()):
247
+ return zero
248
+ f = f.change_ring(ZZ)
249
+ except AttributeError:
250
+ return zero
251
+
252
+ from sage.rings.real_mpfr import RR
253
+ from sage.rings.finite_rings.finite_field_constructor import GF
254
+
255
+ h = f.degree()
256
+ h2list = [d for d in h.divisors()
257
+ if (d-h) % 2 == 0 and d.prime_to_m_part(2) == 1]
258
+ pmin = 33 * (h**2 * (RR(h+2).log().log()+2)**2).ceil()
259
+ # Guarantees 4*p > |D| for fundamental D under GRH
260
+ p = pmin-1
261
+ n = 0
262
+ from sage.arith.misc import next_prime
263
+ from sage.schemes.elliptic_curves.constructor import EllipticCurve
264
+
265
+ while True:
266
+ p = next_prime(p)
267
+ n += 1
268
+ fp = f.change_ring(GF(p))
269
+ # Compute X^p-X mod fp
270
+ z = fp.parent().gen()
271
+ r = pow(z, p, fp) - z
272
+ r = r.gcd(fp)
273
+ d = r.degree() # number of roots mod p
274
+ if d == 0:
275
+ continue
276
+ if not r.is_squarefree():
277
+ continue
278
+ if d < h and d not in h2list:
279
+ return zero
280
+ jp = r.any_root(degree=1, assume_squarefree=True, assume_equal_deg=True)
281
+ E = EllipticCurve(j=jp)
282
+ if E.is_supersingular():
283
+ continue
284
+ try:
285
+ D = E.endomorphism_discriminant_from_class_number(h)
286
+ except ValueError:
287
+ return zero
288
+ return D if f == hilbert_class_polynomial(D) else zero
289
+
290
+
291
+ def OrderClassNumber(D0, h0, f):
292
+ r"""
293
+ Return the class number h(f**2 * D0), given h(D0)=h0.
294
+
295
+ INPUT:
296
+
297
+ - ``D0`` -- integer; a negative fundamental discriminant
298
+ - ``h0`` -- integer; the class number of the (maximal) imaginary quadratic order of discriminant ``D0``
299
+ - ``f`` -- positive integer
300
+
301
+ OUTPUT:
302
+
303
+ (integer) the class number of the imaginary quadratic order of discriminant ``D0*f**2``
304
+
305
+ ALGORITHM:
306
+
307
+ We use the formula for the class number of the order `\mathcal{O}_{D}` in terms of the class number of the
308
+ maximal order `\mathcal{O}_{D_0}`; see [Cox1989]_ Theorem 7.24:
309
+
310
+ .. MATH::
311
+
312
+ h(D) = \frac{h(D_0)f}{[\mathcal{O}_{D_0}^\times:\mathcal{O}_{D}^\times]}\prod_{p\,|\,f}\left(1-\left(\frac{D_0}{p}\right)\frac{1}{p}\right)
313
+
314
+ EXAMPLES::
315
+
316
+ sage: # needs sage.libs.pari
317
+ sage: from sage.schemes.elliptic_curves.cm import OrderClassNumber
318
+ sage: D0 = -4
319
+ sage: h = D0.class_number()
320
+ sage: [OrderClassNumber(D0,h,f) for f in srange(1,20)]
321
+ [1, 1, 2, 2, 2, 4, 4, 4, 6, 4, 6, 8, 6, 8, 8, 8, 8, 12, 10]
322
+ sage: all([OrderClassNumber(D0,h,f) == (D0*f**2).class_number() for f in srange(1,20)])
323
+ True
324
+ """
325
+ if not D0.is_fundamental_discriminant():
326
+ raise ValueError("{} is not a fundamental discriminant".format(D0))
327
+ if f <= 0:
328
+ raise ValueError("{} is not a positive integer".format(f))
329
+ if f == 1:
330
+ return h0
331
+ ps = f.prime_divisors()
332
+ from sage.misc.misc_c import prod
333
+ from sage.arith.misc import kronecker as kronecker_symbol
334
+ n = (f // prod(ps)) * prod(p - kronecker_symbol(D0, p) for p in ps)
335
+ if D0 == -3:
336
+ # assert h0 == 1 and n % 3 == 0
337
+ return n // 3
338
+ if D0 == -4:
339
+ # assert h0 == 1 and n % 2 == 0
340
+ return n // 2
341
+ return n * h0
342
+
343
+
344
+ @cached_function
345
+ def cm_j_invariants(K, proof=None):
346
+ r"""
347
+ Return a list of all CM `j`-invariants in the field `K`.
348
+
349
+ INPUT:
350
+
351
+ - ``K`` -- a number field
352
+ - ``proof`` -- (default: proof.number_field())
353
+
354
+ OUTPUT:
355
+
356
+ (list) -- A list of CM `j`-invariants in the field `K`.
357
+
358
+ EXAMPLES::
359
+
360
+ sage: cm_j_invariants(QQ)
361
+ [-262537412640768000, -147197952000, -884736000, -12288000, -884736,
362
+ -32768, -3375, 0, 1728, 8000, 54000, 287496, 16581375]
363
+
364
+ Over imaginary quadratic fields there are no more than over `QQ`::
365
+
366
+ sage: cm_j_invariants(QuadraticField(-1, 'i')) # needs sage.rings.number_field
367
+ [-262537412640768000, -147197952000, -884736000, -12288000, -884736,
368
+ -32768, -3375, 0, 1728, 8000, 54000, 287496, 16581375]
369
+
370
+ Over real quadratic fields there may be more, for example::
371
+
372
+ sage: len(cm_j_invariants(QuadraticField(5, 'a'))) # needs sage.rings.number_field
373
+ 31
374
+
375
+ Over number fields K of many higher degrees this also works::
376
+
377
+ sage: # needs sage.rings.number_field
378
+ sage: x = polygen(ZZ, 'x')
379
+ sage: K.<a> = NumberField(x^3 - 2)
380
+ sage: cm_j_invariants(K)
381
+ [-262537412640768000, -147197952000, -884736000, -884736, -32768,
382
+ 8000, -3375, 16581375, 1728, 287496, 0, 54000, -12288000,
383
+ 31710790944000*a^2 + 39953093016000*a + 50337742902000]
384
+ sage: K.<a> = NumberField(x^4 - 2)
385
+ sage: len(cm_j_invariants(K))
386
+ 23
387
+ """
388
+ return sorted(j for D, f, j in cm_j_invariants_and_orders(K, proof=proof))
389
+
390
+
391
+ @cached_function
392
+ def cm_j_invariants_and_orders(K, proof=None):
393
+ r"""
394
+ Return a list of all CM `j`-invariants in the field `K`, together with the associated orders.
395
+
396
+ INPUT:
397
+
398
+ - ``K`` -- a number field
399
+ - ``proof`` -- (default: proof.number_field())
400
+
401
+ OUTPUT:
402
+
403
+ A list of 3-tuples `(D,f,j)` where `j` is a CM `j`-invariant in `K` with
404
+ quadratic fundamental discriminant `D` and conductor `f`.
405
+
406
+ EXAMPLES::
407
+
408
+ sage: cm_j_invariants_and_orders(QQ)
409
+ [(-3, 3, -12288000), (-3, 2, 54000), (-3, 1, 0), (-4, 2, 287496), (-4, 1, 1728),
410
+ (-7, 2, 16581375), (-7, 1, -3375), (-8, 1, 8000), (-11, 1, -32768),
411
+ (-19, 1, -884736), (-43, 1, -884736000), (-67, 1, -147197952000),
412
+ (-163, 1, -262537412640768000)]
413
+
414
+ Over an imaginary quadratic field there are no more than over `QQ`::
415
+
416
+ sage: cm_j_invariants_and_orders(QuadraticField(-1, 'i')) # needs sage.rings.number_field
417
+ [(-163, 1, -262537412640768000), (-67, 1, -147197952000),
418
+ (-43, 1, -884736000), (-19, 1, -884736), (-11, 1, -32768),
419
+ (-8, 1, 8000), (-7, 1, -3375), (-7, 2, 16581375), (-4, 1, 1728),
420
+ (-4, 2, 287496), (-3, 1, 0), (-3, 2, 54000), (-3, 3, -12288000)]
421
+
422
+ Over real quadratic fields there may be more::
423
+
424
+ sage: v = cm_j_invariants_and_orders(QuadraticField(5,'a')); len(v) # needs sage.rings.number_field
425
+ 31
426
+ sage: [(D, f) for D, f, j in v if j not in QQ] # needs sage.rings.number_field
427
+ [(-235, 1), (-235, 1), (-115, 1), (-115, 1), (-40, 1), (-40, 1),
428
+ (-35, 1), (-35, 1), (-20, 1), (-20, 1), (-15, 1), (-15, 1), (-15, 2),
429
+ (-15, 2), (-4, 5), (-4, 5), (-3, 5), (-3, 5)]
430
+
431
+ Over number fields K of many higher degrees this also works::
432
+
433
+ sage: x = polygen(ZZ, 'x')
434
+ sage: K.<a> = NumberField(x^3 - 2) # needs sage.rings.number_field
435
+ sage: cm_j_invariants_and_orders(K) # needs sage.rings.number_field
436
+ [(-163, 1, -262537412640768000), (-67, 1, -147197952000),
437
+ (-43, 1, -884736000), (-19, 1, -884736), (-11, 1, -32768),
438
+ (-8, 1, 8000), (-7, 1, -3375), (-7, 2, 16581375), (-4, 1, 1728),
439
+ (-4, 2, 287496), (-3, 1, 0), (-3, 2, 54000), (-3, 3, -12288000),
440
+ (-3, 6, 31710790944000*a^2 + 39953093016000*a + 50337742902000)]
441
+ """
442
+ if K == QQ:
443
+ return [(ZZ(d), ZZ(f), ZZ(j)) for d, f, j in [
444
+ (-3, 3, -12288000),
445
+ (-3, 2, 54000),
446
+ (-3, 1, 0),
447
+ (-4, 2, 287496),
448
+ (-4, 1, 1728),
449
+ (-7, 2, 16581375),
450
+ (-7, 1, -3375),
451
+ (-8, 1, 8000),
452
+ (-11, 1, -32768),
453
+ (-19, 1, -884736),
454
+ (-43, 1, -884736000),
455
+ (-67, 1, -147197952000),
456
+ (-163, 1, -262537412640768000)]]
457
+
458
+ # Get the list of CM orders that could possibly have Hilbert class
459
+ # polynomial F(x) with a root in K. If F(x) has a root alpha in K,
460
+ # then F is the minimal polynomial of alpha in K, so the degree of
461
+ # F(x) divides [K:QQ].
462
+ n = K.absolute_degree()
463
+ T = discriminants_with_bounded_class_number(n, proof=proof)
464
+ dlist = sorted(sum((Dflist for h,Dflist in T.items() if h.divides(n)), []))
465
+
466
+ return [(D, f, j) for D, f in dlist
467
+ for j in hilbert_class_polynomial(D*f*f).roots(K, multiplicities=False)]
468
+
469
+
470
+ @cached_function
471
+ def cm_orders(h, proof=None):
472
+ """
473
+ Return a list of all pairs `(D,f)` where there is a CM order of
474
+ discriminant `D f^2` with class number h, with `D` a fundamental
475
+ discriminant.
476
+
477
+ INPUT:
478
+
479
+ - ``h`` -- positive integer
480
+ - ``proof`` -- (default: proof.number_field())
481
+
482
+ OUTPUT: list of 2-tuples `(D,f)` sorted lexicographically by `(|D|, f)`
483
+
484
+ EXAMPLES::
485
+
486
+ sage: cm_orders(0)
487
+ []
488
+ sage: v = cm_orders(1); v
489
+ [(-3, 1), (-3, 2), (-3, 3), (-4, 1), (-4, 2), (-7, 1), (-7, 2), (-8, 1),
490
+ (-11, 1), (-19, 1), (-43, 1), (-67, 1), (-163, 1)]
491
+ sage: type(v[0][0]), type(v[0][1])
492
+ (<... 'sage.rings.integer.Integer'>, <... 'sage.rings.integer.Integer'>)
493
+ sage: # needs sage.libs.pari
494
+ sage: v = cm_orders(2); v
495
+ [(-3, 4), (-3, 5), (-3, 7), (-4, 3), (-4, 4), (-4, 5), (-7, 4), (-8, 2),
496
+ (-8, 3), (-11, 3), (-15, 1), (-15, 2), (-20, 1), (-24, 1), (-35, 1),
497
+ (-40, 1), (-51, 1), (-52, 1), (-88, 1), (-91, 1), (-115, 1), (-123, 1),
498
+ (-148, 1), (-187, 1), (-232, 1), (-235, 1), (-267, 1), (-403, 1), (-427, 1)]
499
+ sage: len(v)
500
+ 29
501
+ sage: set([hilbert_class_polynomial(D*f^2).degree() for D,f in v])
502
+ {2}
503
+
504
+ Any degree up to 100 is implemented, but may be slow::
505
+
506
+ sage: # needs sage.libs.pari
507
+ sage: cm_orders(3)
508
+ [(-3, 6), (-3, 9), (-11, 2), (-19, 2), (-23, 1), (-23, 2), (-31, 1), (-31, 2),
509
+ (-43, 2), (-59, 1), (-67, 2), (-83, 1), (-107, 1), (-139, 1), (-163, 2),
510
+ (-211, 1), (-283, 1), (-307, 1), (-331, 1), (-379, 1), (-499, 1), (-547, 1),
511
+ (-643, 1), (-883, 1), (-907, 1)]
512
+ sage: len(cm_orders(4))
513
+ 84
514
+ """
515
+ h = Integer(h)
516
+ if h <= 0:
517
+ # trivial case
518
+ return []
519
+
520
+ if h in hDf_dict:
521
+ return hDf_dict[h]
522
+
523
+ # Get all discriminants for all class numbers up to h (which will
524
+ # be stored in hDf_dict), and return just those with class number h.
525
+ return discriminants_with_bounded_class_number(h, proof=proof)[h]
526
+
527
+ # Table from Mark Watkins paper "Class numbers of imaginary quadratic fields".
528
+
529
+ # WAS extracted this by cutting/pasting from the pdf, and running this program:
530
+ # z = {}
531
+ # for X in open('/Users/wstein/tmp/a.txt').readlines():
532
+ # if X.strip():
533
+ # v = [int(a) for a in X.split()]
534
+ # for i in range(5):
535
+ # z[v[3*i]]=(v[3*i+2], v[3*i+1])
536
+
537
+ # The keys are integers 1--100 and the value for each h is (|D|,n)
538
+ # where |D| is the largest absolute discriminant of an imaginary
539
+ # quadratic field with class number h, and n is the number of such
540
+ # fields. These are all *unconditional* (not dependent on GRH).
541
+
542
+
543
+ watkins_table = {1: (163, 9), 2: (427, 18), 3: (907, 16), 4: (1555, 54), 5: (2683, 25),
544
+ 6: (3763, 51), 7: (5923, 31), 8: (6307, 131), 9: (10627, 34), 10:
545
+ (13843, 87), 11: (15667, 41), 12: (17803, 206), 13: (20563, 37), 14:
546
+ (30067, 95), 15: (34483, 68), 16: (31243, 322), 17: (37123, 45), 18:
547
+ (48427, 150), 19: (38707, 47), 20: (58507, 350), 21: (61483, 85), 22:
548
+ (85507, 139), 23: (90787, 68), 24: (111763, 511), 25: (93307, 95), 26:
549
+ (103027, 190), 27: (103387, 93), 28: (126043, 457), 29: (166147, 83),
550
+ 30: (134467, 255), 31: (133387, 73), 32: (164803, 708), 33: (222643, 101),
551
+ 34: (189883, 219), 35: (210907, 103), 36: (217627, 668), 37:
552
+ (158923, 85), 38: (289963, 237), 39: (253507, 115), 40: (260947, 912),
553
+ 41: (296587, 109), 42: (280267, 339), 43: (300787, 106), 44: (319867, 691),
554
+ 45: (308323, 154), 46: (462883, 268), 47: (375523, 107), 48:
555
+ (335203, 1365), 49: (393187, 132), 50: (389467, 345), 51: (546067, 159),
556
+ 52: (439147, 770), 53: (425107, 114), 54: (532123, 427), 55: (452083,163),
557
+ 56: (494323, 1205), 57: (615883, 179), 58: (586987, 291),
558
+ 59:(474307, 128), 60: (662803, 1302), 61: (606643, 132), 62: (647707, 323),
559
+ 63: (991027, 216), 64: (693067, 1672), 65: (703123, 164), 66: (958483, 530),
560
+ 67: (652723, 120), 68: (819163, 976), 69: (888427, 209), 70:(811507, 560),
561
+ 71: (909547, 150), 72: (947923, 1930), 73: (886867, 119),
562
+ 74: (951043, 407), 75: (916507, 237), 76: (1086187, 1075), 77: (1242763, 216),
563
+ 78: (1004347, 561), 79: (1333963, 175), 80: (1165483, 2277), 81: (1030723, 228),
564
+ 82: (1446547, 402), 83: (1074907, 150), 84: (1225387,1715),
565
+ 85: (1285747, 221), 86: (1534723, 472), 87: (1261747, 222),
566
+ 88:(1265587, 1905), 89: (1429387, 192), 90: (1548523, 801),
567
+ 91: (1391083,214), 92: (1452067, 1248), 93: (1475203, 262), 94: (1587763, 509),
568
+ 95:(1659067, 241), 96: (1684027, 3283), 97: (1842523, 185), 98: (2383747,580),
569
+ 99: (1480627, 289), 100: (1856563, 1736)}
570
+
571
+ # Table from Janis Klaise [Klaise2012]_
572
+
573
+ # Extracted by converting pdf to text via pdf2ps and ps2txt, cutting/pasting
574
+ # and running this code:
575
+
576
+ # klaise_table = {}
577
+ # for X in open('klaise_table.txt').readlines():
578
+ # if X.strip():
579
+ # v = [int(a) for a in X.split()]
580
+ # for i in range(4):
581
+ # klaise_table[v[3*i]]=(v[3*i+2], v[3*i+1])
582
+
583
+ # The keys are integers 1--100 and the value for each h is (|D|,n)
584
+ # where |D| is the largest discriminant of an imaginary quadratic
585
+ # order with class number h, and n is the number of such orders.
586
+ # These are all *unconditional* (not dependent on GRH).
587
+
588
+ klaise_table = {1: (163, 13), 2: (427, 29), 3: (907, 25), 4: (1555, 84), 5: (2683, 29), 6: (4075, 101),
589
+ 7: (5923, 38), 8: (7987, 208), 9: (10627, 55), 10: (13843, 123), 11: (15667, 46),
590
+ 12: (19723, 379), 13: (20563, 43), 14: (30067, 134), 15: (34483, 95), 16: (35275, 531),
591
+ 17: (37123, 50), 18: (48427, 291), 19: (38707, 59), 20: (58843, 502), 21: (61483, 118),
592
+ 22: (85507, 184), 23: (90787, 78), 24: (111763, 1042), 25: (93307, 101), 26: (103027, 227),
593
+ 27: (103387, 136), 28: (126043, 623), 29: (166147, 94), 30: (137083, 473), 31: (133387, 83),
594
+ 32: (164803, 1231), 33: (222643, 158), 34: (189883, 262), 35: (210907, 111), 36: (217627, 1306),
595
+ 37: (158923, 96), 38: (289963, 284), 39: (253507, 162), 40: (274003, 1418), 41: (296587, 125),
596
+ 42: (301387, 596), 43: (300787, 123), 44: (319867, 911), 45: (308323, 231), 46: (462883, 330),
597
+ 47: (375523, 117), 48: (335203, 2895), 49: (393187, 146), 50: (389467, 445), 51: (546067, 217),
598
+ 52: (457867, 1006), 53: (425107, 130), 54: (532123, 812), 55: (452083, 177), 56: (494323, 1812),
599
+ 57: (615883, 237), 58: (586987, 361), 59: (474307, 144), 60: (662803, 2361), 61: (606643, 149),
600
+ 62: (647707, 386), 63: (991027, 311), 64: (693067, 2919), 65: (703123, 192), 66: (958483, 861),
601
+ 67: (652723, 145), 68: (819163, 1228), 69: (888427, 292), 70: (821683, 704), 71: (909547, 176),
602
+ 72: (947923, 4059), 73: (886867, 137), 74: (951043, 474), 75: (916507, 353), 76: (1086187, 1384),
603
+ 77: (1242763, 236), 78: (1004347, 925), 79: (1333963, 200), 80: (1165483, 3856), 81: (1030723, 339),
604
+ 82: (1446547, 487), 83: (1074907, 174), 84: (1225387, 2998), 85: (1285747, 246), 86: (1534723, 555),
605
+ 87: (1261747, 313), 88: (1265587, 2771), 89: (1429387, 206), 90: (1548523, 1516), 91: (1391083, 249),
606
+ 92: (1452067, 1591), 93: (1475203, 354), 94: (1587763, 600), 95: (1659067, 273), 96: (1684027, 7276),
607
+ 97: (1842523, 208), 98: (2383747, 710), 99: (1480627, 396), 100: (1856563, 2311)}
608
+
609
+
610
+ def largest_fundamental_disc_with_class_number(h):
611
+ r"""
612
+ Return largest absolute value of any fundamental negative discriminant with
613
+ class number `h`, and the number of fundamental negative discriminants with
614
+ that class number. This is known (unconditionally) for `h` up to 100,
615
+ by work of Mark Watkins ([Watkins2004]_).
616
+
617
+ .. NOTE::
618
+
619
+ The class number of a fundamental negative discriminant `D` is
620
+ the same as the class number of the imaginary quadratic field
621
+ `\QQ(\sqrt{D})`, so this function gives the number of such
622
+ fields of each class number `h\le100`. It is easy to extend
623
+ this to larger class number conditional on the GRH, but much
624
+ harder to obtain unconditional results.
625
+
626
+ INPUT:
627
+
628
+ - ``h`` -- integer
629
+
630
+ EXAMPLES::
631
+
632
+ sage: from sage.schemes.elliptic_curves.cm import largest_fundamental_disc_with_class_number
633
+ sage: largest_fundamental_disc_with_class_number(0)
634
+ (0, 0)
635
+ sage: largest_fundamental_disc_with_class_number(1)
636
+ (163, 9)
637
+ sage: largest_fundamental_disc_with_class_number(2)
638
+ (427, 18)
639
+ sage: largest_fundamental_disc_with_class_number(10)
640
+ (13843, 87)
641
+ sage: largest_fundamental_disc_with_class_number(100)
642
+ (1856563, 1736)
643
+ sage: largest_fundamental_disc_with_class_number(101)
644
+ Traceback (most recent call last):
645
+ ...
646
+ NotImplementedError: largest fundamental discriminant not available for class number 101
647
+ """
648
+ h = Integer(h)
649
+ if h <= 0:
650
+ return Integer(0), Integer(0)
651
+ try:
652
+ B, c = watkins_table[h]
653
+ return (Integer(B), Integer(c))
654
+ except KeyError:
655
+ raise NotImplementedError("largest fundamental discriminant not available for class number %s" % h)
656
+
657
+
658
+ def largest_disc_with_class_number(h):
659
+ r"""
660
+ Return largest absolute value of any negative discriminant with
661
+ class number `h`, and the number of fundamental negative
662
+ discriminants with that class number. This is known
663
+ (unconditionally) for `h` up to 100, by work of Mark Watkins
664
+ [Watkins2004]_ for fundamental discriminants, extended to all
665
+ discriminants of class number `h\le100` by Klaise [Klaise2012]_.
666
+
667
+ .. NOTE::
668
+
669
+ The class number of a negative discriminant `D` is
670
+ the same as the class number of the unique imaginary quadratic order
671
+ of discriminant `D`, so this function gives the number of such
672
+ orders of each class number `h\le100`. It is easy to extend
673
+ this to larger class number conditional on the GRH, but much
674
+ harder to obtain unconditional results.
675
+
676
+ INPUT:
677
+
678
+ - ``h`` -- integer
679
+
680
+ EXAMPLES::
681
+
682
+ sage: from sage.schemes.elliptic_curves.cm import largest_disc_with_class_number
683
+ sage: largest_disc_with_class_number(0)
684
+ (0, 0)
685
+ sage: largest_disc_with_class_number(1)
686
+ (163, 13)
687
+ sage: largest_disc_with_class_number(2)
688
+ (427, 29)
689
+ sage: largest_disc_with_class_number(10)
690
+ (13843, 123)
691
+ sage: largest_disc_with_class_number(100)
692
+ (1856563, 2311)
693
+ sage: largest_disc_with_class_number(101)
694
+ Traceback (most recent call last):
695
+ ...
696
+ NotImplementedError: largest discriminant not available for class number 101
697
+
698
+ For most `h\le100`, the largest fundamental discriminant with
699
+ class number `h` is also the largest discriminant, but this is not
700
+ the case for some `h`::
701
+
702
+ sage: from sage.schemes.elliptic_curves.cm import largest_disc_with_class_number, largest_fundamental_disc_with_class_number
703
+ sage: [h for h in range(1,101) if largest_disc_with_class_number(h)[0] != largest_fundamental_disc_with_class_number(h)[0]]
704
+ [6, 8, 12, 16, 20, 30, 40, 42, 52, 70]
705
+ sage: largest_fundamental_disc_with_class_number(6)
706
+ (3763, 51)
707
+ sage: largest_disc_with_class_number(6)
708
+ (4075, 101)
709
+ """
710
+ h = Integer(h)
711
+ if h <= 0:
712
+ return Integer(0), Integer(0)
713
+ try:
714
+ B, c = klaise_table[h]
715
+ return (Integer(B), Integer(c))
716
+ except KeyError:
717
+ raise NotImplementedError("largest discriminant not available for class number %s" % h)
718
+
719
+ # This dict has class numbers h as keys, the value at h is a complete
720
+ # list of pairs (D0,f) such that D=D0*f**2 has class number h. We
721
+ # initialise it with h=1 only; other values will be added by calls to
722
+ # discriminants_with_bounded_class_number().
723
+
724
+
725
+ hDf_dict = {ZZ(1): [(ZZ(D), ZZ(h)) for D,h in
726
+ [(-3, 1), (-3, 2), (-3, 3), (-4, 1), (-4, 2), (-7, 1), (-7, 2),
727
+ (-8, 1), (-11, 1), (-19, 1), (-43, 1), (-67, 1), (-163, 1)]]}
728
+
729
+
730
+ def discriminants_with_bounded_class_number(hmax, B=None, proof=None):
731
+ r"""Return a dictionary with keys class numbers `h\le hmax` and values the
732
+ list of all pairs `(D_0, f)`, with `D_0<0` a fundamental discriminant such
733
+ that `D=D_0f^2` has class number `h`. If the optional bound `B` is given,
734
+ return only those pairs with `|D| \le B`.
735
+
736
+ INPUT:
737
+
738
+ - ``hmax`` -- integer
739
+ - ``B`` -- integer or ``None``; if ``None`` returns all pairs
740
+ - ``proof`` -- this code calls the PARI function :pari:`qfbclassno`, so it
741
+ could give wrong answers when ``proof``==``False`` (though only for
742
+ discriminants greater than `2\cdot10^{10}`). The default is
743
+ the current value of ``proof.number_field()``.
744
+
745
+ OUTPUT: dictionary
746
+
747
+ .. NOTE::
748
+
749
+ In case `B` is not given, then ``hmax`` must be at most 100; we
750
+ use the tables from [Watkins2004]_ and [Klaise2012]_ to compute
751
+ a `B` that captures all `h` up to `hmax`.
752
+
753
+ EXAMPLES::
754
+
755
+ sage: # needs sage.libs.pari
756
+ sage: from sage.schemes.elliptic_curves.cm import discriminants_with_bounded_class_number
757
+ sage: v = discriminants_with_bounded_class_number(3)
758
+ sage: sorted(v)
759
+ [1, 2, 3]
760
+ sage: v[1]
761
+ [(-3, 1), (-3, 2), (-3, 3), (-4, 1), (-4, 2), (-7, 1), (-7, 2), (-8, 1),
762
+ (-11, 1), (-19, 1), (-43, 1), (-67, 1), (-163, 1)]
763
+ sage: v[2]
764
+ [(-3, 4), (-3, 5), (-3, 7), (-4, 3), (-4, 4), (-4, 5), (-7, 4), (-8, 2),
765
+ (-8, 3), (-11, 3), (-15, 1), (-15, 2), (-20, 1), (-24, 1), (-35, 1), (-40, 1),
766
+ (-51, 1), (-52, 1), (-88, 1), (-91, 1), (-115, 1), (-123, 1), (-148, 1),
767
+ (-187, 1), (-232, 1), (-235, 1), (-267, 1), (-403, 1), (-427, 1)]
768
+ sage: v[3]
769
+ [(-3, 6), (-3, 9), (-11, 2), (-19, 2), (-23, 1), (-23, 2), (-31, 1), (-31, 2),
770
+ (-43, 2), (-59, 1), (-67, 2), (-83, 1), (-107, 1), (-139, 1), (-163, 2),
771
+ (-211, 1), (-283, 1), (-307, 1), (-331, 1), (-379, 1), (-499, 1), (-547, 1),
772
+ (-643, 1), (-883, 1), (-907, 1)]
773
+ sage: v = discriminants_with_bounded_class_number(8, proof=False)
774
+ sage: sorted(len(v[h]) for h in v)
775
+ [13, 25, 29, 29, 38, 84, 101, 208]
776
+
777
+ Find all class numbers for discriminant up to 50::
778
+
779
+ sage: sage.schemes.elliptic_curves.cm.discriminants_with_bounded_class_number(hmax=5, B=50)
780
+ {1: [(-3, 1), (-3, 2), (-3, 3), (-4, 1), (-4, 2), (-7, 1), (-7, 2), (-8, 1), (-11, 1), (-19, 1), (-43, 1)], 2: [(-3, 4), (-4, 3), (-8, 2), (-15, 1), (-20, 1), (-24, 1), (-35, 1), (-40, 1)], 3: [(-11, 2), (-23, 1), (-31, 1)], 4: [(-39, 1)], 5: [(-47, 1)]}
781
+ """
782
+ hmax = Integer(hmax)
783
+ global hDf_dict
784
+
785
+ # Easy case where we have already computed and cached the relevant values
786
+ if hDf_dict and hmax <= max(hDf_dict):
787
+ T = {h:Dflist for h,Dflist in hDf_dict.items() if h <= hmax}
788
+ if B:
789
+ for h in T:
790
+ T[h] = [Df for Df in T[h] if Df[0].abs()*Df[1]**2 <= B]
791
+ return T
792
+
793
+ # imports that are needed only for this function
794
+ from sage.arith.srange import xsrange
795
+ from sage.structure.proof.proof import get_flag
796
+ proof = get_flag(proof, 'number_field')
797
+
798
+ if B is None:
799
+ if hmax <= 100:
800
+ # Determine how far we have to go by applying Watkins + Klaise's results.
801
+ v = [largest_disc_with_class_number(h) for h in range(1, hmax+1)]
802
+ B = max([b for b,_ in v])
803
+ #print("Testing all discriminants up to {}".format(B))
804
+ count = [0] + [cnt for _,cnt in v]
805
+ else:
806
+ raise ValueError("if hmax>100 you must specify a discriminant bound B")
807
+ else:
808
+ # Nothing to do -- set to None so we can use this later to know not
809
+ # to do a double check about how many we find.
810
+ count = None
811
+ B = Integer(B)
812
+
813
+ if B <= 2:
814
+ # This is an easy special case, since there are no fundamental discriminants
815
+ # this small.
816
+ return {}
817
+
818
+ # T stores the values found, to be returned. It will also be used
819
+ # to update the global hDf_dict *provided that* the parameter B
820
+ # was not provided. Note that we only reach this point if we have
821
+ # not already computed data for at least one class number, hmax.
822
+
823
+ # To avoid recomputing class numbers, we initialise T with the
824
+ # global hDf_dict, only including those (D,f) for which |D|*f**2
825
+ # <= B if B was provided:
826
+
827
+ # h_dict caches the class number h of all discriminants previously
828
+ # encountered; we will use the function OrderClassNumber() to
829
+ # quickly compute the class number of non-fundamental discriminants
830
+ # from the fundamental ones. Note that in the initialisation, the
831
+ # keys of h_dict include nonfundamental discriminants, but we only
832
+ # update it with fundamental ones.
833
+
834
+ from collections import defaultdict
835
+ T = defaultdict(set)
836
+ h_dict = {}
837
+ for h, Dflist in hDf_dict.items():
838
+ for D0,f in Dflist:
839
+ h_dict[D0*f**2] = h
840
+ if not count:
841
+ Dflist = [Df for Df in Dflist if Df[0].abs()*Df[1]**2 <= B]
842
+ T[h] = set(Dflist)
843
+
844
+ # We do not need to certify the class number from :pari:`qfbclassno` for discriminants under 2*10^10
845
+ if B < 2*10**10:
846
+ proof = False
847
+
848
+ for D in xsrange(-3, -B-1, -1):
849
+ if not D.is_discriminant():
850
+ continue
851
+ D0 = D.squarefree_part()
852
+ if D0 % 4 != 1:
853
+ D0 *= 4
854
+ f = (D//D0).isqrt()
855
+
856
+ # Now D0 is the fundamental discriminant and f the conductor
857
+
858
+ if D in h_dict:
859
+ h = h_dict[D]
860
+ else:
861
+ if f == 1: # D itself is fundamental
862
+ h = D.class_number(proof)
863
+ h_dict[D] = h
864
+ else:
865
+ h = OrderClassNumber(D0,h_dict[D0],f)
866
+
867
+ # If the class number of this order is within the range, then store (D0,f)
868
+ if h <= hmax:
869
+ T[h].add((D0,f))
870
+
871
+ # sort each list of (D,f) pairs by (|D|,f)
872
+
873
+ for h in T:
874
+ T[h] = list(T[h])
875
+ T[h].sort(key=lambda Df: (Df[0].abs(), Df[1]))
876
+
877
+ # count is None precisely when the user provided a value of B
878
+ if count is not None:
879
+ # 1. Check that we found the right number of discriminants
880
+ for h in T:
881
+ if len(T[h]) != count[h]:
882
+ raise RuntimeError("number of discriminants inconsistent with Watkins's table")
883
+ # 2. Update the global dict
884
+ hDf_dict.update(dict(T))
885
+
886
+ return T
887
+
888
+
889
+ @cached_function
890
+ def is_cm_j_invariant(j, algorithm='CremonaSutherland', method=None):
891
+ r"""
892
+ Return whether or not this is a CM `j`-invariant, and the CM discriminant if it is.
893
+
894
+ INPUT:
895
+
896
+ - ``j`` -- an element of a number field `K`
897
+
898
+ - ``algorithm`` -- string (default: ``'CremonaSutherland'``); the algorithm
899
+ used, either ``'CremonaSutherland'`` (the default, very much faster
900
+ for all but very small degrees), ``'exhaustive'`` or ``'reduction'``
901
+
902
+ - ``method`` -- string; deprecated name for ``algorithm``
903
+
904
+ OUTPUT:
905
+
906
+ A pair (bool, (d,f)) which is either (False, None) if `j` is not a
907
+ CM j-invariant or (True, (d,f)) if `j` is the `j`-invariant of the
908
+ imaginary quadratic order of discriminant `D=df^2` where `d` is
909
+ the associated fundamental discriminant and `f` the index.
910
+
911
+ ALGORITHM:
912
+
913
+ The default algorithm used is to test whether the minimal
914
+ polynomial of ``j`` is a Hilbert CLass Polynomial, using
915
+ :func:`is_HCP` which implements Algorithm 2 of [CreSuth2023]_ by
916
+ Cremona and Sutherland.
917
+
918
+ Two older algorithms are available, both of which are much slower
919
+ except for very small degrees.
920
+
921
+ Method 'exhaustive' makes use of the complete and unconditionsl classification of
922
+ all orders of class number up to 100, and hence will raise an
923
+ error if `j` is an algebraic integer of degree greater than
924
+ this.
925
+
926
+ Method 'reduction' constructs an elliptic curve over the number
927
+ field `\QQ(j)` and computes its traces of Frobenius at several
928
+ primes of degree 1.
929
+
930
+ EXAMPLES::
931
+
932
+ sage: from sage.schemes.elliptic_curves.cm import is_cm_j_invariant
933
+ sage: is_cm_j_invariant(0)
934
+ (True, (-3, 1))
935
+ sage: is_cm_j_invariant(8000)
936
+ (True, (-8, 1))
937
+
938
+ sage: # needs sage.rings.number_field
939
+ sage: K.<a> = QuadraticField(5)
940
+ sage: is_cm_j_invariant(282880*a + 632000)
941
+ (True, (-20, 1))
942
+ sage: x = polygen(ZZ, 'x')
943
+ sage: K.<a> = NumberField(x^3 - 2)
944
+ sage: is_cm_j_invariant(31710790944000*a^2 + 39953093016000*a + 50337742902000)
945
+ (True, (-3, 6))
946
+
947
+ An example of large degree. This is only possible using the default algorithm::
948
+
949
+ sage: from sage.schemes.elliptic_curves.cm import is_cm_j_invariant
950
+ sage: D = -1856563
951
+ sage: H = hilbert_class_polynomial(D) # needs sage.libs.flint
952
+ sage: H.degree() # needs sage.libs.flint
953
+ 100
954
+ sage: K.<j> = NumberField(H) # needs sage.libs.flint sage.rings.number_field
955
+ sage: is_cm_j_invariant(j) # needs sage.libs.flint sage.rings.number_field
956
+ (True, (-1856563, 1))
957
+
958
+ TESTS::
959
+
960
+ sage: from sage.schemes.elliptic_curves.cm import is_cm_j_invariant
961
+ sage: all(is_cm_j_invariant(j) == (True, (d,f)) for d,f,j in cm_j_invariants_and_orders(QQ))
962
+ True
963
+ """
964
+ if method:
965
+ if not algorithm:
966
+ algorithm = method
967
+ raise DeprecationWarning("'method' is deprecated, use 'algorithm instead'")
968
+
969
+ # First we check that j is an algebraic number:
970
+ if not isinstance(j, NumberFieldElement_base) and j not in QQ:
971
+ raise NotImplementedError("is_cm_j_invariant() is only implemented for number field elements")
972
+
973
+ # for j in ZZ we have a lookup-table:
974
+
975
+ if j in ZZ:
976
+ j = ZZ(j)
977
+ table = {jj: (d,f) for d,f,jj in cm_j_invariants_and_orders(QQ)}
978
+ if j in table:
979
+ return True, table[j]
980
+ return False, None
981
+
982
+ # Otherwise if j is in Q then it is not integral so is not CM:
983
+
984
+ if j in QQ:
985
+ return False, None
986
+
987
+ # Next we find its minimal polynomial of j:
988
+
989
+ if j.parent().absolute_degree() == 2:
990
+ jpol = j.absolute_minpoly() # no algorithm parameter
991
+ else:
992
+ jpol = j.absolute_minpoly(algorithm='pari')
993
+
994
+ # If it does not have integer coefficients then j is not integral, hence not CM:
995
+
996
+ if not all(c in ZZ for c in jpol):
997
+ return False, None
998
+
999
+ # Otherwise test whether it is a Hilbert Class Polynomial
1000
+ # (using the fact that we know that it is monic and irreducible):
1001
+
1002
+ if algorithm == 'CremonaSutherland':
1003
+ D = is_HCP(jpol, check_monic_irreducible=False)
1004
+ if D:
1005
+ D0 = D.squarefree_part()
1006
+ if D0 % 4 != 1:
1007
+ D0 *= 4
1008
+ f = ZZ(D // D0).isqrt()
1009
+ return (True, (D0, f))
1010
+ else:
1011
+ return (False, None)
1012
+
1013
+ h = jpol.degree()
1014
+ if algorithm in ['exhaustive', 'old']:
1015
+ if h > 100:
1016
+ raise NotImplementedError("CM data only available for class numbers up to 100")
1017
+ for d,f in cm_orders(h):
1018
+ if jpol == hilbert_class_polynomial(d*f**2):
1019
+ return (True, (d,f))
1020
+ return (False, None)
1021
+
1022
+ if algorithm not in ['reduction', 'new']:
1023
+ raise ValueError("Invalid algorithm {} in is_cm_j_invariant".format(algorithm))
1024
+
1025
+ # Now we use the reduction algorithm
1026
+
1027
+ # If the degree h is less than the degree of j.parent() we recreate j as an element
1028
+ # of Q(j, and replace j by a clone whose parent is Q(j), if necessary:
1029
+
1030
+ K = j.parent()
1031
+ if h < K.absolute_degree():
1032
+ from sage.rings.number_field.number_field import NumberField
1033
+
1034
+ K = NumberField(jpol, 'j')
1035
+ j = K.gen()
1036
+
1037
+ # Construct an elliptic curve with j-invariant j, with
1038
+ # integral model:
1039
+
1040
+ from sage.schemes.elliptic_curves.constructor import EllipticCurve
1041
+ E = EllipticCurve(j=j).integral_model()
1042
+ D = E.discriminant()
1043
+ prime_bound = 1000 # test primes of degree 1 up to this norm
1044
+ max_primes = 20 # test at most this many primes
1045
+ num_prime = 0
1046
+ cmd = 0
1047
+ cmf = 0
1048
+
1049
+ # Test primes of good reduction. If E has CM then for half the
1050
+ # primes P we will have a_P=0, and for all other prime P the CM
1051
+ # field is Q(sqrt(a_P^2-4N(P))). Hence if these fields are
1052
+ # different for two primes then E does not have CM. If they are
1053
+ # all equal for the primes tested, then we have a candidate CM
1054
+ # field. Moreover the discriminant of the endomorphism ring
1055
+ # divides all the values a_P^2-4N(P), since that is the
1056
+ # discriminant of the order containing the Frobenius at P. So we
1057
+ # end up with a finite number (usually one) of candidate
1058
+ # discriminants to test. Each is tested by checking that its class
1059
+ # number is h, and if so then that j is a root of its Hilbert
1060
+ # class polynomial. In practice non CM curves will be eliminated
1061
+ # by the local test at a small number of primes (probably just 2).
1062
+
1063
+ for P in K.primes_of_degree_one_iter(prime_bound):
1064
+ if num_prime > max_primes:
1065
+ if cmd: # we have a candidate CM field already
1066
+ break
1067
+ else: # we need to try more primes
1068
+ max_primes *= 2
1069
+ if D.valuation(P) > 0: # skip bad primes
1070
+ continue
1071
+ aP = E.reduction(P).trace_of_frobenius()
1072
+ if aP == 0: # skip supersingular primes
1073
+ continue
1074
+ num_prime += 1
1075
+ DP = aP**2 - 4*P.norm()
1076
+ dP = DP.squarefree_part()
1077
+ fP = ZZ(DP//dP).isqrt()
1078
+ if cmd == 0: # first one, so store d and f
1079
+ cmd = dP
1080
+ cmf = fP
1081
+ elif cmd != dP: # inconsistent with previous
1082
+ return (False, None)
1083
+ else: # consistent d, so update f
1084
+ cmf = cmf.gcd(fP)
1085
+
1086
+ if cmd == 0: # no conclusion, we found no degree 1 primes, revert to default algorithm
1087
+ return is_cm_j_invariant(j)
1088
+
1089
+ # it looks like cm by disc cmd * f**2 where f divides cmf
1090
+
1091
+ if cmd % 4 != 1:
1092
+ cmd = cmd * 4
1093
+ cmf = cmf // 2
1094
+
1095
+ # Now we must check if h(cmd*f**2)==h for f|cmf; if so we check
1096
+ # whether j is a root of the associated Hilbert class polynomial.
1097
+ h0 = cmd.class_number()
1098
+ for f in cmf.divisors(): # only positive divisors
1099
+ if h != OrderClassNumber(cmd,h0,f):
1100
+ continue
1101
+ if jpol == hilbert_class_polynomial(cmd*f**2):
1102
+ return (True, (cmd, f))
1103
+ return (False, None)