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,1441 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
"""
|
|
3
|
+
Finite field elements implemented via PARI's FFELT type
|
|
4
|
+
|
|
5
|
+
AUTHORS:
|
|
6
|
+
|
|
7
|
+
- Peter Bruin (June 2013): initial version, based on
|
|
8
|
+
element_ext_pari.py by William Stein et al. and
|
|
9
|
+
element_ntl_gf2e.pyx by Martin Albrecht.
|
|
10
|
+
"""
|
|
11
|
+
# ****************************************************************************
|
|
12
|
+
# Copyright (C) 2013 Peter Bruin <peter.bruin@math.uzh.ch>
|
|
13
|
+
#
|
|
14
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
15
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
16
|
+
# the License, or (at your option) any later version.
|
|
17
|
+
# https://www.gnu.org/licenses/
|
|
18
|
+
# ****************************************************************************
|
|
19
|
+
|
|
20
|
+
from cysignals.signals cimport sig_on, sig_off
|
|
21
|
+
|
|
22
|
+
from cypari2.paridecl cimport *
|
|
23
|
+
from cypari2.paripriv cimport *
|
|
24
|
+
from sage.libs.pari.convert_gmp cimport _new_GEN_from_mpz_t
|
|
25
|
+
from cypari2.stack cimport new_gen, new_gen_noclear, clear_stack
|
|
26
|
+
from cypari2.gen cimport Gen as pari_gen, objtogen
|
|
27
|
+
|
|
28
|
+
from sage.rings.finite_rings.element_base cimport FinitePolyExtElement
|
|
29
|
+
from sage.rings.finite_rings.integer_mod import IntegerMod_abstract
|
|
30
|
+
|
|
31
|
+
import sage.rings.integer
|
|
32
|
+
from sage.rings.integer cimport Integer
|
|
33
|
+
from sage.rings.polynomial.polynomial_element import Polynomial
|
|
34
|
+
from sage.rings.polynomial.multi_polynomial_element import MPolynomial
|
|
35
|
+
from sage.rings.rational import Rational
|
|
36
|
+
from sage.structure.element cimport Vector
|
|
37
|
+
from sage.structure.richcmp cimport rich_to_bool
|
|
38
|
+
|
|
39
|
+
from sage.interfaces.abc import GapElement
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
cdef GEN _INT_to_FFELT(GEN g, GEN x) except NULL:
|
|
43
|
+
"""
|
|
44
|
+
Convert the t_INT `x` to an element of the field of definition of
|
|
45
|
+
the t_FFELT `g`.
|
|
46
|
+
|
|
47
|
+
This function must be called within ``sig_on()`` ... ``sig_off()``.
|
|
48
|
+
|
|
49
|
+
TESTS:
|
|
50
|
+
|
|
51
|
+
Converting large integers to finite field elements does not lead
|
|
52
|
+
to overflow errors (see :issue:`16807`)::
|
|
53
|
+
|
|
54
|
+
sage: p = previous_prime(2^64)
|
|
55
|
+
sage: F.<x> = GF(p^2)
|
|
56
|
+
sage: x * 2^63
|
|
57
|
+
9223372036854775808*x
|
|
58
|
+
"""
|
|
59
|
+
cdef GEN f, p = gel(g, 4), result
|
|
60
|
+
cdef long t
|
|
61
|
+
|
|
62
|
+
x = modii(x, p)
|
|
63
|
+
if gequal0(x):
|
|
64
|
+
return FF_zero(g)
|
|
65
|
+
elif gequal1(x):
|
|
66
|
+
return FF_1(g)
|
|
67
|
+
else:
|
|
68
|
+
# In characteristic 2, we have already dealt with the
|
|
69
|
+
# two possible values of x, so we may assume that the
|
|
70
|
+
# characteristic is > 2.
|
|
71
|
+
t = g[1] # codeword: t_FF_FpXQ, t_FF_Flxq, t_FF_F2xq
|
|
72
|
+
if t == t_FF_FpXQ:
|
|
73
|
+
f = cgetg(3, t_POL)
|
|
74
|
+
set_gel(f, 1, gmael(g, 2, 1))
|
|
75
|
+
set_gel(f, 2, x)
|
|
76
|
+
elif t == t_FF_Flxq:
|
|
77
|
+
f = cgetg(3, t_VECSMALL)
|
|
78
|
+
set_gel(f, 1, gmael(g, 2, 1))
|
|
79
|
+
f[2] = itou(x)
|
|
80
|
+
else:
|
|
81
|
+
sig_off()
|
|
82
|
+
raise TypeError("unknown PARI finite field type")
|
|
83
|
+
result = cgetg(5, t_FFELT)
|
|
84
|
+
result[1] = t
|
|
85
|
+
set_gel(result, 2, f)
|
|
86
|
+
set_gel(result, 3, gel(g, 3)) # modulus
|
|
87
|
+
set_gel(result, 4, p)
|
|
88
|
+
return result
|
|
89
|
+
|
|
90
|
+
cdef class FiniteFieldElement_pari_ffelt(FinitePolyExtElement):
|
|
91
|
+
"""
|
|
92
|
+
An element of a finite field implemented using PARI.
|
|
93
|
+
|
|
94
|
+
EXAMPLES::
|
|
95
|
+
|
|
96
|
+
sage: K = FiniteField(10007^10, 'a', impl='pari_ffelt')
|
|
97
|
+
sage: a = K.gen(); a
|
|
98
|
+
a
|
|
99
|
+
sage: type(a)
|
|
100
|
+
<class 'sage.rings.finite_rings.element_pari_ffelt.FiniteFieldElement_pari_ffelt'>
|
|
101
|
+
|
|
102
|
+
TESTS::
|
|
103
|
+
|
|
104
|
+
sage: n = 63
|
|
105
|
+
sage: m = 3
|
|
106
|
+
sage: K.<a> = GF(2^n, impl='pari_ffelt')
|
|
107
|
+
sage: f = conway_polynomial(2, n)
|
|
108
|
+
sage: f(a) == 0
|
|
109
|
+
True
|
|
110
|
+
sage: e = (2^n - 1) / (2^m - 1)
|
|
111
|
+
sage: conway_polynomial(2, m)(a^e) == 0
|
|
112
|
+
True
|
|
113
|
+
|
|
114
|
+
sage: K.<a> = FiniteField(2^16, impl='pari_ffelt')
|
|
115
|
+
sage: K(0).is_zero()
|
|
116
|
+
True
|
|
117
|
+
sage: (a - a).is_zero()
|
|
118
|
+
True
|
|
119
|
+
sage: a - a
|
|
120
|
+
0
|
|
121
|
+
sage: a == a
|
|
122
|
+
True
|
|
123
|
+
sage: a - a == 0
|
|
124
|
+
True
|
|
125
|
+
sage: a - a == K(0)
|
|
126
|
+
True
|
|
127
|
+
sage: TestSuite(a).run()
|
|
128
|
+
|
|
129
|
+
Test creating elements from basic Python types::
|
|
130
|
+
|
|
131
|
+
sage: K.<a> = FiniteField(7^20, impl='pari_ffelt')
|
|
132
|
+
sage: K(int(8))
|
|
133
|
+
1
|
|
134
|
+
|
|
135
|
+
::
|
|
136
|
+
|
|
137
|
+
sage: k = FiniteField(3^4, 'a', impl='pari_ffelt')
|
|
138
|
+
sage: b = k(5) # indirect doctest
|
|
139
|
+
sage: b.parent()
|
|
140
|
+
Finite Field in a of size 3^4
|
|
141
|
+
sage: a = k.gen()
|
|
142
|
+
sage: k(a + 2)
|
|
143
|
+
a + 2
|
|
144
|
+
|
|
145
|
+
Univariate polynomials coerce into finite fields by evaluating
|
|
146
|
+
the polynomial at the field's generator::
|
|
147
|
+
|
|
148
|
+
sage: R.<x> = QQ[]
|
|
149
|
+
sage: k.<a> = FiniteField(5^2, 'a', impl='pari_ffelt')
|
|
150
|
+
sage: k(R(2/3))
|
|
151
|
+
4
|
|
152
|
+
sage: k(x^2)
|
|
153
|
+
a + 3
|
|
154
|
+
|
|
155
|
+
sage: R.<x> = GF(5)[]
|
|
156
|
+
sage: k(x^3-2*x+1)
|
|
157
|
+
2*a + 4
|
|
158
|
+
|
|
159
|
+
sage: x = polygen(QQ)
|
|
160
|
+
sage: k(x^25)
|
|
161
|
+
a
|
|
162
|
+
|
|
163
|
+
sage: Q.<q> = FiniteField(5^7, 'q', impl='pari_ffelt')
|
|
164
|
+
sage: L = GF(5)
|
|
165
|
+
sage: LL.<xx> = L[]
|
|
166
|
+
sage: Q(xx^2 + 2*xx + 4)
|
|
167
|
+
q^2 + 2*q + 4
|
|
168
|
+
|
|
169
|
+
sage: k = FiniteField(3^11, 't', impl='pari_ffelt')
|
|
170
|
+
sage: k.polynomial()
|
|
171
|
+
t^11 + 2*t^2 + 1
|
|
172
|
+
sage: P = k.polynomial_ring()
|
|
173
|
+
sage: k(P.0^11)
|
|
174
|
+
t^2 + 2
|
|
175
|
+
|
|
176
|
+
An element can be specified by its vector of coordinates with
|
|
177
|
+
respect to the basis consisting of powers of the generator:
|
|
178
|
+
|
|
179
|
+
sage: # needs sage.modules
|
|
180
|
+
sage: k = FiniteField(3^11, 't', impl='pari_ffelt')
|
|
181
|
+
sage: V = k.vector_space(map=False)
|
|
182
|
+
sage: V
|
|
183
|
+
Vector space of dimension 11 over Finite Field of size 3
|
|
184
|
+
sage: v = V([0,1,2,0,1,2,0,1,2,0,1])
|
|
185
|
+
sage: k(v)
|
|
186
|
+
t^10 + 2*t^8 + t^7 + 2*t^5 + t^4 + 2*t^2 + t
|
|
187
|
+
|
|
188
|
+
Multivariate polynomials only coerce if constant::
|
|
189
|
+
|
|
190
|
+
sage: k = FiniteField(5^2, 'a', impl='pari_ffelt')
|
|
191
|
+
sage: R = k['x,y,z']; R
|
|
192
|
+
Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2
|
|
193
|
+
sage: k(R(2))
|
|
194
|
+
2
|
|
195
|
+
sage: R = QQ['x,y,z']
|
|
196
|
+
sage: k(R(1/5))
|
|
197
|
+
Traceback (most recent call last):
|
|
198
|
+
...
|
|
199
|
+
ZeroDivisionError: inverse of Mod(0, 5) does not exist
|
|
200
|
+
|
|
201
|
+
Gap elements can also be coerced into finite fields::
|
|
202
|
+
|
|
203
|
+
sage: F = FiniteField(2^3, 'a', impl='pari_ffelt')
|
|
204
|
+
sage: a = F.multiplicative_generator(); a
|
|
205
|
+
a
|
|
206
|
+
sage: b = gap(a^3); b # needs sage.libs.gap
|
|
207
|
+
Z(2^3)^3
|
|
208
|
+
sage: F(b) # needs sage.libs.gap
|
|
209
|
+
a + 1
|
|
210
|
+
sage: a^3
|
|
211
|
+
a + 1
|
|
212
|
+
|
|
213
|
+
sage: a = GF(13)(gap('0*Z(13)')); a # needs sage.libs.gap
|
|
214
|
+
0
|
|
215
|
+
sage: a.parent() # needs sage.libs.gap
|
|
216
|
+
Finite Field of size 13
|
|
217
|
+
|
|
218
|
+
sage: F = FiniteField(2^4, 'a', impl='pari_ffelt')
|
|
219
|
+
sage: F(gap('Z(16)^3')) # needs sage.libs.gap
|
|
220
|
+
a^3
|
|
221
|
+
sage: F(gap('Z(16)^2')) # needs sage.libs.gap
|
|
222
|
+
a^2
|
|
223
|
+
|
|
224
|
+
You can also call a finite extension field with a string
|
|
225
|
+
to produce an element of that field, like this::
|
|
226
|
+
|
|
227
|
+
sage: k = GF(2^8, 'a')
|
|
228
|
+
sage: k('a^200')
|
|
229
|
+
a^4 + a^3 + a^2
|
|
230
|
+
|
|
231
|
+
This is especially useful for conversion from Singular etc.
|
|
232
|
+
|
|
233
|
+
TESTS::
|
|
234
|
+
|
|
235
|
+
sage: k = FiniteField(3^2, 'a', impl='pari_ffelt')
|
|
236
|
+
sage: a = k(11); a
|
|
237
|
+
2
|
|
238
|
+
sage: a.parent()
|
|
239
|
+
Finite Field in a of size 3^2
|
|
240
|
+
sage: V = k.vector_space(map=False); v = V((1,2)) # needs sage.modules
|
|
241
|
+
sage: k(v) # needs sage.modules
|
|
242
|
+
2*a + 1
|
|
243
|
+
|
|
244
|
+
We create elements using a list and verify that :issue:`10486` has
|
|
245
|
+
been fixed::
|
|
246
|
+
|
|
247
|
+
sage: k = FiniteField(3^11, 't', impl='pari_ffelt')
|
|
248
|
+
sage: x = k([1,0,2,1]); x
|
|
249
|
+
t^3 + 2*t^2 + 1
|
|
250
|
+
sage: x + x + x
|
|
251
|
+
0
|
|
252
|
+
sage: pari(x)
|
|
253
|
+
t^3 + 2*t^2 + 1
|
|
254
|
+
|
|
255
|
+
If the list is longer than the degree, we just get the result
|
|
256
|
+
modulo the modulus::
|
|
257
|
+
|
|
258
|
+
sage: from sage.rings.finite_rings.finite_field_pari_ffelt import FiniteField_pari_ffelt
|
|
259
|
+
sage: R.<a> = PolynomialRing(GF(5))
|
|
260
|
+
sage: k = FiniteField_pari_ffelt(5, a^2 - 2, 't')
|
|
261
|
+
sage: x = k([0,0,0,1]); x
|
|
262
|
+
2*t
|
|
263
|
+
sage: pari(x)
|
|
264
|
+
2*t
|
|
265
|
+
|
|
266
|
+
When initializing from a list, the elements are first coerced
|
|
267
|
+
to the prime field (:issue:`11685`)::
|
|
268
|
+
|
|
269
|
+
sage: k = FiniteField(3^11, 't', impl='pari_ffelt')
|
|
270
|
+
sage: k([ 0, 1/2 ])
|
|
271
|
+
2*t
|
|
272
|
+
sage: k([ 0, 1/2, 0, 0, 0, 0, 0, 0, 0, -1, 0 ])
|
|
273
|
+
2*t^9 + 2*t
|
|
274
|
+
sage: k([ k(0), k(1) ])
|
|
275
|
+
t
|
|
276
|
+
sage: k([ GF(3)(2), GF(3^5,'u')(1) ])
|
|
277
|
+
t + 2
|
|
278
|
+
sage: R.<x> = PolynomialRing(k)
|
|
279
|
+
sage: k([ x/x ])
|
|
280
|
+
1
|
|
281
|
+
sage: k([ R(-1), x/x ])
|
|
282
|
+
t + 2
|
|
283
|
+
sage: k([ R(-1), R(0), 0 ])
|
|
284
|
+
2
|
|
285
|
+
|
|
286
|
+
Check that zeros are created correctly (:issue:`11685`)::
|
|
287
|
+
|
|
288
|
+
sage: K = FiniteField(3^11, 't', impl='pari_ffelt'); a = K.0
|
|
289
|
+
sage: v = 0; pari(K(v))
|
|
290
|
+
0
|
|
291
|
+
sage: v = Mod(0,3); pari(K(v))
|
|
292
|
+
0
|
|
293
|
+
sage: v = pari(0); pari(K(v))
|
|
294
|
+
0
|
|
295
|
+
sage: v = pari("Mod(0,3)"); pari(K(v))
|
|
296
|
+
0
|
|
297
|
+
sage: v = []; pari(K(v))
|
|
298
|
+
0
|
|
299
|
+
sage: v = [0]; pari(K(v))
|
|
300
|
+
0
|
|
301
|
+
sage: v = [0,0]; pari(K(v))
|
|
302
|
+
0
|
|
303
|
+
sage: v = pari("Pol(0)"); pari(K(v))
|
|
304
|
+
0
|
|
305
|
+
sage: v = pari("Mod(0, %s)"%K.modulus()); pari(K(v))
|
|
306
|
+
0
|
|
307
|
+
sage: v = pari("Mod(Pol(0), %s)"%K.modulus()); pari(K(v))
|
|
308
|
+
0
|
|
309
|
+
sage: v = K(1) - K(1); pari(K(v))
|
|
310
|
+
0
|
|
311
|
+
sage: v = K([1]) - K([1]); pari(K(v))
|
|
312
|
+
0
|
|
313
|
+
sage: v = a - a; pari(K(v))
|
|
314
|
+
0
|
|
315
|
+
sage: v = K(1)*0; pari(K(v))
|
|
316
|
+
0
|
|
317
|
+
sage: v = K([1])*K([0]); pari(K(v))
|
|
318
|
+
0
|
|
319
|
+
sage: v = a*0; pari(K(v))
|
|
320
|
+
0
|
|
321
|
+
"""
|
|
322
|
+
|
|
323
|
+
def __init__(self, parent, x):
|
|
324
|
+
"""
|
|
325
|
+
Initialise ``self`` with the given ``parent`` and value
|
|
326
|
+
converted from ``x``.
|
|
327
|
+
|
|
328
|
+
This is called when constructing elements from Python.
|
|
329
|
+
|
|
330
|
+
TESTS::
|
|
331
|
+
|
|
332
|
+
sage: from sage.rings.finite_rings.element_pari_ffelt import FiniteFieldElement_pari_ffelt
|
|
333
|
+
sage: K = FiniteField(101^2, 'a', impl='pari_ffelt')
|
|
334
|
+
sage: x = FiniteFieldElement_pari_ffelt(K, 'a + 1')
|
|
335
|
+
sage: x
|
|
336
|
+
a + 1
|
|
337
|
+
"""
|
|
338
|
+
# FinitePolyExtElement.__init__(self, parent)
|
|
339
|
+
self._parent = parent
|
|
340
|
+
self.construct_from(x)
|
|
341
|
+
|
|
342
|
+
def __dealloc__(self):
|
|
343
|
+
"""
|
|
344
|
+
Cython destructor.
|
|
345
|
+
"""
|
|
346
|
+
if self.val is not NULL:
|
|
347
|
+
gunclone_deep(self.val)
|
|
348
|
+
|
|
349
|
+
cdef FiniteFieldElement_pari_ffelt _new(self):
|
|
350
|
+
"""
|
|
351
|
+
Create an empty element with the same parent as ``self``.
|
|
352
|
+
"""
|
|
353
|
+
cdef FiniteFieldElement_pari_ffelt x
|
|
354
|
+
x = FiniteFieldElement_pari_ffelt.__new__(FiniteFieldElement_pari_ffelt)
|
|
355
|
+
x._parent = self._parent
|
|
356
|
+
return x
|
|
357
|
+
|
|
358
|
+
cdef void construct(self, GEN g) noexcept:
|
|
359
|
+
"""
|
|
360
|
+
Initialise ``self`` to the FFELT ``g``, reset the PARI stack,
|
|
361
|
+
and call sig_off().
|
|
362
|
+
|
|
363
|
+
This should be called exactly once on every instance.
|
|
364
|
+
"""
|
|
365
|
+
self.val = gcloneref(g)
|
|
366
|
+
clear_stack()
|
|
367
|
+
|
|
368
|
+
cdef int construct_from(self, x) except -1:
|
|
369
|
+
"""
|
|
370
|
+
Initialise ``self`` to an FFELT constructed from the Sage
|
|
371
|
+
object `x`.
|
|
372
|
+
|
|
373
|
+
TESTS:
|
|
374
|
+
|
|
375
|
+
Conversion of elements of the underlying vector space works in
|
|
376
|
+
large characteristic (see :issue:`21186`)::
|
|
377
|
+
|
|
378
|
+
sage: p = 13189065031705623239
|
|
379
|
+
sage: Fq = FiniteField(p^3, "a")
|
|
380
|
+
sage: Fq_X = PolynomialRing(Fq, "x")
|
|
381
|
+
sage: pol = Fq_X("x^9 + 13189065031705622723*x^7 + 13189065031705622723*x^6 + 9288*x^5 + 18576*x^4 + 13189065031705590731*x^3 + 13189065031705497851*x^2 + 13189065031705497851*x + 13189065031705581443")
|
|
382
|
+
sage: R = [r[0] for r in pol.roots()]
|
|
383
|
+
sage: prod(Fq_X.gen() - r for r in R) == pol
|
|
384
|
+
True
|
|
385
|
+
"""
|
|
386
|
+
cdef GEN f, g, result, x_GEN
|
|
387
|
+
cdef long i, n, t
|
|
388
|
+
cdef Integer xi
|
|
389
|
+
|
|
390
|
+
if isinstance(x, FiniteFieldElement_pari_ffelt):
|
|
391
|
+
if self._parent is (<FiniteFieldElement_pari_ffelt>x)._parent:
|
|
392
|
+
sig_on()
|
|
393
|
+
self.construct((<FiniteFieldElement_pari_ffelt>x).val)
|
|
394
|
+
else:
|
|
395
|
+
raise TypeError("no coercion defined")
|
|
396
|
+
|
|
397
|
+
elif isinstance(x, Integer):
|
|
398
|
+
g = (<pari_gen>self._parent._gen_pari).g
|
|
399
|
+
sig_on()
|
|
400
|
+
x_GEN = _new_GEN_from_mpz_t((<Integer>x).value)
|
|
401
|
+
self.construct(_INT_to_FFELT(g, x_GEN))
|
|
402
|
+
|
|
403
|
+
elif isinstance(x, int):
|
|
404
|
+
g = (<pari_gen>self._parent._gen_pari).g
|
|
405
|
+
x = objtogen(x)
|
|
406
|
+
sig_on()
|
|
407
|
+
x_GEN = (<pari_gen>x).g
|
|
408
|
+
self.construct(_INT_to_FFELT(g, x_GEN))
|
|
409
|
+
|
|
410
|
+
elif isinstance(x, IntegerMod_abstract):
|
|
411
|
+
if self._parent.characteristic().divides(x.modulus()):
|
|
412
|
+
g = (<pari_gen>self._parent._gen_pari).g
|
|
413
|
+
sig_on()
|
|
414
|
+
x_GEN = _new_GEN_from_mpz_t(Integer(x).value)
|
|
415
|
+
self.construct(_INT_to_FFELT(g, x_GEN))
|
|
416
|
+
else:
|
|
417
|
+
raise TypeError("no coercion defined")
|
|
418
|
+
|
|
419
|
+
elif x is None:
|
|
420
|
+
g = (<pari_gen>self._parent._gen_pari).g
|
|
421
|
+
sig_on()
|
|
422
|
+
self.construct(FF_zero(g))
|
|
423
|
+
|
|
424
|
+
elif isinstance(x, pari_gen):
|
|
425
|
+
g = (<pari_gen>self._parent._gen_pari).g
|
|
426
|
+
x_GEN = (<pari_gen>x).g
|
|
427
|
+
|
|
428
|
+
sig_on()
|
|
429
|
+
if gequal0(x_GEN):
|
|
430
|
+
self.construct(FF_zero(g))
|
|
431
|
+
return 0
|
|
432
|
+
elif gequal1(x_GEN):
|
|
433
|
+
self.construct(FF_1(g))
|
|
434
|
+
return 0
|
|
435
|
+
|
|
436
|
+
t = typ(x_GEN)
|
|
437
|
+
if t == t_FFELT:
|
|
438
|
+
if FF_samefield(x_GEN, g):
|
|
439
|
+
self.construct(x_GEN)
|
|
440
|
+
return 0
|
|
441
|
+
elif t == t_INT:
|
|
442
|
+
self.construct(_INT_to_FFELT(g, x_GEN))
|
|
443
|
+
return 0
|
|
444
|
+
elif t == t_INTMOD:
|
|
445
|
+
if gequal0(modii(gel(x_GEN, 1), FF_p_i(g))):
|
|
446
|
+
self.construct(_INT_to_FFELT(g, gel(x_GEN, 2)))
|
|
447
|
+
return 0
|
|
448
|
+
elif t == t_FRAC:
|
|
449
|
+
if not gequal0(modii(gel(x_GEN, 2), FF_p_i(g))):
|
|
450
|
+
elt = FF_div(_INT_to_FFELT(g, gel(x_GEN, 1)),
|
|
451
|
+
_INT_to_FFELT(g, gel(x_GEN, 2)))
|
|
452
|
+
self.construct(elt)
|
|
453
|
+
return 0
|
|
454
|
+
sig_off()
|
|
455
|
+
raise TypeError(f"unable to convert PARI {x.type()} to finite field element")
|
|
456
|
+
|
|
457
|
+
elif (isinstance(x, Vector)
|
|
458
|
+
and x.parent() is self._parent.vector_space(map=False)):
|
|
459
|
+
g = (<pari_gen>self._parent._gen_pari).g
|
|
460
|
+
t = g[1] # codeword: t_FF_FpXQ, t_FF_Flxq, t_FF_F2xq
|
|
461
|
+
n = len(x)
|
|
462
|
+
while n > 0 and x[n - 1] == 0:
|
|
463
|
+
n -= 1
|
|
464
|
+
sig_on()
|
|
465
|
+
if n == 0:
|
|
466
|
+
self.construct(FF_zero(g))
|
|
467
|
+
return 0
|
|
468
|
+
if t == t_FF_FpXQ:
|
|
469
|
+
f = cgetg(n + 2, t_POL)
|
|
470
|
+
set_gel(f, 1, gmael(g, 2, 1))
|
|
471
|
+
for i in range(n):
|
|
472
|
+
xi = Integer(x[i])
|
|
473
|
+
set_gel(f, i + 2, _new_GEN_from_mpz_t(xi.value))
|
|
474
|
+
elif t == t_FF_Flxq or t == t_FF_F2xq:
|
|
475
|
+
f = cgetg(n + 2, t_VECSMALL)
|
|
476
|
+
set_gel(f, 1, gmael(g, 2, 1))
|
|
477
|
+
for i in range(n):
|
|
478
|
+
set_uel(f, i + 2, x[i])
|
|
479
|
+
if t == t_FF_F2xq:
|
|
480
|
+
f = Flx_to_F2x(f)
|
|
481
|
+
else:
|
|
482
|
+
sig_off()
|
|
483
|
+
raise TypeError("unknown PARI finite field type")
|
|
484
|
+
result = cgetg(5, t_FFELT)
|
|
485
|
+
result[1] = t
|
|
486
|
+
set_gel(result, 2, f)
|
|
487
|
+
set_gel(result, 3, gel(g, 3)) # modulus
|
|
488
|
+
set_gel(result, 4, gel(g, 4)) # p
|
|
489
|
+
self.construct(result)
|
|
490
|
+
|
|
491
|
+
elif isinstance(x, Rational):
|
|
492
|
+
self.construct_from(x % self._parent.characteristic())
|
|
493
|
+
|
|
494
|
+
elif isinstance(x, Polynomial):
|
|
495
|
+
if x.base_ring() is not self._parent.base_ring():
|
|
496
|
+
x = x.change_ring(self._parent.base_ring())
|
|
497
|
+
self.construct_from(x.substitute(self._parent.gen()))
|
|
498
|
+
|
|
499
|
+
elif isinstance(x, MPolynomial) and x.is_constant():
|
|
500
|
+
self.construct_from(x.constant_coefficient())
|
|
501
|
+
|
|
502
|
+
elif isinstance(x, list):
|
|
503
|
+
n = len(x)
|
|
504
|
+
if n == 0:
|
|
505
|
+
self.construct_from(None)
|
|
506
|
+
elif n == 1:
|
|
507
|
+
Fp = self._parent.base_ring()
|
|
508
|
+
self.construct_from(Fp(x[0]))
|
|
509
|
+
elif n == self._parent.degree():
|
|
510
|
+
self.construct_from(self._parent.vector_space(map=False)(x))
|
|
511
|
+
else:
|
|
512
|
+
Fp = self._parent.base_ring()
|
|
513
|
+
self.construct_from(self._parent.polynomial_ring()([Fp(y) for y in x]))
|
|
514
|
+
|
|
515
|
+
elif isinstance(x, str):
|
|
516
|
+
self.construct_from(self._parent.polynomial_ring()(x))
|
|
517
|
+
|
|
518
|
+
elif isinstance(x, GapElement):
|
|
519
|
+
try:
|
|
520
|
+
from sage.libs.gap.libgap import libgap
|
|
521
|
+
self.construct_from(libgap(x).sage(ring=self._parent))
|
|
522
|
+
except (ValueError, IndexError, TypeError):
|
|
523
|
+
raise TypeError("no coercion defined")
|
|
524
|
+
|
|
525
|
+
else:
|
|
526
|
+
try:
|
|
527
|
+
from sage.libs.gap.element import GapElement_FiniteField
|
|
528
|
+
except ImportError:
|
|
529
|
+
raise TypeError("no coercion defined")
|
|
530
|
+
else:
|
|
531
|
+
if isinstance(x, GapElement_FiniteField):
|
|
532
|
+
try:
|
|
533
|
+
self.construct_from(x.sage(ring=self._parent))
|
|
534
|
+
except (ValueError, IndexError, TypeError):
|
|
535
|
+
raise TypeError("no coercion defined")
|
|
536
|
+
else:
|
|
537
|
+
raise TypeError("no coercion defined")
|
|
538
|
+
|
|
539
|
+
def _repr_(self):
|
|
540
|
+
"""
|
|
541
|
+
Return the string representation of ``self``.
|
|
542
|
+
|
|
543
|
+
EXAMPLES::
|
|
544
|
+
|
|
545
|
+
sage: k.<c> = GF(3^17, impl='pari_ffelt')
|
|
546
|
+
sage: c^20 # indirect doctest
|
|
547
|
+
c^4 + 2*c^3
|
|
548
|
+
"""
|
|
549
|
+
return str(new_gen_noclear(self.val))
|
|
550
|
+
|
|
551
|
+
def __hash__(self):
|
|
552
|
+
"""
|
|
553
|
+
Return the hash of ``self``. This is by definition equal to
|
|
554
|
+
the hash of ``self.polynomial()``.
|
|
555
|
+
|
|
556
|
+
EXAMPLES::
|
|
557
|
+
|
|
558
|
+
sage: k.<a> = GF(3^15, impl='pari_ffelt')
|
|
559
|
+
sage: R = GF(3)['a']; aa = R.gen()
|
|
560
|
+
sage: hash(a^2 + 1) == hash(aa^2 + 1)
|
|
561
|
+
True
|
|
562
|
+
"""
|
|
563
|
+
return hash(self.polynomial())
|
|
564
|
+
|
|
565
|
+
def __reduce__(self):
|
|
566
|
+
"""
|
|
567
|
+
For pickling.
|
|
568
|
+
|
|
569
|
+
TESTS::
|
|
570
|
+
|
|
571
|
+
sage: K.<a> = FiniteField(10007^10, impl='pari_ffelt')
|
|
572
|
+
sage: loads(a.dumps()) == a
|
|
573
|
+
True
|
|
574
|
+
"""
|
|
575
|
+
return unpickle_FiniteFieldElement_pari_ffelt, (self._parent, str(self))
|
|
576
|
+
|
|
577
|
+
def __copy__(self):
|
|
578
|
+
"""
|
|
579
|
+
TESTS::
|
|
580
|
+
|
|
581
|
+
sage: k.<a> = FiniteField(3^3, impl='pari_ffelt')
|
|
582
|
+
sage: a
|
|
583
|
+
a
|
|
584
|
+
sage: b = copy(a); b
|
|
585
|
+
a
|
|
586
|
+
sage: a is b
|
|
587
|
+
True
|
|
588
|
+
"""
|
|
589
|
+
# immutable
|
|
590
|
+
return self
|
|
591
|
+
|
|
592
|
+
def __deepcopy__(self, memo):
|
|
593
|
+
"""
|
|
594
|
+
TESTS::
|
|
595
|
+
|
|
596
|
+
sage: k.<a> = FiniteField(3^3, impl='pari_ffelt')
|
|
597
|
+
sage: a
|
|
598
|
+
a
|
|
599
|
+
sage: b = deepcopy(a); b
|
|
600
|
+
a
|
|
601
|
+
sage: a is b
|
|
602
|
+
True
|
|
603
|
+
"""
|
|
604
|
+
# immutable
|
|
605
|
+
return self
|
|
606
|
+
|
|
607
|
+
cpdef _richcmp_(self, other, int op):
|
|
608
|
+
"""
|
|
609
|
+
Comparison of finite field elements.
|
|
610
|
+
|
|
611
|
+
.. NOTE::
|
|
612
|
+
|
|
613
|
+
Finite fields are unordered. However, for the purpose of
|
|
614
|
+
this function, we adopt the lexicographic ordering on the
|
|
615
|
+
representing polynomials.
|
|
616
|
+
|
|
617
|
+
EXAMPLES::
|
|
618
|
+
|
|
619
|
+
sage: # needs sage.modules
|
|
620
|
+
sage: k.<a> = GF(2^20, impl='pari_ffelt')
|
|
621
|
+
sage: e = k.random_element()
|
|
622
|
+
sage: f = loads(dumps(e))
|
|
623
|
+
sage: e is f
|
|
624
|
+
False
|
|
625
|
+
sage: e == f
|
|
626
|
+
True
|
|
627
|
+
sage: e != (e + 1)
|
|
628
|
+
True
|
|
629
|
+
|
|
630
|
+
::
|
|
631
|
+
|
|
632
|
+
sage: K.<a> = GF(2^100, impl='pari_ffelt')
|
|
633
|
+
sage: a < a^2
|
|
634
|
+
True
|
|
635
|
+
sage: a > a^2
|
|
636
|
+
False
|
|
637
|
+
sage: a+1 > a^2
|
|
638
|
+
False
|
|
639
|
+
sage: a+1 < a^2
|
|
640
|
+
True
|
|
641
|
+
sage: a+1 < a
|
|
642
|
+
False
|
|
643
|
+
sage: a+1 == a
|
|
644
|
+
False
|
|
645
|
+
sage: a == a
|
|
646
|
+
True
|
|
647
|
+
|
|
648
|
+
TESTS::
|
|
649
|
+
|
|
650
|
+
sage: k.<a> = FiniteField(3^3, impl='pari_ffelt')
|
|
651
|
+
sage: a == 1
|
|
652
|
+
False
|
|
653
|
+
sage: a^0 == 1
|
|
654
|
+
True
|
|
655
|
+
sage: a == a
|
|
656
|
+
True
|
|
657
|
+
sage: a < a^2
|
|
658
|
+
True
|
|
659
|
+
sage: a > a^2
|
|
660
|
+
False
|
|
661
|
+
"""
|
|
662
|
+
cdef int r
|
|
663
|
+
sig_on()
|
|
664
|
+
r = cmp_universal(self.val, (<FiniteFieldElement_pari_ffelt>other).val)
|
|
665
|
+
sig_off()
|
|
666
|
+
return rich_to_bool(op, r)
|
|
667
|
+
|
|
668
|
+
cpdef _add_(self, right):
|
|
669
|
+
"""
|
|
670
|
+
Addition.
|
|
671
|
+
|
|
672
|
+
EXAMPLES::
|
|
673
|
+
|
|
674
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
675
|
+
sage: a + a^2 # indirect doctest
|
|
676
|
+
a^2 + a
|
|
677
|
+
"""
|
|
678
|
+
cdef FiniteFieldElement_pari_ffelt x = self._new()
|
|
679
|
+
sig_on()
|
|
680
|
+
x.construct(FF_add((<FiniteFieldElement_pari_ffelt>self).val,
|
|
681
|
+
(<FiniteFieldElement_pari_ffelt>right).val))
|
|
682
|
+
return x
|
|
683
|
+
|
|
684
|
+
cpdef _sub_(self, right):
|
|
685
|
+
"""
|
|
686
|
+
Subtraction.
|
|
687
|
+
|
|
688
|
+
EXAMPLES::
|
|
689
|
+
|
|
690
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
691
|
+
sage: a - a # indirect doctest
|
|
692
|
+
0
|
|
693
|
+
"""
|
|
694
|
+
cdef FiniteFieldElement_pari_ffelt x = self._new()
|
|
695
|
+
sig_on()
|
|
696
|
+
x.construct(FF_sub((<FiniteFieldElement_pari_ffelt>self).val,
|
|
697
|
+
(<FiniteFieldElement_pari_ffelt>right).val))
|
|
698
|
+
return x
|
|
699
|
+
|
|
700
|
+
cpdef _mul_(self, right):
|
|
701
|
+
"""
|
|
702
|
+
Multiplication.
|
|
703
|
+
|
|
704
|
+
EXAMPLES::
|
|
705
|
+
|
|
706
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
707
|
+
sage: (a^12 + 1)*(a^15 - 1) # indirect doctest
|
|
708
|
+
a^15 + 2*a^12 + a^11 + 2*a^10 + 2
|
|
709
|
+
"""
|
|
710
|
+
cdef FiniteFieldElement_pari_ffelt x = self._new()
|
|
711
|
+
sig_on()
|
|
712
|
+
x.construct(FF_mul((<FiniteFieldElement_pari_ffelt>self).val,
|
|
713
|
+
(<FiniteFieldElement_pari_ffelt>right).val))
|
|
714
|
+
return x
|
|
715
|
+
|
|
716
|
+
cpdef _div_(self, right):
|
|
717
|
+
"""
|
|
718
|
+
Division.
|
|
719
|
+
|
|
720
|
+
EXAMPLES::
|
|
721
|
+
|
|
722
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
723
|
+
sage: (a - 1) / (a + 1) # indirect doctest
|
|
724
|
+
2*a^16 + a^15 + 2*a^14 + a^13 + 2*a^12 + a^11 + 2*a^10 + a^9 + 2*a^8 + a^7 + 2*a^6 + a^5 + 2*a^4 + a^3 + 2*a^2 + a + 1
|
|
725
|
+
"""
|
|
726
|
+
if FF_equal0((<FiniteFieldElement_pari_ffelt>right).val):
|
|
727
|
+
raise ZeroDivisionError
|
|
728
|
+
cdef FiniteFieldElement_pari_ffelt x = self._new()
|
|
729
|
+
sig_on()
|
|
730
|
+
x.construct(FF_div((<FiniteFieldElement_pari_ffelt>self).val,
|
|
731
|
+
(<FiniteFieldElement_pari_ffelt>right).val))
|
|
732
|
+
return x
|
|
733
|
+
|
|
734
|
+
def is_zero(self):
|
|
735
|
+
"""
|
|
736
|
+
Return ``True`` if ``self`` equals 0.
|
|
737
|
+
|
|
738
|
+
EXAMPLES::
|
|
739
|
+
|
|
740
|
+
sage: F.<a> = FiniteField(5^3, impl='pari_ffelt')
|
|
741
|
+
sage: a.is_zero()
|
|
742
|
+
False
|
|
743
|
+
sage: (a - a).is_zero()
|
|
744
|
+
True
|
|
745
|
+
"""
|
|
746
|
+
return bool(FF_equal0(self.val))
|
|
747
|
+
|
|
748
|
+
def is_one(self):
|
|
749
|
+
"""
|
|
750
|
+
Return ``True`` if ``self`` equals 1.
|
|
751
|
+
|
|
752
|
+
EXAMPLES::
|
|
753
|
+
|
|
754
|
+
sage: F.<a> = FiniteField(5^3, impl='pari_ffelt')
|
|
755
|
+
sage: a.is_one()
|
|
756
|
+
False
|
|
757
|
+
sage: (a/a).is_one()
|
|
758
|
+
True
|
|
759
|
+
"""
|
|
760
|
+
return bool(FF_equal1(self.val))
|
|
761
|
+
|
|
762
|
+
def is_unit(self):
|
|
763
|
+
"""
|
|
764
|
+
Return ``True`` if ``self`` is nonzero.
|
|
765
|
+
|
|
766
|
+
EXAMPLES::
|
|
767
|
+
|
|
768
|
+
sage: F.<a> = FiniteField(5^3, impl='pari_ffelt')
|
|
769
|
+
sage: a.is_unit()
|
|
770
|
+
True
|
|
771
|
+
"""
|
|
772
|
+
return not bool(FF_equal0(self.val))
|
|
773
|
+
|
|
774
|
+
__bool__ = is_unit
|
|
775
|
+
|
|
776
|
+
def __pos__(self):
|
|
777
|
+
"""
|
|
778
|
+
Unitary positive operator...
|
|
779
|
+
|
|
780
|
+
EXAMPLES::
|
|
781
|
+
|
|
782
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
783
|
+
sage: +a
|
|
784
|
+
a
|
|
785
|
+
"""
|
|
786
|
+
return self
|
|
787
|
+
|
|
788
|
+
def __neg__(self):
|
|
789
|
+
"""
|
|
790
|
+
Negation.
|
|
791
|
+
|
|
792
|
+
EXAMPLES::
|
|
793
|
+
|
|
794
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
795
|
+
sage: -a
|
|
796
|
+
2*a
|
|
797
|
+
"""
|
|
798
|
+
cdef FiniteFieldElement_pari_ffelt x = self._new()
|
|
799
|
+
sig_on()
|
|
800
|
+
x.construct(FF_neg_i((<FiniteFieldElement_pari_ffelt>self).val))
|
|
801
|
+
return x
|
|
802
|
+
|
|
803
|
+
def __invert__(self):
|
|
804
|
+
"""
|
|
805
|
+
Return the multiplicative inverse of ``self``.
|
|
806
|
+
|
|
807
|
+
EXAMPLES::
|
|
808
|
+
|
|
809
|
+
sage: k.<a> = FiniteField(3^2, impl='pari_ffelt')
|
|
810
|
+
sage: ~a
|
|
811
|
+
a + 2
|
|
812
|
+
sage: (a+1)*a
|
|
813
|
+
2*a + 1
|
|
814
|
+
sage: ~((2*a)/a)
|
|
815
|
+
2
|
|
816
|
+
"""
|
|
817
|
+
if FF_equal0(self.val):
|
|
818
|
+
raise ZeroDivisionError
|
|
819
|
+
cdef FiniteFieldElement_pari_ffelt x = self._new()
|
|
820
|
+
sig_on()
|
|
821
|
+
x.construct(FF_inv((<FiniteFieldElement_pari_ffelt>self).val))
|
|
822
|
+
return x
|
|
823
|
+
|
|
824
|
+
def __pow__(FiniteFieldElement_pari_ffelt self, exp, other):
|
|
825
|
+
"""
|
|
826
|
+
Exponentiation.
|
|
827
|
+
|
|
828
|
+
TESTS::
|
|
829
|
+
|
|
830
|
+
sage: K.<a> = GF(5^10, impl='pari_ffelt')
|
|
831
|
+
sage: n = (2*a)/a
|
|
832
|
+
sage: n^-15
|
|
833
|
+
2
|
|
834
|
+
|
|
835
|
+
Large exponents are not a problem::
|
|
836
|
+
|
|
837
|
+
sage: e = 3^10000
|
|
838
|
+
sage: a^e
|
|
839
|
+
2*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a
|
|
840
|
+
sage: a^(e % (5^10 - 1))
|
|
841
|
+
2*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a
|
|
842
|
+
|
|
843
|
+
The exponent is converted to an integer (see :issue:`16540`)::
|
|
844
|
+
|
|
845
|
+
sage: q = 11^23
|
|
846
|
+
sage: F.<a> = FiniteField(q)
|
|
847
|
+
sage: a^Mod(1, q - 1)
|
|
848
|
+
a
|
|
849
|
+
|
|
850
|
+
.. WARNING::
|
|
851
|
+
|
|
852
|
+
For efficiency reasons, we do not verify that the
|
|
853
|
+
exponentiation is well defined before converting the
|
|
854
|
+
exponent to an integer. This means that ``a^Mod(1, n)``
|
|
855
|
+
returns `a` even if `n` is not a multiple of the
|
|
856
|
+
multiplicative order of `a`.
|
|
857
|
+
"""
|
|
858
|
+
if exp == 0:
|
|
859
|
+
return self._parent.one()
|
|
860
|
+
if exp < 0 and FF_equal0(self.val):
|
|
861
|
+
raise ZeroDivisionError
|
|
862
|
+
exp = Integer(exp).__pari__()
|
|
863
|
+
cdef FiniteFieldElement_pari_ffelt x = self._new()
|
|
864
|
+
sig_on()
|
|
865
|
+
x.construct(FF_pow(self.val, (<pari_gen>exp).g))
|
|
866
|
+
return x
|
|
867
|
+
|
|
868
|
+
def pth_power(FiniteFieldElement_pari_ffelt self, int k=1):
|
|
869
|
+
r"""
|
|
870
|
+
Return the `(p^k)`-th power of ``self``, where `p` is the
|
|
871
|
+
characteristic of the field.
|
|
872
|
+
|
|
873
|
+
INPUT:
|
|
874
|
+
|
|
875
|
+
- ``k`` -- integer (default: 1); must fit in a C ``int``
|
|
876
|
+
|
|
877
|
+
Note that if `k` is negative, then this computes the appropriate root.
|
|
878
|
+
|
|
879
|
+
TESTS::
|
|
880
|
+
|
|
881
|
+
sage: # needs sage.modules
|
|
882
|
+
sage: F.<a> = GF(13^64, impl='pari_ffelt'); F
|
|
883
|
+
Finite Field in a of size 13^64
|
|
884
|
+
sage: x = F.random_element()
|
|
885
|
+
sage: x.pth_power(0) == x
|
|
886
|
+
True
|
|
887
|
+
sage: x.pth_power(1) == x**13
|
|
888
|
+
True
|
|
889
|
+
sage: x.pth_power(2) == x**(13**2)
|
|
890
|
+
True
|
|
891
|
+
sage: x.pth_power(-1)**13 == x
|
|
892
|
+
True
|
|
893
|
+
|
|
894
|
+
sage: # needs sage.modules
|
|
895
|
+
sage: F.<a> = GF(127^16, impl='pari_ffelt'); F
|
|
896
|
+
Finite Field in a of size 127^16
|
|
897
|
+
sage: x = F.random_element()
|
|
898
|
+
sage: x.pth_power(0) == x
|
|
899
|
+
True
|
|
900
|
+
sage: x.pth_power(1) == x**127
|
|
901
|
+
True
|
|
902
|
+
sage: x.pth_power(2) == x**(127**2)
|
|
903
|
+
True
|
|
904
|
+
sage: x.pth_power(-1)**127 == x
|
|
905
|
+
True
|
|
906
|
+
"""
|
|
907
|
+
cdef int n = int(self._parent.degree())
|
|
908
|
+
if k % n == 0:
|
|
909
|
+
return self
|
|
910
|
+
cdef Integer p = self._parent.characteristic()
|
|
911
|
+
if k == 1 and (p < 100 or p.bit_length()**2 < n):
|
|
912
|
+
# For extremely small primes or very large extension degrees,
|
|
913
|
+
# exponentiation is faster.
|
|
914
|
+
return self**p
|
|
915
|
+
# Otherwise use PARI field morphism (evaluation of a Fp polynomial
|
|
916
|
+
# at the image of the generator).
|
|
917
|
+
f = self._parent._pari_frobenius(k)
|
|
918
|
+
cdef FiniteFieldElement_pari_ffelt x = self._new()
|
|
919
|
+
sig_on()
|
|
920
|
+
x.construct(ffmap((<pari_gen>f).g, self.val))
|
|
921
|
+
return x
|
|
922
|
+
|
|
923
|
+
frobenius = pth_power
|
|
924
|
+
|
|
925
|
+
def polynomial(self, name=None):
|
|
926
|
+
"""
|
|
927
|
+
Return the unique representative of ``self`` as a polynomial
|
|
928
|
+
over the prime field whose degree is less than the degree of
|
|
929
|
+
the finite field over its prime field.
|
|
930
|
+
|
|
931
|
+
INPUT:
|
|
932
|
+
|
|
933
|
+
- ``name`` -- (optional) variable name
|
|
934
|
+
|
|
935
|
+
EXAMPLES::
|
|
936
|
+
|
|
937
|
+
sage: k.<a> = FiniteField(3^2, impl='pari_ffelt')
|
|
938
|
+
sage: pol = a.polynomial()
|
|
939
|
+
sage: pol
|
|
940
|
+
a
|
|
941
|
+
sage: parent(pol)
|
|
942
|
+
Univariate Polynomial Ring in a over Finite Field of size 3
|
|
943
|
+
|
|
944
|
+
::
|
|
945
|
+
|
|
946
|
+
sage: k = FiniteField(3^4, 'alpha', impl='pari_ffelt')
|
|
947
|
+
sage: a = k.gen()
|
|
948
|
+
sage: a.polynomial()
|
|
949
|
+
alpha
|
|
950
|
+
sage: (a**2 + 1).polynomial('beta')
|
|
951
|
+
beta^2 + 1
|
|
952
|
+
sage: (a**2 + 1).polynomial().parent()
|
|
953
|
+
Univariate Polynomial Ring in alpha over Finite Field of size 3
|
|
954
|
+
sage: (a**2 + 1).polynomial('beta').parent()
|
|
955
|
+
Univariate Polynomial Ring in beta over Finite Field of size 3
|
|
956
|
+
"""
|
|
957
|
+
sig_on()
|
|
958
|
+
pol = new_gen(FF_to_FpXQ(self.val))
|
|
959
|
+
return self._parent.polynomial_ring(name)(pol)
|
|
960
|
+
|
|
961
|
+
def minpoly(self, var='x'):
|
|
962
|
+
"""
|
|
963
|
+
Return the minimal polynomial of ``self``.
|
|
964
|
+
|
|
965
|
+
INPUT:
|
|
966
|
+
|
|
967
|
+
- ``var`` -- string (default: ``'x'``); variable name to use
|
|
968
|
+
|
|
969
|
+
EXAMPLES::
|
|
970
|
+
|
|
971
|
+
sage: R.<x> = PolynomialRing(FiniteField(3))
|
|
972
|
+
sage: F.<a> = FiniteField(3^2, modulus=x^2 + 1, impl='pari_ffelt')
|
|
973
|
+
sage: a.minpoly('y')
|
|
974
|
+
y^2 + 1
|
|
975
|
+
"""
|
|
976
|
+
sig_on()
|
|
977
|
+
pol = new_gen(FF_minpoly(self.val))
|
|
978
|
+
return self._parent.polynomial_ring(var)(pol)
|
|
979
|
+
|
|
980
|
+
def charpoly(self, var='x'):
|
|
981
|
+
"""
|
|
982
|
+
Return the characteristic polynomial of ``self``.
|
|
983
|
+
|
|
984
|
+
INPUT:
|
|
985
|
+
|
|
986
|
+
- ``var`` -- string (default: ``'x'``); variable name to use
|
|
987
|
+
|
|
988
|
+
EXAMPLES::
|
|
989
|
+
|
|
990
|
+
sage: R.<x> = PolynomialRing(FiniteField(3))
|
|
991
|
+
sage: F.<a> = FiniteField(3^2, modulus=x^2 + 1, impl='pari_ffelt')
|
|
992
|
+
sage: a.charpoly('y')
|
|
993
|
+
y^2 + 1
|
|
994
|
+
"""
|
|
995
|
+
sig_on()
|
|
996
|
+
pol = new_gen(FF_charpoly(self.val))
|
|
997
|
+
return self._parent.polynomial_ring(var)(pol)
|
|
998
|
+
|
|
999
|
+
def is_square(self):
|
|
1000
|
+
"""
|
|
1001
|
+
Return ``True`` if and only if ``self`` is a square in the
|
|
1002
|
+
finite field.
|
|
1003
|
+
|
|
1004
|
+
EXAMPLES::
|
|
1005
|
+
|
|
1006
|
+
sage: k.<a> = FiniteField(3^2, impl='pari_ffelt')
|
|
1007
|
+
sage: a.is_square()
|
|
1008
|
+
False
|
|
1009
|
+
sage: (a**2).is_square()
|
|
1010
|
+
True
|
|
1011
|
+
|
|
1012
|
+
sage: k.<a> = FiniteField(2^2, impl='pari_ffelt')
|
|
1013
|
+
sage: (a**2).is_square()
|
|
1014
|
+
True
|
|
1015
|
+
|
|
1016
|
+
sage: k.<a> = FiniteField(17^5, impl='pari_ffelt')
|
|
1017
|
+
sage: (a**2).is_square()
|
|
1018
|
+
True
|
|
1019
|
+
sage: a.is_square()
|
|
1020
|
+
False
|
|
1021
|
+
sage: k(0).is_square()
|
|
1022
|
+
True
|
|
1023
|
+
"""
|
|
1024
|
+
cdef long i
|
|
1025
|
+
sig_on()
|
|
1026
|
+
i = FF_issquare(self.val)
|
|
1027
|
+
sig_off()
|
|
1028
|
+
return bool(i)
|
|
1029
|
+
|
|
1030
|
+
def sqrt(self, extend=False, all=False):
|
|
1031
|
+
"""
|
|
1032
|
+
Return a square root of ``self``, if it exists.
|
|
1033
|
+
|
|
1034
|
+
INPUT:
|
|
1035
|
+
|
|
1036
|
+
- ``extend`` -- boolean (default: ``False``)
|
|
1037
|
+
|
|
1038
|
+
.. WARNING::
|
|
1039
|
+
|
|
1040
|
+
This option is not implemented.
|
|
1041
|
+
|
|
1042
|
+
- ``all`` -- boolean (default: ``False``)
|
|
1043
|
+
|
|
1044
|
+
OUTPUT:
|
|
1045
|
+
|
|
1046
|
+
A square root of ``self``, if it exists. If ``all`` is
|
|
1047
|
+
``True``, a list containing all square roots of ``self``
|
|
1048
|
+
(of length zero, one or two) is returned instead.
|
|
1049
|
+
|
|
1050
|
+
If ``extend`` is ``True``, a square root is chosen in an
|
|
1051
|
+
extension field if necessary. If ``extend`` is ``False``, a
|
|
1052
|
+
:exc:`ValueError` is raised if the element is not a square in the
|
|
1053
|
+
base field.
|
|
1054
|
+
|
|
1055
|
+
.. WARNING::
|
|
1056
|
+
|
|
1057
|
+
The ``extend`` option is not implemented (yet).
|
|
1058
|
+
|
|
1059
|
+
EXAMPLES::
|
|
1060
|
+
|
|
1061
|
+
sage: F = FiniteField(7^2, 'a', impl='pari_ffelt')
|
|
1062
|
+
sage: F(2).sqrt()
|
|
1063
|
+
4
|
|
1064
|
+
sage: F(3).sqrt() in (2*F.gen() + 6, 5*F.gen() + 1)
|
|
1065
|
+
True
|
|
1066
|
+
sage: F(3).sqrt()**2
|
|
1067
|
+
3
|
|
1068
|
+
sage: F(4).sqrt(all=True)
|
|
1069
|
+
[2, 5]
|
|
1070
|
+
|
|
1071
|
+
sage: K = FiniteField(7^3, 'alpha', impl='pari_ffelt')
|
|
1072
|
+
sage: K(3).sqrt()
|
|
1073
|
+
Traceback (most recent call last):
|
|
1074
|
+
...
|
|
1075
|
+
ValueError: element is not a square
|
|
1076
|
+
sage: K(3).sqrt(all=True)
|
|
1077
|
+
[]
|
|
1078
|
+
|
|
1079
|
+
sage: K.<a> = GF(3^17, impl='pari_ffelt')
|
|
1080
|
+
sage: (a^3 - a - 1).sqrt()
|
|
1081
|
+
a^16 + 2*a^15 + a^13 + 2*a^12 + a^10 + 2*a^9 + 2*a^8 + a^7 + a^6 + 2*a^5 + a^4 + 2*a^2 + 2*a + 2
|
|
1082
|
+
"""
|
|
1083
|
+
if extend:
|
|
1084
|
+
raise NotImplementedError
|
|
1085
|
+
cdef GEN s
|
|
1086
|
+
cdef FiniteFieldElement_pari_ffelt x, mx
|
|
1087
|
+
sig_on()
|
|
1088
|
+
if FF_issquareall(self.val, &s):
|
|
1089
|
+
x = self._new()
|
|
1090
|
+
x.construct(s)
|
|
1091
|
+
if not all:
|
|
1092
|
+
return x
|
|
1093
|
+
elif gequal0(x.val) or self._parent.characteristic() == 2:
|
|
1094
|
+
return [x]
|
|
1095
|
+
else:
|
|
1096
|
+
sig_on()
|
|
1097
|
+
mx = self._new()
|
|
1098
|
+
mx.construct(FF_neg_i(x.val))
|
|
1099
|
+
return [x, mx]
|
|
1100
|
+
else:
|
|
1101
|
+
sig_off()
|
|
1102
|
+
if all:
|
|
1103
|
+
return []
|
|
1104
|
+
else:
|
|
1105
|
+
raise ValueError("element is not a square")
|
|
1106
|
+
|
|
1107
|
+
def log(self, base, order=None, *, check=False):
|
|
1108
|
+
"""
|
|
1109
|
+
Return a discrete logarithm of ``self`` with respect to the
|
|
1110
|
+
given base.
|
|
1111
|
+
|
|
1112
|
+
INPUT:
|
|
1113
|
+
|
|
1114
|
+
- ``base`` -- nonzero field element
|
|
1115
|
+
- ``order`` -- integer (optional), the order of the base
|
|
1116
|
+
- ``check`` -- boolean (default: ``False``); if set,
|
|
1117
|
+
test whether the given ``order`` is correct
|
|
1118
|
+
|
|
1119
|
+
OUTPUT:
|
|
1120
|
+
|
|
1121
|
+
An integer `x` such that ``self`` equals ``base`` raised to
|
|
1122
|
+
the power `x`. If no such `x` exists, a :exc:`ValueError` is
|
|
1123
|
+
raised.
|
|
1124
|
+
|
|
1125
|
+
EXAMPLES::
|
|
1126
|
+
|
|
1127
|
+
sage: F.<g> = FiniteField(2^10, impl='pari_ffelt')
|
|
1128
|
+
sage: b = g; a = g^37
|
|
1129
|
+
sage: a.log(b)
|
|
1130
|
+
37
|
|
1131
|
+
sage: b^37; a
|
|
1132
|
+
g^8 + g^7 + g^4 + g + 1
|
|
1133
|
+
g^8 + g^7 + g^4 + g + 1
|
|
1134
|
+
|
|
1135
|
+
::
|
|
1136
|
+
|
|
1137
|
+
sage: F.<a> = FiniteField(5^2, impl='pari_ffelt')
|
|
1138
|
+
sage: F(-1).log(F(2))
|
|
1139
|
+
2
|
|
1140
|
+
sage: F(1).log(a)
|
|
1141
|
+
0
|
|
1142
|
+
|
|
1143
|
+
::
|
|
1144
|
+
|
|
1145
|
+
sage: # needs sage.modules
|
|
1146
|
+
sage: p = 2^127 - 1
|
|
1147
|
+
sage: F.<t> = GF((p, 3))
|
|
1148
|
+
sage: elt = F.random_element()^(p^2+p+1)
|
|
1149
|
+
sage: (elt^2).log(elt, p-1)
|
|
1150
|
+
2
|
|
1151
|
+
|
|
1152
|
+
Passing the ``order`` argument can lead to huge speedups when
|
|
1153
|
+
factoring the order of the entire unit group is expensive but
|
|
1154
|
+
the order of the base element is much smaller::
|
|
1155
|
+
|
|
1156
|
+
sage: %timeit (elt^2).log(elt) # not tested
|
|
1157
|
+
6.18 s ± 85 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
|
|
1158
|
+
sage: %timeit (elt^2).log(elt, p-1) # not tested
|
|
1159
|
+
147 ms ± 1.39 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
|
|
1160
|
+
|
|
1161
|
+
Some cases where the logarithm is not defined or does not exist::
|
|
1162
|
+
|
|
1163
|
+
sage: F.<a> = GF(3^10, impl='pari_ffelt')
|
|
1164
|
+
sage: a.log(-1)
|
|
1165
|
+
Traceback (most recent call last):
|
|
1166
|
+
...
|
|
1167
|
+
ArithmeticError: element a does not lie in group generated by 2
|
|
1168
|
+
sage: a.log(0)
|
|
1169
|
+
Traceback (most recent call last):
|
|
1170
|
+
...
|
|
1171
|
+
ArithmeticError: discrete logarithm with base 0 is not defined
|
|
1172
|
+
sage: F(0).log(1)
|
|
1173
|
+
Traceback (most recent call last):
|
|
1174
|
+
...
|
|
1175
|
+
ArithmeticError: discrete logarithm of 0 is not defined
|
|
1176
|
+
|
|
1177
|
+
TESTS:
|
|
1178
|
+
|
|
1179
|
+
An example for ``check=True``::
|
|
1180
|
+
|
|
1181
|
+
sage: a = GF(101^5).primitive_element()
|
|
1182
|
+
sage: a.log(a, 10510100500, check=True)
|
|
1183
|
+
1
|
|
1184
|
+
sage: a.log(a, 5255050250, check=True)
|
|
1185
|
+
Traceback (most recent call last):
|
|
1186
|
+
...
|
|
1187
|
+
ValueError: element does not have the provided order
|
|
1188
|
+
"""
|
|
1189
|
+
base = self._parent(base)
|
|
1190
|
+
if self.is_zero():
|
|
1191
|
+
raise ArithmeticError("discrete logarithm of 0 is not defined")
|
|
1192
|
+
if base.is_zero():
|
|
1193
|
+
raise ArithmeticError("discrete logarithm with base 0 is not defined")
|
|
1194
|
+
|
|
1195
|
+
# Compute the order of the base to check whether the element actually
|
|
1196
|
+
# lies in the group generated by the base. PARI may otherwise enter an
|
|
1197
|
+
# infinite loop.
|
|
1198
|
+
# We also have to specify the order of the base anyway as PARI assumes
|
|
1199
|
+
# by default that the base generates the entire multiplicative group.
|
|
1200
|
+
cdef GEN x, base_order
|
|
1201
|
+
sig_on()
|
|
1202
|
+
if order is None:
|
|
1203
|
+
base_order = FF_order((<FiniteFieldElement_pari_ffelt>base).val, NULL)
|
|
1204
|
+
else:
|
|
1205
|
+
if check:
|
|
1206
|
+
from sage.groups.generic import has_order
|
|
1207
|
+
if not has_order(base, order, '*'):
|
|
1208
|
+
clear_stack()
|
|
1209
|
+
raise ValueError('element does not have the provided order')
|
|
1210
|
+
base_order = _new_GEN_from_mpz_t((<Integer>order).value)
|
|
1211
|
+
if not gequal1(powgi(self.val, base_order)):
|
|
1212
|
+
clear_stack()
|
|
1213
|
+
raise ArithmeticError(f'element {self} does not lie in group generated by {base}')
|
|
1214
|
+
x = FF_log(self.val, (<FiniteFieldElement_pari_ffelt>base).val, base_order)
|
|
1215
|
+
return Integer(new_gen(x))
|
|
1216
|
+
|
|
1217
|
+
def multiplicative_order(self):
|
|
1218
|
+
"""
|
|
1219
|
+
Return the order of ``self`` in the multiplicative group.
|
|
1220
|
+
|
|
1221
|
+
EXAMPLES::
|
|
1222
|
+
|
|
1223
|
+
sage: a = FiniteField(5^3, 'a', impl='pari_ffelt').0
|
|
1224
|
+
sage: a.multiplicative_order()
|
|
1225
|
+
124
|
|
1226
|
+
sage: a**124
|
|
1227
|
+
1
|
|
1228
|
+
"""
|
|
1229
|
+
if self.is_zero():
|
|
1230
|
+
raise ArithmeticError("Multiplicative order of 0 not defined.")
|
|
1231
|
+
cdef GEN order
|
|
1232
|
+
sig_on()
|
|
1233
|
+
order = FF_order(self.val, NULL)
|
|
1234
|
+
return Integer(new_gen(order))
|
|
1235
|
+
|
|
1236
|
+
def lift(self):
|
|
1237
|
+
"""
|
|
1238
|
+
If ``self`` is an element of the prime field, return a lift of
|
|
1239
|
+
this element to an integer.
|
|
1240
|
+
|
|
1241
|
+
EXAMPLES::
|
|
1242
|
+
|
|
1243
|
+
sage: k = FiniteField(next_prime(10^10)^2, 'u', impl='pari_ffelt')
|
|
1244
|
+
sage: a = k(17)/k(19)
|
|
1245
|
+
sage: b = a.lift(); b
|
|
1246
|
+
7894736858
|
|
1247
|
+
sage: b.parent()
|
|
1248
|
+
Integer Ring
|
|
1249
|
+
"""
|
|
1250
|
+
if FF_equal0(self.val):
|
|
1251
|
+
return Integer(0)
|
|
1252
|
+
f = self.polynomial()
|
|
1253
|
+
if f.degree() == 0:
|
|
1254
|
+
return f.constant_coefficient().lift()
|
|
1255
|
+
else:
|
|
1256
|
+
raise ValueError("element is not in the prime field")
|
|
1257
|
+
|
|
1258
|
+
def _integer_(self, ZZ=None):
|
|
1259
|
+
"""
|
|
1260
|
+
Lift to a Sage integer, if possible.
|
|
1261
|
+
|
|
1262
|
+
EXAMPLES::
|
|
1263
|
+
|
|
1264
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
1265
|
+
sage: b = k(2)
|
|
1266
|
+
sage: b._integer_()
|
|
1267
|
+
2
|
|
1268
|
+
sage: a._integer_()
|
|
1269
|
+
Traceback (most recent call last):
|
|
1270
|
+
...
|
|
1271
|
+
ValueError: element is not in the prime field
|
|
1272
|
+
"""
|
|
1273
|
+
return self.lift()
|
|
1274
|
+
|
|
1275
|
+
def __int__(self):
|
|
1276
|
+
"""
|
|
1277
|
+
Lift to a python int, if possible.
|
|
1278
|
+
|
|
1279
|
+
EXAMPLES::
|
|
1280
|
+
|
|
1281
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
1282
|
+
sage: b = k(2)
|
|
1283
|
+
sage: int(b)
|
|
1284
|
+
2
|
|
1285
|
+
sage: int(a)
|
|
1286
|
+
Traceback (most recent call last):
|
|
1287
|
+
...
|
|
1288
|
+
ValueError: element is not in the prime field
|
|
1289
|
+
"""
|
|
1290
|
+
return int(self.lift())
|
|
1291
|
+
|
|
1292
|
+
def __float__(self):
|
|
1293
|
+
"""
|
|
1294
|
+
Lift to a python float, if possible.
|
|
1295
|
+
|
|
1296
|
+
EXAMPLES::
|
|
1297
|
+
|
|
1298
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
1299
|
+
sage: b = k(2)
|
|
1300
|
+
sage: float(b)
|
|
1301
|
+
2.0
|
|
1302
|
+
"""
|
|
1303
|
+
return float(self.lift())
|
|
1304
|
+
|
|
1305
|
+
def __pari__(self, var=None):
|
|
1306
|
+
"""
|
|
1307
|
+
Return a PARI object representing ``self``.
|
|
1308
|
+
|
|
1309
|
+
EXAMPLES::
|
|
1310
|
+
|
|
1311
|
+
sage: k.<a> = FiniteField(3^3, impl='pari_ffelt')
|
|
1312
|
+
sage: b = a**2 + 2*a + 1
|
|
1313
|
+
sage: b.__pari__()
|
|
1314
|
+
a^2 + 2*a + 1
|
|
1315
|
+
"""
|
|
1316
|
+
return new_gen_noclear(self.val)
|
|
1317
|
+
|
|
1318
|
+
def _pari_init_(self):
|
|
1319
|
+
"""
|
|
1320
|
+
Return a string representing ``self`` in PARI.
|
|
1321
|
+
|
|
1322
|
+
EXAMPLES::
|
|
1323
|
+
|
|
1324
|
+
sage: k.<a> = GF(3^17, impl='pari_ffelt')
|
|
1325
|
+
sage: a._pari_init_()
|
|
1326
|
+
'subst(a+3*a,a,ffgen(Mod(1, 3)*x^17 + Mod(2, 3)*x + Mod(1, 3),a))'
|
|
1327
|
+
sage: k(1)._pari_init_()
|
|
1328
|
+
'subst(1+3*a,a,ffgen(Mod(1, 3)*x^17 + Mod(2, 3)*x + Mod(1, 3),a))'
|
|
1329
|
+
|
|
1330
|
+
This is used for conversion to GP. The element is displayed
|
|
1331
|
+
as "a" but has correct arithmetic::
|
|
1332
|
+
|
|
1333
|
+
sage: gp(a)
|
|
1334
|
+
a
|
|
1335
|
+
sage: gp(a).type()
|
|
1336
|
+
t_FFELT
|
|
1337
|
+
sage: gp(a)^100
|
|
1338
|
+
2*a^16 + 2*a^15 + a^4 + a + 1
|
|
1339
|
+
sage: gp(a^100)
|
|
1340
|
+
2*a^16 + 2*a^15 + a^4 + a + 1
|
|
1341
|
+
sage: gp(k(0))
|
|
1342
|
+
0
|
|
1343
|
+
sage: gp(k(0)).type()
|
|
1344
|
+
t_FFELT
|
|
1345
|
+
"""
|
|
1346
|
+
ffgen = "ffgen(%s,a)" % self._parent.modulus()._pari_init_()
|
|
1347
|
+
# Add this "zero" to ensure that the polynomial is not constant
|
|
1348
|
+
zero = "%s*a" % self._parent.characteristic()
|
|
1349
|
+
return "subst(%s+%s,a,%s)" % (self, zero, ffgen)
|
|
1350
|
+
|
|
1351
|
+
def _magma_init_(self, magma):
|
|
1352
|
+
"""
|
|
1353
|
+
Return a string representing ``self`` in Magma.
|
|
1354
|
+
|
|
1355
|
+
EXAMPLES::
|
|
1356
|
+
|
|
1357
|
+
sage: GF(7)(3)._magma_init_(magma) # optional - magma
|
|
1358
|
+
'GF(7)!3'
|
|
1359
|
+
"""
|
|
1360
|
+
k = self._parent
|
|
1361
|
+
km = magma(k)
|
|
1362
|
+
return str(self).replace(k.variable_name(), km.gen(1).name())
|
|
1363
|
+
|
|
1364
|
+
def _gap_init_(self):
|
|
1365
|
+
r"""
|
|
1366
|
+
Return the string representing ``self`` in GAP.
|
|
1367
|
+
|
|
1368
|
+
.. NOTE::
|
|
1369
|
+
|
|
1370
|
+
The order of the parent field must be `\leq 65536`. This
|
|
1371
|
+
function can be slow since elements of non-prime finite
|
|
1372
|
+
fields are represented in GAP as powers of a generator for
|
|
1373
|
+
the multiplicative group, so a discrete logarithm must be
|
|
1374
|
+
computed.
|
|
1375
|
+
|
|
1376
|
+
EXAMPLES::
|
|
1377
|
+
|
|
1378
|
+
sage: # needs sage.libs.gap
|
|
1379
|
+
sage: F = FiniteField(2^3, 'aa', impl='pari_ffelt')
|
|
1380
|
+
sage: aa = F.multiplicative_generator()
|
|
1381
|
+
sage: gap(aa) # indirect doctest
|
|
1382
|
+
Z(2^3)
|
|
1383
|
+
sage: b = F.multiplicative_generator()
|
|
1384
|
+
sage: a = b^3
|
|
1385
|
+
sage: gap(a)
|
|
1386
|
+
Z(2^3)^3
|
|
1387
|
+
sage: gap(a^3)
|
|
1388
|
+
Z(2^3)^2
|
|
1389
|
+
sage: F(gap('Z(8)^3'))
|
|
1390
|
+
aa + 1
|
|
1391
|
+
sage: F(libgap.Z(8)^3)
|
|
1392
|
+
aa + 1
|
|
1393
|
+
|
|
1394
|
+
You can specify the instance of the Gap interpreter that is used::
|
|
1395
|
+
|
|
1396
|
+
sage: # needs sage.libs.gap
|
|
1397
|
+
sage: F = FiniteField(next_prime(200)^2, 'a', impl='pari_ffelt')
|
|
1398
|
+
sage: a = F.multiplicative_generator()
|
|
1399
|
+
sage: a._gap_ (gap)
|
|
1400
|
+
Z(211^2)
|
|
1401
|
+
sage: (a^20)._gap_(gap)
|
|
1402
|
+
Z(211^2)^20
|
|
1403
|
+
|
|
1404
|
+
Gap only supports relatively small finite fields::
|
|
1405
|
+
|
|
1406
|
+
sage: # needs sage.libs.gap
|
|
1407
|
+
sage: F = FiniteField(next_prime(1000)^2, 'a', impl='pari_ffelt')
|
|
1408
|
+
sage: a = F.multiplicative_generator()
|
|
1409
|
+
sage: a._gap_init_()
|
|
1410
|
+
Traceback (most recent call last):
|
|
1411
|
+
...
|
|
1412
|
+
TypeError: order must be at most 65536
|
|
1413
|
+
sage: gap.coerce(a)
|
|
1414
|
+
Traceback (most recent call last):
|
|
1415
|
+
...
|
|
1416
|
+
TypeError: no canonical coercion from Finite Field in a of size 1009^2 to Gap
|
|
1417
|
+
"""
|
|
1418
|
+
F = self._parent
|
|
1419
|
+
if F.order() > 65536:
|
|
1420
|
+
raise TypeError("order must be at most 65536")
|
|
1421
|
+
|
|
1422
|
+
if self == 0:
|
|
1423
|
+
return '0*Z(%s)' % F.order()
|
|
1424
|
+
assert F.degree() > 1
|
|
1425
|
+
g = F.multiplicative_generator()
|
|
1426
|
+
n = self.log(g)
|
|
1427
|
+
return 'Z(%s)^%s' % (F.order(), n)
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
def unpickle_FiniteFieldElement_pari_ffelt(parent, elem):
|
|
1431
|
+
"""
|
|
1432
|
+
EXAMPLES::
|
|
1433
|
+
|
|
1434
|
+
sage: # needs sage.modules
|
|
1435
|
+
sage: k.<a> = GF(2^20, impl='pari_ffelt')
|
|
1436
|
+
sage: e = k.random_element()
|
|
1437
|
+
sage: f = loads(dumps(e)) # indirect doctest
|
|
1438
|
+
sage: e == f
|
|
1439
|
+
True
|
|
1440
|
+
"""
|
|
1441
|
+
return parent(elem)
|