passagemath-flint 10.6.1rc10__cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.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.
- passagemath_flint-10.6.1rc10.dist-info/METADATA +122 -0
- passagemath_flint-10.6.1rc10.dist-info/RECORD +360 -0
- passagemath_flint-10.6.1rc10.dist-info/WHEEL +6 -0
- passagemath_flint-10.6.1rc10.dist-info/top_level.txt +2 -0
- passagemath_flint.libs/libflint-3701249d.so.21.0.0 +0 -0
- passagemath_flint.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
- passagemath_flint.libs/libgfortran-8a9a71bc.so.5.0.0 +0 -0
- passagemath_flint.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
- passagemath_flint.libs/libgsl-e3525837.so.28.0.0 +0 -0
- passagemath_flint.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
- passagemath_flint.libs/libmpfr-e0f11cf3.so.6.2.1 +0 -0
- passagemath_flint.libs/libntl-1004113e.so.44.0.1 +0 -0
- passagemath_flint.libs/libopenblasp-r0-4c5b64b1.3.29.so +0 -0
- sage/all__sagemath_flint.py +29 -0
- sage/combinat/all__sagemath_flint.py +1 -0
- sage/combinat/posets/all__sagemath_flint.py +1 -0
- sage/combinat/posets/hasse_cython_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/hasse_cython_flint.pyx +194 -0
- sage/data_structures/all__sagemath_flint.py +1 -0
- sage/data_structures/bounded_integer_sequences.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/data_structures/bounded_integer_sequences.pxd +62 -0
- sage/data_structures/bounded_integer_sequences.pyx +1418 -0
- sage/graphs/all__sagemath_flint.py +1 -0
- sage/graphs/chrompoly.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/graphs/chrompoly.pyx +555 -0
- sage/graphs/matchpoly.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/graphs/matchpoly.pyx +412 -0
- sage/libs/all__sagemath_flint.py +17 -0
- sage/libs/arb/__init__.py +1 -0
- sage/libs/arb/acb.pxd +154 -0
- sage/libs/arb/acb_calc.pxd +9 -0
- sage/libs/arb/acb_elliptic.pxd +25 -0
- sage/libs/arb/acb_hypgeom.pxd +74 -0
- sage/libs/arb/acb_mat.pxd +62 -0
- sage/libs/arb/acb_modular.pxd +17 -0
- sage/libs/arb/acb_poly.pxd +216 -0
- sage/libs/arb/arb.pxd +240 -0
- sage/libs/arb/arb_fmpz_poly.pxd +21 -0
- sage/libs/arb/arb_hypgeom.pxd +83 -0
- sage/libs/arb/arb_wrap.h +34 -0
- sage/libs/arb/arf.pxd +131 -0
- sage/libs/arb/arith.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/arb/arith.pyx +87 -0
- sage/libs/arb/bernoulli.pxd +6 -0
- sage/libs/arb/mag.pxd +77 -0
- sage/libs/arb/types.pxd +37 -0
- sage/libs/flint/__init__.py +1 -0
- sage/libs/flint/acb.pxd +270 -0
- sage/libs/flint/acb_calc.pxd +22 -0
- sage/libs/flint/acb_dft.pxd +51 -0
- sage/libs/flint/acb_dirichlet.pxd +112 -0
- sage/libs/flint/acb_elliptic.pxd +42 -0
- sage/libs/flint/acb_hypgeom.pxd +169 -0
- sage/libs/flint/acb_macros.pxd +9 -0
- sage/libs/flint/acb_mat.pxd +136 -0
- sage/libs/flint/acb_mat_macros.pxd +10 -0
- sage/libs/flint/acb_modular.pxd +62 -0
- sage/libs/flint/acb_poly.pxd +251 -0
- sage/libs/flint/acb_poly_macros.pxd +8 -0
- sage/libs/flint/acb_theta.pxd +124 -0
- sage/libs/flint/acf.pxd +32 -0
- sage/libs/flint/aprcl.pxd +84 -0
- sage/libs/flint/arb.pxd +382 -0
- sage/libs/flint/arb_calc.pxd +31 -0
- sage/libs/flint/arb_fmpz_poly.pxd +34 -0
- sage/libs/flint/arb_fpwrap.pxd +215 -0
- sage/libs/flint/arb_hypgeom.pxd +147 -0
- sage/libs/flint/arb_macros.pxd +9 -0
- sage/libs/flint/arb_mat.pxd +140 -0
- sage/libs/flint/arb_mat_macros.pxd +10 -0
- sage/libs/flint/arb_poly.pxd +237 -0
- sage/libs/flint/arf.pxd +167 -0
- sage/libs/flint/arith.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/arith.pxd +76 -0
- sage/libs/flint/arith.pyx +77 -0
- sage/libs/flint/arith_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/arith_sage.pyx +308 -0
- sage/libs/flint/bernoulli.pxd +28 -0
- sage/libs/flint/bool_mat.pxd +52 -0
- sage/libs/flint/ca.pxd +203 -0
- sage/libs/flint/ca_ext.pxd +34 -0
- sage/libs/flint/ca_field.pxd +32 -0
- sage/libs/flint/ca_mat.pxd +117 -0
- sage/libs/flint/ca_poly.pxd +104 -0
- sage/libs/flint/ca_vec.pxd +46 -0
- sage/libs/flint/calcium.pxd +27 -0
- sage/libs/flint/d_mat.pxd +39 -0
- sage/libs/flint/d_vec.pxd +32 -0
- sage/libs/flint/dirichlet.pxd +57 -0
- sage/libs/flint/dlog.pxd +53 -0
- sage/libs/flint/double_extras.pxd +24 -0
- sage/libs/flint/double_interval.pxd +36 -0
- sage/libs/flint/fexpr.pxd +104 -0
- sage/libs/flint/fexpr_builtin.pxd +20 -0
- sage/libs/flint/fft.pxd +66 -0
- sage/libs/flint/flint.pxd +36 -0
- sage/libs/flint/flint_ntl_wrap.h +35 -0
- sage/libs/flint/flint_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/flint_sage.pyx +163 -0
- sage/libs/flint/flint_wrap.h +190 -0
- sage/libs/flint/fmpq.pxd +137 -0
- sage/libs/flint/fmpq_mat.pxd +105 -0
- sage/libs/flint/fmpq_mat_macros.pxd +10 -0
- sage/libs/flint/fmpq_mpoly.pxd +165 -0
- sage/libs/flint/fmpq_mpoly_factor.pxd +30 -0
- sage/libs/flint/fmpq_poly.pxd +241 -0
- sage/libs/flint/fmpq_poly_macros.pxd +9 -0
- sage/libs/flint/fmpq_poly_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/fmpq_poly_sage.pxd +31 -0
- sage/libs/flint/fmpq_poly_sage.pyx +48 -0
- sage/libs/flint/fmpq_vec.pxd +27 -0
- sage/libs/flint/fmpz.pxd +256 -0
- sage/libs/flint/fmpz_extras.pxd +32 -0
- sage/libs/flint/fmpz_factor.pxd +42 -0
- sage/libs/flint/fmpz_factor_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_factor_sage.pxd +4 -0
- sage/libs/flint/fmpz_factor_sage.pyx +29 -0
- sage/libs/flint/fmpz_lll.pxd +49 -0
- sage/libs/flint/fmpz_macros.pxd +8 -0
- sage/libs/flint/fmpz_mat.pxd +184 -0
- sage/libs/flint/fmpz_mat_macros.pxd +10 -0
- sage/libs/flint/fmpz_mod.pxd +46 -0
- sage/libs/flint/fmpz_mod_mat.pxd +71 -0
- sage/libs/flint/fmpz_mod_mpoly.pxd +161 -0
- sage/libs/flint/fmpz_mod_mpoly_factor.pxd +28 -0
- sage/libs/flint/fmpz_mod_poly.pxd +249 -0
- sage/libs/flint/fmpz_mod_poly_factor.pxd +46 -0
- sage/libs/flint/fmpz_mod_vec.pxd +27 -0
- sage/libs/flint/fmpz_mpoly.pxd +224 -0
- sage/libs/flint/fmpz_mpoly_factor.pxd +29 -0
- sage/libs/flint/fmpz_mpoly_q.pxd +57 -0
- sage/libs/flint/fmpz_poly.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_poly.pxd +407 -0
- sage/libs/flint/fmpz_poly.pyx +19 -0
- sage/libs/flint/fmpz_poly_factor.pxd +33 -0
- sage/libs/flint/fmpz_poly_macros.pxd +8 -0
- sage/libs/flint/fmpz_poly_mat.pxd +71 -0
- sage/libs/flint/fmpz_poly_q.pxd +55 -0
- sage/libs/flint/fmpz_poly_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_poly_sage.pxd +20 -0
- sage/libs/flint/fmpz_poly_sage.pyx +500 -0
- sage/libs/flint/fmpz_vec.pxd +80 -0
- sage/libs/flint/fmpzi.pxd +52 -0
- sage/libs/flint/fq.pxd +97 -0
- sage/libs/flint/fq_default.pxd +84 -0
- sage/libs/flint/fq_default_mat.pxd +70 -0
- sage/libs/flint/fq_default_poly.pxd +97 -0
- sage/libs/flint/fq_default_poly_factor.pxd +39 -0
- sage/libs/flint/fq_embed.pxd +28 -0
- sage/libs/flint/fq_mat.pxd +83 -0
- sage/libs/flint/fq_nmod.pxd +95 -0
- sage/libs/flint/fq_nmod_embed.pxd +28 -0
- sage/libs/flint/fq_nmod_mat.pxd +83 -0
- sage/libs/flint/fq_nmod_mpoly.pxd +130 -0
- sage/libs/flint/fq_nmod_mpoly_factor.pxd +28 -0
- sage/libs/flint/fq_nmod_poly.pxd +202 -0
- sage/libs/flint/fq_nmod_poly_factor.pxd +47 -0
- sage/libs/flint/fq_nmod_vec.pxd +33 -0
- sage/libs/flint/fq_poly.pxd +204 -0
- sage/libs/flint/fq_poly_factor.pxd +47 -0
- sage/libs/flint/fq_vec.pxd +33 -0
- sage/libs/flint/fq_zech.pxd +99 -0
- sage/libs/flint/fq_zech_embed.pxd +28 -0
- sage/libs/flint/fq_zech_mat.pxd +78 -0
- sage/libs/flint/fq_zech_poly.pxd +198 -0
- sage/libs/flint/fq_zech_poly_factor.pxd +47 -0
- sage/libs/flint/fq_zech_vec.pxd +33 -0
- sage/libs/flint/gr.pxd +174 -0
- sage/libs/flint/gr_generic.pxd +215 -0
- sage/libs/flint/gr_mat.pxd +161 -0
- sage/libs/flint/gr_mpoly.pxd +68 -0
- sage/libs/flint/gr_poly.pxd +276 -0
- sage/libs/flint/gr_special.pxd +237 -0
- sage/libs/flint/gr_vec.pxd +120 -0
- sage/libs/flint/hypgeom.pxd +24 -0
- sage/libs/flint/long_extras.pxd +23 -0
- sage/libs/flint/mag.pxd +131 -0
- sage/libs/flint/mag_macros.pxd +8 -0
- sage/libs/flint/mpf_mat.pxd +36 -0
- sage/libs/flint/mpf_vec.pxd +34 -0
- sage/libs/flint/mpfr_mat.pxd +27 -0
- sage/libs/flint/mpfr_vec.pxd +25 -0
- sage/libs/flint/mpn_extras.pxd +41 -0
- sage/libs/flint/mpoly.pxd +72 -0
- sage/libs/flint/nf.pxd +19 -0
- sage/libs/flint/nf_elem.pxd +74 -0
- sage/libs/flint/nmod.pxd +35 -0
- sage/libs/flint/nmod_mat.pxd +104 -0
- sage/libs/flint/nmod_mpoly.pxd +144 -0
- sage/libs/flint/nmod_mpoly_factor.pxd +28 -0
- sage/libs/flint/nmod_poly.pxd +339 -0
- sage/libs/flint/nmod_poly_factor.pxd +44 -0
- sage/libs/flint/nmod_poly_linkage.pxi +710 -0
- sage/libs/flint/nmod_poly_mat.pxd +76 -0
- sage/libs/flint/nmod_vec.pxd +40 -0
- sage/libs/flint/ntl_interface.pxd +17 -0
- sage/libs/flint/padic.pxd +93 -0
- sage/libs/flint/padic_mat.pxd +64 -0
- sage/libs/flint/padic_poly.pxd +88 -0
- sage/libs/flint/partitions.pxd +23 -0
- sage/libs/flint/perm.pxd +26 -0
- sage/libs/flint/profiler.pxd +24 -0
- sage/libs/flint/qadic.pxd +77 -0
- sage/libs/flint/qfb.pxd +44 -0
- sage/libs/flint/qqbar.pxd +172 -0
- sage/libs/flint/qsieve.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/qsieve.pxd +41 -0
- sage/libs/flint/qsieve.pyx +21 -0
- sage/libs/flint/qsieve_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/qsieve_sage.pyx +67 -0
- sage/libs/flint/thread_pool.pxd +25 -0
- sage/libs/flint/types.pxd +2076 -0
- sage/libs/flint/ulong_extras.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/ulong_extras.pxd +141 -0
- sage/libs/flint/ulong_extras.pyx +21 -0
- sage/libs/flint/ulong_extras_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/ulong_extras_sage.pyx +21 -0
- sage/matrix/all__sagemath_flint.py +1 -0
- sage/matrix/change_ring.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/change_ring.pyx +43 -0
- sage/matrix/matrix_complex_ball_dense.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_complex_ball_dense.pxd +14 -0
- sage/matrix/matrix_complex_ball_dense.pyx +973 -0
- sage/matrix/matrix_cyclo_dense.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_cyclo_dense.pxd +16 -0
- sage/matrix/matrix_cyclo_dense.pyx +1761 -0
- sage/matrix/matrix_integer_dense.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_dense.pxd +32 -0
- sage/matrix/matrix_integer_dense.pyx +5801 -0
- sage/matrix/matrix_integer_dense_hnf.py +1294 -0
- sage/matrix/matrix_integer_dense_saturation.py +346 -0
- sage/matrix/matrix_integer_sparse.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_sparse.pxd +9 -0
- sage/matrix/matrix_integer_sparse.pyx +1090 -0
- sage/matrix/matrix_rational_dense.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_rational_dense.pxd +23 -0
- sage/matrix/matrix_rational_dense.pyx +2995 -0
- sage/matrix/matrix_rational_sparse.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_rational_sparse.pxd +11 -0
- sage/matrix/matrix_rational_sparse.pyx +789 -0
- sage/matrix/misc_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/misc_flint.pyx +109 -0
- sage/modular/all__sagemath_flint.py +1 -0
- sage/modular/modform/all__sagemath_flint.py +1 -0
- sage/modular/modform/eis_series_cython.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/modular/modform/eis_series_cython.pyx +226 -0
- sage/modular/modsym/all__sagemath_flint.py +1 -0
- sage/modular/modsym/apply.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/modular/modsym/apply.pxd +6 -0
- sage/modular/modsym/apply.pyx +113 -0
- sage/modular/modsym/heilbronn.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/modular/modsym/heilbronn.pyx +966 -0
- sage/modular/pollack_stevens/all__sagemath_flint.py +1 -0
- sage/modular/pollack_stevens/dist.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/modular/pollack_stevens/dist.pxd +38 -0
- sage/modular/pollack_stevens/dist.pyx +1439 -0
- sage/quivers/algebra.py +691 -0
- sage/quivers/algebra_elements.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/quivers/algebra_elements.pxd +97 -0
- sage/quivers/algebra_elements.pxi +1324 -0
- sage/quivers/algebra_elements.pyx +1424 -0
- sage/quivers/all.py +1 -0
- sage/quivers/ar_quiver.py +917 -0
- sage/quivers/homspace.py +640 -0
- sage/quivers/morphism.py +1282 -0
- sage/quivers/path_semigroup.py +1155 -0
- sage/quivers/paths.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/quivers/paths.pxd +13 -0
- sage/quivers/paths.pyx +809 -0
- sage/quivers/representation.py +2975 -0
- sage/rings/all__sagemath_flint.py +37 -0
- sage/rings/cif.py +4 -0
- sage/rings/complex_arb.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/complex_arb.pxd +29 -0
- sage/rings/complex_arb.pyx +5176 -0
- sage/rings/complex_interval.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/complex_interval.pxd +30 -0
- sage/rings/complex_interval.pyx +2475 -0
- sage/rings/complex_interval_field.py +711 -0
- sage/rings/convert/all.py +1 -0
- sage/rings/convert/mpfi.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/convert/mpfi.pxd +6 -0
- sage/rings/convert/mpfi.pyx +576 -0
- sage/rings/factorint_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/factorint_flint.pyx +99 -0
- sage/rings/fraction_field_FpT.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/fraction_field_FpT.pxd +28 -0
- sage/rings/fraction_field_FpT.pyx +2043 -0
- sage/rings/imaginary_unit.py +5 -0
- sage/rings/monomials.py +73 -0
- sage/rings/number_field/S_unit_solver.py +2870 -0
- sage/rings/number_field/all__sagemath_flint.py +7 -0
- sage/rings/number_field/bdd_height.py +664 -0
- sage/rings/number_field/class_group.py +762 -0
- sage/rings/number_field/galois_group.py +1307 -0
- sage/rings/number_field/homset.py +612 -0
- sage/rings/number_field/maps.py +687 -0
- sage/rings/number_field/morphism.py +272 -0
- sage/rings/number_field/number_field.py +12820 -0
- sage/rings/number_field/number_field_element.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_element.pxd +59 -0
- sage/rings/number_field/number_field_element.pyx +5735 -0
- sage/rings/number_field/number_field_element_quadratic.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_element_quadratic.pxd +34 -0
- sage/rings/number_field/number_field_element_quadratic.pyx +3185 -0
- sage/rings/number_field/number_field_ideal_rel.py +925 -0
- sage/rings/number_field/number_field_morphisms.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_morphisms.pyx +781 -0
- sage/rings/number_field/number_field_rel.py +2734 -0
- sage/rings/number_field/order.py +2981 -0
- sage/rings/number_field/order_ideal.py +804 -0
- sage/rings/number_field/selmer_group.py +715 -0
- sage/rings/number_field/small_primes_of_degree_one.py +242 -0
- sage/rings/number_field/splitting_field.py +606 -0
- sage/rings/number_field/structure.py +380 -0
- sage/rings/number_field/unit_group.py +721 -0
- sage/rings/padics/all__sagemath_flint.py +3 -0
- sage/rings/polynomial/all__sagemath_flint.py +1 -0
- sage/rings/polynomial/complex_roots.py +312 -0
- sage/rings/polynomial/evaluation_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/evaluation_flint.pxd +7 -0
- sage/rings/polynomial/evaluation_flint.pyx +68 -0
- sage/rings/polynomial/hilbert.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/hilbert.pyx +602 -0
- sage/rings/polynomial/polynomial_complex_arb.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_complex_arb.pxd +7 -0
- sage/rings/polynomial/polynomial_complex_arb.pyx +963 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.pxd +13 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.pyx +1881 -0
- sage/rings/polynomial/polynomial_number_field.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_number_field.pyx +345 -0
- sage/rings/polynomial/polynomial_rational_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_rational_flint.pxd +20 -0
- sage/rings/polynomial/polynomial_rational_flint.pyx +2598 -0
- sage/rings/polynomial/polynomial_zmod_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_zmod_flint.pxd +20 -0
- sage/rings/polynomial/polynomial_zmod_flint.pyx +1063 -0
- sage/rings/polynomial/real_roots.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/real_roots.pxd +81 -0
- sage/rings/polynomial/real_roots.pyx +4704 -0
- sage/rings/polynomial/refine_root.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/refine_root.pyx +142 -0
- sage/rings/polynomial/weil/all.py +4 -0
- sage/rings/polynomial/weil/power_sums.h +46 -0
- sage/rings/polynomial/weil/weil_polynomials.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/weil/weil_polynomials.pyx +596 -0
- sage/rings/qqbar.py +9025 -0
- sage/rings/real_arb.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/real_arb.pxd +21 -0
- sage/rings/real_arb.pyx +4065 -0
- sage/rings/real_interval_absolute.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/real_interval_absolute.pyx +1073 -0
- sage/rings/real_mpfi.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/real_mpfi.pyx +5428 -0
- sage/schemes/all__sagemath_flint.py +1 -0
- sage/schemes/elliptic_curves/all__sagemath_flint.py +1 -0
- sage/schemes/elliptic_curves/descent_two_isogeny.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/schemes/elliptic_curves/descent_two_isogeny.pyx +1387 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.pxd +5 -0
@@ -0,0 +1,715 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-flint
|
2
|
+
# sage.doctest: needs sage.libs.pari
|
3
|
+
r"""
|
4
|
+
`p`-Selmer groups of number fields
|
5
|
+
|
6
|
+
This file contains code to compute `K(S,p)` where
|
7
|
+
|
8
|
+
- `K` is a number field
|
9
|
+
- `S` is a finite set of primes of `K`
|
10
|
+
- `p` is a prime number
|
11
|
+
|
12
|
+
For `m\ge2`, `K(S,m)` is defined to be the finite subgroup of
|
13
|
+
`K^*/(K^*)^m` consisting of elements represented by `a\in K^*` whose
|
14
|
+
valuation at all primes not in `S` is a multiple of `m`. It fits in
|
15
|
+
the short exact sequence
|
16
|
+
|
17
|
+
.. MATH::
|
18
|
+
|
19
|
+
1 \rightarrow O^*_{K,S}/(O^*_{K,S})^m \rightarrow K(S,m) \rightarrow Cl_{K,S}[m] \rightarrow 1
|
20
|
+
|
21
|
+
where `O^*_{K,S}` is the group of `S`-units of `K` and `Cl_{K,S}` the
|
22
|
+
`S`-class group. When `m=p` is prime, `K(S,p)` is a
|
23
|
+
finite-dimensional vector space over `GF(p)`. Its generators come
|
24
|
+
from three sources: units (modulo `p`-th powers); generators of the
|
25
|
+
`p`-th powers of ideals which are not principal but whose `p`-th
|
26
|
+
powers are principal; and generators coming from the prime ideals in
|
27
|
+
`S`.
|
28
|
+
|
29
|
+
The main function here is :meth:`pSelmerGroup`. This will not
|
30
|
+
normally be used by users, who instead will access it through a method
|
31
|
+
of the NumberField class.
|
32
|
+
|
33
|
+
|
34
|
+
AUTHORS:
|
35
|
+
|
36
|
+
- John Cremona (2005-2021)
|
37
|
+
"""
|
38
|
+
|
39
|
+
# ****************************************************************************
|
40
|
+
# Copyright (C) 2021 John Cremona <john.cremona@gmail.com>
|
41
|
+
#
|
42
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
43
|
+
# as published by the Free Software Foundation; either version 2 of
|
44
|
+
# the License, or (at your option) any later version.
|
45
|
+
# https://www.gnu.org/licenses/
|
46
|
+
# ****************************************************************************
|
47
|
+
|
48
|
+
|
49
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
50
|
+
from sage.rings.rational_field import QQ
|
51
|
+
from sage.misc.misc_c import prod
|
52
|
+
|
53
|
+
# A utility function to allow the same code to be used over QQ and
|
54
|
+
# over number fields:
|
55
|
+
|
56
|
+
|
57
|
+
def _ideal_generator(I):
|
58
|
+
r"""
|
59
|
+
Return the generator of a principal ideal.
|
60
|
+
|
61
|
+
INPUT:
|
62
|
+
|
63
|
+
- ``I`` -- either a fractional ideal of a number field, which must be
|
64
|
+
principal, or a rational integer
|
65
|
+
|
66
|
+
OUTPUT: a generator of `I` when `I` is a principal ideal, else `I` itself
|
67
|
+
|
68
|
+
EXAMPLES::
|
69
|
+
|
70
|
+
sage: from sage.rings.number_field.selmer_group import _ideal_generator
|
71
|
+
sage: _ideal_generator(5)
|
72
|
+
5
|
73
|
+
|
74
|
+
sage: K.<a> = QuadraticField(-11)
|
75
|
+
sage: [_ideal_generator(K.prime_above(p)) for p in primes(25)]
|
76
|
+
[2, 1/2*a - 1/2, -1/2*a - 3/2, 7, a, 13, 17, 19, 1/2*a + 9/2]
|
77
|
+
"""
|
78
|
+
try:
|
79
|
+
return I.gens_reduced()[0]
|
80
|
+
except AttributeError:
|
81
|
+
return I.abs()
|
82
|
+
|
83
|
+
|
84
|
+
def _coords_in_C_p(I, C, p):
|
85
|
+
r"""
|
86
|
+
Return coordinates of the ideal ``I`` with respect to a basis of
|
87
|
+
the `p`-torsion of the ideal class group ``C``.
|
88
|
+
|
89
|
+
INPUT:
|
90
|
+
|
91
|
+
- ``I`` -- ideal; a fractional ideal of a number field ``K``, whose
|
92
|
+
`p`-th power is principal
|
93
|
+
|
94
|
+
- ``C`` -- (class group) the ideal class group of ``K``
|
95
|
+
|
96
|
+
- ``p`` -- prime number
|
97
|
+
|
98
|
+
OUTPUT:
|
99
|
+
|
100
|
+
The coordinates of the ideal class `[I]` in the `p`-torsion
|
101
|
+
subgroup `C[p]`. An error is raised if `I^p` is not principal.
|
102
|
+
|
103
|
+
ALGORITHM:
|
104
|
+
|
105
|
+
Find the coordinates of `[I]` with respect to generators of `C` as
|
106
|
+
an abelian group, check that coordinates are 0 in cyclic factors
|
107
|
+
of order prime to `p`, and return the list of `c/(n/p)` (mod `p`)
|
108
|
+
for coordinates `c` for each cyclic factor of order `n` which is a
|
109
|
+
multiple of `p`.
|
110
|
+
|
111
|
+
EXAMPLES::
|
112
|
+
|
113
|
+
sage: from sage.rings.number_field.selmer_group import _coords_in_C_p
|
114
|
+
sage: K.<a> = QuadraticField(-5)
|
115
|
+
sage: C = K.class_group()
|
116
|
+
sage: C.order()
|
117
|
+
2
|
118
|
+
sage: P = K.prime_above(2)
|
119
|
+
sage: C(P).order()
|
120
|
+
2
|
121
|
+
sage: _coords_in_C_p(P,C,2)
|
122
|
+
[1]
|
123
|
+
sage: _coords_in_C_p(P,C,3)
|
124
|
+
Traceback (most recent call last):
|
125
|
+
...
|
126
|
+
ValueError: The 3rd power of Fractional ideal (2, a + 1) is not principal
|
127
|
+
"""
|
128
|
+
cyclic_orders = C.gens_orders()
|
129
|
+
non_p_indices = [i for i,n in enumerate(cyclic_orders) if not p.divides(n)]
|
130
|
+
p_indices = [(i, n // p) for i,n in enumerate(cyclic_orders) if p.divides(n)]
|
131
|
+
|
132
|
+
coords = C(I).exponents()
|
133
|
+
if all(coords[i] == 0 for i in non_p_indices) and all(coords[i] % n == 0 for i, n in p_indices):
|
134
|
+
return [(coords[i] // n) % p for i, n in p_indices]
|
135
|
+
raise ValueError("The {} power of {} is not principal".format(p.ordinal_str(),I))
|
136
|
+
|
137
|
+
|
138
|
+
def _coords_in_C_mod_p(I, C, p):
|
139
|
+
r"""
|
140
|
+
Return coordinates of the ideal ``I`` with respect to a basis of
|
141
|
+
the `p`-cotorsion of the ideal class group ``C``.
|
142
|
+
|
143
|
+
INPUT:
|
144
|
+
|
145
|
+
- ``I`` -- ideal; a fractional ideal of a number field ``K``
|
146
|
+
|
147
|
+
- ``C`` -- (class group) the ideal class group of ``K``
|
148
|
+
|
149
|
+
- ``p`` -- prime number
|
150
|
+
|
151
|
+
OUTPUT:
|
152
|
+
|
153
|
+
The coordinates of the ideal class `[I]` in the `p`-cotorsion group `C/C^p`.
|
154
|
+
|
155
|
+
ALGORITHM:
|
156
|
+
|
157
|
+
Find the coordinates of `[I]` with respect to generators of `C` as
|
158
|
+
an abelian group, and return the list of `c` (mod `p`)
|
159
|
+
for coordinates `c` for each cyclic factor of order `n` which is a
|
160
|
+
multiple of `p`.
|
161
|
+
|
162
|
+
EXAMPLES::
|
163
|
+
|
164
|
+
sage: from sage.rings.number_field.selmer_group import _coords_in_C_mod_p
|
165
|
+
sage: K.<a> = QuadraticField(-5)
|
166
|
+
sage: C = K.class_group()
|
167
|
+
sage: [_coords_in_C_mod_p(K.prime_above(p), C, 2) for p in primes(25)]
|
168
|
+
[[1], [1], [0], [1], [0], [0], [0], [0], [1]]
|
169
|
+
|
170
|
+
An example where the class group has two primary components, one
|
171
|
+
of which is not cyclic::
|
172
|
+
|
173
|
+
sage: from sage.rings.number_field.selmer_group import _coords_in_C_mod_p
|
174
|
+
sage: x = polygen(ZZ, 'x')
|
175
|
+
sage: K.<a> = NumberField(x^2 - x + 58)
|
176
|
+
sage: C = K.class_group()
|
177
|
+
sage: C.gens_orders()
|
178
|
+
(6, 2)
|
179
|
+
sage: [_coords_in_C_mod_p(K.prime_above(p), C, 2) for p in primes(25)]
|
180
|
+
[[1, 0], [1, 1], [1, 1], [0, 1], [1, 0], [0, 1], [0, 0], [0, 1], [0, 0]]
|
181
|
+
sage: [_coords_in_C_mod_p(K.prime_above(p), C, 3) for p in primes(25)]
|
182
|
+
[[2], [0], [1], [0], [0], [1], [0], [2], [0]]
|
183
|
+
"""
|
184
|
+
cyclic_orders = C.gens_orders()
|
185
|
+
p_indices = [i for i, n in enumerate(cyclic_orders) if p.divides(n)]
|
186
|
+
coords = C(I).exponents()
|
187
|
+
return [coords[i] % p for i in p_indices]
|
188
|
+
|
189
|
+
|
190
|
+
def _root_ideal(I, C, p):
|
191
|
+
r"""
|
192
|
+
Return a `p`-th root of an ideal with respect to the class group.
|
193
|
+
|
194
|
+
INPUT:
|
195
|
+
|
196
|
+
- ``I`` -- ideal; a fractional ideal of a number field ``K``,
|
197
|
+
whose ideal class is a `p`-th power
|
198
|
+
|
199
|
+
- ``C`` -- (class group) the ideal class group of ``K``
|
200
|
+
|
201
|
+
- ``p`` -- prime number
|
202
|
+
|
203
|
+
OUTPUT: an ideal `J` such that `J^p` is in the same ideal class as `I`
|
204
|
+
|
205
|
+
EXAMPLES::
|
206
|
+
|
207
|
+
sage: from sage.rings.number_field.selmer_group import _root_ideal
|
208
|
+
sage: x = polygen(ZZ, 'x')
|
209
|
+
sage: K.<a> = NumberField(x^2 - x + 58)
|
210
|
+
sage: C = K.class_group()
|
211
|
+
sage: cyclic_gens = C.gens_ideals()
|
212
|
+
sage: [C(I).order() for I in cyclic_gens]
|
213
|
+
[6, 2]
|
214
|
+
sage: C.gens_orders()
|
215
|
+
(6, 2)
|
216
|
+
sage: I = cyclic_gens[0]^2
|
217
|
+
sage: J = _root_ideal(I, C, 2)
|
218
|
+
sage: C(J^2) == C(I)
|
219
|
+
True
|
220
|
+
sage: I = cyclic_gens[0]^3
|
221
|
+
sage: J = _root_ideal(I, C, 3)
|
222
|
+
sage: C(J^3) == C(I)
|
223
|
+
True
|
224
|
+
"""
|
225
|
+
cyclic_orders = C.gens_orders()
|
226
|
+
cyclic_gens = C.gens_ideals()
|
227
|
+
coords = C(I).exponents()
|
228
|
+
|
229
|
+
# In the next line, e=(ci/p)%n should satisfy p*e=ci (mod n): we
|
230
|
+
# are dividing the coordinate vector by p in the appropriate sense
|
231
|
+
|
232
|
+
if not all(p.divides(ci) for ci, n in zip(coords, cyclic_orders) if p.divides(n)):
|
233
|
+
raise ValueError("The ideal class of {} is not a {} power".format(I,p.ordinal_str()))
|
234
|
+
|
235
|
+
w = [ci // p if p.divides(n) else (ci / p) % n for ci, n in zip(coords, cyclic_orders)]
|
236
|
+
|
237
|
+
return prod([gen ** wi for wi, gen in zip(w, cyclic_gens)], C.number_field().ideal(1))
|
238
|
+
|
239
|
+
|
240
|
+
def coords_in_U_mod_p(u, U, p):
|
241
|
+
r"""
|
242
|
+
Return coordinates of a unit ``u`` with respect to a basis of the
|
243
|
+
`p`-cotorsion `U/U^p` of the unit group ``U``.
|
244
|
+
|
245
|
+
INPUT:
|
246
|
+
|
247
|
+
- ``u`` -- (algebraic unit) a unit in a number field ``K``
|
248
|
+
|
249
|
+
- ``U`` -- (unit group) the unit group of ``K``
|
250
|
+
|
251
|
+
- ``p`` -- prime number
|
252
|
+
|
253
|
+
OUTPUT:
|
254
|
+
|
255
|
+
The coordinates of the unit `u` in the `p`-cotorsion group `U/U^p`.
|
256
|
+
|
257
|
+
ALGORITHM:
|
258
|
+
|
259
|
+
Take the coordinate vector of `u` with respect to the generators
|
260
|
+
of the unit group, drop the coordinate of the roots of unity
|
261
|
+
factor if it is prime to `p`, and reduce the vector mod `p`.
|
262
|
+
|
263
|
+
EXAMPLES::
|
264
|
+
|
265
|
+
sage: from sage.rings.number_field.selmer_group import coords_in_U_mod_p
|
266
|
+
sage: x = polygen(ZZ, 'x')
|
267
|
+
sage: K.<a> = NumberField(x^4 - 5*x^2 + 1)
|
268
|
+
sage: U = K.unit_group()
|
269
|
+
sage: U
|
270
|
+
Unit group with structure C2 x Z x Z x Z of Number Field in a with defining polynomial x^4 - 5*x^2 + 1
|
271
|
+
sage: u0, u1, u2, u3 = U.gens_values()
|
272
|
+
sage: u = u1*u2^2*u3^3
|
273
|
+
sage: coords_in_U_mod_p(u,U,2)
|
274
|
+
[0, 1, 0, 1]
|
275
|
+
sage: coords_in_U_mod_p(u,U,3)
|
276
|
+
[1, 2, 0]
|
277
|
+
sage: u*=u0
|
278
|
+
sage: coords_in_U_mod_p(u,U,2)
|
279
|
+
[1, 1, 0, 1]
|
280
|
+
sage: coords_in_U_mod_p(u,U,3)
|
281
|
+
[1, 2, 0]
|
282
|
+
"""
|
283
|
+
coords = U.log(u)
|
284
|
+
start = 1 - int(p.divides(U.zeta_order())) # 0 or 1
|
285
|
+
return [c % p for c in coords[start:]]
|
286
|
+
|
287
|
+
|
288
|
+
def basis_for_p_cokernel(S, C, p):
|
289
|
+
r"""
|
290
|
+
Return a basis for the group of ideals supported on ``S`` (mod
|
291
|
+
`p`-th-powers) whose class in the class group ``C`` is a `p`-th power,
|
292
|
+
together with a function which takes the ``S``-exponents of such an
|
293
|
+
ideal and returns its coordinates on this basis.
|
294
|
+
|
295
|
+
INPUT:
|
296
|
+
|
297
|
+
- ``S`` -- list of prime ideals in a number field ``K``
|
298
|
+
|
299
|
+
- ``C`` -- (class group) the ideal class group of ``K``
|
300
|
+
|
301
|
+
- ``p`` -- prime number
|
302
|
+
|
303
|
+
OUTPUT:
|
304
|
+
|
305
|
+
(tuple) (``b``, ``f``) where
|
306
|
+
|
307
|
+
- ``b`` is a list of ideals which is a basis for the group of
|
308
|
+
ideals supported on ``S`` (modulo `p`-th powers) whose ideal
|
309
|
+
class is a `p`-th power;
|
310
|
+
|
311
|
+
- ``f`` is a function which takes such an ideal and returns its
|
312
|
+
coordinates with respect to this basis.
|
313
|
+
|
314
|
+
EXAMPLES::
|
315
|
+
|
316
|
+
sage: from sage.rings.number_field.selmer_group import basis_for_p_cokernel
|
317
|
+
sage: x = polygen(ZZ, 'x')
|
318
|
+
sage: K.<a> = NumberField(x^2 - x + 58)
|
319
|
+
sage: S = K.ideal(30).support(); S
|
320
|
+
[Fractional ideal (2, a),
|
321
|
+
Fractional ideal (2, a + 1),
|
322
|
+
Fractional ideal (3, a + 1),
|
323
|
+
Fractional ideal (5, a + 1),
|
324
|
+
Fractional ideal (5, a + 3)]
|
325
|
+
sage: C = K.class_group()
|
326
|
+
sage: C.gens_orders()
|
327
|
+
(6, 2)
|
328
|
+
sage: [C(P).exponents() for P in S]
|
329
|
+
[(5, 0), (1, 0), (3, 1), (1, 1), (5, 1)]
|
330
|
+
sage: b, f = basis_for_p_cokernel(S, C, 2); b
|
331
|
+
[Fractional ideal (2), Fractional ideal (15, a + 13), Fractional ideal (5)]
|
332
|
+
sage: b, f = basis_for_p_cokernel(S, C, 3); b
|
333
|
+
[Fractional ideal (50, a + 18),
|
334
|
+
Fractional ideal (10, a + 3),
|
335
|
+
Fractional ideal (3, a + 1),
|
336
|
+
Fractional ideal (5)]
|
337
|
+
sage: b, f = basis_for_p_cokernel(S, C, 5); b
|
338
|
+
[Fractional ideal (2, a),
|
339
|
+
Fractional ideal (2, a + 1),
|
340
|
+
Fractional ideal (3, a + 1),
|
341
|
+
Fractional ideal (5, a + 1),
|
342
|
+
Fractional ideal (5, a + 3)]
|
343
|
+
"""
|
344
|
+
from sage.matrix.constructor import Matrix
|
345
|
+
M = Matrix(GF(p), [_coords_in_C_mod_p(P, C, p) for P in S])
|
346
|
+
k = M.left_kernel()
|
347
|
+
bas = [prod([P ** bj.lift() for P, bj in zip(S, b.list())],
|
348
|
+
C.number_field().ideal(1)) for b in k.basis()]
|
349
|
+
return bas, k.coordinate_vector
|
350
|
+
|
351
|
+
# The main function
|
352
|
+
|
353
|
+
|
354
|
+
def pSelmerGroup(K, S, p, proof=None, debug=False):
|
355
|
+
r"""
|
356
|
+
Return the `p`-Selmer group `K(S,p)` of the number field `K`
|
357
|
+
with respect to the prime ideals in ``S``.
|
358
|
+
|
359
|
+
INPUT:
|
360
|
+
|
361
|
+
- ``K`` -- a number field or `\QQ`
|
362
|
+
|
363
|
+
- ``S`` -- list of prime ideals in `K`, or prime
|
364
|
+
numbers when `K` is `\QQ`
|
365
|
+
|
366
|
+
- ``p`` -- a prime number
|
367
|
+
|
368
|
+
- ``proof`` -- if ``True``, compute the class group provably
|
369
|
+
correctly. Default is ``True``. Call :meth:`proof.number_field` to
|
370
|
+
change this default globally.
|
371
|
+
|
372
|
+
- ``debug`` -- boolean (default: ``False``); debug flag
|
373
|
+
|
374
|
+
OUTPUT:
|
375
|
+
|
376
|
+
(tuple) ``KSp``, ``KSp_gens``, ``from_KSp``, ``to_KSp`` where
|
377
|
+
|
378
|
+
- ``KSp`` is an abstract vector space over `GF(p)` isomorphic to `K(S,p)`;
|
379
|
+
|
380
|
+
- ``KSp_gens`` is a list of elements of `K^*` generating `K(S,p)`;
|
381
|
+
|
382
|
+
- ``from_KSp`` is a function from ``KSp`` to `K^*` implementing
|
383
|
+
the isomorphism from the abstract `K(S,p)` to `K(S,p)` as a
|
384
|
+
subgroup of `K^*/(K^*)^p`;
|
385
|
+
|
386
|
+
- ``to_KSP`` is a partial function from `K^*` to ``KSp``, defined
|
387
|
+
on elements `a` whose image in `K^*/(K^*)^p` lies in `K(S,p)`,
|
388
|
+
mapping them via the inverse isomorphism to the abstract vector
|
389
|
+
space ``KSp``.
|
390
|
+
|
391
|
+
ALGORITHM:
|
392
|
+
|
393
|
+
The list of generators of `K(S,p)` is the concatenation of three
|
394
|
+
sublists, called ``alphalist``, ``betalist`` and ``ulist`` in the
|
395
|
+
code. Only ``alphalist`` depends on the primes in `S`.
|
396
|
+
|
397
|
+
- ``ulist`` is a basis for `U/U^p` where `U` is the unit group.
|
398
|
+
This is the list of fundamental units, including the generator
|
399
|
+
of the group of roots of unity if its order is divisible by `p`.
|
400
|
+
These have valuation `0` at all primes.
|
401
|
+
|
402
|
+
- ``betalist`` is a list of the generators of the `p`-th powers of
|
403
|
+
ideals which generate the `p`-torsion in the class group (so is
|
404
|
+
empty if the class number is prime to `p`). These have
|
405
|
+
valuation divisible by `p` at all primes.
|
406
|
+
|
407
|
+
- ``alphalist`` is a list of generators for each ideal `A` in a
|
408
|
+
basis of those ideals supported on `S` (modulo `p`-th powers of
|
409
|
+
ideals) which are `p`-th powers in the class group. We find `B`
|
410
|
+
such that `A/B^p` is principal and take a generator of it, for
|
411
|
+
each `A` in a generating set. As a special case, if all the
|
412
|
+
ideals in `S` are principal then ``alphalist`` is a list of
|
413
|
+
their generators.
|
414
|
+
|
415
|
+
The map from the abstract space to `K^*` is easy: we just take the
|
416
|
+
product of the generators to powers given by the coefficient
|
417
|
+
vector. No attempt is made to reduce the resulting product modulo
|
418
|
+
`p`-th powers.
|
419
|
+
|
420
|
+
The reverse map is more complicated. Given `a\in K^*`:
|
421
|
+
|
422
|
+
- write the principal ideal `(a)` in the form `AB^p` with `A`
|
423
|
+
supported by `S` and `p`-th power free. If this fails, then `a`
|
424
|
+
does not represent an element of `K(S,p)` and an error is
|
425
|
+
raised.
|
426
|
+
|
427
|
+
- set `I_S` to be the group of ideals spanned by `S` mod `p`-th
|
428
|
+
powers, and `I_{S,p}` the subgroup of `I_S` which maps to `0` in
|
429
|
+
`C/C^p`.
|
430
|
+
|
431
|
+
- Convert `A` to an element of `I_{S,p}`, hence find the
|
432
|
+
coordinates of `a` with respect to the generators in
|
433
|
+
``alphalist``.
|
434
|
+
|
435
|
+
- after dividing out by `A`, now `(a)=B^p` (with a different `a`
|
436
|
+
and `B`). Write the ideal class `[B]`, whose `p`-th power is
|
437
|
+
trivial, in terms of the generators of `C[p]`; then `B=(b)B_1`,
|
438
|
+
where the coefficients of `B_1` with respect to generators of
|
439
|
+
`C[p]` give the coordinates of the result with respect to the
|
440
|
+
generators in ``betalist``.
|
441
|
+
|
442
|
+
- after dividing out by `B`, and by `b^p`, we now have `(a)=(1)`,
|
443
|
+
so `a` is a unit, which can be expressed in terms of the unit
|
444
|
+
generators.
|
445
|
+
|
446
|
+
EXAMPLES:
|
447
|
+
|
448
|
+
Over `\QQ` the unit contribution is trivial unless `p=2` and
|
449
|
+
the class group is trivial::
|
450
|
+
|
451
|
+
sage: from sage.rings.number_field.selmer_group import pSelmerGroup
|
452
|
+
sage: QS2, gens, fromQS2, toQS2 = pSelmerGroup(QQ, [2,3], 2)
|
453
|
+
sage: QS2
|
454
|
+
Vector space of dimension 3 over Finite Field of size 2
|
455
|
+
sage: gens
|
456
|
+
[2, 3, -1]
|
457
|
+
sage: a = fromQS2([1,1,1]); a.factor()
|
458
|
+
-1 * 2 * 3
|
459
|
+
sage: toQS2(-6)
|
460
|
+
(1, 1, 1)
|
461
|
+
|
462
|
+
sage: QS3, gens, fromQS3, toQS3 = pSelmerGroup(QQ, [2,13], 3)
|
463
|
+
sage: QS3
|
464
|
+
Vector space of dimension 2 over Finite Field of size 3
|
465
|
+
sage: gens
|
466
|
+
[2, 13]
|
467
|
+
sage: a = fromQS3([5,4]); a.factor()
|
468
|
+
2^5 * 13^4
|
469
|
+
sage: toQS3(a)
|
470
|
+
(2, 1)
|
471
|
+
sage: toQS3(a) == QS3([5,4])
|
472
|
+
True
|
473
|
+
|
474
|
+
A real quadratic field with class number 2, where the fundamental
|
475
|
+
unit is a generator, and the class group provides another
|
476
|
+
generator when `p=2`::
|
477
|
+
|
478
|
+
sage: K.<a> = QuadraticField(-5)
|
479
|
+
sage: K.class_number()
|
480
|
+
2
|
481
|
+
sage: P2 = K.ideal(2, -a+1)
|
482
|
+
sage: P3 = K.ideal(3, a+1)
|
483
|
+
sage: P5 = K.ideal(a)
|
484
|
+
sage: KS2, gens, fromKS2, toKS2 = pSelmerGroup(K, [P2, P3, P5], 2)
|
485
|
+
sage: KS2
|
486
|
+
Vector space of dimension 4 over Finite Field of size 2
|
487
|
+
sage: gens
|
488
|
+
[a + 1, a, 2, -1]
|
489
|
+
|
490
|
+
Each generator must have even valuation at primes not in `S`::
|
491
|
+
|
492
|
+
sage: [K.ideal(g).factor() for g in gens]
|
493
|
+
[(Fractional ideal (2, a + 1)) * (Fractional ideal (3, a + 1)),
|
494
|
+
Fractional ideal (-a),
|
495
|
+
(Fractional ideal (2, a + 1))^2,
|
496
|
+
1]
|
497
|
+
|
498
|
+
sage: toKS2(10)
|
499
|
+
(0, 0, 1, 1)
|
500
|
+
sage: fromKS2([0,0,1,1])
|
501
|
+
-2
|
502
|
+
sage: K(10/(-2)).is_square()
|
503
|
+
True
|
504
|
+
|
505
|
+
sage: KS3, gens, fromKS3, toKS3 = pSelmerGroup(K, [P2, P3, P5], 3)
|
506
|
+
sage: KS3
|
507
|
+
Vector space of dimension 3 over Finite Field of size 3
|
508
|
+
sage: gens
|
509
|
+
[1/2, 1/4*a + 1/4, a]
|
510
|
+
|
511
|
+
The ``to`` and ``from`` maps are inverses of each other::
|
512
|
+
|
513
|
+
sage: K.<a> = QuadraticField(-5)
|
514
|
+
sage: S = K.ideal(30).support()
|
515
|
+
sage: KS2, gens, fromKS2, toKS2 = pSelmerGroup(K, S, 2)
|
516
|
+
sage: KS2
|
517
|
+
Vector space of dimension 5 over Finite Field of size 2
|
518
|
+
sage: assert all(toKS2(fromKS2(v))==v for v in KS2)
|
519
|
+
sage: KS3, gens, fromKS3, toKS3 = pSelmerGroup(K, S, 3)
|
520
|
+
sage: KS3
|
521
|
+
Vector space of dimension 4 over Finite Field of size 3
|
522
|
+
sage: assert all(toKS3(fromKS3(v))==v for v in KS3)
|
523
|
+
"""
|
524
|
+
from sage.rings.number_field.number_field import proof_flag
|
525
|
+
from sage.modules.free_module import VectorSpace
|
526
|
+
from sage.sets.set import Set
|
527
|
+
|
528
|
+
proof = proof_flag(proof)
|
529
|
+
|
530
|
+
# Input check: p and all P in S must be prime. Remove any repeats in S.
|
531
|
+
|
532
|
+
S = list(Set(S))
|
533
|
+
if not all(P.is_prime() for P in S):
|
534
|
+
raise ValueError("elements of S must all be prime")
|
535
|
+
if not p.is_prime():
|
536
|
+
raise ValueError("p must be prime")
|
537
|
+
|
538
|
+
F = GF(p)
|
539
|
+
|
540
|
+
# Step 1. The unit contribution: all fundamental units, and also the
|
541
|
+
# generating root of unity if its order is a multiple of p; we just
|
542
|
+
# take generators of U/U^p. These have valuation 0 everywhere.
|
543
|
+
|
544
|
+
hK = 1 if K == QQ else K.class_number(proof=proof)
|
545
|
+
C = K.class_group() if K == QQ else K.class_group(proof=proof)
|
546
|
+
|
547
|
+
hKp = (hK % p == 0) # flag whether the class number is divisible by p
|
548
|
+
|
549
|
+
if K == QQ:
|
550
|
+
if p == 2:
|
551
|
+
ulist = [QQ(-1)]
|
552
|
+
else:
|
553
|
+
ulist = []
|
554
|
+
else:
|
555
|
+
U = K.unit_group(proof=proof)
|
556
|
+
ulist = U.gens_values()
|
557
|
+
if U.zeta_order() % p:
|
558
|
+
ulist = ulist[1:]
|
559
|
+
|
560
|
+
if debug:
|
561
|
+
print("{} generators in ulist = {}".format(len(ulist),ulist))
|
562
|
+
|
563
|
+
# Step 2. The class group contribution: generators of the p'th
|
564
|
+
# powers of ideals generating the p-torsion in the class group.
|
565
|
+
# These have valuation divisible by p everywhere.
|
566
|
+
|
567
|
+
if hKp:
|
568
|
+
betalist = [_ideal_generator(c ** n)
|
569
|
+
for c, n in zip(C.gens_ideals(), C.gens_orders())
|
570
|
+
if n % p == 0]
|
571
|
+
else:
|
572
|
+
betalist = []
|
573
|
+
|
574
|
+
if debug:
|
575
|
+
print("{} generators in betalist = {}".format(len(betalist),betalist))
|
576
|
+
|
577
|
+
# Step 3. The part depending on S: one generator for each ideal A
|
578
|
+
# in a basis of those ideals supported on S (modulo p'th powers of
|
579
|
+
# ideals) which is a p'th power in the class group. We find B
|
580
|
+
# such that A/B^p is principal and take a generator of that, for
|
581
|
+
# each A in a generating set.
|
582
|
+
|
583
|
+
# As a special case, when the class number is 1 we just take
|
584
|
+
# generators of the primes in S.
|
585
|
+
|
586
|
+
if hK > 1:
|
587
|
+
T, f = basis_for_p_cokernel(S, C, p)
|
588
|
+
alphalist = [_ideal_generator(I / _root_ideal(I, C, p) ** p) for I in T]
|
589
|
+
else:
|
590
|
+
f = lambda x:x
|
591
|
+
alphalist = [_ideal_generator(P) for P in S]
|
592
|
+
|
593
|
+
if debug:
|
594
|
+
print("{} generators in alphalist = {}".format(len(alphalist), alphalist))
|
595
|
+
|
596
|
+
# Now we have the generators of K(S,p), and define K(S,p) as an
|
597
|
+
# abstract vector space:
|
598
|
+
|
599
|
+
KSp_gens = alphalist + betalist + ulist
|
600
|
+
KSp = VectorSpace(GF(p), len(KSp_gens))
|
601
|
+
|
602
|
+
if debug:
|
603
|
+
print("Generators of K(S,p) = {} (dimension {})".format(KSp_gens, len(KSp_gens)))
|
604
|
+
|
605
|
+
# Now we define maps in each direction between the abstract space and K^*.
|
606
|
+
|
607
|
+
# Define the easy map from KSp into K^*:
|
608
|
+
|
609
|
+
def from_KSp(v):
|
610
|
+
return prod([g ** vi for g, vi in zip(KSp_gens, v)], K(1))
|
611
|
+
|
612
|
+
# Define the hard map from (a subgroup of) K^* to KSp:
|
613
|
+
|
614
|
+
def to_KSp(a):
|
615
|
+
# Check that a is in K(S,p):
|
616
|
+
|
617
|
+
if not a:
|
618
|
+
raise ValueError("argument {} should be nonzero".format(a))
|
619
|
+
try:
|
620
|
+
a = K(a)
|
621
|
+
except ValueError:
|
622
|
+
raise ValueError("argument {} should be in {}".format(a, K))
|
623
|
+
|
624
|
+
if not all(P in S or a.valuation(P) % p == 0 for P in a.support()):
|
625
|
+
raise ValueError("argument {} should have valuations divisible by {} at all primes in {}".format(a, p, S))
|
626
|
+
|
627
|
+
# 1. (a) is a p'th power mod ideals in S, say (a)=AB^p, where
|
628
|
+
# A is supported on S and is a linear combination of the
|
629
|
+
# ideals T above. Find the exponents of the P_i in S in A:
|
630
|
+
|
631
|
+
S_vals = [F(a.valuation(P)) for P in S]
|
632
|
+
avec = list(f(S_vals)) # coordinates of A w.r.t ideals in T (mod p'th powers)
|
633
|
+
a1 = prod((alpha ** e for alpha, e in zip(alphalist,avec)), K(1))
|
634
|
+
a /= a1
|
635
|
+
if debug:
|
636
|
+
print("alpha component is {} with coords {}".format(a1,avec))
|
637
|
+
if K == QQ:
|
638
|
+
print("continuing with quotient {} whose ideal should be a {}'th power: {}".format(a,p,a.factor()))
|
639
|
+
else:
|
640
|
+
print("continuing with quotient {} whose ideal should be a {}'th power: {}".format(a,p,K.ideal(a).factor()))
|
641
|
+
|
642
|
+
# 2. Now (a) is a p'th power, say (a)=B^p.
|
643
|
+
# Find B and the exponents of [B] w.r.t. basis of C[p]:
|
644
|
+
|
645
|
+
supp = a.support()
|
646
|
+
vals = [a.valuation(P) for P in supp]
|
647
|
+
if debug:
|
648
|
+
assert all(v % p == 0 for v in vals)
|
649
|
+
one = K(1) if K == QQ else K.ideal(1)
|
650
|
+
aa = a.abs() if K == QQ else K.ideal(a)
|
651
|
+
B = prod((P ** (v // p) for P, v in zip(supp,vals)), one)
|
652
|
+
if debug:
|
653
|
+
assert B ** p == aa
|
654
|
+
print("B={}".format(B))
|
655
|
+
print("a={}".format(a))
|
656
|
+
|
657
|
+
if hKp:
|
658
|
+
bvec = _coords_in_C_p(B, C, p)
|
659
|
+
a2 = prod((beta ** e for beta, e in zip(betalist, bvec)), K(1))
|
660
|
+
a /= a2
|
661
|
+
supp = a.support()
|
662
|
+
vals = [a.valuation(P) for P in supp]
|
663
|
+
if debug:
|
664
|
+
assert all(v % p == 0 for v in vals)
|
665
|
+
B = prod((P ** (v // p) for P, v in zip(supp, vals)), one)
|
666
|
+
if debug:
|
667
|
+
assert B ** p == aa
|
668
|
+
else:
|
669
|
+
bvec = []
|
670
|
+
a2 = 1
|
671
|
+
|
672
|
+
if debug:
|
673
|
+
print("beta component is {} with coords {}".format(a2,bvec))
|
674
|
+
print("continuing with quotient {} which should be a p'th power times a unit".format(a))
|
675
|
+
|
676
|
+
# 3. Now (a) = (c)^p for some c, so a/c^p is a unit
|
677
|
+
|
678
|
+
if K != QQ:
|
679
|
+
assert B.is_principal()
|
680
|
+
|
681
|
+
if debug:
|
682
|
+
print("B={}".format(B))
|
683
|
+
a3 = B if K == QQ else _ideal_generator(B)
|
684
|
+
if debug:
|
685
|
+
print("a3={}".format(a3))
|
686
|
+
a /= a3 ** p
|
687
|
+
if debug:
|
688
|
+
print("dividing by {}th power of {}".format(p,a3))
|
689
|
+
print("continuing with quotient {} which should be a unit".format(a))
|
690
|
+
|
691
|
+
#4. Now a is a unit
|
692
|
+
|
693
|
+
# NB not a.is_unit which is true for all a in K^*. One could
|
694
|
+
# also test K.ring_of_integers()(a).is_unit().
|
695
|
+
|
696
|
+
if debug:
|
697
|
+
if K == QQ:
|
698
|
+
assert a.abs() == 1
|
699
|
+
else:
|
700
|
+
assert K.ideal(a).is_one()
|
701
|
+
|
702
|
+
if K == QQ:
|
703
|
+
if p == 2:
|
704
|
+
cvec = [1] if a == -1 else [0]
|
705
|
+
else:
|
706
|
+
cvec = []
|
707
|
+
else:
|
708
|
+
cvec = coords_in_U_mod_p(a,U,p)
|
709
|
+
|
710
|
+
if debug:
|
711
|
+
print("gamma component has coords {}".format(cvec))
|
712
|
+
|
713
|
+
return KSp(avec + bvec + cvec)
|
714
|
+
|
715
|
+
return KSp, KSp_gens, from_KSp, to_KSp
|