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,2981 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-flint
|
2
|
+
# sage.doctest: needs sage.libs.linbox
|
3
|
+
"""
|
4
|
+
Orders in number fields
|
5
|
+
|
6
|
+
EXAMPLES:
|
7
|
+
|
8
|
+
We define an absolute order::
|
9
|
+
|
10
|
+
sage: x = polygen(ZZ, 'x')
|
11
|
+
sage: K.<a> = NumberField(x^2 + 1); O = K.order(2*a)
|
12
|
+
sage: O.basis()
|
13
|
+
[1, 2*a]
|
14
|
+
|
15
|
+
We compute a basis for an order in a relative extension
|
16
|
+
that is generated by 2 elements::
|
17
|
+
|
18
|
+
sage: K.<a,b> = NumberField([x^2 + 1, x^2 - 3])
|
19
|
+
sage: O = K.order([3*a, 2*b])
|
20
|
+
sage: O.basis()
|
21
|
+
[1, 3*a - 2*b, -6*b*a + 6, 3*a]
|
22
|
+
|
23
|
+
We compute a maximal order of a degree 10 field::
|
24
|
+
|
25
|
+
sage: K.<a> = NumberField((x+1)^10 + 17)
|
26
|
+
sage: K.maximal_order()
|
27
|
+
Maximal Order generated by a in Number Field in a with defining polynomial
|
28
|
+
x^10 + 10*x^9 + 45*x^8 + 120*x^7 + 210*x^6 + 252*x^5 + 210*x^4 + 120*x^3 + 45*x^2 + 10*x + 18
|
29
|
+
|
30
|
+
We compute a suborder, which has index a power of 17 in the maximal order::
|
31
|
+
|
32
|
+
sage: O = K.order(17*a); O
|
33
|
+
Order generated by 17*a in Number Field in a with defining polynomial
|
34
|
+
x^10 + 10*x^9 + 45*x^8 + 120*x^7 + 210*x^6 + 252*x^5 + 210*x^4 + 120*x^3 + 45*x^2 + 10*x + 18
|
35
|
+
sage: m = O.index_in(K.maximal_order()); m
|
36
|
+
23453165165327788911665591944416226304630809183732482257
|
37
|
+
sage: factor(m)
|
38
|
+
17^45
|
39
|
+
|
40
|
+
AUTHORS:
|
41
|
+
|
42
|
+
- William Stein and Robert Bradshaw (2007-09): initial version
|
43
|
+
"""
|
44
|
+
# ****************************************************************************
|
45
|
+
# Copyright (C) 2007 Robert Bradshaw <robertwb@gmail.com>
|
46
|
+
# 2007-2009 William Stein <wstein@gmail.com>
|
47
|
+
# 2007-2017 David Roe <roed.math@gmail.com>
|
48
|
+
# 2008 Craig Citro <craigcitro@gmail.com>
|
49
|
+
# 2008 Alexandru Ghitza <aghitza@alum.mit.edu>
|
50
|
+
# 2008 Gary Furnish <bill@indirectproof.net>
|
51
|
+
# 2008-2009 Francis Clarke <F.Clarke@Swansea.ac.uk>
|
52
|
+
# 2008-2017 John Cremona <john.cremona@gmail.com>
|
53
|
+
# 2008 Mike Hansen <mhansen@gmail.com>
|
54
|
+
# 2008-2011 David Loeffler <D.Loeffler@dpmms.cam.ac.uk>
|
55
|
+
# 2009 Sebastian Pancratz <sage@pancratz.org>
|
56
|
+
# 2010-2016 Jeroen Demeyer <jdemeyer@cage.ugent.be>
|
57
|
+
# 2011 Martin Albrecht <martinralbrecht@googlemail.com>
|
58
|
+
# 2012 Vincent Delecroix <vincent.delecroix@u-bordeaux.fr>
|
59
|
+
# 2013-2020 Marc Mezzarobba <marc@mezzarobba.net>
|
60
|
+
# 2014 Wilfried Luebbe <wluebbe@gmail.com>
|
61
|
+
# 2014-2016 Peter Bruin <P.J.Bruin@math.leidenuniv.nl>
|
62
|
+
# 2014 Gonzalo Tornaría <tornaria@cmat.edu.uy>
|
63
|
+
# 2014-2018 Frédéric Chapoton <chapoton@unistra.fr>
|
64
|
+
# 2016 Marc Masdeu <marc.masdeu@gmail.com>
|
65
|
+
# 2017 Édouard Rousseau <edouard.rousseau@u-psud.fr>
|
66
|
+
# 2017-2022 Julian Rüth <julian.rueth@fsfe.org>
|
67
|
+
# 2018 Erik M. Bray <erik.bray@lri.fr>
|
68
|
+
# 2019-2021 Matthias Koeppe <mkoeppe@math.ucdavis.edu>
|
69
|
+
# 2019 Tuomas Tajakka <tuomas.tajakka@gmail.com>
|
70
|
+
# 2020 John H. Palmieri <jhpalmieri64@gmail.com>
|
71
|
+
# 2020 Thierry Monteil <sage@lma.metelu.net>
|
72
|
+
# 2021 Antonio Rojas <arojas@archlinux.org>
|
73
|
+
# 2021 Jonathan Kliem <jonathan.kliem@gmail.com>
|
74
|
+
#
|
75
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
76
|
+
# as published by the Free Software Foundation; either version 2 of
|
77
|
+
# the License, or (at your option) any later version.
|
78
|
+
# https://www.gnu.org/licenses/
|
79
|
+
# ****************************************************************************
|
80
|
+
|
81
|
+
from sage.categories.integral_domains import IntegralDomains
|
82
|
+
from sage.categories.noetherian_rings import NoetherianRings
|
83
|
+
from sage.misc.cachefunc import cached_method
|
84
|
+
from sage.structure.parent import Parent
|
85
|
+
from sage.structure.sequence import Sequence
|
86
|
+
from sage.rings.integer_ring import ZZ
|
87
|
+
import sage.rings.abc
|
88
|
+
from sage.structure.element import Element
|
89
|
+
from sage.structure.factory import UniqueFactory
|
90
|
+
from .number_field_element import OrderElement_absolute, OrderElement_relative
|
91
|
+
|
92
|
+
from .number_field_element_quadratic import OrderElement_quadratic
|
93
|
+
|
94
|
+
from sage.rings.monomials import monomials
|
95
|
+
|
96
|
+
|
97
|
+
def quadratic_order_class_number(disc):
|
98
|
+
r"""
|
99
|
+
Return the class number of the quadratic order of given discriminant.
|
100
|
+
|
101
|
+
EXAMPLES::
|
102
|
+
|
103
|
+
sage: from sage.rings.number_field.order import quadratic_order_class_number
|
104
|
+
sage: quadratic_order_class_number(-419)
|
105
|
+
9
|
106
|
+
sage: quadratic_order_class_number(60)
|
107
|
+
2
|
108
|
+
|
109
|
+
ALGORITHM: Either :pari:`qfbclassno` or :pari:`quadclassunit`,
|
110
|
+
depending on the size of the discriminant.
|
111
|
+
"""
|
112
|
+
from sage.libs.pari import pari
|
113
|
+
|
114
|
+
# cutoffs from PARI documentation
|
115
|
+
if disc < -10**25 or disc > 10**10:
|
116
|
+
h = pari.quadclassunit(disc)[0]
|
117
|
+
else:
|
118
|
+
h = pari.qfbclassno(disc)
|
119
|
+
return ZZ(h)
|
120
|
+
|
121
|
+
|
122
|
+
class OrderFactory(UniqueFactory):
|
123
|
+
r"""
|
124
|
+
Abstract base class for factories creating orders, such as
|
125
|
+
:class:`AbsoluteOrderFactory` and :class:`RelativeOrderFactory`.
|
126
|
+
|
127
|
+
TESTS::
|
128
|
+
|
129
|
+
sage: from sage.rings.number_field.order import AbsoluteOrder, OrderFactory
|
130
|
+
sage: isinstance(AbsoluteOrder, OrderFactory)
|
131
|
+
True
|
132
|
+
"""
|
133
|
+
|
134
|
+
def get_object(self, version, key, extra_args):
|
135
|
+
r"""
|
136
|
+
Create the order identified by ``key``.
|
137
|
+
|
138
|
+
This overrides the default implementation to update the maximality of
|
139
|
+
the order if it was explicitly specified.
|
140
|
+
|
141
|
+
EXAMPLES:
|
142
|
+
|
143
|
+
Even though orders are unique parents, this lets us update their
|
144
|
+
internal state when they are recreated with more additional
|
145
|
+
information available about them::
|
146
|
+
|
147
|
+
sage: x = polygen(ZZ, 'x')
|
148
|
+
sage: L.<a, b> = NumberField([x^2 - 1000003, x^2 - 5*1000099^2])
|
149
|
+
sage: O = L.maximal_order([2], assume_maximal=None)
|
150
|
+
|
151
|
+
sage: O._is_maximal_at(2)
|
152
|
+
True
|
153
|
+
sage: O._is_maximal_at(3) is None
|
154
|
+
True
|
155
|
+
|
156
|
+
sage: N = L.maximal_order([3], assume_maximal=None)
|
157
|
+
sage: N is O
|
158
|
+
True
|
159
|
+
sage: N._is_maximal_at(2)
|
160
|
+
True
|
161
|
+
sage: N._is_maximal_at(3)
|
162
|
+
True
|
163
|
+
"""
|
164
|
+
is_maximal = extra_args.pop("is_maximal", None)
|
165
|
+
is_maximal_at = extra_args.pop("is_maximal_at", {})
|
166
|
+
|
167
|
+
order = super().get_object(version, key, extra_args)
|
168
|
+
|
169
|
+
# Add assumptions about maximality to the order (potentially creating
|
170
|
+
# an independent non-unique clone to support legacy use cases.)
|
171
|
+
order = order._assume_maximal(is_maximal)
|
172
|
+
for p, v in is_maximal_at.items():
|
173
|
+
order = order._assume_maximal(p=p, is_maximal=v)
|
174
|
+
|
175
|
+
return order
|
176
|
+
|
177
|
+
|
178
|
+
class AbsoluteOrderFactory(OrderFactory):
|
179
|
+
r"""
|
180
|
+
An order in an (absolute) number field.
|
181
|
+
|
182
|
+
EXAMPLES::
|
183
|
+
|
184
|
+
sage: x = polygen(ZZ, 'x')
|
185
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
186
|
+
sage: K.order(i)
|
187
|
+
Gaussian Integers generated by i in Number Field in i with defining polynomial x^2 + 1
|
188
|
+
"""
|
189
|
+
|
190
|
+
def create_key_and_extra_args(self, K, module_rep, is_maximal=None, check=True, is_maximal_at=()):
|
191
|
+
r"""
|
192
|
+
Return normalized arguments to create an absolute order.
|
193
|
+
|
194
|
+
TESTS:
|
195
|
+
|
196
|
+
In particular, this normalizes the data that is used when pickling orders::
|
197
|
+
|
198
|
+
sage: x = polygen(ZZ, 'x')
|
199
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
200
|
+
sage: OK = K.order(i)
|
201
|
+
sage: OK._factory_data
|
202
|
+
(<sage.rings.number_field.order.AbsoluteOrderFactory object at 0x...>,
|
203
|
+
(...),
|
204
|
+
(Number Field in i with defining polynomial x^2 + 1,
|
205
|
+
Free module of degree 2 and rank 2 over Integer Ring
|
206
|
+
Echelon basis matrix:
|
207
|
+
[1 0]
|
208
|
+
[0 1]),
|
209
|
+
{})
|
210
|
+
|
211
|
+
Note how the above is lacking the ``is_maximal`` and ``is_maximal_at``
|
212
|
+
keywords. These are stripped by :meth:`OrderFactory.get_object` and
|
213
|
+
then put back in by :meth:`reduce_data`.
|
214
|
+
"""
|
215
|
+
if check:
|
216
|
+
if not K.is_absolute():
|
217
|
+
raise ValueError("AbsoluteOrder must be called with an absolute number field")
|
218
|
+
|
219
|
+
_, _, to_v = K.vector_space()
|
220
|
+
if to_v(1) not in module_rep:
|
221
|
+
raise ValueError("1 is not in the span of the module, hence not an order")
|
222
|
+
|
223
|
+
if module_rep.rank() != K.degree():
|
224
|
+
raise ValueError("the module defining an absolute order must have full rank")
|
225
|
+
|
226
|
+
return (K, module_rep), {"is_maximal": is_maximal, "is_maximal_at": {p: True for p in is_maximal_at}}
|
227
|
+
|
228
|
+
def create_object(self, version, key, is_maximal=None, is_maximal_at=()):
|
229
|
+
r"""
|
230
|
+
Create an absolute order.
|
231
|
+
|
232
|
+
TESTS:
|
233
|
+
|
234
|
+
This method is also used during unpickling::
|
235
|
+
|
236
|
+
sage: x = polygen(ZZ, 'x')
|
237
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
238
|
+
sage: OK = K.order(i)
|
239
|
+
sage: loads(dumps(OK)) is OK
|
240
|
+
True
|
241
|
+
"""
|
242
|
+
K, module_rep = key
|
243
|
+
|
244
|
+
# We intentionally ignore is_maximal and is_maximal_at.
|
245
|
+
# OrderFactory.get_object() sets these for us.
|
246
|
+
return Order_absolute(K, module_rep)
|
247
|
+
|
248
|
+
def reduce_data(self, order):
|
249
|
+
r"""
|
250
|
+
Return the data that can be used to pickle an order created by this factory.
|
251
|
+
|
252
|
+
This overrides the default implementation to update the latest
|
253
|
+
knowledge about primes at which the order is maximal.
|
254
|
+
|
255
|
+
EXAMPLES:
|
256
|
+
|
257
|
+
This also works for relative orders since they are wrapping absolute
|
258
|
+
orders::
|
259
|
+
|
260
|
+
sage: x = polygen(ZZ, 'x')
|
261
|
+
sage: L.<a, b> = NumberField([x^2 - 1000003, x^2 - 5*1000099^2])
|
262
|
+
sage: O = L.maximal_order([5], assume_maximal=None)
|
263
|
+
|
264
|
+
sage: s = dumps(O)
|
265
|
+
sage: loads(s) is O
|
266
|
+
True
|
267
|
+
|
268
|
+
sage: N = L.maximal_order([7], assume_maximal=None)
|
269
|
+
sage: dumps(N) == s
|
270
|
+
False
|
271
|
+
|
272
|
+
sage: loads(dumps(N)) is O
|
273
|
+
True
|
274
|
+
"""
|
275
|
+
reduction = super().reduce_data(order)
|
276
|
+
reduction[1][3]["is_maximal"] = order._is_maximal()
|
277
|
+
reduction[1][3]["is_maximal_at"] = order._is_maximal_at()
|
278
|
+
return reduction
|
279
|
+
|
280
|
+
|
281
|
+
AbsoluteOrder = AbsoluteOrderFactory("sage.rings.number_field.order.AbsoluteOrder")
|
282
|
+
|
283
|
+
|
284
|
+
class RelativeOrderFactory(OrderFactory):
|
285
|
+
r"""
|
286
|
+
An order in a relative number field extension.
|
287
|
+
|
288
|
+
EXAMPLES::
|
289
|
+
|
290
|
+
sage: x = polygen(ZZ, 'x')
|
291
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
292
|
+
sage: R.<j> = K[]
|
293
|
+
sage: L.<j> = K.extension(j^2 - 2)
|
294
|
+
sage: L.order([i, j])
|
295
|
+
Relative Order generated by [-i*j + 1, -i] in
|
296
|
+
Number Field in j with defining polynomial j^2 - 2 over its base field
|
297
|
+
"""
|
298
|
+
|
299
|
+
def create_key_and_extra_args(self, K, absolute_order, is_maximal=None, check=True, is_maximal_at=()):
|
300
|
+
r"""
|
301
|
+
Return normalized arguments to create a relative order.
|
302
|
+
|
303
|
+
TESTS:
|
304
|
+
|
305
|
+
In particular, this normalizes the data that is used when pickling orders::
|
306
|
+
|
307
|
+
sage: x = polygen(ZZ, 'x')
|
308
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
309
|
+
sage: R.<j> = K[]
|
310
|
+
sage: L.<j> = K.extension(j^2 - 2)
|
311
|
+
sage: OK = L.order([i, j])
|
312
|
+
sage: OK._factory_data
|
313
|
+
(<sage.rings.number_field.order.RelativeOrderFactory object at 0x...>,
|
314
|
+
(...),
|
315
|
+
(Number Field in j with defining polynomial j^2 - 2 over its base field,
|
316
|
+
Order generated by [1/2*z^2 + 1/2, 1/6*z^3 + 1/6*z] in Number Field in z with defining polynomial x^4 - 2*x^2 + 9),
|
317
|
+
{})
|
318
|
+
|
319
|
+
Note how the above is lacking the ``is_maximal`` and ``is_maximal_at``
|
320
|
+
keywords. These are stripped by :meth:`OrderFactory.get_object`. Since
|
321
|
+
they are applied to the underlying absolute order, they then get
|
322
|
+
pickled when the underlying order is pickled.
|
323
|
+
"""
|
324
|
+
return (K, absolute_order), {"is_maximal": is_maximal, "is_maximal_at": {p: True for p in is_maximal_at}}
|
325
|
+
|
326
|
+
def create_object(self, version, key, is_maximal=None, is_maximal_at=()):
|
327
|
+
r"""
|
328
|
+
Create a relative order.
|
329
|
+
|
330
|
+
TESTS:
|
331
|
+
|
332
|
+
This method is also used during unpickling::
|
333
|
+
|
334
|
+
sage: x = polygen(ZZ, 'x')
|
335
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
336
|
+
sage: R.<j> = K[]
|
337
|
+
sage: L.<j> = K.extension(j^2 - 2)
|
338
|
+
sage: OK = L.order([i, j])
|
339
|
+
sage: loads(dumps(OK)) is OK
|
340
|
+
True
|
341
|
+
"""
|
342
|
+
K, absolute_order = key
|
343
|
+
|
344
|
+
# We intentionally ignore is_maximal and is_maximal_at.
|
345
|
+
# OrderFactory.get_object() sets these for us.
|
346
|
+
return Order_relative(K, absolute_order)
|
347
|
+
|
348
|
+
|
349
|
+
RelativeOrder = RelativeOrderFactory("sage.rings.number_field.order.RelativeOrder")
|
350
|
+
|
351
|
+
|
352
|
+
def is_NumberFieldOrder(R):
|
353
|
+
r"""
|
354
|
+
Return ``True`` if `R` is either an order in a number field or is the ring `\ZZ` of integers.
|
355
|
+
|
356
|
+
EXAMPLES::
|
357
|
+
|
358
|
+
sage: from sage.rings.number_field.order import is_NumberFieldOrder
|
359
|
+
sage: x = polygen(ZZ, 'x')
|
360
|
+
sage: is_NumberFieldOrder(NumberField(x^2 + 1, 'a').maximal_order())
|
361
|
+
doctest:warning...
|
362
|
+
DeprecationWarning: The function is_NumberFieldOrder is deprecated;
|
363
|
+
use 'isinstance(..., sage.rings.abc.Order) or ... == ZZ' instead.
|
364
|
+
See https://github.com/sagemath/sage/issues/38124 for details.
|
365
|
+
True
|
366
|
+
sage: is_NumberFieldOrder(ZZ)
|
367
|
+
True
|
368
|
+
sage: is_NumberFieldOrder(QQ)
|
369
|
+
False
|
370
|
+
sage: is_NumberFieldOrder(45)
|
371
|
+
False
|
372
|
+
"""
|
373
|
+
from sage.misc.superseded import deprecation
|
374
|
+
deprecation(38124,
|
375
|
+
"The function is_NumberFieldOrder is deprecated; "
|
376
|
+
"use 'isinstance(..., sage.rings.abc.Order) or ... == ZZ' instead.")
|
377
|
+
return isinstance(R, Order) or R == ZZ
|
378
|
+
|
379
|
+
|
380
|
+
def EquationOrder(f, names, **kwds):
|
381
|
+
r"""
|
382
|
+
Return the equation order generated by a root of the irreducible
|
383
|
+
polynomial `f` or list ``f`` of polynomials (to construct a relative
|
384
|
+
equation order).
|
385
|
+
|
386
|
+
IMPORTANT: Note that the generators of the returned order need
|
387
|
+
*not* be roots of `f`, since the generators of an order are -- in
|
388
|
+
Sage -- module generators.
|
389
|
+
|
390
|
+
EXAMPLES::
|
391
|
+
|
392
|
+
sage: x = polygen(ZZ, 'x')
|
393
|
+
sage: O.<a,b> = EquationOrder([x^2 + 1, x^2 + 2])
|
394
|
+
sage: O
|
395
|
+
Relative Order generated by [-b*a - 1, -3*a + 2*b] in
|
396
|
+
Number Field in a with defining polynomial x^2 + 1 over its base field
|
397
|
+
sage: O.0
|
398
|
+
-b*a - 1
|
399
|
+
sage: O.1
|
400
|
+
-3*a + 2*b
|
401
|
+
|
402
|
+
Of course the input polynomial must be integral::
|
403
|
+
|
404
|
+
sage: R = EquationOrder(x^3 + x + 1/3, 'alpha'); R
|
405
|
+
Traceback (most recent call last):
|
406
|
+
...
|
407
|
+
ValueError: each generator must be integral
|
408
|
+
|
409
|
+
sage: R = EquationOrder([x^3 + x + 1, x^2 + 1/2], 'alpha'); R
|
410
|
+
Traceback (most recent call last):
|
411
|
+
...
|
412
|
+
ValueError: each generator must be integral
|
413
|
+
"""
|
414
|
+
from .number_field import NumberField
|
415
|
+
R = ZZ['x']
|
416
|
+
if isinstance(f, (list, tuple)):
|
417
|
+
for g in f:
|
418
|
+
try:
|
419
|
+
R(g)
|
420
|
+
except TypeError:
|
421
|
+
raise ValueError('each generator must be integral')
|
422
|
+
else:
|
423
|
+
try:
|
424
|
+
R(f)
|
425
|
+
except TypeError:
|
426
|
+
raise ValueError('each generator must be integral')
|
427
|
+
|
428
|
+
K = NumberField(f, names=names, **kwds)
|
429
|
+
return K.order(K.gens())
|
430
|
+
|
431
|
+
|
432
|
+
class Order(Parent, sage.rings.abc.Order):
|
433
|
+
r"""
|
434
|
+
An order in a number field.
|
435
|
+
|
436
|
+
An order is a subring of the number field that has `\ZZ`-rank equal
|
437
|
+
to the degree of the number field over `\QQ`.
|
438
|
+
|
439
|
+
EXAMPLES::
|
440
|
+
|
441
|
+
sage: x = polygen(ZZ, 'x')
|
442
|
+
sage: K.<theta> = NumberField(x^4 + x + 17)
|
443
|
+
sage: K.maximal_order()
|
444
|
+
Maximal Order generated by theta in Number Field in theta with defining polynomial x^4 + x + 17
|
445
|
+
sage: R = K.order(17*theta); R
|
446
|
+
Order generated by 17*theta in Number Field in theta with defining polynomial x^4 + x + 17
|
447
|
+
sage: R.basis()
|
448
|
+
[1, 17*theta, 289*theta^2, 4913*theta^3]
|
449
|
+
sage: R = K.order(17*theta, 13*theta); R
|
450
|
+
Maximal Order generated by theta in Number Field in theta with defining polynomial x^4 + x + 17
|
451
|
+
sage: R.basis()
|
452
|
+
[1, theta, theta^2, theta^3]
|
453
|
+
sage: R = K.order([34*theta, 17*theta + 17]); R
|
454
|
+
Order generated by 17*theta in Number Field in theta with defining polynomial x^4 + x + 17
|
455
|
+
sage: K.<b> = NumberField(x^4 + x^2 + 2)
|
456
|
+
sage: (b^2).charpoly().factor()
|
457
|
+
(x^2 + x + 2)^2
|
458
|
+
sage: K.order(b^2)
|
459
|
+
Traceback (most recent call last):
|
460
|
+
...
|
461
|
+
ValueError: the rank of the span of gens is wrong
|
462
|
+
|
463
|
+
Orders are always Noetherian::
|
464
|
+
|
465
|
+
sage: x = polygen(ZZ, 'x')
|
466
|
+
sage: L.<alpha> = NumberField(x**4 - x**2 + 7)
|
467
|
+
sage: O = L.maximal_order() ; O.is_noetherian()
|
468
|
+
True
|
469
|
+
sage: E.<w> = NumberField(x^2 - x + 2)
|
470
|
+
sage: OE = E.ring_of_integers(); OE.is_noetherian()
|
471
|
+
True
|
472
|
+
"""
|
473
|
+
|
474
|
+
def __init__(self, K):
|
475
|
+
"""
|
476
|
+
This is called when creating an order to set the ambient field.
|
477
|
+
|
478
|
+
EXAMPLES::
|
479
|
+
|
480
|
+
sage: k = CyclotomicField(5)
|
481
|
+
sage: k.maximal_order()
|
482
|
+
Maximal Order generated by zeta5 in Cyclotomic Field of order 5 and degree 4
|
483
|
+
|
484
|
+
TESTS::
|
485
|
+
|
486
|
+
sage: x = polygen(ZZ, 'x')
|
487
|
+
sage: k.<alg> = NumberField(x^7 + 3*x + 1, embedding=CC(0,1))
|
488
|
+
sage: O = k.order(alg)
|
489
|
+
sage: ordelt = O(alg)
|
490
|
+
sage: CC(ordelt)
|
491
|
+
0.0535229072603327 + 1.20934552493846*I
|
492
|
+
"""
|
493
|
+
self._K = K
|
494
|
+
cat = IntegralDomains() & NoetherianRings()
|
495
|
+
Parent.__init__(self, base=ZZ, names=K.variable_names(),
|
496
|
+
normalize=False, category=cat)
|
497
|
+
self._populate_coercion_lists_(embedding=self.number_field())
|
498
|
+
if self.absolute_degree() == 2:
|
499
|
+
self.is_maximal() # cache
|
500
|
+
|
501
|
+
def fractional_ideal(self, *args, **kwds):
|
502
|
+
"""
|
503
|
+
Return the fractional ideal of the maximal order with given
|
504
|
+
generators.
|
505
|
+
|
506
|
+
EXAMPLES::
|
507
|
+
|
508
|
+
sage: x = polygen(ZZ, 'x')
|
509
|
+
sage: K.<a> = NumberField(x^2 + 2)
|
510
|
+
sage: R = K.maximal_order()
|
511
|
+
sage: R.fractional_ideal(2/3 + 7*a, a)
|
512
|
+
Fractional ideal (1/3*a)
|
513
|
+
"""
|
514
|
+
return self.number_field().fractional_ideal(*args, **kwds)
|
515
|
+
|
516
|
+
def ideal(self, *args, **kwds):
|
517
|
+
"""
|
518
|
+
Return the integral ideal with given generators.
|
519
|
+
|
520
|
+
.. NOTE::
|
521
|
+
|
522
|
+
This method constructs an ideal of this (not necessarily maximal) order.
|
523
|
+
To construct a fractional ideal in the ambient number field, use
|
524
|
+
:meth:`~sage.rings.number_field.number_field.NumberField_generic.fractional_ideal`.
|
525
|
+
|
526
|
+
EXAMPLES::
|
527
|
+
|
528
|
+
sage: x = polygen(ZZ, 'x')
|
529
|
+
sage: K.<a> = NumberField(x^2 + 7)
|
530
|
+
sage: R = K.maximal_order()
|
531
|
+
sage: R.ideal([7*a, 77 + 28*a])
|
532
|
+
Ideal (7/2*a + 7/2, 7*a) of Maximal Order generated by 1/2*a + 1/2 in Number Field in a with defining polynomial x^2 + 7
|
533
|
+
sage: R = K.order(4*a)
|
534
|
+
sage: R.ideal(8)
|
535
|
+
Ideal (8, 32*a) of Order of conductor 8 generated by 4*a
|
536
|
+
in Number Field in a with defining polynomial x^2 + 7
|
537
|
+
|
538
|
+
This function is called implicitly below::
|
539
|
+
|
540
|
+
sage: R = EquationOrder(x^2 + 2, 'a'); R
|
541
|
+
Maximal Order generated by a in Number Field in a with defining polynomial x^2 + 2
|
542
|
+
sage: (3,15)*R
|
543
|
+
Ideal (3, 3*a) of Maximal Order generated by a in Number Field in a with defining polynomial x^2 + 2
|
544
|
+
|
545
|
+
The zero ideal is handled properly::
|
546
|
+
|
547
|
+
sage: R.ideal(0)
|
548
|
+
Ideal (0) of Maximal Order generated by a in Number Field in a with defining polynomial x^2 + 2
|
549
|
+
"""
|
550
|
+
# these keyword arguments are ignored since there used to be optional
|
551
|
+
# arguments with these names for controlling deprecated/future behavior;
|
552
|
+
# see #34806 and #35762
|
553
|
+
if 'warn' in kwds:
|
554
|
+
del kwds['warn']
|
555
|
+
if 'future' in kwds:
|
556
|
+
del kwds['future']
|
557
|
+
from sage.rings.number_field.order_ideal import NumberFieldOrderIdeal
|
558
|
+
return NumberFieldOrderIdeal(self, *args, **kwds)
|
559
|
+
|
560
|
+
def _coerce_map_from_(self, R):
|
561
|
+
"""
|
562
|
+
Orders currently only have coerce maps from the integers.
|
563
|
+
|
564
|
+
EXAMPLES::
|
565
|
+
|
566
|
+
sage: x = polygen(ZZ, 'x')
|
567
|
+
sage: k.<a> = NumberField(x^2 + 5077)
|
568
|
+
sage: Ok = k.maximal_order()
|
569
|
+
sage: Ok.has_coerce_map_from(k) #indirect doctest
|
570
|
+
False
|
571
|
+
sage: Ok.has_coerce_map_from(ZZ)
|
572
|
+
True
|
573
|
+
"""
|
574
|
+
return R is ZZ or R is int
|
575
|
+
|
576
|
+
def __mul__(self, right):
|
577
|
+
"""
|
578
|
+
Create an ideal in this order using the syntax ``O * gens``.
|
579
|
+
|
580
|
+
EXAMPLES::
|
581
|
+
|
582
|
+
sage: x = polygen(ZZ, 'x')
|
583
|
+
sage: k.<a> = NumberField(x^2 + 5077); G = k.class_group(); G
|
584
|
+
Class group of order 22 with structure C22 of Number Field in a with defining polynomial x^2 + 5077
|
585
|
+
sage: G.0 ^ -9
|
586
|
+
Fractional ideal class (43, a + 13)
|
587
|
+
sage: Ok = k.maximal_order(); Ok
|
588
|
+
Maximal Order generated by a in Number Field in a with defining polynomial x^2 + 5077
|
589
|
+
sage: Ok * (11, a + 7)
|
590
|
+
Ideal (8*a + 1, 11*a) of Maximal Order generated by a in Number Field in a with defining polynomial x^2 + 5077
|
591
|
+
sage: (11, a + 7) * Ok
|
592
|
+
Ideal (8*a + 1, 11*a) of Maximal Order generated by a in Number Field in a with defining polynomial x^2 + 5077
|
593
|
+
"""
|
594
|
+
return self.ideal(right)
|
595
|
+
|
596
|
+
def __rmul__(self, left):
|
597
|
+
"""
|
598
|
+
Create an ideal in this order using the syntax ``gens * O``.
|
599
|
+
|
600
|
+
EXAMPLES::
|
601
|
+
|
602
|
+
sage: x = polygen(ZZ, 'x')
|
603
|
+
sage: k.<a> = NumberField(x^2 + 431); G = k.class_group(); G
|
604
|
+
Class group of order 21 with structure C21 of Number Field in a with defining polynomial x^2 + 431
|
605
|
+
sage: G.0 # random output
|
606
|
+
Fractional ideal class (6, 1/2*a + 11/2)
|
607
|
+
sage: Ok = k.maximal_order(); Ok
|
608
|
+
Maximal Order generated by 1/2*a + 1/2 in Number Field in a with defining polynomial x^2 + 431
|
609
|
+
sage: (6, 1/2*a + 11/2)*Ok # random output
|
610
|
+
Fractional ideal (6, 1/2*a + 11/2)
|
611
|
+
sage: 17*Ok
|
612
|
+
Ideal (17/2*a + 17/2, 17*a) of Maximal Order generated by 1/2*a + 1/2 in Number Field in a with defining polynomial x^2 + 431
|
613
|
+
"""
|
614
|
+
return self.ideal(left)
|
615
|
+
|
616
|
+
def is_field(self, proof=True):
|
617
|
+
r"""
|
618
|
+
Return ``False`` (because an order is never a field).
|
619
|
+
|
620
|
+
EXAMPLES::
|
621
|
+
|
622
|
+
sage: x = polygen(ZZ, 'x')
|
623
|
+
sage: L.<alpha> = NumberField(x**4 - x**2 + 7)
|
624
|
+
sage: O = L.maximal_order() ; O.is_field()
|
625
|
+
False
|
626
|
+
sage: CyclotomicField(12).ring_of_integers().is_field()
|
627
|
+
False
|
628
|
+
"""
|
629
|
+
return False
|
630
|
+
|
631
|
+
def is_integrally_closed(self) -> bool:
|
632
|
+
r"""
|
633
|
+
Return whether this ring is integrally closed.
|
634
|
+
|
635
|
+
This is true if and only if it is equal
|
636
|
+
to the maximal order.
|
637
|
+
|
638
|
+
EXAMPLES::
|
639
|
+
|
640
|
+
sage: x = polygen(ZZ, 'x')
|
641
|
+
sage: K.<a> = NumberField(x^2 + 189*x + 394)
|
642
|
+
sage: R = K.order(2*a)
|
643
|
+
sage: R.is_integrally_closed()
|
644
|
+
False
|
645
|
+
sage: R
|
646
|
+
Order of conductor 2 generated by 2*a in Number Field in a with defining polynomial x^2 + 189*x + 394
|
647
|
+
sage: S = K.maximal_order(); S
|
648
|
+
Maximal Order generated by a in Number Field in a with defining polynomial x^2 + 189*x + 394
|
649
|
+
sage: S.is_integrally_closed()
|
650
|
+
True
|
651
|
+
"""
|
652
|
+
return self.is_maximal()
|
653
|
+
|
654
|
+
def krull_dimension(self):
|
655
|
+
r"""
|
656
|
+
Return the Krull dimension of this order, which is 1.
|
657
|
+
|
658
|
+
EXAMPLES::
|
659
|
+
|
660
|
+
sage: K.<a> = QuadraticField(5)
|
661
|
+
sage: OK = K.maximal_order()
|
662
|
+
sage: OK.krull_dimension()
|
663
|
+
1
|
664
|
+
sage: O2 = K.order(2*a)
|
665
|
+
sage: O2.krull_dimension()
|
666
|
+
1
|
667
|
+
"""
|
668
|
+
return ZZ.one()
|
669
|
+
|
670
|
+
def integral_closure(self):
|
671
|
+
r"""
|
672
|
+
Return the integral closure of this order.
|
673
|
+
|
674
|
+
EXAMPLES::
|
675
|
+
|
676
|
+
sage: K.<a> = QuadraticField(5)
|
677
|
+
sage: O2 = K.order(2*a); O2
|
678
|
+
Order of conductor 4 generated by 2*a in Number Field in a
|
679
|
+
with defining polynomial x^2 - 5 with a = 2.236067977499790?
|
680
|
+
sage: O2.integral_closure()
|
681
|
+
Maximal Order generated by 1/2*a + 1/2 in Number Field in a
|
682
|
+
with defining polynomial x^2 - 5 with a = 2.236067977499790?
|
683
|
+
sage: OK = K.maximal_order()
|
684
|
+
sage: OK is OK.integral_closure()
|
685
|
+
True
|
686
|
+
"""
|
687
|
+
if self.is_maximal():
|
688
|
+
return self
|
689
|
+
else:
|
690
|
+
return self.number_field().maximal_order()
|
691
|
+
|
692
|
+
def gen(self, i):
|
693
|
+
r"""
|
694
|
+
Return `i`-th module generator of this order.
|
695
|
+
|
696
|
+
EXAMPLES::
|
697
|
+
|
698
|
+
sage: x = polygen(ZZ, 'x')
|
699
|
+
sage: K.<c> = NumberField(x^3 + 2*x + 17)
|
700
|
+
sage: O = K.maximal_order(); O
|
701
|
+
Maximal Order generated by c in Number Field in c with defining polynomial x^3 + 2*x + 17
|
702
|
+
sage: O.basis()
|
703
|
+
[1, c, c^2]
|
704
|
+
sage: O.gen(1)
|
705
|
+
c
|
706
|
+
sage: O.gen(2)
|
707
|
+
c^2
|
708
|
+
sage: O.gen(5)
|
709
|
+
Traceback (most recent call last):
|
710
|
+
...
|
711
|
+
IndexError: no 5th generator
|
712
|
+
sage: O.gen(-1)
|
713
|
+
Traceback (most recent call last):
|
714
|
+
...
|
715
|
+
IndexError: no -1th generator
|
716
|
+
"""
|
717
|
+
b = self.basis()
|
718
|
+
if i < 0 or i >= len(b):
|
719
|
+
raise IndexError("no %sth generator" % i)
|
720
|
+
return self.basis()[i]
|
721
|
+
|
722
|
+
def ngens(self):
|
723
|
+
r"""
|
724
|
+
Return the number of module generators of this order.
|
725
|
+
|
726
|
+
EXAMPLES::
|
727
|
+
|
728
|
+
sage: x = polygen(ZZ, 'x')
|
729
|
+
sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
|
730
|
+
sage: O = K.maximal_order()
|
731
|
+
sage: O.ngens()
|
732
|
+
3
|
733
|
+
"""
|
734
|
+
return self.absolute_degree()
|
735
|
+
|
736
|
+
def gens(self) -> tuple:
|
737
|
+
"""
|
738
|
+
Return the generators as a tuple.
|
739
|
+
|
740
|
+
EXAMPLES::
|
741
|
+
|
742
|
+
sage: x = polygen(ZZ, 'x')
|
743
|
+
sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
|
744
|
+
sage: O = K.maximal_order()
|
745
|
+
sage: O.gens()
|
746
|
+
(1, 1/2*a^2 + 1/2*a, a^2)
|
747
|
+
"""
|
748
|
+
return tuple(self.gen(i) for i in range(self.absolute_degree()))
|
749
|
+
|
750
|
+
def basis(self): # this must be defined in derived class
|
751
|
+
r"""
|
752
|
+
Return a basis over `\ZZ` of this order.
|
753
|
+
|
754
|
+
EXAMPLES::
|
755
|
+
|
756
|
+
sage: x = polygen(ZZ, 'x')
|
757
|
+
sage: K.<a> = NumberField(x^3 + x^2 - 16*x + 16)
|
758
|
+
sage: O = K.maximal_order(); O
|
759
|
+
Maximal Order generated by 1/4*a^2 + 1/4*a in Number Field in a with defining polynomial x^3 + x^2 - 16*x + 16
|
760
|
+
sage: O.basis()
|
761
|
+
[1, 1/4*a^2 + 1/4*a, a^2]
|
762
|
+
"""
|
763
|
+
raise NotImplementedError('child classes must implement')
|
764
|
+
|
765
|
+
def coordinates(self, x):
|
766
|
+
r"""
|
767
|
+
Return the coordinate vector of `x` with respect to this order.
|
768
|
+
|
769
|
+
INPUT:
|
770
|
+
|
771
|
+
- ``x`` -- an element of the number field of this order
|
772
|
+
|
773
|
+
OUTPUT:
|
774
|
+
|
775
|
+
A vector of length `n` (the degree of the field) giving
|
776
|
+
the coordinates of `x` with respect to the integral basis
|
777
|
+
of the order. In general this will be a vector of
|
778
|
+
rationals; it will consist of integers if and only if `x`
|
779
|
+
is in the order.
|
780
|
+
|
781
|
+
AUTHOR: John Cremona 2008-11-15
|
782
|
+
|
783
|
+
ALGORITHM:
|
784
|
+
|
785
|
+
Uses linear algebra. The change-of-basis matrix is
|
786
|
+
cached. Provides simpler implementations for
|
787
|
+
:meth:`_contains_`, :meth:`is_integral` and :meth:`smallest_integer`.
|
788
|
+
|
789
|
+
EXAMPLES::
|
790
|
+
|
791
|
+
sage: K.<i> = QuadraticField(-1)
|
792
|
+
sage: OK = K.ring_of_integers()
|
793
|
+
sage: OK_basis = OK.basis(); OK_basis
|
794
|
+
[1, i]
|
795
|
+
sage: a = 23-14*i
|
796
|
+
sage: acoords = OK.coordinates(a); acoords
|
797
|
+
(23, -14)
|
798
|
+
sage: sum([OK_basis[j]*acoords[j] for j in range(2)]) == a
|
799
|
+
True
|
800
|
+
sage: OK.coordinates((120+340*i)/8)
|
801
|
+
(15, 85/2)
|
802
|
+
|
803
|
+
sage: O = K.order(3*i)
|
804
|
+
sage: O.is_maximal()
|
805
|
+
False
|
806
|
+
sage: O.index_in(OK)
|
807
|
+
3
|
808
|
+
sage: acoords = O.coordinates(a); acoords
|
809
|
+
(23, -14/3)
|
810
|
+
sage: sum([O.basis()[j]*acoords[j] for j in range(2)]) == a
|
811
|
+
True
|
812
|
+
"""
|
813
|
+
K = self.number_field()
|
814
|
+
V, from_V, to_V = K.absolute_vector_space()
|
815
|
+
|
816
|
+
try:
|
817
|
+
M = self.__basis_matrix_inverse
|
818
|
+
except AttributeError:
|
819
|
+
from sage.matrix.constructor import Matrix
|
820
|
+
self.__basis_matrix_inverse = Matrix([to_V(b) for b in self.basis()]).inverse()
|
821
|
+
M = self.__basis_matrix_inverse
|
822
|
+
return to_V(K(x)) * M
|
823
|
+
|
824
|
+
def free_module(self):
|
825
|
+
r"""
|
826
|
+
Return the free `\ZZ`-module contained in the vector space
|
827
|
+
associated to the ambient number field, that corresponds
|
828
|
+
to this order.
|
829
|
+
|
830
|
+
EXAMPLES::
|
831
|
+
|
832
|
+
sage: x = polygen(ZZ, 'x')
|
833
|
+
sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
|
834
|
+
sage: O = K.maximal_order(); O.basis()
|
835
|
+
[1, 1/2*a^2 + 1/2*a, a^2]
|
836
|
+
sage: O.free_module()
|
837
|
+
Free module of degree 3 and rank 3 over Integer Ring
|
838
|
+
User basis matrix:
|
839
|
+
[ 1 0 0]
|
840
|
+
[ 0 1/2 1/2]
|
841
|
+
[ 0 0 1]
|
842
|
+
|
843
|
+
An example in a relative extension. Notice that the module is
|
844
|
+
a `\ZZ`-module in the absolute field associated to the relative
|
845
|
+
field::
|
846
|
+
|
847
|
+
sage: x = polygen(ZZ, 'x')
|
848
|
+
sage: K.<a,b> = NumberField([x^2 + 1, x^2 + 2])
|
849
|
+
sage: O = K.maximal_order(); O.basis()
|
850
|
+
[(-3/2*b - 5)*a + 7/2*b - 2, -3*a + 2*b, -2*b*a - 3, -7*a + 5*b]
|
851
|
+
sage: O.free_module()
|
852
|
+
Free module of degree 4 and rank 4 over Integer Ring
|
853
|
+
User basis matrix:
|
854
|
+
[1/4 1/4 3/4 3/4]
|
855
|
+
[ 0 1/2 0 1/2]
|
856
|
+
[ 0 0 1 0]
|
857
|
+
[ 0 0 0 1]
|
858
|
+
"""
|
859
|
+
try:
|
860
|
+
return self.__free_module
|
861
|
+
except AttributeError:
|
862
|
+
pass
|
863
|
+
from .number_field_ideal import basis_to_module
|
864
|
+
M = basis_to_module(self.basis(), self.number_field())
|
865
|
+
self.__free_module = M
|
866
|
+
return M
|
867
|
+
|
868
|
+
@cached_method
|
869
|
+
def ring_generators(self):
|
870
|
+
"""
|
871
|
+
Return generators for ``self`` as a ring.
|
872
|
+
|
873
|
+
EXAMPLES::
|
874
|
+
|
875
|
+
sage: x = polygen(ZZ, 'x')
|
876
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
877
|
+
sage: O = K.maximal_order(); O
|
878
|
+
Gaussian Integers generated by i in Number Field in i with defining polynomial x^2 + 1
|
879
|
+
sage: O.ring_generators()
|
880
|
+
[i]
|
881
|
+
|
882
|
+
This is an example where 2 generators are required (because 2 is an essential
|
883
|
+
discriminant divisor).::
|
884
|
+
|
885
|
+
sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
|
886
|
+
sage: O = K.maximal_order(); O.basis()
|
887
|
+
[1, 1/2*a^2 + 1/2*a, a^2]
|
888
|
+
sage: O.ring_generators()
|
889
|
+
[1/2*a^2 + 1/2*a, a^2]
|
890
|
+
|
891
|
+
An example in a relative number field::
|
892
|
+
|
893
|
+
sage: K.<a, b> = NumberField([x^2 + x + 1, x^3 - 3])
|
894
|
+
sage: O = K.maximal_order()
|
895
|
+
sage: O.ring_generators()
|
896
|
+
[(-5/3*b^2 + 3*b - 2)*a - 7/3*b^2 + b + 3,
|
897
|
+
(-5*b^2 - 9)*a - 5*b^2 - b,
|
898
|
+
(-6*b^2 - 11)*a - 6*b^2 - b]
|
899
|
+
"""
|
900
|
+
K = self._K
|
901
|
+
n = []
|
902
|
+
V, from_V, to_V = self._K.absolute_vector_space()
|
903
|
+
A = ZZ**K.absolute_degree()
|
904
|
+
remaining = [x for x in self.basis() if x != 1]
|
905
|
+
gens = []
|
906
|
+
while remaining:
|
907
|
+
g = remaining.pop(0)
|
908
|
+
gens.append(g)
|
909
|
+
n.append(g.absolute_minpoly().degree())
|
910
|
+
W = A.span([to_V(x) for x in monomials(gens, n)])
|
911
|
+
remaining = [x for x in remaining if to_V(x) not in W]
|
912
|
+
return Sequence(gens, immutable=True)
|
913
|
+
|
914
|
+
@cached_method
|
915
|
+
def _defining_names(self):
|
916
|
+
"""
|
917
|
+
Return the generators of the ambient number field, but with
|
918
|
+
this order as parent.
|
919
|
+
|
920
|
+
EXAMPLES::
|
921
|
+
|
922
|
+
sage: x = polygen(ZZ, 'x')
|
923
|
+
sage: B.<z> = EquationOrder(x^2 + 3)
|
924
|
+
sage: B._defining_names()
|
925
|
+
(z,)
|
926
|
+
|
927
|
+
For relative extensions::
|
928
|
+
|
929
|
+
sage: O.<a,b> = EquationOrder([x^2 + 1, x^2 + 2])
|
930
|
+
sage: O._defining_names()
|
931
|
+
(a, b)
|
932
|
+
"""
|
933
|
+
gens = self.number_field().gens()
|
934
|
+
return tuple(self(g) for g in gens)
|
935
|
+
|
936
|
+
def zeta(self, n=2, all=False):
|
937
|
+
r"""
|
938
|
+
Return a primitive `n`-th root of unity in this order, if it
|
939
|
+
contains one. If ``all`` is ``True``, return all of them.
|
940
|
+
|
941
|
+
EXAMPLES::
|
942
|
+
|
943
|
+
sage: x = polygen(ZZ, 'x')
|
944
|
+
sage: F.<alpha> = NumberField(x**2 + 3)
|
945
|
+
sage: F.ring_of_integers().zeta(6)
|
946
|
+
-1/2*alpha + 1/2
|
947
|
+
sage: O = F.order([3*alpha])
|
948
|
+
sage: O.zeta(3)
|
949
|
+
Traceback (most recent call last):
|
950
|
+
...
|
951
|
+
ArithmeticError: there are no 3rd roots of unity in self
|
952
|
+
"""
|
953
|
+
roots_in_field = self.number_field().zeta(n, True)
|
954
|
+
roots_in_self = [self(x) for x in roots_in_field if x in self]
|
955
|
+
if not roots_in_self:
|
956
|
+
if all:
|
957
|
+
return []
|
958
|
+
else:
|
959
|
+
raise ArithmeticError("there are no %s roots of unity in self" % n.ordinal_str())
|
960
|
+
if all:
|
961
|
+
return roots_in_self
|
962
|
+
else:
|
963
|
+
return roots_in_self[0]
|
964
|
+
|
965
|
+
def number_field(self):
|
966
|
+
"""
|
967
|
+
Return the number field of this order, which is the ambient
|
968
|
+
number field that this order is embedded in.
|
969
|
+
|
970
|
+
EXAMPLES::
|
971
|
+
|
972
|
+
sage: x = polygen(ZZ, 'x')
|
973
|
+
sage: K.<b> = NumberField(x^4 + x^2 + 2)
|
974
|
+
sage: O = K.order(2*b); O
|
975
|
+
Order generated by 2*b in Number Field in b with defining polynomial x^4 + x^2 + 2
|
976
|
+
sage: O.basis()
|
977
|
+
[1, 2*b, 4*b^2, 8*b^3]
|
978
|
+
sage: O.number_field()
|
979
|
+
Number Field in b with defining polynomial x^4 + x^2 + 2
|
980
|
+
sage: O.number_field() is K
|
981
|
+
True
|
982
|
+
"""
|
983
|
+
return self._K
|
984
|
+
|
985
|
+
def ambient(self):
|
986
|
+
r"""
|
987
|
+
Return the ambient number field that contains ``self``.
|
988
|
+
|
989
|
+
This is the same as :meth:`number_field` and
|
990
|
+
:meth:`fraction_field`
|
991
|
+
|
992
|
+
EXAMPLES::
|
993
|
+
|
994
|
+
sage: x = polygen(ZZ, 'x')
|
995
|
+
sage: k.<z> = NumberField(x^2 - 389)
|
996
|
+
sage: o = k.order(389*z + 1)
|
997
|
+
sage: o
|
998
|
+
Order of conductor 778 generated by 389*z in Number Field in z with defining polynomial x^2 - 389
|
999
|
+
sage: o.basis()
|
1000
|
+
[1, 389*z]
|
1001
|
+
sage: o.ambient()
|
1002
|
+
Number Field in z with defining polynomial x^2 - 389
|
1003
|
+
"""
|
1004
|
+
return self._K
|
1005
|
+
|
1006
|
+
def residue_field(self, prime, names=None, check=False):
|
1007
|
+
"""
|
1008
|
+
Return the residue field of this order at a given prime, i.e., `O/pO`.
|
1009
|
+
|
1010
|
+
INPUT:
|
1011
|
+
|
1012
|
+
- ``prime`` -- a prime ideal of the maximal order in this number field
|
1013
|
+
- ``names`` -- the name of the variable in the residue field
|
1014
|
+
- ``check`` -- whether or not to check the primality of prime
|
1015
|
+
|
1016
|
+
OUTPUT: the residue field at this prime
|
1017
|
+
|
1018
|
+
EXAMPLES::
|
1019
|
+
|
1020
|
+
sage: R.<x> = QQ[]
|
1021
|
+
sage: x = polygen(ZZ, 'x')
|
1022
|
+
sage: K.<a> = NumberField(x^4 + 3*x^2 - 17)
|
1023
|
+
sage: P = K.ideal(61).factor()[0][0]
|
1024
|
+
sage: OK = K.maximal_order()
|
1025
|
+
sage: OK.residue_field(P)
|
1026
|
+
Residue field in abar of Fractional ideal (61, a^2 + 30)
|
1027
|
+
sage: Fp.<b> = OK.residue_field(P)
|
1028
|
+
sage: Fp
|
1029
|
+
Residue field in b of Fractional ideal (61, a^2 + 30)
|
1030
|
+
"""
|
1031
|
+
if self.is_maximal():
|
1032
|
+
return self.number_field().residue_field(prime, names, check=check)
|
1033
|
+
|
1034
|
+
raise NotImplementedError("residue fields of non-maximal orders "
|
1035
|
+
"are not yet supported")
|
1036
|
+
|
1037
|
+
def fraction_field(self):
|
1038
|
+
"""
|
1039
|
+
Return the fraction field of this order, which is the
|
1040
|
+
ambient number field.
|
1041
|
+
|
1042
|
+
EXAMPLES::
|
1043
|
+
|
1044
|
+
sage: x = polygen(ZZ, 'x')
|
1045
|
+
sage: K.<b> = NumberField(x^4 + 17*x^2 + 17)
|
1046
|
+
sage: O = K.order(17*b); O
|
1047
|
+
Order generated by 17*b in Number Field in b with defining polynomial x^4 + 17*x^2 + 17
|
1048
|
+
sage: O.fraction_field()
|
1049
|
+
Number Field in b with defining polynomial x^4 + 17*x^2 + 17
|
1050
|
+
"""
|
1051
|
+
return self._K
|
1052
|
+
|
1053
|
+
def degree(self):
|
1054
|
+
r"""
|
1055
|
+
Return the degree of this order, which is the rank of this order as a
|
1056
|
+
`\ZZ`-module.
|
1057
|
+
|
1058
|
+
EXAMPLES::
|
1059
|
+
|
1060
|
+
sage: x = polygen(ZZ, 'x')
|
1061
|
+
sage: k.<c> = NumberField(x^3 + x^2 - 2*x+8)
|
1062
|
+
sage: o = k.maximal_order()
|
1063
|
+
sage: o.degree()
|
1064
|
+
3
|
1065
|
+
sage: o.rank()
|
1066
|
+
3
|
1067
|
+
"""
|
1068
|
+
return self._K.degree()
|
1069
|
+
|
1070
|
+
def rank(self):
|
1071
|
+
r"""
|
1072
|
+
Return the rank of this order, which is the rank of the underlying
|
1073
|
+
`\ZZ`-module, or the degree of the ambient number field that contains
|
1074
|
+
this order.
|
1075
|
+
|
1076
|
+
This is a synonym for :meth:`degree`.
|
1077
|
+
|
1078
|
+
EXAMPLES::
|
1079
|
+
|
1080
|
+
sage: x = polygen(ZZ, 'x')
|
1081
|
+
sage: k.<c> = NumberField(x^5 + x^2 + 1)
|
1082
|
+
sage: o = k.maximal_order(); o
|
1083
|
+
Maximal Order generated by c in Number Field in c with defining polynomial x^5 + x^2 + 1
|
1084
|
+
sage: o.rank()
|
1085
|
+
5
|
1086
|
+
"""
|
1087
|
+
return self.degree()
|
1088
|
+
|
1089
|
+
def class_number(self, proof=None):
|
1090
|
+
r"""
|
1091
|
+
Return the class number of this order.
|
1092
|
+
|
1093
|
+
EXAMPLES::
|
1094
|
+
|
1095
|
+
sage: ZZ[2^(1/3)].class_number() # needs fpylll sage.symbolic
|
1096
|
+
1
|
1097
|
+
sage: QQ[sqrt(-23)].maximal_order().class_number() # needs fpylll sage.symbolic
|
1098
|
+
3
|
1099
|
+
sage: ZZ[120*sqrt(-23)].class_number() # needs fpylll sage.symbolic
|
1100
|
+
288
|
1101
|
+
|
1102
|
+
Note that non-maximal orders are only supported in quadratic fields::
|
1103
|
+
|
1104
|
+
sage: ZZ[120*sqrt(-23)].class_number() # needs fpylll sage.symbolic
|
1105
|
+
288
|
1106
|
+
sage: ZZ[100*sqrt(3)].class_number() # needs fpylll sage.symbolic
|
1107
|
+
4
|
1108
|
+
sage: ZZ[11*2^(1/3)].class_number() # needs fpylll sage.symbolic
|
1109
|
+
Traceback (most recent call last):
|
1110
|
+
...
|
1111
|
+
NotImplementedError: computation of class numbers of non-maximal orders
|
1112
|
+
not in quadratic fields is not implemented
|
1113
|
+
|
1114
|
+
TESTS:
|
1115
|
+
|
1116
|
+
Test for PARI bug #2466::
|
1117
|
+
|
1118
|
+
sage: x = polygen(ZZ)
|
1119
|
+
sage: R.<t> = EquationOrder(x^2 - 8461)
|
1120
|
+
sage: R.class_number()
|
1121
|
+
3
|
1122
|
+
"""
|
1123
|
+
if not self.is_maximal():
|
1124
|
+
K = self.number_field()
|
1125
|
+
if K.degree() != 2:
|
1126
|
+
raise NotImplementedError("computation of class numbers of non-maximal orders not in quadratic fields is not implemented")
|
1127
|
+
return quadratic_order_class_number(self.discriminant())
|
1128
|
+
return self.number_field().class_number(proof=proof)
|
1129
|
+
|
1130
|
+
def class_group(self, proof=None, names='c'):
|
1131
|
+
r"""
|
1132
|
+
Return the class group of this order.
|
1133
|
+
|
1134
|
+
(Currently only implemented for the maximal order.)
|
1135
|
+
|
1136
|
+
EXAMPLES::
|
1137
|
+
|
1138
|
+
sage: x = polygen(ZZ, 'x')
|
1139
|
+
sage: k.<a> = NumberField(x^2 + 5077)
|
1140
|
+
sage: O = k.maximal_order(); O
|
1141
|
+
Maximal Order generated by a in Number Field in a with defining polynomial x^2 + 5077
|
1142
|
+
sage: O.class_group()
|
1143
|
+
Class group of order 22 with structure C22 of
|
1144
|
+
Number Field in a with defining polynomial x^2 + 5077
|
1145
|
+
"""
|
1146
|
+
if self.is_maximal():
|
1147
|
+
return self.number_field().class_group(proof=proof, names=names)
|
1148
|
+
else:
|
1149
|
+
raise NotImplementedError('non-maximal orders are not yet supported')
|
1150
|
+
|
1151
|
+
def is_suborder(self, other):
|
1152
|
+
"""
|
1153
|
+
Return ``True`` if ``self`` and ``other`` are both orders in the
|
1154
|
+
same ambient number field and ``self`` is a subset of ``other``.
|
1155
|
+
|
1156
|
+
EXAMPLES::
|
1157
|
+
|
1158
|
+
sage: x = polygen(ZZ, 'x')
|
1159
|
+
sage: W.<i> = NumberField(x^2 + 1)
|
1160
|
+
sage: O5 = W.order(5*i)
|
1161
|
+
sage: O10 = W.order(10*i)
|
1162
|
+
sage: O15 = W.order(15*i)
|
1163
|
+
sage: O15.is_suborder(O5)
|
1164
|
+
True
|
1165
|
+
sage: O5.is_suborder(O15)
|
1166
|
+
False
|
1167
|
+
sage: O10.is_suborder(O15)
|
1168
|
+
False
|
1169
|
+
|
1170
|
+
We create another isomorphic but different field::
|
1171
|
+
|
1172
|
+
sage: W2.<j> = NumberField(x^2 + 1)
|
1173
|
+
sage: P5 = W2.order(5*j)
|
1174
|
+
|
1175
|
+
This is ``False`` because the ambient number fields are not equal.::
|
1176
|
+
|
1177
|
+
sage: O5.is_suborder(P5)
|
1178
|
+
False
|
1179
|
+
|
1180
|
+
We create a field that contains (in no natural way!) `W`,
|
1181
|
+
and of course again :meth:`is_suborder` returns False::
|
1182
|
+
|
1183
|
+
sage: K.<z> = NumberField(x^4 + 1)
|
1184
|
+
sage: M = K.order(5*z)
|
1185
|
+
sage: O5.is_suborder(M)
|
1186
|
+
False
|
1187
|
+
"""
|
1188
|
+
if not isinstance(other, Order):
|
1189
|
+
return False
|
1190
|
+
if other.number_field() != self.number_field():
|
1191
|
+
return False
|
1192
|
+
return self.module().is_submodule(other.module())
|
1193
|
+
|
1194
|
+
def __eq__(self, other):
|
1195
|
+
r"""
|
1196
|
+
Check whether the order ``self`` is equal to ``other``.
|
1197
|
+
|
1198
|
+
.. NOTE::
|
1199
|
+
|
1200
|
+
This method is just for equality. If you want to check if
|
1201
|
+
``self`` is contained in ``other``, use instead
|
1202
|
+
``self.is_suborder(other)`` to determine inclusion.
|
1203
|
+
|
1204
|
+
EXAMPLES::
|
1205
|
+
|
1206
|
+
sage: x = polygen(ZZ, 'x')
|
1207
|
+
sage: K.<a> = NumberField(x^3 + 2)
|
1208
|
+
sage: O1 = K.order(a); O1
|
1209
|
+
Order generated by a in Number Field in a with defining polynomial x^3 + 2
|
1210
|
+
sage: O2 = K.order(a^2); O2
|
1211
|
+
Order generated by [2*a, a^2] in Number Field in a with defining polynomial x^3 + 2
|
1212
|
+
sage: O1 == O2
|
1213
|
+
False
|
1214
|
+
|
1215
|
+
sage: O1 == K
|
1216
|
+
False
|
1217
|
+
sage: K == O1
|
1218
|
+
False
|
1219
|
+
|
1220
|
+
Here is how to check for inclusion::
|
1221
|
+
|
1222
|
+
sage: O2.is_suborder(O1)
|
1223
|
+
True
|
1224
|
+
"""
|
1225
|
+
if not isinstance(other, Order):
|
1226
|
+
return False
|
1227
|
+
if self._K != other._K:
|
1228
|
+
return False
|
1229
|
+
if self is other:
|
1230
|
+
return True
|
1231
|
+
return self._module_rep == other._module_rep
|
1232
|
+
|
1233
|
+
def __ne__(self, other):
|
1234
|
+
"""
|
1235
|
+
Check whether the order ``self`` is not equal to ``other``.
|
1236
|
+
|
1237
|
+
EXAMPLES::
|
1238
|
+
|
1239
|
+
sage: x = polygen(ZZ, 'x')
|
1240
|
+
sage: K.<a> = NumberField(x^3 + 2)
|
1241
|
+
sage: O1 = K.order(a); O1
|
1242
|
+
Order generated by a in Number Field in a with defining polynomial x^3 + 2
|
1243
|
+
sage: O2 = K.order(a^2); O2
|
1244
|
+
Order generated by [2*a, a^2] in Number Field in a with defining polynomial x^3 + 2
|
1245
|
+
sage: O1 != O2
|
1246
|
+
True
|
1247
|
+
"""
|
1248
|
+
return not (self == other)
|
1249
|
+
|
1250
|
+
def __hash__(self):
|
1251
|
+
"""
|
1252
|
+
Compute the hash of ``self``.
|
1253
|
+
|
1254
|
+
EXAMPLES::
|
1255
|
+
|
1256
|
+
sage: x = polygen(ZZ, 'x')
|
1257
|
+
sage: K.<a> = NumberField(x^3 + 2)
|
1258
|
+
sage: L.<b> = NumberField(x^3 + 3)
|
1259
|
+
sage: O1 = K.order(a)
|
1260
|
+
sage: hash(O1) == hash(K.order(a))
|
1261
|
+
True
|
1262
|
+
sage: hash(O1) == hash(K.order(a^2))
|
1263
|
+
False
|
1264
|
+
sage: hash(O1) == hash(L.order(b))
|
1265
|
+
False
|
1266
|
+
"""
|
1267
|
+
return hash((self._K, self._module_rep))
|
1268
|
+
|
1269
|
+
def conductor(self):
|
1270
|
+
r"""
|
1271
|
+
For orders in *quadratic* number fields, return the conductor
|
1272
|
+
of this order.
|
1273
|
+
|
1274
|
+
The conductor is the unique positive integer `f` such that
|
1275
|
+
the discriminant of this order is `f^2` times the discriminant
|
1276
|
+
of the containing quadratic field.
|
1277
|
+
|
1278
|
+
Not implemented for orders in number fields of degree `\neq 2`.
|
1279
|
+
|
1280
|
+
.. SEEALSO ::
|
1281
|
+
|
1282
|
+
:meth:`sage.rings.number_field.number_field.NumberField_quadratic.order_of_conductor`
|
1283
|
+
|
1284
|
+
EXAMPLES::
|
1285
|
+
|
1286
|
+
sage: K.<t> = QuadraticField(-101)
|
1287
|
+
sage: K.maximal_order().conductor()
|
1288
|
+
1
|
1289
|
+
sage: K.order(5*t).conductor()
|
1290
|
+
5
|
1291
|
+
sage: K.discriminant().factor()
|
1292
|
+
-1 * 2^2 * 101
|
1293
|
+
sage: K.order(5*t).discriminant().factor()
|
1294
|
+
-1 * 2^2 * 5^2 * 101
|
1295
|
+
|
1296
|
+
TESTS::
|
1297
|
+
|
1298
|
+
sage: type(K.order(5*t).conductor())
|
1299
|
+
<class 'sage.rings.integer.Integer'>
|
1300
|
+
"""
|
1301
|
+
if not isinstance(self._K, sage.rings.abc.NumberField_quadratic):
|
1302
|
+
raise NotImplementedError('not implemented for number fields of degree != 2')
|
1303
|
+
D = self.discriminant()
|
1304
|
+
D0 = self._K.discriminant()
|
1305
|
+
return (D // D0).sqrt()
|
1306
|
+
|
1307
|
+
def random_element(self, *args, **kwds):
|
1308
|
+
r"""
|
1309
|
+
Return a random element of this order.
|
1310
|
+
|
1311
|
+
INPUT:
|
1312
|
+
|
1313
|
+
- ``args``, ``kwds`` -- parameters passed to the random
|
1314
|
+
integer function. See the documentation for
|
1315
|
+
``ZZ.random_element()`` for details.
|
1316
|
+
|
1317
|
+
OUTPUT:
|
1318
|
+
|
1319
|
+
A random element of this order, computed as a random
|
1320
|
+
`\ZZ`-linear combination of the basis.
|
1321
|
+
|
1322
|
+
EXAMPLES::
|
1323
|
+
|
1324
|
+
sage: x = polygen(ZZ, 'x')
|
1325
|
+
sage: K.<a> = NumberField(x^3 + 2)
|
1326
|
+
sage: OK = K.ring_of_integers()
|
1327
|
+
sage: OK.random_element() # random output
|
1328
|
+
-2*a^2 - a - 2
|
1329
|
+
sage: OK.random_element(distribution='uniform') # random output
|
1330
|
+
-a^2 - 1
|
1331
|
+
sage: OK.random_element(-10,10) # random output
|
1332
|
+
-10*a^2 - 9*a - 2
|
1333
|
+
sage: K.order(a).random_element() # random output
|
1334
|
+
a^2 - a - 3
|
1335
|
+
|
1336
|
+
::
|
1337
|
+
|
1338
|
+
sage: K.<z> = CyclotomicField(17)
|
1339
|
+
sage: OK = K.ring_of_integers()
|
1340
|
+
sage: OK.random_element() # random output
|
1341
|
+
z^15 - z^11 - z^10 - 4*z^9 + z^8 + 2*z^7 + z^6
|
1342
|
+
- 2*z^5 - z^4 - 445*z^3 - 2*z^2 - 15*z - 2
|
1343
|
+
sage: OK.random_element().is_integral()
|
1344
|
+
True
|
1345
|
+
sage: OK.random_element().parent() is OK
|
1346
|
+
True
|
1347
|
+
|
1348
|
+
A relative example::
|
1349
|
+
|
1350
|
+
sage: K.<a, b> = NumberField([x^2 + 2, x^2 + 1000*x + 1])
|
1351
|
+
sage: OK = K.ring_of_integers()
|
1352
|
+
sage: OK.random_element() # random output
|
1353
|
+
(42221/2*b + 61/2)*a + 7037384*b + 7041
|
1354
|
+
sage: OK.random_element().is_integral() # random output
|
1355
|
+
True
|
1356
|
+
sage: OK.random_element().parent() is OK # random output
|
1357
|
+
True
|
1358
|
+
|
1359
|
+
An example in a non-maximal order::
|
1360
|
+
|
1361
|
+
sage: K.<a> = QuadraticField(-3)
|
1362
|
+
sage: R = K.ring_of_integers()
|
1363
|
+
sage: A = K.order(a)
|
1364
|
+
sage: A.index_in(R)
|
1365
|
+
2
|
1366
|
+
sage: R.random_element() # random output
|
1367
|
+
-39/2*a - 1/2
|
1368
|
+
sage: A.random_element() # random output
|
1369
|
+
2*a - 1
|
1370
|
+
sage: A.random_element().is_integral()
|
1371
|
+
True
|
1372
|
+
sage: A.random_element().parent() is A
|
1373
|
+
True
|
1374
|
+
"""
|
1375
|
+
return sum([ZZ.random_element(*args, **kwds) * a
|
1376
|
+
for a in self.basis()])
|
1377
|
+
|
1378
|
+
def absolute_degree(self):
|
1379
|
+
r"""
|
1380
|
+
Return the absolute degree of this order, i.e., the degree of this order over `\ZZ`.
|
1381
|
+
|
1382
|
+
EXAMPLES::
|
1383
|
+
|
1384
|
+
sage: x = polygen(ZZ, 'x')
|
1385
|
+
sage: K.<a> = NumberField(x^3 + 2)
|
1386
|
+
sage: O = K.maximal_order()
|
1387
|
+
sage: O.absolute_degree()
|
1388
|
+
3
|
1389
|
+
"""
|
1390
|
+
return self.number_field().absolute_degree()
|
1391
|
+
|
1392
|
+
def valuation(self, p):
|
1393
|
+
r"""
|
1394
|
+
Return the `p`-adic valuation on this order.
|
1395
|
+
|
1396
|
+
EXAMPLES:
|
1397
|
+
|
1398
|
+
The valuation can be specified with an integer prime `p` that is
|
1399
|
+
completely ramified or unramified::
|
1400
|
+
|
1401
|
+
sage: x = polygen(ZZ, 'x')
|
1402
|
+
sage: K.<a> = NumberField(x^2 + 1)
|
1403
|
+
sage: O = K.order(2*a)
|
1404
|
+
sage: valuations.pAdicValuation(O, 2) # needs sage.geometry.polyhedron
|
1405
|
+
2-adic valuation
|
1406
|
+
|
1407
|
+
sage: GaussianIntegers().valuation(2) # needs sage.geometry.polyhedron
|
1408
|
+
2-adic valuation
|
1409
|
+
|
1410
|
+
::
|
1411
|
+
|
1412
|
+
sage: GaussianIntegers().valuation(3) # needs sage.geometry.polyhedron
|
1413
|
+
3-adic valuation
|
1414
|
+
|
1415
|
+
A prime `p` that factors into pairwise distinct factors, results in an error::
|
1416
|
+
|
1417
|
+
sage: GaussianIntegers().valuation(5) # needs sage.geometry.polyhedron
|
1418
|
+
Traceback (most recent call last):
|
1419
|
+
...
|
1420
|
+
ValueError: The valuation Gauss valuation induced by 5-adic valuation does not
|
1421
|
+
approximate a unique extension of 5-adic valuation with respect to x^2 + 1
|
1422
|
+
|
1423
|
+
The valuation can also be selected by giving a valuation on the base
|
1424
|
+
ring that extends uniquely::
|
1425
|
+
|
1426
|
+
sage: CyclotomicField(5).ring_of_integers().valuation(ZZ.valuation(5)) # needs sage.geometry.polyhedron
|
1427
|
+
5-adic valuation
|
1428
|
+
|
1429
|
+
When the extension is not unique, this does not work::
|
1430
|
+
|
1431
|
+
sage: GaussianIntegers().valuation(ZZ.valuation(5)) # needs sage.geometry.polyhedron
|
1432
|
+
Traceback (most recent call last):
|
1433
|
+
...
|
1434
|
+
ValueError: The valuation Gauss valuation induced by 5-adic valuation does not
|
1435
|
+
approximate a unique extension of 5-adic valuation with respect to x^2 + 1
|
1436
|
+
|
1437
|
+
If the fraction field is of the form `K[x]/(G)`, you can specify a
|
1438
|
+
valuation by providing a discrete pseudo-valuation on `K[x]` which
|
1439
|
+
sends `G` to infinity::
|
1440
|
+
|
1441
|
+
sage: # needs sage.geometry.polyhedron
|
1442
|
+
sage: R.<x> = QQ[]
|
1443
|
+
sage: GV5 = GaussValuation(R, QQ.valuation(5))
|
1444
|
+
sage: v = GaussianIntegers().valuation(GV5.augmentation(x + 2, infinity))
|
1445
|
+
sage: w = GaussianIntegers().valuation(GV5.augmentation(x + 1/2, infinity))
|
1446
|
+
sage: v == w
|
1447
|
+
False
|
1448
|
+
|
1449
|
+
.. SEEALSO::
|
1450
|
+
|
1451
|
+
:meth:`NumberField_generic.valuation() <sage.rings.number_field.number_field.NumberField_generic.valuation>`,
|
1452
|
+
:meth:`pAdicGeneric.valuation() <sage.rings.padics.padic_generic.pAdicGeneric.valuation>`
|
1453
|
+
"""
|
1454
|
+
from sage.rings.padics.padic_valuation import pAdicValuation
|
1455
|
+
return pAdicValuation(self, p)
|
1456
|
+
|
1457
|
+
def some_elements(self):
|
1458
|
+
"""
|
1459
|
+
Return a list of elements of the given order.
|
1460
|
+
|
1461
|
+
EXAMPLES::
|
1462
|
+
|
1463
|
+
sage: G = GaussianIntegers(); G
|
1464
|
+
Gaussian Integers generated by I in Number Field in I with defining polynomial x^2 + 1 with I = 1*I
|
1465
|
+
sage: G.some_elements()
|
1466
|
+
[1, I, 2*I, -1, 0, -I, 2, 4*I, -2, -2*I, -4]
|
1467
|
+
|
1468
|
+
sage: R.<t> = QQ[]
|
1469
|
+
sage: K.<a> = QQ.extension(t^3 - 2); K
|
1470
|
+
Number Field in a with defining polynomial t^3 - 2
|
1471
|
+
sage: Z = K.ring_of_integers(); Z
|
1472
|
+
Maximal Order generated by a in Number Field in a with defining polynomial t^3 - 2
|
1473
|
+
sage: Z.some_elements()
|
1474
|
+
[1, a, a^2, 2*a, 0, 2, a^2 + 2*a + 1, ..., a^2 + 1, 2*a^2 + 2, a^2 + 2*a, 4*a^2 + 4]
|
1475
|
+
|
1476
|
+
TESTS:
|
1477
|
+
|
1478
|
+
This also works for trivial extensions::
|
1479
|
+
|
1480
|
+
sage: R.<t> = QQ[]
|
1481
|
+
sage: K.<a> = QQ.extension(t); K
|
1482
|
+
Number Field in a with defining polynomial t
|
1483
|
+
sage: Z = K.ring_of_integers(); Z
|
1484
|
+
Maximal Order generated by [] in Number Field in a with defining polynomial t
|
1485
|
+
sage: Z.some_elements()
|
1486
|
+
[1, 0, 2, -1, -2, 4]
|
1487
|
+
"""
|
1488
|
+
elements = list(self.basis())
|
1489
|
+
for a in self.fraction_field().some_elements():
|
1490
|
+
if a in self and a not in elements:
|
1491
|
+
elements.append(self(a))
|
1492
|
+
return elements
|
1493
|
+
|
1494
|
+
# def absolute_polynomial(self):
|
1495
|
+
# """
|
1496
|
+
# Return the absolute polynomial of this order, which is just the absolute polynomial of the number field.
|
1497
|
+
|
1498
|
+
# EXAMPLES::
|
1499
|
+
|
1500
|
+
# sage: K.<a, b> = NumberField([x^2 + 1, x^3 + x + 1]); OK = K.maximal_order()
|
1501
|
+
# Traceback (most recent call last):
|
1502
|
+
# ...
|
1503
|
+
# NotImplementedError
|
1504
|
+
|
1505
|
+
# #sage: OK.absolute_polynomial()
|
1506
|
+
# #x^6 + 5*x^4 - 2*x^3 + 4*x^2 + 4*x + 1
|
1507
|
+
# """
|
1508
|
+
# return self.number_field().absolute_polynomial()
|
1509
|
+
|
1510
|
+
# def polynomial(self):
|
1511
|
+
# """
|
1512
|
+
# Return the polynomial defining the number field that contains self.
|
1513
|
+
# """
|
1514
|
+
# return self.number_field().polynomial()
|
1515
|
+
|
1516
|
+
# def polynomial_ntl(self):
|
1517
|
+
# """
|
1518
|
+
# Return defining polynomial of the parent number field as a
|
1519
|
+
# pair, an ntl polynomial and a denominator.
|
1520
|
+
|
1521
|
+
# This is used mainly to implement some internal arithmetic.
|
1522
|
+
|
1523
|
+
# EXAMPLES::
|
1524
|
+
|
1525
|
+
# sage: NumberField(x^2 + 1,'a').maximal_order().polynomial_ntl()
|
1526
|
+
# ([1 0 1], 1)
|
1527
|
+
# """
|
1528
|
+
# return self.number_field().polynomial_ntl()
|
1529
|
+
|
1530
|
+
|
1531
|
+
class Order_absolute(Order):
|
1532
|
+
def __init__(self, K, module_rep):
|
1533
|
+
"""
|
1534
|
+
EXAMPLES::
|
1535
|
+
|
1536
|
+
sage: from sage.rings.number_field.order import *
|
1537
|
+
sage: x = polygen(QQ)
|
1538
|
+
sage: K.<a> = NumberField(x^3 + 2)
|
1539
|
+
sage: V, from_v, to_v = K.vector_space()
|
1540
|
+
sage: M = span([to_v(a^2), to_v(a), to_v(1)],ZZ)
|
1541
|
+
sage: O = AbsoluteOrder(K, M); O
|
1542
|
+
Maximal Order generated by a in Number Field in a with defining polynomial x^3 + 2
|
1543
|
+
|
1544
|
+
sage: M = span([to_v(a^2), to_v(a), to_v(2)],ZZ)
|
1545
|
+
sage: O = AbsoluteOrder(K, M); O
|
1546
|
+
Traceback (most recent call last):
|
1547
|
+
...
|
1548
|
+
ValueError: 1 is not in the span of the module, hence not an order
|
1549
|
+
|
1550
|
+
TESTS::
|
1551
|
+
|
1552
|
+
sage: loads(dumps(O)) is O
|
1553
|
+
True
|
1554
|
+
sage: TestSuite(O).run()
|
1555
|
+
"""
|
1556
|
+
if K.degree() == 2:
|
1557
|
+
self._element_type = OrderElement_quadratic
|
1558
|
+
# adding the following attribute makes the comparison of elements
|
1559
|
+
# faster.
|
1560
|
+
self._standard_embedding = K._standard_embedding
|
1561
|
+
else:
|
1562
|
+
self._element_type = OrderElement_absolute
|
1563
|
+
|
1564
|
+
# Whether this order is the maximal order, or None if we have not found out yet.
|
1565
|
+
self.__is_maximal = None
|
1566
|
+
# Maps each prime to whether this order is maximal at that prime.
|
1567
|
+
self.__is_maximal_at = {}
|
1568
|
+
|
1569
|
+
self._module_rep = module_rep
|
1570
|
+
Order.__init__(self, K)
|
1571
|
+
|
1572
|
+
if self.absolute_degree() == 2:
|
1573
|
+
self.discriminant() # cache
|
1574
|
+
|
1575
|
+
def _element_constructor_(self, x):
|
1576
|
+
r"""
|
1577
|
+
Coerce ``x`` into this order.
|
1578
|
+
|
1579
|
+
EXAMPLES::
|
1580
|
+
|
1581
|
+
sage: x = polygen(QQ)
|
1582
|
+
sage: k.<z> = NumberField(x^2 - 389)
|
1583
|
+
sage: m = k.order(3*z); m
|
1584
|
+
Order of conductor 6 generated by 3*z in Number Field in z with defining polynomial x^2 - 389
|
1585
|
+
sage: m(6*z)
|
1586
|
+
6*z
|
1587
|
+
sage: k(m(6*z))
|
1588
|
+
6*z
|
1589
|
+
|
1590
|
+
If ``x`` is a list or tuple the element constructed is the
|
1591
|
+
linear combination of the generators with these coefficients
|
1592
|
+
(see :issue:`10017`)::
|
1593
|
+
|
1594
|
+
sage: x = polygen(QQ)
|
1595
|
+
sage: K.<a> = NumberField(x^3 - 10)
|
1596
|
+
sage: ZK = K.ring_of_integers()
|
1597
|
+
sage: ZK.basis()
|
1598
|
+
[1/3*a^2 + 1/3*a + 1/3, a, a^2]
|
1599
|
+
sage: ZK([1,2,3])
|
1600
|
+
10/3*a^2 + 7/3*a + 1/3
|
1601
|
+
sage: K([1,2,3])
|
1602
|
+
3*a^2 + 2*a + 1
|
1603
|
+
"""
|
1604
|
+
if isinstance(x, (tuple, list)):
|
1605
|
+
x = sum(xi * gi for xi, gi in zip(x, self.gens()))
|
1606
|
+
if not isinstance(x, Element) or x.parent() is not self._K:
|
1607
|
+
x = self._K(x)
|
1608
|
+
V, _, embedding = self._K.vector_space()
|
1609
|
+
if embedding(x) not in self._module_rep:
|
1610
|
+
raise TypeError("Not an element of the order.")
|
1611
|
+
return self._element_type(self, x)
|
1612
|
+
|
1613
|
+
def __add__(left, right):
|
1614
|
+
"""
|
1615
|
+
Add two orders.
|
1616
|
+
|
1617
|
+
EXAMPLES::
|
1618
|
+
|
1619
|
+
sage: K.<a> = NumberField(polygen(QQ,'z')^3 - 2)
|
1620
|
+
sage: O6 = K.order(6*a); O6
|
1621
|
+
Order generated by 6*a in Number Field in a with defining polynomial z^3 - 2
|
1622
|
+
sage: O6.basis()
|
1623
|
+
[1, 6*a, 36*a^2]
|
1624
|
+
sage: O15 = K.order(15*a^2); O15.basis()
|
1625
|
+
[1, 450*a, 15*a^2]
|
1626
|
+
sage: R = O6 + O15; R
|
1627
|
+
Order generated by [6*a, 3*a^2] in Number Field in a with defining polynomial z^3 - 2
|
1628
|
+
sage: R.basis()
|
1629
|
+
[1, 6*a, 3*a^2]
|
1630
|
+
"""
|
1631
|
+
if not isinstance(right, Order_absolute):
|
1632
|
+
raise NotImplementedError("cannot add these orders yet")
|
1633
|
+
|
1634
|
+
if left.number_field() != right.number_field():
|
1635
|
+
raise TypeError("number fields do not match")
|
1636
|
+
|
1637
|
+
if left._is_maximal():
|
1638
|
+
return left
|
1639
|
+
|
1640
|
+
elif right._is_maximal():
|
1641
|
+
return right
|
1642
|
+
|
1643
|
+
return AbsoluteOrder(left._K, left._module_rep + right._module_rep)
|
1644
|
+
|
1645
|
+
def __and__(left, right):
|
1646
|
+
"""
|
1647
|
+
Intersect orders.
|
1648
|
+
|
1649
|
+
EXAMPLES::
|
1650
|
+
|
1651
|
+
sage: K.<i> = QuadraticField(-1)
|
1652
|
+
sage: O3 = K.order(3*i); O5 = K.order(5*i)
|
1653
|
+
sage: R = O3 & O5; R
|
1654
|
+
Order of conductor 15 generated by 15*i in Number Field in i with defining polynomial x^2 + 1 with i = 1*I
|
1655
|
+
sage: R.basis()
|
1656
|
+
[1, 15*i]
|
1657
|
+
sage: O3.intersection(O5).basis()
|
1658
|
+
[1, 15*i]
|
1659
|
+
|
1660
|
+
TESTS:
|
1661
|
+
|
1662
|
+
Verify that :issue:`33386` has been resolved::
|
1663
|
+
|
1664
|
+
sage: (K.maximal_order() & K.maximal_order()).is_maximal()
|
1665
|
+
True
|
1666
|
+
|
1667
|
+
Verify that an absolute order can be intersected with a relative order::
|
1668
|
+
|
1669
|
+
sage: x = polygen(ZZ, 'x')
|
1670
|
+
sage: L.<a> = K.extension(x^2 - 2)
|
1671
|
+
sage: L.absolute_field('z').maximal_order() & L.maximal_order()
|
1672
|
+
Maximal Order generated by [7/12*z^3 + 3/4*z^2 + 1/12*z + 1/4, 1/6*z^3 + 1/6*z, z^2] in Number Field in z with defining polynomial x^4 - 2*x^2 + 9
|
1673
|
+
sage: L.maximal_order() & L.absolute_field('z').maximal_order()
|
1674
|
+
Maximal Order generated by [7/12*z^3 + 3/4*z^2 + 1/12*z + 1/4, 1/6*z^3 + 1/6*z, z^2] in Number Field in z with defining polynomial x^4 - 2*x^2 + 9
|
1675
|
+
"""
|
1676
|
+
if isinstance(right, Order_relative):
|
1677
|
+
return right & left
|
1678
|
+
|
1679
|
+
if left.number_field() != right.number_field():
|
1680
|
+
raise TypeError("number fields do not match")
|
1681
|
+
|
1682
|
+
is_maximal = None
|
1683
|
+
|
1684
|
+
# Note that this is not correct while orders created with
|
1685
|
+
# non-maximal-non-unique are still around. Once that deprecation has
|
1686
|
+
# been removed, these simple rules can be enabled.
|
1687
|
+
# if left._is_maximal() is True and right._is_maximal() is True:
|
1688
|
+
# is_maximal = True
|
1689
|
+
# if left._is_maximal() is False or right._is_maximal() is False:
|
1690
|
+
# is_maximal = False
|
1691
|
+
|
1692
|
+
return AbsoluteOrder(left._K, left._module_rep.intersection(right._module_rep), is_maximal=is_maximal)
|
1693
|
+
|
1694
|
+
def _magma_init_(self, magma):
|
1695
|
+
"""
|
1696
|
+
Return Magma version of this absolute order.
|
1697
|
+
|
1698
|
+
INPUT:
|
1699
|
+
|
1700
|
+
- ``magma`` -- a magma interpreter
|
1701
|
+
|
1702
|
+
OUTPUT: a :class:`MagmaElement`, the magma version of this absolute order
|
1703
|
+
|
1704
|
+
EXAMPLES::
|
1705
|
+
|
1706
|
+
sage: x = polygen(ZZ, 'x')
|
1707
|
+
sage: K.<a> = NumberField(x^3 + 2) # optional - magma
|
1708
|
+
sage: magma(K.maximal_order()) # optional - magma
|
1709
|
+
Equation Order with defining polynomial x^3 + 2 over its ground order
|
1710
|
+
|
1711
|
+
_magma_init_ was called implicitly by the above call::
|
1712
|
+
|
1713
|
+
sage: K.maximal_order()._magma_init_(magma) # optional - magma
|
1714
|
+
'Order([(_sage_[...]![1, 0, 0]),(_sage_[...]![0, 1, 0]),(_sage_[...]![0, 0, 1])])'
|
1715
|
+
"""
|
1716
|
+
K = self.number_field()
|
1717
|
+
v = (K(a)._magma_init_(magma) for a in self.basis())
|
1718
|
+
return 'Order([{}])'.format(','.join(v))
|
1719
|
+
|
1720
|
+
def discriminant(self):
|
1721
|
+
"""
|
1722
|
+
Return the discriminant of this order.
|
1723
|
+
|
1724
|
+
EXAMPLES::
|
1725
|
+
|
1726
|
+
sage: x = polygen(ZZ, 'x')
|
1727
|
+
sage: K.<a> = NumberField(x^8 + x^3 - 13*x + 26)
|
1728
|
+
sage: O = K.maximal_order()
|
1729
|
+
sage: factor(O.discriminant())
|
1730
|
+
3 * 11 * 13^2 * 613 * 1575917857
|
1731
|
+
sage: L = K.order(13*a^2)
|
1732
|
+
sage: factor(L.discriminant())
|
1733
|
+
3^3 * 5^2 * 11 * 13^60 * 613 * 733^2 * 1575917857
|
1734
|
+
sage: factor(L.index_in(O))
|
1735
|
+
3 * 5 * 13^29 * 733
|
1736
|
+
sage: L.discriminant() / O.discriminant() == L.index_in(O)^2
|
1737
|
+
True
|
1738
|
+
|
1739
|
+
TESTS::
|
1740
|
+
|
1741
|
+
sage: type(K.order(5*a).discriminant())
|
1742
|
+
<class 'sage.rings.integer.Integer'>
|
1743
|
+
"""
|
1744
|
+
try:
|
1745
|
+
return self.__discriminant
|
1746
|
+
except AttributeError:
|
1747
|
+
if self._is_maximal():
|
1748
|
+
D = self._K.discriminant()
|
1749
|
+
else:
|
1750
|
+
D = ZZ(self._K.discriminant(self.basis()))
|
1751
|
+
self.__discriminant = D
|
1752
|
+
return D
|
1753
|
+
|
1754
|
+
absolute_discriminant = discriminant
|
1755
|
+
|
1756
|
+
def is_maximal(self, p=None):
|
1757
|
+
"""
|
1758
|
+
Return whether this is the maximal order.
|
1759
|
+
|
1760
|
+
INPUT:
|
1761
|
+
|
1762
|
+
- ``p`` -- integer prime or ``None`` (default: ``None``); if
|
1763
|
+
set, return whether this order is maximal at the prime `p`
|
1764
|
+
|
1765
|
+
EXAMPLES::
|
1766
|
+
|
1767
|
+
sage: x = polygen(ZZ, 'x')
|
1768
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
1769
|
+
|
1770
|
+
sage: K.order(3*i).is_maximal()
|
1771
|
+
False
|
1772
|
+
sage: K.order(5*i).is_maximal()
|
1773
|
+
False
|
1774
|
+
sage: (K.order(3*i) + K.order(5*i)).is_maximal()
|
1775
|
+
True
|
1776
|
+
sage: K.maximal_order().is_maximal()
|
1777
|
+
True
|
1778
|
+
|
1779
|
+
Maximality can be checked at primes when the order is maximal at that
|
1780
|
+
prime by construction::
|
1781
|
+
|
1782
|
+
sage: K.maximal_order().is_maximal(p=3)
|
1783
|
+
True
|
1784
|
+
|
1785
|
+
And also at other primes::
|
1786
|
+
|
1787
|
+
sage: K.order(3*i).is_maximal(p=3)
|
1788
|
+
False
|
1789
|
+
|
1790
|
+
An example involving a relative order::
|
1791
|
+
|
1792
|
+
sage: K.<a, b> = NumberField([x^2 + 1, x^2 - 3])
|
1793
|
+
sage: O = K.order([3*a, 2*b])
|
1794
|
+
sage: O.is_maximal()
|
1795
|
+
False
|
1796
|
+
"""
|
1797
|
+
if self._is_maximal() is True:
|
1798
|
+
return True
|
1799
|
+
|
1800
|
+
if p is None:
|
1801
|
+
if self._is_maximal() is None:
|
1802
|
+
self._assume_maximal(self.absolute_discriminant() == self._K.absolute_discriminant())
|
1803
|
+
return self._is_maximal()
|
1804
|
+
else:
|
1805
|
+
p = ZZ(p).abs()
|
1806
|
+
|
1807
|
+
if self._is_maximal_at(p) is None:
|
1808
|
+
is_maximal = self._K.maximal_order(p, assume_maximal=None).absolute_discriminant().valuation(p) == self.absolute_discriminant().valuation(p)
|
1809
|
+
self._assume_maximal(is_maximal, p=p)
|
1810
|
+
|
1811
|
+
return self._is_maximal_at(p)
|
1812
|
+
|
1813
|
+
def _is_maximal(self):
|
1814
|
+
r"""
|
1815
|
+
Return whether this order is already known to be maximal.
|
1816
|
+
|
1817
|
+
Used by :meth:`is_maximal`.
|
1818
|
+
|
1819
|
+
EXAMPLES::
|
1820
|
+
|
1821
|
+
sage: x = polygen(ZZ, 'x')
|
1822
|
+
sage: K.<t> = NumberField(x^3 + x + 1)
|
1823
|
+
sage: K.order(1337*t)._is_maximal() is None
|
1824
|
+
True
|
1825
|
+
sage: K.order(1337*t).is_maximal()
|
1826
|
+
False
|
1827
|
+
sage: K.order(1337*t)._is_maximal()
|
1828
|
+
False
|
1829
|
+
"""
|
1830
|
+
return self.__is_maximal
|
1831
|
+
|
1832
|
+
def _is_maximal_at(self, p=None):
|
1833
|
+
r"""
|
1834
|
+
Return whether this order is already known to be maximal at ``p``.
|
1835
|
+
|
1836
|
+
When no ``p`` is specified, returns a dictionary of primes for which
|
1837
|
+
maximality is known.
|
1838
|
+
|
1839
|
+
Used by :meth:`is_maximal`.
|
1840
|
+
|
1841
|
+
EXAMPLES::
|
1842
|
+
|
1843
|
+
sage: x = polygen(ZZ, 'x')
|
1844
|
+
sage: K.<a> = NumberField(x^13 - 2)
|
1845
|
+
|
1846
|
+
sage: O = K.order(a)
|
1847
|
+
sage: O._is_maximal_at(p=1361) is None
|
1848
|
+
True
|
1849
|
+
sage: O._assume_maximal(p=1361) is O
|
1850
|
+
True
|
1851
|
+
sage: K.order(a).is_maximal(p=1361)
|
1852
|
+
True
|
1853
|
+
sage: K.order(a)._is_maximal_at(p=1361)
|
1854
|
+
True
|
1855
|
+
|
1856
|
+
TESTS::
|
1857
|
+
|
1858
|
+
sage: L.<a, b> = NumberField([x^2 - 1000005, x^2 - 5*1000099^2])
|
1859
|
+
sage: K = L.absolute_field('c')
|
1860
|
+
sage: O = K.maximal_order([13], assume_maximal=None)
|
1861
|
+
sage: O._is_maximal_at()
|
1862
|
+
{13: True}
|
1863
|
+
"""
|
1864
|
+
if p is None:
|
1865
|
+
return dict(self.__is_maximal_at)
|
1866
|
+
|
1867
|
+
p = ZZ(p).abs()
|
1868
|
+
return self.__is_maximal_at.get(p, None)
|
1869
|
+
|
1870
|
+
def _assume_maximal(self, is_maximal=True, p=None):
|
1871
|
+
r"""
|
1872
|
+
Record that this order ``is_maximal`` at the integer prime ``p``.
|
1873
|
+
|
1874
|
+
To support the deprecated behavior for
|
1875
|
+
``is_maximal="non-maximal-non-unique"``, this returns an order.
|
1876
|
+
Typically, the order itself.
|
1877
|
+
|
1878
|
+
EXAMPLES::
|
1879
|
+
|
1880
|
+
sage: x = polygen(ZZ, 'x')
|
1881
|
+
sage: K.<a> = NumberField(x^4 - 10001822082820*x^2 + 25009091240356266913960000)
|
1882
|
+
sage: O = K.maximal_order([13], assume_maximal=None)
|
1883
|
+
|
1884
|
+
We can store information about more primes::
|
1885
|
+
|
1886
|
+
sage: O._is_maximal_at(p=7) is None
|
1887
|
+
True
|
1888
|
+
sage: 7.divides(K.absolute_discriminant())
|
1889
|
+
False
|
1890
|
+
sage: O._assume_maximal(p=7) is O
|
1891
|
+
True
|
1892
|
+
sage: O._is_maximal_at(p=7)
|
1893
|
+
True
|
1894
|
+
|
1895
|
+
We cannot store contradicting information at a prime::
|
1896
|
+
|
1897
|
+
sage: O._assume_maximal(p=7, is_maximal=False)
|
1898
|
+
Traceback (most recent call last):
|
1899
|
+
...
|
1900
|
+
ValueError: cannot assume this order to be non-maximal at 7 because we already found it to be maximal at that prime
|
1901
|
+
|
1902
|
+
We can safely store information that we know to be wrong to support
|
1903
|
+
legacy behavior of orders that are assumed to be only maximal at some
|
1904
|
+
primes::
|
1905
|
+
|
1906
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
1907
|
+
sage: O = K.order(1+i)
|
1908
|
+
sage: O.is_maximal()
|
1909
|
+
True
|
1910
|
+
sage: N = O._assume_maximal(is_maximal='non-maximal-non-unique')
|
1911
|
+
sage: N._assume_maximal(p=2) is N
|
1912
|
+
True
|
1913
|
+
sage: N is O
|
1914
|
+
False
|
1915
|
+
sage: N == O
|
1916
|
+
True
|
1917
|
+
sage: N.is_maximal()
|
1918
|
+
False
|
1919
|
+
sage: N.is_maximal(p=2)
|
1920
|
+
True
|
1921
|
+
"""
|
1922
|
+
if is_maximal is None:
|
1923
|
+
# No assumption made, return the object unchanged.
|
1924
|
+
return self
|
1925
|
+
|
1926
|
+
if p is None:
|
1927
|
+
if is_maximal == "non-maximal-non-unique":
|
1928
|
+
# We force this order to be non-maximal to support legacy code that
|
1929
|
+
# could create such orders.
|
1930
|
+
self = type(self)(self._K, self._module_rep)
|
1931
|
+
self.__is_maximal = False
|
1932
|
+
elif is_maximal:
|
1933
|
+
if self._is_maximal() is False:
|
1934
|
+
raise ValueError("cannot assume this order to be maximal because we already found it to be a non-maximal order")
|
1935
|
+
self.__is_maximal = True
|
1936
|
+
# No need to keep information at specific primes anymore.
|
1937
|
+
self.__is_maximal_at = {}
|
1938
|
+
else:
|
1939
|
+
if self._is_maximal() is True:
|
1940
|
+
raise ValueError("cannot assume this order to be non-maximal because we already found it to be a maximal order")
|
1941
|
+
self.__is_maximal = False
|
1942
|
+
else:
|
1943
|
+
p = ZZ(p).abs()
|
1944
|
+
|
1945
|
+
if is_maximal == "non-maximal-non-unique":
|
1946
|
+
raise NotImplementedError("legacy support for explicitly non-maximal orders only possible at all primes")
|
1947
|
+
elif is_maximal:
|
1948
|
+
if self._is_maximal_at(p) is False:
|
1949
|
+
raise ValueError(f"cannot assume this order to be maximal at {p} because we already found it to be non-maximal at that prime")
|
1950
|
+
self.__is_maximal_at[p] = True
|
1951
|
+
else:
|
1952
|
+
if self._is_maximal_at(p) is True:
|
1953
|
+
raise ValueError(f"cannot assume this order to be non-maximal at {p} because we already found it to be maximal at that prime")
|
1954
|
+
|
1955
|
+
self._assume_maximal(False)
|
1956
|
+
self.__is_maximal_at[p] = False
|
1957
|
+
|
1958
|
+
return self
|
1959
|
+
|
1960
|
+
def change_names(self, names):
|
1961
|
+
"""
|
1962
|
+
Return a new order isomorphic to this one in the number field with
|
1963
|
+
given variable names.
|
1964
|
+
|
1965
|
+
EXAMPLES::
|
1966
|
+
|
1967
|
+
sage: x = polygen(ZZ, 'x')
|
1968
|
+
sage: R = EquationOrder(x^3 + x + 1, 'alpha'); R
|
1969
|
+
Order generated by alpha in Number Field in alpha with defining polynomial x^3 + x + 1
|
1970
|
+
sage: R.basis()
|
1971
|
+
[1, alpha, alpha^2]
|
1972
|
+
sage: S = R.change_names('gamma'); S
|
1973
|
+
Order generated by gamma in Number Field in gamma with defining polynomial x^3 + x + 1
|
1974
|
+
sage: S.basis()
|
1975
|
+
[1, gamma, gamma^2]
|
1976
|
+
"""
|
1977
|
+
K = self.number_field().change_names(names)
|
1978
|
+
_, to_K = K.structure()
|
1979
|
+
B = [to_K(a) for a in self.basis()]
|
1980
|
+
return K.order(B, check_is_integral=False, check_rank=False, allow_subfield=True)
|
1981
|
+
|
1982
|
+
def index_in(self, other):
|
1983
|
+
"""
|
1984
|
+
Return the index of ``self`` in ``other``.
|
1985
|
+
|
1986
|
+
This is a lattice index,
|
1987
|
+
so it is a rational number if ``self`` is not contained in ``other``.
|
1988
|
+
|
1989
|
+
INPUT:
|
1990
|
+
|
1991
|
+
- ``other`` -- another absolute order with the same ambient number field
|
1992
|
+
|
1993
|
+
OUTPUT: a rational number
|
1994
|
+
|
1995
|
+
EXAMPLES::
|
1996
|
+
|
1997
|
+
sage: x = polygen(ZZ, 'x')
|
1998
|
+
sage: k.<i> = NumberField(x^2 + 1)
|
1999
|
+
sage: O1 = k.order(i)
|
2000
|
+
sage: O5 = k.order(5*i)
|
2001
|
+
sage: O5.index_in(O1)
|
2002
|
+
5
|
2003
|
+
|
2004
|
+
sage: k.<a> = NumberField(x^3 + x^2 - 2*x+8)
|
2005
|
+
sage: o = k.maximal_order()
|
2006
|
+
sage: o
|
2007
|
+
Maximal Order generated by [1/2*a^2 + 1/2*a, a^2] in Number Field in a with defining polynomial x^3 + x^2 - 2*x + 8
|
2008
|
+
sage: O1 = k.order(a); O1
|
2009
|
+
Order generated by a in Number Field in a with defining polynomial x^3 + x^2 - 2*x + 8
|
2010
|
+
sage: O1.index_in(o)
|
2011
|
+
2
|
2012
|
+
sage: O2 = k.order(1+2*a); O2
|
2013
|
+
Order generated by 2*a in Number Field in a with defining polynomial x^3 + x^2 - 2*x + 8
|
2014
|
+
sage: O1.basis()
|
2015
|
+
[1, a, a^2]
|
2016
|
+
sage: O2.basis()
|
2017
|
+
[1, 2*a, 4*a^2]
|
2018
|
+
sage: o.index_in(O2)
|
2019
|
+
1/16
|
2020
|
+
"""
|
2021
|
+
if not isinstance(other, Order_absolute):
|
2022
|
+
raise TypeError("other must be an absolute order.")
|
2023
|
+
if other.ambient() != self.ambient():
|
2024
|
+
raise ValueError("other must have the same ambient number field as self.")
|
2025
|
+
return self._module_rep.index_in(other._module_rep)
|
2026
|
+
|
2027
|
+
def module(self):
|
2028
|
+
"""
|
2029
|
+
Return the underlying free module corresponding to this
|
2030
|
+
order, embedded in the vector space corresponding to the
|
2031
|
+
ambient number field.
|
2032
|
+
|
2033
|
+
EXAMPLES::
|
2034
|
+
|
2035
|
+
sage: x = polygen(ZZ, 'x')
|
2036
|
+
sage: k.<a> = NumberField(x^3 + x + 3)
|
2037
|
+
sage: m = k.order(3*a); m
|
2038
|
+
Order generated by 3*a in Number Field in a with defining polynomial x^3 + x + 3
|
2039
|
+
sage: m.module()
|
2040
|
+
Free module of degree 3 and rank 3 over Integer Ring
|
2041
|
+
Echelon basis matrix:
|
2042
|
+
[1 0 0]
|
2043
|
+
[0 3 0]
|
2044
|
+
[0 0 9]
|
2045
|
+
"""
|
2046
|
+
return self._module_rep
|
2047
|
+
|
2048
|
+
def intersection(self, other):
|
2049
|
+
"""
|
2050
|
+
Return the intersection of this order with another order.
|
2051
|
+
|
2052
|
+
EXAMPLES::
|
2053
|
+
|
2054
|
+
sage: x = polygen(ZZ, 'x')
|
2055
|
+
sage: k.<i> = NumberField(x^2 + 1)
|
2056
|
+
sage: O6 = k.order(6*i)
|
2057
|
+
sage: O9 = k.order(9*i)
|
2058
|
+
sage: O6.basis()
|
2059
|
+
[1, 6*i]
|
2060
|
+
sage: O9.basis()
|
2061
|
+
[1, 9*i]
|
2062
|
+
sage: O6.intersection(O9).basis()
|
2063
|
+
[1, 18*i]
|
2064
|
+
sage: (O6 & O9).basis()
|
2065
|
+
[1, 18*i]
|
2066
|
+
sage: (O6 + O9).basis()
|
2067
|
+
[1, 3*i]
|
2068
|
+
"""
|
2069
|
+
return self & other
|
2070
|
+
|
2071
|
+
def _repr_(self):
|
2072
|
+
"""
|
2073
|
+
Return print representation of this absolute order.
|
2074
|
+
|
2075
|
+
EXAMPLES::
|
2076
|
+
|
2077
|
+
sage: x = polygen(ZZ, 'x')
|
2078
|
+
sage: K.<a> = NumberField(x^4 - 5)
|
2079
|
+
sage: K.maximal_order()._repr_()
|
2080
|
+
'Maximal Order generated by [1/2*a^2 + 1/2, 1/2*a^3 + 1/2*a] in Number Field in a with defining polynomial x^4 - 5'
|
2081
|
+
sage: K.order(a)._repr_()
|
2082
|
+
'Order generated by a in Number Field in a with defining polynomial x^4 - 5'
|
2083
|
+
|
2084
|
+
We have special cases for Gaussian and Eisenstein integers::
|
2085
|
+
|
2086
|
+
sage: K = CyclotomicField(4)
|
2087
|
+
sage: K.ring_of_integers()
|
2088
|
+
Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2
|
2089
|
+
sage: K = QuadraticField(-3)
|
2090
|
+
sage: K.ring_of_integers()
|
2091
|
+
Eisenstein Integers generated by 1/2*a + 1/2 in Number Field in a with defining polynomial x^2 + 3 with a = 1.732050807568878?*I
|
2092
|
+
"""
|
2093
|
+
if self._is_maximal():
|
2094
|
+
s = "Maximal Order"
|
2095
|
+
if self.degree() == 2:
|
2096
|
+
D = self.discriminant()
|
2097
|
+
if D == -3:
|
2098
|
+
s = "Eisenstein Integers"
|
2099
|
+
if D == -4:
|
2100
|
+
s = "Gaussian Integers"
|
2101
|
+
else:
|
2102
|
+
s = "Order"
|
2103
|
+
if self.number_field().absolute_degree() == 2:
|
2104
|
+
f = self.conductor()
|
2105
|
+
s += f' of conductor {f}'
|
2106
|
+
try:
|
2107
|
+
gens = self.ring_generators()
|
2108
|
+
except TypeError:
|
2109
|
+
gens = self.gens()
|
2110
|
+
s += f' generated by {gens[0] if len(gens) == 1 else "[" + ", ".join(map(str, gens)) + "]"}'
|
2111
|
+
s += f' in {self._K}'
|
2112
|
+
return s
|
2113
|
+
|
2114
|
+
def basis(self):
|
2115
|
+
r"""
|
2116
|
+
Return the basis over `\ZZ` for this order.
|
2117
|
+
|
2118
|
+
EXAMPLES::
|
2119
|
+
|
2120
|
+
sage: x = polygen(ZZ, 'x')
|
2121
|
+
sage: k.<c> = NumberField(x^3 + x^2 + 1)
|
2122
|
+
sage: O = k.maximal_order(); O
|
2123
|
+
Maximal Order generated by c in Number Field in c with defining polynomial x^3 + x^2 + 1
|
2124
|
+
sage: O.basis()
|
2125
|
+
[1, c, c^2]
|
2126
|
+
|
2127
|
+
The basis is an immutable sequence::
|
2128
|
+
|
2129
|
+
sage: type(O.basis())
|
2130
|
+
<class 'sage.structure.sequence.Sequence_generic'>
|
2131
|
+
|
2132
|
+
The generator functionality uses the basis method::
|
2133
|
+
|
2134
|
+
sage: O.0
|
2135
|
+
1
|
2136
|
+
sage: O.1
|
2137
|
+
c
|
2138
|
+
sage: O.basis()
|
2139
|
+
[1, c, c^2]
|
2140
|
+
sage: O.ngens()
|
2141
|
+
3
|
2142
|
+
"""
|
2143
|
+
try:
|
2144
|
+
return self.__basis
|
2145
|
+
except AttributeError:
|
2146
|
+
V, from_V, to_V = self._K.vector_space()
|
2147
|
+
B = Sequence([self(from_V(b)) for b in self._module_rep.basis()], immutable=True)
|
2148
|
+
self.__basis = B
|
2149
|
+
return B
|
2150
|
+
|
2151
|
+
def absolute_order(self):
|
2152
|
+
"""
|
2153
|
+
Return the absolute order associated to this order, which is
|
2154
|
+
just this order again since this is an absolute order.
|
2155
|
+
|
2156
|
+
EXAMPLES::
|
2157
|
+
|
2158
|
+
sage: x = polygen(ZZ, 'x')
|
2159
|
+
sage: K.<a> = NumberField(x^3 + 2)
|
2160
|
+
sage: O1 = K.order(a); O1
|
2161
|
+
Maximal Order generated by a in Number Field in a with defining polynomial x^3 + 2
|
2162
|
+
sage: O1.absolute_order() is O1
|
2163
|
+
True
|
2164
|
+
"""
|
2165
|
+
return self
|
2166
|
+
|
2167
|
+
|
2168
|
+
class Order_relative(Order):
|
2169
|
+
"""
|
2170
|
+
A relative order in a number field.
|
2171
|
+
|
2172
|
+
A relative order is an order in some relative number field.
|
2173
|
+
|
2174
|
+
Invariants of this order may be computed with respect to the
|
2175
|
+
contained order.
|
2176
|
+
"""
|
2177
|
+
|
2178
|
+
def __init__(self, K, absolute_order):
|
2179
|
+
"""
|
2180
|
+
Create the relative order.
|
2181
|
+
|
2182
|
+
EXAMPLES::
|
2183
|
+
|
2184
|
+
sage: x = polygen(ZZ, 'x')
|
2185
|
+
sage: k.<a,b> = NumberFieldTower([x^2 - 3, x^2 + 1])
|
2186
|
+
sage: O = k.maximal_order(); O # indirect doctest
|
2187
|
+
Maximal Relative Order generated by 1/2*a - 1/2*b in Number Field in a with defining polynomial x^2 - 3 over its base field
|
2188
|
+
|
2189
|
+
sage: _ = O.basis()
|
2190
|
+
|
2191
|
+
TESTS::
|
2192
|
+
|
2193
|
+
sage: loads(dumps(O)) is O
|
2194
|
+
True
|
2195
|
+
sage: TestSuite(O).run()
|
2196
|
+
"""
|
2197
|
+
self._absolute_order = absolute_order
|
2198
|
+
self._module_rep = absolute_order._module_rep
|
2199
|
+
|
2200
|
+
Order.__init__(self, K)
|
2201
|
+
|
2202
|
+
def _element_constructor_(self, x):
|
2203
|
+
"""
|
2204
|
+
Coerce an element into this relative order.
|
2205
|
+
|
2206
|
+
EXAMPLES::
|
2207
|
+
|
2208
|
+
sage: x = polygen(ZZ, 'x')
|
2209
|
+
sage: K.<a, b> = NumberField([x^2 + 2, x^2 + 1000*x + 1])
|
2210
|
+
sage: OK = K.ring_of_integers()
|
2211
|
+
sage: OK(a)
|
2212
|
+
a
|
2213
|
+
sage: OK([3, 4])
|
2214
|
+
4*a + 3
|
2215
|
+
|
2216
|
+
The following used to fail; see :issue:`5276`::
|
2217
|
+
|
2218
|
+
sage: S.<y> = OK[]; S
|
2219
|
+
Univariate Polynomial Ring in y over Maximal Relative Order generated by [(-5787/2*b - 9/2)*a - 964565*b - 965, (-1500*b - 2)*a - 499997*b - 500] in Number Field in a with defining polynomial x^2 + 2 over its base field
|
2220
|
+
|
2221
|
+
We test that :issue:`4193` is also fixed::
|
2222
|
+
|
2223
|
+
sage: K1.<a> = NumberField(x^3 - 2)
|
2224
|
+
sage: R.<y> = PolynomialRing(K1)
|
2225
|
+
sage: K2.<b> = K1.extension(y^2 - a)
|
2226
|
+
sage: R = K2.order(b)
|
2227
|
+
sage: b in R
|
2228
|
+
True
|
2229
|
+
sage: bb = R.basis()[1] # b by any other name
|
2230
|
+
sage: bb == b
|
2231
|
+
True
|
2232
|
+
sage: bb.parent() is R
|
2233
|
+
True
|
2234
|
+
sage: bb in R # this used to return False
|
2235
|
+
True
|
2236
|
+
sage: R(bb) == bb # this used to raise an error
|
2237
|
+
True
|
2238
|
+
"""
|
2239
|
+
|
2240
|
+
x = self._K(x)
|
2241
|
+
abs_order = self._absolute_order
|
2242
|
+
to_abs = abs_order._K.structure()[1]
|
2243
|
+
x = abs_order(to_abs(x)) # will test membership
|
2244
|
+
return OrderElement_relative(self, x)
|
2245
|
+
|
2246
|
+
def _repr_(self):
|
2247
|
+
"""
|
2248
|
+
Return print representation of this relative order.
|
2249
|
+
|
2250
|
+
EXAMPLES::
|
2251
|
+
|
2252
|
+
sage: x = polygen(ZZ, 'x')
|
2253
|
+
sage: O = EquationOrder([x^2 + x + 1, x^3 - 2],'a,b')
|
2254
|
+
sage: O._repr_()
|
2255
|
+
'Relative Order generated by [(-b^2 + 6*b + 11)*a + 3*b^2 + b + 14, (-2*b^2 - 2)*a - 2*b^2 - b, (b + 6)*a + 3*b^2 + 6] in Number Field in a with defining polynomial x^2 + x + 1 over its base field'
|
2256
|
+
"""
|
2257
|
+
s = 'Maximal ' if self._is_maximal() else ''
|
2258
|
+
s += 'Relative Order'
|
2259
|
+
try:
|
2260
|
+
gens = self.ring_generators()
|
2261
|
+
except TypeError:
|
2262
|
+
gens = self.gens()
|
2263
|
+
s += f' generated by {gens[0] if len(gens) == 1 else "[" + ", ".join(map(str, gens)) + "]"}'
|
2264
|
+
s += f' in {self._K}'
|
2265
|
+
return s
|
2266
|
+
|
2267
|
+
def absolute_order(self, names='z'):
|
2268
|
+
"""
|
2269
|
+
Return underlying absolute order associated to this relative
|
2270
|
+
order.
|
2271
|
+
|
2272
|
+
INPUT:
|
2273
|
+
|
2274
|
+
- ``names`` -- string (default: ``'z'``); name of generator of absolute
|
2275
|
+
extension
|
2276
|
+
|
2277
|
+
.. NOTE::
|
2278
|
+
|
2279
|
+
There *is* a default variable name, since this absolute
|
2280
|
+
order is frequently used for internal algorithms.
|
2281
|
+
|
2282
|
+
EXAMPLES::
|
2283
|
+
|
2284
|
+
sage: x = polygen(ZZ, 'x')
|
2285
|
+
sage: R = EquationOrder([x^2 + 1, x^2 - 5], 'i,g'); R
|
2286
|
+
Relative Order generated by [6*i - g, -g*i + 2, 7*i - g] in
|
2287
|
+
Number Field in i with defining polynomial x^2 + 1 over its base field
|
2288
|
+
sage: R.basis()
|
2289
|
+
[1, 6*i - g, -g*i + 2, 7*i - g]
|
2290
|
+
|
2291
|
+
sage: S = R.absolute_order(); S
|
2292
|
+
Order generated by [5/12*z^3 + 1/6*z, 1/2*z^2, 1/2*z^3] in Number Field in z with defining polynomial x^4 - 8*x^2 + 36
|
2293
|
+
sage: S.basis()
|
2294
|
+
[1, 5/12*z^3 + 1/6*z, 1/2*z^2, 1/2*z^3]
|
2295
|
+
|
2296
|
+
We compute a relative order in alpha0, alpha1, then make the
|
2297
|
+
generator of the number field that contains the absolute order be called
|
2298
|
+
gamma.::
|
2299
|
+
|
2300
|
+
sage: R = EquationOrder( [x^2 + 2, x^2 - 3], 'alpha'); R
|
2301
|
+
Relative Order generated by [-alpha1*alpha0 + 1, 5*alpha0 + 2*alpha1, 7*alpha0 + 3*alpha1] in
|
2302
|
+
Number Field in alpha0 with defining polynomial x^2 + 2 over its base field
|
2303
|
+
sage: R.absolute_order('gamma')
|
2304
|
+
Order generated by [1/2*gamma^2 + 1/2, 7/10*gamma^3 + 1/10*gamma, gamma^3] in Number Field in gamma with defining polynomial x^4 - 2*x^2 + 25
|
2305
|
+
sage: R.absolute_order('gamma').basis()
|
2306
|
+
[1/2*gamma^2 + 1/2, 7/10*gamma^3 + 1/10*gamma, gamma^2, gamma^3]
|
2307
|
+
"""
|
2308
|
+
if names == 'z' or names == ('z',):
|
2309
|
+
return self._absolute_order
|
2310
|
+
else:
|
2311
|
+
return self._absolute_order.change_names(names)
|
2312
|
+
|
2313
|
+
def basis(self):
|
2314
|
+
r"""
|
2315
|
+
Return a basis for this order as `\ZZ`-module.
|
2316
|
+
|
2317
|
+
EXAMPLES::
|
2318
|
+
|
2319
|
+
sage: x = polygen(ZZ, 'x')
|
2320
|
+
sage: K.<a,b> = NumberField([x^2 + 1, x^2 + 3])
|
2321
|
+
sage: O = K.order([a,b])
|
2322
|
+
sage: O.basis()
|
2323
|
+
[1, -2*a + b, -b*a - 2, -5*a + 3*b]
|
2324
|
+
sage: z = O.1; z
|
2325
|
+
-2*a + b
|
2326
|
+
sage: z.absolute_minpoly()
|
2327
|
+
x^4 + 14*x^2 + 1
|
2328
|
+
"""
|
2329
|
+
try:
|
2330
|
+
return self.__basis
|
2331
|
+
except AttributeError:
|
2332
|
+
pass
|
2333
|
+
O = self._absolute_order
|
2334
|
+
K = O.number_field()
|
2335
|
+
from_K, _ = K.structure()
|
2336
|
+
self.__basis = [OrderElement_relative(self, from_K(a)) for a in O.basis()]
|
2337
|
+
return self.__basis
|
2338
|
+
|
2339
|
+
def __add__(left, right):
|
2340
|
+
"""
|
2341
|
+
Add two relative orders or a relative order to an absolute
|
2342
|
+
order (which always results in an absolute order).
|
2343
|
+
|
2344
|
+
EXAMPLES::
|
2345
|
+
|
2346
|
+
sage: x = polygen(ZZ, 'x')
|
2347
|
+
sage: K.<a,b> = NumberField([x^2 + 1, x^2 + 3])
|
2348
|
+
sage: O2 = K.order([2*a, b]); O2.absolute_discriminant()
|
2349
|
+
36864
|
2350
|
+
sage: O3 = K.order([3*a, 2*b]); O3.absolute_discriminant()
|
2351
|
+
2985984
|
2352
|
+
sage: R = O2 + O3; R
|
2353
|
+
Relative Order generated by [-2*a + b, -2*b*a - 4, -5*a + 3*b] in Number Field in a with defining polynomial x^2 + 1 over its base field
|
2354
|
+
sage: R.absolute_discriminant()
|
2355
|
+
9216
|
2356
|
+
sage: R.is_suborder(O2)
|
2357
|
+
False
|
2358
|
+
sage: O2.is_suborder(R)
|
2359
|
+
True
|
2360
|
+
sage: O3.is_suborder(R)
|
2361
|
+
True
|
2362
|
+
"""
|
2363
|
+
if isinstance(right, Order_absolute):
|
2364
|
+
return left._absolute_order + right
|
2365
|
+
|
2366
|
+
if not isinstance(right, Order_relative):
|
2367
|
+
raise NotImplementedError("cannot add these orders yet")
|
2368
|
+
|
2369
|
+
if left._K != right._K:
|
2370
|
+
raise TypeError("number fields do not match")
|
2371
|
+
|
2372
|
+
if left._is_maximal():
|
2373
|
+
return left
|
2374
|
+
|
2375
|
+
if right._is_maximal():
|
2376
|
+
return right
|
2377
|
+
|
2378
|
+
return RelativeOrder(left._K, left._absolute_order + right._absolute_order, check=False)
|
2379
|
+
|
2380
|
+
def __and__(left, right):
|
2381
|
+
"""
|
2382
|
+
Intersect two relative orders or a relative and absolute order
|
2383
|
+
(which always results in an absolute order).
|
2384
|
+
|
2385
|
+
EXAMPLES::
|
2386
|
+
|
2387
|
+
sage: x = polygen(ZZ, 'x')
|
2388
|
+
sage: L.<a, b> = NumberField([x^2 + 1, x^2 - 5])
|
2389
|
+
sage: O1 = L.order([a, 2*b])
|
2390
|
+
sage: O2 = L.order([2*a, b])
|
2391
|
+
sage: O3 = O1 & O2; O3
|
2392
|
+
Relative Order generated by [12*a - 2*b, -2*b*a + 4, 14*a - 2*b] in Number Field in a with defining polynomial x^2 + 1 over its base field
|
2393
|
+
sage: O3.index_in(L.maximal_order())
|
2394
|
+
32
|
2395
|
+
|
2396
|
+
TESTS:
|
2397
|
+
|
2398
|
+
Verify that :issue:`33386` has been resolved::
|
2399
|
+
|
2400
|
+
sage: (L.maximal_order() & L.maximal_order()).is_maximal()
|
2401
|
+
True
|
2402
|
+
"""
|
2403
|
+
if isinstance(right, Order_absolute):
|
2404
|
+
return left._absolute_order & right
|
2405
|
+
|
2406
|
+
if not isinstance(right, Order_relative):
|
2407
|
+
raise NotImplementedError("cannot intersect these orders yet")
|
2408
|
+
|
2409
|
+
if left._K != right._K:
|
2410
|
+
raise TypeError("number fields do not match")
|
2411
|
+
|
2412
|
+
return RelativeOrder(left._K, left._absolute_order & right._absolute_order, check=False)
|
2413
|
+
|
2414
|
+
def is_maximal(self, p=None):
|
2415
|
+
"""
|
2416
|
+
Return whether this is the maximal order.
|
2417
|
+
|
2418
|
+
INPUT:
|
2419
|
+
|
2420
|
+
- ``p`` -- integer prime or ``None`` (default: ``None``); if
|
2421
|
+
set, return whether this order is maximal at the prime `p`
|
2422
|
+
|
2423
|
+
EXAMPLES::
|
2424
|
+
|
2425
|
+
sage: x = polygen(ZZ, 'x')
|
2426
|
+
sage: K.<a, b> = NumberField([x^2 + 1, x^2 - 5])
|
2427
|
+
|
2428
|
+
sage: K.order(3*a, b).is_maximal()
|
2429
|
+
False
|
2430
|
+
sage: K.order(5*a, b/2 + 1/2).is_maximal()
|
2431
|
+
False
|
2432
|
+
sage: (K.order(3*a, b) + K.order(5*a, b/2 + 1/2)).is_maximal()
|
2433
|
+
True
|
2434
|
+
sage: K.maximal_order().is_maximal()
|
2435
|
+
True
|
2436
|
+
|
2437
|
+
Maximality can be checked at primes when the order is maximal at that
|
2438
|
+
prime by construction::
|
2439
|
+
|
2440
|
+
sage: K.maximal_order().is_maximal(p=3)
|
2441
|
+
True
|
2442
|
+
|
2443
|
+
And at other primes::
|
2444
|
+
|
2445
|
+
sage: K.order(3*a, b).is_maximal(p=3)
|
2446
|
+
False
|
2447
|
+
"""
|
2448
|
+
return self._absolute_order.is_maximal(p=p)
|
2449
|
+
|
2450
|
+
def _is_maximal(self):
|
2451
|
+
r"""
|
2452
|
+
Return whether this order is already known to be maximal.
|
2453
|
+
|
2454
|
+
EXAMPLES::
|
2455
|
+
|
2456
|
+
sage: x = polygen(ZZ, 'x')
|
2457
|
+
sage: K.<a, b> = NumberField([x^2 + 1, x^2 - 5])
|
2458
|
+
sage: O = K.order(a, b)
|
2459
|
+
sage: O._is_maximal() is None
|
2460
|
+
True
|
2461
|
+
sage: O.is_maximal()
|
2462
|
+
False
|
2463
|
+
sage: O._is_maximal()
|
2464
|
+
False
|
2465
|
+
"""
|
2466
|
+
return self._absolute_order._is_maximal()
|
2467
|
+
|
2468
|
+
def _is_maximal_at(self, p=None):
|
2469
|
+
r"""
|
2470
|
+
Return whether this order is already known to be maximal at ``p``.
|
2471
|
+
|
2472
|
+
When no ``p`` is specified, returns a dictionary of primes for which
|
2473
|
+
maximality is known.
|
2474
|
+
|
2475
|
+
EXAMPLES::
|
2476
|
+
|
2477
|
+
sage: x = polygen(ZZ, 'x')
|
2478
|
+
sage: K.<a, b> = NumberField([x^2 - 2, x^13 - 2])
|
2479
|
+
sage: O = K.maximal_order([2, 3, 5], assume_maximal=None)
|
2480
|
+
sage: O._is_maximal_at(p=7) is None
|
2481
|
+
True
|
2482
|
+
sage: O = K.maximal_order([2, 3, 7], assume_maximal=None)
|
2483
|
+
sage: O._is_maximal_at(p=5)
|
2484
|
+
True
|
2485
|
+
sage: O._is_maximal_at(p=7)
|
2486
|
+
True
|
2487
|
+
sage: O._is_maximal_at()
|
2488
|
+
{2: True, 3: True, 5: True, 7: True}
|
2489
|
+
"""
|
2490
|
+
return self._absolute_order._is_maximal_at(p=p)
|
2491
|
+
|
2492
|
+
def _assume_maximal(self, is_maximal=True, p=None):
|
2493
|
+
r"""
|
2494
|
+
Record that this order ``is_maximal`` at the integer prime ``p``.
|
2495
|
+
|
2496
|
+
To support the deprecated behavior for
|
2497
|
+
``is_maximal="non-maximal-non-unique"``, this returns an order.
|
2498
|
+
Typically, the order itself.
|
2499
|
+
|
2500
|
+
EXAMPLES::
|
2501
|
+
|
2502
|
+
sage: x = polygen(ZZ, 'x')
|
2503
|
+
sage: L.<a, b> = NumberField([x^2 - 1000005, x^2 - 5*1000099^2])
|
2504
|
+
sage: O = L.maximal_order([13], assume_maximal=None)
|
2505
|
+
|
2506
|
+
We can store information about more primes::
|
2507
|
+
|
2508
|
+
sage: O._is_maximal_at(p=7) is None
|
2509
|
+
True
|
2510
|
+
sage: 7.divides(L.absolute_discriminant())
|
2511
|
+
False
|
2512
|
+
sage: O._assume_maximal(p=7) is O
|
2513
|
+
True
|
2514
|
+
sage: O._is_maximal_at(p=7)
|
2515
|
+
True
|
2516
|
+
|
2517
|
+
We cannot store contradicting information at a prime::
|
2518
|
+
|
2519
|
+
sage: O._assume_maximal(p=7, is_maximal=False)
|
2520
|
+
Traceback (most recent call last):
|
2521
|
+
...
|
2522
|
+
ValueError: cannot assume this order to be non-maximal at 7 because we already found it to be maximal at that prime
|
2523
|
+
|
2524
|
+
We can safely store information that we know to be wrong to support
|
2525
|
+
legacy behavior of orders that are assumed to be only maximal at some
|
2526
|
+
primes::
|
2527
|
+
|
2528
|
+
sage: L.<a, b> = NumberField([x^2 - 2, x^3 - 2])
|
2529
|
+
sage: O = L.maximal_order([2, 3], assume_maximal=None)
|
2530
|
+
sage: O.is_maximal()
|
2531
|
+
True
|
2532
|
+
sage: N = O._assume_maximal(is_maximal='non-maximal-non-unique')
|
2533
|
+
sage: N._assume_maximal(p=2) is N
|
2534
|
+
True
|
2535
|
+
sage: N is O
|
2536
|
+
False
|
2537
|
+
sage: N == O
|
2538
|
+
True
|
2539
|
+
sage: N.is_maximal()
|
2540
|
+
False
|
2541
|
+
sage: N.is_maximal(p=2)
|
2542
|
+
True
|
2543
|
+
"""
|
2544
|
+
absolute_order = self._absolute_order._assume_maximal(is_maximal=is_maximal, p=p)
|
2545
|
+
if absolute_order is not self._absolute_order:
|
2546
|
+
assert is_maximal == "non-maximal-non-unique"
|
2547
|
+
self = type(self)(self._K, absolute_order)
|
2548
|
+
return self
|
2549
|
+
|
2550
|
+
def absolute_discriminant(self):
|
2551
|
+
"""
|
2552
|
+
Return the absolute discriminant of ``self``, which is the discriminant
|
2553
|
+
of the absolute order associated to ``self``.
|
2554
|
+
|
2555
|
+
OUTPUT: integer
|
2556
|
+
|
2557
|
+
EXAMPLES::
|
2558
|
+
|
2559
|
+
sage: x = polygen(ZZ, 'x')
|
2560
|
+
sage: R = EquationOrder([x^2 + 1, x^3 + 2], 'a,b')
|
2561
|
+
sage: d = R.absolute_discriminant(); d
|
2562
|
+
-746496
|
2563
|
+
sage: d is R.absolute_discriminant()
|
2564
|
+
True
|
2565
|
+
sage: factor(d)
|
2566
|
+
-1 * 2^10 * 3^6
|
2567
|
+
"""
|
2568
|
+
return self.absolute_order().discriminant()
|
2569
|
+
|
2570
|
+
def is_suborder(self, other):
|
2571
|
+
"""
|
2572
|
+
Return ``True`` if ``self`` is a subset of the order ``other``.
|
2573
|
+
|
2574
|
+
EXAMPLES::
|
2575
|
+
|
2576
|
+
sage: x = polygen(ZZ, 'x')
|
2577
|
+
sage: K.<a,b> = NumberField([x^2 + 1, x^3 + 2])
|
2578
|
+
sage: R1 = K.order([a, b])
|
2579
|
+
sage: R2 = K.order([2*a, b])
|
2580
|
+
sage: R3 = K.order([a + b, b + 2*a])
|
2581
|
+
sage: R1.is_suborder(R2)
|
2582
|
+
False
|
2583
|
+
sage: R2.is_suborder(R1)
|
2584
|
+
True
|
2585
|
+
sage: R3.is_suborder(R1)
|
2586
|
+
True
|
2587
|
+
sage: R1.is_suborder(R3)
|
2588
|
+
True
|
2589
|
+
sage: R1 == R3
|
2590
|
+
True
|
2591
|
+
"""
|
2592
|
+
return self.absolute_order().is_suborder(other.absolute_order())
|
2593
|
+
|
2594
|
+
def index_in(self, other):
|
2595
|
+
"""
|
2596
|
+
Return the index of ``self`` in ``other``.
|
2597
|
+
|
2598
|
+
This is a lattice index,
|
2599
|
+
so it is a rational number if ``self`` is not contained in ``other``.
|
2600
|
+
|
2601
|
+
INPUT:
|
2602
|
+
|
2603
|
+
- ``other`` -- another order with the same ambient absolute number field
|
2604
|
+
|
2605
|
+
OUTPUT: a rational number
|
2606
|
+
|
2607
|
+
EXAMPLES::
|
2608
|
+
|
2609
|
+
sage: x = polygen(ZZ, 'x')
|
2610
|
+
sage: K.<a,b> = NumberField([x^3 + x + 3, x^2 + 1])
|
2611
|
+
sage: R1 = K.order([3*a, 2*b])
|
2612
|
+
sage: R2 = K.order([a, 4*b])
|
2613
|
+
sage: R1.index_in(R2)
|
2614
|
+
729/8
|
2615
|
+
sage: R2.index_in(R1)
|
2616
|
+
8/729
|
2617
|
+
"""
|
2618
|
+
if not isinstance(other, Order):
|
2619
|
+
raise TypeError("other must be an absolute order.")
|
2620
|
+
return self.absolute_order().index_in(other.absolute_order())
|
2621
|
+
|
2622
|
+
|
2623
|
+
def each_is_integral(v):
|
2624
|
+
"""
|
2625
|
+
Return whether every element of the list ``v`` of elements of a number
|
2626
|
+
field is integral.
|
2627
|
+
|
2628
|
+
EXAMPLES::
|
2629
|
+
|
2630
|
+
sage: x = polygen(ZZ, 'x')
|
2631
|
+
sage: W.<sqrt5> = NumberField(x^2 - 5)
|
2632
|
+
sage: from sage.rings.number_field.order import each_is_integral
|
2633
|
+
sage: each_is_integral([sqrt5, 2, (1+sqrt5)/2])
|
2634
|
+
True
|
2635
|
+
sage: each_is_integral([sqrt5, (1+sqrt5)/3])
|
2636
|
+
False
|
2637
|
+
"""
|
2638
|
+
return all(x.is_integral() for x in v)
|
2639
|
+
|
2640
|
+
|
2641
|
+
def absolute_order_from_ring_generators(gens, check_is_integral=True,
|
2642
|
+
check_rank=True, is_maximal=None,
|
2643
|
+
allow_subfield=False):
|
2644
|
+
"""
|
2645
|
+
INPUT:
|
2646
|
+
|
2647
|
+
- ``gens`` -- list of integral elements of an absolute order
|
2648
|
+
- ``check_is_integral`` -- boolean (default: ``True``); whether to check
|
2649
|
+
that each generator is integral
|
2650
|
+
- ``check_rank`` -- boolean (default: ``True``); whether to check that the
|
2651
|
+
ring generated by ``gens`` is of full rank
|
2652
|
+
- ``is_maximal`` -- boolean (or ``None``); set if maximality of the
|
2653
|
+
generated order is known
|
2654
|
+
- ``allow_subfield`` -- boolean (default: ``False``); if ``True`` and the
|
2655
|
+
generators do not generate an order, i.e., they generate a subring of
|
2656
|
+
smaller rank, instead of raising an error, return an order in a smaller
|
2657
|
+
number field
|
2658
|
+
|
2659
|
+
EXAMPLES::
|
2660
|
+
|
2661
|
+
sage: x = polygen(ZZ, 'x')
|
2662
|
+
sage: K.<a> = NumberField(x^4 - 5)
|
2663
|
+
sage: K.order(a)
|
2664
|
+
Order generated by a in Number Field in a with defining polynomial x^4 - 5
|
2665
|
+
|
2666
|
+
We have to explicitly import this function, since typically it is called
|
2667
|
+
with ``K.order`` as above.::
|
2668
|
+
|
2669
|
+
sage: from sage.rings.number_field.order import absolute_order_from_ring_generators
|
2670
|
+
sage: absolute_order_from_ring_generators([a])
|
2671
|
+
Order generated by a in Number Field in a with defining polynomial x^4 - 5
|
2672
|
+
sage: absolute_order_from_ring_generators([3*a, 2, 6*a + 1])
|
2673
|
+
Order generated by 3*a in Number Field in a with defining polynomial x^4 - 5
|
2674
|
+
|
2675
|
+
If one of the inputs is non-integral, it is an error.::
|
2676
|
+
|
2677
|
+
sage: absolute_order_from_ring_generators([a/2])
|
2678
|
+
Traceback (most recent call last):
|
2679
|
+
...
|
2680
|
+
ValueError: each generator must be integral
|
2681
|
+
|
2682
|
+
If the ``gens`` do not generate an order, i.e., generate a ring of full
|
2683
|
+
rank, then it is an error.::
|
2684
|
+
|
2685
|
+
sage: absolute_order_from_ring_generators([a^2])
|
2686
|
+
Traceback (most recent call last):
|
2687
|
+
...
|
2688
|
+
ValueError: the rank of the span of gens is wrong
|
2689
|
+
|
2690
|
+
Both checking for integrality and checking for full rank can be
|
2691
|
+
turned off in order to save time, though one can get nonsense as
|
2692
|
+
illustrated below.::
|
2693
|
+
|
2694
|
+
sage: absolute_order_from_ring_generators([a/2], check_is_integral=False)
|
2695
|
+
Order generated by [1, 1/2*a, 1/4*a^2, 1/8*a^3] in Number Field in a with defining polynomial x^4 - 5
|
2696
|
+
sage: absolute_order_from_ring_generators([a^2], check_rank=False)
|
2697
|
+
Order generated by a^2 in Number Field in a with defining polynomial x^4 - 5
|
2698
|
+
"""
|
2699
|
+
if check_is_integral and not each_is_integral(gens):
|
2700
|
+
raise ValueError("each generator must be integral")
|
2701
|
+
gens = Sequence(gens)
|
2702
|
+
n = [x.absolute_minpoly().degree() for x in gens]
|
2703
|
+
module_gens = monomials(gens, n)
|
2704
|
+
return absolute_order_from_module_generators(module_gens,
|
2705
|
+
check_integral=False,
|
2706
|
+
check_is_ring=False,
|
2707
|
+
check_rank=check_rank,
|
2708
|
+
is_maximal=is_maximal,
|
2709
|
+
allow_subfield=allow_subfield)
|
2710
|
+
|
2711
|
+
|
2712
|
+
def absolute_order_from_module_generators(gens,
|
2713
|
+
check_integral=True, check_rank=True,
|
2714
|
+
check_is_ring=True, is_maximal=None,
|
2715
|
+
allow_subfield=False, is_maximal_at=()):
|
2716
|
+
r"""
|
2717
|
+
INPUT:
|
2718
|
+
|
2719
|
+
- ``gens`` -- list of elements of an absolute number field that generates an
|
2720
|
+
order in that number field as a `\ZZ`-*module*
|
2721
|
+
- ``check_integral`` -- check that each generator is integral
|
2722
|
+
- ``check_rank`` -- check that the ``gens`` span a module of the correct
|
2723
|
+
rank
|
2724
|
+
- ``check_is_ring`` -- check that the module is closed under multiplication
|
2725
|
+
(this is very expensive)
|
2726
|
+
- ``is_maximal`` -- boolean (or ``None``); set if maximality of the
|
2727
|
+
generated order is known
|
2728
|
+
- ``is_maximal_at`` -- tuple of primes where this order is known to be
|
2729
|
+
maximal
|
2730
|
+
|
2731
|
+
OUTPUT: an absolute order
|
2732
|
+
|
2733
|
+
EXAMPLES:
|
2734
|
+
|
2735
|
+
We have to explicitly import the function, since it is not meant
|
2736
|
+
for regular usage::
|
2737
|
+
|
2738
|
+
sage: from sage.rings.number_field.order import absolute_order_from_module_generators
|
2739
|
+
|
2740
|
+
sage: x = polygen(ZZ, 'x')
|
2741
|
+
sage: K.<a> = NumberField(x^4 - 5)
|
2742
|
+
sage: O = K.maximal_order(); O
|
2743
|
+
Maximal Order generated by [1/2*a^2 + 1/2, 1/2*a^3 + 1/2*a] in Number Field in a with defining polynomial x^4 - 5
|
2744
|
+
sage: O.basis()
|
2745
|
+
[1/2*a^2 + 1/2, 1/2*a^3 + 1/2*a, a^2, a^3]
|
2746
|
+
sage: O.module()
|
2747
|
+
Free module of degree 4 and rank 4 over Integer Ring
|
2748
|
+
Echelon basis matrix:
|
2749
|
+
[1/2 0 1/2 0]
|
2750
|
+
[ 0 1/2 0 1/2]
|
2751
|
+
[ 0 0 1 0]
|
2752
|
+
[ 0 0 0 1]
|
2753
|
+
sage: g = O.basis(); g
|
2754
|
+
[1/2*a^2 + 1/2, 1/2*a^3 + 1/2*a, a^2, a^3]
|
2755
|
+
sage: absolute_order_from_module_generators(g)
|
2756
|
+
Maximal Order generated by [1/2*a^2 + 1/2, 1/2*a^3 + 1/2*a] in Number Field in a with defining polynomial x^4 - 5
|
2757
|
+
|
2758
|
+
We illustrate each check flag -- the output is the same but in case
|
2759
|
+
the function would run ever so slightly faster::
|
2760
|
+
|
2761
|
+
sage: absolute_order_from_module_generators(g, check_is_ring=False)
|
2762
|
+
Maximal Order generated by [1/2*a^2 + 1/2, 1/2*a^3 + 1/2*a] in Number Field in a with defining polynomial x^4 - 5
|
2763
|
+
sage: absolute_order_from_module_generators(g, check_rank=False)
|
2764
|
+
Maximal Order generated by [1/2*a^2 + 1/2, 1/2*a^3 + 1/2*a] in Number Field in a with defining polynomial x^4 - 5
|
2765
|
+
sage: absolute_order_from_module_generators(g, check_integral=False)
|
2766
|
+
Maximal Order generated by [1/2*a^2 + 1/2, 1/2*a^3 + 1/2*a] in Number Field in a with defining polynomial x^4 - 5
|
2767
|
+
|
2768
|
+
Next we illustrate constructing "fake" orders to illustrate turning
|
2769
|
+
off various check flags::
|
2770
|
+
|
2771
|
+
sage: k.<i> = NumberField(x^2 + 1)
|
2772
|
+
sage: R = absolute_order_from_module_generators([2, 2*i],
|
2773
|
+
....: check_is_ring=False); R
|
2774
|
+
Order of conductor 4 generated by [2, 2*i]
|
2775
|
+
in Number Field in i with defining polynomial x^2 + 1
|
2776
|
+
sage: R.basis()
|
2777
|
+
[2, 2*i]
|
2778
|
+
sage: R = absolute_order_from_module_generators([k(1)], # needs sage.symbolic
|
2779
|
+
....: check_rank=False); R
|
2780
|
+
Order of conductor I generated by []
|
2781
|
+
in Number Field in i with defining polynomial x^2 + 1
|
2782
|
+
sage: R.basis() # needs sage.symbolic
|
2783
|
+
[1]
|
2784
|
+
|
2785
|
+
If the order contains a non-integral element, even if we do not check
|
2786
|
+
that, we will find that the rank is wrong or that the order is not closed
|
2787
|
+
under multiplication::
|
2788
|
+
|
2789
|
+
sage: absolute_order_from_module_generators([1/2, i],
|
2790
|
+
....: check_integral=False)
|
2791
|
+
Traceback (most recent call last):
|
2792
|
+
...
|
2793
|
+
ValueError: the module span of the gens is not closed under multiplication.
|
2794
|
+
sage: R = absolute_order_from_module_generators([1/2, i],
|
2795
|
+
....: check_is_ring=False,
|
2796
|
+
....: check_integral=False); R
|
2797
|
+
Order of conductor 0 generated by [1/2, i] in Number Field in i with defining polynomial x^2 + 1
|
2798
|
+
sage: R.basis()
|
2799
|
+
[1/2, i]
|
2800
|
+
|
2801
|
+
We turn off all check flags and make a really messed up order::
|
2802
|
+
|
2803
|
+
sage: R = absolute_order_from_module_generators([1/2, i],
|
2804
|
+
....: check_is_ring=False,
|
2805
|
+
....: check_integral=False,
|
2806
|
+
....: check_rank=False); R
|
2807
|
+
Order of conductor 0 generated by [1/2, i] in Number Field in i with defining polynomial x^2 + 1
|
2808
|
+
sage: R.basis()
|
2809
|
+
[1/2, i]
|
2810
|
+
|
2811
|
+
An order that lives in a subfield::
|
2812
|
+
|
2813
|
+
sage: F.<alpha> = NumberField(x**4 + 3)
|
2814
|
+
sage: F.order([alpha**2], allow_subfield=True)
|
2815
|
+
Order of conductor 2 generated by ... in Number Field in beta with defining polynomial ... with beta = ...
|
2816
|
+
"""
|
2817
|
+
if not gens:
|
2818
|
+
raise ValueError("gens must span an order over ZZ")
|
2819
|
+
gens = Sequence(gens)
|
2820
|
+
if check_integral and not each_is_integral(gens):
|
2821
|
+
raise ValueError("each generator must be integral")
|
2822
|
+
|
2823
|
+
K = gens.universe()
|
2824
|
+
if isinstance(K, Order) or K == ZZ:
|
2825
|
+
K = K.number_field()
|
2826
|
+
V, from_V, to_V = K.vector_space()
|
2827
|
+
mod_gens = [to_V(x) for x in gens]
|
2828
|
+
ambient = ZZ**V.dimension()
|
2829
|
+
W = ambient.span(mod_gens)
|
2830
|
+
|
2831
|
+
if allow_subfield:
|
2832
|
+
if W.rank() < K.degree():
|
2833
|
+
# We have to make the order in a smaller field.
|
2834
|
+
# We do this by choosing a random element of W,
|
2835
|
+
# moving it back to K, and checking that it defines
|
2836
|
+
# a field of degree equal to the degree of W.
|
2837
|
+
# Then we move everything into that field, where
|
2838
|
+
# W does define an order.
|
2839
|
+
while True:
|
2840
|
+
alpha = from_V(W.random_element())
|
2841
|
+
if alpha.minpoly().degree() == W.rank():
|
2842
|
+
break
|
2843
|
+
# Now alpha generates a subfield where W is an order
|
2844
|
+
# (with the right rank).
|
2845
|
+
# We move each generator of W to this subfield.
|
2846
|
+
K, _ = K.subfield(alpha, 'beta')
|
2847
|
+
gens = [K(x) for x in gens]
|
2848
|
+
V, from_V, to_V = K.vector_space()
|
2849
|
+
mod_gens = [to_V(x) for x in gens]
|
2850
|
+
ambient = ZZ**V.dimension()
|
2851
|
+
W = ambient.span(mod_gens)
|
2852
|
+
|
2853
|
+
elif check_rank:
|
2854
|
+
if W.rank() != K.degree():
|
2855
|
+
raise ValueError("the rank of the span of gens is wrong")
|
2856
|
+
|
2857
|
+
if check_is_ring:
|
2858
|
+
if any(to_V(x * y) not in W for x in gens for y in gens):
|
2859
|
+
raise ValueError("the module span of the gens is not closed under multiplication.")
|
2860
|
+
|
2861
|
+
return AbsoluteOrder(K, W, check=False, is_maximal=is_maximal, is_maximal_at=is_maximal_at)
|
2862
|
+
|
2863
|
+
|
2864
|
+
def relative_order_from_ring_generators(gens,
|
2865
|
+
check_is_integral=True,
|
2866
|
+
check_rank=True,
|
2867
|
+
is_maximal=None,
|
2868
|
+
allow_subfield=False,
|
2869
|
+
is_maximal_at=()):
|
2870
|
+
"""
|
2871
|
+
INPUT:
|
2872
|
+
|
2873
|
+
- ``gens`` -- list of integral elements of an absolute order
|
2874
|
+
- ``check_is_integral`` -- boolean (default: ``True``); whether to check
|
2875
|
+
that each generator is integral
|
2876
|
+
- ``check_rank`` -- boolean (default: ``True``); whether to check that the
|
2877
|
+
ring generated by ``gens`` is of full rank
|
2878
|
+
- ``is_maximal`` -- boolean (or ``None``); set if maximality of the
|
2879
|
+
generated order is known
|
2880
|
+
|
2881
|
+
EXAMPLES:
|
2882
|
+
|
2883
|
+
We have to explicitly import this function, since it is not meant
|
2884
|
+
for regular usage::
|
2885
|
+
|
2886
|
+
sage: from sage.rings.number_field.order import relative_order_from_ring_generators
|
2887
|
+
sage: x = polygen(ZZ, 'x')
|
2888
|
+
sage: K.<i, a> = NumberField([x^2 + 1, x^2 - 17])
|
2889
|
+
sage: R = K.base_field().maximal_order()
|
2890
|
+
sage: S = relative_order_from_ring_generators([i,a]); S
|
2891
|
+
Relative Order generated by [7*i - 2*a, -a*i + 8, 25*i - 7*a] in
|
2892
|
+
Number Field in i with defining polynomial x^2 + 1 over its base field
|
2893
|
+
|
2894
|
+
Basis for the relative order, which is obtained by computing the algebra generated
|
2895
|
+
by i and a::
|
2896
|
+
|
2897
|
+
sage: S.basis()
|
2898
|
+
[1, 7*i - 2*a, -a*i + 8, 25*i - 7*a]
|
2899
|
+
"""
|
2900
|
+
if check_is_integral and not each_is_integral(gens):
|
2901
|
+
raise ValueError("each generator must be integral")
|
2902
|
+
gens = Sequence(gens)
|
2903
|
+
|
2904
|
+
# The top number field that contains the order.
|
2905
|
+
K = gens.universe()
|
2906
|
+
|
2907
|
+
# The absolute version of that field.
|
2908
|
+
Kabs = K.absolute_field('z')
|
2909
|
+
from_Kabs, to_Kabs = Kabs.structure()
|
2910
|
+
|
2911
|
+
module_gens = [to_Kabs(a) for a in gens]
|
2912
|
+
n = [a.absolute_minpoly().degree() for a in gens]
|
2913
|
+
absolute_order_module_gens = monomials(module_gens, n)
|
2914
|
+
|
2915
|
+
abs_order = absolute_order_from_module_generators(absolute_order_module_gens,
|
2916
|
+
check_integral=False,
|
2917
|
+
check_is_ring=False,
|
2918
|
+
check_rank=check_rank,
|
2919
|
+
is_maximal=is_maximal,
|
2920
|
+
is_maximal_at=is_maximal_at)
|
2921
|
+
|
2922
|
+
return RelativeOrder(K, abs_order, check=False)
|
2923
|
+
|
2924
|
+
|
2925
|
+
def GaussianIntegers(names='I', latex_name='i'):
|
2926
|
+
r"""
|
2927
|
+
Return the ring of Gaussian integers.
|
2928
|
+
|
2929
|
+
This is the ring of all complex numbers
|
2930
|
+
of the form `a + b I` with `a` and `b` integers and `I = \sqrt{-1}`.
|
2931
|
+
|
2932
|
+
EXAMPLES::
|
2933
|
+
|
2934
|
+
sage: ZZI.<I> = GaussianIntegers()
|
2935
|
+
sage: ZZI
|
2936
|
+
Gaussian Integers generated by I in Number Field in I with defining polynomial x^2 + 1 with I = 1*I
|
2937
|
+
sage: factor(3 + I)
|
2938
|
+
(-2*I - 1) * (I - 1)
|
2939
|
+
sage: CC(I)
|
2940
|
+
1.00000000000000*I
|
2941
|
+
sage: I.minpoly()
|
2942
|
+
x^2 + 1
|
2943
|
+
sage: GaussianIntegers().basis()
|
2944
|
+
[1, I]
|
2945
|
+
"""
|
2946
|
+
from sage.rings.complex_double import CDF
|
2947
|
+
from sage.rings.number_field.number_field import NumberField
|
2948
|
+
f = ZZ['x']([1, 0, 1])
|
2949
|
+
nf = NumberField(f, names, embedding=CDF(0, 1), latex_name=latex_name)
|
2950
|
+
return nf.ring_of_integers()
|
2951
|
+
|
2952
|
+
|
2953
|
+
def EisensteinIntegers(names='omega'):
|
2954
|
+
r"""
|
2955
|
+
Return the ring of Eisenstein integers.
|
2956
|
+
|
2957
|
+
This is the ring of all complex numbers
|
2958
|
+
of the form `a + b \omega` with `a` and `b` integers and
|
2959
|
+
`\omega = (-1 + \sqrt{-3})/2`.
|
2960
|
+
|
2961
|
+
EXAMPLES::
|
2962
|
+
|
2963
|
+
sage: R.<omega> = EisensteinIntegers()
|
2964
|
+
sage: R
|
2965
|
+
Eisenstein Integers generated by omega in Number Field in omega
|
2966
|
+
with defining polynomial x^2 + x + 1
|
2967
|
+
with omega = -0.50000000000000000? + 0.866025403784439?*I
|
2968
|
+
sage: factor(3 + omega)
|
2969
|
+
(omega) * (-3*omega - 2)
|
2970
|
+
sage: CC(omega)
|
2971
|
+
-0.500000000000000 + 0.866025403784439*I
|
2972
|
+
sage: omega.minpoly()
|
2973
|
+
x^2 + x + 1
|
2974
|
+
sage: EisensteinIntegers().basis()
|
2975
|
+
[1, omega]
|
2976
|
+
"""
|
2977
|
+
from sage.rings.complex_double import CDF
|
2978
|
+
from sage.rings.number_field.number_field import NumberField
|
2979
|
+
f = ZZ['x']([1, 1, 1])
|
2980
|
+
nf = NumberField(f, names, embedding=CDF(-0.5, 0.8660254037844386))
|
2981
|
+
return nf.ring_of_integers()
|