passagemath-pari 10.6.32__cp314-cp314-musllinux_1_2_x86_64.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.
Potentially problematic release.
This version of passagemath-pari might be problematic. Click here for more details.
- PARIKernel/__init__.py +2 -0
- PARIKernel/__main__.py +5 -0
- PARIKernel/io.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/io.pxd +7 -0
- PARIKernel/io.pyx +84 -0
- PARIKernel/kernel.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/kernel.pyx +260 -0
- PARIKernel/paridecl.pxd +95 -0
- PARIKernel/svg.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/svg.pyx +52 -0
- cypari2/__init__.py +8 -0
- cypari2/auto_paridecl.pxd +1070 -0
- cypari2/closure.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/closure.pxd +5 -0
- cypari2/closure.pyx +246 -0
- cypari2/convert.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/convert.pxd +80 -0
- cypari2/convert.pyx +613 -0
- cypari2/custom_block.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/custom_block.pyx +30 -0
- cypari2/cypari.h +13 -0
- cypari2/gen.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/gen.pxd +69 -0
- cypari2/gen.pyx +4819 -0
- cypari2/handle_error.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/handle_error.pxd +7 -0
- cypari2/handle_error.pyx +232 -0
- cypari2/pari_instance.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/pari_instance.pxd +27 -0
- cypari2/pari_instance.pyx +1438 -0
- cypari2/paridecl.pxd +5353 -0
- cypari2/paripriv.pxd +34 -0
- cypari2/pycore_long.h +98 -0
- cypari2/pycore_long.pxd +9 -0
- cypari2/stack.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/stack.pxd +27 -0
- cypari2/stack.pyx +278 -0
- cypari2/string_utils.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/string_utils.pxd +29 -0
- cypari2/string_utils.pyx +65 -0
- cypari2/types.pxd +147 -0
- passagemath_pari-10.6.32.data/data/etc/jupyter/nbconfig/notebook.d/gp-mode.json +5 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.js +28 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.json +6 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/logo-64x64.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/kernel.json +13 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-32x32.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-64x64.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-svg.svg +75 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/gp.js +284 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/main.js +15 -0
- passagemath_pari-10.6.32.dist-info/METADATA +209 -0
- passagemath_pari-10.6.32.dist-info/RECORD +331 -0
- passagemath_pari-10.6.32.dist-info/WHEEL +5 -0
- passagemath_pari-10.6.32.dist-info/top_level.txt +4 -0
- passagemath_pari.libs/libcrypto-f04afe95.so.3 +0 -0
- passagemath_pari.libs/libflint-fd6f12fc.so.21.0.0 +0 -0
- passagemath_pari.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_pari.libs/libgf2x-9e30c3e3.so.3.0.0 +0 -0
- passagemath_pari.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
- passagemath_pari.libs/libgivaro-9a94c711.so.9.2.1 +0 -0
- passagemath_pari.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_pari.libs/libgmpxx-9e08595c.so.4.7.0 +0 -0
- passagemath_pari.libs/libgsl-42cda06f.so.28.0.0 +0 -0
- passagemath_pari.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
- passagemath_pari.libs/libncursesw-9c9e32c3.so.6.5 +0 -0
- passagemath_pari.libs/libntl-26885ca2.so.44.0.1 +0 -0
- passagemath_pari.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
- passagemath_pari.libs/libpari-gmp-tls-f31f908f.so.2.17.2 +0 -0
- passagemath_pari.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
- passagemath_pari.libs/libreadline-06542304.so.8.2 +0 -0
- passagemath_pari.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
- passagemath_pari.libs/libuuid-f3770415.so.1.3.0 +0 -0
- passagemath_pari.libs/libxeus-735780ff.so.13.1.0 +0 -0
- passagemath_pari.libs/libxeus-zmq-c68577b4.so.6.0.1 +0 -0
- passagemath_pari.libs/libzmq-1ba9a3da.so.5.2.5 +0 -0
- sage/all__sagemath_pari.py +26 -0
- sage/databases/all__sagemath_pari.py +7 -0
- sage/databases/conway.py +274 -0
- sage/ext/all__sagemath_pari.py +1 -0
- sage/ext/memory.cpython-314-x86_64-linux-musl.so +0 -0
- sage/ext/memory.pyx +98 -0
- sage/ext_data/pari/buzzard/DimensionSk.g +286 -0
- sage/ext_data/pari/buzzard/Tpprog.g +179 -0
- sage/ext_data/pari/buzzard/genusn.g +129 -0
- sage/ext_data/pari/dokchitser/computel.gp +740 -0
- sage/ext_data/pari/dokchitser/computel.gp.template +740 -0
- sage/ext_data/pari/dokchitser/ex-bsw +43 -0
- sage/ext_data/pari/dokchitser/ex-chgen +48 -0
- sage/ext_data/pari/dokchitser/ex-chqua +37 -0
- sage/ext_data/pari/dokchitser/ex-delta +35 -0
- sage/ext_data/pari/dokchitser/ex-eisen +30 -0
- sage/ext_data/pari/dokchitser/ex-gen2 +38 -0
- sage/ext_data/pari/dokchitser/ex-gen3 +49 -0
- sage/ext_data/pari/dokchitser/ex-gen4 +54 -0
- sage/ext_data/pari/dokchitser/ex-nf +48 -0
- sage/ext_data/pari/dokchitser/ex-shin +50 -0
- sage/ext_data/pari/dokchitser/ex-tau2 +30 -0
- sage/ext_data/pari/dokchitser/ex-zeta +27 -0
- sage/ext_data/pari/dokchitser/ex-zeta2 +47 -0
- sage/ext_data/pari/dokchitser/testall +13 -0
- sage/ext_data/pari/simon/ell.gp +2129 -0
- sage/ext_data/pari/simon/ellQ.gp +2151 -0
- sage/ext_data/pari/simon/ellcommon.gp +126 -0
- sage/ext_data/pari/simon/qfsolve.gp +722 -0
- sage/ext_data/pari/simon/resultant3.gp +306 -0
- sage/groups/all__sagemath_pari.py +3 -0
- sage/groups/pari_group.py +175 -0
- sage/interfaces/all__sagemath_pari.py +1 -0
- sage/interfaces/genus2reduction.py +464 -0
- sage/interfaces/gp.py +1114 -0
- sage/libs/all__sagemath_pari.py +2 -0
- sage/libs/linkages/__init__.py +1 -0
- sage/libs/linkages/padics/API.pxi +617 -0
- sage/libs/linkages/padics/Polynomial_ram.pxi +388 -0
- sage/libs/linkages/padics/Polynomial_shared.pxi +554 -0
- sage/libs/linkages/padics/__init__.py +1 -0
- sage/libs/linkages/padics/fmpz_poly_unram.pxi +869 -0
- sage/libs/linkages/padics/mpz.pxi +691 -0
- sage/libs/linkages/padics/relaxed/API.pxi +518 -0
- sage/libs/linkages/padics/relaxed/__init__.py +1 -0
- sage/libs/linkages/padics/relaxed/flint.pxi +543 -0
- sage/libs/linkages/padics/unram_shared.pxi +247 -0
- sage/libs/pari/__init__.py +210 -0
- sage/libs/pari/all.py +5 -0
- sage/libs/pari/convert_flint.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_flint.pxd +14 -0
- sage/libs/pari/convert_flint.pyx +159 -0
- sage/libs/pari/convert_gmp.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_gmp.pxd +14 -0
- sage/libs/pari/convert_gmp.pyx +210 -0
- sage/libs/pari/convert_sage.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage.pxd +16 -0
- sage/libs/pari/convert_sage.pyx +588 -0
- sage/libs/pari/convert_sage_complex_double.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_complex_double.pxd +14 -0
- sage/libs/pari/convert_sage_complex_double.pyx +132 -0
- sage/libs/pari/convert_sage_matrix.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_matrix.pyx +106 -0
- sage/libs/pari/convert_sage_real_double.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_real_double.pxd +5 -0
- sage/libs/pari/convert_sage_real_double.pyx +14 -0
- sage/libs/pari/convert_sage_real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_real_mpfr.pxd +7 -0
- sage/libs/pari/convert_sage_real_mpfr.pyx +108 -0
- sage/libs/pari/misc.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/misc.pxd +4 -0
- sage/libs/pari/misc.pyx +26 -0
- sage/libs/pari/tests.py +1848 -0
- sage/matrix/all__sagemath_pari.py +1 -0
- sage/matrix/matrix_integer_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_integer_pari.pyx +187 -0
- sage/matrix/matrix_rational_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_rational_pari.pyx +160 -0
- sage/quadratic_forms/all__sagemath_pari.py +10 -0
- sage/quadratic_forms/genera/all.py +9 -0
- sage/quadratic_forms/genera/genus.py +3506 -0
- sage/quadratic_forms/genera/normal_form.py +1519 -0
- sage/quadratic_forms/genera/spinor_genus.py +243 -0
- sage/quadratic_forms/qfsolve.py +255 -0
- sage/quadratic_forms/quadratic_form__automorphisms.py +427 -0
- sage/quadratic_forms/quadratic_form__genus.py +141 -0
- sage/quadratic_forms/quadratic_form__local_density_interfaces.py +140 -0
- sage/quadratic_forms/quadratic_form__local_normal_form.py +421 -0
- sage/quadratic_forms/quadratic_form__local_representation_conditions.py +889 -0
- sage/quadratic_forms/quadratic_form__mass.py +69 -0
- sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +663 -0
- sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py +373 -0
- sage/quadratic_forms/quadratic_form__siegel_product.py +198 -0
- sage/quadratic_forms/special_values.py +323 -0
- sage/rings/all__sagemath_pari.py +15 -0
- sage/rings/factorint_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/factorint_pari.pyx +80 -0
- sage/rings/finite_rings/all__sagemath_pari.py +1 -0
- sage/rings/finite_rings/element_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_givaro.pxd +91 -0
- sage/rings/finite_rings/element_givaro.pyx +1769 -0
- sage/rings/finite_rings/element_ntl_gf2e.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_ntl_gf2e.pxd +22 -0
- sage/rings/finite_rings/element_ntl_gf2e.pyx +1333 -0
- sage/rings/finite_rings/element_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_pari_ffelt.pxd +13 -0
- sage/rings/finite_rings/element_pari_ffelt.pyx +1441 -0
- sage/rings/finite_rings/finite_field_givaro.py +612 -0
- sage/rings/finite_rings/finite_field_pari_ffelt.py +238 -0
- sage/rings/finite_rings/hom_finite_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field_givaro.pxd +28 -0
- sage/rings/finite_rings/hom_finite_field_givaro.pyx +280 -0
- sage/rings/finite_rings/residue_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field_givaro.pyx +133 -0
- sage/rings/finite_rings/residue_field_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field_pari_ffelt.pyx +128 -0
- sage/rings/function_field/all__sagemath_pari.py +1 -0
- sage/rings/function_field/valuation.py +1450 -0
- sage/rings/function_field/valuation_ring.py +212 -0
- sage/rings/number_field/all__sagemath_pari.py +14 -0
- sage/rings/number_field/totallyreal.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/number_field/totallyreal.pyx +509 -0
- sage/rings/number_field/totallyreal_data.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/number_field/totallyreal_data.pxd +26 -0
- sage/rings/number_field/totallyreal_data.pyx +928 -0
- sage/rings/number_field/totallyreal_phc.py +144 -0
- sage/rings/number_field/totallyreal_rel.py +1018 -0
- sage/rings/padics/CA_template.pxi +1847 -0
- sage/rings/padics/CA_template_header.pxi +50 -0
- sage/rings/padics/CR_template.pxi +2563 -0
- sage/rings/padics/CR_template_header.pxi +57 -0
- sage/rings/padics/FM_template.pxi +1575 -0
- sage/rings/padics/FM_template_header.pxi +50 -0
- sage/rings/padics/FP_template.pxi +2176 -0
- sage/rings/padics/FP_template_header.pxi +57 -0
- sage/rings/padics/all.py +3 -0
- sage/rings/padics/all__sagemath_pari.py +11 -0
- sage/rings/padics/common_conversion.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/common_conversion.pxd +15 -0
- sage/rings/padics/common_conversion.pyx +508 -0
- sage/rings/padics/eisenstein_extension_generic.py +232 -0
- sage/rings/padics/factory.py +3623 -0
- sage/rings/padics/generic_nodes.py +1615 -0
- sage/rings/padics/lattice_precision.py +2889 -0
- sage/rings/padics/morphism.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/morphism.pxd +11 -0
- sage/rings/padics/morphism.pyx +366 -0
- sage/rings/padics/padic_base_generic.py +467 -0
- sage/rings/padics/padic_base_leaves.py +1235 -0
- sage/rings/padics/padic_capped_absolute_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_capped_absolute_element.pxd +15 -0
- sage/rings/padics/padic_capped_absolute_element.pyx +520 -0
- sage/rings/padics/padic_capped_relative_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_capped_relative_element.pxd +14 -0
- sage/rings/padics/padic_capped_relative_element.pyx +614 -0
- sage/rings/padics/padic_extension_generic.py +990 -0
- sage/rings/padics/padic_extension_leaves.py +738 -0
- sage/rings/padics/padic_fixed_mod_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_fixed_mod_element.pxd +15 -0
- sage/rings/padics/padic_fixed_mod_element.pyx +584 -0
- sage/rings/padics/padic_floating_point_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_floating_point_element.pxd +14 -0
- sage/rings/padics/padic_floating_point_element.pyx +447 -0
- sage/rings/padics/padic_generic_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_generic_element.pxd +48 -0
- sage/rings/padics/padic_generic_element.pyx +4642 -0
- sage/rings/padics/padic_lattice_element.py +1342 -0
- sage/rings/padics/padic_printing.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_printing.pxd +38 -0
- sage/rings/padics/padic_printing.pyx +1505 -0
- sage/rings/padics/padic_relaxed_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_relaxed_element.pxd +56 -0
- sage/rings/padics/padic_relaxed_element.pyx +18 -0
- sage/rings/padics/padic_relaxed_errors.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_relaxed_errors.pxd +11 -0
- sage/rings/padics/padic_relaxed_errors.pyx +71 -0
- sage/rings/padics/padic_template_element.pxi +1212 -0
- sage/rings/padics/padic_template_element_header.pxi +50 -0
- sage/rings/padics/padic_valuation.py +1423 -0
- sage/rings/padics/pow_computer_flint.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer_flint.pxd +38 -0
- sage/rings/padics/pow_computer_flint.pyx +641 -0
- sage/rings/padics/pow_computer_relative.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer_relative.pxd +29 -0
- sage/rings/padics/pow_computer_relative.pyx +415 -0
- sage/rings/padics/qadic_flint_CA.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_CA.pxd +21 -0
- sage/rings/padics/qadic_flint_CA.pyx +130 -0
- sage/rings/padics/qadic_flint_CR.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_CR.pxd +13 -0
- sage/rings/padics/qadic_flint_CR.pyx +172 -0
- sage/rings/padics/qadic_flint_FM.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_FM.pxd +14 -0
- sage/rings/padics/qadic_flint_FM.pyx +111 -0
- sage/rings/padics/qadic_flint_FP.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_FP.pxd +12 -0
- sage/rings/padics/qadic_flint_FP.pyx +165 -0
- sage/rings/padics/relative_extension_leaves.py +429 -0
- sage/rings/padics/relative_ramified_CA.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_CA.pxd +9 -0
- sage/rings/padics/relative_ramified_CA.pyx +33 -0
- sage/rings/padics/relative_ramified_CR.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_CR.pxd +8 -0
- sage/rings/padics/relative_ramified_CR.pyx +33 -0
- sage/rings/padics/relative_ramified_FM.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_FM.pxd +9 -0
- sage/rings/padics/relative_ramified_FM.pyx +33 -0
- sage/rings/padics/relative_ramified_FP.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_FP.pxd +8 -0
- sage/rings/padics/relative_ramified_FP.pyx +33 -0
- sage/rings/padics/relaxed_template.pxi +4229 -0
- sage/rings/padics/relaxed_template_header.pxi +160 -0
- sage/rings/padics/tests.py +35 -0
- sage/rings/padics/tutorial.py +341 -0
- sage/rings/padics/unramified_extension_generic.py +335 -0
- sage/rings/padics/witt_vector.py +917 -0
- sage/rings/padics/witt_vector_ring.py +934 -0
- sage/rings/pari_ring.py +235 -0
- sage/rings/polynomial/all__sagemath_pari.py +1 -0
- sage/rings/polynomial/padics/all.py +1 -0
- sage/rings/polynomial/padics/polynomial_padic.py +360 -0
- sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +1324 -0
- sage/rings/polynomial/padics/polynomial_padic_flat.py +72 -0
- sage/rings/power_series_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/power_series_pari.pxd +6 -0
- sage/rings/power_series_pari.pyx +934 -0
- sage/rings/tate_algebra.py +1282 -0
- sage/rings/tate_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/tate_algebra_element.pxd +49 -0
- sage/rings/tate_algebra_element.pyx +3464 -0
- sage/rings/tate_algebra_ideal.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/tate_algebra_ideal.pxd +7 -0
- sage/rings/tate_algebra_ideal.pyx +1307 -0
- sage/rings/valuation/all.py +7 -0
- sage/rings/valuation/augmented_valuation.py +2118 -0
- sage/rings/valuation/developing_valuation.py +362 -0
- sage/rings/valuation/gauss_valuation.py +812 -0
- sage/rings/valuation/inductive_valuation.py +1686 -0
- sage/rings/valuation/limit_valuation.py +946 -0
- sage/rings/valuation/mapped_valuation.py +656 -0
- sage/rings/valuation/scaled_valuation.py +322 -0
- sage/rings/valuation/trivial_valuation.py +382 -0
- sage/rings/valuation/valuation.py +1119 -0
- sage/rings/valuation/valuation_space.py +1615 -0
- sage/rings/valuation/valuations_catalog.py +10 -0
- sage/rings/valuation/value_group.py +697 -0
- sage/schemes/all__sagemath_pari.py +1 -0
- sage/schemes/elliptic_curves/all__sagemath_pari.py +1 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.pyx +46 -0
- sage_wheels/bin/gp +0 -0
- sage_wheels/bin/gp2c +0 -0
- sage_wheels/bin/gp2c-run +57 -0
- sage_wheels/bin/xeus-gp +0 -0
- sage_wheels/share/gp2c/func.dsc +18414 -0
|
@@ -0,0 +1,1769 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
# distutils: libraries = givaro gmp M_LIBRARIES
|
|
3
|
+
# distutils: language = c++
|
|
4
|
+
r"""
|
|
5
|
+
Givaro finite field elements
|
|
6
|
+
|
|
7
|
+
Sage includes the Givaro finite field library, for highly optimized
|
|
8
|
+
arithmetic in finite fields.
|
|
9
|
+
|
|
10
|
+
.. NOTE::
|
|
11
|
+
|
|
12
|
+
The arithmetic is performed by the Givaro C++ library which uses
|
|
13
|
+
Zech logs internally to represent finite field elements. This
|
|
14
|
+
implementation is the default finite extension field implementation
|
|
15
|
+
in Sage for the cardinality less than `2^{16}`, as it is a lot
|
|
16
|
+
faster than the PARI implementation. Some functionality in this
|
|
17
|
+
class however is implemented using PARI.
|
|
18
|
+
|
|
19
|
+
EXAMPLES::
|
|
20
|
+
|
|
21
|
+
sage: k = GF(5); type(k)
|
|
22
|
+
<class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
|
|
23
|
+
sage: k = GF(5^2,'c'); type(k)
|
|
24
|
+
<class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
|
|
25
|
+
sage: k = GF(2^16,'c'); type(k) # needs sage.libs.ntl
|
|
26
|
+
<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
|
|
27
|
+
sage: k = GF(3^16,'c'); type(k)
|
|
28
|
+
<class 'sage.rings.finite_rings.finite_field_pari_ffelt.FiniteField_pari_ffelt_with_category'>
|
|
29
|
+
|
|
30
|
+
sage: n = previous_prime_power(2^16 - 1)
|
|
31
|
+
sage: while is_prime(n):
|
|
32
|
+
....: n = previous_prime_power(n)
|
|
33
|
+
sage: factor(n)
|
|
34
|
+
251^2
|
|
35
|
+
sage: k = GF(n,'c'); type(k)
|
|
36
|
+
<class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
|
|
37
|
+
|
|
38
|
+
AUTHORS:
|
|
39
|
+
|
|
40
|
+
- Martin Albrecht <malb@informatik.uni-bremen.de> (2006-06-05)
|
|
41
|
+
- William Stein (2006-12-07): editing, lots of docs, etc.
|
|
42
|
+
- Robert Bradshaw (2007-05-23): is_square/sqrt, pow.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
# ****************************************************************************
|
|
46
|
+
# Copyright (C) 2006 William Stein <wstein@gmail.com>
|
|
47
|
+
#
|
|
48
|
+
# This program is free software: you can redistribute it and/or modify
|
|
49
|
+
# it under the terms of the GNU General Public License as published by
|
|
50
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
51
|
+
# (at your option) any later version.
|
|
52
|
+
# https://www.gnu.org/licenses/
|
|
53
|
+
# ****************************************************************************
|
|
54
|
+
|
|
55
|
+
from cysignals.signals cimport sig_on, sig_off
|
|
56
|
+
|
|
57
|
+
from cypari2.paridecl cimport *
|
|
58
|
+
|
|
59
|
+
import sage.arith.misc
|
|
60
|
+
|
|
61
|
+
from sage.misc.randstate cimport current_randstate
|
|
62
|
+
from sage.rings.finite_rings.element_pari_ffelt cimport FiniteFieldElement_pari_ffelt
|
|
63
|
+
from sage.structure.richcmp cimport richcmp
|
|
64
|
+
|
|
65
|
+
from cypari2.gen cimport Gen
|
|
66
|
+
from cypari2.stack cimport clear_stack
|
|
67
|
+
|
|
68
|
+
from sage.structure.parent cimport Parent
|
|
69
|
+
from sage.structure.element cimport Vector
|
|
70
|
+
|
|
71
|
+
from sage.interfaces.abc import GapElement
|
|
72
|
+
|
|
73
|
+
cdef object IntegerMod_abstract
|
|
74
|
+
cdef object Integer
|
|
75
|
+
cdef object Rational
|
|
76
|
+
cdef object MPolynomial
|
|
77
|
+
cdef object Polynomial
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
cdef void late_import() noexcept:
|
|
81
|
+
"""
|
|
82
|
+
Late import of modules
|
|
83
|
+
"""
|
|
84
|
+
global IntegerMod_abstract, \
|
|
85
|
+
Integer, \
|
|
86
|
+
Rational, \
|
|
87
|
+
MPolynomial, \
|
|
88
|
+
Polynomial
|
|
89
|
+
|
|
90
|
+
if IntegerMod_abstract is not None:
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
import sage.rings.finite_rings.integer_mod
|
|
94
|
+
IntegerMod_abstract = sage.rings.finite_rings.integer_mod.IntegerMod_abstract
|
|
95
|
+
|
|
96
|
+
import sage.rings.integer
|
|
97
|
+
Integer = sage.rings.integer.Integer
|
|
98
|
+
|
|
99
|
+
import sage.rings.rational
|
|
100
|
+
Rational = sage.rings.rational.Rational
|
|
101
|
+
|
|
102
|
+
import sage.rings.polynomial.multi_polynomial_element
|
|
103
|
+
MPolynomial = sage.rings.polynomial.multi_polynomial_element.MPolynomial
|
|
104
|
+
|
|
105
|
+
import sage.rings.polynomial.polynomial_element
|
|
106
|
+
Polynomial = sage.rings.polynomial.polynomial_element.Polynomial
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
cdef class Cache_givaro(Cache_base):
|
|
110
|
+
def __init__(self, parent, unsigned int p, unsigned int k, modulus, repr='poly', cache=False):
|
|
111
|
+
"""
|
|
112
|
+
Finite Field.
|
|
113
|
+
|
|
114
|
+
These are implemented using Zech logs and the
|
|
115
|
+
cardinality must be less than `2^{16}`. By default Conway polynomials
|
|
116
|
+
are used as minimal polynomial.
|
|
117
|
+
|
|
118
|
+
INPUT:
|
|
119
|
+
|
|
120
|
+
- ``q`` -- `p^n` (must be prime power)
|
|
121
|
+
|
|
122
|
+
- ``name`` -- variable used for poly_repr (default: ``'a'``)
|
|
123
|
+
|
|
124
|
+
- ``modulus`` -- a polynomial to use as modulus
|
|
125
|
+
|
|
126
|
+
- ``repr`` -- (default: ``'poly'``) controls the way elements are printed
|
|
127
|
+
to the user:
|
|
128
|
+
|
|
129
|
+
- 'log': repr is :meth:`~FiniteField_givaroElement.log_repr()`
|
|
130
|
+
- 'int': repr is :meth:`~FiniteField_givaroElement.int_repr()`
|
|
131
|
+
- 'poly': repr is :meth:`~FiniteField_givaroElement.poly_repr()`
|
|
132
|
+
|
|
133
|
+
- ``cache`` -- boolean (default: ``False``); if ``True`` a cache of all
|
|
134
|
+
elements of this field is created. Thus, arithmetic does not
|
|
135
|
+
create new elements which speeds calculations up. Also, if many
|
|
136
|
+
elements are needed during a calculation this cache reduces the
|
|
137
|
+
memory requirement as at most :meth:`order()` elements are created.
|
|
138
|
+
|
|
139
|
+
OUTPUT: Givaro finite field with characteristic `p` and cardinality `p^n`
|
|
140
|
+
|
|
141
|
+
EXAMPLES:
|
|
142
|
+
|
|
143
|
+
By default Conway polynomials are used::
|
|
144
|
+
|
|
145
|
+
sage: k.<a> = GF(2**8)
|
|
146
|
+
sage: -a ^ k.degree()
|
|
147
|
+
a^4 + a^3 + a^2 + 1
|
|
148
|
+
sage: f = k.modulus(); f
|
|
149
|
+
x^8 + x^4 + x^3 + x^2 + 1
|
|
150
|
+
|
|
151
|
+
You may enforce a modulus::
|
|
152
|
+
|
|
153
|
+
sage: P.<x> = PolynomialRing(GF(2))
|
|
154
|
+
sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael polynomial
|
|
155
|
+
sage: k.<a> = GF(2^8, modulus=f)
|
|
156
|
+
sage: k.modulus()
|
|
157
|
+
x^8 + x^4 + x^3 + x + 1
|
|
158
|
+
sage: a^(2^8)
|
|
159
|
+
a
|
|
160
|
+
|
|
161
|
+
You may enforce a random modulus::
|
|
162
|
+
|
|
163
|
+
sage: k = GF(3**5, 'a', modulus='random')
|
|
164
|
+
sage: k.modulus() # random polynomial
|
|
165
|
+
x^5 + 2*x^4 + 2*x^3 + x^2 + 2
|
|
166
|
+
|
|
167
|
+
For binary fields, you may ask for a minimal weight polynomial::
|
|
168
|
+
|
|
169
|
+
sage: k = GF(2**10, 'a', modulus='minimal_weight') # needs sage.libs.ntl
|
|
170
|
+
sage: k.modulus() # needs sage.libs.ntl
|
|
171
|
+
x^10 + x^3 + 1
|
|
172
|
+
"""
|
|
173
|
+
# we are calling late_import here because this constructor is
|
|
174
|
+
# called at least once before any arithmetic is performed.
|
|
175
|
+
late_import()
|
|
176
|
+
|
|
177
|
+
cdef intvec cPoly
|
|
178
|
+
|
|
179
|
+
self.parent = <Parent?> parent
|
|
180
|
+
|
|
181
|
+
if repr=='poly':
|
|
182
|
+
self.repr = 0
|
|
183
|
+
elif repr=='log':
|
|
184
|
+
self.repr = 1
|
|
185
|
+
elif repr=='int':
|
|
186
|
+
self.repr = 2
|
|
187
|
+
else:
|
|
188
|
+
raise RuntimeError
|
|
189
|
+
|
|
190
|
+
if k == 1:
|
|
191
|
+
sig_on()
|
|
192
|
+
self.objectptr = gfq_factorypk(p, k)
|
|
193
|
+
else:
|
|
194
|
+
# Givaro does not support this when k == 1
|
|
195
|
+
for coeff in modulus:
|
|
196
|
+
cPoly.push_back(<int>coeff)
|
|
197
|
+
sig_on()
|
|
198
|
+
self.objectptr = gfq_factorypkp(p, k, cPoly)
|
|
199
|
+
|
|
200
|
+
self._zero_element = make_FiniteField_givaroElement(self, self.objectptr.zero)
|
|
201
|
+
self._one_element = make_FiniteField_givaroElement(self, self.objectptr.one)
|
|
202
|
+
sig_off()
|
|
203
|
+
|
|
204
|
+
parent._zero_element = self._zero_element
|
|
205
|
+
parent._one_element = self._one_element
|
|
206
|
+
if cache:
|
|
207
|
+
self._array = self.gen_array()
|
|
208
|
+
self._has_array = True
|
|
209
|
+
|
|
210
|
+
cdef gen_array(self):
|
|
211
|
+
"""
|
|
212
|
+
Generates an array/list/tuple containing all elements of ``self``
|
|
213
|
+
indexed by their power with respect to the internal generator.
|
|
214
|
+
"""
|
|
215
|
+
cdef int i
|
|
216
|
+
|
|
217
|
+
array = list()
|
|
218
|
+
for i in range(self.order_c()):
|
|
219
|
+
array.append(make_FiniteField_givaroElement(self, i))
|
|
220
|
+
return tuple(array)
|
|
221
|
+
|
|
222
|
+
def __dealloc__(self):
|
|
223
|
+
"""
|
|
224
|
+
Free the memory occupied by this Givaro finite field.
|
|
225
|
+
"""
|
|
226
|
+
delete(self.objectptr)
|
|
227
|
+
|
|
228
|
+
cpdef int characteristic(self) noexcept:
|
|
229
|
+
"""
|
|
230
|
+
Return the characteristic of this field.
|
|
231
|
+
|
|
232
|
+
EXAMPLES::
|
|
233
|
+
|
|
234
|
+
sage: p = GF(19^3,'a')._cache.characteristic(); p
|
|
235
|
+
19
|
|
236
|
+
"""
|
|
237
|
+
return self.objectptr.characteristic()
|
|
238
|
+
|
|
239
|
+
def order(self):
|
|
240
|
+
"""
|
|
241
|
+
Return the order of this field.
|
|
242
|
+
|
|
243
|
+
EXAMPLES::
|
|
244
|
+
|
|
245
|
+
sage: K.<a> = GF(9)
|
|
246
|
+
sage: K._cache.order()
|
|
247
|
+
9
|
|
248
|
+
"""
|
|
249
|
+
return Integer(self.order_c())
|
|
250
|
+
|
|
251
|
+
cpdef int order_c(self) noexcept:
|
|
252
|
+
"""
|
|
253
|
+
Return the order of this field.
|
|
254
|
+
|
|
255
|
+
EXAMPLES::
|
|
256
|
+
|
|
257
|
+
sage: K.<a> = GF(9)
|
|
258
|
+
sage: K._cache.order_c()
|
|
259
|
+
9
|
|
260
|
+
"""
|
|
261
|
+
return self.objectptr.cardinality()
|
|
262
|
+
|
|
263
|
+
cpdef int exponent(self) noexcept:
|
|
264
|
+
r"""
|
|
265
|
+
Return the degree of this field over `\GF{p}`.
|
|
266
|
+
|
|
267
|
+
EXAMPLES::
|
|
268
|
+
|
|
269
|
+
sage: K.<a> = GF(9); K._cache.exponent()
|
|
270
|
+
2
|
|
271
|
+
"""
|
|
272
|
+
return self.objectptr.exponent()
|
|
273
|
+
|
|
274
|
+
def random_element(self, *args, **kwds):
|
|
275
|
+
"""
|
|
276
|
+
Return a random element of ``self``.
|
|
277
|
+
|
|
278
|
+
EXAMPLES::
|
|
279
|
+
|
|
280
|
+
sage: k = GF(23**3, 'a')
|
|
281
|
+
sage: e = k._cache.random_element()
|
|
282
|
+
sage: e.parent() is k
|
|
283
|
+
True
|
|
284
|
+
sage: type(e)
|
|
285
|
+
<class 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>
|
|
286
|
+
|
|
287
|
+
sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))
|
|
288
|
+
sage: P.random_element(5).parent() is P
|
|
289
|
+
True
|
|
290
|
+
"""
|
|
291
|
+
cdef int seed = current_randstate().c_random()
|
|
292
|
+
cdef int res = 0
|
|
293
|
+
cdef GivRandom generator = GivRandomSeeded(seed)
|
|
294
|
+
self.objectptr.random(generator, res)
|
|
295
|
+
return make_FiniteField_givaroElement(self, res)
|
|
296
|
+
|
|
297
|
+
cpdef FiniteField_givaroElement element_from_data(self, e):
|
|
298
|
+
"""
|
|
299
|
+
Coerces several data types to ``self``.
|
|
300
|
+
|
|
301
|
+
INPUT:
|
|
302
|
+
|
|
303
|
+
- ``e`` -- data to coerce in
|
|
304
|
+
|
|
305
|
+
EXAMPLES::
|
|
306
|
+
|
|
307
|
+
sage: k = GF(3^8, 'a')
|
|
308
|
+
sage: type(k)
|
|
309
|
+
<class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
|
|
310
|
+
sage: e = k.vector_space(map=False).gen(1); e # needs sage.modules
|
|
311
|
+
(0, 1, 0, 0, 0, 0, 0, 0)
|
|
312
|
+
sage: k(e) # indirect doctest # needs sage.modules
|
|
313
|
+
a
|
|
314
|
+
|
|
315
|
+
TESTS:
|
|
316
|
+
|
|
317
|
+
Check coercion of large integers::
|
|
318
|
+
|
|
319
|
+
sage: k(-5^13)
|
|
320
|
+
1
|
|
321
|
+
sage: k(2^31)
|
|
322
|
+
2
|
|
323
|
+
sage: k(int(10^19))
|
|
324
|
+
1
|
|
325
|
+
sage: k(2^63)
|
|
326
|
+
2
|
|
327
|
+
sage: k(2^100)
|
|
328
|
+
1
|
|
329
|
+
sage: k(int(2^100))
|
|
330
|
+
1
|
|
331
|
+
sage: k(-2^100)
|
|
332
|
+
2
|
|
333
|
+
|
|
334
|
+
Check coercion of incompatible fields::
|
|
335
|
+
|
|
336
|
+
sage: x=GF(7).random_element()
|
|
337
|
+
sage: k(x)
|
|
338
|
+
Traceback (most recent call last):
|
|
339
|
+
...
|
|
340
|
+
TypeError: unable to coerce from a finite field other than the prime subfield
|
|
341
|
+
|
|
342
|
+
For more examples, see
|
|
343
|
+
``finite_field_givaro.FiniteField_givaro._element_constructor_``
|
|
344
|
+
"""
|
|
345
|
+
cdef int res = 0
|
|
346
|
+
cdef int g
|
|
347
|
+
cdef int x
|
|
348
|
+
cdef int e_int
|
|
349
|
+
|
|
350
|
+
cdef FiniteField_givaroElement to_add
|
|
351
|
+
########
|
|
352
|
+
|
|
353
|
+
if isinstance(e, FiniteField_givaroElement):
|
|
354
|
+
if e.parent() is self.parent:
|
|
355
|
+
return e
|
|
356
|
+
if e.parent() == self.parent:
|
|
357
|
+
return make_FiniteField_givaroElement(self, (<FiniteField_givaroElement>e).element)
|
|
358
|
+
if e.parent() is self.parent.prime_subfield() or e.parent() == self.parent.prime_subfield():
|
|
359
|
+
res = self.int_to_log(int(e))
|
|
360
|
+
else:
|
|
361
|
+
raise TypeError("unable to coerce from a finite field other than the prime subfield")
|
|
362
|
+
|
|
363
|
+
elif isinstance(e, (int, Integer, IntegerMod_abstract)):
|
|
364
|
+
try:
|
|
365
|
+
e_int = e % self.characteristic()
|
|
366
|
+
self.objectptr.initi(res, e_int)
|
|
367
|
+
except ArithmeticError:
|
|
368
|
+
raise TypeError("unable to coerce from a finite field other than the prime subfield")
|
|
369
|
+
elif e is None:
|
|
370
|
+
e_int = 0
|
|
371
|
+
self.objectptr.initi(res, e_int)
|
|
372
|
+
|
|
373
|
+
elif isinstance(e, float):
|
|
374
|
+
e_int = int(e) % self.characteristic()
|
|
375
|
+
self.objectptr.initd(res, e_int)
|
|
376
|
+
|
|
377
|
+
elif isinstance(e, str):
|
|
378
|
+
return self.parent(eval(e.replace("^", "**"),
|
|
379
|
+
self.parent.gens_dict()))
|
|
380
|
+
|
|
381
|
+
elif isinstance(e, Vector):
|
|
382
|
+
if self.parent.vector_space(map=False) != e.parent():
|
|
383
|
+
raise TypeError("e.parent must match self.vector_space")
|
|
384
|
+
ret = self._zero_element
|
|
385
|
+
for i in range(len(e)):
|
|
386
|
+
e_int = e[i] % self.characteristic()
|
|
387
|
+
self.objectptr.initi(res, e_int)
|
|
388
|
+
to_add = make_FiniteField_givaroElement(self, res)
|
|
389
|
+
ret = ret + to_add * self.parent.gen()**i
|
|
390
|
+
return ret
|
|
391
|
+
|
|
392
|
+
elif isinstance(e, MPolynomial):
|
|
393
|
+
if e.is_constant():
|
|
394
|
+
return self.parent(e.constant_coefficient())
|
|
395
|
+
else:
|
|
396
|
+
raise TypeError("no coercion defined")
|
|
397
|
+
|
|
398
|
+
elif isinstance(e, Polynomial):
|
|
399
|
+
if e.is_constant():
|
|
400
|
+
return self.parent(e.constant_coefficient())
|
|
401
|
+
else:
|
|
402
|
+
return e.change_ring(self.parent)(self.parent.gen())
|
|
403
|
+
|
|
404
|
+
elif isinstance(e, Rational):
|
|
405
|
+
num = e.numer()
|
|
406
|
+
den = e.denom()
|
|
407
|
+
return self.parent(num) / self.parent(den)
|
|
408
|
+
|
|
409
|
+
elif isinstance(e, Gen):
|
|
410
|
+
pass # handle this in next if clause
|
|
411
|
+
|
|
412
|
+
elif isinstance(e, FiniteFieldElement_pari_ffelt):
|
|
413
|
+
# Reduce to pari
|
|
414
|
+
e = e.__pari__()
|
|
415
|
+
|
|
416
|
+
elif isinstance(e, GapElement):
|
|
417
|
+
from sage.libs.gap.libgap import libgap
|
|
418
|
+
return libgap(e).sage(ring=self.parent)
|
|
419
|
+
|
|
420
|
+
elif isinstance(e, list):
|
|
421
|
+
if len(e) > self.exponent():
|
|
422
|
+
# could reduce here...
|
|
423
|
+
raise ValueError("list is too long")
|
|
424
|
+
ret = self._zero_element
|
|
425
|
+
for i in range(len(e)):
|
|
426
|
+
e_int = e[i] % self.characteristic()
|
|
427
|
+
self.objectptr.initi(res, e_int)
|
|
428
|
+
to_add = make_FiniteField_givaroElement(self, res)
|
|
429
|
+
ret = ret + to_add * self.parent.gen()**i
|
|
430
|
+
return ret
|
|
431
|
+
|
|
432
|
+
else:
|
|
433
|
+
try:
|
|
434
|
+
from sage.libs.gap.element import GapElement_FiniteField
|
|
435
|
+
except ImportError:
|
|
436
|
+
pass
|
|
437
|
+
else:
|
|
438
|
+
if isinstance(e, GapElement_FiniteField):
|
|
439
|
+
return e.sage(ring=self.parent)
|
|
440
|
+
raise TypeError("unable to coerce %r" % type(e))
|
|
441
|
+
|
|
442
|
+
cdef GEN t
|
|
443
|
+
cdef long c
|
|
444
|
+
if isinstance(e, Gen):
|
|
445
|
+
sig_on()
|
|
446
|
+
t = (<Gen>e).g
|
|
447
|
+
if typ(t) == t_FFELT:
|
|
448
|
+
t = FF_to_FpXQ(t)
|
|
449
|
+
else:
|
|
450
|
+
t = liftall_shallow(t)
|
|
451
|
+
|
|
452
|
+
if typ(t) == t_INT:
|
|
453
|
+
res = self.int_to_log(itos(t))
|
|
454
|
+
clear_stack()
|
|
455
|
+
elif typ(t) == t_POL:
|
|
456
|
+
res = self._zero_element
|
|
457
|
+
|
|
458
|
+
g = self.objectptr.indeterminate()
|
|
459
|
+
x = self.objectptr.one
|
|
460
|
+
|
|
461
|
+
for i in range(degpol(t) + 1):
|
|
462
|
+
c = gtolong(gel(t, i + 2))
|
|
463
|
+
self.objectptr.axpyin(res, self.int_to_log(c), x)
|
|
464
|
+
self.objectptr.mulin(x, g)
|
|
465
|
+
clear_stack()
|
|
466
|
+
else:
|
|
467
|
+
clear_stack()
|
|
468
|
+
raise TypeError(f"unable to convert PARI {e.type()} to {self.parent}")
|
|
469
|
+
|
|
470
|
+
return make_FiniteField_givaroElement(self, res)
|
|
471
|
+
|
|
472
|
+
cpdef FiniteField_givaroElement gen(self):
|
|
473
|
+
"""
|
|
474
|
+
Return a generator of the field.
|
|
475
|
+
|
|
476
|
+
EXAMPLES::
|
|
477
|
+
|
|
478
|
+
sage: K.<a> = GF(625)
|
|
479
|
+
sage: K._cache.gen()
|
|
480
|
+
a
|
|
481
|
+
"""
|
|
482
|
+
cdef int g = 0
|
|
483
|
+
if self.objectptr.exponent() == 1:
|
|
484
|
+
self.objectptr.initi(g, -self.parent.modulus()[0])
|
|
485
|
+
else:
|
|
486
|
+
g = self.objectptr.indeterminate()
|
|
487
|
+
return make_FiniteField_givaroElement(self, g)
|
|
488
|
+
|
|
489
|
+
cpdef int log_to_int(self, int n) except -1:
|
|
490
|
+
r"""
|
|
491
|
+
Given an integer `n` this method returns `i` where `i`
|
|
492
|
+
satisfies `g^n = i` where `g` is the generator of ``self``; the
|
|
493
|
+
result is interpreted as an integer.
|
|
494
|
+
|
|
495
|
+
INPUT:
|
|
496
|
+
|
|
497
|
+
- ``n`` -- log representation of a finite field element
|
|
498
|
+
|
|
499
|
+
OUTPUT: integer representation of a finite field element
|
|
500
|
+
|
|
501
|
+
EXAMPLES::
|
|
502
|
+
|
|
503
|
+
sage: k = GF(2**8, 'a')
|
|
504
|
+
sage: k._cache.log_to_int(4)
|
|
505
|
+
16
|
|
506
|
+
sage: k._cache.log_to_int(20)
|
|
507
|
+
180
|
|
508
|
+
"""
|
|
509
|
+
if n < 0:
|
|
510
|
+
raise IndexError("Cannot serve negative exponent %d" % n)
|
|
511
|
+
elif n >= self.order_c():
|
|
512
|
+
raise IndexError("n=%d must be < self.order()" % n)
|
|
513
|
+
|
|
514
|
+
cdef int r = 0
|
|
515
|
+
sig_on()
|
|
516
|
+
self.objectptr.convert(r, n)
|
|
517
|
+
sig_off()
|
|
518
|
+
return r
|
|
519
|
+
|
|
520
|
+
cpdef int int_to_log(self, int n) except -1:
|
|
521
|
+
r"""
|
|
522
|
+
Given an integer `n` this method returns `i` where `i` satisfies
|
|
523
|
+
`g^i = n \mod p` where `g` is the generator and `p` is the
|
|
524
|
+
characteristic of ``self``.
|
|
525
|
+
|
|
526
|
+
INPUT:
|
|
527
|
+
|
|
528
|
+
- ``n`` -- integer representation of a finite field element
|
|
529
|
+
|
|
530
|
+
OUTPUT: log representation of ``n``
|
|
531
|
+
|
|
532
|
+
EXAMPLES::
|
|
533
|
+
|
|
534
|
+
sage: k = GF(7**3, 'a')
|
|
535
|
+
sage: k._cache.int_to_log(4)
|
|
536
|
+
228
|
|
537
|
+
sage: k._cache.int_to_log(3)
|
|
538
|
+
57
|
|
539
|
+
sage: k.gen()^57
|
|
540
|
+
3
|
|
541
|
+
"""
|
|
542
|
+
cdef int r = 0
|
|
543
|
+
sig_on()
|
|
544
|
+
self.objectptr.initi(r, n)
|
|
545
|
+
sig_off()
|
|
546
|
+
return r
|
|
547
|
+
|
|
548
|
+
cpdef FiniteField_givaroElement fetch_int(self, number):
|
|
549
|
+
r"""
|
|
550
|
+
Given an integer ``n`` return a finite field element in ``self``
|
|
551
|
+
which equals ``n`` under the condition that :meth:`gen()` is set to
|
|
552
|
+
:meth:`characteristic()`.
|
|
553
|
+
|
|
554
|
+
EXAMPLES::
|
|
555
|
+
|
|
556
|
+
sage: k.<a> = GF(2^8)
|
|
557
|
+
sage: k._cache.fetch_int(8)
|
|
558
|
+
a^3
|
|
559
|
+
sage: e = k._cache.fetch_int(151); e
|
|
560
|
+
a^7 + a^4 + a^2 + a + 1
|
|
561
|
+
sage: 2^7 + 2^4 + 2^2 + 2 + 1
|
|
562
|
+
151
|
|
563
|
+
"""
|
|
564
|
+
cdef int n = number
|
|
565
|
+
if n < 0 or n > self.order_c():
|
|
566
|
+
raise TypeError("n must be between 0 and self.order()")
|
|
567
|
+
|
|
568
|
+
cdef int ret = self.int_to_log(n)
|
|
569
|
+
return make_FiniteField_givaroElement(self, ret)
|
|
570
|
+
|
|
571
|
+
def _element_repr(self, FiniteField_givaroElement e):
|
|
572
|
+
"""
|
|
573
|
+
Wrapper for log, int, and poly representations.
|
|
574
|
+
|
|
575
|
+
EXAMPLES::
|
|
576
|
+
|
|
577
|
+
sage: k.<a> = GF(3^4); k
|
|
578
|
+
Finite Field in a of size 3^4
|
|
579
|
+
sage: k._cache._element_repr(a^20)
|
|
580
|
+
'2*a^3 + 2*a^2 + 2'
|
|
581
|
+
|
|
582
|
+
sage: k = FiniteField(3^4,'a', impl='givaro', repr='int')
|
|
583
|
+
sage: a = k.gen()
|
|
584
|
+
sage: k._cache._element_repr(a^20)
|
|
585
|
+
'74'
|
|
586
|
+
|
|
587
|
+
sage: k = FiniteField(3^4,'a', impl='givaro', repr='log')
|
|
588
|
+
sage: a = k.gen()
|
|
589
|
+
sage: k._cache._element_repr(a^20)
|
|
590
|
+
'20'
|
|
591
|
+
"""
|
|
592
|
+
if self.repr==0:
|
|
593
|
+
return self._element_poly_repr(e)
|
|
594
|
+
elif self.repr==1:
|
|
595
|
+
return self._element_log_repr(e)
|
|
596
|
+
else:
|
|
597
|
+
return self._element_int_repr(e)
|
|
598
|
+
|
|
599
|
+
def _element_log_repr(self, FiniteField_givaroElement e):
|
|
600
|
+
"""
|
|
601
|
+
Return ``str(i)`` where ``self`` is ``gen^i`` with ``gen``
|
|
602
|
+
being the *internal* multiplicative generator of this finite
|
|
603
|
+
field.
|
|
604
|
+
|
|
605
|
+
EXAMPLES::
|
|
606
|
+
|
|
607
|
+
sage: k.<a> = GF(3^4); k
|
|
608
|
+
Finite Field in a of size 3^4
|
|
609
|
+
sage: k._cache._element_log_repr(a^20)
|
|
610
|
+
'20'
|
|
611
|
+
sage: k._cache._element_log_repr(a)
|
|
612
|
+
'1'
|
|
613
|
+
"""
|
|
614
|
+
return str(int(e.element))
|
|
615
|
+
|
|
616
|
+
def _element_int_repr(self, FiniteField_givaroElement e):
|
|
617
|
+
r"""
|
|
618
|
+
Return integer representation of ``e``.
|
|
619
|
+
|
|
620
|
+
Elements of this field are represented as ints in as follows:
|
|
621
|
+
for `e \in \GF{p}[x]` with `e = a_0 + a_1x + a_2x^2 + \cdots`, `e` is
|
|
622
|
+
represented as: `n = a_0 + a_1 p + a_2 p^2 + \cdots`.
|
|
623
|
+
|
|
624
|
+
EXAMPLES::
|
|
625
|
+
|
|
626
|
+
sage: k.<a> = GF(3^4); k
|
|
627
|
+
Finite Field in a of size 3^4
|
|
628
|
+
sage: k._cache._element_int_repr(a^20)
|
|
629
|
+
'74'
|
|
630
|
+
"""
|
|
631
|
+
return str(e._integer_representation())
|
|
632
|
+
|
|
633
|
+
def _element_poly_repr(self, FiniteField_givaroElement e, varname=None):
|
|
634
|
+
"""
|
|
635
|
+
Return a polynomial expression in the generator of ``self``.
|
|
636
|
+
|
|
637
|
+
EXAMPLES::
|
|
638
|
+
|
|
639
|
+
sage: k.<a> = GF(3^4); k
|
|
640
|
+
Finite Field in a of size 3^4
|
|
641
|
+
sage: k._cache._element_poly_repr(a^20)
|
|
642
|
+
'2*a^3 + 2*a^2 + 2'
|
|
643
|
+
"""
|
|
644
|
+
if varname is None:
|
|
645
|
+
variable = self.parent.variable_name()
|
|
646
|
+
else:
|
|
647
|
+
variable = varname
|
|
648
|
+
|
|
649
|
+
quo = self.log_to_int(e.element)
|
|
650
|
+
b = int(self.characteristic())
|
|
651
|
+
|
|
652
|
+
ret = ""
|
|
653
|
+
for i in range(self.exponent()):
|
|
654
|
+
coeff = quo % b
|
|
655
|
+
if coeff != 0:
|
|
656
|
+
if i > 0:
|
|
657
|
+
if coeff == 1:
|
|
658
|
+
coeff = ""
|
|
659
|
+
else:
|
|
660
|
+
coeff = str(coeff) + "*"
|
|
661
|
+
if i > 1:
|
|
662
|
+
ret = coeff + variable + "^" + str(i) + " + " + ret
|
|
663
|
+
else:
|
|
664
|
+
ret = coeff + variable + " + " + ret
|
|
665
|
+
else:
|
|
666
|
+
ret = str(coeff) + " + " + ret
|
|
667
|
+
quo = quo // b
|
|
668
|
+
if ret == '':
|
|
669
|
+
return "0"
|
|
670
|
+
return ret[:-3]
|
|
671
|
+
|
|
672
|
+
def a_times_b_plus_c(self, FiniteField_givaroElement a,
|
|
673
|
+
FiniteField_givaroElement b,
|
|
674
|
+
FiniteField_givaroElement c):
|
|
675
|
+
"""
|
|
676
|
+
Return ``a*b + c``.
|
|
677
|
+
|
|
678
|
+
This is faster than multiplying ``a`` and ``b``
|
|
679
|
+
first and adding ``c`` to the result.
|
|
680
|
+
|
|
681
|
+
INPUT:
|
|
682
|
+
|
|
683
|
+
- ``a``, ``b``, ``c`` -- :class:`FiniteField_givaroElement`
|
|
684
|
+
|
|
685
|
+
EXAMPLES::
|
|
686
|
+
|
|
687
|
+
sage: k.<a> = GF(2**8)
|
|
688
|
+
sage: k._cache.a_times_b_plus_c(a,a,k(1))
|
|
689
|
+
a^2 + 1
|
|
690
|
+
"""
|
|
691
|
+
cdef int r = 0
|
|
692
|
+
|
|
693
|
+
self.objectptr.axpy(r, a.element, b.element, c.element)
|
|
694
|
+
return make_FiniteField_givaroElement(self, r)
|
|
695
|
+
|
|
696
|
+
def a_times_b_minus_c(self, FiniteField_givaroElement a,
|
|
697
|
+
FiniteField_givaroElement b,
|
|
698
|
+
FiniteField_givaroElement c):
|
|
699
|
+
"""
|
|
700
|
+
Return ``a*b - c``.
|
|
701
|
+
|
|
702
|
+
INPUT:
|
|
703
|
+
|
|
704
|
+
- ``a``, ``b``, ``c`` -- :class:`FiniteField_givaroElement`
|
|
705
|
+
|
|
706
|
+
EXAMPLES::
|
|
707
|
+
|
|
708
|
+
sage: k.<a> = GF(3**3)
|
|
709
|
+
sage: k._cache.a_times_b_minus_c(a,a,k(1))
|
|
710
|
+
a^2 + 2
|
|
711
|
+
"""
|
|
712
|
+
cdef int r = 0
|
|
713
|
+
|
|
714
|
+
self.objectptr.axmy(r, a.element, b.element, c.element, )
|
|
715
|
+
return make_FiniteField_givaroElement(self, r)
|
|
716
|
+
|
|
717
|
+
def c_minus_a_times_b(self, FiniteField_givaroElement a,
|
|
718
|
+
FiniteField_givaroElement b,
|
|
719
|
+
FiniteField_givaroElement c):
|
|
720
|
+
"""
|
|
721
|
+
Return ``c - a*b``.
|
|
722
|
+
|
|
723
|
+
INPUT:
|
|
724
|
+
|
|
725
|
+
- ``a``, ``b``, ``c`` -- :class:`FiniteField_givaroElement`
|
|
726
|
+
|
|
727
|
+
EXAMPLES::
|
|
728
|
+
|
|
729
|
+
sage: k.<a> = GF(3**3)
|
|
730
|
+
sage: k._cache.c_minus_a_times_b(a,a,k(1))
|
|
731
|
+
2*a^2 + 1
|
|
732
|
+
"""
|
|
733
|
+
cdef int r = 0
|
|
734
|
+
|
|
735
|
+
self.objectptr.maxpy(r, a.element, b.element, c.element,)
|
|
736
|
+
return make_FiniteField_givaroElement(self, r)
|
|
737
|
+
|
|
738
|
+
def __reduce__(self):
|
|
739
|
+
"""
|
|
740
|
+
For pickling.
|
|
741
|
+
|
|
742
|
+
TESTS::
|
|
743
|
+
|
|
744
|
+
sage: k.<a> = GF(3^8)
|
|
745
|
+
sage: TestSuite(a).run()
|
|
746
|
+
"""
|
|
747
|
+
p, k = self.order().factor()[0]
|
|
748
|
+
if self.repr == 0:
|
|
749
|
+
rep = 'poly'
|
|
750
|
+
elif self.repr == 1:
|
|
751
|
+
rep = 'log'
|
|
752
|
+
elif self.repr == 2:
|
|
753
|
+
rep = 'int'
|
|
754
|
+
return unpickle_Cache_givaro, (self.parent, p, k, self.parent.polynomial(), rep, self._has_array)
|
|
755
|
+
|
|
756
|
+
cdef FiniteField_givaroElement _new_c(self, int value):
|
|
757
|
+
return make_FiniteField_givaroElement(self, value)
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
def unpickle_Cache_givaro(parent, p, k, modulus, rep, cache):
|
|
761
|
+
"""
|
|
762
|
+
EXAMPLES::
|
|
763
|
+
|
|
764
|
+
sage: k = GF(3**7, 'a')
|
|
765
|
+
sage: loads(dumps(k)) == k # indirect doctest
|
|
766
|
+
True
|
|
767
|
+
"""
|
|
768
|
+
return Cache_givaro(parent, p, k, modulus, rep, cache)
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
cdef class FiniteField_givaro_iterator:
|
|
772
|
+
"""
|
|
773
|
+
Iterator over :class:`FiniteField_givaro` elements. We iterate
|
|
774
|
+
multiplicatively, as powers of a fixed internal generator.
|
|
775
|
+
|
|
776
|
+
EXAMPLES::
|
|
777
|
+
|
|
778
|
+
sage: for x in GF(2^2,'a'): print(x)
|
|
779
|
+
0
|
|
780
|
+
a
|
|
781
|
+
a + 1
|
|
782
|
+
1
|
|
783
|
+
"""
|
|
784
|
+
|
|
785
|
+
def __init__(self, Cache_givaro cache):
|
|
786
|
+
"""
|
|
787
|
+
EXAMPLES::
|
|
788
|
+
|
|
789
|
+
sage: k.<a> = GF(3^4)
|
|
790
|
+
sage: i = iter(k) # indirect doctest
|
|
791
|
+
sage: i
|
|
792
|
+
Iterator over Finite Field in a of size 3^4
|
|
793
|
+
"""
|
|
794
|
+
self._cache = cache
|
|
795
|
+
self.iterator = -1
|
|
796
|
+
|
|
797
|
+
def __next__(self):
|
|
798
|
+
"""
|
|
799
|
+
EXAMPLES::
|
|
800
|
+
|
|
801
|
+
sage: k.<a> = GF(3^4)
|
|
802
|
+
sage: i = iter(k) # indirect doctest
|
|
803
|
+
sage: next(i)
|
|
804
|
+
0
|
|
805
|
+
sage: next(i)
|
|
806
|
+
a
|
|
807
|
+
"""
|
|
808
|
+
self.iterator += 1
|
|
809
|
+
|
|
810
|
+
if self.iterator == self._cache.order_c():
|
|
811
|
+
self.iterator = -1
|
|
812
|
+
raise StopIteration
|
|
813
|
+
|
|
814
|
+
return make_FiniteField_givaroElement(self._cache, self.iterator)
|
|
815
|
+
|
|
816
|
+
def __repr__(self):
|
|
817
|
+
"""
|
|
818
|
+
EXAMPLES::
|
|
819
|
+
|
|
820
|
+
sage: k.<a> = GF(3^4)
|
|
821
|
+
sage: i = iter(k)
|
|
822
|
+
sage: i # indirect doctest
|
|
823
|
+
Iterator over Finite Field in a of size 3^4
|
|
824
|
+
"""
|
|
825
|
+
return "Iterator over %s" % self._cache.parent
|
|
826
|
+
|
|
827
|
+
def __iter__(self):
|
|
828
|
+
"""
|
|
829
|
+
EXAMPLES::
|
|
830
|
+
|
|
831
|
+
sage: K.<a> = GF(4)
|
|
832
|
+
sage: K.list() # indirect doctest
|
|
833
|
+
[0, a, a + 1, 1]
|
|
834
|
+
"""
|
|
835
|
+
return self
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
cdef class FiniteField_givaroElement(FinitePolyExtElement):
|
|
839
|
+
"""
|
|
840
|
+
An element of a (Givaro) finite field.
|
|
841
|
+
"""
|
|
842
|
+
|
|
843
|
+
def __init__(FiniteField_givaroElement self, parent):
|
|
844
|
+
"""
|
|
845
|
+
Initialize an element in parent. It's much better to use
|
|
846
|
+
parent(<value>) or any specialized method of parent
|
|
847
|
+
like gen() instead. In general do not call this
|
|
848
|
+
constructor directly.
|
|
849
|
+
|
|
850
|
+
Alternatively you may provide a value which is directly
|
|
851
|
+
assigned to this element. So the value must represent the
|
|
852
|
+
log_g of the value you wish to assign.
|
|
853
|
+
|
|
854
|
+
INPUT:
|
|
855
|
+
|
|
856
|
+
- ``parent`` -- base field
|
|
857
|
+
|
|
858
|
+
OUTPUT: a finite field element
|
|
859
|
+
|
|
860
|
+
EXAMPLES::
|
|
861
|
+
|
|
862
|
+
sage: k.<a> = GF(5^2)
|
|
863
|
+
sage: from sage.rings.finite_rings.element_givaro import FiniteField_givaroElement
|
|
864
|
+
sage: FiniteField_givaroElement(k)
|
|
865
|
+
0
|
|
866
|
+
"""
|
|
867
|
+
FinitePolyExtElement.__init__(self, parent)
|
|
868
|
+
self._cache = parent._cache
|
|
869
|
+
self.element = 0
|
|
870
|
+
|
|
871
|
+
cdef FiniteField_givaroElement _new_c(self, int value):
|
|
872
|
+
return make_FiniteField_givaroElement(self._cache, value)
|
|
873
|
+
|
|
874
|
+
def __dealloc__(FiniteField_givaroElement self):
|
|
875
|
+
pass
|
|
876
|
+
|
|
877
|
+
def _repr_(FiniteField_givaroElement self):
|
|
878
|
+
"""
|
|
879
|
+
EXAMPLES::
|
|
880
|
+
|
|
881
|
+
sage: k.<FOOBAR> = GF(3^4)
|
|
882
|
+
sage: FOOBAR #indirect doctest
|
|
883
|
+
FOOBAR
|
|
884
|
+
|
|
885
|
+
sage: k.<FOOBAR> = GF(3^4, repr='log')
|
|
886
|
+
sage: FOOBAR
|
|
887
|
+
1
|
|
888
|
+
|
|
889
|
+
sage: k.<FOOBAR> = GF(3^4, repr='int')
|
|
890
|
+
sage: FOOBAR
|
|
891
|
+
3
|
|
892
|
+
"""
|
|
893
|
+
return self._cache._element_repr(self)
|
|
894
|
+
|
|
895
|
+
def _element(self):
|
|
896
|
+
"""
|
|
897
|
+
Return the int internally representing this element.
|
|
898
|
+
|
|
899
|
+
EXAMPLES::
|
|
900
|
+
|
|
901
|
+
sage: k.<a> = GF(3^4)
|
|
902
|
+
sage: (a^2 + 1)._element()
|
|
903
|
+
58
|
|
904
|
+
"""
|
|
905
|
+
return self.element
|
|
906
|
+
|
|
907
|
+
def __bool__(FiniteField_givaroElement self):
|
|
908
|
+
r"""
|
|
909
|
+
Return ``True`` if ``self != k(0)``.
|
|
910
|
+
|
|
911
|
+
EXAMPLES::
|
|
912
|
+
|
|
913
|
+
sage: k.<a> = GF(3^4); k
|
|
914
|
+
Finite Field in a of size 3^4
|
|
915
|
+
sage: a.is_zero()
|
|
916
|
+
False
|
|
917
|
+
sage: k(0).is_zero()
|
|
918
|
+
True
|
|
919
|
+
"""
|
|
920
|
+
return not self._cache.objectptr.isZero(self.element)
|
|
921
|
+
|
|
922
|
+
def is_one(FiniteField_givaroElement self):
|
|
923
|
+
r"""
|
|
924
|
+
Return ``True`` if ``self == k(1)``.
|
|
925
|
+
|
|
926
|
+
EXAMPLES::
|
|
927
|
+
|
|
928
|
+
sage: k.<a> = GF(3^4); k
|
|
929
|
+
Finite Field in a of size 3^4
|
|
930
|
+
sage: a.is_one()
|
|
931
|
+
False
|
|
932
|
+
sage: k(1).is_one()
|
|
933
|
+
True
|
|
934
|
+
"""
|
|
935
|
+
return self._cache.objectptr.isOne(self.element)
|
|
936
|
+
|
|
937
|
+
def is_unit(FiniteField_givaroElement self):
|
|
938
|
+
"""
|
|
939
|
+
Return ``True`` if ``self`` is nonzero, so it is a unit as an element of
|
|
940
|
+
the finite field.
|
|
941
|
+
|
|
942
|
+
EXAMPLES::
|
|
943
|
+
|
|
944
|
+
sage: k.<a> = GF(3^4); k
|
|
945
|
+
Finite Field in a of size 3^4
|
|
946
|
+
sage: a.is_unit()
|
|
947
|
+
True
|
|
948
|
+
sage: k(0).is_unit()
|
|
949
|
+
False
|
|
950
|
+
"""
|
|
951
|
+
return not (<Cache_givaro>self._cache).objectptr.isZero(self.element)
|
|
952
|
+
# **WARNING** Givaro seems to define unit to mean in the prime field,
|
|
953
|
+
# which is totally wrong! It's a confusion with the underlying polynomial
|
|
954
|
+
# representation maybe?? That's why the following is commented out.
|
|
955
|
+
# return (<FiniteField_givaro>self._parent).objectptr.isunit(self.element)
|
|
956
|
+
|
|
957
|
+
def is_square(FiniteField_givaroElement self):
|
|
958
|
+
"""
|
|
959
|
+
Return ``True`` if ``self`` is a square in ``self.parent()``.
|
|
960
|
+
|
|
961
|
+
ALGORITHM:
|
|
962
|
+
|
|
963
|
+
Elements are stored as powers of generators, so we simply check
|
|
964
|
+
to see if it is an even power of a generator.
|
|
965
|
+
|
|
966
|
+
EXAMPLES::
|
|
967
|
+
|
|
968
|
+
sage: k.<a> = GF(9); k
|
|
969
|
+
Finite Field in a of size 3^2
|
|
970
|
+
sage: a.is_square()
|
|
971
|
+
False
|
|
972
|
+
sage: v = set([x^2 for x in k])
|
|
973
|
+
sage: [x.is_square() for x in v]
|
|
974
|
+
[True, True, True, True, True]
|
|
975
|
+
sage: [x.is_square() for x in k if not x in v]
|
|
976
|
+
[False, False, False, False]
|
|
977
|
+
|
|
978
|
+
TESTS::
|
|
979
|
+
|
|
980
|
+
sage: K = GF(27, 'a')
|
|
981
|
+
sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])
|
|
982
|
+
True
|
|
983
|
+
sage: K = GF(25, 'a')
|
|
984
|
+
sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])
|
|
985
|
+
True
|
|
986
|
+
sage: K = GF(16, 'a')
|
|
987
|
+
sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])
|
|
988
|
+
True
|
|
989
|
+
"""
|
|
990
|
+
cdef Cache_givaro cache = <Cache_givaro>self._cache
|
|
991
|
+
if cache.objectptr.characteristic() == 2:
|
|
992
|
+
return True
|
|
993
|
+
elif self.element == cache.objectptr.one:
|
|
994
|
+
return True
|
|
995
|
+
else:
|
|
996
|
+
return self.element % 2 == 0
|
|
997
|
+
|
|
998
|
+
def sqrt(FiniteField_givaroElement self, extend=False, all=False):
|
|
999
|
+
"""
|
|
1000
|
+
Return a square root of this finite field element in its
|
|
1001
|
+
parent, if there is one. Otherwise, raise a :exc:`ValueError`.
|
|
1002
|
+
|
|
1003
|
+
INPUT:
|
|
1004
|
+
|
|
1005
|
+
- ``extend`` -- boolean (default: ``True``); if ``True``, return a
|
|
1006
|
+
square root in an extension ring, if necessary. Otherwise,
|
|
1007
|
+
raise a :exc:`ValueError` if the root is not in the base ring.
|
|
1008
|
+
|
|
1009
|
+
.. WARNING::
|
|
1010
|
+
|
|
1011
|
+
this option is not implemented!
|
|
1012
|
+
|
|
1013
|
+
- ``all`` -- boolean (default: ``False``); if ``True``, return all
|
|
1014
|
+
square roots of ``self``, instead of just one
|
|
1015
|
+
|
|
1016
|
+
.. WARNING::
|
|
1017
|
+
|
|
1018
|
+
The ``extend`` option is not implemented (yet).
|
|
1019
|
+
|
|
1020
|
+
ALGORITHM:
|
|
1021
|
+
|
|
1022
|
+
``self`` is stored as `a^k` for some generator `a`.
|
|
1023
|
+
Return `a^{k/2}` for even `k`.
|
|
1024
|
+
|
|
1025
|
+
EXAMPLES::
|
|
1026
|
+
|
|
1027
|
+
sage: k.<a> = GF(7^2)
|
|
1028
|
+
sage: k(2).sqrt()
|
|
1029
|
+
3
|
|
1030
|
+
sage: k(3).sqrt()
|
|
1031
|
+
2*a + 6
|
|
1032
|
+
sage: k(3).sqrt()**2
|
|
1033
|
+
3
|
|
1034
|
+
sage: k(4).sqrt()
|
|
1035
|
+
2
|
|
1036
|
+
sage: k.<a> = GF(7^3)
|
|
1037
|
+
sage: k(3).sqrt()
|
|
1038
|
+
Traceback (most recent call last):
|
|
1039
|
+
...
|
|
1040
|
+
ValueError: must be a perfect square.
|
|
1041
|
+
|
|
1042
|
+
TESTS::
|
|
1043
|
+
|
|
1044
|
+
sage: K = GF(49, 'a')
|
|
1045
|
+
sage: all(a.sqrt()*a.sqrt() == a for a in K if a.is_square())
|
|
1046
|
+
True
|
|
1047
|
+
sage: K = GF(27, 'a')
|
|
1048
|
+
sage: all(a.sqrt()*a.sqrt() == a for a in K if a.is_square())
|
|
1049
|
+
True
|
|
1050
|
+
sage: K = GF(8, 'a')
|
|
1051
|
+
sage: all(a.sqrt()*a.sqrt() == a for a in K if a.is_square())
|
|
1052
|
+
True
|
|
1053
|
+
sage: K.<a> = FiniteField(9)
|
|
1054
|
+
sage: a.sqrt(extend = False, all = True)
|
|
1055
|
+
[]
|
|
1056
|
+
"""
|
|
1057
|
+
if all:
|
|
1058
|
+
if self.is_square():
|
|
1059
|
+
a = self.sqrt()
|
|
1060
|
+
return [a, -a] if -a != a else [a]
|
|
1061
|
+
return []
|
|
1062
|
+
cdef Cache_givaro cache = <Cache_givaro>self._cache
|
|
1063
|
+
if self.element == cache.objectptr.one:
|
|
1064
|
+
return make_FiniteField_givaroElement(cache, cache.objectptr.one)
|
|
1065
|
+
elif self.element % 2 == 0:
|
|
1066
|
+
return make_FiniteField_givaroElement(cache, self.element // 2)
|
|
1067
|
+
elif cache.objectptr.characteristic() == 2:
|
|
1068
|
+
return make_FiniteField_givaroElement(cache, (cache.objectptr.cardinality() - 1 + self.element) / 2)
|
|
1069
|
+
elif extend:
|
|
1070
|
+
raise NotImplementedError # TODO: fix this once we have nested embeddings of finite fields
|
|
1071
|
+
else:
|
|
1072
|
+
raise ValueError("must be a perfect square.")
|
|
1073
|
+
|
|
1074
|
+
cpdef _add_(self, right):
|
|
1075
|
+
"""
|
|
1076
|
+
Add two elements.
|
|
1077
|
+
|
|
1078
|
+
EXAMPLES::
|
|
1079
|
+
|
|
1080
|
+
sage: k.<b> = GF(9**2)
|
|
1081
|
+
sage: b^10 + 2*b # indirect doctest
|
|
1082
|
+
2*b^3 + 2*b^2 + 2*b + 1
|
|
1083
|
+
"""
|
|
1084
|
+
cdef int r = 0
|
|
1085
|
+
self._cache.objectptr.add(r, self.element,
|
|
1086
|
+
(<FiniteField_givaroElement>right).element)
|
|
1087
|
+
return make_FiniteField_givaroElement(self._cache, r)
|
|
1088
|
+
|
|
1089
|
+
cpdef _mul_(self, right):
|
|
1090
|
+
"""
|
|
1091
|
+
Multiply two elements.
|
|
1092
|
+
|
|
1093
|
+
EXAMPLES::
|
|
1094
|
+
|
|
1095
|
+
sage: k.<c> = GF(7**4)
|
|
1096
|
+
sage: 3*c # indirect doctest
|
|
1097
|
+
3*c
|
|
1098
|
+
sage: c*c
|
|
1099
|
+
c^2
|
|
1100
|
+
"""
|
|
1101
|
+
cdef int r = 0
|
|
1102
|
+
self._cache.objectptr.mul(r, self.element,
|
|
1103
|
+
(<FiniteField_givaroElement>right).element)
|
|
1104
|
+
return make_FiniteField_givaroElement(self._cache, r)
|
|
1105
|
+
|
|
1106
|
+
cpdef _div_(self, right):
|
|
1107
|
+
"""
|
|
1108
|
+
Divide two elements.
|
|
1109
|
+
|
|
1110
|
+
EXAMPLES::
|
|
1111
|
+
|
|
1112
|
+
sage: k.<g> = GF(2**8)
|
|
1113
|
+
sage: g/g # indirect doctest
|
|
1114
|
+
1
|
|
1115
|
+
|
|
1116
|
+
sage: k(1) / k(0)
|
|
1117
|
+
Traceback (most recent call last):
|
|
1118
|
+
...
|
|
1119
|
+
ZeroDivisionError: division by zero in finite field
|
|
1120
|
+
"""
|
|
1121
|
+
cdef int r = 0
|
|
1122
|
+
if (<FiniteField_givaroElement>right).element == 0:
|
|
1123
|
+
raise ZeroDivisionError('division by zero in finite field')
|
|
1124
|
+
self._cache.objectptr.div(r, self.element,
|
|
1125
|
+
(<FiniteField_givaroElement>right).element)
|
|
1126
|
+
return make_FiniteField_givaroElement(self._cache, r)
|
|
1127
|
+
|
|
1128
|
+
cpdef _sub_(self, right):
|
|
1129
|
+
"""
|
|
1130
|
+
Subtract two elements.
|
|
1131
|
+
|
|
1132
|
+
EXAMPLES::
|
|
1133
|
+
|
|
1134
|
+
sage: k.<a> = GF(3**4)
|
|
1135
|
+
sage: k(3) - k(1) # indirect doctest
|
|
1136
|
+
2
|
|
1137
|
+
sage: 2*a - a^2
|
|
1138
|
+
2*a^2 + 2*a
|
|
1139
|
+
"""
|
|
1140
|
+
cdef int r = 0
|
|
1141
|
+
self._cache.objectptr.sub(r, self.element,
|
|
1142
|
+
(<FiniteField_givaroElement>right).element)
|
|
1143
|
+
return make_FiniteField_givaroElement(self._cache, r)
|
|
1144
|
+
|
|
1145
|
+
def __neg__(FiniteField_givaroElement self):
|
|
1146
|
+
"""
|
|
1147
|
+
Negative of an element.
|
|
1148
|
+
|
|
1149
|
+
EXAMPLES::
|
|
1150
|
+
|
|
1151
|
+
sage: k.<a> = GF(9); k
|
|
1152
|
+
Finite Field in a of size 3^2
|
|
1153
|
+
sage: -a
|
|
1154
|
+
2*a
|
|
1155
|
+
"""
|
|
1156
|
+
cdef int r = 0
|
|
1157
|
+
|
|
1158
|
+
self._cache.objectptr.neg(r, self.element)
|
|
1159
|
+
return make_FiniteField_givaroElement(self._cache, r)
|
|
1160
|
+
|
|
1161
|
+
def __invert__(FiniteField_givaroElement self):
|
|
1162
|
+
"""
|
|
1163
|
+
Return the multiplicative inverse of an element.
|
|
1164
|
+
|
|
1165
|
+
EXAMPLES::
|
|
1166
|
+
|
|
1167
|
+
sage: k.<a> = GF(9); k
|
|
1168
|
+
Finite Field in a of size 3^2
|
|
1169
|
+
sage: ~a
|
|
1170
|
+
a + 2
|
|
1171
|
+
sage: ~a*a
|
|
1172
|
+
1
|
|
1173
|
+
|
|
1174
|
+
TESTS:
|
|
1175
|
+
|
|
1176
|
+
Check that trying to invert zero raises an error
|
|
1177
|
+
(see :issue:`12217`)::
|
|
1178
|
+
|
|
1179
|
+
sage: F = GF(25, 'a')
|
|
1180
|
+
sage: z = F(0)
|
|
1181
|
+
sage: ~z
|
|
1182
|
+
Traceback (most recent call last):
|
|
1183
|
+
...
|
|
1184
|
+
ZeroDivisionError: division by zero in finite field
|
|
1185
|
+
"""
|
|
1186
|
+
cdef int r = 0
|
|
1187
|
+
if self.element == 0:
|
|
1188
|
+
raise ZeroDivisionError('division by zero in finite field')
|
|
1189
|
+
self._cache.objectptr.inv(r, self.element)
|
|
1190
|
+
return make_FiniteField_givaroElement(self._cache, r)
|
|
1191
|
+
|
|
1192
|
+
def __pow__(FiniteField_givaroElement self, exp, other):
|
|
1193
|
+
r"""
|
|
1194
|
+
EXAMPLES::
|
|
1195
|
+
|
|
1196
|
+
sage: K.<a> = GF(3^3, 'a')
|
|
1197
|
+
sage: a^3 == a*a*a
|
|
1198
|
+
True
|
|
1199
|
+
sage: b = a+1
|
|
1200
|
+
sage: b^5 == b^2 * b^3
|
|
1201
|
+
True
|
|
1202
|
+
sage: b^(-1) == 1/b
|
|
1203
|
+
True
|
|
1204
|
+
sage: b = K(-1)
|
|
1205
|
+
sage: b^2 == 1
|
|
1206
|
+
True
|
|
1207
|
+
|
|
1208
|
+
TESTS:
|
|
1209
|
+
|
|
1210
|
+
The following checks that :issue:`7923` is resolved::
|
|
1211
|
+
|
|
1212
|
+
sage: K.<a> = GF(3^10)
|
|
1213
|
+
sage: b = a^9 + a^7 + 2*a^6 + a^4 + a^3 + 2*a^2 + a + 2
|
|
1214
|
+
sage: b^(71*7381) == (b^71)^7381
|
|
1215
|
+
True
|
|
1216
|
+
|
|
1217
|
+
We define ``0^0`` to be unity, :issue:`13897`::
|
|
1218
|
+
|
|
1219
|
+
sage: K.<a> = GF(3^10)
|
|
1220
|
+
sage: K(0)^0
|
|
1221
|
+
1
|
|
1222
|
+
|
|
1223
|
+
The value returned from ``0^0`` should belong to our ring::
|
|
1224
|
+
|
|
1225
|
+
sage: K.<a> = GF(3^10)
|
|
1226
|
+
sage: type(K(0)^0) == type(K(0))
|
|
1227
|
+
True
|
|
1228
|
+
|
|
1229
|
+
ALGORITHM:
|
|
1230
|
+
|
|
1231
|
+
Givaro objects are stored as integers `i` such that ``self`` `= a^i`,
|
|
1232
|
+
where `a` is a generator of `K` (though not necessarily the one
|
|
1233
|
+
returned by ``K.gens()``). Now it is trivial to compute
|
|
1234
|
+
`(a^i)^e = a^{i \cdot e}`, and reducing the exponent
|
|
1235
|
+
mod the multiplicative order of `K`.
|
|
1236
|
+
|
|
1237
|
+
AUTHOR:
|
|
1238
|
+
|
|
1239
|
+
- Robert Bradshaw
|
|
1240
|
+
"""
|
|
1241
|
+
if not isinstance(exp, (int, Integer)):
|
|
1242
|
+
_exp = Integer(exp)
|
|
1243
|
+
if _exp != exp:
|
|
1244
|
+
raise ValueError("exponent must be an integer")
|
|
1245
|
+
exp = _exp
|
|
1246
|
+
|
|
1247
|
+
cdef Cache_givaro cache = self._cache
|
|
1248
|
+
|
|
1249
|
+
if (cache.objectptr).isOne(self.element):
|
|
1250
|
+
return self
|
|
1251
|
+
|
|
1252
|
+
elif exp == 0:
|
|
1253
|
+
return make_FiniteField_givaroElement(cache, cache.objectptr.one)
|
|
1254
|
+
|
|
1255
|
+
elif (cache.objectptr).isZero(self.element):
|
|
1256
|
+
if exp < 0:
|
|
1257
|
+
raise ZeroDivisionError('division by zero in finite field')
|
|
1258
|
+
return make_FiniteField_givaroElement(cache, cache.objectptr.zero)
|
|
1259
|
+
|
|
1260
|
+
cdef int order = (cache.order_c() - 1)
|
|
1261
|
+
cdef int r = exp % order
|
|
1262
|
+
|
|
1263
|
+
if r == 0:
|
|
1264
|
+
return make_FiniteField_givaroElement(cache, cache.objectptr.one)
|
|
1265
|
+
|
|
1266
|
+
cdef unsigned int r_unsigned
|
|
1267
|
+
if r < 0:
|
|
1268
|
+
r_unsigned = <unsigned int> r + order
|
|
1269
|
+
else:
|
|
1270
|
+
r_unsigned = <unsigned int>r
|
|
1271
|
+
cdef unsigned int elt_unsigned = <unsigned int>self.element
|
|
1272
|
+
cdef unsigned int order_unsigned = <unsigned int>order
|
|
1273
|
+
r = <int>(r_unsigned * elt_unsigned) % order_unsigned
|
|
1274
|
+
if r == 0:
|
|
1275
|
+
return make_FiniteField_givaroElement(cache, cache.objectptr.one)
|
|
1276
|
+
return make_FiniteField_givaroElement(cache, r)
|
|
1277
|
+
|
|
1278
|
+
cpdef _richcmp_(left, right, int op):
|
|
1279
|
+
"""
|
|
1280
|
+
Comparison of finite field elements is correct or equality
|
|
1281
|
+
tests and somewhat random for ``<`` and ``>`` type of
|
|
1282
|
+
comparisons. This implementation performs these tests by
|
|
1283
|
+
comparing the underlying int representations.
|
|
1284
|
+
|
|
1285
|
+
EXAMPLES::
|
|
1286
|
+
|
|
1287
|
+
sage: k.<a> = GF(9); k
|
|
1288
|
+
Finite Field in a of size 3^2
|
|
1289
|
+
sage: a == k('a')
|
|
1290
|
+
True
|
|
1291
|
+
sage: a == a + 1
|
|
1292
|
+
False
|
|
1293
|
+
|
|
1294
|
+
Even though inequality tests do return answers, they
|
|
1295
|
+
really make no sense as finite fields are unordered. Thus,
|
|
1296
|
+
you cannot rely on the result as it is implementation specific.
|
|
1297
|
+
|
|
1298
|
+
::
|
|
1299
|
+
|
|
1300
|
+
sage: a < a^2
|
|
1301
|
+
True
|
|
1302
|
+
sage: a^2 < a
|
|
1303
|
+
False
|
|
1304
|
+
"""
|
|
1305
|
+
cdef Cache_givaro cache = (<FiniteField_givaroElement>left)._cache
|
|
1306
|
+
|
|
1307
|
+
return richcmp(cache.log_to_int(left.element),
|
|
1308
|
+
cache.log_to_int((<FiniteField_givaroElement>right).element), op)
|
|
1309
|
+
|
|
1310
|
+
def __int__(FiniteField_givaroElement self):
|
|
1311
|
+
"""
|
|
1312
|
+
Return the int representation of ``self``. When ``self`` is in the
|
|
1313
|
+
prime subfield, the integer returned is equal to ``self``, otherwise
|
|
1314
|
+
an error is raised.
|
|
1315
|
+
|
|
1316
|
+
EXAMPLES::
|
|
1317
|
+
|
|
1318
|
+
sage: k.<b> = GF(5^2); k
|
|
1319
|
+
Finite Field in b of size 5^2
|
|
1320
|
+
sage: int(k(4))
|
|
1321
|
+
4
|
|
1322
|
+
sage: int(b)
|
|
1323
|
+
Traceback (most recent call last):
|
|
1324
|
+
...
|
|
1325
|
+
TypeError: Cannot coerce element to an integer.
|
|
1326
|
+
"""
|
|
1327
|
+
cdef int self_int = self._cache.log_to_int(self.element)
|
|
1328
|
+
if self_int % self._cache.characteristic() != self_int:
|
|
1329
|
+
raise TypeError("Cannot coerce element to an integer.")
|
|
1330
|
+
return self_int
|
|
1331
|
+
|
|
1332
|
+
def _integer_representation(FiniteField_givaroElement self):
|
|
1333
|
+
r"""
|
|
1334
|
+
Return the integer representation of ``self``. When ``self`` is in the
|
|
1335
|
+
prime subfield, the integer returned is equal to ``self``.
|
|
1336
|
+
|
|
1337
|
+
Elements of this field are represented as integers as follows:
|
|
1338
|
+
given the element `e \in \GF{p}[x]` with
|
|
1339
|
+
`e = a_0 + a_1 x + a_2 x^2 + \cdots`, the integer representation
|
|
1340
|
+
is `a_0 + a_1 p + a_2 p^2 + \cdots`.
|
|
1341
|
+
|
|
1342
|
+
OUTPUT: a Python ``int``
|
|
1343
|
+
|
|
1344
|
+
.. SEEALSO::
|
|
1345
|
+
|
|
1346
|
+
:meth:`sage.rings.finite_rings.element_base.FinitePolyExtElement.to_integer`
|
|
1347
|
+
|
|
1348
|
+
EXAMPLES::
|
|
1349
|
+
|
|
1350
|
+
sage: k.<b> = GF(5^2); k
|
|
1351
|
+
Finite Field in b of size 5^2
|
|
1352
|
+
sage: k(4)._integer_representation()
|
|
1353
|
+
4
|
|
1354
|
+
sage: b._integer_representation()
|
|
1355
|
+
5
|
|
1356
|
+
sage: type(b._integer_representation())
|
|
1357
|
+
<... 'int'>
|
|
1358
|
+
"""
|
|
1359
|
+
return self._cache.log_to_int(self.element)
|
|
1360
|
+
|
|
1361
|
+
def _integer_(FiniteField_givaroElement self, ZZ=None):
|
|
1362
|
+
"""
|
|
1363
|
+
Convert ``self`` to an integer if it is in the prime subfield.
|
|
1364
|
+
|
|
1365
|
+
EXAMPLES::
|
|
1366
|
+
|
|
1367
|
+
sage: k.<b> = GF(5^2); k
|
|
1368
|
+
Finite Field in b of size 5^2
|
|
1369
|
+
sage: k(4)._integer_()
|
|
1370
|
+
4
|
|
1371
|
+
sage: ZZ(b)
|
|
1372
|
+
Traceback (most recent call last):
|
|
1373
|
+
...
|
|
1374
|
+
TypeError: not in prime subfield
|
|
1375
|
+
"""
|
|
1376
|
+
cdef int a = self._cache.log_to_int(self.element)
|
|
1377
|
+
if a < self._cache.objectptr.characteristic():
|
|
1378
|
+
return Integer(a)
|
|
1379
|
+
raise TypeError("not in prime subfield")
|
|
1380
|
+
|
|
1381
|
+
def _log_to_int(FiniteField_givaroElement self):
|
|
1382
|
+
r"""
|
|
1383
|
+
Return the int representation of ``self``, as a Sage integer.
|
|
1384
|
+
|
|
1385
|
+
Elements of this field are represented as ints as follows:
|
|
1386
|
+
given the element `e \in \GF{p}[x]` with
|
|
1387
|
+
`e = a_0 + a_1x + a_2x^2 + \cdots`, the int representation is
|
|
1388
|
+
`a_0 + a_1 p + a_2 p^2 + \cdots`.
|
|
1389
|
+
|
|
1390
|
+
EXAMPLES::
|
|
1391
|
+
|
|
1392
|
+
sage: k.<b> = GF(5^2); k
|
|
1393
|
+
Finite Field in b of size 5^2
|
|
1394
|
+
sage: k(4)._log_to_int()
|
|
1395
|
+
4
|
|
1396
|
+
sage: b._log_to_int()
|
|
1397
|
+
5
|
|
1398
|
+
sage: type(b._log_to_int())
|
|
1399
|
+
<class 'sage.rings.integer.Integer'>
|
|
1400
|
+
"""
|
|
1401
|
+
return Integer(self._cache.log_to_int(self.element))
|
|
1402
|
+
|
|
1403
|
+
def log(FiniteField_givaroElement self, base, order=None, *, check=False):
|
|
1404
|
+
"""
|
|
1405
|
+
Return the log to the base `b` of ``self``, i.e., an integer `n`
|
|
1406
|
+
such that `b^n =` ``self``.
|
|
1407
|
+
|
|
1408
|
+
INPUT:
|
|
1409
|
+
|
|
1410
|
+
- ``base`` -- non-zero field element
|
|
1411
|
+
- ``order`` -- integer (optional), multiple of order of ``base``
|
|
1412
|
+
- ``check`` -- boolean (default: ``False``): If set,
|
|
1413
|
+
test whether the given ``order`` is correct.
|
|
1414
|
+
|
|
1415
|
+
.. WARNING::
|
|
1416
|
+
|
|
1417
|
+
TODO -- This is currently implemented by solving the discrete
|
|
1418
|
+
log problem -- which shouldn't be needed because of how finite field
|
|
1419
|
+
elements are represented.
|
|
1420
|
+
|
|
1421
|
+
EXAMPLES::
|
|
1422
|
+
|
|
1423
|
+
sage: k.<b> = GF(5^2); k
|
|
1424
|
+
Finite Field in b of size 5^2
|
|
1425
|
+
sage: a = b^7
|
|
1426
|
+
sage: a.log(b)
|
|
1427
|
+
7
|
|
1428
|
+
|
|
1429
|
+
TESTS:
|
|
1430
|
+
|
|
1431
|
+
An example for ``check=True``::
|
|
1432
|
+
|
|
1433
|
+
sage: F.<t> = GF(3^5, impl='givaro')
|
|
1434
|
+
sage: t.log(t, 3^4, check=True)
|
|
1435
|
+
Traceback (most recent call last):
|
|
1436
|
+
...
|
|
1437
|
+
ValueError: 81 is not a multiple of the order of the base
|
|
1438
|
+
"""
|
|
1439
|
+
b = self.parent()(base)
|
|
1440
|
+
if (order is not None) and check and not (b**order).is_one():
|
|
1441
|
+
raise ValueError(f"{order} is not a multiple of the order of the base")
|
|
1442
|
+
|
|
1443
|
+
return sage.groups.generic.discrete_log(self, b, ord=order)
|
|
1444
|
+
|
|
1445
|
+
def _int_repr(FiniteField_givaroElement self):
|
|
1446
|
+
r"""
|
|
1447
|
+
Return the string representation of ``self`` as an int (as returned
|
|
1448
|
+
by :meth:`log_to_int`).
|
|
1449
|
+
|
|
1450
|
+
EXAMPLES::
|
|
1451
|
+
|
|
1452
|
+
sage: k.<b> = GF(5^2); k
|
|
1453
|
+
Finite Field in b of size 5^2
|
|
1454
|
+
sage: (b+1)._int_repr()
|
|
1455
|
+
'6'
|
|
1456
|
+
"""
|
|
1457
|
+
return self._cache._element_int_repr(self)
|
|
1458
|
+
|
|
1459
|
+
def _log_repr(FiniteField_givaroElement self):
|
|
1460
|
+
r"""
|
|
1461
|
+
Return the log representation of ``self`` as a string. See the
|
|
1462
|
+
documentation of the ``_element_log_repr`` function of the
|
|
1463
|
+
parent field.
|
|
1464
|
+
|
|
1465
|
+
EXAMPLES::
|
|
1466
|
+
|
|
1467
|
+
sage: k.<b> = GF(5^2); k
|
|
1468
|
+
Finite Field in b of size 5^2
|
|
1469
|
+
sage: (b+2)._log_repr()
|
|
1470
|
+
'15'
|
|
1471
|
+
"""
|
|
1472
|
+
return self._cache._element_log_repr(self)
|
|
1473
|
+
|
|
1474
|
+
def _poly_repr(FiniteField_givaroElement self):
|
|
1475
|
+
r"""
|
|
1476
|
+
Return representation of this finite field element as a polynomial
|
|
1477
|
+
in the generator.
|
|
1478
|
+
|
|
1479
|
+
EXAMPLES::
|
|
1480
|
+
|
|
1481
|
+
sage: k.<b> = GF(5^2); k
|
|
1482
|
+
Finite Field in b of size 5^2
|
|
1483
|
+
sage: (b+2)._poly_repr()
|
|
1484
|
+
'b + 2'
|
|
1485
|
+
"""
|
|
1486
|
+
return self._cache._element_poly_repr(self)
|
|
1487
|
+
|
|
1488
|
+
def polynomial(FiniteField_givaroElement self, name=None):
|
|
1489
|
+
"""
|
|
1490
|
+
Return ``self`` viewed as a polynomial over
|
|
1491
|
+
``self.parent().prime_subfield()``.
|
|
1492
|
+
|
|
1493
|
+
EXAMPLES::
|
|
1494
|
+
|
|
1495
|
+
sage: k.<b> = GF(5^2); k
|
|
1496
|
+
Finite Field in b of size 5^2
|
|
1497
|
+
sage: f = (b^2+1).polynomial(); f
|
|
1498
|
+
b + 4
|
|
1499
|
+
sage: type(f) # needs sage.libs.flint
|
|
1500
|
+
<class 'sage.rings.polynomial.polynomial_zmod_flint.Polynomial_zmod_flint'>
|
|
1501
|
+
sage: parent(f)
|
|
1502
|
+
Univariate Polynomial Ring in b over Finite Field of size 5
|
|
1503
|
+
"""
|
|
1504
|
+
cdef Cache_givaro cache = self._cache
|
|
1505
|
+
K = self.parent()
|
|
1506
|
+
quo = cache.log_to_int(self.element)
|
|
1507
|
+
b = int(cache.characteristic())
|
|
1508
|
+
ret = []
|
|
1509
|
+
for i in range(K.degree()):
|
|
1510
|
+
coeff = quo % b
|
|
1511
|
+
ret.append(coeff)
|
|
1512
|
+
quo = quo // b
|
|
1513
|
+
if name is not None and K.variable_name() != name:
|
|
1514
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
1515
|
+
return PolynomialRing(K.prime_subfield(), name)(ret)
|
|
1516
|
+
else:
|
|
1517
|
+
return K.polynomial_ring()(ret)
|
|
1518
|
+
|
|
1519
|
+
def _magma_init_(self, magma):
|
|
1520
|
+
"""
|
|
1521
|
+
Return a string representation of ``self`` that MAGMA can
|
|
1522
|
+
understand.
|
|
1523
|
+
|
|
1524
|
+
EXAMPLES::
|
|
1525
|
+
|
|
1526
|
+
sage: k.<a> = GF(3^5)
|
|
1527
|
+
|
|
1528
|
+
String rep of parent::
|
|
1529
|
+
|
|
1530
|
+
sage: k._magma_init_(magma) # optional - magma
|
|
1531
|
+
'SageCreateWithNames(ext<GF(3)|_sage_[...]![GF(3)!1,GF(3)!2,GF(3)!0,GF(3)!0,GF(3)!0,GF(3)!1]>,["a"])'
|
|
1532
|
+
|
|
1533
|
+
Magma repr of element::
|
|
1534
|
+
|
|
1535
|
+
sage: a._magma_init_(magma) # optional - magma
|
|
1536
|
+
'_sage_[...]!(_sage_[...])'
|
|
1537
|
+
|
|
1538
|
+
Because of caching the string representation of an element must
|
|
1539
|
+
not change::
|
|
1540
|
+
|
|
1541
|
+
sage: a._magma_init_(magma) == a._magma_init_(magma) # optional - magma
|
|
1542
|
+
True
|
|
1543
|
+
|
|
1544
|
+
We test a conversion back and forth::
|
|
1545
|
+
|
|
1546
|
+
sage: k.<a> = GF(3^6)
|
|
1547
|
+
sage: b = magma(a^5 + 2*a^2 + 1) # optional - magma
|
|
1548
|
+
|
|
1549
|
+
Note that small fields print using a log representation in Magma
|
|
1550
|
+
(unlike Sage)::
|
|
1551
|
+
|
|
1552
|
+
sage: b # optional - magma
|
|
1553
|
+
a^436
|
|
1554
|
+
sage: b.sage() # optional - magma
|
|
1555
|
+
a^5 + 2*a^2 + 1
|
|
1556
|
+
"""
|
|
1557
|
+
R = magma(self.parent())
|
|
1558
|
+
a = R.gen(1).name()
|
|
1559
|
+
return '%s!(%s)' % (R.name(), self._cache._element_poly_repr(self, a))
|
|
1560
|
+
|
|
1561
|
+
def multiplicative_order(FiniteField_givaroElement self):
|
|
1562
|
+
"""
|
|
1563
|
+
Return the multiplicative order of this field element.
|
|
1564
|
+
|
|
1565
|
+
EXAMPLES::
|
|
1566
|
+
|
|
1567
|
+
sage: S.<b> = GF(5^2); S
|
|
1568
|
+
Finite Field in b of size 5^2
|
|
1569
|
+
sage: b.multiplicative_order()
|
|
1570
|
+
24
|
|
1571
|
+
sage: (b^6).multiplicative_order()
|
|
1572
|
+
4
|
|
1573
|
+
"""
|
|
1574
|
+
# TODO -- I'm sure this can be made vastly faster
|
|
1575
|
+
# using how elements are represented as a power of the generator ??
|
|
1576
|
+
|
|
1577
|
+
if self._multiplicative_order is not None:
|
|
1578
|
+
return self._multiplicative_order
|
|
1579
|
+
else:
|
|
1580
|
+
if self.is_zero():
|
|
1581
|
+
raise ArithmeticError("Multiplicative order of 0 not defined.")
|
|
1582
|
+
n = (self._cache).order_c() - 1
|
|
1583
|
+
order = Integer(1)
|
|
1584
|
+
for p, e in sage.arith.misc.factor(n):
|
|
1585
|
+
# Determine the power of p that divides the order.
|
|
1586
|
+
a = self**(n / (p**e))
|
|
1587
|
+
while a != 1:
|
|
1588
|
+
order = order * p
|
|
1589
|
+
a = a**p
|
|
1590
|
+
|
|
1591
|
+
self._multiplicative_order = order
|
|
1592
|
+
return order
|
|
1593
|
+
|
|
1594
|
+
def __copy__(self):
|
|
1595
|
+
"""
|
|
1596
|
+
Return a copy of this element. Actually just returns ``self``, since
|
|
1597
|
+
finite field elements are immutable.
|
|
1598
|
+
|
|
1599
|
+
EXAMPLES::
|
|
1600
|
+
|
|
1601
|
+
sage: S.<b> = GF(5^2); S
|
|
1602
|
+
Finite Field in b of size 5^2
|
|
1603
|
+
sage: c = copy(b); c
|
|
1604
|
+
b
|
|
1605
|
+
sage: c is b
|
|
1606
|
+
True
|
|
1607
|
+
sage: copy(5r) == 5r
|
|
1608
|
+
True
|
|
1609
|
+
"""
|
|
1610
|
+
return self
|
|
1611
|
+
|
|
1612
|
+
def __deepcopy__(self, memo):
|
|
1613
|
+
"""
|
|
1614
|
+
EXAMPLES::
|
|
1615
|
+
|
|
1616
|
+
sage: S.<b> = GF(5^2); S
|
|
1617
|
+
Finite Field in b of size 5^2
|
|
1618
|
+
sage: c = deepcopy(b); c
|
|
1619
|
+
b
|
|
1620
|
+
sage: c is b
|
|
1621
|
+
True
|
|
1622
|
+
"""
|
|
1623
|
+
return self
|
|
1624
|
+
|
|
1625
|
+
def _gap_init_(FiniteField_givaroElement self):
|
|
1626
|
+
"""
|
|
1627
|
+
Return a string that evaluates to the GAP representation of
|
|
1628
|
+
this element.
|
|
1629
|
+
|
|
1630
|
+
A :exc:`NotImplementedError` is raised if ``self.parent().modulus()``
|
|
1631
|
+
is not a Conway polynomial, as the isomorphism of finite fields is
|
|
1632
|
+
not implemented yet.
|
|
1633
|
+
|
|
1634
|
+
EXAMPLES::
|
|
1635
|
+
|
|
1636
|
+
sage: # needs sage.libs.gap
|
|
1637
|
+
sage: S.<b> = GF(5^2); S
|
|
1638
|
+
Finite Field in b of size 5^2
|
|
1639
|
+
sage: (4*b+3)._gap_init_()
|
|
1640
|
+
'Z(25)^3'
|
|
1641
|
+
sage: S(gap('Z(25)^3'))
|
|
1642
|
+
4*b + 3
|
|
1643
|
+
sage: S(libgap.Z(25)^3)
|
|
1644
|
+
4*b + 3
|
|
1645
|
+
"""
|
|
1646
|
+
cdef Cache_givaro cache = self._cache
|
|
1647
|
+
if self == 0:
|
|
1648
|
+
return '0*Z(%s)' % cache.order_c()
|
|
1649
|
+
F = self.parent()
|
|
1650
|
+
if F.degree() == 1:
|
|
1651
|
+
# Find the root of unity used by Gap. See _gap_init_ in sage.rings.finite_rings.integer_mod
|
|
1652
|
+
from sage.libs.gap.libgap import libgap # here to reduce dependencies
|
|
1653
|
+
from sage.rings.finite_rings.integer_mod import mod
|
|
1654
|
+
g = int(libgap.Int(libgap.Z(cache.order_c())))
|
|
1655
|
+
n = self.log(mod(g, cache.order_c()))
|
|
1656
|
+
return 'Z(%s)^%s' % (cache.order_c(), n)
|
|
1657
|
+
if not F.is_conway():
|
|
1658
|
+
raise NotImplementedError("conversion of (Givaro) finite field element to GAP not implemented except for fields defined by Conway polynomials.")
|
|
1659
|
+
if cache.order_c() > 65536:
|
|
1660
|
+
raise TypeError("order (=%s) must be at most 65536." % F.order_c())
|
|
1661
|
+
g = F.multiplicative_generator()
|
|
1662
|
+
n = self.log(g)
|
|
1663
|
+
return 'Z(%s)^%s' % (cache.order_c(), n)
|
|
1664
|
+
|
|
1665
|
+
def __hash__(FiniteField_givaroElement self):
|
|
1666
|
+
"""
|
|
1667
|
+
Return the hash of this finite field element. We hash the parent
|
|
1668
|
+
and the underlying integer representation of this element.
|
|
1669
|
+
|
|
1670
|
+
EXAMPLES::
|
|
1671
|
+
|
|
1672
|
+
sage: S.<a> = GF(5^3); S
|
|
1673
|
+
Finite Field in a of size 5^3
|
|
1674
|
+
sage: hash(a)
|
|
1675
|
+
5
|
|
1676
|
+
"""
|
|
1677
|
+
return hash(self._integer_representation())
|
|
1678
|
+
|
|
1679
|
+
def _vector_(FiniteField_givaroElement self, reverse=False):
|
|
1680
|
+
"""
|
|
1681
|
+
Return a vector matching this element in the vector space attached
|
|
1682
|
+
to the parent. The most significant bit is to the right.
|
|
1683
|
+
|
|
1684
|
+
INPUT:
|
|
1685
|
+
|
|
1686
|
+
- ``reverse`` -- reverse the order of the bits from little endian to
|
|
1687
|
+
big endian
|
|
1688
|
+
|
|
1689
|
+
EXAMPLES::
|
|
1690
|
+
|
|
1691
|
+
sage: # needs sage.modules
|
|
1692
|
+
sage: k.<a> = GF(2^4)
|
|
1693
|
+
sage: e = a^2 + 1
|
|
1694
|
+
sage: v = vector(e)
|
|
1695
|
+
sage: v
|
|
1696
|
+
(1, 0, 1, 0)
|
|
1697
|
+
sage: k(v)
|
|
1698
|
+
a^2 + 1
|
|
1699
|
+
|
|
1700
|
+
sage: # needs sage.modules
|
|
1701
|
+
sage: k.<a> = GF(3^4)
|
|
1702
|
+
sage: e = 2*a^2 + 1
|
|
1703
|
+
sage: v = vector(e)
|
|
1704
|
+
sage: v
|
|
1705
|
+
(1, 0, 2, 0)
|
|
1706
|
+
sage: k(v)
|
|
1707
|
+
2*a^2 + 1
|
|
1708
|
+
|
|
1709
|
+
You can also compute the vector in the other order::
|
|
1710
|
+
|
|
1711
|
+
sage: e._vector_(reverse=True) # needs sage.modules
|
|
1712
|
+
(0, 2, 0, 1)
|
|
1713
|
+
"""
|
|
1714
|
+
#vector(foo) might pass in ZZ
|
|
1715
|
+
if isinstance(reverse, Parent):
|
|
1716
|
+
raise TypeError("Base field is fixed to prime subfield.")
|
|
1717
|
+
cdef Cache_givaro cache = self._cache
|
|
1718
|
+
k = self.parent()
|
|
1719
|
+
|
|
1720
|
+
quo = cache.log_to_int(self.element)
|
|
1721
|
+
b = int(k.characteristic())
|
|
1722
|
+
|
|
1723
|
+
ret = []
|
|
1724
|
+
for i in range(k.degree()):
|
|
1725
|
+
coeff = quo % b
|
|
1726
|
+
ret.append(coeff)
|
|
1727
|
+
quo = quo // b
|
|
1728
|
+
if reverse:
|
|
1729
|
+
ret = list(reversed(ret))
|
|
1730
|
+
return k.vector_space(map=False)(ret)
|
|
1731
|
+
|
|
1732
|
+
def __reduce__(FiniteField_givaroElement self):
|
|
1733
|
+
"""
|
|
1734
|
+
Used for supporting pickling of finite field elements.
|
|
1735
|
+
|
|
1736
|
+
EXAMPLES::
|
|
1737
|
+
|
|
1738
|
+
sage: k = GF(2**8, 'a')
|
|
1739
|
+
sage: e = k.random_element()
|
|
1740
|
+
sage: TestSuite(e).run() # indirect doctest
|
|
1741
|
+
"""
|
|
1742
|
+
return unpickle_FiniteField_givaroElement,(self.parent(),self.element)
|
|
1743
|
+
|
|
1744
|
+
|
|
1745
|
+
def unpickle_FiniteField_givaroElement(parent, int x):
|
|
1746
|
+
"""
|
|
1747
|
+
TESTS::
|
|
1748
|
+
|
|
1749
|
+
sage: k = GF(3**4, 'a')
|
|
1750
|
+
sage: e = k.random_element()
|
|
1751
|
+
sage: TestSuite(e).run() # indirect doctest
|
|
1752
|
+
"""
|
|
1753
|
+
return make_FiniteField_givaroElement(parent._cache, x)
|
|
1754
|
+
|
|
1755
|
+
|
|
1756
|
+
from sage.misc.persist import register_unpickle_override
|
|
1757
|
+
register_unpickle_override('sage.rings.finite_field_givaro', 'unpickle_FiniteField_givaroElement', unpickle_FiniteField_givaroElement)
|
|
1758
|
+
|
|
1759
|
+
cdef inline FiniteField_givaroElement make_FiniteField_givaroElement(Cache_givaro cache, int x):
|
|
1760
|
+
cdef FiniteField_givaroElement y
|
|
1761
|
+
|
|
1762
|
+
if cache._has_array:
|
|
1763
|
+
return <FiniteField_givaroElement>cache._array[x]
|
|
1764
|
+
else:
|
|
1765
|
+
y = FiniteField_givaroElement.__new__(FiniteField_givaroElement)
|
|
1766
|
+
y._parent = <Parent> cache.parent
|
|
1767
|
+
y._cache = cache
|
|
1768
|
+
y.element = x
|
|
1769
|
+
return y
|