passagemath-flint 10.6.1rc10__cp310-cp310-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-310-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-310-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-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/chrompoly.pyx +555 -0
- sage/graphs/matchpoly.cpython-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-aarch64-linux-gnu.so +0 -0
- sage/matrix/change_ring.pyx +43 -0
- sage/matrix/matrix_complex_ball_dense.cpython-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-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-310-aarch64-linux-gnu.so +0 -0
- sage/rings/factorint_flint.pyx +99 -0
- sage/rings/fraction_field_FpT.cpython-310-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-310-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-310-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-310-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-310-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-310-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/hilbert.pyx +602 -0
- sage/rings/polynomial/polynomial_complex_arb.cpython-310-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-310-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-310-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_number_field.pyx +345 -0
- sage/rings/polynomial/polynomial_rational_flint.cpython-310-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-310-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-310-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-310-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-310-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-310-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-310-aarch64-linux-gnu.so +0 -0
- sage/rings/real_interval_absolute.pyx +1073 -0
- sage/rings/real_mpfi.cpython-310-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-310-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,2734 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-flint
|
2
|
+
# sage.doctest: needs sage.rings.number_field
|
3
|
+
r"""
|
4
|
+
Relative number fields
|
5
|
+
|
6
|
+
This example constructs a quadratic extension of a quartic number field::
|
7
|
+
|
8
|
+
sage: x = polygen(ZZ, 'x')
|
9
|
+
sage: K.<y> = NumberField(x^4 - 420*x^2 + 40000)
|
10
|
+
sage: z = y^5/11; z
|
11
|
+
420/11*y^3 - 40000/11*y
|
12
|
+
sage: R.<y> = PolynomialRing(K)
|
13
|
+
sage: f = y^2 + y + 1
|
14
|
+
sage: L.<a> = K.extension(f); L
|
15
|
+
Number Field in a with defining polynomial y^2 + y + 1 over its base field
|
16
|
+
sage: KL.<b> = NumberField([x^4 - 420*x^2 + 40000, x^2 + x + 1]); KL
|
17
|
+
Number Field in b0 with defining polynomial x^4 - 420*x^2 + 40000 over its base field
|
18
|
+
|
19
|
+
We do some arithmetic in a tower of relative number fields::
|
20
|
+
|
21
|
+
sage: K.<cuberoot2> = NumberField(x^3 - 2)
|
22
|
+
sage: L.<cuberoot3> = K.extension(x^3 - 3)
|
23
|
+
sage: S.<sqrt2> = L.extension(x^2 - 2)
|
24
|
+
sage: S
|
25
|
+
Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
|
26
|
+
sage: sqrt2 * cuberoot3
|
27
|
+
cuberoot3*sqrt2
|
28
|
+
sage: (sqrt2 + cuberoot3)^5
|
29
|
+
(20*cuberoot3^2 + 15*cuberoot3 + 4)*sqrt2 + 3*cuberoot3^2 + 20*cuberoot3 + 60
|
30
|
+
sage: cuberoot2 + cuberoot3
|
31
|
+
cuberoot3 + cuberoot2
|
32
|
+
sage: cuberoot2 + cuberoot3 + sqrt2
|
33
|
+
sqrt2 + cuberoot3 + cuberoot2
|
34
|
+
sage: (cuberoot2 + cuberoot3 + sqrt2)^2
|
35
|
+
(2*cuberoot3 + 2*cuberoot2)*sqrt2 + cuberoot3^2 + 2*cuberoot2*cuberoot3 + cuberoot2^2 + 2
|
36
|
+
sage: cuberoot2 + sqrt2
|
37
|
+
sqrt2 + cuberoot2
|
38
|
+
sage: a = S(cuberoot2); a
|
39
|
+
cuberoot2
|
40
|
+
sage: a.parent()
|
41
|
+
Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
|
42
|
+
|
43
|
+
.. WARNING::
|
44
|
+
|
45
|
+
Doing arithmetic in towers of relative fields that depends on canonical
|
46
|
+
coercions is currently VERY SLOW. It is much better to explicitly coerce
|
47
|
+
all elements into a common field, then do arithmetic with them there (which
|
48
|
+
is quite fast).
|
49
|
+
|
50
|
+
TESTS::
|
51
|
+
|
52
|
+
sage: y = polygen(QQ,'y'); K.<beta> = NumberField([y^3 - 3, y^2 - 2])
|
53
|
+
sage: K(y^10)
|
54
|
+
27*beta0
|
55
|
+
sage: beta^10
|
56
|
+
27*beta0
|
57
|
+
|
58
|
+
AUTHORS:
|
59
|
+
|
60
|
+
- William Stein (2004, 2005): initial version
|
61
|
+
- Steven Sivek (2006-05-12): added support for relative extensions
|
62
|
+
- William Stein (2007-09-04): major rewrite and documentation
|
63
|
+
- Robert Bradshaw (2008-10): specified embeddings into ambient fields
|
64
|
+
- Nick Alexander (2009-01): modernized coercion implementation
|
65
|
+
- Robert Harron (2012-08): added is_CM_extension
|
66
|
+
- Julian Rüth (2014-04): absolute number fields are unique parents
|
67
|
+
"""
|
68
|
+
# ****************************************************************************
|
69
|
+
# Copyright (C) 2004-2009 William Stein <wstein@gmail.com>
|
70
|
+
# 2014-2022 Julian Rüth <julian.rueth@fsfe.org>
|
71
|
+
#
|
72
|
+
# This program is free software: you can redistribute it and/or modify
|
73
|
+
# it under the terms of the GNU General Public License as published by
|
74
|
+
# the Free Software Foundation, either version 2 of the License, or
|
75
|
+
# (at your option) any later version.
|
76
|
+
# https://www.gnu.org/licenses/
|
77
|
+
# ****************************************************************************
|
78
|
+
|
79
|
+
from sage.categories.map import Map
|
80
|
+
from sage.structure.sequence import Sequence
|
81
|
+
|
82
|
+
import sage.rings.abc
|
83
|
+
import sage.structure.parent_gens
|
84
|
+
|
85
|
+
from . import maps
|
86
|
+
from . import structure
|
87
|
+
|
88
|
+
from sage.misc.latex import latex
|
89
|
+
from sage.misc.cachefunc import cached_method
|
90
|
+
from sage.structure.factorization import Factorization
|
91
|
+
import sage.rings.polynomial.polynomial_element as polynomial_element
|
92
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
93
|
+
|
94
|
+
from . import number_field_element
|
95
|
+
import sage.rings.number_field.number_field_ideal_rel
|
96
|
+
from .number_field_ideal import NumberFieldIdeal
|
97
|
+
from .number_field import (NumberField, NumberField_generic,
|
98
|
+
put_natural_embedding_first, proof_flag,
|
99
|
+
is_NumberFieldHomsetCodomain)
|
100
|
+
from sage.rings.number_field.number_field_base import NumberField as NumberField_base
|
101
|
+
from sage.rings.number_field.order import (RelativeOrder,
|
102
|
+
relative_order_from_ring_generators)
|
103
|
+
from sage.rings.number_field.morphism import RelativeNumberFieldHomomorphism_from_abs
|
104
|
+
from cypari2.gen import Gen as pari_gen
|
105
|
+
|
106
|
+
from sage.categories.homset import Hom
|
107
|
+
from sage.categories.sets_cat import Sets
|
108
|
+
from sage.modules.free_module import VectorSpace
|
109
|
+
from sage.modules.free_module_element import vector
|
110
|
+
|
111
|
+
from sage.rings.real_mpfr import RR
|
112
|
+
from sage.rings.rational_field import QQ
|
113
|
+
from sage.rings.integer_ring import ZZ
|
114
|
+
|
115
|
+
|
116
|
+
def is_RelativeNumberField(x):
|
117
|
+
r"""
|
118
|
+
Return ``True`` if `x` is a relative number field.
|
119
|
+
|
120
|
+
EXAMPLES::
|
121
|
+
|
122
|
+
sage: from sage.rings.number_field.number_field_rel import is_RelativeNumberField
|
123
|
+
sage: x = polygen(ZZ, 'x')
|
124
|
+
sage: is_RelativeNumberField(NumberField(x^2+1,'a'))
|
125
|
+
doctest:warning...
|
126
|
+
DeprecationWarning: The function is_RelativeNumberField is deprecated;
|
127
|
+
use 'isinstance(..., NumberField_relative)' instead.
|
128
|
+
See https://github.com/sagemath/sage/issues/38124 for details.
|
129
|
+
False
|
130
|
+
sage: k.<a> = NumberField(x^3 - 2)
|
131
|
+
sage: l.<b> = k.extension(x^3 - 3); l
|
132
|
+
Number Field in b with defining polynomial x^3 - 3 over its base field
|
133
|
+
sage: is_RelativeNumberField(l)
|
134
|
+
True
|
135
|
+
sage: is_RelativeNumberField(QQ)
|
136
|
+
False
|
137
|
+
"""
|
138
|
+
from sage.misc.superseded import deprecation
|
139
|
+
deprecation(38124,
|
140
|
+
"The function is_RelativeNumberField is deprecated; "
|
141
|
+
"use 'isinstance(..., NumberField_relative)' instead.")
|
142
|
+
return isinstance(x, NumberField_relative)
|
143
|
+
|
144
|
+
|
145
|
+
class NumberField_relative(NumberField_generic):
|
146
|
+
"""
|
147
|
+
INPUT:
|
148
|
+
|
149
|
+
- ``base`` -- the base field
|
150
|
+
|
151
|
+
- ``polynomial`` -- a polynomial which must be defined in the ring `K[x]`,
|
152
|
+
where `K` is the base field
|
153
|
+
|
154
|
+
- ``name`` -- string; the variable name
|
155
|
+
|
156
|
+
- ``latex_name`` -- string or ``None`` (default: ``None``); variable name
|
157
|
+
for latex printing
|
158
|
+
|
159
|
+
- ``check`` -- boolean (default: ``True``); whether to check
|
160
|
+
irreducibility of ``polynomial``
|
161
|
+
|
162
|
+
- ``embedding`` -- currently not supported, must be ``None``
|
163
|
+
|
164
|
+
- ``structure`` -- an instance of :class:`structure.NumberFieldStructure`
|
165
|
+
or ``None`` (default: ``None``), provides additional information about
|
166
|
+
this number field, e.g., the absolute number field from which it was
|
167
|
+
created
|
168
|
+
|
169
|
+
EXAMPLES::
|
170
|
+
|
171
|
+
sage: x = polygen(ZZ, 'x')
|
172
|
+
sage: K.<a> = NumberField(x^3 - 2)
|
173
|
+
sage: t = polygen(K)
|
174
|
+
sage: L.<b> = K.extension(t^2 + t + a); L
|
175
|
+
Number Field in b with defining polynomial x^2 + x + a over its base field
|
176
|
+
|
177
|
+
TESTS::
|
178
|
+
|
179
|
+
sage: Z = polygen(ZZ, 'Z')
|
180
|
+
sage: K.<w> = NumberField(Z^3 + Z + 1)
|
181
|
+
sage: L.<z> = K.extension(Z^3 + 2)
|
182
|
+
sage: K = loads(dumps(L))
|
183
|
+
sage: K
|
184
|
+
Number Field in z with defining polynomial Z^3 + 2 over its base field
|
185
|
+
sage: L is K
|
186
|
+
True
|
187
|
+
|
188
|
+
sage: M.<u,v> = L.change_names()
|
189
|
+
sage: M.structure()
|
190
|
+
(Isomorphism given by variable name change map:
|
191
|
+
From: Number Field in u with defining polynomial x^3 + 2 over its base field
|
192
|
+
To: Number Field in z with defining polynomial Z^3 + 2 over its base field,
|
193
|
+
Isomorphism given by variable name change map:
|
194
|
+
From: Number Field in z with defining polynomial Z^3 + 2 over its base field
|
195
|
+
To: Number Field in u with defining polynomial x^3 + 2 over its base field)
|
196
|
+
sage: loads(dumps(M)) is M
|
197
|
+
True
|
198
|
+
"""
|
199
|
+
def __init__(self, base, polynomial, name,
|
200
|
+
latex_name=None, names=None, check=True, embedding=None, structure=None):
|
201
|
+
r"""
|
202
|
+
Initialization.
|
203
|
+
|
204
|
+
EXAMPLES::
|
205
|
+
|
206
|
+
sage: K.<x> = CyclotomicField(5)[]
|
207
|
+
sage: W.<a> = NumberField(x^2 + 1)
|
208
|
+
sage: W
|
209
|
+
Number Field in a with defining polynomial x^2 + 1 over its base field
|
210
|
+
sage: type(W)
|
211
|
+
<class 'sage.rings.number_field.number_field_rel.NumberField_relative_with_category'>
|
212
|
+
|
213
|
+
Test that check=False really skips the test::
|
214
|
+
|
215
|
+
sage: W.<a> = NumberField(K.cyclotomic_polynomial(5), check=False)
|
216
|
+
sage: W
|
217
|
+
Number Field in a with defining polynomial x^4 + x^3 + x^2 + x + 1 over its base field
|
218
|
+
|
219
|
+
A relative extension of a relative extension::
|
220
|
+
|
221
|
+
sage: x = polygen(ZZ)
|
222
|
+
sage: k.<a0,a1> = NumberField([x^2 + 2, x^2 + 1])
|
223
|
+
sage: l.<b> = k.extension(x^2 + 3)
|
224
|
+
sage: l
|
225
|
+
Number Field in b with defining polynomial x^2 + 3 over its base field
|
226
|
+
sage: l.base_field()
|
227
|
+
Number Field in a0 with defining polynomial x^2 + 2 over its base field
|
228
|
+
sage: l.base_field().base_field()
|
229
|
+
Number Field in a1 with defining polynomial x^2 + 1
|
230
|
+
|
231
|
+
Non-monic and non-integral polynomials are supported (:issue:`252`)::
|
232
|
+
|
233
|
+
sage: l.<b> = k.extension(5*x^2 + 3); l
|
234
|
+
Number Field in b with defining polynomial 5*x^2 + 3 over its base field
|
235
|
+
sage: l.pari_rnf()
|
236
|
+
[x^2 + (5/4*y^3 - 1/4*y^2 + 27/4*y - 3/4)*x + (-9/4*y^3 - 1/4*y^2 - 47/4*y - 7/4), ..., y^4 + 6*y^2 + 1, x^2 + (5/4*y^3 - 1/4*y^2 + 27/4*y - 3/4)*x + (-9/4*y^3 - 1/4*y^2 - 47/4*y - 7/4)], [0, 0]]
|
237
|
+
sage: b
|
238
|
+
b
|
239
|
+
|
240
|
+
sage: l.<b> = k.extension(x^2 + 3/5); l
|
241
|
+
Number Field in b with defining polynomial x^2 + 3/5 over its base field
|
242
|
+
sage: l.pari_rnf()
|
243
|
+
[x^2 + (5/4*y^3 - 1/4*y^2 + 27/4*y - 3/4)*x + (-9/4*y^3 - 1/4*y^2 - 47/4*y - 7/4), ..., y^4 + 6*y^2 + 1, x^2 + (5/4*y^3 - 1/4*y^2 + 27/4*y - 3/4)*x + (-9/4*y^3 - 1/4*y^2 - 47/4*y - 7/4)], [0, 0]]
|
244
|
+
sage: b
|
245
|
+
b
|
246
|
+
|
247
|
+
sage: l.<b> = k.extension(x - 1/a0); l
|
248
|
+
Number Field in b with defining polynomial x + 1/2*a0 over its base field
|
249
|
+
sage: l.pari_rnf()
|
250
|
+
[x, [4, -x^3 + x^2 - 7*x + 3, -2*x^3 - 10*x, x^3 + x^2 + 7*x + 3], ..., [x^4 + 6*x^2 + 1, -x, -1, y^4 + 6*y^2 + 1, x], [0, 0]]
|
251
|
+
sage: b
|
252
|
+
-1/2*a0
|
253
|
+
|
254
|
+
TESTS:
|
255
|
+
|
256
|
+
Test that irreducibility testing is working::
|
257
|
+
|
258
|
+
sage: x = polygen(ZZ)
|
259
|
+
sage: K.<a, b> = NumberField([x^2 + 2, x^2 + 3])
|
260
|
+
sage: K.<a> = NumberField(x^2 + 2)
|
261
|
+
sage: x = polygen(K)
|
262
|
+
sage: L.<b> = K.extension(x^3 + 3*a)
|
263
|
+
|
264
|
+
sage: (x^3 + 2*a).factor()
|
265
|
+
(x - a) * (x^2 + a*x - 2)
|
266
|
+
sage: L.<b> = K.extension(x^3 + 2*a)
|
267
|
+
Traceback (most recent call last):
|
268
|
+
...
|
269
|
+
ValueError: defining polynomial (x^3 + 2*a) must be irreducible
|
270
|
+
sage: (x^2 + 2).factor()
|
271
|
+
(x - a) * (x + a)
|
272
|
+
sage: L.<b> = K.extension(x^2 + 2)
|
273
|
+
Traceback (most recent call last):
|
274
|
+
...
|
275
|
+
ValueError: defining polynomial (x^2 + 2) must be irreducible
|
276
|
+
sage: L.<b> = K.extension(x^2 + 2)
|
277
|
+
Traceback (most recent call last):
|
278
|
+
...
|
279
|
+
ValueError: defining polynomial (x^2 + 2) must be irreducible
|
280
|
+
|
281
|
+
Error checks::
|
282
|
+
|
283
|
+
sage: x = polygen(ZZ)
|
284
|
+
sage: K.<a> = NumberField(x^2 + 1)
|
285
|
+
sage: K.extension(x^2 + 2, 'a')
|
286
|
+
Traceback (most recent call last):
|
287
|
+
...
|
288
|
+
ValueError: base field and extension cannot have the same name 'a'
|
289
|
+
"""
|
290
|
+
if embedding is not None:
|
291
|
+
raise NotImplementedError("Embeddings not implemented for relative number fields")
|
292
|
+
if names is not None:
|
293
|
+
name = names
|
294
|
+
if not isinstance(base, NumberField_base):
|
295
|
+
raise TypeError("base (=%s) must be a number field" % base)
|
296
|
+
if not isinstance(polynomial, polynomial_element.Polynomial):
|
297
|
+
try:
|
298
|
+
polynomial = polynomial.polynomial(base)
|
299
|
+
except (AttributeError, TypeError):
|
300
|
+
raise TypeError("polynomial (=%r) must be a polynomial" % polynomial)
|
301
|
+
if name == base.variable_name():
|
302
|
+
raise ValueError("base field and extension cannot have the same name %r" % name)
|
303
|
+
if polynomial.parent().base_ring() != base:
|
304
|
+
polynomial = polynomial.change_ring(base)
|
305
|
+
# raise ValueError("The polynomial must be defined over the base field")
|
306
|
+
|
307
|
+
# Generate the nf and bnf corresponding to the base field
|
308
|
+
# defined as polynomials in y, e.g. for rnfisfree
|
309
|
+
|
310
|
+
# Convert the polynomial defining the base field into a
|
311
|
+
# polynomial in y to satisfy PARI's ordering requirements.
|
312
|
+
|
313
|
+
if base.is_relative():
|
314
|
+
abs_base = base.absolute_field(name + '0')
|
315
|
+
from_abs_base, to_abs_base = abs_base.structure()
|
316
|
+
else:
|
317
|
+
abs_base = base
|
318
|
+
from_abs_base = maps.IdentityMap(base)
|
319
|
+
to_abs_base = maps.IdentityMap(base)
|
320
|
+
|
321
|
+
self.__absolute_base_field = abs_base, from_abs_base, to_abs_base
|
322
|
+
self.__base_field = base
|
323
|
+
self.__relative_polynomial = polynomial
|
324
|
+
self._element_class = number_field_element.NumberFieldElement_relative
|
325
|
+
|
326
|
+
if check and not self.pari_relative_polynomial().polisirreducible():
|
327
|
+
raise ValueError("defining polynomial (%s) must be irreducible" % polynomial)
|
328
|
+
|
329
|
+
names = (name,) + base.variable_names()
|
330
|
+
self._assign_names(tuple(names), normalize=False)
|
331
|
+
|
332
|
+
NumberField_generic.__init__(self, self.absolute_polynomial(), name=None,
|
333
|
+
latex_name=latex_name, check=False,
|
334
|
+
embedding=embedding, structure=structure)
|
335
|
+
|
336
|
+
self._zero_element = self(0)
|
337
|
+
self._one_element = self(1)
|
338
|
+
|
339
|
+
def change_names(self, names):
|
340
|
+
r"""
|
341
|
+
Return relative number field isomorphic to ``self`` but with the
|
342
|
+
given generator names.
|
343
|
+
|
344
|
+
INPUT:
|
345
|
+
|
346
|
+
- ``names`` -- number of names should be at most the number of
|
347
|
+
generators of ``self``, i.e., the number of steps in the tower
|
348
|
+
of relative fields.
|
349
|
+
|
350
|
+
Also, ``K.structure()`` returns ``from_K`` and ``to_K``, where
|
351
|
+
``from_K`` is an isomorphism from `K` to ``self`` and ``to_K`` is an
|
352
|
+
isomorphism from ``self`` to `K`.
|
353
|
+
|
354
|
+
EXAMPLES::
|
355
|
+
|
356
|
+
sage: x = polygen(ZZ, 'x')
|
357
|
+
sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
|
358
|
+
Number Field in a with defining polynomial x^4 + 3 over its base field
|
359
|
+
sage: L.<c,d> = K.change_names()
|
360
|
+
sage: L
|
361
|
+
Number Field in c with defining polynomial x^4 + 3 over its base field
|
362
|
+
sage: L.base_field()
|
363
|
+
Number Field in d with defining polynomial x^2 + 2
|
364
|
+
|
365
|
+
An example with a 3-level tower::
|
366
|
+
|
367
|
+
sage: K.<a,b,c> = NumberField([x^2 + 17, x^2 + x + 1, x^3 - 2]); K
|
368
|
+
Number Field in a with defining polynomial x^2 + 17 over its base field
|
369
|
+
sage: L.<m,n,r> = K.change_names()
|
370
|
+
sage: L
|
371
|
+
Number Field in m with defining polynomial x^2 + 17 over its base field
|
372
|
+
sage: L.base_field()
|
373
|
+
Number Field in n with defining polynomial x^2 + x + 1 over its base field
|
374
|
+
sage: L.base_field().base_field()
|
375
|
+
Number Field in r with defining polynomial x^3 - 2
|
376
|
+
|
377
|
+
And a more complicated example::
|
378
|
+
|
379
|
+
sage: PQ.<X> = QQ[]
|
380
|
+
sage: F.<a, b> = NumberField([X^2 - 2, X^2 - 3])
|
381
|
+
sage: PF.<Y> = F[]
|
382
|
+
sage: K.<c> = F.extension(Y^2 - (1 + a)*(a + b)*a*b)
|
383
|
+
sage: L.<m, n, r> = K.change_names(); L
|
384
|
+
Number Field in m with defining polynomial
|
385
|
+
x^2 + (-2*r - 3)*n - 2*r - 6 over its base field
|
386
|
+
sage: L.structure()
|
387
|
+
(Isomorphism given by variable name change map:
|
388
|
+
From: Number Field in m with defining polynomial
|
389
|
+
x^2 + (-2*r - 3)*n - 2*r - 6 over its base field
|
390
|
+
To: Number Field in c with defining polynomial
|
391
|
+
Y^2 + (-2*b - 3)*a - 2*b - 6 over its base field,
|
392
|
+
Isomorphism given by variable name change map:
|
393
|
+
From: Number Field in c with defining polynomial
|
394
|
+
Y^2 + (-2*b - 3)*a - 2*b - 6 over its base field
|
395
|
+
To: Number Field in m with defining polynomial
|
396
|
+
x^2 + (-2*r - 3)*n - 2*r - 6 over its base field)
|
397
|
+
"""
|
398
|
+
if len(names) == 0:
|
399
|
+
names = self.variable_names()
|
400
|
+
elif isinstance(names, str):
|
401
|
+
names = names.split(',')
|
402
|
+
K = self.base_field().change_names(tuple(names[1:]))
|
403
|
+
to_K = K.structure()[1]
|
404
|
+
old_poly = self.relative_polynomial()
|
405
|
+
new_poly = PolynomialRing(K, 'x')([to_K(c) for c in old_poly])
|
406
|
+
return K.extension(new_poly, names=names[0], structure=structure.NameChange(self))
|
407
|
+
|
408
|
+
def subfields(self, degree=0, name=None):
|
409
|
+
"""
|
410
|
+
Return all subfields of this relative number field ``self`` of the given degree,
|
411
|
+
or of all possible degrees if degree is 0. The subfields are returned as
|
412
|
+
absolute fields together with an embedding into ``self``. For the case of the
|
413
|
+
field itself, the reverse isomorphism is also provided.
|
414
|
+
|
415
|
+
EXAMPLES::
|
416
|
+
|
417
|
+
sage: PQ.<X> = QQ[]
|
418
|
+
sage: F.<a, b> = NumberField([X^2 - 2, X^2 - 3])
|
419
|
+
sage: PF.<Y> = F[]
|
420
|
+
sage: K.<c> = F.extension(Y^2 - (1 + a)*(a + b)*a*b)
|
421
|
+
sage: K.subfields(2)
|
422
|
+
[(Number Field in c0 with defining polynomial x^2 - 24*x + 96,
|
423
|
+
Ring morphism:
|
424
|
+
From: Number Field in c0 with defining polynomial x^2 - 24*x + 96
|
425
|
+
To: Number Field in c with defining polynomial Y^2 + (-2*b - 3)*a - 2*b - 6 over its base field
|
426
|
+
Defn: c0 |--> -4*b + 12,
|
427
|
+
None),
|
428
|
+
(Number Field in c1 with defining polynomial x^2 - 24*x + 120,
|
429
|
+
Ring morphism:
|
430
|
+
From: Number Field in c1 with defining polynomial x^2 - 24*x + 120
|
431
|
+
To: Number Field in c with defining polynomial Y^2 + (-2*b - 3)*a - 2*b - 6 over its base field
|
432
|
+
Defn: c1 |--> 2*b*a + 12,
|
433
|
+
None),
|
434
|
+
(Number Field in c2 with defining polynomial x^2 - 24*x + 72,
|
435
|
+
Ring morphism:
|
436
|
+
From: Number Field in c2 with defining polynomial x^2 - 24*x + 72
|
437
|
+
To: Number Field in c with defining polynomial Y^2 + (-2*b - 3)*a - 2*b - 6 over its base field
|
438
|
+
Defn: c2 |--> -6*a + 12,
|
439
|
+
None)]
|
440
|
+
sage: K.subfields(8, 'w')
|
441
|
+
[(Number Field in w0 with defining polynomial x^8 - 12*x^6 + 36*x^4 - 36*x^2 + 9,
|
442
|
+
Ring morphism:
|
443
|
+
From: Number Field in w0 with defining polynomial x^8 - 12*x^6 + 36*x^4 - 36*x^2 + 9
|
444
|
+
To: Number Field in c with defining polynomial Y^2 + (-2*b - 3)*a - 2*b - 6 over its base field
|
445
|
+
Defn: w0 |--> (-1/2*b*a + 1/2*b + 1/2)*c,
|
446
|
+
Relative number field morphism:
|
447
|
+
From: Number Field in c with defining polynomial Y^2 + (-2*b - 3)*a - 2*b - 6 over its base field
|
448
|
+
To: Number Field in w0 with defining polynomial x^8 - 12*x^6 + 36*x^4 - 36*x^2 + 9
|
449
|
+
Defn: c |--> -1/3*w0^7 + 4*w0^5 - 12*w0^3 + 11*w0
|
450
|
+
a |--> 1/3*w0^6 - 10/3*w0^4 + 5*w0^2
|
451
|
+
b |--> -2/3*w0^6 + 7*w0^4 - 14*w0^2 + 6)]
|
452
|
+
sage: K.subfields(3)
|
453
|
+
[]
|
454
|
+
"""
|
455
|
+
if name is None:
|
456
|
+
name = self.variable_name()
|
457
|
+
abs = self.absolute_field(name)
|
458
|
+
from_abs, to_abs = abs.structure()
|
459
|
+
abs_subfields = abs.subfields(degree=degree)
|
460
|
+
ans = []
|
461
|
+
for K, from_K, to_K in abs_subfields:
|
462
|
+
from_K = K.hom([from_abs(from_K(K.gen()))])
|
463
|
+
if to_K is not None:
|
464
|
+
to_K = RelativeNumberFieldHomomorphism_from_abs(self.Hom(K), to_K*to_abs)
|
465
|
+
ans.append((K, from_K, to_K))
|
466
|
+
ans = Sequence(ans, immutable=True, cr=bool(ans))
|
467
|
+
return ans
|
468
|
+
|
469
|
+
def is_absolute(self):
|
470
|
+
r"""
|
471
|
+
Return ``False``, since this is not an absolute field.
|
472
|
+
|
473
|
+
EXAMPLES::
|
474
|
+
|
475
|
+
sage: x = polygen(ZZ, 'x')
|
476
|
+
sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
|
477
|
+
Number Field in a with defining polynomial x^4 + 3 over its base field
|
478
|
+
sage: K.is_absolute()
|
479
|
+
False
|
480
|
+
sage: K.is_relative()
|
481
|
+
True
|
482
|
+
"""
|
483
|
+
return False
|
484
|
+
|
485
|
+
def gens(self) -> tuple:
|
486
|
+
"""
|
487
|
+
Return the generators of this relative number field.
|
488
|
+
|
489
|
+
EXAMPLES::
|
490
|
+
|
491
|
+
sage: x = polygen(ZZ, 'x')
|
492
|
+
sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
|
493
|
+
Number Field in a with defining polynomial x^4 + 3 over its base field
|
494
|
+
sage: K.gens()
|
495
|
+
(a, b)
|
496
|
+
|
497
|
+
TESTS:
|
498
|
+
|
499
|
+
Trivial extensions work like non-trivial ones (:issue:`2220`)::
|
500
|
+
|
501
|
+
sage: NumberField([x^2 - 3, x], 'a').gens()
|
502
|
+
(a0, 0)
|
503
|
+
sage: NumberField([x, x^2 - 3], 'a').gens()
|
504
|
+
(0, a1)
|
505
|
+
"""
|
506
|
+
return ((self._gen_relative(),) +
|
507
|
+
tuple(map(self, self.base_field().gens())))
|
508
|
+
|
509
|
+
def _first_ngens(self, n):
|
510
|
+
"""
|
511
|
+
Return the first `n` generators of this relative number field.
|
512
|
+
|
513
|
+
If `n` is greater than the number of generators, the output is
|
514
|
+
the same as that of :meth:`gens`.
|
515
|
+
|
516
|
+
EXAMPLES::
|
517
|
+
|
518
|
+
sage: x = polygen(ZZ, 'x')
|
519
|
+
sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
|
520
|
+
Number Field in a with defining polynomial x^4 + 3 over its base field
|
521
|
+
sage: K._first_ngens(0)
|
522
|
+
()
|
523
|
+
sage: K._first_ngens(1)
|
524
|
+
(a,)
|
525
|
+
sage: K._first_ngens(2)
|
526
|
+
(a, b)
|
527
|
+
sage: K._first_ngens(3)
|
528
|
+
(a, b)
|
529
|
+
"""
|
530
|
+
if n <= 0:
|
531
|
+
return ()
|
532
|
+
v = (self._gen_relative(),)
|
533
|
+
if n > 1:
|
534
|
+
v += tuple(map(self, self.base_field()._first_ngens(n - 1)))
|
535
|
+
return v
|
536
|
+
|
537
|
+
def ngens(self):
|
538
|
+
"""
|
539
|
+
Return the number of generators of this relative number field.
|
540
|
+
|
541
|
+
EXAMPLES::
|
542
|
+
|
543
|
+
sage: x = polygen(ZZ, 'x')
|
544
|
+
sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
|
545
|
+
Number Field in a with defining polynomial x^4 + 3 over its base field
|
546
|
+
sage: K.gens()
|
547
|
+
(a, b)
|
548
|
+
sage: K.ngens()
|
549
|
+
2
|
550
|
+
"""
|
551
|
+
return self.base_field().ngens() + 1
|
552
|
+
|
553
|
+
def gen(self, n=0):
|
554
|
+
"""
|
555
|
+
Return the `n`-th generator of this relative number field.
|
556
|
+
|
557
|
+
EXAMPLES::
|
558
|
+
|
559
|
+
sage: x = polygen(ZZ, 'x')
|
560
|
+
sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
|
561
|
+
Number Field in a with defining polynomial x^4 + 3 over its base field
|
562
|
+
sage: K.gens()
|
563
|
+
(a, b)
|
564
|
+
sage: K.gen(0)
|
565
|
+
a
|
566
|
+
"""
|
567
|
+
if n == 0:
|
568
|
+
return self._gen_relative()
|
569
|
+
return self(self.base_field().gen(n - 1))
|
570
|
+
|
571
|
+
def galois_closure(self, names=None):
|
572
|
+
r"""
|
573
|
+
Return the absolute number field `K` that is the Galois closure of this
|
574
|
+
relative number field.
|
575
|
+
|
576
|
+
EXAMPLES::
|
577
|
+
|
578
|
+
sage: x = polygen(ZZ, 'x')
|
579
|
+
sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
|
580
|
+
Number Field in a with defining polynomial x^4 + 3 over its base field
|
581
|
+
sage: K.galois_closure('c') # needs sage.groups
|
582
|
+
Number Field in c with defining polynomial x^16 + 16*x^14 + 28*x^12
|
583
|
+
+ 784*x^10 + 19846*x^8 - 595280*x^6 + 2744476*x^4 + 3212848*x^2 + 29953729
|
584
|
+
"""
|
585
|
+
return self.absolute_field('a').galois_closure(names=names)
|
586
|
+
|
587
|
+
def composite_fields(self, other, names=None, both_maps=False, preserve_embedding=True):
|
588
|
+
"""
|
589
|
+
List of all possible composite number fields formed from ``self`` and
|
590
|
+
``other``, together with (optionally) embeddings into the compositum;
|
591
|
+
see the documentation for ``both_maps`` below.
|
592
|
+
|
593
|
+
Since relative fields do not have ambient embeddings,
|
594
|
+
``preserve_embedding`` has no effect. In every case all possible
|
595
|
+
composite number fields are returned.
|
596
|
+
|
597
|
+
INPUT:
|
598
|
+
|
599
|
+
- ``other`` -- a number field
|
600
|
+
|
601
|
+
- ``names`` -- generator name for composite fields
|
602
|
+
|
603
|
+
- ``both_maps`` -- boolean (default: ``False``); if ``True``, return
|
604
|
+
quadruples (`F`, ``self_into_F, ``other_into_F``, `k`) such that
|
605
|
+
``self_into_F`` maps ``self`` into `F`, ``other_into_F`` maps
|
606
|
+
``other`` into `F`. For relative number fields, `k` is always
|
607
|
+
``None``.
|
608
|
+
|
609
|
+
- ``preserve_embedding`` -- boolean (default: ``True``); has no effect,
|
610
|
+
but is kept for compatibility with the absolute version of this,
|
611
|
+
method. In every case the list of all possible compositums is returned.
|
612
|
+
|
613
|
+
OUTPUT: list of the composite fields, possibly with maps
|
614
|
+
|
615
|
+
EXAMPLES::
|
616
|
+
|
617
|
+
sage: x = polygen(ZZ, 'x')
|
618
|
+
sage: K.<a, b> = NumberField([x^2 + 5, x^2 - 2])
|
619
|
+
sage: L.<c, d> = NumberField([x^2 + 5, x^2 - 3])
|
620
|
+
sage: K.composite_fields(L, 'e')
|
621
|
+
[Number Field in e with defining polynomial
|
622
|
+
x^8 - 24*x^6 + 464*x^4 + 3840*x^2 + 25600]
|
623
|
+
sage: K.composite_fields(L, 'e', both_maps=True)
|
624
|
+
[[Number Field in e with defining polynomial
|
625
|
+
x^8 - 24*x^6 + 464*x^4 + 3840*x^2 + 25600,
|
626
|
+
Relative number field morphism:
|
627
|
+
From: Number Field in a with defining polynomial x^2 + 5 over its base field
|
628
|
+
To: Number Field in e with defining polynomial
|
629
|
+
x^8 - 24*x^6 + 464*x^4 + 3840*x^2 + 25600
|
630
|
+
Defn: a |--> -9/66560*e^7 + 11/4160*e^5 - 241/4160*e^3 - 101/104*e
|
631
|
+
b |--> -21/166400*e^7 + 73/20800*e^5 - 779/10400*e^3 + 7/260*e,
|
632
|
+
Relative number field morphism:
|
633
|
+
From: Number Field in c with defining polynomial x^2 + 5 over its base field
|
634
|
+
To: Number Field in e with defining polynomial
|
635
|
+
x^8 - 24*x^6 + 464*x^4 + 3840*x^2 + 25600
|
636
|
+
Defn: c |--> -9/66560*e^7 + 11/4160*e^5 - 241/4160*e^3 - 101/104*e
|
637
|
+
d |--> -3/25600*e^7 + 7/1600*e^5 - 147/1600*e^3 + 1/40*e,
|
638
|
+
None]]
|
639
|
+
"""
|
640
|
+
if not isinstance(other, NumberField_generic):
|
641
|
+
raise TypeError("other must be a number field.")
|
642
|
+
if names is None:
|
643
|
+
sv = self.variable_name()
|
644
|
+
ov = other.variable_name()
|
645
|
+
names = sv + (ov if ov != sv else "")
|
646
|
+
|
647
|
+
self_abs = self.absolute_field('w')
|
648
|
+
abs_composites = self_abs.composite_fields(other, names=names, both_maps=both_maps)
|
649
|
+
|
650
|
+
m = self.absolute_degree()
|
651
|
+
|
652
|
+
if not both_maps:
|
653
|
+
rets = []
|
654
|
+
for F in abs_composites:
|
655
|
+
if F.absolute_degree() == m:
|
656
|
+
F = self
|
657
|
+
rets.append(F)
|
658
|
+
return rets
|
659
|
+
|
660
|
+
from_self_abs, to_self_abs = self_abs.structure()
|
661
|
+
|
662
|
+
rets = []
|
663
|
+
for F, self_abs_to_F, other_to_F, k in abs_composites:
|
664
|
+
self_to_F = RelativeNumberFieldHomomorphism_from_abs(self.Hom(F), self_abs_to_F*to_self_abs)
|
665
|
+
if F.absolute_degree() == m:
|
666
|
+
if other.is_absolute():
|
667
|
+
other_to_F = other.hom([(from_self_abs*(~self_abs_to_F)*other_to_F)(other.gen())])
|
668
|
+
else:
|
669
|
+
other_to_F = RelativeNumberFieldHomomorphism_from_abs(self.Hom(self), from_self_abs*(~self_abs_to_F)*other_to_F)
|
670
|
+
self_to_F = RelativeNumberFieldHomomorphism_from_abs(self.Hom(self), from_self_abs)
|
671
|
+
F = self
|
672
|
+
rets.append([F, self_to_F, other_to_F, None])
|
673
|
+
return rets
|
674
|
+
|
675
|
+
def absolute_degree(self):
|
676
|
+
"""
|
677
|
+
The degree of this relative number field over the rational field.
|
678
|
+
|
679
|
+
EXAMPLES::
|
680
|
+
|
681
|
+
sage: x = polygen(ZZ, 'x')
|
682
|
+
sage: K.<a> = NumberFieldTower([x^2 - 17, x^3 - 2])
|
683
|
+
sage: K.absolute_degree()
|
684
|
+
6
|
685
|
+
"""
|
686
|
+
return self.absolute_polynomial().degree()
|
687
|
+
|
688
|
+
def relative_degree(self):
|
689
|
+
r"""
|
690
|
+
Return the relative degree of this relative number field.
|
691
|
+
|
692
|
+
EXAMPLES::
|
693
|
+
|
694
|
+
sage: x = polygen(ZZ, 'x')
|
695
|
+
sage: K.<a> = NumberFieldTower([x^2 - 17, x^3 - 2])
|
696
|
+
sage: K.relative_degree()
|
697
|
+
2
|
698
|
+
"""
|
699
|
+
return self.relative_polynomial().degree()
|
700
|
+
|
701
|
+
def degree(self):
|
702
|
+
"""
|
703
|
+
The degree, unqualified, of a relative number field is deliberately
|
704
|
+
not implemented, so that a user cannot mistake the absolute degree
|
705
|
+
for the relative degree, or vice versa.
|
706
|
+
|
707
|
+
EXAMPLES::
|
708
|
+
|
709
|
+
sage: x = polygen(ZZ, 'x')
|
710
|
+
sage: K.<a> = NumberFieldTower([x^2 - 17, x^3 - 2])
|
711
|
+
sage: K.degree()
|
712
|
+
Traceback (most recent call last):
|
713
|
+
...
|
714
|
+
NotImplementedError: For a relative number field
|
715
|
+
you must use relative_degree or absolute_degree as appropriate
|
716
|
+
"""
|
717
|
+
raise NotImplementedError("For a relative number field you must use relative_degree or absolute_degree as appropriate")
|
718
|
+
|
719
|
+
@cached_method
|
720
|
+
def _maximal_order(self, v=(), assume_maximal='non-maximal-non-unique'):
|
721
|
+
"""
|
722
|
+
Implement :meth:`NumberField_generic.maximal_order` for relative
|
723
|
+
number fields.
|
724
|
+
|
725
|
+
EXAMPLES::
|
726
|
+
|
727
|
+
sage: x = polygen(ZZ, 'x')
|
728
|
+
sage: K.<a> = NumberFieldTower([x^2 - 17, x^3 - 2])
|
729
|
+
sage: K.maximal_order() is K.maximal_order() # indirect doctest
|
730
|
+
True
|
731
|
+
"""
|
732
|
+
absolute_order = self.absolute_field('z').maximal_order(v=v, assume_maximal=assume_maximal)
|
733
|
+
|
734
|
+
return RelativeOrder(self, absolute_order, is_maximal=assume_maximal, is_maximal_at=v)
|
735
|
+
|
736
|
+
def _repr_(self):
|
737
|
+
"""
|
738
|
+
Return string representation of this relative number field.
|
739
|
+
|
740
|
+
The base field is not part of the string representation. To
|
741
|
+
find out what the base field is use :meth:`~base_field`.
|
742
|
+
|
743
|
+
EXAMPLES::
|
744
|
+
|
745
|
+
sage: x = polygen(ZZ, 'x')
|
746
|
+
sage: k.<a, b> = NumberField([x^5 + 2, x^7 + 3])
|
747
|
+
sage: repr(k) # indirect doctest
|
748
|
+
'Number Field in a with defining polynomial x^5 + 2 over its base field'
|
749
|
+
sage: k.base_field()
|
750
|
+
Number Field in b with defining polynomial x^7 + 3
|
751
|
+
"""
|
752
|
+
|
753
|
+
return "Number Field in %s with defining polynomial %s over its base field" % (self.variable_name(), self.relative_polynomial())
|
754
|
+
|
755
|
+
def _Hom_(self, codomain, category=None):
|
756
|
+
"""
|
757
|
+
Return homset of homomorphisms from this relative number field
|
758
|
+
to the codomain.
|
759
|
+
|
760
|
+
EXAMPLES:
|
761
|
+
|
762
|
+
This function is implicitly called by the ``Hom`` method or
|
763
|
+
function::
|
764
|
+
|
765
|
+
sage: x = polygen(ZZ, 'x')
|
766
|
+
sage: K.<a,b> = NumberField([x^3 - 2, x^2+1])
|
767
|
+
sage: K.Hom(K) # indirect doctest
|
768
|
+
Automorphism group of Number Field in a with defining polynomial x^3 - 2 over its base field
|
769
|
+
sage: type(K.Hom(K))
|
770
|
+
<class 'sage.rings.number_field.homset.RelativeNumberFieldHomset_with_category'>
|
771
|
+
|
772
|
+
TESTS::
|
773
|
+
|
774
|
+
sage: H = End(K)
|
775
|
+
sage: loads(dumps(H)) is H
|
776
|
+
True
|
777
|
+
"""
|
778
|
+
if not is_NumberFieldHomsetCodomain(codomain):
|
779
|
+
raise TypeError("{} is not suitable as codomain for homomorphisms from {}".format(codomain, self))
|
780
|
+
|
781
|
+
from sage.rings.number_field.homset import RelativeNumberFieldHomset
|
782
|
+
return RelativeNumberFieldHomset(self, codomain, category)
|
783
|
+
|
784
|
+
def _latex_(self):
|
785
|
+
r"""
|
786
|
+
Return a `\LaTeX` representation of the extension.
|
787
|
+
|
788
|
+
EXAMPLES::
|
789
|
+
|
790
|
+
sage: x = polygen(QQ)
|
791
|
+
sage: x = polygen(ZZ, 'x')
|
792
|
+
sage: K.<a> = NumberField(x^3 - 2)
|
793
|
+
sage: t = polygen(K)
|
794
|
+
sage: K.extension(t^2+t+a, 'b')._latex_()
|
795
|
+
'( \\Bold{Q}[a]/(a^{3} - 2) )[b]/(b^{2} + b + a)'
|
796
|
+
"""
|
797
|
+
latex_name = self.latex_variable_names()[0]
|
798
|
+
return "( %s )[%s]/(%s)" % (latex(self.base_field()), latex_name,
|
799
|
+
self.relative_polynomial()._latex_(latex_name))
|
800
|
+
|
801
|
+
def _coerce_from_other_number_field(self, x):
|
802
|
+
"""
|
803
|
+
Coerce a number field element x into this number field.
|
804
|
+
|
805
|
+
In most cases this currently doesn't work (since it is
|
806
|
+
barely implemented) -- it only works for constants.
|
807
|
+
|
808
|
+
INPUT:
|
809
|
+
|
810
|
+
- ``x`` -- an element of some number field
|
811
|
+
|
812
|
+
EXAMPLES::
|
813
|
+
|
814
|
+
sage: x = polygen(ZZ, 'x')
|
815
|
+
sage: K.<a> = NumberField(x^3 + 2)
|
816
|
+
sage: L.<b> = NumberField(x^2 + 1)
|
817
|
+
sage: K._coerce_from_other_number_field(L(2/3))
|
818
|
+
2/3
|
819
|
+
"""
|
820
|
+
if x.parent() is self.base_ring():
|
821
|
+
return self.__base_inclusion(x)
|
822
|
+
|
823
|
+
f = x.polynomial()
|
824
|
+
if f.degree() <= 0:
|
825
|
+
return self._element_class(self, f[0])
|
826
|
+
# todo: more general coercion if embedding have been asserted
|
827
|
+
raise TypeError("Cannot coerce element into this number field")
|
828
|
+
|
829
|
+
def _convert_non_number_field_element(self, x):
|
830
|
+
r"""
|
831
|
+
Convert the non-number field element `x` into this number field.
|
832
|
+
|
833
|
+
INPUT:
|
834
|
+
|
835
|
+
- ``x`` -- a non number field element, e.g., a list,
|
836
|
+
integer, rational, or polynomial
|
837
|
+
|
838
|
+
EXAMPLES::
|
839
|
+
|
840
|
+
sage: x = polygen(ZZ)
|
841
|
+
sage: K.<a> = NumberField(x^5 + 2)
|
842
|
+
sage: L.<b> = K.extension(x^2 + 3*a)
|
843
|
+
sage: R.<u> = QQ[]
|
844
|
+
sage: S.<t> = R[]
|
845
|
+
|
846
|
+
sage: L(a + b)
|
847
|
+
b + a
|
848
|
+
|
849
|
+
sage: L(5*t*(1 + u) + 2/3*u)
|
850
|
+
(5*a + 5)*b + 2/3*a
|
851
|
+
sage: L(0*t + 2/3)
|
852
|
+
2/3
|
853
|
+
sage: L(1/2*t + 5)
|
854
|
+
1/2*b + 5
|
855
|
+
|
856
|
+
This seems reasonable::
|
857
|
+
|
858
|
+
sage: L(t*5)
|
859
|
+
5*b
|
860
|
+
|
861
|
+
This is misleading, but correct! It is more often desired
|
862
|
+
to make a number field element given by rational
|
863
|
+
coefficients of the relative power basis (so 2*b^2 + 3)
|
864
|
+
than it is to create the constant term of such an element,
|
865
|
+
which is what would happen if L(u*5) gave 5*a.::
|
866
|
+
|
867
|
+
sage: L(u*5)
|
868
|
+
5*b
|
869
|
+
|
870
|
+
sage: L([1, 1/2])
|
871
|
+
1/2*b + 1
|
872
|
+
sage: L([ a, 1/2 + a/3 ])
|
873
|
+
(1/3*a + 1/2)*b + a
|
874
|
+
|
875
|
+
sage: L([ 1 ])
|
876
|
+
Traceback (most recent call last):
|
877
|
+
...
|
878
|
+
ValueError: Length must be equal to the degree of this number field
|
879
|
+
|
880
|
+
TESTS:
|
881
|
+
|
882
|
+
Examples from :issue:`4727`::
|
883
|
+
|
884
|
+
sage: # needs fpylll sage.symbolic
|
885
|
+
sage: K.<j,b> = QQ[sqrt(-1), sqrt(2)]
|
886
|
+
sage: j
|
887
|
+
I
|
888
|
+
sage: j.list()
|
889
|
+
[0, 1]
|
890
|
+
sage: K(j.list())
|
891
|
+
I
|
892
|
+
sage: (b*j + 1/2).list()
|
893
|
+
[1/2, sqrt2]
|
894
|
+
sage: K((b*j + 1/2).list())
|
895
|
+
sqrt2*I + 1/2
|
896
|
+
|
897
|
+
Examples from :issue:`4869`::
|
898
|
+
|
899
|
+
sage: K.<z> = CyclotomicField(7)
|
900
|
+
sage: Ky.<y> = PolynomialRing(K)
|
901
|
+
sage: L.<a> = K.extension(y^2 + 1)
|
902
|
+
sage: K(K.polynomial_ring().random_element()) # random
|
903
|
+
-12*z^2 + 1/2*z - 1/95
|
904
|
+
sage: L(L.polynomial_ring().random_element()) # random
|
905
|
+
(z^5 + 1/3*z^4 - z^3 + z^2 - z + 2/3)*a + 1/4*z^5 - 7/2*z^4 + 5/3*z^3 - 1/4*z^2 + 3/2*z - 1
|
906
|
+
|
907
|
+
Examples from :issue:`11307`::
|
908
|
+
|
909
|
+
sage: L = NumberField([x^2 + 1, x^2 - 3], 'a')
|
910
|
+
sage: L(L)
|
911
|
+
Traceback (most recent call last):
|
912
|
+
...
|
913
|
+
TypeError: unable to convert Number Field in a0 with defining polynomial x^2 + 1 over its base field
|
914
|
+
to Number Field in a0 with defining polynomial x^2 + 1 over its base field
|
915
|
+
sage: L in L
|
916
|
+
False
|
917
|
+
|
918
|
+
We construct the composite of three quadratic fields, then
|
919
|
+
coerce from the quartic subfield of the relative extension::
|
920
|
+
|
921
|
+
sage: k.<a,b,c> = NumberField([x^2 + 5, x^2 + 3, x^2 + 1])
|
922
|
+
sage: m = k.base_field(); m
|
923
|
+
Number Field in b with defining polynomial x^2 + 3 over its base field
|
924
|
+
sage: k(m.0)
|
925
|
+
b
|
926
|
+
sage: k(2/3)
|
927
|
+
2/3
|
928
|
+
sage: k(m.0^4)
|
929
|
+
9
|
930
|
+
|
931
|
+
sage: x = polygen(ZZ)
|
932
|
+
sage: K.<a> = NumberField(x^2 + 2, 'a')
|
933
|
+
sage: L.<b> = K.extension(x - a, 'b')
|
934
|
+
sage: L(a)
|
935
|
+
a
|
936
|
+
sage: L(b+a)
|
937
|
+
2*a
|
938
|
+
sage: K.<a> = NumberField(x^5 + 2, 'a')
|
939
|
+
sage: L.<b> = K.extension(x - a, 'b')
|
940
|
+
sage: L(a)
|
941
|
+
a
|
942
|
+
sage: L(a**3)
|
943
|
+
a^3
|
944
|
+
sage: L(a**2+b)
|
945
|
+
a^2 + a
|
946
|
+
sage: L.<b> = K.extension(x + a/2, 'b')
|
947
|
+
sage: L(a)
|
948
|
+
a
|
949
|
+
sage: L(a).polynomial()
|
950
|
+
-x
|
951
|
+
sage: L(a).minpoly()
|
952
|
+
x - a
|
953
|
+
sage: L(a).absolute_minpoly()
|
954
|
+
x^5 + 2
|
955
|
+
sage: L(b)
|
956
|
+
-1/2*a
|
957
|
+
sage: L(b).polynomial()
|
958
|
+
1/2*x
|
959
|
+
sage: L(b).absolute_minpoly()
|
960
|
+
x^5 - 1/16
|
961
|
+
sage: L(b).minpoly()
|
962
|
+
x + 1/2*a
|
963
|
+
|
964
|
+
::
|
965
|
+
|
966
|
+
sage: K.<a> = NumberField(x^5+2)
|
967
|
+
sage: R.<y> = K[]
|
968
|
+
sage: L.<x0> = K.extension(y + a**2)
|
969
|
+
sage: L(a)
|
970
|
+
a
|
971
|
+
"""
|
972
|
+
if isinstance(x, polynomial_element.Polynomial):
|
973
|
+
# we have been given a polynomial, change it to an absolute polynomial
|
974
|
+
K = self.base_ring()
|
975
|
+
R = self.polynomial_ring()
|
976
|
+
if QQ.has_coerce_map_from(x.parent().base_ring()):
|
977
|
+
# special case absolute polynomials -- they should be
|
978
|
+
# in terms of the relative generator
|
979
|
+
x = R(x.list())
|
980
|
+
# this should work for base_ring()['x'] and QQ['base']['ext']
|
981
|
+
x = self.polynomial_ring()(x)
|
982
|
+
f = R( [ K(coeff) for coeff in x.list() ] )
|
983
|
+
return self._element_class(self, f(self.gen()).polynomial() )
|
984
|
+
|
985
|
+
# Anything else: use the code for generic number fields
|
986
|
+
return super()._convert_non_number_field_element(x)
|
987
|
+
|
988
|
+
def _coerce_map_from_(self, R):
|
989
|
+
"""
|
990
|
+
Canonical coercion of x into this relative number field.
|
991
|
+
|
992
|
+
Currently integers, rationals, the base field, and this field
|
993
|
+
itself coerce canonically into this field (and hence so does
|
994
|
+
anything that coerces into one of these).
|
995
|
+
|
996
|
+
EXAMPLES::
|
997
|
+
|
998
|
+
sage: x = polygen(ZZ, 'x')
|
999
|
+
sage: k.<a> = NumberField([x^5 + 2, x^7 + 3])
|
1000
|
+
sage: b = k(k.base_field().gen())
|
1001
|
+
sage: b = k.coerce(k.base_field().gen()) # indirect doctest
|
1002
|
+
sage: b^7
|
1003
|
+
-3
|
1004
|
+
sage: k.coerce(2/3)
|
1005
|
+
2/3
|
1006
|
+
sage: c = a + b # no output
|
1007
|
+
"""
|
1008
|
+
if R is int:
|
1009
|
+
return self._generic_coerce_map(R)
|
1010
|
+
if R in (ZZ, QQ, self.base_field()):
|
1011
|
+
return self._generic_coerce_map(R)
|
1012
|
+
if isinstance(R, sage.rings.abc.Order) and R.number_field() is self:
|
1013
|
+
return self._generic_coerce_map(R)
|
1014
|
+
mor = self.base_field()._internal_coerce_map_from(R)
|
1015
|
+
if mor is not None:
|
1016
|
+
return self._internal_coerce_map_from(self.base_field()) * mor
|
1017
|
+
|
1018
|
+
def _element_constructor_(self, x, check=True):
|
1019
|
+
"""
|
1020
|
+
Construct a relative number field element from ``x``.
|
1021
|
+
|
1022
|
+
EXAMPLES:
|
1023
|
+
|
1024
|
+
We can create relative number field elements from PARI::
|
1025
|
+
|
1026
|
+
sage: y = polygen(QQ)
|
1027
|
+
sage: K.<a> = NumberField(y^2 + y + 1)
|
1028
|
+
sage: x = polygen(K)
|
1029
|
+
sage: L.<b> = NumberField(x^4 + a*x + 2)
|
1030
|
+
sage: e = a.__pari__(); e
|
1031
|
+
Mod(y, y^2 + y + 1)
|
1032
|
+
sage: L(e) # Conversion from PARI base field element
|
1033
|
+
a
|
1034
|
+
sage: e = (a*b).__pari__('x'); e
|
1035
|
+
Mod(-x^4 - 2, x^8 - x^5 + 4*x^4 + x^2 - 2*x + 4)
|
1036
|
+
sage: L(e) # Conversion from PARI absolute number field element
|
1037
|
+
a*b
|
1038
|
+
sage: e = L.pari_rnf().rnfeltabstorel(e); e
|
1039
|
+
Mod(Mod(y, y^2 + y + 1)*x, x^4 + Mod(y, y^2 + y + 1)*x + 2)
|
1040
|
+
sage: L(e) # Conversion from PARI relative number field element
|
1041
|
+
a*b
|
1042
|
+
sage: e = pari('Mod(0, x^8 + 1)'); L(e) # Wrong modulus
|
1043
|
+
Traceback (most recent call last):
|
1044
|
+
...
|
1045
|
+
TypeError: cannot convert PARI element Mod(0, x^8 + 1) into Number Field in b with defining polynomial x^4 + a*x + 2 over its base field
|
1046
|
+
|
1047
|
+
We test a relative number field element created "by hand"::
|
1048
|
+
|
1049
|
+
sage: e = pari("Mod(Mod(y, y^2 + y + 1)*x^2 + Mod(1, y^2 + y + 1), x^4 + y*x + 2)")
|
1050
|
+
sage: L(e)
|
1051
|
+
a*b^2 + 1
|
1052
|
+
|
1053
|
+
A wrong modulus yields an error::
|
1054
|
+
|
1055
|
+
sage: e = pari('Mod(y*x, x^4 + y^2*x + 2)'); L(e)
|
1056
|
+
Traceback (most recent call last):
|
1057
|
+
...
|
1058
|
+
TypeError: cannot convert PARI element Mod(y*x, x^4 + y^2*x + 2) into Number Field in b with defining polynomial x^4 + a*x + 2 over its base field
|
1059
|
+
"""
|
1060
|
+
# If x is a *relative* PARI number field element, convert it
|
1061
|
+
# to an absolute element.
|
1062
|
+
if isinstance(x, pari_gen) and x.type() == "t_POLMOD":
|
1063
|
+
modulus = x.mod()
|
1064
|
+
if (modulus == self.pari_relative_polynomial()
|
1065
|
+
or modulus == self.pari_absolute_base_polynomial()):
|
1066
|
+
x = self._pari_rnfeq()._eltreltoabs(x.liftpol())
|
1067
|
+
check = False
|
1068
|
+
return NumberField_generic._element_constructor_(self, x, check=check)
|
1069
|
+
|
1070
|
+
def __base_inclusion(self, element):
|
1071
|
+
"""
|
1072
|
+
Given an element of the base field, give its inclusion into
|
1073
|
+
this extension in terms of the generator of this field.
|
1074
|
+
|
1075
|
+
This is called by the canonical coercion map on elements from
|
1076
|
+
the base field.
|
1077
|
+
|
1078
|
+
EXAMPLES::
|
1079
|
+
|
1080
|
+
sage: x = polygen(ZZ, 'x')
|
1081
|
+
sage: k.<a> = NumberField([x^2 + 3, x^2 + 1])
|
1082
|
+
sage: m = k.base_field(); m
|
1083
|
+
Number Field in a1 with defining polynomial x^2 + 1
|
1084
|
+
sage: k.coerce(m.0 + 2/3) # indirect doctest
|
1085
|
+
a1 + 2/3
|
1086
|
+
sage: s = k.coerce(m.0); s
|
1087
|
+
a1
|
1088
|
+
sage: s^2
|
1089
|
+
-1
|
1090
|
+
|
1091
|
+
This implicitly tests this coercion map::
|
1092
|
+
|
1093
|
+
sage: K.<a> = NumberField([x^2 + p for p in [5,3,2]])
|
1094
|
+
sage: K.coerce(K.base_field().0)
|
1095
|
+
a1
|
1096
|
+
sage: K.coerce(K.base_field().0)^2
|
1097
|
+
-3
|
1098
|
+
|
1099
|
+
TESTS:
|
1100
|
+
|
1101
|
+
Check that :issue:`5828` is solved::
|
1102
|
+
|
1103
|
+
sage: K.<w> = QuadraticField(-1)
|
1104
|
+
sage: KX.<X> = K[]
|
1105
|
+
sage: H.<h> = K.extension(X-1)
|
1106
|
+
sage: H(w)
|
1107
|
+
w
|
1108
|
+
"""
|
1109
|
+
abs_base, from_abs_base, to_abs_base = self.absolute_base_field()
|
1110
|
+
# Write element in terms of the absolute base field
|
1111
|
+
element = self.base_field().coerce(element)
|
1112
|
+
element = to_abs_base(element)
|
1113
|
+
# Express element as a polynomial in the absolute generator of self
|
1114
|
+
nfzk = self._pari_nfzk()
|
1115
|
+
expr_x = self._pari_base_nf()._nfeltup(element._pari_polynomial(), nfzk)
|
1116
|
+
# We do NOT call self(...) because this code is called by
|
1117
|
+
# __init__ before we initialize self.gens(), and self(...)
|
1118
|
+
# uses self.gens()
|
1119
|
+
return self._element_constructor_(expr_x, check=False)
|
1120
|
+
|
1121
|
+
def _fractional_ideal_class_(self):
|
1122
|
+
"""
|
1123
|
+
Return the Python class used to represent ideals of a relative
|
1124
|
+
number field.
|
1125
|
+
|
1126
|
+
EXAMPLES::
|
1127
|
+
|
1128
|
+
sage: x = polygen(ZZ, 'x')
|
1129
|
+
sage: k.<a> = NumberField([x^5 + 2, x^7 + 3])
|
1130
|
+
sage: k._fractional_ideal_class_ ()
|
1131
|
+
<class 'sage.rings.number_field.number_field_ideal_rel.NumberFieldFractionalIdeal_rel'>
|
1132
|
+
"""
|
1133
|
+
return sage.rings.number_field.number_field_ideal_rel.NumberFieldFractionalIdeal_rel
|
1134
|
+
|
1135
|
+
def _pari_base_bnf(self, proof=False, units=True):
|
1136
|
+
r"""
|
1137
|
+
Return the PARI bnf (big number field) representation of the
|
1138
|
+
absolute base field in terms of the pari variable ``y``, suitable
|
1139
|
+
for extension by the pari variable ``x``.
|
1140
|
+
|
1141
|
+
All caching is done by the absolute base field.
|
1142
|
+
|
1143
|
+
INPUT:
|
1144
|
+
|
1145
|
+
- ``proof`` -- boolean (default: ``True``); if ``True``, certify
|
1146
|
+
correctness of calculations (not assuming GRH)
|
1147
|
+
|
1148
|
+
EXAMPLES::
|
1149
|
+
|
1150
|
+
sage: x = polygen(ZZ, 'x')
|
1151
|
+
sage: k.<a> = NumberField([x^3 + 2, x^2 + 2])
|
1152
|
+
sage: k._pari_base_bnf()
|
1153
|
+
[[;], matrix(0,3), [;], ...]
|
1154
|
+
"""
|
1155
|
+
abs_base, from_abs_base, to_abs_base = self.absolute_base_field()
|
1156
|
+
return abs_base.pari_bnf(proof, units)
|
1157
|
+
|
1158
|
+
def _pari_base_nf(self):
|
1159
|
+
r"""
|
1160
|
+
Return the PARI number field representation of the absolute
|
1161
|
+
base field, in terms of the pari variable ``y``, suitable for
|
1162
|
+
extension by the pari variable ``x``.
|
1163
|
+
|
1164
|
+
All caching is done by the absolute base field.
|
1165
|
+
|
1166
|
+
EXAMPLES::
|
1167
|
+
|
1168
|
+
sage: y = polygen(QQ,'y')
|
1169
|
+
sage: k.<a> = NumberField([y^3 + 2, y^2 + 2])
|
1170
|
+
sage: k._pari_base_nf()
|
1171
|
+
[y^2 + 2, [0, 1], -8, 1, ..., [1, 0, 0, -2; 0, 1, 1, 0]]
|
1172
|
+
"""
|
1173
|
+
abs_base, from_abs_base, to_abs_base = self.absolute_base_field()
|
1174
|
+
return abs_base.pari_nf()
|
1175
|
+
|
1176
|
+
def is_galois(self):
|
1177
|
+
r"""
|
1178
|
+
For a relative number field, :meth:`is_galois` is deliberately not
|
1179
|
+
implemented, since it is not clear whether this would mean "Galois over
|
1180
|
+
`\QQ`" or "Galois over the given base field".
|
1181
|
+
Use either :meth:`is_galois_absolute` or :meth:`is_galois_relative`, respectively.
|
1182
|
+
|
1183
|
+
EXAMPLES::
|
1184
|
+
|
1185
|
+
sage: x = polygen(ZZ, 'x')
|
1186
|
+
sage: k.<a> = NumberField([x^3 - 2, x^2 + x + 1])
|
1187
|
+
sage: k.is_galois()
|
1188
|
+
Traceback (most recent call last):
|
1189
|
+
...
|
1190
|
+
NotImplementedError: For a relative number field L you must use
|
1191
|
+
either L.is_galois_relative() or L.is_galois_absolute() as appropriate
|
1192
|
+
"""
|
1193
|
+
raise NotImplementedError("For a relative number field L you must use either L.is_galois_relative() or L.is_galois_absolute() as appropriate")
|
1194
|
+
|
1195
|
+
def is_galois_relative(self):
|
1196
|
+
r"""
|
1197
|
+
Return ``True`` if for this relative extension `L/K`, `L` is a
|
1198
|
+
Galois extension of `K`.
|
1199
|
+
|
1200
|
+
EXAMPLES::
|
1201
|
+
|
1202
|
+
sage: x = polygen(ZZ, 'x')
|
1203
|
+
sage: K.<a> = NumberField(x^3 - 2)
|
1204
|
+
sage: y = polygen(K)
|
1205
|
+
sage: L.<b> = K.extension(y^2 - a)
|
1206
|
+
sage: L.is_galois_relative()
|
1207
|
+
True
|
1208
|
+
sage: M.<c> = K.extension(y^3 - a)
|
1209
|
+
sage: M.is_galois_relative()
|
1210
|
+
False
|
1211
|
+
|
1212
|
+
The next example previously gave a wrong result; see :issue:`9390`::
|
1213
|
+
|
1214
|
+
sage: F.<a, b> = NumberField([x^2 - 2, x^2 - 3])
|
1215
|
+
sage: F.is_galois_relative()
|
1216
|
+
True
|
1217
|
+
"""
|
1218
|
+
d = self.relative_degree()
|
1219
|
+
if d <= 2:
|
1220
|
+
return True
|
1221
|
+
else:
|
1222
|
+
rel_poly = self.relative_polynomial()
|
1223
|
+
return d == len(rel_poly.base_extend(self).factor())
|
1224
|
+
|
1225
|
+
def is_galois_absolute(self):
|
1226
|
+
r"""
|
1227
|
+
Return ``True`` if for this relative extension `L/K`, `L` is a Galois extension of `\QQ`.
|
1228
|
+
|
1229
|
+
EXAMPLES::
|
1230
|
+
|
1231
|
+
sage: x = polygen(ZZ, 'x')
|
1232
|
+
sage: K.<a> = NumberField(x^3 - 2)
|
1233
|
+
sage: y = polygen(K); L.<b> = K.extension(y^2 - a)
|
1234
|
+
sage: L.is_galois_absolute() # needs sage.groups
|
1235
|
+
False
|
1236
|
+
"""
|
1237
|
+
f = self.absolute_polynomial()
|
1238
|
+
return f.galois_group(pari_group=True).order() == self.absolute_degree()
|
1239
|
+
|
1240
|
+
def is_isomorphic_relative(self, other, base_isom=None):
|
1241
|
+
r"""
|
1242
|
+
For this relative extension `L/K` and another relative extension `M/K`, return ``True``
|
1243
|
+
if there is a `K`-linear isomorphism from `L` to `M`. More generally, ``other`` can be a
|
1244
|
+
relative extension `M/K^\prime` with ``base_isom`` an isomorphism from `K` to
|
1245
|
+
`K^\prime`.
|
1246
|
+
|
1247
|
+
EXAMPLES::
|
1248
|
+
|
1249
|
+
sage: x = polygen(ZZ, 'x')
|
1250
|
+
sage: K.<z9> = NumberField(x^6 + x^3 + 1)
|
1251
|
+
sage: R.<z> = PolynomialRing(K)
|
1252
|
+
sage: m1 = 3*z9^4 - 4*z9^3 - 4*z9^2 + 3*z9 - 8
|
1253
|
+
sage: L1 = K.extension(z^2 - m1, 'b1')
|
1254
|
+
|
1255
|
+
sage: # needs sage.groups
|
1256
|
+
sage: G = K.galois_group(); gamma = G.gen()
|
1257
|
+
sage: m2 = (gamma^2)(m1)
|
1258
|
+
sage: L2 = K.extension(z^2 - m2, 'b2')
|
1259
|
+
sage: L1.is_isomorphic_relative(L2)
|
1260
|
+
False
|
1261
|
+
sage: L1.is_isomorphic(L2)
|
1262
|
+
True
|
1263
|
+
|
1264
|
+
sage: L3 = K.extension(z^4 - m1, 'b3')
|
1265
|
+
sage: L1.is_isomorphic_relative(L3)
|
1266
|
+
False
|
1267
|
+
|
1268
|
+
If we have two extensions over different, but isomorphic, bases, we can compare them by
|
1269
|
+
letting ``base_isom`` be an isomorphism from ``self``'s base field to ``other``'s base field::
|
1270
|
+
|
1271
|
+
sage: Kcyc.<zeta9> = CyclotomicField(9)
|
1272
|
+
sage: Rcyc.<zcyc> = PolynomialRing(Kcyc)
|
1273
|
+
sage: phi1 = K.hom([zeta9])
|
1274
|
+
sage: m1cyc = phi1(m1)
|
1275
|
+
sage: L1cyc = Kcyc.extension(zcyc^2 - m1cyc, 'b1cyc')
|
1276
|
+
sage: L1.is_isomorphic_relative(L1cyc, base_isom=phi1)
|
1277
|
+
True
|
1278
|
+
|
1279
|
+
sage: # needs sage.groups
|
1280
|
+
sage: L2.is_isomorphic_relative(L1cyc, base_isom=phi1)
|
1281
|
+
False
|
1282
|
+
sage: phi2 = K.hom([phi1((gamma^(-2))(z9))])
|
1283
|
+
sage: L1.is_isomorphic_relative(L1cyc, base_isom=phi2)
|
1284
|
+
False
|
1285
|
+
sage: L2.is_isomorphic_relative(L1cyc, base_isom=phi2)
|
1286
|
+
True
|
1287
|
+
|
1288
|
+
Omitting ``base_isom`` raises a :exc:`ValueError` when the base fields
|
1289
|
+
are not identical::
|
1290
|
+
|
1291
|
+
sage: L1.is_isomorphic_relative(L1cyc)
|
1292
|
+
Traceback (most recent call last):
|
1293
|
+
...
|
1294
|
+
ValueError: other does not have the same base field as self,
|
1295
|
+
so an isomorphism from self's base_field to other's base_field
|
1296
|
+
must be provided using the base_isom parameter.
|
1297
|
+
|
1298
|
+
The parameter ``base_isom`` can also be used to check if the relative extensions are
|
1299
|
+
Galois conjugate::
|
1300
|
+
|
1301
|
+
sage: for g in G: # needs sage.groups
|
1302
|
+
....: if L1.is_isomorphic_relative(L2, g.as_hom()):
|
1303
|
+
....: print(g.as_hom())
|
1304
|
+
Ring endomorphism of Number Field in z9 with defining polynomial x^6 + x^3 + 1
|
1305
|
+
Defn: z9 |--> z9^4
|
1306
|
+
"""
|
1307
|
+
if isinstance(other, NumberField_relative):
|
1308
|
+
s_base_field = self.base_field()
|
1309
|
+
o_base_field = other.base_field()
|
1310
|
+
if base_isom is None:
|
1311
|
+
if s_base_field is o_base_field:
|
1312
|
+
return self.relative_degree() == other.relative_degree() and len(self.relative_polynomial().roots(other)) > 0
|
1313
|
+
raise ValueError("other does not have the same base field as self, so an isomorphism from self's base_field to other's base_field must be provided using the base_isom parameter.")
|
1314
|
+
if s_base_field.absolute_degree() != o_base_field.absolute_degree():
|
1315
|
+
raise ValueError("The base fields are not isomorphic.")
|
1316
|
+
if base_isom.domain() is s_base_field and base_isom.codomain() is o_base_field:
|
1317
|
+
if s_base_field.absolute_degree() != o_base_field.absolute_degree():
|
1318
|
+
raise ValueError("The base fields are not isomorphic.")
|
1319
|
+
if not self.relative_degree() == other.relative_degree():
|
1320
|
+
return False
|
1321
|
+
R = PolynomialRing(o_base_field, 'x')
|
1322
|
+
F = R([base_isom(_) for _ in self.relative_polynomial()])
|
1323
|
+
return len(F.roots(other)) > 0
|
1324
|
+
raise ValueError("base_isom is not a homomorphism from self's base_field to other's base_field")
|
1325
|
+
raise ValueError("other must be a relative number field.")
|
1326
|
+
|
1327
|
+
def is_CM_extension(self):
|
1328
|
+
"""
|
1329
|
+
Return ``True`` is this is a CM extension, i.e. a totally imaginary
|
1330
|
+
quadratic extension of a totally real field.
|
1331
|
+
|
1332
|
+
EXAMPLES::
|
1333
|
+
|
1334
|
+
sage: x = polygen(ZZ, 'x')
|
1335
|
+
sage: F.<a> = NumberField(x^2 - 5)
|
1336
|
+
sage: K.<z> = F.extension(x^2 + 7)
|
1337
|
+
sage: K.is_CM_extension()
|
1338
|
+
True
|
1339
|
+
sage: K = CyclotomicField(7)
|
1340
|
+
sage: K_rel = K.relativize(K.gen() + K.gen()^(-1), 'z')
|
1341
|
+
sage: K_rel.is_CM_extension()
|
1342
|
+
True
|
1343
|
+
sage: F = CyclotomicField(3)
|
1344
|
+
sage: K.<z> = F.extension(x^3 - 2)
|
1345
|
+
sage: K.is_CM_extension()
|
1346
|
+
False
|
1347
|
+
|
1348
|
+
A CM field `K` such that `K/F` is not a CM extension
|
1349
|
+
|
1350
|
+
::
|
1351
|
+
|
1352
|
+
sage: F.<a> = NumberField(x^2 + 1)
|
1353
|
+
sage: K.<z> = F.extension(x^2 - 3)
|
1354
|
+
sage: K.is_CM_extension()
|
1355
|
+
False
|
1356
|
+
sage: K.is_CM()
|
1357
|
+
True
|
1358
|
+
"""
|
1359
|
+
|
1360
|
+
try:
|
1361
|
+
return self.__is_CM_extension
|
1362
|
+
except (AttributeError):
|
1363
|
+
pass
|
1364
|
+
|
1365
|
+
if self.relative_degree() == 2:
|
1366
|
+
if self.base_field().is_totally_real():
|
1367
|
+
if self.is_totally_imaginary():
|
1368
|
+
self.__is_CM_extension = True
|
1369
|
+
self.__is_CM = True
|
1370
|
+
self.__max_tot_real_sub = [self.base_field(), self._internal_coerce_map_from(self.base_field())]
|
1371
|
+
return True
|
1372
|
+
self.__is_CM_extension = False
|
1373
|
+
return False
|
1374
|
+
|
1375
|
+
@cached_method(key=lambda self, base, basis, map: (base or self.base_ring(), basis, map))
|
1376
|
+
def free_module(self, base=None, basis=None, map=True):
|
1377
|
+
"""
|
1378
|
+
Return a vector space over a specified subfield that is isomorphic to this number field,
|
1379
|
+
together with the isomorphisms in each direction.
|
1380
|
+
|
1381
|
+
INPUT:
|
1382
|
+
|
1383
|
+
- ``base`` -- a subfield
|
1384
|
+
|
1385
|
+
- ``basis`` -- (optional) a list of elements giving a basis over the subfield
|
1386
|
+
|
1387
|
+
- ``map`` -- (default: ``True``) whether to return isomorphisms to and
|
1388
|
+
from the vector space
|
1389
|
+
|
1390
|
+
EXAMPLES::
|
1391
|
+
|
1392
|
+
sage: x = polygen(ZZ, 'x')
|
1393
|
+
sage: K.<a,b,c> = NumberField([x^2 + 2, x^3 + 2, x^3 + 3]); K
|
1394
|
+
Number Field in a with defining polynomial x^2 + 2 over its base field
|
1395
|
+
sage: V, from_V, to_V = K.free_module()
|
1396
|
+
sage: to_V(K.0)
|
1397
|
+
(0, 1)
|
1398
|
+
sage: W, from_W, to_W = K.free_module(base=QQ)
|
1399
|
+
sage: w = to_W(K.0); len(w)
|
1400
|
+
18
|
1401
|
+
sage: w[0]
|
1402
|
+
-127917622658689792301282/48787705559800061938765
|
1403
|
+
"""
|
1404
|
+
if basis is not None:
|
1405
|
+
raise NotImplementedError
|
1406
|
+
if base is None:
|
1407
|
+
base = self.base_field()
|
1408
|
+
if base is self.base_field():
|
1409
|
+
V = self.base_field()**self.relative_degree()
|
1410
|
+
if not map:
|
1411
|
+
return V
|
1412
|
+
fr = maps.MapRelativeVectorSpaceToRelativeNumberField(V, self)
|
1413
|
+
to = maps.MapRelativeNumberFieldToRelativeVectorSpace(self, V)
|
1414
|
+
elif base is QQ:
|
1415
|
+
if not map:
|
1416
|
+
return QQ**self.absolute_degree()
|
1417
|
+
K = self.absolute_field('a')
|
1418
|
+
from_K, to_K = K.structure()
|
1419
|
+
V, from_V, to_V = K.free_module()
|
1420
|
+
fr = maps.MapVectorSpaceToRelativeNumberField(V, self, from_V, from_K)
|
1421
|
+
to = maps.MapRelativeNumberFieldToVectorSpace(self, V, to_K, to_V)
|
1422
|
+
else:
|
1423
|
+
raise NotImplementedError
|
1424
|
+
return V, fr, to
|
1425
|
+
|
1426
|
+
def relative_vector_space(self, base=None, *args, **kwds):
|
1427
|
+
"""
|
1428
|
+
Return vector space over the base field of ``self`` and isomorphisms
|
1429
|
+
from the vector space to ``self`` and in the other direction.
|
1430
|
+
|
1431
|
+
EXAMPLES::
|
1432
|
+
|
1433
|
+
sage: x = polygen(ZZ, 'x')
|
1434
|
+
sage: K.<a,b,c> = NumberField([x^2 + 2, x^3 + 2, x^3 + 3]); K
|
1435
|
+
Number Field in a with defining polynomial x^2 + 2 over its base field
|
1436
|
+
sage: V, from_V, to_V = K.relative_vector_space()
|
1437
|
+
sage: from_V(V.0)
|
1438
|
+
1
|
1439
|
+
sage: to_V(K.0)
|
1440
|
+
(0, 1)
|
1441
|
+
sage: from_V(to_V(K.0))
|
1442
|
+
a
|
1443
|
+
sage: to_V(from_V(V.0))
|
1444
|
+
(1, 0)
|
1445
|
+
sage: to_V(from_V(V.1))
|
1446
|
+
(0, 1)
|
1447
|
+
|
1448
|
+
The underlying vector space and maps is cached::
|
1449
|
+
|
1450
|
+
sage: W, from_V, to_V = K.relative_vector_space()
|
1451
|
+
sage: V is W
|
1452
|
+
True
|
1453
|
+
"""
|
1454
|
+
if base is not None and base is not self.base_field():
|
1455
|
+
raise ValueError("Relative vector space base must be the base field")
|
1456
|
+
return self.free_module(self.base_field(), *args, **kwds)
|
1457
|
+
|
1458
|
+
def absolute_vector_space(self, base=None, *args, **kwds):
|
1459
|
+
r"""
|
1460
|
+
Return vector space over `\QQ` of ``self`` and isomorphisms from
|
1461
|
+
the vector space to ``self`` and in the other direction.
|
1462
|
+
|
1463
|
+
EXAMPLES::
|
1464
|
+
|
1465
|
+
sage: x = polygen(ZZ, 'x')
|
1466
|
+
sage: K.<a,b> = NumberField([x^3 + 3, x^3 + 2]); K
|
1467
|
+
Number Field in a with defining polynomial x^3 + 3 over its base field
|
1468
|
+
sage: V,from_V,to_V = K.absolute_vector_space(); V
|
1469
|
+
Vector space of dimension 9 over Rational Field
|
1470
|
+
sage: from_V
|
1471
|
+
Isomorphism map:
|
1472
|
+
From: Vector space of dimension 9 over Rational Field
|
1473
|
+
To: Number Field in a with defining polynomial x^3 + 3 over its base field
|
1474
|
+
sage: to_V
|
1475
|
+
Isomorphism map:
|
1476
|
+
From: Number Field in a with defining polynomial x^3 + 3 over its base field
|
1477
|
+
To: Vector space of dimension 9 over Rational Field
|
1478
|
+
sage: c = (a+1)^5; c
|
1479
|
+
7*a^2 - 10*a - 29
|
1480
|
+
sage: to_V(c)
|
1481
|
+
(-29, -712/9, 19712/45, 0, -14/9, 364/45, 0, -4/9, 119/45)
|
1482
|
+
sage: from_V(to_V(c))
|
1483
|
+
7*a^2 - 10*a - 29
|
1484
|
+
sage: from_V(3*to_V(b))
|
1485
|
+
3*b
|
1486
|
+
"""
|
1487
|
+
if base is not None and base is not QQ:
|
1488
|
+
raise ValueError("Absolute vector space base must be QQ")
|
1489
|
+
return self.free_module(QQ, *args, **kwds)
|
1490
|
+
|
1491
|
+
def vector_space(self, *args, **kwds):
|
1492
|
+
r"""
|
1493
|
+
For a relative number field, :meth:`vector_space` is
|
1494
|
+
deliberately not implemented, so that a user cannot confuse
|
1495
|
+
:meth:`~relative_vector_space` with :meth:`~absolute_vector_space`.
|
1496
|
+
|
1497
|
+
EXAMPLES::
|
1498
|
+
|
1499
|
+
sage: x = polygen(ZZ, 'x')
|
1500
|
+
sage: K.<a> = NumberFieldTower([x^2 - 17, x^3 - 2])
|
1501
|
+
sage: K.vector_space()
|
1502
|
+
Traceback (most recent call last):
|
1503
|
+
...
|
1504
|
+
NotImplementedError: For a relative number field L you must use either
|
1505
|
+
L.relative_vector_space() or L.absolute_vector_space() as appropriate
|
1506
|
+
"""
|
1507
|
+
raise NotImplementedError("For a relative number field L you must use either L.relative_vector_space() or L.absolute_vector_space() as appropriate")
|
1508
|
+
|
1509
|
+
def absolute_base_field(self):
|
1510
|
+
r"""
|
1511
|
+
Return the base field of this relative extension, but viewed
|
1512
|
+
as an absolute field over `\QQ`.
|
1513
|
+
|
1514
|
+
EXAMPLES::
|
1515
|
+
|
1516
|
+
sage: x = polygen(ZZ, 'x')
|
1517
|
+
sage: K.<a,b,c> = NumberField([x^2 + 2, x^3 + 3, x^3 + 2])
|
1518
|
+
sage: K
|
1519
|
+
Number Field in a with defining polynomial x^2 + 2 over its base field
|
1520
|
+
sage: K.base_field()
|
1521
|
+
Number Field in b with defining polynomial x^3 + 3 over its base field
|
1522
|
+
sage: K.absolute_base_field()[0]
|
1523
|
+
Number Field in a0 with defining polynomial x^9 + 3*x^6 + 165*x^3 + 1
|
1524
|
+
sage: K.base_field().absolute_field('z')
|
1525
|
+
Number Field in z with defining polynomial x^9 + 3*x^6 + 165*x^3 + 1
|
1526
|
+
"""
|
1527
|
+
return self.__absolute_base_field
|
1528
|
+
|
1529
|
+
@cached_method
|
1530
|
+
def _pari_rnfeq(self):
|
1531
|
+
"""
|
1532
|
+
Return PARI data attached to this relative number field.
|
1533
|
+
|
1534
|
+
OUTPUT:
|
1535
|
+
|
1536
|
+
A 5-element PARI vector containing an absolute polynomial and
|
1537
|
+
further data needed for ``eltabstorel`` and ``eltreltoabs``,
|
1538
|
+
obtained from PARI's ``nf_rnfeq`` function. This means that
|
1539
|
+
we do not have to initialize a full PARI ``rnf`` structure.
|
1540
|
+
|
1541
|
+
TESTS::
|
1542
|
+
|
1543
|
+
sage: x = polygen(ZZ, 'x')
|
1544
|
+
sage: K.<a> = NumberField(x^2 + 2)
|
1545
|
+
sage: x = polygen(K)
|
1546
|
+
sage: L.<b> = K.extension(x^5 + 2*a)
|
1547
|
+
sage: L._pari_rnfeq()
|
1548
|
+
[x^10 + 8, -1/2*x^5, 0, y^2 + 2, x^5 + 2*y]
|
1549
|
+
sage: x = polygen(ZZ)
|
1550
|
+
sage: NumberField(x^10 + 8, 'a').is_isomorphic(L)
|
1551
|
+
True
|
1552
|
+
|
1553
|
+
Initialization is lazy enough to allow arithmetic in massive fields::
|
1554
|
+
|
1555
|
+
sage: x = polygen(ZZ, 'x')
|
1556
|
+
sage: K.<a> = NumberField(x^10 + 2000*x + 100001)
|
1557
|
+
sage: x = polygen(K)
|
1558
|
+
sage: L.<b> = K.extension(x^10 + 2*a)
|
1559
|
+
sage: L._pari_rnfeq()
|
1560
|
+
[x^100 - 1024000*x^10 + 102401024, -1/2*x^10, 0, y^10 + 2000*y + 100001, x^10 + 2*y]
|
1561
|
+
sage: a + b
|
1562
|
+
b + a
|
1563
|
+
sage: b^100
|
1564
|
+
-2048000*a - 102401024
|
1565
|
+
sage: (-2*a)^10
|
1566
|
+
-2048000*a - 102401024
|
1567
|
+
"""
|
1568
|
+
f = self.pari_absolute_base_polynomial()
|
1569
|
+
g = self.pari_relative_polynomial()
|
1570
|
+
return f._nf_rnfeq(g)
|
1571
|
+
|
1572
|
+
@cached_method
|
1573
|
+
def _pari_nfzk(self):
|
1574
|
+
"""
|
1575
|
+
Return PARI data needed for constructing relative number field
|
1576
|
+
elements from elements of the base field.
|
1577
|
+
|
1578
|
+
TESTS::
|
1579
|
+
|
1580
|
+
sage: x = polygen(ZZ, 'x')
|
1581
|
+
sage: K.<a> = NumberField(x^2 - 2)
|
1582
|
+
sage: L.<b> = K.extension(x^2 - 3)
|
1583
|
+
sage: L._pari_nfzk()
|
1584
|
+
[2, -x^3 + 9*x]
|
1585
|
+
"""
|
1586
|
+
return self._pari_base_nf()._nf_nfzk(self._pari_rnfeq())
|
1587
|
+
|
1588
|
+
@cached_method
|
1589
|
+
def _pari_relative_structure(self):
|
1590
|
+
r"""
|
1591
|
+
Return data relating the Sage and PARI relative polynomials.
|
1592
|
+
|
1593
|
+
OUTPUT:
|
1594
|
+
|
1595
|
+
Let `L` be this relative number field, let `K` be its base
|
1596
|
+
field, and let `f` be the defining polynomial of `L` over `K`.
|
1597
|
+
This method returns a triple ``(g, alpha, beta)``, where
|
1598
|
+
|
1599
|
+
- ``g`` -- the defining relative polynomial of the PARI
|
1600
|
+
``rnf`` structure (see :meth:`pari_rnf`);
|
1601
|
+
|
1602
|
+
- ``alpha`` is the image of `x \bmod f` under some isomorphism
|
1603
|
+
`\phi\colon K[x]/(f) \to K[x]/(g)`;
|
1604
|
+
|
1605
|
+
- ``beta`` is the image of `x \bmod g` under the inverse
|
1606
|
+
isomorphism `\phi^{-1}\colon K[x]/(g) \to K[x]/(f)`.
|
1607
|
+
|
1608
|
+
EXAMPLES:
|
1609
|
+
|
1610
|
+
If the defining polynomials are monic and integral, the result
|
1611
|
+
satisfies ``g = f`` and ``alpha = beta = x``::
|
1612
|
+
|
1613
|
+
sage: R.<x> = QQ[]
|
1614
|
+
sage: K.<a> = NumberField(x^2 + 1)
|
1615
|
+
sage: L.<b> = K.extension(x^2 - a)
|
1616
|
+
sage: L._pari_relative_structure()
|
1617
|
+
(Mod(1, y^2 + 1)*x^2 + Mod(-y, y^2 + 1),
|
1618
|
+
Mod(x, Mod(1, y^2 + 1)*x^2 + Mod(-y, y^2 + 1)),
|
1619
|
+
Mod(x, Mod(1, y^2 + 1)*x^2 + Mod(-y, y^2 + 1)))
|
1620
|
+
|
1621
|
+
An example where the base field is defined by a monic integral
|
1622
|
+
polynomial, but the extension is not::
|
1623
|
+
|
1624
|
+
sage: K.<a> = NumberField(x^2 + 1)
|
1625
|
+
sage: L.<b> = K.extension(x^2 - 1/2)
|
1626
|
+
sage: L._pari_relative_structure()
|
1627
|
+
(x^2 + Mod(y, y^2 + 1),
|
1628
|
+
Mod(Mod(-1/2*y - 1/2, y^2 + 1)*x, x^2 + Mod(y, y^2 + 1)),
|
1629
|
+
Mod(Mod(y - 1, y^2 + 1)*x, x^2 + Mod(-1/2, y^2 + 1)))
|
1630
|
+
|
1631
|
+
An example where both fields are defined by non-integral or
|
1632
|
+
non-monic polynomials::
|
1633
|
+
|
1634
|
+
sage: K.<a> = NumberField(2*x^2 + 1)
|
1635
|
+
sage: L.<b> = K.extension(x^2 - 1/3)
|
1636
|
+
sage: L._pari_relative_structure()
|
1637
|
+
(x^2 + Mod(y, y^2 + 2)*x + 1,
|
1638
|
+
Mod(Mod(-1/3*y, y^2 + 2)*x + Mod(1/3, y^2 + 2), x^2 + Mod(y, y^2 + 2)*x + 1),
|
1639
|
+
Mod(Mod(3/2*y, y^2 + 2)*x + Mod(-1/2*y, y^2 + 2), Mod(1, y^2 + 2)*x^2 + Mod(-1/3, y^2 + 2)))
|
1640
|
+
|
1641
|
+
Note that in the last example, the *absolute* defining
|
1642
|
+
polynomials is the same for Sage and PARI, even though this is
|
1643
|
+
not the case for the base field::
|
1644
|
+
|
1645
|
+
sage: K._pari_absolute_structure()
|
1646
|
+
(y^2 + 2, Mod(1/2*y, y^2 + 2), Mod(2*y, y^2 + 1/2))
|
1647
|
+
sage: L._pari_absolute_structure()
|
1648
|
+
(y^4 + 4*y^2 + 1, Mod(y, y^4 + 4*y^2 + 1), Mod(y, y^4 + 4*y^2 + 1))
|
1649
|
+
"""
|
1650
|
+
f = self.relative_polynomial()._pari_with_name('x')
|
1651
|
+
if f.pollead() == f.content().lift().content().denominator() == 1:
|
1652
|
+
g = f
|
1653
|
+
alpha = beta = f.variable().Mod(f)
|
1654
|
+
elif f.poldegree() == 1:
|
1655
|
+
# PARI's rnfpolredbest() does not always return a
|
1656
|
+
# polynomial with integral coefficients in this case.
|
1657
|
+
from sage.libs.pari import pari
|
1658
|
+
g = f.variable()
|
1659
|
+
alpha = -f[0]/f[1]
|
1660
|
+
beta = pari(0).Mod(f)
|
1661
|
+
else:
|
1662
|
+
g, alpha = self._pari_base_nf().rnfpolredbest(f, flag=1)
|
1663
|
+
beta = alpha.modreverse()
|
1664
|
+
return g, alpha, beta
|
1665
|
+
|
1666
|
+
@cached_method
|
1667
|
+
def _gen_relative(self):
|
1668
|
+
r"""
|
1669
|
+
Return root of defining polynomial, which is a generator of
|
1670
|
+
the relative number field over the base.
|
1671
|
+
|
1672
|
+
EXAMPLES::
|
1673
|
+
|
1674
|
+
sage: x = polygen(ZZ, 'x')
|
1675
|
+
sage: k.<a> = NumberField(x^2 + 1); k
|
1676
|
+
Number Field in a with defining polynomial x^2 + 1
|
1677
|
+
sage: y = polygen(k)
|
1678
|
+
sage: m.<b> = k.extension(y^2 + 3); m
|
1679
|
+
Number Field in b with defining polynomial x^2 + 3 over its base field
|
1680
|
+
sage: c = m.gen(); c # indirect doctest
|
1681
|
+
b
|
1682
|
+
sage: c^2 + 3
|
1683
|
+
0
|
1684
|
+
|
1685
|
+
An example where the defining polynomials are not monic or
|
1686
|
+
integral::
|
1687
|
+
|
1688
|
+
sage: K.<a> = NumberField(3*x^2 + 1)
|
1689
|
+
sage: L.<b> = K.extension(x^2 - 1/2)
|
1690
|
+
sage: L._gen_relative()
|
1691
|
+
b
|
1692
|
+
"""
|
1693
|
+
alpha = self._pari_relative_structure()[1].liftpol()
|
1694
|
+
return self._element_constructor_(self._pari_rnfeq()._eltreltoabs(alpha), check=False)
|
1695
|
+
|
1696
|
+
@cached_method
|
1697
|
+
def pari_rnf(self):
|
1698
|
+
r"""
|
1699
|
+
Return the PARI relative number field object associated
|
1700
|
+
to this relative extension.
|
1701
|
+
|
1702
|
+
EXAMPLES::
|
1703
|
+
|
1704
|
+
sage: x = polygen(ZZ, 'x')
|
1705
|
+
sage: k.<a> = NumberField([x^4 + 3, x^2 + 2])
|
1706
|
+
sage: k.pari_rnf()
|
1707
|
+
[x^4 + 3, [364, -10*x^7 - 87*x^5 - 370*x^3 - 41*x], [108, 3], ...]
|
1708
|
+
"""
|
1709
|
+
return self._pari_base_nf().rnfinit(self.pari_relative_polynomial())
|
1710
|
+
|
1711
|
+
def pari_absolute_base_polynomial(self):
|
1712
|
+
r"""
|
1713
|
+
Return the PARI polynomial defining the absolute base field, in ``y``.
|
1714
|
+
|
1715
|
+
EXAMPLES::
|
1716
|
+
|
1717
|
+
sage: x = polygen(ZZ)
|
1718
|
+
sage: x = polygen(ZZ, 'x')
|
1719
|
+
sage: K.<a, b> = NumberField([x^2 + 2, x^2 + 3]); K
|
1720
|
+
Number Field in a with defining polynomial x^2 + 2 over its base field
|
1721
|
+
sage: K.pari_absolute_base_polynomial()
|
1722
|
+
y^2 + 3
|
1723
|
+
sage: type(K.pari_absolute_base_polynomial())
|
1724
|
+
<class 'cypari2.gen.Gen'>
|
1725
|
+
sage: z = ZZ['z'].0
|
1726
|
+
sage: K.<a, b, c> = NumberField([z^2 + 2, z^2 + 3, z^2 + 5]); K
|
1727
|
+
Number Field in a with defining polynomial z^2 + 2 over its base field
|
1728
|
+
sage: K.pari_absolute_base_polynomial()
|
1729
|
+
y^4 + 16*y^2 + 4
|
1730
|
+
sage: K.base_field()
|
1731
|
+
Number Field in b with defining polynomial z^2 + 3 over its base field
|
1732
|
+
sage: len(QQ['y'](K.pari_absolute_base_polynomial()).roots(K.base_field()))
|
1733
|
+
4
|
1734
|
+
sage: type(K.pari_absolute_base_polynomial())
|
1735
|
+
<class 'cypari2.gen.Gen'>
|
1736
|
+
"""
|
1737
|
+
abs_base, from_abs_base, to_abs_base = self.absolute_base_field()
|
1738
|
+
return abs_base.pari_polynomial('y')
|
1739
|
+
|
1740
|
+
def pari_relative_polynomial(self):
|
1741
|
+
r"""
|
1742
|
+
Return the PARI relative polynomial associated to this number
|
1743
|
+
field.
|
1744
|
+
|
1745
|
+
This is always a polynomial in `x` and `y`, suitable for PARI's
|
1746
|
+
:pari:`rnfinit` function. Notice that if this is a relative extension
|
1747
|
+
of a relative extension, the base field is the absolute base
|
1748
|
+
field.
|
1749
|
+
|
1750
|
+
EXAMPLES::
|
1751
|
+
|
1752
|
+
sage: x = polygen(ZZ, 'x')
|
1753
|
+
sage: k.<i> = NumberField(x^2 + 1)
|
1754
|
+
sage: m.<z> = k.extension(k['w']([i,0,1]))
|
1755
|
+
sage: m
|
1756
|
+
Number Field in z with defining polynomial w^2 + i over its base field
|
1757
|
+
sage: m.pari_relative_polynomial()
|
1758
|
+
Mod(1, y^2 + 1)*x^2 + Mod(y, y^2 + 1)
|
1759
|
+
|
1760
|
+
sage: l.<t> = m.extension(m['t'].0^2 + z)
|
1761
|
+
sage: l.pari_relative_polynomial()
|
1762
|
+
Mod(1, y^4 + 1)*x^2 + Mod(y, y^4 + 1)
|
1763
|
+
"""
|
1764
|
+
return self._pari_relative_structure()[0]
|
1765
|
+
|
1766
|
+
def number_of_roots_of_unity(self):
|
1767
|
+
r"""
|
1768
|
+
Return the number of roots of unity in this relative field.
|
1769
|
+
|
1770
|
+
EXAMPLES::
|
1771
|
+
|
1772
|
+
sage: x = polygen(ZZ, 'x')
|
1773
|
+
sage: K.<a, b> = NumberField([x^2 + x + 1, x^4 + 1])
|
1774
|
+
sage: K.number_of_roots_of_unity()
|
1775
|
+
24
|
1776
|
+
"""
|
1777
|
+
return self.absolute_field('a').number_of_roots_of_unity()
|
1778
|
+
|
1779
|
+
def roots_of_unity(self):
|
1780
|
+
r"""
|
1781
|
+
Return all the roots of unity in this relative field, primitive or not.
|
1782
|
+
|
1783
|
+
EXAMPLES::
|
1784
|
+
|
1785
|
+
sage: x = polygen(ZZ, 'x')
|
1786
|
+
sage: K.<a, b> = NumberField([x^2 + x + 1, x^4 + 1])
|
1787
|
+
sage: rts = K.roots_of_unity()
|
1788
|
+
sage: len(rts)
|
1789
|
+
24
|
1790
|
+
sage: all(u in rts for u in [b*a, -b^2*a - b^2, b^3, -a, b*a + b])
|
1791
|
+
True
|
1792
|
+
"""
|
1793
|
+
abs = self.absolute_field('a')
|
1794
|
+
from_abs, _ = abs.structure()
|
1795
|
+
return [from_abs(x) for x in abs.roots_of_unity()]
|
1796
|
+
|
1797
|
+
def absolute_generator(self):
|
1798
|
+
r"""
|
1799
|
+
Return the chosen generator over `\QQ` for this relative number field.
|
1800
|
+
|
1801
|
+
EXAMPLES::
|
1802
|
+
|
1803
|
+
sage: y = polygen(QQ,'y')
|
1804
|
+
sage: k.<a> = NumberField([y^2 + 2, y^4 + 3])
|
1805
|
+
sage: g = k.absolute_generator(); g
|
1806
|
+
a0 - a1
|
1807
|
+
sage: g.minpoly()
|
1808
|
+
x^2 + 2*a1*x + a1^2 + 2
|
1809
|
+
sage: g.absolute_minpoly()
|
1810
|
+
x^8 + 8*x^6 + 30*x^4 - 40*x^2 + 49
|
1811
|
+
"""
|
1812
|
+
try:
|
1813
|
+
return self.__abs_gen
|
1814
|
+
except AttributeError:
|
1815
|
+
self.__abs_gen = self._element_class(self, QQ['x'].gen())
|
1816
|
+
return self.__abs_gen
|
1817
|
+
|
1818
|
+
def absolute_field(self, names):
|
1819
|
+
"""
|
1820
|
+
Return ``self`` as an absolute number field.
|
1821
|
+
|
1822
|
+
INPUT:
|
1823
|
+
|
1824
|
+
- ``names`` -- string; name of generator of the absolute field
|
1825
|
+
|
1826
|
+
OUTPUT: an absolute number field `K` that is isomorphic to this field
|
1827
|
+
|
1828
|
+
Also, ``K.structure()`` returns ``from_K`` and ``to_K``, where
|
1829
|
+
``from_K`` is an isomorphism from `K` to ``self`` and ``to_K``
|
1830
|
+
is an isomorphism from ``self`` to `K`.
|
1831
|
+
|
1832
|
+
EXAMPLES::
|
1833
|
+
|
1834
|
+
sage: x = polygen(ZZ, 'x')
|
1835
|
+
sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
|
1836
|
+
Number Field in a with defining polynomial x^4 + 3 over its base field
|
1837
|
+
sage: L.<xyz> = K.absolute_field(); L
|
1838
|
+
Number Field in xyz with defining polynomial x^8 + 8*x^6 + 30*x^4 - 40*x^2 + 49
|
1839
|
+
sage: L.<c> = K.absolute_field(); L
|
1840
|
+
Number Field in c with defining polynomial x^8 + 8*x^6 + 30*x^4 - 40*x^2 + 49
|
1841
|
+
|
1842
|
+
sage: from_L, to_L = L.structure()
|
1843
|
+
sage: from_L
|
1844
|
+
Isomorphism map:
|
1845
|
+
From: Number Field in c with defining polynomial
|
1846
|
+
x^8 + 8*x^6 + 30*x^4 - 40*x^2 + 49
|
1847
|
+
To: Number Field in a with defining polynomial x^4 + 3 over its base field
|
1848
|
+
sage: from_L(c)
|
1849
|
+
a - b
|
1850
|
+
sage: to_L
|
1851
|
+
Isomorphism map:
|
1852
|
+
From: Number Field in a with defining polynomial x^4 + 3 over its base field
|
1853
|
+
To: Number Field in c with defining polynomial
|
1854
|
+
x^8 + 8*x^6 + 30*x^4 - 40*x^2 + 49
|
1855
|
+
sage: to_L(a)
|
1856
|
+
-5/182*c^7 - 87/364*c^5 - 185/182*c^3 + 323/364*c
|
1857
|
+
sage: to_L(b)
|
1858
|
+
-5/182*c^7 - 87/364*c^5 - 185/182*c^3 - 41/364*c
|
1859
|
+
sage: to_L(a)^4
|
1860
|
+
-3
|
1861
|
+
sage: to_L(b)^2
|
1862
|
+
-2
|
1863
|
+
"""
|
1864
|
+
return NumberField(self.absolute_polynomial(), names, structure=structure.AbsoluteFromRelative(self))
|
1865
|
+
|
1866
|
+
def absolute_polynomial_ntl(self):
|
1867
|
+
"""
|
1868
|
+
Return defining polynomial of this number field
|
1869
|
+
as a pair, an ntl polynomial and a denominator.
|
1870
|
+
|
1871
|
+
This is used mainly to implement some internal arithmetic.
|
1872
|
+
|
1873
|
+
EXAMPLES::
|
1874
|
+
|
1875
|
+
sage: x = polygen(ZZ, 'x')
|
1876
|
+
sage: NumberField(x^2 + (2/3)*x - 9/17,'a').absolute_polynomial_ntl()
|
1877
|
+
([-27 34 51], 51)
|
1878
|
+
"""
|
1879
|
+
try:
|
1880
|
+
return (self.__abs_polynomial_ntl, self.__abs_denominator_ntl)
|
1881
|
+
except AttributeError:
|
1882
|
+
import sage.libs.ntl.all as ntl
|
1883
|
+
self.__abs_denominator_ntl = ntl.ZZ()
|
1884
|
+
den = self.absolute_polynomial().denominator()
|
1885
|
+
self.__abs_denominator_ntl.set_from_sage_int(ZZ(den))
|
1886
|
+
self.__abs_polynomial_ntl = ntl.ZZX((self.absolute_polynomial()*den).list())
|
1887
|
+
return (self.__abs_polynomial_ntl, self.__abs_denominator_ntl)
|
1888
|
+
|
1889
|
+
@cached_method
|
1890
|
+
def absolute_polynomial(self):
|
1891
|
+
r"""
|
1892
|
+
Return the polynomial over `\QQ` that defines this field as an
|
1893
|
+
extension of the rational numbers.
|
1894
|
+
|
1895
|
+
.. NOTE::
|
1896
|
+
|
1897
|
+
The absolute polynomial of a relative number field is
|
1898
|
+
chosen to be equal to the defining polynomial of the
|
1899
|
+
underlying PARI absolute number field (it cannot be
|
1900
|
+
specified by the user). In particular, it is always a
|
1901
|
+
monic polynomial with integral coefficients. On the other
|
1902
|
+
hand, the defining polynomial of an absolute number field
|
1903
|
+
and the relative polynomial of a relative number field are
|
1904
|
+
in general different from their PARI counterparts.
|
1905
|
+
|
1906
|
+
EXAMPLES::
|
1907
|
+
|
1908
|
+
sage: x = polygen(ZZ, 'x')
|
1909
|
+
sage: k.<a, b> = NumberField([x^2 + 1, x^3 + x + 1]); k
|
1910
|
+
Number Field in a with defining polynomial x^2 + 1 over its base field
|
1911
|
+
sage: k.absolute_polynomial()
|
1912
|
+
x^6 + 5*x^4 - 2*x^3 + 4*x^2 + 4*x + 1
|
1913
|
+
|
1914
|
+
An example comparing the various defining polynomials to their
|
1915
|
+
PARI counterparts::
|
1916
|
+
|
1917
|
+
sage: x = polygen(ZZ, 'x')
|
1918
|
+
sage: k.<a, c> = NumberField([x^2 + 1/3, x^2 + 1/4])
|
1919
|
+
sage: k.absolute_polynomial()
|
1920
|
+
x^4 - x^2 + 1
|
1921
|
+
sage: k.pari_polynomial()
|
1922
|
+
x^4 - x^2 + 1
|
1923
|
+
sage: k.base_field().absolute_polynomial()
|
1924
|
+
x^2 + 1/4
|
1925
|
+
sage: k.pari_absolute_base_polynomial()
|
1926
|
+
y^2 + 1
|
1927
|
+
sage: k.relative_polynomial()
|
1928
|
+
x^2 + 1/3
|
1929
|
+
sage: k.pari_relative_polynomial()
|
1930
|
+
x^2 + Mod(-y, y^2 + 1)*x - 1
|
1931
|
+
"""
|
1932
|
+
return QQ['x'](self._pari_rnfeq()[0])
|
1933
|
+
|
1934
|
+
def relative_polynomial(self):
|
1935
|
+
"""
|
1936
|
+
Return the defining polynomial of this relative number field over its base field.
|
1937
|
+
|
1938
|
+
EXAMPLES::
|
1939
|
+
|
1940
|
+
sage: x = polygen(ZZ, 'x')
|
1941
|
+
sage: K.<a> = NumberFieldTower([x^2 + x + 1, x^3 + x + 1])
|
1942
|
+
sage: K.relative_polynomial()
|
1943
|
+
x^2 + x + 1
|
1944
|
+
|
1945
|
+
Use :meth:`absolute_polynomial` for a polynomial that defines the absolute
|
1946
|
+
extension.::
|
1947
|
+
|
1948
|
+
sage: K.absolute_polynomial()
|
1949
|
+
x^6 + 3*x^5 + 8*x^4 + 9*x^3 + 7*x^2 + 6*x + 3
|
1950
|
+
"""
|
1951
|
+
return self.__relative_polynomial
|
1952
|
+
|
1953
|
+
def defining_polynomial(self):
|
1954
|
+
"""
|
1955
|
+
Return the defining polynomial of this relative number field.
|
1956
|
+
|
1957
|
+
This is exactly the same as :meth:`relative_polynomial`.
|
1958
|
+
|
1959
|
+
EXAMPLES::
|
1960
|
+
|
1961
|
+
sage: C.<z> = CyclotomicField(5)
|
1962
|
+
sage: PC.<X> = C[]
|
1963
|
+
sage: K.<a> = C.extension(X^2 + X + z); K
|
1964
|
+
Number Field in a with defining polynomial X^2 + X + z over its base field
|
1965
|
+
sage: K.defining_polynomial()
|
1966
|
+
X^2 + X + z
|
1967
|
+
"""
|
1968
|
+
return self.relative_polynomial()
|
1969
|
+
|
1970
|
+
def polynomial(self):
|
1971
|
+
"""
|
1972
|
+
For a relative number field, :meth:`polynomial` is deliberately
|
1973
|
+
not implemented. Either :meth:`~relative_polynomial` or
|
1974
|
+
:meth:`~absolute_polynomial` must be used.
|
1975
|
+
|
1976
|
+
EXAMPLES::
|
1977
|
+
|
1978
|
+
sage: x = polygen(ZZ, 'x')
|
1979
|
+
sage: K.<a> = NumberFieldTower([x^2 + x + 1, x^3 + x + 1])
|
1980
|
+
sage: K.polynomial()
|
1981
|
+
Traceback (most recent call last):
|
1982
|
+
...
|
1983
|
+
NotImplementedError: For a relative number field L you must use either
|
1984
|
+
L.relative_polynomial() or L.absolute_polynomial() as appropriate
|
1985
|
+
"""
|
1986
|
+
raise NotImplementedError("For a relative number field L you must use either L.relative_polynomial() or L.absolute_polynomial() as appropriate")
|
1987
|
+
|
1988
|
+
def base_field(self):
|
1989
|
+
"""
|
1990
|
+
Return the base field of this relative number field.
|
1991
|
+
|
1992
|
+
EXAMPLES::
|
1993
|
+
|
1994
|
+
sage: x = polygen(ZZ, 'x')
|
1995
|
+
sage: k.<a> = NumberField([x^3 + x + 1])
|
1996
|
+
sage: R.<z> = k[]
|
1997
|
+
sage: L.<b> = NumberField(z^3 + a)
|
1998
|
+
sage: L.base_field()
|
1999
|
+
Number Field in a with defining polynomial x^3 + x + 1
|
2000
|
+
sage: L.base_field() is k
|
2001
|
+
True
|
2002
|
+
|
2003
|
+
This is very useful because the print representation of
|
2004
|
+
a relative field doesn't describe the base field.::
|
2005
|
+
|
2006
|
+
sage: L
|
2007
|
+
Number Field in b with defining polynomial z^3 + a over its base field
|
2008
|
+
"""
|
2009
|
+
return self.__base_field
|
2010
|
+
|
2011
|
+
def base_ring(self):
|
2012
|
+
"""
|
2013
|
+
This is exactly the same as base_field.
|
2014
|
+
|
2015
|
+
EXAMPLES::
|
2016
|
+
|
2017
|
+
sage: x = polygen(ZZ, 'x')
|
2018
|
+
sage: k.<a> = NumberField([x^2 + 1, x^3 + x + 1])
|
2019
|
+
sage: k.base_ring()
|
2020
|
+
Number Field in a1 with defining polynomial x^3 + x + 1
|
2021
|
+
sage: k.base_field()
|
2022
|
+
Number Field in a1 with defining polynomial x^3 + x + 1
|
2023
|
+
"""
|
2024
|
+
return self.base_field()
|
2025
|
+
|
2026
|
+
def embeddings(self, K):
|
2027
|
+
r"""
|
2028
|
+
Compute all field embeddings of the relative number field self
|
2029
|
+
into the field `K` (which need not even be a number field,
|
2030
|
+
e.g., it could be the complex numbers). This will return an
|
2031
|
+
identical result when given `K` as input again.
|
2032
|
+
|
2033
|
+
If possible, the most natural embedding of ``self`` into `K`
|
2034
|
+
is put first in the list.
|
2035
|
+
|
2036
|
+
INPUT:
|
2037
|
+
|
2038
|
+
- ``K`` -- a field
|
2039
|
+
|
2040
|
+
EXAMPLES::
|
2041
|
+
|
2042
|
+
sage: x = polygen(ZZ, 'x')
|
2043
|
+
sage: K.<a,b> = NumberField([x^3 - 2, x^2 + 1])
|
2044
|
+
sage: f = K.embeddings(ComplexField(58)); f
|
2045
|
+
[Relative number field morphism:
|
2046
|
+
From: Number Field in a with defining polynomial x^3 - 2 over its base field
|
2047
|
+
To: Complex Field with 58 bits of precision
|
2048
|
+
Defn: a |--> -0.62996052494743676 - 1.0911236359717214*I
|
2049
|
+
b |--> -1.9428902930940239e-16 + 1.0000000000000000*I,
|
2050
|
+
...
|
2051
|
+
Relative number field morphism:
|
2052
|
+
From: Number Field in a with defining polynomial x^3 - 2 over its base field
|
2053
|
+
To: Complex Field with 58 bits of precision
|
2054
|
+
Defn: a |--> 1.2599210498948731
|
2055
|
+
b |--> -0.99999999999999999*I]
|
2056
|
+
sage: f[0](a)^3
|
2057
|
+
2.0000000000000002 - 8.6389229103644993e-16*I
|
2058
|
+
sage: f[0](b)^2
|
2059
|
+
-1.0000000000000001 - 3.8857805861880480e-16*I
|
2060
|
+
sage: f[0](a+b)
|
2061
|
+
-0.62996052494743693 - 0.091123635971721295*I
|
2062
|
+
"""
|
2063
|
+
if K.characteristic():
|
2064
|
+
return Sequence([], immutable=True, check=False, universe=self.Hom(K))
|
2065
|
+
|
2066
|
+
try:
|
2067
|
+
# this should be concordant with automorphisms
|
2068
|
+
return self.__embeddings[K]
|
2069
|
+
except AttributeError:
|
2070
|
+
self.__embeddings = {}
|
2071
|
+
except KeyError:
|
2072
|
+
pass
|
2073
|
+
L = self.absolute_field('a')
|
2074
|
+
E = L.embeddings(K)
|
2075
|
+
v = [self.hom(f, K) for f in E]
|
2076
|
+
|
2077
|
+
# If there is an embedding that preserves variable names
|
2078
|
+
# then it is most natural, so we put it first.
|
2079
|
+
put_natural_embedding_first(v)
|
2080
|
+
|
2081
|
+
self.__embeddings[K] = Sequence(v, cr=bool(v), immutable=True, check=False, universe=self.Hom(K))
|
2082
|
+
return self.__embeddings[K]
|
2083
|
+
|
2084
|
+
def automorphisms(self):
|
2085
|
+
r"""
|
2086
|
+
Compute all Galois automorphisms of ``self`` over the base field. This is
|
2087
|
+
different from computing the embeddings of ``self`` into ``self``; there,
|
2088
|
+
automorphisms that do not fix the base field are considered.
|
2089
|
+
|
2090
|
+
EXAMPLES::
|
2091
|
+
|
2092
|
+
sage: x = polygen(ZZ, 'x')
|
2093
|
+
sage: K.<a, b> = NumberField([x^2 + 10000, x^2 + x + 50]); K
|
2094
|
+
Number Field in a with defining polynomial x^2 + 10000 over its base field
|
2095
|
+
sage: K.automorphisms()
|
2096
|
+
[Relative number field endomorphism of Number Field in a with defining polynomial x^2 + 10000 over its base field
|
2097
|
+
Defn: a |--> a
|
2098
|
+
b |--> b,
|
2099
|
+
Relative number field endomorphism of Number Field in a with defining polynomial x^2 + 10000 over its base field
|
2100
|
+
Defn: a |--> -a
|
2101
|
+
b |--> b]
|
2102
|
+
sage: rho, tau = K.automorphisms()
|
2103
|
+
sage: tau(a)
|
2104
|
+
-a
|
2105
|
+
sage: tau(b) == b
|
2106
|
+
True
|
2107
|
+
|
2108
|
+
sage: L.<b, a> = NumberField([x^2 + x + 50, x^2 + 10000, ]); L
|
2109
|
+
Number Field in b with defining polynomial x^2 + x + 50 over its base field
|
2110
|
+
sage: L.automorphisms()
|
2111
|
+
[Relative number field endomorphism of Number Field in b with defining polynomial x^2 + x + 50 over its base field
|
2112
|
+
Defn: b |--> b
|
2113
|
+
a |--> a,
|
2114
|
+
Relative number field endomorphism of Number Field in b with defining polynomial x^2 + x + 50 over its base field
|
2115
|
+
Defn: b |--> -b - 1
|
2116
|
+
a |--> a]
|
2117
|
+
sage: rho, tau = L.automorphisms()
|
2118
|
+
sage: tau(a) == a
|
2119
|
+
True
|
2120
|
+
sage: tau(b)
|
2121
|
+
-b - 1
|
2122
|
+
|
2123
|
+
sage: PQ.<X> = QQ[]
|
2124
|
+
sage: F.<a, b> = NumberField([X^2 - 2, X^2 - 3])
|
2125
|
+
sage: PF.<Y> = F[]
|
2126
|
+
sage: K.<c> = F.extension(Y^2 - (1 + a)*(a + b)*a*b)
|
2127
|
+
sage: K.automorphisms()
|
2128
|
+
[Relative number field endomorphism of Number Field in c with defining polynomial Y^2 + (-2*b - 3)*a - 2*b - 6 over its base field
|
2129
|
+
Defn: c |--> c
|
2130
|
+
a |--> a
|
2131
|
+
b |--> b,
|
2132
|
+
Relative number field endomorphism of Number Field in c with defining polynomial Y^2 + (-2*b - 3)*a - 2*b - 6 over its base field
|
2133
|
+
Defn: c |--> -c
|
2134
|
+
a |--> a
|
2135
|
+
b |--> b]
|
2136
|
+
"""
|
2137
|
+
try:
|
2138
|
+
return self.__automorphisms
|
2139
|
+
except AttributeError:
|
2140
|
+
pass
|
2141
|
+
|
2142
|
+
L = self.absolute_field('a')
|
2143
|
+
L_into_self, self_into_L = L.structure()
|
2144
|
+
aas = L.automorphisms() # absolute automorphisms
|
2145
|
+
|
2146
|
+
a = self_into_L(self.gen())
|
2147
|
+
abs_base_gens = [self_into_L(_) for _ in self.base_field().gens()]
|
2148
|
+
v = sorted([self.hom([L_into_self(aa(a))]) for aa in aas
|
2149
|
+
if all(aa(g) == g for g in abs_base_gens)])
|
2150
|
+
put_natural_embedding_first(v)
|
2151
|
+
self.__automorphisms = Sequence(v, cr=bool(v), immutable=True,
|
2152
|
+
check=False, universe=self.Hom(self))
|
2153
|
+
return self.__automorphisms
|
2154
|
+
|
2155
|
+
def logarithmic_embedding(self, prec=53):
|
2156
|
+
r"""
|
2157
|
+
Return the morphism of ``self`` under the logarithmic embedding
|
2158
|
+
in the category Set.
|
2159
|
+
|
2160
|
+
The logarithmic embedding is defined as a map from the relative number field ``self`` to `\RR^n`.
|
2161
|
+
|
2162
|
+
It is defined under Definition 4.9.6 in [Coh1993]_.
|
2163
|
+
|
2164
|
+
INPUT:
|
2165
|
+
|
2166
|
+
- ``prec`` -- desired floating point precision
|
2167
|
+
|
2168
|
+
OUTPUT: the morphism of ``self`` under the logarithmic embedding in the category Set
|
2169
|
+
|
2170
|
+
EXAMPLES::
|
2171
|
+
|
2172
|
+
sage: K.<k> = CyclotomicField(3)
|
2173
|
+
sage: R.<x> = K[]
|
2174
|
+
sage: L.<l> = K.extension(x^5 + 5)
|
2175
|
+
sage: f = L.logarithmic_embedding()
|
2176
|
+
sage: f(0)
|
2177
|
+
(-1, -1, -1, -1, -1)
|
2178
|
+
sage: f(5)
|
2179
|
+
(3.21887582486820, 3.21887582486820, 3.21887582486820,
|
2180
|
+
3.21887582486820, 3.21887582486820)
|
2181
|
+
|
2182
|
+
::
|
2183
|
+
|
2184
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
2185
|
+
sage: t = K['t'].gen()
|
2186
|
+
sage: L.<a> = K.extension(t^4 - i)
|
2187
|
+
sage: f = L.logarithmic_embedding()
|
2188
|
+
sage: f(0)
|
2189
|
+
(-1, -1, -1, -1, -1, -1, -1, -1)
|
2190
|
+
sage: f(3)
|
2191
|
+
(2.19722457733622, 2.19722457733622, 2.19722457733622, 2.19722457733622,
|
2192
|
+
2.19722457733622, 2.19722457733622, 2.19722457733622, 2.19722457733622)
|
2193
|
+
"""
|
2194
|
+
def closure_map(x, prec=53):
|
2195
|
+
"""
|
2196
|
+
The function closure of the logarithmic embedding.
|
2197
|
+
"""
|
2198
|
+
K = self
|
2199
|
+
K_embeddings = K.places(prec)
|
2200
|
+
r1, r2 = K.signature()
|
2201
|
+
r = r1 + r2 - 1
|
2202
|
+
|
2203
|
+
from sage.rings.real_mpfr import RealField
|
2204
|
+
Reals = RealField(prec)
|
2205
|
+
|
2206
|
+
if x == 0:
|
2207
|
+
return vector([-1 for _ in range(r + 1)])
|
2208
|
+
|
2209
|
+
x_logs = []
|
2210
|
+
for i in range(r1):
|
2211
|
+
sigma = K_embeddings[i]
|
2212
|
+
x_logs.append(Reals(abs(sigma(x))).log())
|
2213
|
+
for i in range(r1, r + 1):
|
2214
|
+
tau = K_embeddings[i]
|
2215
|
+
x_logs.append(2 * Reals(abs(tau(x))).log())
|
2216
|
+
|
2217
|
+
return vector(x_logs)
|
2218
|
+
|
2219
|
+
hom = Hom(self, VectorSpace(RR, len(closure_map(self(0), prec))), Sets())
|
2220
|
+
return hom(closure_map)
|
2221
|
+
|
2222
|
+
def places(self, all_complex=False, prec=None):
|
2223
|
+
"""
|
2224
|
+
Return the collection of all infinite places of ``self``.
|
2225
|
+
|
2226
|
+
By default, this returns the set of real places as
|
2227
|
+
homomorphisms into ``RIF`` first, followed by a choice of one of
|
2228
|
+
each pair of complex conjugate homomorphisms into ``CIF``.
|
2229
|
+
|
2230
|
+
On the other hand, if ``prec`` is not ``None``, we simply return places
|
2231
|
+
into ``RealField(prec)`` and ``ComplexField(prec)`` (or ``RDF``, ``CDF`` if
|
2232
|
+
``prec=53``).
|
2233
|
+
|
2234
|
+
There is an optional flag ``all_complex``, which defaults to ``False``. If
|
2235
|
+
``all_complex`` is ``True``, then the real embeddings are returned as
|
2236
|
+
embeddings into ``CIF`` instead of ``RIF``.
|
2237
|
+
|
2238
|
+
EXAMPLES::
|
2239
|
+
|
2240
|
+
sage: x = polygen(ZZ, 'x')
|
2241
|
+
sage: L.<b, c> = NumberFieldTower([x^2 - 5, x^3 + x + 3])
|
2242
|
+
sage: L.places() # needs sage.libs.linbox
|
2243
|
+
[Relative number field morphism:
|
2244
|
+
From: Number Field in b with defining polynomial x^2 - 5 over its base field
|
2245
|
+
To: Real Field with 106 bits of precision
|
2246
|
+
Defn: b |--> -2.236067977499789696409173668937
|
2247
|
+
c |--> -1.213411662762229634132131377426,
|
2248
|
+
Relative number field morphism:
|
2249
|
+
From: Number Field in b with defining polynomial x^2 - 5 over its base field
|
2250
|
+
To: Real Field with 106 bits of precision
|
2251
|
+
Defn: b |--> 2.236067977499789696411548005367
|
2252
|
+
c |--> -1.213411662762229634130492421800,
|
2253
|
+
Relative number field morphism:
|
2254
|
+
From: Number Field in b with defining polynomial x^2 - 5 over its base field
|
2255
|
+
To: Complex Field with 53 bits of precision
|
2256
|
+
Defn: b |--> -2.23606797749979 ...e-1...*I
|
2257
|
+
c |--> 0.606705831381... - 1.45061224918844*I,
|
2258
|
+
Relative number field morphism:
|
2259
|
+
From: Number Field in b with defining polynomial x^2 - 5 over its base field
|
2260
|
+
To: Complex Field with 53 bits of precision
|
2261
|
+
Defn: b |--> 2.23606797749979 - 4.44089209850063e-16*I
|
2262
|
+
c |--> 0.606705831381115 - 1.45061224918844*I]
|
2263
|
+
"""
|
2264
|
+
L = self.absolute_field('a')
|
2265
|
+
pl = L.places(all_complex, prec)
|
2266
|
+
return [self.hom(p, p.codomain()) for p in pl]
|
2267
|
+
|
2268
|
+
def absolute_different(self):
|
2269
|
+
r"""
|
2270
|
+
Return the absolute different of this relative number field `L`, as an
|
2271
|
+
ideal of `L`. To get the relative different of `L/K`, use
|
2272
|
+
:meth:`relative_different`.
|
2273
|
+
|
2274
|
+
EXAMPLES::
|
2275
|
+
|
2276
|
+
sage: x = polygen(ZZ, 'x')
|
2277
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
2278
|
+
sage: t = K['t'].gen()
|
2279
|
+
sage: L.<b> = K.extension(t^4 - i)
|
2280
|
+
sage: L.absolute_different()
|
2281
|
+
Fractional ideal (8)
|
2282
|
+
"""
|
2283
|
+
abs = self.absolute_field('a')
|
2284
|
+
from_abs = abs.structure()[0]
|
2285
|
+
return self.ideal([from_abs(g) for g in abs.different().gens()])
|
2286
|
+
|
2287
|
+
def relative_different(self):
|
2288
|
+
r"""
|
2289
|
+
Return the relative different of this extension `L/K` as
|
2290
|
+
an ideal of `L`. If you want the absolute different of
|
2291
|
+
`L/\QQ`, use :meth:`absolute_different`.
|
2292
|
+
|
2293
|
+
EXAMPLES::
|
2294
|
+
|
2295
|
+
sage: x = polygen(ZZ, 'x')
|
2296
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
2297
|
+
sage: PK.<t> = K[]
|
2298
|
+
sage: L.<a> = K.extension(t^4 - i)
|
2299
|
+
sage: L.relative_different()
|
2300
|
+
Fractional ideal (4)
|
2301
|
+
"""
|
2302
|
+
I = self.absolute_different()
|
2303
|
+
J = self.ideal(self.base_field().absolute_different().gens())
|
2304
|
+
return I/J
|
2305
|
+
|
2306
|
+
def different(self):
|
2307
|
+
"""
|
2308
|
+
The different, unqualified, of a relative number field is deliberately
|
2309
|
+
not implemented, so that a user cannot mistake the absolute different
|
2310
|
+
for the relative different, or vice versa.
|
2311
|
+
|
2312
|
+
EXAMPLES::
|
2313
|
+
|
2314
|
+
sage: x = polygen(ZZ, 'x')
|
2315
|
+
sage: K.<a> = NumberFieldTower([x^2 + x + 1, x^3 + x + 1])
|
2316
|
+
sage: K.different()
|
2317
|
+
Traceback (most recent call last):
|
2318
|
+
...
|
2319
|
+
NotImplementedError: For a relative number field you must use
|
2320
|
+
relative_different or absolute_different as appropriate
|
2321
|
+
"""
|
2322
|
+
raise NotImplementedError("For a relative number field you must use relative_different or absolute_different as appropriate")
|
2323
|
+
|
2324
|
+
def absolute_discriminant(self, v=None):
|
2325
|
+
r"""
|
2326
|
+
Return the absolute discriminant of this relative number field
|
2327
|
+
or if ``v`` is specified, the determinant of the trace pairing
|
2328
|
+
on the elements of the list ``v``.
|
2329
|
+
|
2330
|
+
INPUT:
|
2331
|
+
|
2332
|
+
- ``v`` -- (optional) list of element of this relative number field
|
2333
|
+
|
2334
|
+
OUTPUT: integer if ``v`` is omitted, and Rational otherwise
|
2335
|
+
|
2336
|
+
EXAMPLES::
|
2337
|
+
|
2338
|
+
sage: x = polygen(ZZ, 'x')
|
2339
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
2340
|
+
sage: t = K['t'].gen()
|
2341
|
+
sage: L.<b> = K.extension(t^4 - i)
|
2342
|
+
sage: L.absolute_discriminant()
|
2343
|
+
16777216
|
2344
|
+
sage: L.absolute_discriminant([(b + i)^j for j in range(8)])
|
2345
|
+
61911970349056
|
2346
|
+
"""
|
2347
|
+
abs = self.absolute_field('a')
|
2348
|
+
if v is not None:
|
2349
|
+
to_abs = abs.structure()[1]
|
2350
|
+
v = [to_abs(x) for x in v]
|
2351
|
+
return abs.discriminant(v=v)
|
2352
|
+
|
2353
|
+
def relative_discriminant(self):
|
2354
|
+
r"""
|
2355
|
+
Return the relative discriminant of this extension `L/K` as an ideal of
|
2356
|
+
`K`. If you want the (rational) discriminant of `L/\QQ`, use e.g.
|
2357
|
+
``L.absolute_discriminant()``.
|
2358
|
+
|
2359
|
+
EXAMPLES::
|
2360
|
+
|
2361
|
+
sage: x = polygen(ZZ, 'x')
|
2362
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
2363
|
+
sage: t = K['t'].gen()
|
2364
|
+
sage: L.<b> = K.extension(t^4 - i)
|
2365
|
+
sage: L.relative_discriminant()
|
2366
|
+
Fractional ideal (256)
|
2367
|
+
sage: PQ.<X> = QQ[]
|
2368
|
+
sage: F.<a, b> = NumberField([X^2 - 2, X^2 - 3])
|
2369
|
+
sage: PF.<Y> = F[]
|
2370
|
+
sage: K.<c> = F.extension(Y^2 - (1 + a)*(a + b)*a*b)
|
2371
|
+
sage: K.relative_discriminant() == F.ideal(4*b)
|
2372
|
+
True
|
2373
|
+
|
2374
|
+
TESTS:
|
2375
|
+
|
2376
|
+
Number fields defined by non-monic and non-integral
|
2377
|
+
polynomials are supported (:issue:`252`)::
|
2378
|
+
|
2379
|
+
sage: K.<a> = NumberField(x^2 + 1/2)
|
2380
|
+
sage: L.<b> = K.extension(x^2 - 1/2)
|
2381
|
+
sage: L.relative_discriminant()
|
2382
|
+
Fractional ideal (2)
|
2383
|
+
"""
|
2384
|
+
base = self.base_field()
|
2385
|
+
nf = base.pari_nf()
|
2386
|
+
D, d = nf.rnfdisc(self.pari_relative_polynomial())
|
2387
|
+
return base.ideal(nf.idealhnf(D))
|
2388
|
+
|
2389
|
+
def discriminant(self):
|
2390
|
+
"""
|
2391
|
+
The discriminant, unqualified, of a relative number field is deliberately
|
2392
|
+
not implemented, so that a user cannot mistake the absolute discriminant
|
2393
|
+
for the relative discriminant, or vice versa.
|
2394
|
+
|
2395
|
+
EXAMPLES::
|
2396
|
+
|
2397
|
+
sage: x = polygen(ZZ, 'x')
|
2398
|
+
sage: K.<a> = NumberFieldTower([x^2 + x + 1, x^3 + x + 1])
|
2399
|
+
sage: K.discriminant()
|
2400
|
+
Traceback (most recent call last):
|
2401
|
+
...
|
2402
|
+
NotImplementedError: For a relative number field you must use
|
2403
|
+
relative_discriminant or absolute_discriminant as appropriate
|
2404
|
+
"""
|
2405
|
+
raise NotImplementedError("For a relative number field you must use relative_discriminant or absolute_discriminant as appropriate")
|
2406
|
+
|
2407
|
+
def disc(self):
|
2408
|
+
"""
|
2409
|
+
The discriminant, unqualified, of a relative number field is deliberately
|
2410
|
+
not implemented, so that a user cannot mistake the absolute discriminant
|
2411
|
+
for the relative discriminant, or vice versa.
|
2412
|
+
|
2413
|
+
EXAMPLES::
|
2414
|
+
|
2415
|
+
sage: x = polygen(ZZ, 'x')
|
2416
|
+
sage: K.<a> = NumberFieldTower([x^2 + x + 1, x^3 + x + 1])
|
2417
|
+
sage: K.disc()
|
2418
|
+
Traceback (most recent call last):
|
2419
|
+
...
|
2420
|
+
NotImplementedError: For a relative number field you must use
|
2421
|
+
relative_discriminant or absolute_discriminant as appropriate
|
2422
|
+
"""
|
2423
|
+
raise NotImplementedError("For a relative number field you must use relative_discriminant or absolute_discriminant as appropriate")
|
2424
|
+
|
2425
|
+
def order(self, *gens, **kwds):
|
2426
|
+
r"""
|
2427
|
+
Return the order with given ring generators in the maximal
|
2428
|
+
order of this number field.
|
2429
|
+
|
2430
|
+
INPUT:
|
2431
|
+
|
2432
|
+
- ``gens`` -- list of elements of ``self``; if no generators are given, just
|
2433
|
+
returns the cardinality of this number field (`\infty`) for consistency.
|
2434
|
+
- ``check_is_integral`` -- boolean (default: ``True``); whether to
|
2435
|
+
check that each generator is integral
|
2436
|
+
- ``check_rank`` -- boolean (default: ``True``); whether to check that
|
2437
|
+
the ring generated by ``gens`` is of full rank
|
2438
|
+
- ``allow_subfield`` -- boolean (default: ``False``); if ``True`` and
|
2439
|
+
the generators do not generate an order, i.e., they generate a
|
2440
|
+
subring of smaller rank, instead of raising an error, return an order
|
2441
|
+
in a smaller number field.
|
2442
|
+
|
2443
|
+
The ``check_is_integral`` and ``check_rank`` inputs must be given as
|
2444
|
+
explicit keyword arguments.
|
2445
|
+
|
2446
|
+
EXAMPLES::
|
2447
|
+
|
2448
|
+
sage: # needs fpylll sage.symbolic
|
2449
|
+
sage: P3.<a,b,c> = QQ[2^(1/2), 2^(1/3), 3^(1/2)]
|
2450
|
+
sage: R = P3.order([a,b,c]); R # not tested (83s, 2GB memory)
|
2451
|
+
Relative Order generated by
|
2452
|
+
[((-36372*sqrt3 + 371270)*a^2 + (-89082*sqrt3 + 384161)*a - 422504*sqrt3 - 46595)*sqrt2 + (303148*sqrt3 - 89080)*a^2 + (313664*sqrt3 - 218211)*a - 38053*sqrt3 - 1034933,
|
2453
|
+
((-65954*sqrt3 + 323491)*a^2 + (-110591*sqrt3 + 350011)*a - 351557*sqrt3 + 77507)*sqrt2 + (264138*sqrt3 - 161552)*a^2 + (285784*sqrt3 - 270906)*a + 63287*sqrt3 - 861151,
|
2454
|
+
((-89292*sqrt3 + 406648)*a^2 + (-137274*sqrt3 + 457033)*a - 449503*sqrt3 + 102712)*sqrt2 + (332036*sqrt3 - 218718)*a^2 + (373172*sqrt3 - 336261)*a + 83862*sqrt3 - 1101079,
|
2455
|
+
((-164204*sqrt3 + 553344)*a^2 + (-225111*sqrt3 + 646064)*a - 594724*sqrt3 + 280879)*sqrt2 + (451819*sqrt3 - 402227)*a^2 + (527524*sqrt3 - 551431)*a + 229346*sqrt3 - 1456815,
|
2456
|
+
((-73815*sqrt3 + 257278)*a^2 + (-102896*sqrt3 + 298046)*a - 277080*sqrt3 + 123726)*sqrt2 + (210072*sqrt3 - 180812)*a^2 + (243357*sqrt3 - 252052)*a + 101026*sqrt3 - 678718]
|
2457
|
+
in Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
|
2458
|
+
|
2459
|
+
sage: P2.<u,v> = QQ[2^(1/2), 2^(1/3)] # needs fpylll sage.symbolic
|
2460
|
+
sage: R = P2.order([u,v]); R # needs fpylll sage.symbolic
|
2461
|
+
Relative Order generated by [(6*a^2 - a - 1)*sqrt2 + 4*a^2 - 6*a - 9, sqrt2 - a]
|
2462
|
+
in Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
|
2463
|
+
|
2464
|
+
The base ring of an order in a relative extension is still `\ZZ`::
|
2465
|
+
|
2466
|
+
sage: R.base_ring() # needs fpylll sage.symbolic
|
2467
|
+
Integer Ring
|
2468
|
+
|
2469
|
+
One must give enough generators to generate a ring of finite index
|
2470
|
+
in the maximal order::
|
2471
|
+
|
2472
|
+
sage: P3.order([a, b]) # needs fpylll sage.symbolic
|
2473
|
+
Traceback (most recent call last):
|
2474
|
+
...
|
2475
|
+
ValueError: the rank of the span of gens is wrong
|
2476
|
+
"""
|
2477
|
+
if len(gens) == 0:
|
2478
|
+
return NumberField_generic.order(self)
|
2479
|
+
if len(gens) == 1 and isinstance(gens[0], (list, tuple)):
|
2480
|
+
gens = gens[0]
|
2481
|
+
gens = [self(x) for x in gens]
|
2482
|
+
return relative_order_from_ring_generators(gens, **kwds)
|
2483
|
+
|
2484
|
+
def is_free(self, proof=None):
|
2485
|
+
r"""
|
2486
|
+
Determine whether or not `L/K` is free.
|
2487
|
+
|
2488
|
+
(i.e. if `\mathcal{O}_L` is a free `\mathcal{O}_K`-module).
|
2489
|
+
|
2490
|
+
INPUT:
|
2491
|
+
|
2492
|
+
- ``proof`` -- (default: ``True``)
|
2493
|
+
|
2494
|
+
EXAMPLES::
|
2495
|
+
|
2496
|
+
sage: x = polygen(QQ)
|
2497
|
+
sage: K.<a> = NumberField(x^2 + 6)
|
2498
|
+
sage: x = polygen(K)
|
2499
|
+
sage: L.<b> = K.extension(x^2 + 3) # extend by x^2+3
|
2500
|
+
sage: L.is_free()
|
2501
|
+
False
|
2502
|
+
"""
|
2503
|
+
proof = proof_flag(proof)
|
2504
|
+
base_bnf = self._pari_base_bnf(proof)
|
2505
|
+
return base_bnf.rnfisfree(self.pari_relative_polynomial()) == 1
|
2506
|
+
|
2507
|
+
def _factor_univariate_polynomial(self, poly, **kwargs):
|
2508
|
+
"""
|
2509
|
+
Factorisation of univariate polynomials over relative number fields.
|
2510
|
+
|
2511
|
+
This is called by the ``factor`` method of univariate polynomials.
|
2512
|
+
|
2513
|
+
EXAMPLES::
|
2514
|
+
|
2515
|
+
sage: x = polygen(ZZ, 'x')
|
2516
|
+
sage: K.<i> = NumberField(x**2 + 1)
|
2517
|
+
sage: L.<sqrt2> = K.extension(x*x - 2)
|
2518
|
+
sage: x = polygen(L,'x')
|
2519
|
+
sage: factor(x**2+8) # indirect doctest
|
2520
|
+
(x + 2*i*sqrt2) * (x - 2*i*sqrt2)
|
2521
|
+
"""
|
2522
|
+
M = self.absolute_field('a')
|
2523
|
+
from_M, to_M = M.structure()
|
2524
|
+
g = M['x']([to_M(x) for x in poly.list()])
|
2525
|
+
F = g.factor()
|
2526
|
+
S = poly.parent()
|
2527
|
+
v = [(S([from_M(x) for x in f.list()]), e) for f, e in F]
|
2528
|
+
return Factorization(v, from_M(F.unit()))
|
2529
|
+
|
2530
|
+
def lift_to_base(self, element):
|
2531
|
+
"""
|
2532
|
+
Lift an element of this extension into the base field if possible,
|
2533
|
+
or raise a :exc:`ValueError` if it is not possible.
|
2534
|
+
|
2535
|
+
EXAMPLES::
|
2536
|
+
|
2537
|
+
sage: x = polygen(ZZ)
|
2538
|
+
sage: K.<a> = NumberField(x^3 - 2)
|
2539
|
+
sage: R.<y> = K[]
|
2540
|
+
sage: L.<b> = K.extension(y^2 - a)
|
2541
|
+
sage: L.lift_to_base(b^4)
|
2542
|
+
a^2
|
2543
|
+
sage: L.lift_to_base(b^6)
|
2544
|
+
2
|
2545
|
+
sage: L.lift_to_base(355/113)
|
2546
|
+
355/113
|
2547
|
+
sage: L.lift_to_base(b)
|
2548
|
+
Traceback (most recent call last):
|
2549
|
+
...
|
2550
|
+
ValueError: The element b is not in the base field
|
2551
|
+
|
2552
|
+
TESTS:
|
2553
|
+
|
2554
|
+
Number fields defined by non-monic and non-integral
|
2555
|
+
polynomials are supported (:issue:`252`)::
|
2556
|
+
|
2557
|
+
sage: R.<x> = QQ[]
|
2558
|
+
sage: K.<a> = NumberField(x^2 + 1/2)
|
2559
|
+
sage: L.<b> = K.extension(x^2 - a/2)
|
2560
|
+
sage: L.lift_to_base(b^2)
|
2561
|
+
1/2*a
|
2562
|
+
"""
|
2563
|
+
# Convert the element to a PARI polynomial with t_POLMOD
|
2564
|
+
# coefficients representing elements of the base field.
|
2565
|
+
r = self._pari_rnfeq()._eltabstorel_lift(self(element)._pari_polynomial('x'))
|
2566
|
+
# Lift the coefficients and call simplify() to make PARI check
|
2567
|
+
# which variables really appear in the resulting polynomial
|
2568
|
+
# (otherwise we always have a polynomial in two variables even
|
2569
|
+
# though not all variables actually occur).
|
2570
|
+
r = r.lift().simplify()
|
2571
|
+
|
2572
|
+
# Special case: check whether the result is simply an integer or rational
|
2573
|
+
if r.type() in ["t_INT", "t_FRAC"]:
|
2574
|
+
return self.base_field()(r)
|
2575
|
+
# Now we should have a polynomial in the variable y.
|
2576
|
+
# Otherwise we're not in the base field.
|
2577
|
+
if r.type() != "t_POL" or str(r.variable()) != 'y':
|
2578
|
+
raise ValueError("The element %s is not in the base field" % element)
|
2579
|
+
return self.base_field()(r, check=False)
|
2580
|
+
|
2581
|
+
def relativize(self, alpha, names):
|
2582
|
+
r"""
|
2583
|
+
Given an element in ``self`` or an embedding of a subfield into ``self``,
|
2584
|
+
return a relative number field `K` isomorphic to ``self`` that is relative
|
2585
|
+
over the absolute field `\QQ(\alpha)` or the domain of `\alpha`, along
|
2586
|
+
with isomorphisms from `K` to ``self`` and from ``self`` to `K`.
|
2587
|
+
|
2588
|
+
INPUT:
|
2589
|
+
|
2590
|
+
- ``alpha`` -- an element of ``self``, or an embedding of a subfield into ``self``
|
2591
|
+
- ``names`` -- name of generator for output field `K`
|
2592
|
+
|
2593
|
+
OUTPUT: `K` -- a relative number field
|
2594
|
+
|
2595
|
+
Also, ``K.structure()`` returns ``from_K`` and ``to_K``, where
|
2596
|
+
``from_K`` is an isomorphism from `K` to ``self`` and ``to_K`` is
|
2597
|
+
an isomorphism from ``self`` to `K`.
|
2598
|
+
|
2599
|
+
EXAMPLES::
|
2600
|
+
|
2601
|
+
sage: x = polygen(ZZ, 'x')
|
2602
|
+
sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
|
2603
|
+
Number Field in a with defining polynomial x^4 + 3 over its base field
|
2604
|
+
sage: L.<z,w> = K.relativize(a^2)
|
2605
|
+
sage: z^2
|
2606
|
+
z^2
|
2607
|
+
sage: w^2
|
2608
|
+
-3
|
2609
|
+
sage: L
|
2610
|
+
Number Field in z with defining polynomial
|
2611
|
+
x^4 + (-2*w + 4)*x^2 + 4*w + 1 over its base field
|
2612
|
+
sage: L.base_field()
|
2613
|
+
Number Field in w with defining polynomial x^2 + 3
|
2614
|
+
|
2615
|
+
Now suppose we have `K` below `L` below `M`::
|
2616
|
+
|
2617
|
+
sage: M = NumberField(x^8 + 2, 'a'); M
|
2618
|
+
Number Field in a with defining polynomial x^8 + 2
|
2619
|
+
sage: L, L_into_M, _ = M.subfields(4)[0]; L
|
2620
|
+
Number Field in a0 with defining polynomial x^4 + 2
|
2621
|
+
sage: K, K_into_L, _ = L.subfields(2)[0]; K
|
2622
|
+
Number Field in a0_0 with defining polynomial x^2 + 2
|
2623
|
+
sage: K_into_M = L_into_M * K_into_L
|
2624
|
+
|
2625
|
+
sage: L_over_K = L.relativize(K_into_L, 'c'); L_over_K
|
2626
|
+
Number Field in c with defining polynomial x^2 + a0_0 over its base field
|
2627
|
+
sage: L_over_K_to_L, L_to_L_over_K = L_over_K.structure()
|
2628
|
+
sage: M_over_L_over_K = M.relativize(L_into_M * L_over_K_to_L, 'd')
|
2629
|
+
sage: M_over_L_over_K
|
2630
|
+
Number Field in d with defining polynomial x^2 + c over its base field
|
2631
|
+
sage: M_over_L_over_K.base_field() is L_over_K
|
2632
|
+
True
|
2633
|
+
|
2634
|
+
Test relativizing a degree 6 field over its degree 2 and degree 3
|
2635
|
+
subfields, using both an explicit element::
|
2636
|
+
|
2637
|
+
sage: K.<a> = NumberField(x^6 + 2); K
|
2638
|
+
Number Field in a with defining polynomial x^6 + 2
|
2639
|
+
sage: K2, K2_into_K, _ = K.subfields(2)[0]; K2
|
2640
|
+
Number Field in a0 with defining polynomial x^2 + 2
|
2641
|
+
sage: K3, K3_into_K, _ = K.subfields(3)[0]; K3
|
2642
|
+
Number Field in a0 with defining polynomial x^3 - 2
|
2643
|
+
|
2644
|
+
Here we explicitly relativize over an element of K2 (not the
|
2645
|
+
generator)::
|
2646
|
+
|
2647
|
+
sage: L = K.relativize(K3_into_K, 'b'); L
|
2648
|
+
Number Field in b with defining polynomial x^2 + a0 over its base field
|
2649
|
+
sage: L_to_K, K_to_L = L.structure()
|
2650
|
+
sage: L_over_K2 = L.relativize(K_to_L(K2_into_K(K2.gen() + 1)), 'c'); L_over_K2
|
2651
|
+
Number Field in c0 with defining polynomial x^3 - c1 + 1 over its base field
|
2652
|
+
sage: L_over_K2.base_field()
|
2653
|
+
Number Field in c1 with defining polynomial x^2 - 2*x + 3
|
2654
|
+
|
2655
|
+
Here we use a morphism to preserve the base field information::
|
2656
|
+
|
2657
|
+
sage: K2_into_L = K_to_L * K2_into_K
|
2658
|
+
sage: L_over_K2 = L.relativize(K2_into_L, 'c'); L_over_K2
|
2659
|
+
Number Field in c with defining polynomial x^3 - a0 over its base field
|
2660
|
+
sage: L_over_K2.base_field() is K2
|
2661
|
+
True
|
2662
|
+
"""
|
2663
|
+
K = self.absolute_field('a')
|
2664
|
+
from_K, to_K = K.structure()
|
2665
|
+
|
2666
|
+
if isinstance(alpha, Map):
|
2667
|
+
# alpha is an embedding of a subfield into self; compose to get an
|
2668
|
+
# embedding of a subfield into the absolute field
|
2669
|
+
beta = to_K * alpha
|
2670
|
+
else:
|
2671
|
+
# alpha is an element coercible into self
|
2672
|
+
beta = to_K(alpha)
|
2673
|
+
|
2674
|
+
L = K.relativize(beta, names)
|
2675
|
+
return K.relativize(beta, names, structure=structure.RelativeFromRelative(L))
|
2676
|
+
|
2677
|
+
def uniformizer(self, P, others='positive'):
|
2678
|
+
"""
|
2679
|
+
Return an element of ``self`` with valuation 1 at the prime ideal `P`.
|
2680
|
+
|
2681
|
+
INPUT:
|
2682
|
+
|
2683
|
+
- ``self`` -- a number field
|
2684
|
+
|
2685
|
+
- ``P`` -- a prime ideal of ``self``
|
2686
|
+
|
2687
|
+
- ``others`` -- either ``'positive'`` (default), in which case the
|
2688
|
+
element will have nonnegative valuation at all other primes of
|
2689
|
+
``self``, or ``'negative'``, in which case the element will have
|
2690
|
+
nonpositive valuation at all other primes of ``self``
|
2691
|
+
|
2692
|
+
|
2693
|
+
.. NOTE::
|
2694
|
+
|
2695
|
+
When `P` is principal (e.g., always when ``self`` has class number
|
2696
|
+
one), the result may or may not be a generator of `P`!
|
2697
|
+
|
2698
|
+
EXAMPLES::
|
2699
|
+
|
2700
|
+
sage: x = polygen(ZZ, 'x')
|
2701
|
+
sage: K.<a, b> = NumberField([x^2 + 23, x^2 - 3])
|
2702
|
+
sage: P = K.prime_factors(5)[0]; P
|
2703
|
+
Fractional ideal (5, -1/2*a + b + 5/2)
|
2704
|
+
sage: u = K.uniformizer(P)
|
2705
|
+
sage: u.valuation(P)
|
2706
|
+
1
|
2707
|
+
sage: (P, 1) in K.factor(u)
|
2708
|
+
True
|
2709
|
+
"""
|
2710
|
+
if not isinstance(P, NumberFieldIdeal):
|
2711
|
+
P = self.ideal(P)
|
2712
|
+
if not P.is_maximal():
|
2713
|
+
raise ValueError("P (=%s) must be a nonzero prime." % P)
|
2714
|
+
abs = self.absolute_field('a')
|
2715
|
+
from_abs = abs.structure()[0]
|
2716
|
+
return from_abs(abs.uniformizer(P.absolute_ideal(), others=others))
|
2717
|
+
|
2718
|
+
|
2719
|
+
def NumberField_relative_v1(base_field, poly, name, latex_name, canonical_embedding=None):
|
2720
|
+
"""
|
2721
|
+
Used for unpickling old pickles.
|
2722
|
+
|
2723
|
+
EXAMPLES::
|
2724
|
+
|
2725
|
+
sage: from sage.rings.number_field.number_field_rel import NumberField_relative_v1
|
2726
|
+
sage: R.<x> = CyclotomicField(3)[]
|
2727
|
+
sage: NumberField_relative_v1(CyclotomicField(3), x^2 + 7, 'a', 'a')
|
2728
|
+
Number Field in a with defining polynomial x^2 + 7 over its base field
|
2729
|
+
"""
|
2730
|
+
return NumberField(poly.change_ring(base_field), name, check=False,
|
2731
|
+
embedding=canonical_embedding, latex_name=latex_name)
|
2732
|
+
|
2733
|
+
|
2734
|
+
NumberField_extension_v1 = NumberField_relative_v1 # historical reasons only
|