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,1333 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
# distutils: libraries = NTL_LIBRARIES
|
|
3
|
+
# distutils: extra_compile_args = NTL_CFLAGS
|
|
4
|
+
# distutils: include_dirs = NTL_INCDIR
|
|
5
|
+
# distutils: library_dirs = NTL_LIBDIR
|
|
6
|
+
# distutils: extra_link_args = NTL_LIBEXTRA
|
|
7
|
+
# distutils: language = c++
|
|
8
|
+
# sage.doctest: needs sage.libs.ntl sage.rings.finite_rings
|
|
9
|
+
r"""
|
|
10
|
+
Elements of finite fields of characteristic 2
|
|
11
|
+
|
|
12
|
+
This implementation uses NTL's GF2E class to perform the arithmetic
|
|
13
|
+
and is the standard implementation for ``GF(2^n)`` for ``n >= 16``.
|
|
14
|
+
|
|
15
|
+
AUTHORS:
|
|
16
|
+
|
|
17
|
+
- Martin Albrecht <malb@informatik.uni-bremen.de> (2007-10)
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
# ****************************************************************************
|
|
21
|
+
# Copyright (C) 2007 Martin Albrecht <malb@informatik.uni-bremen.de>
|
|
22
|
+
#
|
|
23
|
+
# This program is free software: you can redistribute it and/or modify
|
|
24
|
+
# it under the terms of the GNU General Public License as published by
|
|
25
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
26
|
+
# (at your option) any later version.
|
|
27
|
+
# https://www.gnu.org/licenses/
|
|
28
|
+
# ****************************************************************************
|
|
29
|
+
|
|
30
|
+
from cysignals.memory cimport check_malloc, sig_free
|
|
31
|
+
from cysignals.signals cimport sig_on
|
|
32
|
+
from sage.ext.cplusplus cimport ccrepr, ccreadstr
|
|
33
|
+
|
|
34
|
+
include "sage/libs/ntl/decl.pxi"
|
|
35
|
+
from cypari2.paridecl cimport *
|
|
36
|
+
|
|
37
|
+
from sage.structure.richcmp cimport (richcmp,
|
|
38
|
+
richcmp_not_equal, rich_to_bool)
|
|
39
|
+
|
|
40
|
+
from sage.structure.parent cimport Parent
|
|
41
|
+
from sage.structure.element cimport Vector
|
|
42
|
+
|
|
43
|
+
from sage.rings.finite_rings.finite_field_base cimport FiniteField
|
|
44
|
+
|
|
45
|
+
from sage.libs.pari import pari
|
|
46
|
+
from cypari2.gen cimport Gen
|
|
47
|
+
from cypari2.stack cimport clear_stack
|
|
48
|
+
|
|
49
|
+
from sage.rings.finite_rings.element_pari_ffelt import FiniteFieldElement_pari_ffelt
|
|
50
|
+
from sage.rings.finite_rings.finite_field_ntl_gf2e import FiniteField_ntl_gf2e
|
|
51
|
+
|
|
52
|
+
from sage.interfaces.abc import GapElement
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
cdef object IntegerMod_abstract
|
|
56
|
+
cdef object Integer
|
|
57
|
+
cdef object Rational
|
|
58
|
+
cdef object MPolynomial
|
|
59
|
+
cdef object Polynomial
|
|
60
|
+
cdef object GF
|
|
61
|
+
cdef object GF2, GF2_0, GF2_1
|
|
62
|
+
|
|
63
|
+
cdef int late_import() except -1:
|
|
64
|
+
"""
|
|
65
|
+
Import a bunch of objects to the module name space late,
|
|
66
|
+
i.e. after the module was loaded. This is needed to avoid circular
|
|
67
|
+
imports.
|
|
68
|
+
"""
|
|
69
|
+
global IntegerMod_abstract, \
|
|
70
|
+
Integer, \
|
|
71
|
+
Rational, \
|
|
72
|
+
MPolynomial, \
|
|
73
|
+
Polynomial, \
|
|
74
|
+
GF, \
|
|
75
|
+
GF2, GF2_0, GF2_1
|
|
76
|
+
|
|
77
|
+
if IntegerMod_abstract is not None:
|
|
78
|
+
return 0
|
|
79
|
+
|
|
80
|
+
import sage.rings.finite_rings.integer_mod
|
|
81
|
+
IntegerMod_abstract = sage.rings.finite_rings.integer_mod.IntegerMod_abstract
|
|
82
|
+
|
|
83
|
+
import sage.rings.rational
|
|
84
|
+
Rational = sage.rings.rational.Rational
|
|
85
|
+
|
|
86
|
+
import sage.rings.polynomial.multi_polynomial_element
|
|
87
|
+
MPolynomial = sage.rings.polynomial.multi_polynomial_element.MPolynomial
|
|
88
|
+
|
|
89
|
+
import sage.rings.polynomial.polynomial_element
|
|
90
|
+
Polynomial = sage.rings.polynomial.polynomial_element.Polynomial
|
|
91
|
+
|
|
92
|
+
import sage.rings.finite_rings.finite_field_constructor
|
|
93
|
+
GF = sage.rings.finite_rings.finite_field_constructor.FiniteField
|
|
94
|
+
GF2 = GF(2)
|
|
95
|
+
GF2_0 = GF2(0)
|
|
96
|
+
GF2_1 = GF2(1)
|
|
97
|
+
|
|
98
|
+
cdef extern from "arpa/inet.h":
|
|
99
|
+
unsigned int htonl(unsigned int)
|
|
100
|
+
|
|
101
|
+
cdef little_endian():
|
|
102
|
+
return htonl(1) != 1
|
|
103
|
+
|
|
104
|
+
cdef unsigned int switch_endianess(unsigned int i) noexcept:
|
|
105
|
+
cdef size_t j
|
|
106
|
+
cdef unsigned int ret = 0
|
|
107
|
+
for j in range(sizeof(int)):
|
|
108
|
+
(<unsigned char*>&ret)[j] = (<unsigned char*>&i)[sizeof(int)-j-1]
|
|
109
|
+
return ret
|
|
110
|
+
|
|
111
|
+
cdef class Cache_ntl_gf2e(Cache_base):
|
|
112
|
+
"""
|
|
113
|
+
This class stores information for an NTL finite field in a Cython
|
|
114
|
+
class so that elements can access it quickly.
|
|
115
|
+
|
|
116
|
+
It's modeled on
|
|
117
|
+
:class:`~sage.rings.finite_rings.integer_mod.NativeIntStruct`,
|
|
118
|
+
but includes many functions that were previously included in
|
|
119
|
+
the parent (see :issue:`12062`).
|
|
120
|
+
"""
|
|
121
|
+
def __cinit__(self, parent, Py_ssize_t k, modulus):
|
|
122
|
+
"""
|
|
123
|
+
Construction.
|
|
124
|
+
|
|
125
|
+
TESTS::
|
|
126
|
+
|
|
127
|
+
sage: from sage.rings.finite_rings.element_ntl_gf2e import Cache_ntl_gf2e
|
|
128
|
+
sage: Cache_ntl_gf2e.__new__(Cache_ntl_gf2e, None, 2, [1,1,1])
|
|
129
|
+
<sage.rings.finite_rings.element_ntl_gf2e.Cache_ntl_gf2e object at ...>
|
|
130
|
+
"""
|
|
131
|
+
cdef GF2X_c ntl_m
|
|
132
|
+
cdef GF2_c c
|
|
133
|
+
cdef Py_ssize_t i
|
|
134
|
+
|
|
135
|
+
for i in range(k + 1):
|
|
136
|
+
GF2_conv_long(c, modulus[i])
|
|
137
|
+
GF2X_SetCoeff(ntl_m, i, c)
|
|
138
|
+
self.F = GF2EContext_c(ntl_m)
|
|
139
|
+
self.F.restore()
|
|
140
|
+
self._order = Integer(1) << GF2E_degree()
|
|
141
|
+
self._degree = Integer(GF2E_degree())
|
|
142
|
+
|
|
143
|
+
def __init__(self, parent, Py_ssize_t k, modulus):
|
|
144
|
+
"""
|
|
145
|
+
Initialization.
|
|
146
|
+
|
|
147
|
+
TESTS::
|
|
148
|
+
|
|
149
|
+
sage: k.<a> = GF(2^8, impl='ntl')
|
|
150
|
+
"""
|
|
151
|
+
self._parent = <FiniteField?>parent
|
|
152
|
+
self._zero_element = self._new()
|
|
153
|
+
GF2E_conv_long((<FiniteField_ntl_gf2eElement>self._zero_element).x,0)
|
|
154
|
+
self._one_element = self._new()
|
|
155
|
+
GF2E_conv_long((<FiniteField_ntl_gf2eElement>self._one_element).x,1)
|
|
156
|
+
if k > 1:
|
|
157
|
+
self._gen = self._new()
|
|
158
|
+
ccreadstr(self._gen.x, b"[0 1]")
|
|
159
|
+
elif modulus[0]:
|
|
160
|
+
self._gen = self._one_element
|
|
161
|
+
else:
|
|
162
|
+
self._gen = self._zero_element
|
|
163
|
+
|
|
164
|
+
late_import()
|
|
165
|
+
|
|
166
|
+
def _doctest_for_5340(self):
|
|
167
|
+
r"""
|
|
168
|
+
Every bug fix should have a doctest. But :issue:`5340` only happens
|
|
169
|
+
when a garbage collection happens between restoring the modulus and
|
|
170
|
+
using it, so it can't be reliably doctested using any of the
|
|
171
|
+
existing Cython functions in this module. The sole purpose of
|
|
172
|
+
this method is to doctest the fix for :issue:`5340`.
|
|
173
|
+
|
|
174
|
+
EXAMPLES::
|
|
175
|
+
|
|
176
|
+
sage: k.<a> = GF(2^20)
|
|
177
|
+
sage: k._cache._doctest_for_5340()
|
|
178
|
+
[1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1]
|
|
179
|
+
[1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1]
|
|
180
|
+
"""
|
|
181
|
+
import gc
|
|
182
|
+
|
|
183
|
+
# Do a garbage collection, so that this method is repeatable.
|
|
184
|
+
gc.collect()
|
|
185
|
+
|
|
186
|
+
# Create a new finite field.
|
|
187
|
+
new_fld = GF(1<<30, 'a', modulus='random')
|
|
188
|
+
# Create a garbage cycle.
|
|
189
|
+
cycle = [new_fld]
|
|
190
|
+
cycle.append(cycle)
|
|
191
|
+
# Make the cycle inaccessible.
|
|
192
|
+
new_fld = None
|
|
193
|
+
cycle = None
|
|
194
|
+
|
|
195
|
+
# Set the modulus.
|
|
196
|
+
self.F.restore()
|
|
197
|
+
# Print the current modulus.
|
|
198
|
+
cdef GF2XModulus_c modulus = GF2E_modulus()
|
|
199
|
+
cdef GF2X_c mod_poly = GF2XModulus_GF2X(modulus)
|
|
200
|
+
print(ccrepr(mod_poly))
|
|
201
|
+
|
|
202
|
+
# do another garbage collection
|
|
203
|
+
gc.collect()
|
|
204
|
+
|
|
205
|
+
# and print the modulus again
|
|
206
|
+
modulus = GF2E_modulus()
|
|
207
|
+
mod_poly = GF2XModulus_GF2X(modulus)
|
|
208
|
+
print(ccrepr(mod_poly))
|
|
209
|
+
|
|
210
|
+
cdef FiniteField_ntl_gf2eElement _new(self):
|
|
211
|
+
"""
|
|
212
|
+
Return a new element in ``self``. Use this method to construct
|
|
213
|
+
'empty' elements.
|
|
214
|
+
"""
|
|
215
|
+
cdef FiniteField_ntl_gf2eElement y
|
|
216
|
+
self.F.restore()
|
|
217
|
+
y = FiniteField_ntl_gf2eElement.__new__(FiniteField_ntl_gf2eElement)
|
|
218
|
+
y._parent = self._parent
|
|
219
|
+
y._cache = self
|
|
220
|
+
return y
|
|
221
|
+
|
|
222
|
+
def order(self):
|
|
223
|
+
"""
|
|
224
|
+
Return the cardinality of the field.
|
|
225
|
+
|
|
226
|
+
EXAMPLES::
|
|
227
|
+
|
|
228
|
+
sage: k.<a> = GF(2^64)
|
|
229
|
+
sage: k._cache.order()
|
|
230
|
+
18446744073709551616
|
|
231
|
+
"""
|
|
232
|
+
return self._order
|
|
233
|
+
|
|
234
|
+
def degree(self):
|
|
235
|
+
r"""
|
|
236
|
+
If the field has cardinality `2^n` this method returns `n`.
|
|
237
|
+
|
|
238
|
+
EXAMPLES::
|
|
239
|
+
|
|
240
|
+
sage: k.<a> = GF(2^64)
|
|
241
|
+
sage: k._cache.degree()
|
|
242
|
+
64
|
|
243
|
+
"""
|
|
244
|
+
return self._degree
|
|
245
|
+
|
|
246
|
+
def import_data(self, e):
|
|
247
|
+
"""
|
|
248
|
+
EXAMPLES::
|
|
249
|
+
|
|
250
|
+
sage: k.<a> = GF(2^17)
|
|
251
|
+
sage: V = k.vector_space(map=False)
|
|
252
|
+
sage: v = [1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0]
|
|
253
|
+
sage: k._cache.import_data(v)
|
|
254
|
+
a^13 + a^8 + a^5 + 1
|
|
255
|
+
sage: k._cache.import_data(V(v))
|
|
256
|
+
a^13 + a^8 + a^5 + 1
|
|
257
|
+
|
|
258
|
+
TESTS:
|
|
259
|
+
|
|
260
|
+
We check that :issue:`12584` is fixed::
|
|
261
|
+
|
|
262
|
+
sage: k(2^63)
|
|
263
|
+
0
|
|
264
|
+
|
|
265
|
+
We can coerce from PARI finite field implementations::
|
|
266
|
+
|
|
267
|
+
sage: K.<a> = GF(2^19, impl='ntl')
|
|
268
|
+
sage: a^20
|
|
269
|
+
a^6 + a^3 + a^2 + a
|
|
270
|
+
sage: M.<c> = GF(2^19, impl='pari_ffelt')
|
|
271
|
+
sage: K(c^20)
|
|
272
|
+
a^6 + a^3 + a^2 + a
|
|
273
|
+
"""
|
|
274
|
+
if isinstance(e, FiniteField_ntl_gf2eElement) and e.parent() is self._parent: return e
|
|
275
|
+
cdef FiniteField_ntl_gf2eElement res = self._new()
|
|
276
|
+
cdef FiniteField_ntl_gf2eElement x
|
|
277
|
+
cdef FiniteField_ntl_gf2eElement g
|
|
278
|
+
cdef Py_ssize_t i
|
|
279
|
+
|
|
280
|
+
if isinstance(e, IntegerMod_abstract):
|
|
281
|
+
e = e.lift()
|
|
282
|
+
if isinstance(e, (int, Integer)):
|
|
283
|
+
GF2E_conv_long(res.x,int(e&1))
|
|
284
|
+
return res
|
|
285
|
+
|
|
286
|
+
elif isinstance(e, float):
|
|
287
|
+
GF2E_conv_long(res.x,int(e))
|
|
288
|
+
return res
|
|
289
|
+
|
|
290
|
+
elif isinstance(e, str):
|
|
291
|
+
return self._parent(eval(e.replace("^","**"),self._parent.gens_dict()))
|
|
292
|
+
|
|
293
|
+
elif isinstance(e, Vector):
|
|
294
|
+
if self._parent.vector_space(map=False) != e.parent():
|
|
295
|
+
raise TypeError("e.parent must match self.vector_space")
|
|
296
|
+
ztmp = Integer(e.list(),2)
|
|
297
|
+
# Can't do the following since we can't cimport Integer because of circular imports.
|
|
298
|
+
#for i from 0 <= i < len(e):
|
|
299
|
+
# if e[i]:
|
|
300
|
+
# mpz_setbit(ztmp.value, i)
|
|
301
|
+
return self.fetch_int(ztmp)
|
|
302
|
+
|
|
303
|
+
elif isinstance(e, (list, tuple)):
|
|
304
|
+
if len(e) > self._degree:
|
|
305
|
+
# could reduce here...
|
|
306
|
+
raise ValueError("list is too long")
|
|
307
|
+
ztmp = Integer(e,2)
|
|
308
|
+
return self.fetch_int(ztmp)
|
|
309
|
+
|
|
310
|
+
elif isinstance(e, MPolynomial):
|
|
311
|
+
if e.is_constant():
|
|
312
|
+
return self._parent(e.constant_coefficient())
|
|
313
|
+
else:
|
|
314
|
+
raise TypeError("no coercion defined")
|
|
315
|
+
|
|
316
|
+
elif isinstance(e, Polynomial):
|
|
317
|
+
if e.is_constant():
|
|
318
|
+
return self._parent(e.constant_coefficient())
|
|
319
|
+
else:
|
|
320
|
+
return e(self._parent.gen())
|
|
321
|
+
|
|
322
|
+
elif isinstance(e, Rational):
|
|
323
|
+
num = e.numer()
|
|
324
|
+
den = e.denom()
|
|
325
|
+
if den % 2:
|
|
326
|
+
if num % 2:
|
|
327
|
+
return self._one_element
|
|
328
|
+
return self._zero_element
|
|
329
|
+
raise ZeroDivisionError
|
|
330
|
+
|
|
331
|
+
elif isinstance(e, Gen):
|
|
332
|
+
pass # handle this in next if clause
|
|
333
|
+
|
|
334
|
+
elif isinstance(e, FiniteFieldElement_pari_ffelt):
|
|
335
|
+
# Reduce to pari
|
|
336
|
+
e = e.__pari__()
|
|
337
|
+
|
|
338
|
+
elif isinstance(e, GapElement):
|
|
339
|
+
from sage.libs.gap.libgap import libgap
|
|
340
|
+
return libgap(e).sage(ring=self._parent)
|
|
341
|
+
|
|
342
|
+
else:
|
|
343
|
+
try:
|
|
344
|
+
from sage.libs.gap.element import GapElement_FiniteField
|
|
345
|
+
except ImportError:
|
|
346
|
+
pass
|
|
347
|
+
else:
|
|
348
|
+
if isinstance(e, GapElement_FiniteField):
|
|
349
|
+
return e.sage(ring=self._parent)
|
|
350
|
+
raise TypeError("unable to coerce %r" % type(e))
|
|
351
|
+
|
|
352
|
+
cdef GEN t
|
|
353
|
+
if isinstance(e, Gen):
|
|
354
|
+
sig_on()
|
|
355
|
+
t = (<Gen>e).g
|
|
356
|
+
if typ(t) == t_FFELT:
|
|
357
|
+
t = FF_to_FpXQ(t)
|
|
358
|
+
else:
|
|
359
|
+
t = liftall_shallow(t)
|
|
360
|
+
|
|
361
|
+
if typ(t) == t_INT:
|
|
362
|
+
GF2E_conv_long(res.x, itos(t))
|
|
363
|
+
clear_stack()
|
|
364
|
+
elif typ(t) == t_POL:
|
|
365
|
+
g = self._gen
|
|
366
|
+
x = self._new()
|
|
367
|
+
GF2E_conv_long(x.x, 1)
|
|
368
|
+
|
|
369
|
+
for i from 0 <= i <= degpol(t):
|
|
370
|
+
if gtolong(gel(t, i+2)):
|
|
371
|
+
GF2E_add(res.x, res.x, x.x)
|
|
372
|
+
GF2E_mul(x.x, x.x, g.x)
|
|
373
|
+
clear_stack()
|
|
374
|
+
else:
|
|
375
|
+
clear_stack()
|
|
376
|
+
raise TypeError(f"unable to convert PARI {e.type()} to {self.parent}")
|
|
377
|
+
|
|
378
|
+
return res
|
|
379
|
+
|
|
380
|
+
raise ValueError("Cannot coerce element %s to this field." % e)
|
|
381
|
+
|
|
382
|
+
cpdef FiniteField_ntl_gf2eElement fetch_int(self, number):
|
|
383
|
+
r"""
|
|
384
|
+
Given an integer less than `p^n` with base `2`
|
|
385
|
+
representation `a_0 + a_1 \cdot 2 + \cdots + a_k 2^k`, this returns
|
|
386
|
+
`a_0 + a_1 x + \cdots + a_k x^k`, where `x` is the
|
|
387
|
+
generator of this finite field.
|
|
388
|
+
|
|
389
|
+
INPUT:
|
|
390
|
+
|
|
391
|
+
- ``number`` -- integer; of size less than the cardinality
|
|
392
|
+
|
|
393
|
+
EXAMPLES::
|
|
394
|
+
|
|
395
|
+
sage: k.<a> = GF(2^48)
|
|
396
|
+
sage: k._cache.fetch_int(2^33 + 2 + 1)
|
|
397
|
+
a^33 + a + 1
|
|
398
|
+
|
|
399
|
+
TESTS:
|
|
400
|
+
|
|
401
|
+
We test that :issue:`17027` is fixed::
|
|
402
|
+
|
|
403
|
+
sage: K.<a> = GF(2^16)
|
|
404
|
+
sage: K._cache.fetch_int(0r)
|
|
405
|
+
0
|
|
406
|
+
"""
|
|
407
|
+
cdef FiniteField_ntl_gf2eElement a
|
|
408
|
+
cdef GF2X_c _a
|
|
409
|
+
cdef int n
|
|
410
|
+
|
|
411
|
+
self.F.restore()
|
|
412
|
+
|
|
413
|
+
if number < 0 or number >= self._order:
|
|
414
|
+
raise TypeError("n must be between 0 and self.order()")
|
|
415
|
+
|
|
416
|
+
if isinstance(number, int):
|
|
417
|
+
if not number:
|
|
418
|
+
n = 0
|
|
419
|
+
else:
|
|
420
|
+
n = int(Integer(number).nbits())
|
|
421
|
+
n = n // 8 + 1
|
|
422
|
+
elif isinstance(number, Integer):
|
|
423
|
+
n = int(number.nbits())
|
|
424
|
+
n = n // 8 + 1
|
|
425
|
+
else:
|
|
426
|
+
raise TypeError("number %s is not an integer" % number)
|
|
427
|
+
|
|
428
|
+
cdef unsigned char* p = <unsigned char*>check_malloc(n)
|
|
429
|
+
cdef long i
|
|
430
|
+
a = self._new()
|
|
431
|
+
for i in range(n):
|
|
432
|
+
p[i] = (number % 256)
|
|
433
|
+
number = number >> 8
|
|
434
|
+
GF2XFromBytes(_a, p, n)
|
|
435
|
+
GF2E_conv_GF2X(a.x, _a)
|
|
436
|
+
sig_free(p)
|
|
437
|
+
return a
|
|
438
|
+
|
|
439
|
+
def polynomial(self):
|
|
440
|
+
"""
|
|
441
|
+
Return the list of 0s and 1s giving the defining polynomial of the
|
|
442
|
+
field.
|
|
443
|
+
|
|
444
|
+
EXAMPLES::
|
|
445
|
+
|
|
446
|
+
sage: k.<a> = GF(2^20,modulus='minimal_weight')
|
|
447
|
+
sage: k._cache.polynomial()
|
|
448
|
+
[1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
|
|
449
|
+
"""
|
|
450
|
+
cdef FiniteField_ntl_gf2eElement P
|
|
451
|
+
cdef GF2X_c _P
|
|
452
|
+
cdef GF2_c c
|
|
453
|
+
self.F.restore()
|
|
454
|
+
cdef int i
|
|
455
|
+
|
|
456
|
+
P = -(self._gen**self._degree)
|
|
457
|
+
_P = GF2E_rep(P.x)
|
|
458
|
+
|
|
459
|
+
ret = []
|
|
460
|
+
for i from 0 <= i < GF2E_degree():
|
|
461
|
+
c = GF2X_coeff(_P,i)
|
|
462
|
+
if not GF2_IsZero(c):
|
|
463
|
+
ret.append(1)
|
|
464
|
+
else:
|
|
465
|
+
ret.append(0)
|
|
466
|
+
ret.append(1)
|
|
467
|
+
return ret
|
|
468
|
+
|
|
469
|
+
cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement):
|
|
470
|
+
"""
|
|
471
|
+
An element of an NTL:GF2E finite field.
|
|
472
|
+
"""
|
|
473
|
+
|
|
474
|
+
def __init__(FiniteField_ntl_gf2eElement self, parent=None ):
|
|
475
|
+
"""
|
|
476
|
+
Initialize an element in parent. It's much better to use
|
|
477
|
+
parent(<value>) or any specialized method of parent
|
|
478
|
+
(one,zero,gen) instead. Do not call this constructor directly,
|
|
479
|
+
it doesn't make much sense.
|
|
480
|
+
|
|
481
|
+
INPUT:
|
|
482
|
+
|
|
483
|
+
- ``parent`` -- base field
|
|
484
|
+
|
|
485
|
+
OUTPUT: a finite field element
|
|
486
|
+
|
|
487
|
+
EXAMPLES::
|
|
488
|
+
|
|
489
|
+
sage: k.<a> = GF(2^16)
|
|
490
|
+
sage: from sage.rings.finite_rings.element_ntl_gf2e import FiniteField_ntl_gf2eElement
|
|
491
|
+
sage: FiniteField_ntl_gf2eElement(k)
|
|
492
|
+
0
|
|
493
|
+
sage: k.<a> = GF(2^20)
|
|
494
|
+
sage: a.parent() is k
|
|
495
|
+
True
|
|
496
|
+
"""
|
|
497
|
+
if parent is None:
|
|
498
|
+
raise ValueError("You must provide a parent to construct a finite field element")
|
|
499
|
+
|
|
500
|
+
def __cinit__(FiniteField_ntl_gf2eElement self, parent=None ):
|
|
501
|
+
"""
|
|
502
|
+
Restore the cache and construct the underlying NTL element.
|
|
503
|
+
|
|
504
|
+
EXAMPLES::
|
|
505
|
+
|
|
506
|
+
sage: k.<a> = GF(2^8, impl='ntl') # indirect doctest
|
|
507
|
+
"""
|
|
508
|
+
if parent is None:
|
|
509
|
+
return
|
|
510
|
+
if isinstance(parent, FiniteField_ntl_gf2e):
|
|
511
|
+
self._parent = parent
|
|
512
|
+
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
|
|
513
|
+
|
|
514
|
+
cdef FiniteField_ntl_gf2eElement _new(FiniteField_ntl_gf2eElement self):
|
|
515
|
+
cdef FiniteField_ntl_gf2eElement y
|
|
516
|
+
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
|
|
517
|
+
y = FiniteField_ntl_gf2eElement.__new__(FiniteField_ntl_gf2eElement)
|
|
518
|
+
y._parent = self._parent
|
|
519
|
+
y._cache = self._cache
|
|
520
|
+
return y
|
|
521
|
+
|
|
522
|
+
def __repr__(FiniteField_ntl_gf2eElement self) -> str:
|
|
523
|
+
"""
|
|
524
|
+
Polynomial representation of ``self``.
|
|
525
|
+
|
|
526
|
+
EXAMPLES::
|
|
527
|
+
|
|
528
|
+
sage: k.<a> = GF(2^16)
|
|
529
|
+
sage: str(a^16) # indirect doctest
|
|
530
|
+
'a^5 + a^3 + a^2 + 1'
|
|
531
|
+
sage: k.<u> = GF(2^16)
|
|
532
|
+
sage: u
|
|
533
|
+
u
|
|
534
|
+
"""
|
|
535
|
+
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
|
|
536
|
+
cdef GF2X_c rep = GF2E_rep(self.x)
|
|
537
|
+
cdef GF2_c c
|
|
538
|
+
cdef int i
|
|
539
|
+
|
|
540
|
+
if GF2E_IsZero(self.x):
|
|
541
|
+
return "0"
|
|
542
|
+
|
|
543
|
+
name = self._parent.variable_name()
|
|
544
|
+
_repr = []
|
|
545
|
+
|
|
546
|
+
c = GF2X_coeff(rep, 0)
|
|
547
|
+
if not GF2_IsZero(c):
|
|
548
|
+
_repr.append("1")
|
|
549
|
+
|
|
550
|
+
c = GF2X_coeff(rep, 1)
|
|
551
|
+
if not GF2_IsZero(c):
|
|
552
|
+
_repr.append(name)
|
|
553
|
+
|
|
554
|
+
for i from 1 < i <= GF2X_deg(rep):
|
|
555
|
+
c = GF2X_coeff(rep, i)
|
|
556
|
+
if not GF2_IsZero(c):
|
|
557
|
+
_repr.append("%s^%d" % (name, i))
|
|
558
|
+
|
|
559
|
+
return " + ".join(reversed(_repr))
|
|
560
|
+
|
|
561
|
+
def __bool__(FiniteField_ntl_gf2eElement self) -> bool:
|
|
562
|
+
r"""
|
|
563
|
+
Return ``True`` if ``self != k(0)``.
|
|
564
|
+
|
|
565
|
+
EXAMPLES::
|
|
566
|
+
|
|
567
|
+
sage: k.<a> = GF(2^20)
|
|
568
|
+
sage: bool(a) # indirect doctest
|
|
569
|
+
True
|
|
570
|
+
sage: bool(k(0))
|
|
571
|
+
False
|
|
572
|
+
sage: a.is_zero()
|
|
573
|
+
False
|
|
574
|
+
"""
|
|
575
|
+
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
|
|
576
|
+
return not bool(GF2E_IsZero(self.x))
|
|
577
|
+
|
|
578
|
+
def is_one(FiniteField_ntl_gf2eElement self):
|
|
579
|
+
r"""
|
|
580
|
+
Return ``True`` if ``self == k(1)``.
|
|
581
|
+
|
|
582
|
+
Equivalent to ``self != k(0)``.
|
|
583
|
+
|
|
584
|
+
EXAMPLES::
|
|
585
|
+
|
|
586
|
+
sage: k.<a> = GF(2^20)
|
|
587
|
+
sage: a.is_one() # indirect doctest
|
|
588
|
+
False
|
|
589
|
+
sage: k(1).is_one()
|
|
590
|
+
True
|
|
591
|
+
"""
|
|
592
|
+
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
|
|
593
|
+
return self.x == self._cache._one_element.x
|
|
594
|
+
|
|
595
|
+
def is_unit(FiniteField_ntl_gf2eElement self):
|
|
596
|
+
"""
|
|
597
|
+
Return ``True`` if ``self`` is nonzero, so it is a unit as an element
|
|
598
|
+
of the finite field.
|
|
599
|
+
|
|
600
|
+
EXAMPLES::
|
|
601
|
+
|
|
602
|
+
sage: k.<a> = GF(2^17)
|
|
603
|
+
sage: a.is_unit()
|
|
604
|
+
True
|
|
605
|
+
sage: k(0).is_unit()
|
|
606
|
+
False
|
|
607
|
+
"""
|
|
608
|
+
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
|
|
609
|
+
if not GF2E_IsZero(self.x):
|
|
610
|
+
return True
|
|
611
|
+
else:
|
|
612
|
+
return False
|
|
613
|
+
|
|
614
|
+
def is_square(FiniteField_ntl_gf2eElement self):
|
|
615
|
+
r"""
|
|
616
|
+
Return ``True`` as every element in `\GF{2^n}` is a square.
|
|
617
|
+
|
|
618
|
+
EXAMPLES::
|
|
619
|
+
|
|
620
|
+
sage: k.<a> = GF(2^18)
|
|
621
|
+
sage: e = k.random_element()
|
|
622
|
+
sage: e.parent() is k
|
|
623
|
+
True
|
|
624
|
+
sage: e.is_square()
|
|
625
|
+
True
|
|
626
|
+
sage: e.sqrt()^2 == e
|
|
627
|
+
True
|
|
628
|
+
"""
|
|
629
|
+
return True
|
|
630
|
+
|
|
631
|
+
def sqrt(FiniteField_ntl_gf2eElement self, all=False, extend=False):
|
|
632
|
+
"""
|
|
633
|
+
Return a square root of this finite field element in its parent.
|
|
634
|
+
|
|
635
|
+
EXAMPLES::
|
|
636
|
+
|
|
637
|
+
sage: k.<a> = GF(2^20)
|
|
638
|
+
sage: a.is_square()
|
|
639
|
+
True
|
|
640
|
+
sage: a.sqrt()
|
|
641
|
+
a^19 + a^15 + a^14 + a^12 + a^9 + a^7 + a^4 + a^3 + a + 1
|
|
642
|
+
sage: a.sqrt()^2 == a
|
|
643
|
+
True
|
|
644
|
+
|
|
645
|
+
This failed before :issue:`4899`::
|
|
646
|
+
|
|
647
|
+
sage: GF(2^16,'a')(1).sqrt()
|
|
648
|
+
1
|
|
649
|
+
"""
|
|
650
|
+
# this really should be handled special, its gf2 linear after
|
|
651
|
+
# all
|
|
652
|
+
a = self ** (self._cache._order // 2)
|
|
653
|
+
if all:
|
|
654
|
+
return [a]
|
|
655
|
+
else:
|
|
656
|
+
return a
|
|
657
|
+
|
|
658
|
+
cpdef _add_(self, right):
|
|
659
|
+
"""
|
|
660
|
+
Add two elements.
|
|
661
|
+
|
|
662
|
+
EXAMPLES::
|
|
663
|
+
|
|
664
|
+
sage: k.<a> = GF(2^16)
|
|
665
|
+
sage: e = a^2 + a + 1 # indirect doctest
|
|
666
|
+
sage: f = a^15 + a^2 + 1
|
|
667
|
+
sage: e + f
|
|
668
|
+
a^15 + a
|
|
669
|
+
"""
|
|
670
|
+
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
|
|
671
|
+
GF2E_add(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
|
|
672
|
+
return r
|
|
673
|
+
|
|
674
|
+
cpdef _mul_(self, right):
|
|
675
|
+
"""
|
|
676
|
+
Multiply two elements.
|
|
677
|
+
|
|
678
|
+
EXAMPLES::
|
|
679
|
+
|
|
680
|
+
sage: k.<a> = GF(2^16)
|
|
681
|
+
sage: e = a^2 + a + 1 # indirect doctest
|
|
682
|
+
sage: f = a^15 + a^2 + 1
|
|
683
|
+
sage: e * f
|
|
684
|
+
a^15 + a^6 + a^5 + a^3 + a^2
|
|
685
|
+
"""
|
|
686
|
+
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
|
|
687
|
+
GF2E_mul(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
|
|
688
|
+
return r
|
|
689
|
+
|
|
690
|
+
cpdef _div_(self, other):
|
|
691
|
+
"""
|
|
692
|
+
Divide two elements.
|
|
693
|
+
|
|
694
|
+
EXAMPLES::
|
|
695
|
+
|
|
696
|
+
sage: k.<a> = GF(2^16)
|
|
697
|
+
sage: e = a^2 + a + 1 # indirect doctest
|
|
698
|
+
sage: f = a^15 + a^2 + 1
|
|
699
|
+
sage: e / f
|
|
700
|
+
a^11 + a^8 + a^7 + a^6 + a^5 + a^3 + a^2 + 1
|
|
701
|
+
sage: k(1) / k(0)
|
|
702
|
+
Traceback (most recent call last):
|
|
703
|
+
...
|
|
704
|
+
ZeroDivisionError: division by zero in finite field
|
|
705
|
+
"""
|
|
706
|
+
cdef FiniteField_ntl_gf2eElement o = <FiniteField_ntl_gf2eElement>other
|
|
707
|
+
if GF2E_IsZero(o.x):
|
|
708
|
+
raise ZeroDivisionError('division by zero in finite field')
|
|
709
|
+
cdef FiniteField_ntl_gf2eElement r = self._new()
|
|
710
|
+
GF2E_div(r.x, self.x, o.x)
|
|
711
|
+
return r
|
|
712
|
+
|
|
713
|
+
cpdef _sub_(self, right):
|
|
714
|
+
"""
|
|
715
|
+
Subtract two elements.
|
|
716
|
+
|
|
717
|
+
EXAMPLES::
|
|
718
|
+
|
|
719
|
+
sage: k.<a> = GF(2^16)
|
|
720
|
+
sage: e = a^2 - a + 1 # indirect doctest
|
|
721
|
+
sage: f = a^15 - a^2 + 1
|
|
722
|
+
sage: e - f
|
|
723
|
+
a^15 + a
|
|
724
|
+
"""
|
|
725
|
+
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
|
|
726
|
+
GF2E_sub(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
|
|
727
|
+
return r
|
|
728
|
+
|
|
729
|
+
def __neg__(FiniteField_ntl_gf2eElement self):
|
|
730
|
+
"""
|
|
731
|
+
Return this element.
|
|
732
|
+
|
|
733
|
+
EXAMPLES::
|
|
734
|
+
|
|
735
|
+
sage: k.<a> = GF(2^16)
|
|
736
|
+
sage: -a
|
|
737
|
+
a
|
|
738
|
+
"""
|
|
739
|
+
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
|
|
740
|
+
r.x = (<FiniteField_ntl_gf2eElement>self).x
|
|
741
|
+
return r
|
|
742
|
+
|
|
743
|
+
def __invert__(self):
|
|
744
|
+
"""
|
|
745
|
+
Return the multiplicative inverse of an element.
|
|
746
|
+
|
|
747
|
+
EXAMPLES::
|
|
748
|
+
|
|
749
|
+
sage: k.<a> = GF(2^16)
|
|
750
|
+
sage: ~a
|
|
751
|
+
a^15 + a^4 + a^2 + a
|
|
752
|
+
sage: a * ~a
|
|
753
|
+
1
|
|
754
|
+
sage: ~k(0)
|
|
755
|
+
Traceback (most recent call last):
|
|
756
|
+
...
|
|
757
|
+
ZeroDivisionError: division by zero in finite field
|
|
758
|
+
"""
|
|
759
|
+
cdef FiniteField_ntl_gf2eElement o = self._parent._cache._one_element
|
|
760
|
+
return o._div_(self)
|
|
761
|
+
|
|
762
|
+
cdef _pow_long(self, long n):
|
|
763
|
+
"""
|
|
764
|
+
EXAMPLES::
|
|
765
|
+
|
|
766
|
+
sage: k.<a> = GF(2^63)
|
|
767
|
+
sage: a^2
|
|
768
|
+
a^2
|
|
769
|
+
sage: a^64
|
|
770
|
+
a^25 + a^24 + a^23 + a^18 + a^17 + a^16 + a^12 + a^10 + a^9 + a^5 + a^4 + a^3 + a^2 + a
|
|
771
|
+
sage: a^(2^64)
|
|
772
|
+
a^2
|
|
773
|
+
sage: a^(2^128)
|
|
774
|
+
a^4
|
|
775
|
+
|
|
776
|
+
TESTS::
|
|
777
|
+
|
|
778
|
+
sage: k(0) ^ (-1)
|
|
779
|
+
Traceback (most recent call last):
|
|
780
|
+
...
|
|
781
|
+
ZeroDivisionError: division by zero in finite field
|
|
782
|
+
sage: k(0) ^ (-10^100)
|
|
783
|
+
Traceback (most recent call last):
|
|
784
|
+
...
|
|
785
|
+
ZeroDivisionError: division by zero in finite field
|
|
786
|
+
sage: 2 ^ a
|
|
787
|
+
Traceback (most recent call last):
|
|
788
|
+
...
|
|
789
|
+
TypeError: unsupported operand parent(s) for ^: 'Finite Field in a of size 2^63' and 'Finite Field in a of size 2^63'
|
|
790
|
+
sage: a ^ "exp"
|
|
791
|
+
Traceback (most recent call last):
|
|
792
|
+
...
|
|
793
|
+
TypeError: unsupported operand type(s) for ** or pow(): 'sage.rings.finite_rings.element_ntl_gf2e.FiniteField_ntl_gf2eElement' and 'str'
|
|
794
|
+
"""
|
|
795
|
+
if n < 0 and GF2E_IsZero(self.x):
|
|
796
|
+
raise ZeroDivisionError('division by zero in finite field')
|
|
797
|
+
r = self._new()
|
|
798
|
+
GF2E_power(r.x, self.x, n)
|
|
799
|
+
return r
|
|
800
|
+
|
|
801
|
+
cpdef _richcmp_(left, right, int op):
|
|
802
|
+
"""
|
|
803
|
+
Comparison of finite field elements.
|
|
804
|
+
|
|
805
|
+
.. NOTE::
|
|
806
|
+
|
|
807
|
+
Finite fields are unordered. However, we adopt the convention that
|
|
808
|
+
an element ``e`` is bigger than element ``f`` if its polynomial
|
|
809
|
+
representation is bigger.
|
|
810
|
+
|
|
811
|
+
EXAMPLES::
|
|
812
|
+
|
|
813
|
+
sage: k.<a> = GF(2^20)
|
|
814
|
+
sage: e = k.random_element()
|
|
815
|
+
sage: f = loads(dumps(e))
|
|
816
|
+
sage: e is f
|
|
817
|
+
False
|
|
818
|
+
sage: e == f
|
|
819
|
+
True
|
|
820
|
+
sage: e != (e + 1)
|
|
821
|
+
True
|
|
822
|
+
|
|
823
|
+
::
|
|
824
|
+
|
|
825
|
+
sage: K.<a> = GF(2^100)
|
|
826
|
+
sage: a < a^2
|
|
827
|
+
True
|
|
828
|
+
sage: a > a^2
|
|
829
|
+
False
|
|
830
|
+
sage: a+1 > a^2
|
|
831
|
+
False
|
|
832
|
+
sage: a+1 < a^2
|
|
833
|
+
True
|
|
834
|
+
sage: a+1 < a
|
|
835
|
+
False
|
|
836
|
+
sage: a+1 == a
|
|
837
|
+
False
|
|
838
|
+
sage: a == a
|
|
839
|
+
True
|
|
840
|
+
"""
|
|
841
|
+
(<Cache_ntl_gf2e>left._parent._cache).F.restore()
|
|
842
|
+
cdef int c = (<FiniteField_ntl_gf2eElement>left).x == (<FiniteField_ntl_gf2eElement>right).x
|
|
843
|
+
if c == 1:
|
|
844
|
+
return rich_to_bool(op, 0)
|
|
845
|
+
else:
|
|
846
|
+
lx = GF2X_deg(GF2E_rep((<FiniteField_ntl_gf2eElement>left).x))
|
|
847
|
+
rx = GF2X_deg(GF2E_rep((<FiniteField_ntl_gf2eElement>right).x))
|
|
848
|
+
if lx != rx:
|
|
849
|
+
return richcmp_not_equal(lx, rx, op)
|
|
850
|
+
li = left._integer_representation()
|
|
851
|
+
ri = right._integer_representation()
|
|
852
|
+
return richcmp(li, ri, op)
|
|
853
|
+
|
|
854
|
+
def _integer_(FiniteField_ntl_gf2eElement self, Integer):
|
|
855
|
+
"""
|
|
856
|
+
Convert ``self`` to an integer if it is in the prime subfield.
|
|
857
|
+
|
|
858
|
+
EXAMPLES::
|
|
859
|
+
|
|
860
|
+
sage: k.<b> = GF(2^16); k
|
|
861
|
+
Finite Field in b of size 2^16
|
|
862
|
+
sage: ZZ(k(1))
|
|
863
|
+
1
|
|
864
|
+
sage: ZZ(k(0))
|
|
865
|
+
0
|
|
866
|
+
sage: ZZ(b)
|
|
867
|
+
Traceback (most recent call last):
|
|
868
|
+
...
|
|
869
|
+
TypeError: not in prime subfield
|
|
870
|
+
sage: GF(2)(b^(2^16-1)) # indirect doctest
|
|
871
|
+
1
|
|
872
|
+
"""
|
|
873
|
+
if self.is_zero(): return Integer(0)
|
|
874
|
+
elif self.is_one(): return Integer(1)
|
|
875
|
+
else:
|
|
876
|
+
raise TypeError("not in prime subfield")
|
|
877
|
+
|
|
878
|
+
def __int__(FiniteField_ntl_gf2eElement self):
|
|
879
|
+
"""
|
|
880
|
+
Return the int representation of ``self``. When ``self`` is in the
|
|
881
|
+
prime subfield, the integer returned is equal to ``self`` and
|
|
882
|
+
otherwise raises an error.
|
|
883
|
+
|
|
884
|
+
EXAMPLES::
|
|
885
|
+
|
|
886
|
+
sage: k.<a> = GF(2^20)
|
|
887
|
+
sage: int(k(0))
|
|
888
|
+
0
|
|
889
|
+
sage: int(k(1))
|
|
890
|
+
1
|
|
891
|
+
sage: int(a)
|
|
892
|
+
Traceback (most recent call last):
|
|
893
|
+
...
|
|
894
|
+
TypeError: Cannot coerce element to an integer.
|
|
895
|
+
sage: int(a^2 + 1)
|
|
896
|
+
Traceback (most recent call last):
|
|
897
|
+
...
|
|
898
|
+
TypeError: Cannot coerce element to an integer.
|
|
899
|
+
"""
|
|
900
|
+
if self == 0:
|
|
901
|
+
return int(0)
|
|
902
|
+
elif self == 1:
|
|
903
|
+
return int(1)
|
|
904
|
+
else:
|
|
905
|
+
raise TypeError("Cannot coerce element to an integer.")
|
|
906
|
+
|
|
907
|
+
def _integer_representation(FiniteField_ntl_gf2eElement self):
|
|
908
|
+
r"""
|
|
909
|
+
Return the int representation of ``self``. When ``self`` is in the
|
|
910
|
+
prime subfield, the integer returned is equal to ``self`` and not
|
|
911
|
+
to ``log_repr``.
|
|
912
|
+
|
|
913
|
+
Elements of this field are represented as ints in as follows:
|
|
914
|
+
for `e \in \GF{p}[x]` with `e = a_0 + a_1 x + a_2 x^2 + \cdots`,
|
|
915
|
+
`e` is represented as: `n = a_0 + a_1 p + a_2 p^2 + \cdots`.
|
|
916
|
+
|
|
917
|
+
.. SEEALSO::
|
|
918
|
+
|
|
919
|
+
:meth:`sage.rings.finite_rings.element_base.FinitePolyExtElement.to_integer`
|
|
920
|
+
|
|
921
|
+
EXAMPLES::
|
|
922
|
+
|
|
923
|
+
sage: k.<a> = GF(2^20)
|
|
924
|
+
sage: a._integer_representation()
|
|
925
|
+
2
|
|
926
|
+
sage: (a^2 + 1)._integer_representation()
|
|
927
|
+
5
|
|
928
|
+
sage: k.<a> = GF(2^70)
|
|
929
|
+
sage: (a^65 + a^64 + 1)._integer_representation()
|
|
930
|
+
55340232221128654849
|
|
931
|
+
"""
|
|
932
|
+
cdef unsigned int i = 0
|
|
933
|
+
ret = int(0)
|
|
934
|
+
cdef unsigned long shift = 0
|
|
935
|
+
cdef GF2X_c r = GF2E_rep(self.x)
|
|
936
|
+
|
|
937
|
+
if GF2X_IsZero(r):
|
|
938
|
+
return 0
|
|
939
|
+
|
|
940
|
+
if little_endian():
|
|
941
|
+
while GF2X_deg(r) >= <long>(8 * sizeof(int)):
|
|
942
|
+
BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))
|
|
943
|
+
ret += int(i) << shift
|
|
944
|
+
shift += sizeof(int)*8
|
|
945
|
+
GF2X_RightShift(r,r,(sizeof(int)*8))
|
|
946
|
+
BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))
|
|
947
|
+
ret += int(i) << shift
|
|
948
|
+
else:
|
|
949
|
+
while GF2X_deg(r) >= <long>(8 * sizeof(int)):
|
|
950
|
+
BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))
|
|
951
|
+
ret += int(switch_endianess(i)) << shift
|
|
952
|
+
shift += sizeof(int)*8
|
|
953
|
+
GF2X_RightShift(r,r,(sizeof(int)*8))
|
|
954
|
+
BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))
|
|
955
|
+
ret += int(switch_endianess(i)) << shift
|
|
956
|
+
|
|
957
|
+
return int(ret)
|
|
958
|
+
|
|
959
|
+
def polynomial(FiniteField_ntl_gf2eElement self, name=None):
|
|
960
|
+
r"""
|
|
961
|
+
Return ``self`` viewed as a polynomial over
|
|
962
|
+
``self.parent().prime_subfield()``.
|
|
963
|
+
|
|
964
|
+
INPUT:
|
|
965
|
+
|
|
966
|
+
- ``name`` -- (optional) variable name
|
|
967
|
+
|
|
968
|
+
EXAMPLES::
|
|
969
|
+
|
|
970
|
+
sage: k.<a> = GF(2^17)
|
|
971
|
+
sage: e = a^15 + a^13 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a + 1
|
|
972
|
+
sage: e.polynomial()
|
|
973
|
+
a^15 + a^13 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a + 1
|
|
974
|
+
|
|
975
|
+
sage: from sage.rings.polynomial.polynomial_element import Polynomial
|
|
976
|
+
sage: isinstance(e.polynomial(), Polynomial)
|
|
977
|
+
True
|
|
978
|
+
|
|
979
|
+
sage: e.polynomial('x')
|
|
980
|
+
x^15 + x^13 + x^11 + x^10 + x^9 + x^8 + x^7 + x^6 + x^4 + x + 1
|
|
981
|
+
"""
|
|
982
|
+
cdef GF2X_c r = GF2E_rep(self.x)
|
|
983
|
+
cdef int i
|
|
984
|
+
|
|
985
|
+
C = []
|
|
986
|
+
for i from 0 <= i <= GF2X_deg(r):
|
|
987
|
+
C.append(GF2_conv_to_long(GF2X_coeff(r,i)))
|
|
988
|
+
return self._parent.polynomial_ring(name)(C)
|
|
989
|
+
|
|
990
|
+
def charpoly(self, var='x'):
|
|
991
|
+
r"""
|
|
992
|
+
Return the characteristic polynomial of ``self`` as a polynomial
|
|
993
|
+
in var over the prime subfield.
|
|
994
|
+
|
|
995
|
+
INPUT:
|
|
996
|
+
|
|
997
|
+
- ``var`` -- string (default: ``'x'``)
|
|
998
|
+
|
|
999
|
+
OUTPUT: polynomial
|
|
1000
|
+
|
|
1001
|
+
EXAMPLES::
|
|
1002
|
+
|
|
1003
|
+
sage: k.<a> = GF(2^8, impl='ntl')
|
|
1004
|
+
sage: b = a^3 + a
|
|
1005
|
+
sage: b.minpoly()
|
|
1006
|
+
x^4 + x^3 + x^2 + x + 1
|
|
1007
|
+
sage: b.charpoly()
|
|
1008
|
+
x^8 + x^6 + x^4 + x^2 + 1
|
|
1009
|
+
sage: b.charpoly().factor()
|
|
1010
|
+
(x^4 + x^3 + x^2 + x + 1)^2
|
|
1011
|
+
sage: b.charpoly('Z')
|
|
1012
|
+
Z^8 + Z^6 + Z^4 + Z^2 + 1
|
|
1013
|
+
"""
|
|
1014
|
+
f = self.minpoly(var)
|
|
1015
|
+
cdef int d = f.degree(), n = self.parent().degree()
|
|
1016
|
+
cdef int pow = n/d
|
|
1017
|
+
return f if pow == 1 else f**pow
|
|
1018
|
+
|
|
1019
|
+
def minpoly(self, var='x'):
|
|
1020
|
+
r"""
|
|
1021
|
+
Return the minimal polynomial of ``self``, which is the smallest
|
|
1022
|
+
degree polynomial `f \in \GF{2}[x]` such that ``f(self) == 0``.
|
|
1023
|
+
|
|
1024
|
+
INPUT:
|
|
1025
|
+
|
|
1026
|
+
- ``var`` -- string (default: ``'x'``)
|
|
1027
|
+
|
|
1028
|
+
OUTPUT: polynomial
|
|
1029
|
+
|
|
1030
|
+
EXAMPLES::
|
|
1031
|
+
|
|
1032
|
+
sage: K.<a> = GF(2^100)
|
|
1033
|
+
sage: f = a.minpoly(); f
|
|
1034
|
+
x^100 + x^57 + x^56 + x^55 + x^52 + x^48 + x^47 + x^46 + x^45 + x^44 + x^43 + x^41 + x^37 + x^36 + x^35 + x^34 + x^31 + x^30 + x^27 + x^25 + x^24 + x^22 + x^20 + x^19 + x^16 + x^15 + x^11 + x^9 + x^8 + x^6 + x^5 + x^3 + 1
|
|
1035
|
+
sage: f(a)
|
|
1036
|
+
0
|
|
1037
|
+
sage: g = K.random_element()
|
|
1038
|
+
sage: g.minpoly()(g)
|
|
1039
|
+
0
|
|
1040
|
+
"""
|
|
1041
|
+
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
|
|
1042
|
+
cdef GF2X_c r = GF2X_IrredPolyMod(GF2E_rep(self.x), GF2E_modulus())
|
|
1043
|
+
cdef int i
|
|
1044
|
+
C = []
|
|
1045
|
+
for i from 0 <= i <= GF2X_deg(r):
|
|
1046
|
+
C.append(GF2_conv_to_long(GF2X_coeff(r,i)))
|
|
1047
|
+
return self._parent.polynomial_ring(var)(C)
|
|
1048
|
+
|
|
1049
|
+
def trace(self):
|
|
1050
|
+
"""
|
|
1051
|
+
Return the trace of ``self``.
|
|
1052
|
+
|
|
1053
|
+
EXAMPLES::
|
|
1054
|
+
|
|
1055
|
+
sage: K.<a> = GF(2^25)
|
|
1056
|
+
sage: a.trace()
|
|
1057
|
+
0
|
|
1058
|
+
sage: a.charpoly()
|
|
1059
|
+
x^25 + x^8 + x^6 + x^2 + 1
|
|
1060
|
+
sage: parent(a.trace())
|
|
1061
|
+
Finite Field of size 2
|
|
1062
|
+
|
|
1063
|
+
sage: b = a+1
|
|
1064
|
+
sage: b.trace()
|
|
1065
|
+
1
|
|
1066
|
+
sage: b.charpoly()[1]
|
|
1067
|
+
1
|
|
1068
|
+
"""
|
|
1069
|
+
if GF2_IsOne(GF2E_trace(self.x)):
|
|
1070
|
+
return GF2_1
|
|
1071
|
+
else:
|
|
1072
|
+
return GF2_0
|
|
1073
|
+
|
|
1074
|
+
def weight(self):
|
|
1075
|
+
"""
|
|
1076
|
+
Return the number of nonzero coefficients in the polynomial
|
|
1077
|
+
representation of ``self``.
|
|
1078
|
+
|
|
1079
|
+
EXAMPLES::
|
|
1080
|
+
|
|
1081
|
+
sage: K.<a> = GF(2^21)
|
|
1082
|
+
sage: a.weight()
|
|
1083
|
+
1
|
|
1084
|
+
sage: (a^5+a^2+1).weight()
|
|
1085
|
+
3
|
|
1086
|
+
sage: b = 1/(a+1); b
|
|
1087
|
+
a^20 + a^19 + a^18 + a^17 + a^16 + a^15 + a^14 + a^13 + a^12 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a^3 + a^2
|
|
1088
|
+
sage: b.weight()
|
|
1089
|
+
18
|
|
1090
|
+
"""
|
|
1091
|
+
return GF2X_weight(GF2E_rep(self.x))
|
|
1092
|
+
|
|
1093
|
+
def _magma_init_(self, magma):
|
|
1094
|
+
r"""
|
|
1095
|
+
Return a string representation of ``self`` that MAGMA can
|
|
1096
|
+
understand.
|
|
1097
|
+
|
|
1098
|
+
EXAMPLES::
|
|
1099
|
+
|
|
1100
|
+
sage: k.<a> = GF(2^16)
|
|
1101
|
+
sage: a._magma_init_(magma) # random; optional - magma
|
|
1102
|
+
'_sage_[...]'
|
|
1103
|
+
|
|
1104
|
+
.. NOTE::
|
|
1105
|
+
|
|
1106
|
+
This method calls MAGMA to setup the parent.
|
|
1107
|
+
"""
|
|
1108
|
+
km = magma(self.parent())
|
|
1109
|
+
vn_m = km.gen(1).name()
|
|
1110
|
+
vn_s = str(self.parent().polynomial_ring().gen())
|
|
1111
|
+
return str(self.polynomial()).replace(vn_s,vn_m)
|
|
1112
|
+
|
|
1113
|
+
def __copy__(self):
|
|
1114
|
+
"""
|
|
1115
|
+
Return a copy of this element. Actually just returns ``self``, since
|
|
1116
|
+
finite field elements are immutable.
|
|
1117
|
+
|
|
1118
|
+
EXAMPLES::
|
|
1119
|
+
|
|
1120
|
+
sage: k.<a> = GF(2^16)
|
|
1121
|
+
sage: copy(a) is a
|
|
1122
|
+
True
|
|
1123
|
+
"""
|
|
1124
|
+
return self
|
|
1125
|
+
|
|
1126
|
+
def __deepcopy__(self, memo):
|
|
1127
|
+
"""
|
|
1128
|
+
EXAMPLES::
|
|
1129
|
+
|
|
1130
|
+
sage: k.<a> = GF(2^16)
|
|
1131
|
+
sage: deepcopy(a) is a
|
|
1132
|
+
True
|
|
1133
|
+
"""
|
|
1134
|
+
return self
|
|
1135
|
+
|
|
1136
|
+
def _gap_init_(self):
|
|
1137
|
+
r"""
|
|
1138
|
+
Return a string that evaluates to the GAP representation of
|
|
1139
|
+
this element.
|
|
1140
|
+
|
|
1141
|
+
A :exc:`NotImplementedError` is raised if
|
|
1142
|
+
``self.parent().modulus()`` is not a Conway polynomial, as
|
|
1143
|
+
the isomorphism of finite fields is not implemented yet.
|
|
1144
|
+
|
|
1145
|
+
EXAMPLES::
|
|
1146
|
+
|
|
1147
|
+
sage: k.<b> = GF(2^16)
|
|
1148
|
+
sage: b._gap_init_()
|
|
1149
|
+
'Z(65536)^1'
|
|
1150
|
+
sage: k(gap('Z(2^16)^3+Z(2^16)^5')) # needs sage.libs.gap
|
|
1151
|
+
b^5 + b^3
|
|
1152
|
+
sage: k(libgap.Z(2^16)^3+libgap.Z(2^16)^5) # needs sage.libs.gap
|
|
1153
|
+
b^5 + b^3
|
|
1154
|
+
"""
|
|
1155
|
+
F = self._parent
|
|
1156
|
+
if not F.is_conway():
|
|
1157
|
+
raise NotImplementedError("conversion of (NTL) finite field element to GAP not implemented except for fields defined by Conway polynomials.")
|
|
1158
|
+
order = F.order()
|
|
1159
|
+
if order > 65536:
|
|
1160
|
+
raise TypeError("order (=%s) must be at most 65536." % order)
|
|
1161
|
+
if self == 0:
|
|
1162
|
+
return '0*Z(%s)' % order
|
|
1163
|
+
assert F.degree() > 1
|
|
1164
|
+
g = F.multiplicative_generator()
|
|
1165
|
+
n = self.log(g)
|
|
1166
|
+
return 'Z(%s)^%s' % (order, n)
|
|
1167
|
+
|
|
1168
|
+
def __hash__(FiniteField_ntl_gf2eElement self):
|
|
1169
|
+
"""
|
|
1170
|
+
Return the hash of this finite field element. We hash the parent
|
|
1171
|
+
and the underlying integer representation of this element.
|
|
1172
|
+
|
|
1173
|
+
EXAMPLES::
|
|
1174
|
+
|
|
1175
|
+
sage: k.<a> = GF(2^18)
|
|
1176
|
+
sage: {a:1,a:0} # indirect doctest
|
|
1177
|
+
{a: 0}
|
|
1178
|
+
"""
|
|
1179
|
+
return hash(self._integer_representation()) # todo, come up with a faster version
|
|
1180
|
+
|
|
1181
|
+
def _vector_(FiniteField_ntl_gf2eElement self, reverse=False):
|
|
1182
|
+
r"""
|
|
1183
|
+
Return a vector matching this element in the vector space attached
|
|
1184
|
+
to the parent. The most significant bit is to the right.
|
|
1185
|
+
|
|
1186
|
+
INPUT:
|
|
1187
|
+
|
|
1188
|
+
- ``reverse`` -- reverse the order of the bits from little endian to
|
|
1189
|
+
big endian
|
|
1190
|
+
|
|
1191
|
+
EXAMPLES::
|
|
1192
|
+
|
|
1193
|
+
sage: k.<a> = GF(2^16)
|
|
1194
|
+
sage: e = a^14 + a^13 + 1
|
|
1195
|
+
sage: vector(e) # little endian
|
|
1196
|
+
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0)
|
|
1197
|
+
|
|
1198
|
+
sage: e._vector_(reverse=True) # big endian
|
|
1199
|
+
(0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
|
|
1200
|
+
"""
|
|
1201
|
+
#vector(foo) might pass in ZZ
|
|
1202
|
+
if isinstance(reverse, Parent):
|
|
1203
|
+
raise TypeError("Base field is fixed to prime subfield.")
|
|
1204
|
+
|
|
1205
|
+
cdef GF2X_c r = GF2E_rep(self.x)
|
|
1206
|
+
cdef int i
|
|
1207
|
+
|
|
1208
|
+
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
|
|
1209
|
+
|
|
1210
|
+
C = []
|
|
1211
|
+
for i from 0 <= i < GF2E_degree():
|
|
1212
|
+
C.append(GF2_conv_to_long(GF2X_coeff(r,i)))
|
|
1213
|
+
if reverse:
|
|
1214
|
+
C = list(reversed(C))
|
|
1215
|
+
return self._parent.vector_space(map=False)(C)
|
|
1216
|
+
|
|
1217
|
+
def __reduce__(FiniteField_ntl_gf2eElement self):
|
|
1218
|
+
"""
|
|
1219
|
+
Used for supporting pickling of finite field elements.
|
|
1220
|
+
|
|
1221
|
+
EXAMPLES::
|
|
1222
|
+
|
|
1223
|
+
sage: k.<a> = GF(2^16)
|
|
1224
|
+
sage: loads(dumps(a)) == a
|
|
1225
|
+
True
|
|
1226
|
+
"""
|
|
1227
|
+
return unpickleFiniteField_ntl_gf2eElement, (self._parent, str(self))
|
|
1228
|
+
|
|
1229
|
+
def log(self, base, order=None, *, check=False):
|
|
1230
|
+
"""
|
|
1231
|
+
Compute an integer `x` such that `b^x = a`, where `a` is ``self``
|
|
1232
|
+
and `b` is ``base``.
|
|
1233
|
+
|
|
1234
|
+
INPUT:
|
|
1235
|
+
|
|
1236
|
+
- ``base`` -- finite field element
|
|
1237
|
+
- ``order`` -- integer (optional), the order of the base
|
|
1238
|
+
- ``check`` -- boolean (default: ``False``): If set,
|
|
1239
|
+
test whether the given ``order`` is correct.
|
|
1240
|
+
|
|
1241
|
+
OUTPUT:
|
|
1242
|
+
|
|
1243
|
+
Integer `x` such that `a^x = b`, if it exists.
|
|
1244
|
+
Raises a :exc:`ValueError` exception if no such `x` exists.
|
|
1245
|
+
|
|
1246
|
+
ALGORITHM: :pari:`fflog`
|
|
1247
|
+
|
|
1248
|
+
EXAMPLES::
|
|
1249
|
+
|
|
1250
|
+
sage: F = FiniteField(2^10, 'a')
|
|
1251
|
+
sage: g = F.gen()
|
|
1252
|
+
sage: b = g; a = g^37
|
|
1253
|
+
sage: a.log(b)
|
|
1254
|
+
37
|
|
1255
|
+
sage: b^37; a
|
|
1256
|
+
a^8 + a^7 + a^4 + a + 1
|
|
1257
|
+
a^8 + a^7 + a^4 + a + 1
|
|
1258
|
+
|
|
1259
|
+
Big instances used to take a very long time before :issue:`32842`::
|
|
1260
|
+
|
|
1261
|
+
sage: g = GF(2^61).gen()
|
|
1262
|
+
sage: g.log(g^7)
|
|
1263
|
+
1976436865040309101
|
|
1264
|
+
|
|
1265
|
+
TESTS:
|
|
1266
|
+
|
|
1267
|
+
Check that non-existence is correctly detected::
|
|
1268
|
+
|
|
1269
|
+
sage: g = GF(2^50).gen()
|
|
1270
|
+
sage: (2^50-1) % 1023
|
|
1271
|
+
0
|
|
1272
|
+
sage: g.log(g^1023)
|
|
1273
|
+
Traceback (most recent call last):
|
|
1274
|
+
...
|
|
1275
|
+
ValueError: no logarithm of z50 exists to base z50^49 + z50^46 + z50^45 + z50^44 + z50^41 + z50^34 + z50^33 + z50^32 + z50^27 + z50^25 + z50^24 + z50^21 + z50^18 + z50^17 + z50^16 + z50^15 + z50^12 + z50^11 + z50^10 + z50^8 + z50^7 + z50^3 + z50^2
|
|
1276
|
+
|
|
1277
|
+
An example for ``check=True``::
|
|
1278
|
+
|
|
1279
|
+
sage: F.<t> = GF(2^5, impl='ntl')
|
|
1280
|
+
sage: t.log(t, 3^4, check=True)
|
|
1281
|
+
Traceback (most recent call last):
|
|
1282
|
+
...
|
|
1283
|
+
ValueError: base does not have the provided order
|
|
1284
|
+
|
|
1285
|
+
AUTHORS:
|
|
1286
|
+
|
|
1287
|
+
- David Joyner and William Stein (2005-11)
|
|
1288
|
+
- Lorenz Panny (2021-11): use PARI's :pari:`fflog` instead of :func:`sage.groups.generic.discrete_log`
|
|
1289
|
+
"""
|
|
1290
|
+
cdef Integer base_order
|
|
1291
|
+
|
|
1292
|
+
base = self.parent()(base)
|
|
1293
|
+
|
|
1294
|
+
# The result is undefined if the input to fflog() is invalid.
|
|
1295
|
+
# Since the unit group is cyclic, it suffices to check orders.
|
|
1296
|
+
if order is None:
|
|
1297
|
+
base_order = base.multiplicative_order()
|
|
1298
|
+
else:
|
|
1299
|
+
if check:
|
|
1300
|
+
from sage.groups.generic import has_order
|
|
1301
|
+
if not has_order(base, order, '*'):
|
|
1302
|
+
raise ValueError('base does not have the provided order')
|
|
1303
|
+
base_order = order
|
|
1304
|
+
|
|
1305
|
+
cdef Integer self_order = self.multiplicative_order()
|
|
1306
|
+
if not self_order.divides(base_order):
|
|
1307
|
+
raise ValueError(f'no logarithm of {self} exists to base {base}')
|
|
1308
|
+
|
|
1309
|
+
# Let's pass the known factorization of the order to PARI.
|
|
1310
|
+
fs, = self._parent.factored_unit_order() # cached
|
|
1311
|
+
ps = pari.Col(p for p,_ in fs)
|
|
1312
|
+
vs = pari.Col(base_order.valuation(p) for p,_ in fs)
|
|
1313
|
+
fac = pari.matconcat((ps, vs))
|
|
1314
|
+
|
|
1315
|
+
x = pari.fflog(self, base, (base_order, fac))
|
|
1316
|
+
return Integer(x)
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
def unpickleFiniteField_ntl_gf2eElement(parent, elem):
|
|
1320
|
+
"""
|
|
1321
|
+
EXAMPLES::
|
|
1322
|
+
|
|
1323
|
+
sage: k.<a> = GF(2^20)
|
|
1324
|
+
sage: e = k.random_element()
|
|
1325
|
+
sage: f = loads(dumps(e)) # indirect doctest
|
|
1326
|
+
sage: e == f
|
|
1327
|
+
True
|
|
1328
|
+
"""
|
|
1329
|
+
return parent(elem)
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
from sage.misc.persist import register_unpickle_override
|
|
1333
|
+
register_unpickle_override('sage.rings.finite_field_ntl_gf2e', 'unpickleFiniteField_ntl_gf2eElement', unpickleFiniteField_ntl_gf2eElement)
|