passagemath-modules 10.6.31rc3__cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_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-modules might be problematic. Click here for more details.
- passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
- passagemath_modules-10.6.31rc3.dist-info/RECORD +807 -0
- passagemath_modules-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_modules.libs/libgfortran-83c28eba.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-6e109695.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-cda90e79.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-7f678fcf.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-82690d50.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
- passagemath_modules.libs/libquadmath-2284e583.so.0.0.0 +0 -0
- sage/algebras/all__sagemath_modules.py +20 -0
- sage/algebras/catalog.py +148 -0
- sage/algebras/clifford_algebra.py +3107 -0
- sage/algebras/clifford_algebra_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/clifford_algebra_element.pxd +16 -0
- sage/algebras/clifford_algebra_element.pyx +997 -0
- sage/algebras/commutative_dga.py +4252 -0
- sage/algebras/exterior_algebra_groebner.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/exterior_algebra_groebner.pxd +55 -0
- sage/algebras/exterior_algebra_groebner.pyx +727 -0
- sage/algebras/finite_dimensional_algebras/all.py +2 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
- sage/algebras/finite_gca.py +528 -0
- sage/algebras/group_algebra.py +232 -0
- sage/algebras/lie_algebras/abelian.py +197 -0
- sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
- sage/algebras/lie_algebras/all.py +25 -0
- sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
- sage/algebras/lie_algebras/bch.py +177 -0
- sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
- sage/algebras/lie_algebras/bgg_resolution.py +232 -0
- sage/algebras/lie_algebras/center_uea.py +767 -0
- sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
- sage/algebras/lie_algebras/examples.py +683 -0
- sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
- sage/algebras/lie_algebras/heisenberg.py +820 -0
- sage/algebras/lie_algebras/lie_algebra.py +1562 -0
- sage/algebras/lie_algebras/lie_algebra_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
- sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
- sage/algebras/lie_algebras/morphism.py +661 -0
- sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
- sage/algebras/lie_algebras/onsager.py +1324 -0
- sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
- sage/algebras/lie_algebras/quotient.py +462 -0
- sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
- sage/algebras/lie_algebras/representation.py +1040 -0
- sage/algebras/lie_algebras/structure_coefficients.py +459 -0
- sage/algebras/lie_algebras/subalgebra.py +967 -0
- sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
- sage/algebras/lie_algebras/verma_module.py +1630 -0
- sage/algebras/lie_algebras/virasoro.py +1186 -0
- sage/algebras/octonion_algebra.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/octonion_algebra.pxd +20 -0
- sage/algebras/octonion_algebra.pyx +987 -0
- sage/algebras/orlik_solomon.py +907 -0
- sage/algebras/orlik_terao.py +779 -0
- sage/algebras/steenrod/all.py +7 -0
- sage/algebras/steenrod/steenrod_algebra.py +4258 -0
- sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
- sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
- sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
- sage/algebras/weyl_algebra.py +1126 -0
- sage/all__sagemath_modules.py +62 -0
- sage/calculus/all__sagemath_modules.py +19 -0
- sage/calculus/expr.py +205 -0
- sage/calculus/integration.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/riemann.pyx +1521 -0
- sage/calculus/test_sympy.py +201 -0
- sage/calculus/transforms/all.py +7 -0
- sage/calculus/transforms/dft.py +844 -0
- sage/calculus/transforms/dwt.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/transforms/dwt.pxd +7 -0
- sage/calculus/transforms/dwt.pyx +160 -0
- sage/calculus/transforms/fft.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/transforms/fft.pxd +12 -0
- sage/calculus/transforms/fft.pyx +487 -0
- sage/calculus/wester.py +662 -0
- sage/coding/abstract_code.py +1108 -0
- sage/coding/ag_code.py +868 -0
- sage/coding/ag_code_decoders.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/coding/ag_code_decoders.pyx +2639 -0
- sage/coding/all.py +15 -0
- sage/coding/bch_code.py +494 -0
- sage/coding/binary_code.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/coding/binary_code.pxd +124 -0
- sage/coding/binary_code.pyx +4139 -0
- sage/coding/bounds_catalog.py +43 -0
- sage/coding/channel.py +819 -0
- sage/coding/channels_catalog.py +29 -0
- sage/coding/code_bounds.py +755 -0
- sage/coding/code_constructions.py +804 -0
- sage/coding/codes_catalog.py +111 -0
- sage/coding/cyclic_code.py +1329 -0
- sage/coding/databases.py +316 -0
- sage/coding/decoder.py +373 -0
- sage/coding/decoders_catalog.py +88 -0
- sage/coding/delsarte_bounds.py +709 -0
- sage/coding/encoder.py +390 -0
- sage/coding/encoders_catalog.py +64 -0
- sage/coding/extended_code.py +468 -0
- sage/coding/gabidulin_code.py +1058 -0
- sage/coding/golay_code.py +404 -0
- sage/coding/goppa_code.py +441 -0
- sage/coding/grs_code.py +2371 -0
- sage/coding/guava.py +107 -0
- sage/coding/guruswami_sudan/all.py +1 -0
- sage/coding/guruswami_sudan/gs_decoder.py +897 -0
- sage/coding/guruswami_sudan/interpolation.py +409 -0
- sage/coding/guruswami_sudan/utils.py +176 -0
- sage/coding/hamming_code.py +176 -0
- sage/coding/information_set_decoder.py +1032 -0
- sage/coding/kasami_codes.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/coding/kasami_codes.pyx +351 -0
- sage/coding/linear_code.py +3067 -0
- sage/coding/linear_code_no_metric.py +1354 -0
- sage/coding/linear_rank_metric.py +961 -0
- sage/coding/parity_check_code.py +353 -0
- sage/coding/punctured_code.py +719 -0
- sage/coding/reed_muller_code.py +999 -0
- sage/coding/self_dual_codes.py +942 -0
- sage/coding/source_coding/all.py +2 -0
- sage/coding/source_coding/huffman.py +553 -0
- sage/coding/subfield_subcode.py +423 -0
- sage/coding/two_weight_db.py +399 -0
- sage/combinat/all__sagemath_modules.py +7 -0
- sage/combinat/cartesian_product.py +347 -0
- sage/combinat/family.py +11 -0
- sage/combinat/free_module.py +1977 -0
- sage/combinat/root_system/all.py +147 -0
- sage/combinat/root_system/ambient_space.py +527 -0
- sage/combinat/root_system/associahedron.py +471 -0
- sage/combinat/root_system/braid_move_calculator.py +143 -0
- sage/combinat/root_system/braid_orbit.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/combinat/root_system/braid_orbit.pyx +144 -0
- sage/combinat/root_system/branching_rules.py +2301 -0
- sage/combinat/root_system/cartan_matrix.py +1245 -0
- sage/combinat/root_system/cartan_type.py +3069 -0
- sage/combinat/root_system/coxeter_group.py +162 -0
- sage/combinat/root_system/coxeter_matrix.py +1261 -0
- sage/combinat/root_system/coxeter_type.py +681 -0
- sage/combinat/root_system/dynkin_diagram.py +900 -0
- sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
- sage/combinat/root_system/fundamental_group.py +795 -0
- sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
- sage/combinat/root_system/integrable_representations.py +1227 -0
- sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
- sage/combinat/root_system/pieri_factors.py +1147 -0
- sage/combinat/root_system/plot.py +1615 -0
- sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
- sage/combinat/root_system/root_lattice_realizations.py +4628 -0
- sage/combinat/root_system/root_space.py +487 -0
- sage/combinat/root_system/root_system.py +882 -0
- sage/combinat/root_system/type_A.py +348 -0
- sage/combinat/root_system/type_A_affine.py +227 -0
- sage/combinat/root_system/type_A_infinity.py +241 -0
- sage/combinat/root_system/type_B.py +347 -0
- sage/combinat/root_system/type_BC_affine.py +287 -0
- sage/combinat/root_system/type_B_affine.py +216 -0
- sage/combinat/root_system/type_C.py +317 -0
- sage/combinat/root_system/type_C_affine.py +188 -0
- sage/combinat/root_system/type_D.py +357 -0
- sage/combinat/root_system/type_D_affine.py +208 -0
- sage/combinat/root_system/type_E.py +641 -0
- sage/combinat/root_system/type_E_affine.py +231 -0
- sage/combinat/root_system/type_F.py +387 -0
- sage/combinat/root_system/type_F_affine.py +137 -0
- sage/combinat/root_system/type_G.py +293 -0
- sage/combinat/root_system/type_G_affine.py +132 -0
- sage/combinat/root_system/type_H.py +105 -0
- sage/combinat/root_system/type_I.py +110 -0
- sage/combinat/root_system/type_Q.py +150 -0
- sage/combinat/root_system/type_affine.py +509 -0
- sage/combinat/root_system/type_dual.py +704 -0
- sage/combinat/root_system/type_folded.py +301 -0
- sage/combinat/root_system/type_marked.py +748 -0
- sage/combinat/root_system/type_reducible.py +601 -0
- sage/combinat/root_system/type_relabel.py +730 -0
- sage/combinat/root_system/type_super_A.py +837 -0
- sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
- sage/combinat/root_system/weight_space.py +639 -0
- sage/combinat/root_system/weyl_characters.py +2238 -0
- sage/crypto/__init__.py +4 -0
- sage/crypto/all.py +28 -0
- sage/crypto/block_cipher/all.py +7 -0
- sage/crypto/block_cipher/des.py +1065 -0
- sage/crypto/block_cipher/miniaes.py +2171 -0
- sage/crypto/block_cipher/present.py +909 -0
- sage/crypto/block_cipher/sdes.py +1527 -0
- sage/crypto/boolean_function.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/crypto/boolean_function.pxd +10 -0
- sage/crypto/boolean_function.pyx +1487 -0
- sage/crypto/cipher.py +78 -0
- sage/crypto/classical.py +3668 -0
- sage/crypto/classical_cipher.py +569 -0
- sage/crypto/cryptosystem.py +387 -0
- sage/crypto/key_exchange/all.py +7 -0
- sage/crypto/key_exchange/catalog.py +24 -0
- sage/crypto/key_exchange/diffie_hellman.py +323 -0
- sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
- sage/crypto/lattice.py +312 -0
- sage/crypto/lfsr.py +295 -0
- sage/crypto/lwe.py +840 -0
- sage/crypto/mq/__init__.py +4 -0
- sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
- sage/crypto/mq/rijndael_gf.py +2345 -0
- sage/crypto/mq/sbox.py +7 -0
- sage/crypto/mq/sr.py +3344 -0
- sage/crypto/public_key/all.py +5 -0
- sage/crypto/public_key/blum_goldwasser.py +776 -0
- sage/crypto/sbox.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/crypto/sbox.pyx +2090 -0
- sage/crypto/sboxes.py +2090 -0
- sage/crypto/stream.py +390 -0
- sage/crypto/stream_cipher.py +297 -0
- sage/crypto/util.py +519 -0
- sage/ext/all__sagemath_modules.py +1 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_modules.py +2 -0
- sage/ext/interpreters/wrapper_cc.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_cc.pxd +30 -0
- sage/ext/interpreters/wrapper_cc.pyx +252 -0
- sage/ext/interpreters/wrapper_cdf.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_cdf.pxd +26 -0
- sage/ext/interpreters/wrapper_cdf.pyx +245 -0
- sage/ext/interpreters/wrapper_rdf.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_rdf.pxd +23 -0
- sage/ext/interpreters/wrapper_rdf.pyx +221 -0
- sage/ext/interpreters/wrapper_rr.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_rr.pxd +28 -0
- sage/ext/interpreters/wrapper_rr.pyx +335 -0
- sage/geometry/all__sagemath_modules.py +5 -0
- sage/geometry/toric_lattice.py +1745 -0
- sage/geometry/toric_lattice_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/toric_lattice_element.pyx +432 -0
- sage/groups/abelian_gps/abelian_group.py +1925 -0
- sage/groups/abelian_gps/abelian_group_element.py +164 -0
- sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
- sage/groups/abelian_gps/dual_abelian_group.py +421 -0
- sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
- sage/groups/abelian_gps/element_base.py +341 -0
- sage/groups/abelian_gps/values.py +488 -0
- sage/groups/additive_abelian/additive_abelian_group.py +476 -0
- sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
- sage/groups/additive_abelian/all.py +4 -0
- sage/groups/additive_abelian/qmodnz.py +231 -0
- sage/groups/additive_abelian/qmodnz_element.py +349 -0
- sage/groups/affine_gps/affine_group.py +535 -0
- sage/groups/affine_gps/all.py +1 -0
- sage/groups/affine_gps/catalog.py +17 -0
- sage/groups/affine_gps/euclidean_group.py +246 -0
- sage/groups/affine_gps/group_element.py +562 -0
- sage/groups/all__sagemath_modules.py +12 -0
- sage/groups/galois_group.py +479 -0
- sage/groups/matrix_gps/all.py +4 -0
- sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
- sage/groups/matrix_gps/catalog.py +26 -0
- sage/groups/matrix_gps/coxeter_group.py +927 -0
- sage/groups/matrix_gps/finitely_generated.py +487 -0
- sage/groups/matrix_gps/group_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/groups/matrix_gps/group_element.pxd +11 -0
- sage/groups/matrix_gps/group_element.pyx +431 -0
- sage/groups/matrix_gps/linear.py +440 -0
- sage/groups/matrix_gps/matrix_group.py +617 -0
- sage/groups/matrix_gps/named_group.py +296 -0
- sage/groups/matrix_gps/orthogonal.py +544 -0
- sage/groups/matrix_gps/symplectic.py +251 -0
- sage/groups/matrix_gps/unitary.py +436 -0
- sage/groups/misc_gps/all__sagemath_modules.py +1 -0
- sage/groups/misc_gps/argument_groups.py +1905 -0
- sage/groups/misc_gps/imaginary_groups.py +479 -0
- sage/groups/perm_gps/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
- sage/homology/algebraic_topological_model.py +595 -0
- sage/homology/all.py +2 -0
- sage/homology/all__sagemath_modules.py +8 -0
- sage/homology/chain_complex.py +2148 -0
- sage/homology/chain_complex_homspace.py +165 -0
- sage/homology/chain_complex_morphism.py +629 -0
- sage/homology/chain_homotopy.py +604 -0
- sage/homology/chains.py +653 -0
- sage/homology/free_resolution.py +923 -0
- sage/homology/graded_resolution.py +567 -0
- sage/homology/hochschild_complex.py +756 -0
- sage/homology/homology_group.py +188 -0
- sage/homology/homology_morphism.py +422 -0
- sage/homology/homology_vector_space_with_basis.py +1454 -0
- sage/homology/koszul_complex.py +169 -0
- sage/homology/matrix_utils.py +205 -0
- sage/libs/all__sagemath_modules.py +1 -0
- sage/libs/gsl/__init__.py +1 -0
- sage/libs/gsl/airy.pxd +56 -0
- sage/libs/gsl/all.pxd +66 -0
- sage/libs/gsl/array.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/gsl/array.pxd +5 -0
- sage/libs/gsl/array.pyx +102 -0
- sage/libs/gsl/bessel.pxd +208 -0
- sage/libs/gsl/blas.pxd +116 -0
- sage/libs/gsl/blas_types.pxd +34 -0
- sage/libs/gsl/block.pxd +52 -0
- sage/libs/gsl/chebyshev.pxd +37 -0
- sage/libs/gsl/clausen.pxd +12 -0
- sage/libs/gsl/combination.pxd +47 -0
- sage/libs/gsl/complex.pxd +151 -0
- sage/libs/gsl/coulomb.pxd +30 -0
- sage/libs/gsl/coupling.pxd +21 -0
- sage/libs/gsl/dawson.pxd +12 -0
- sage/libs/gsl/debye.pxd +24 -0
- sage/libs/gsl/dilog.pxd +14 -0
- sage/libs/gsl/eigen.pxd +46 -0
- sage/libs/gsl/elementary.pxd +12 -0
- sage/libs/gsl/ellint.pxd +48 -0
- sage/libs/gsl/elljac.pxd +8 -0
- sage/libs/gsl/erf.pxd +32 -0
- sage/libs/gsl/errno.pxd +26 -0
- sage/libs/gsl/exp.pxd +44 -0
- sage/libs/gsl/expint.pxd +44 -0
- sage/libs/gsl/fermi_dirac.pxd +44 -0
- sage/libs/gsl/fft.pxd +121 -0
- sage/libs/gsl/fit.pxd +50 -0
- sage/libs/gsl/gamma.pxd +94 -0
- sage/libs/gsl/gegenbauer.pxd +26 -0
- sage/libs/gsl/histogram.pxd +176 -0
- sage/libs/gsl/hyperg.pxd +52 -0
- sage/libs/gsl/integration.pxd +69 -0
- sage/libs/gsl/interp.pxd +109 -0
- sage/libs/gsl/laguerre.pxd +24 -0
- sage/libs/gsl/lambert.pxd +16 -0
- sage/libs/gsl/legendre.pxd +90 -0
- sage/libs/gsl/linalg.pxd +185 -0
- sage/libs/gsl/log.pxd +26 -0
- sage/libs/gsl/math.pxd +43 -0
- sage/libs/gsl/matrix.pxd +143 -0
- sage/libs/gsl/matrix_complex.pxd +130 -0
- sage/libs/gsl/min.pxd +67 -0
- sage/libs/gsl/monte.pxd +56 -0
- sage/libs/gsl/ntuple.pxd +32 -0
- sage/libs/gsl/odeiv.pxd +70 -0
- sage/libs/gsl/permutation.pxd +78 -0
- sage/libs/gsl/poly.pxd +40 -0
- sage/libs/gsl/pow_int.pxd +12 -0
- sage/libs/gsl/psi.pxd +28 -0
- sage/libs/gsl/qrng.pxd +29 -0
- sage/libs/gsl/random.pxd +257 -0
- sage/libs/gsl/rng.pxd +100 -0
- sage/libs/gsl/roots.pxd +72 -0
- sage/libs/gsl/sort.pxd +36 -0
- sage/libs/gsl/statistics.pxd +59 -0
- sage/libs/gsl/sum.pxd +55 -0
- sage/libs/gsl/synchrotron.pxd +16 -0
- sage/libs/gsl/transport.pxd +24 -0
- sage/libs/gsl/trig.pxd +58 -0
- sage/libs/gsl/types.pxd +137 -0
- sage/libs/gsl/vector.pxd +101 -0
- sage/libs/gsl/vector_complex.pxd +83 -0
- sage/libs/gsl/wavelet.pxd +49 -0
- sage/libs/gsl/zeta.pxd +28 -0
- sage/libs/mpc/__init__.pxd +114 -0
- sage/libs/mpc/types.pxd +28 -0
- sage/libs/mpfr/__init__.pxd +299 -0
- sage/libs/mpfr/types.pxd +26 -0
- sage/libs/mpmath/__init__.py +1 -0
- sage/libs/mpmath/all.py +27 -0
- sage/libs/mpmath/all__sagemath_modules.py +1 -0
- sage/libs/mpmath/utils.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/action.pxd +26 -0
- sage/matrix/action.pyx +596 -0
- sage/matrix/all.py +9 -0
- sage/matrix/args.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/args.pxd +144 -0
- sage/matrix/args.pyx +1668 -0
- sage/matrix/benchmark.py +1258 -0
- sage/matrix/berlekamp_massey.py +95 -0
- sage/matrix/compute_J_ideal.py +926 -0
- sage/matrix/constructor.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_cdv.pxd +4 -0
- sage/matrix/matrix_cdv.pyx +93 -0
- sage/matrix/matrix_complex_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_complex_double_dense.pxd +5 -0
- sage/matrix/matrix_complex_double_dense.pyx +98 -0
- sage/matrix/matrix_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_dense.pxd +5 -0
- sage/matrix/matrix_dense.pyx +343 -0
- sage/matrix/matrix_domain_dense.pxd +5 -0
- sage/matrix/matrix_domain_sparse.pxd +5 -0
- sage/matrix/matrix_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_double_dense.pxd +7 -0
- sage/matrix/matrix_double_dense.pyx +3906 -0
- sage/matrix/matrix_double_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_double_sparse.pxd +6 -0
- sage/matrix/matrix_double_sparse.pyx +248 -0
- sage/matrix/matrix_generic_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_generic_dense.pxd +7 -0
- sage/matrix/matrix_generic_dense.pyx +354 -0
- sage/matrix/matrix_generic_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_generic_sparse.pxd +7 -0
- sage/matrix/matrix_generic_sparse.pyx +461 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
- sage/matrix/matrix_misc.py +313 -0
- sage/matrix/matrix_numpy_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_numpy_dense.pxd +14 -0
- sage/matrix/matrix_numpy_dense.pyx +450 -0
- sage/matrix/matrix_numpy_integer_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
- sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
- sage/matrix/matrix_polynomial_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_polynomial_dense.pxd +5 -0
- sage/matrix/matrix_polynomial_dense.pyx +5341 -0
- sage/matrix/matrix_real_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_real_double_dense.pxd +7 -0
- sage/matrix/matrix_real_double_dense.pyx +122 -0
- sage/matrix/matrix_space.py +2848 -0
- sage/matrix/matrix_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_sparse.pxd +5 -0
- sage/matrix/matrix_sparse.pyx +1222 -0
- sage/matrix/matrix_window.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_window.pxd +37 -0
- sage/matrix/matrix_window.pyx +242 -0
- sage/matrix/misc_mpfr.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/misc_mpfr.pyx +80 -0
- sage/matrix/operation_table.py +1182 -0
- sage/matrix/special.py +3666 -0
- sage/matrix/strassen.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/strassen.pyx +851 -0
- sage/matrix/symplectic_basis.py +541 -0
- sage/matrix/template.pxd +6 -0
- sage/matrix/tests.py +71 -0
- sage/matroids/advanced.py +77 -0
- sage/matroids/all.py +13 -0
- sage/matroids/basis_exchange_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/basis_exchange_matroid.pxd +96 -0
- sage/matroids/basis_exchange_matroid.pyx +2344 -0
- sage/matroids/basis_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/basis_matroid.pxd +45 -0
- sage/matroids/basis_matroid.pyx +1217 -0
- sage/matroids/catalog.py +44 -0
- sage/matroids/chow_ring.py +473 -0
- sage/matroids/chow_ring_ideal.py +849 -0
- sage/matroids/circuit_closures_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/circuit_closures_matroid.pxd +16 -0
- sage/matroids/circuit_closures_matroid.pyx +559 -0
- sage/matroids/circuits_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/circuits_matroid.pxd +38 -0
- sage/matroids/circuits_matroid.pyx +947 -0
- sage/matroids/constructor.py +1086 -0
- sage/matroids/database_collections.py +365 -0
- sage/matroids/database_matroids.py +5338 -0
- sage/matroids/dual_matroid.py +583 -0
- sage/matroids/extension.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/flats_matroid.pxd +28 -0
- sage/matroids/flats_matroid.pyx +715 -0
- sage/matroids/gammoid.py +600 -0
- sage/matroids/graphic_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/graphic_matroid.pxd +39 -0
- sage/matroids/graphic_matroid.pyx +2024 -0
- sage/matroids/lean_matrix.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/lean_matrix.pxd +126 -0
- sage/matroids/lean_matrix.pyx +3667 -0
- sage/matroids/linear_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/matroid.pxd +243 -0
- sage/matroids/matroid.pyx +8759 -0
- sage/matroids/matroids_catalog.py +190 -0
- sage/matroids/matroids_plot_helpers.py +890 -0
- sage/matroids/minor_matroid.py +480 -0
- sage/matroids/minorfix.h +9 -0
- sage/matroids/named_matroids.py +5 -0
- sage/matroids/rank_matroid.py +268 -0
- sage/matroids/set_system.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/set_system.pxd +38 -0
- sage/matroids/set_system.pyx +800 -0
- sage/matroids/transversal_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/transversal_matroid.pxd +14 -0
- sage/matroids/transversal_matroid.pyx +893 -0
- sage/matroids/union_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/unpickling.pyx +843 -0
- sage/matroids/utilities.py +809 -0
- sage/misc/all__sagemath_modules.py +20 -0
- sage/misc/c3.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/misc/c3.pyx +238 -0
- sage/misc/compat.py +87 -0
- sage/misc/element_with_label.py +173 -0
- sage/misc/func_persist.py +79 -0
- sage/misc/pickle_old.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/misc/pickle_old.pyx +19 -0
- sage/misc/proof.py +7 -0
- sage/misc/replace_dot_all.py +472 -0
- sage/misc/sagedoc_conf.py +168 -0
- sage/misc/sphinxify.py +167 -0
- sage/misc/test_class_pickling.py +85 -0
- sage/modules/all.py +42 -0
- sage/modules/complex_double_vector.py +25 -0
- sage/modules/diamond_cutting.py +380 -0
- sage/modules/fg_pid/all.py +1 -0
- sage/modules/fg_pid/fgp_element.py +456 -0
- sage/modules/fg_pid/fgp_module.py +2091 -0
- sage/modules/fg_pid/fgp_morphism.py +550 -0
- sage/modules/filtered_vector_space.py +1271 -0
- sage/modules/finite_submodule_iter.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/finite_submodule_iter.pxd +27 -0
- sage/modules/finite_submodule_iter.pyx +452 -0
- sage/modules/fp_graded/all.py +1 -0
- sage/modules/fp_graded/element.py +346 -0
- sage/modules/fp_graded/free_element.py +298 -0
- sage/modules/fp_graded/free_homspace.py +53 -0
- sage/modules/fp_graded/free_module.py +1060 -0
- sage/modules/fp_graded/free_morphism.py +217 -0
- sage/modules/fp_graded/homspace.py +563 -0
- sage/modules/fp_graded/module.py +1340 -0
- sage/modules/fp_graded/morphism.py +1990 -0
- sage/modules/fp_graded/steenrod/all.py +1 -0
- sage/modules/fp_graded/steenrod/homspace.py +65 -0
- sage/modules/fp_graded/steenrod/module.py +477 -0
- sage/modules/fp_graded/steenrod/morphism.py +404 -0
- sage/modules/fp_graded/steenrod/profile.py +241 -0
- sage/modules/free_module.py +8447 -0
- sage/modules/free_module_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/free_module_element.pxd +22 -0
- sage/modules/free_module_element.pyx +5445 -0
- sage/modules/free_module_homspace.py +369 -0
- sage/modules/free_module_integer.py +896 -0
- sage/modules/free_module_morphism.py +823 -0
- sage/modules/free_module_pseudohomspace.py +352 -0
- sage/modules/free_module_pseudomorphism.py +578 -0
- sage/modules/free_quadratic_module.py +1706 -0
- sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
- sage/modules/matrix_morphism.py +1745 -0
- sage/modules/misc.py +103 -0
- sage/modules/module_functors.py +192 -0
- sage/modules/multi_filtered_vector_space.py +719 -0
- sage/modules/ore_module.py +2208 -0
- sage/modules/ore_module_element.py +178 -0
- sage/modules/ore_module_homspace.py +147 -0
- sage/modules/ore_module_morphism.py +968 -0
- sage/modules/quotient_module.py +699 -0
- sage/modules/real_double_vector.py +22 -0
- sage/modules/submodule.py +255 -0
- sage/modules/tensor_operations.py +567 -0
- sage/modules/torsion_quadratic_module.py +1352 -0
- sage/modules/tutorial_free_modules.py +248 -0
- sage/modules/vector_complex_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_complex_double_dense.pxd +6 -0
- sage/modules/vector_complex_double_dense.pyx +117 -0
- sage/modules/vector_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_double_dense.pxd +6 -0
- sage/modules/vector_double_dense.pyx +604 -0
- sage/modules/vector_integer_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_integer_dense.pxd +15 -0
- sage/modules/vector_integer_dense.pyx +361 -0
- sage/modules/vector_integer_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_integer_sparse.pxd +29 -0
- sage/modules/vector_integer_sparse.pyx +406 -0
- sage/modules/vector_modn_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_modn_dense.pxd +12 -0
- sage/modules/vector_modn_dense.pyx +394 -0
- sage/modules/vector_modn_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_modn_sparse.pxd +21 -0
- sage/modules/vector_modn_sparse.pyx +298 -0
- sage/modules/vector_numpy_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_numpy_dense.pxd +15 -0
- sage/modules/vector_numpy_dense.pyx +304 -0
- sage/modules/vector_numpy_integer_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_numpy_integer_dense.pxd +7 -0
- sage/modules/vector_numpy_integer_dense.pyx +54 -0
- sage/modules/vector_rational_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_rational_dense.pxd +15 -0
- sage/modules/vector_rational_dense.pyx +387 -0
- sage/modules/vector_rational_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_rational_sparse.pxd +30 -0
- sage/modules/vector_rational_sparse.pyx +413 -0
- sage/modules/vector_real_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_real_double_dense.pxd +6 -0
- sage/modules/vector_real_double_dense.pyx +126 -0
- sage/modules/vector_space_homspace.py +430 -0
- sage/modules/vector_space_morphism.py +989 -0
- sage/modules/with_basis/all.py +15 -0
- sage/modules/with_basis/cell_module.py +494 -0
- sage/modules/with_basis/indexed_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/with_basis/indexed_element.pxd +13 -0
- sage/modules/with_basis/indexed_element.pyx +1058 -0
- sage/modules/with_basis/invariant.py +1075 -0
- sage/modules/with_basis/morphism.py +1636 -0
- sage/modules/with_basis/representation.py +2939 -0
- sage/modules/with_basis/subquotient.py +685 -0
- sage/numerical/all__sagemath_modules.py +6 -0
- sage/numerical/gauss_legendre.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/gauss_legendre.pyx +381 -0
- sage/numerical/optimize.py +910 -0
- sage/probability/all.py +10 -0
- sage/probability/probability_distribution.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/probability/probability_distribution.pyx +1242 -0
- sage/probability/random_variable.py +411 -0
- sage/quadratic_forms/all.py +4 -0
- sage/quadratic_forms/all__sagemath_modules.py +15 -0
- sage/quadratic_forms/binary_qf.py +2042 -0
- sage/quadratic_forms/bqf_class_group.py +748 -0
- sage/quadratic_forms/constructions.py +93 -0
- sage/quadratic_forms/count_local_2.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/quadratic_forms/count_local_2.pyx +365 -0
- sage/quadratic_forms/extras.py +195 -0
- sage/quadratic_forms/quadratic_form.py +1753 -0
- sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
- sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
- sage/quadratic_forms/quadratic_form__evaluate.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
- sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
- sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
- sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
- sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
- sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
- sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
- sage/quadratic_forms/quadratic_form__theta.py +352 -0
- sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
- sage/quadratic_forms/random_quadraticform.py +209 -0
- sage/quadratic_forms/ternary.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/quadratic_forms/ternary.pyx +1154 -0
- sage/quadratic_forms/ternary_qf.py +2027 -0
- sage/rings/all__sagemath_modules.py +28 -0
- sage/rings/asymptotic/all__sagemath_modules.py +1 -0
- sage/rings/asymptotic/misc.py +1252 -0
- sage/rings/cc.py +4 -0
- sage/rings/cfinite_sequence.py +1306 -0
- sage/rings/complex_conversion.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_conversion.pxd +8 -0
- sage/rings/complex_conversion.pyx +23 -0
- sage/rings/complex_double.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_double.pxd +21 -0
- sage/rings/complex_double.pyx +2654 -0
- sage/rings/complex_mpc.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_mpc.pxd +21 -0
- sage/rings/complex_mpc.pyx +2576 -0
- sage/rings/complex_mpfr.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_mpfr.pxd +18 -0
- sage/rings/complex_mpfr.pyx +3602 -0
- sage/rings/derivation.py +2334 -0
- sage/rings/finite_rings/all__sagemath_modules.py +1 -0
- sage/rings/finite_rings/maps_finite_field.py +191 -0
- sage/rings/function_field/all__sagemath_modules.py +8 -0
- sage/rings/function_field/derivations.py +102 -0
- sage/rings/function_field/derivations_rational.py +132 -0
- sage/rings/function_field/differential.py +853 -0
- sage/rings/function_field/divisor.py +1107 -0
- sage/rings/function_field/drinfeld_modules/action.py +199 -0
- sage/rings/function_field/drinfeld_modules/all.py +1 -0
- sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
- sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
- sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
- sage/rings/function_field/drinfeld_modules/homset.py +420 -0
- sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
- sage/rings/function_field/hermite_form_polynomial.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/function_field/khuri_makdisi.pyx +935 -0
- sage/rings/invariants/all.py +4 -0
- sage/rings/invariants/invariant_theory.py +4597 -0
- sage/rings/invariants/reconstruction.py +395 -0
- sage/rings/polynomial/all__sagemath_modules.py +17 -0
- sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
- sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
- sage/rings/polynomial/ore_function_element.py +952 -0
- sage/rings/polynomial/ore_function_field.py +1028 -0
- sage/rings/polynomial/ore_polynomial_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
- sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
- sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
- sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
- sage/rings/polynomial/skew_polynomial_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
- sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
- sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
- sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
- sage/rings/polynomial/skew_polynomial_ring.py +908 -0
- sage/rings/real_double_element_gsl.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/real_double_element_gsl.pxd +8 -0
- sage/rings/real_double_element_gsl.pyx +794 -0
- sage/rings/real_field.py +58 -0
- sage/rings/real_mpfr.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/real_mpfr.pxd +29 -0
- sage/rings/real_mpfr.pyx +6122 -0
- sage/rings/ring_extension.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/ring_extension.pxd +42 -0
- sage/rings/ring_extension.pyx +2779 -0
- sage/rings/ring_extension_conversion.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/ring_extension_conversion.pxd +16 -0
- sage/rings/ring_extension_conversion.pyx +462 -0
- sage/rings/ring_extension_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/ring_extension_element.pxd +21 -0
- sage/rings/ring_extension_element.pyx +1635 -0
- sage/rings/ring_extension_homset.py +64 -0
- sage/rings/ring_extension_morphism.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/ring_extension_morphism.pxd +35 -0
- sage/rings/ring_extension_morphism.pyx +920 -0
- sage/schemes/all__sagemath_modules.py +1 -0
- sage/schemes/projective/all__sagemath_modules.py +1 -0
- sage/schemes/projective/coherent_sheaf.py +300 -0
- sage/schemes/projective/cohomology.py +510 -0
- sage/stats/all.py +15 -0
- sage/stats/basic_stats.py +489 -0
- sage/stats/distributions/all.py +7 -0
- sage/stats/distributions/catalog.py +34 -0
- sage/stats/distributions/dgs.h +50 -0
- sage/stats/distributions/dgs.pxd +111 -0
- sage/stats/distributions/dgs_bern.h +400 -0
- sage/stats/distributions/dgs_gauss.h +614 -0
- sage/stats/distributions/dgs_misc.h +104 -0
- sage/stats/distributions/discrete_gaussian_integer.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
- sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
- sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
- sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
- sage/stats/hmm/all.py +15 -0
- sage/stats/hmm/chmm.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/hmm/distributions.pxd +29 -0
- sage/stats/hmm/distributions.pyx +531 -0
- sage/stats/hmm/hmm.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/hmm/hmm.pxd +17 -0
- sage/stats/hmm/hmm.pyx +1388 -0
- sage/stats/hmm/util.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/intlist.pxd +14 -0
- sage/stats/intlist.pyx +588 -0
- sage/stats/r.py +49 -0
- sage/stats/time_series.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/time_series.pxd +6 -0
- sage/stats/time_series.pyx +2546 -0
- sage/tensor/all.py +2 -0
- sage/tensor/modules/all.py +8 -0
- sage/tensor/modules/alternating_contr_tensor.py +761 -0
- sage/tensor/modules/comp.py +5598 -0
- sage/tensor/modules/ext_pow_free_module.py +824 -0
- sage/tensor/modules/finite_rank_free_module.py +3589 -0
- sage/tensor/modules/format_utilities.py +333 -0
- sage/tensor/modules/free_module_alt_form.py +858 -0
- sage/tensor/modules/free_module_automorphism.py +1207 -0
- sage/tensor/modules/free_module_basis.py +1074 -0
- sage/tensor/modules/free_module_element.py +284 -0
- sage/tensor/modules/free_module_homset.py +652 -0
- sage/tensor/modules/free_module_linear_group.py +564 -0
- sage/tensor/modules/free_module_morphism.py +1581 -0
- sage/tensor/modules/free_module_tensor.py +3289 -0
- sage/tensor/modules/reflexive_module.py +386 -0
- sage/tensor/modules/tensor_free_module.py +780 -0
- sage/tensor/modules/tensor_free_submodule.py +538 -0
- sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
- sage/tensor/modules/tensor_with_indices.py +1043 -0
|
@@ -0,0 +1,1487 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
"""
|
|
3
|
+
Boolean functions
|
|
4
|
+
|
|
5
|
+
Those functions are used for example in LFSR based ciphers like
|
|
6
|
+
the filter generator or the combination generator.
|
|
7
|
+
|
|
8
|
+
This module allows to study properties linked to spectral analysis,
|
|
9
|
+
and also algebraic immunity.
|
|
10
|
+
|
|
11
|
+
EXAMPLES::
|
|
12
|
+
|
|
13
|
+
sage: # needs sage.rings.finite_rings
|
|
14
|
+
sage: R.<x> = GF(2^8,'a')[]
|
|
15
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
16
|
+
sage: B = BooleanFunction(x^254); B # the Boolean function Tr(x^254)
|
|
17
|
+
Boolean function with 8 variables
|
|
18
|
+
sage: B.nonlinearity()
|
|
19
|
+
112
|
|
20
|
+
sage: B.algebraic_immunity() # needs sage.rings.polynomial.pbori
|
|
21
|
+
4
|
|
22
|
+
|
|
23
|
+
AUTHOR:
|
|
24
|
+
|
|
25
|
+
- Rusydi H. Makarim (2016-10-13): add functions related to linear structures
|
|
26
|
+
- Rusydi H. Makarim (2016-07-09): add is_plateaued()
|
|
27
|
+
- Yann Laigle-Chapuy (2010-02-26): add basic arithmetic
|
|
28
|
+
- Yann Laigle-Chapuy (2009-08-28): first implementation
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from cysignals.signals cimport sig_check
|
|
32
|
+
from libc.string cimport memcpy
|
|
33
|
+
|
|
34
|
+
from sage.data_structures.bitset_base cimport *
|
|
35
|
+
from sage.misc.superseded import deprecated_function_alias
|
|
36
|
+
from sage.rings.finite_rings.finite_field_base import FiniteField
|
|
37
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
38
|
+
from sage.rings.integer cimport Integer
|
|
39
|
+
from sage.rings.integer_ring import ZZ
|
|
40
|
+
from sage.rings.polynomial.polynomial_element import Polynomial
|
|
41
|
+
from sage.structure.richcmp cimport rich_to_bool
|
|
42
|
+
from sage.structure.sage_object cimport SageObject
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
from sage.rings.polynomial.pbori.pbori import BooleanPolynomial
|
|
46
|
+
except ImportError:
|
|
47
|
+
BooleanPolynomial = ()
|
|
48
|
+
|
|
49
|
+
# for details about the implementation of hamming_weight (in .pxd),
|
|
50
|
+
# walsh_hadamard transform, reed_muller transform, and a lot
|
|
51
|
+
# more, see 'Matters computational' available on www.jjj.de.
|
|
52
|
+
|
|
53
|
+
cdef walsh_hadamard(long *f, int ldn):
|
|
54
|
+
r"""
|
|
55
|
+
The Walsh Hadamard transform is an orthogonal transform equivalent
|
|
56
|
+
to a multidimensional discrete Fourier transform of size 2x2x...x2.
|
|
57
|
+
It can be defined by the following formula:
|
|
58
|
+
|
|
59
|
+
.. MATH:: W(j) = \sum_{i\in\{0,1\}^n} (-1)^{f(i)\oplus i \cdot j}
|
|
60
|
+
|
|
61
|
+
EXAMPLES::
|
|
62
|
+
|
|
63
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
64
|
+
sage: B = BooleanFunction([1,0,0,1])
|
|
65
|
+
sage: B.walsh_hadamard_transform() # indirect doctest
|
|
66
|
+
(0, 0, 0, -4)
|
|
67
|
+
"""
|
|
68
|
+
cdef long n, ldm, m, mh, t1, t2, r, j, u, v
|
|
69
|
+
n = 1 << ldn
|
|
70
|
+
for ldm in range(1, ldn+1):
|
|
71
|
+
m = (1 << ldm)
|
|
72
|
+
mh = m // 2
|
|
73
|
+
# If this is ``for r in range(0, n, m):``, then Cython generates horrible C code
|
|
74
|
+
for 0 <= r < n by m:
|
|
75
|
+
t1 = r
|
|
76
|
+
t2 = r + mh
|
|
77
|
+
for j in range(mh):
|
|
78
|
+
sig_check()
|
|
79
|
+
u = f[t1]
|
|
80
|
+
v = f[t2]
|
|
81
|
+
f[t1] = u + v
|
|
82
|
+
f[t2] = u - v
|
|
83
|
+
t1 += 1
|
|
84
|
+
t2 += 1
|
|
85
|
+
|
|
86
|
+
cdef long yellow_code(unsigned long a) noexcept:
|
|
87
|
+
"""
|
|
88
|
+
The yellow-code is just a Reed Muller transform applied to a
|
|
89
|
+
word.
|
|
90
|
+
|
|
91
|
+
EXAMPLES::
|
|
92
|
+
|
|
93
|
+
sage: # needs sage.rings.polynomial.pbori
|
|
94
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
95
|
+
sage: R.<x,y,z> = BooleanPolynomialRing(3)
|
|
96
|
+
sage: P = x*y
|
|
97
|
+
sage: B = BooleanFunction(P)
|
|
98
|
+
sage: B.truth_table() # indirect doctest
|
|
99
|
+
(False, False, False, True, False, False, False, True)
|
|
100
|
+
"""
|
|
101
|
+
cdef unsigned long s = (8*sizeof(unsigned long)) >> 1
|
|
102
|
+
cdef unsigned long m = (~0UL) >> s
|
|
103
|
+
cdef unsigned long r = a
|
|
104
|
+
while s:
|
|
105
|
+
sig_check()
|
|
106
|
+
r ^= (r&m) << s
|
|
107
|
+
s >>= 1
|
|
108
|
+
m ^= (m<<s)
|
|
109
|
+
return r
|
|
110
|
+
|
|
111
|
+
cdef reed_muller(mp_limb_t* f, int ldn):
|
|
112
|
+
r"""
|
|
113
|
+
The Reed Muller transform (also known as binary Möbius transform)
|
|
114
|
+
is an orthogonal transform. For a function `f` defined by
|
|
115
|
+
|
|
116
|
+
.. MATH:: f(x) = \bigoplus_{I\subset\{1,\ldots,n\}} \left(a_I \prod_{i\in I} x_i\right)
|
|
117
|
+
|
|
118
|
+
it allows to compute efficiently the ANF from the truth table and
|
|
119
|
+
vice versa, using the formulae:
|
|
120
|
+
|
|
121
|
+
.. MATH:: f(x) = \bigoplus_{support(x)\subset I} a_I
|
|
122
|
+
.. MATH:: a_i = \bigoplus_{I\subset support(x)} f(x)
|
|
123
|
+
|
|
124
|
+
EXAMPLES::
|
|
125
|
+
|
|
126
|
+
sage: # needs sage.rings.polynomial.pbori
|
|
127
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
128
|
+
sage: R.<x,y,z> = BooleanPolynomialRing(3)
|
|
129
|
+
sage: P = x*y
|
|
130
|
+
sage: B = BooleanFunction(P)
|
|
131
|
+
sage: B.truth_table() # indirect doctest
|
|
132
|
+
(False, False, False, True, False, False, False, True)
|
|
133
|
+
"""
|
|
134
|
+
cdef long n, ldm, m, mh, t1, t2, r, j
|
|
135
|
+
n = 1 << ldn
|
|
136
|
+
# intra word transform
|
|
137
|
+
for r in range(n):
|
|
138
|
+
f[r] = yellow_code(f[r])
|
|
139
|
+
# inter word transform
|
|
140
|
+
for ldm in range(1, ldn+1):
|
|
141
|
+
m = 1 << ldm
|
|
142
|
+
mh = m // 2
|
|
143
|
+
# If this is ``for r in range(0, n, m):``, then Cython generates horrible C code
|
|
144
|
+
for 0 <= r < n by m:
|
|
145
|
+
t1 = r
|
|
146
|
+
t2 = r + mh
|
|
147
|
+
for j in range(mh):
|
|
148
|
+
sig_check()
|
|
149
|
+
f[t2] ^= f[t1]
|
|
150
|
+
t1 += 1
|
|
151
|
+
t2 += 1
|
|
152
|
+
|
|
153
|
+
cdef class BooleanFunction(SageObject):
|
|
154
|
+
r"""
|
|
155
|
+
This module implements Boolean functions represented as a truth table.
|
|
156
|
+
|
|
157
|
+
We can construct a Boolean Function from either:
|
|
158
|
+
|
|
159
|
+
- an integer -- the result is the zero function with ``x`` variables;
|
|
160
|
+
- a list -- it is expected to be the truth table of the
|
|
161
|
+
result. Therefore it must be of length a power of 2, and its
|
|
162
|
+
elements are interpreted as Booleans;
|
|
163
|
+
- a string -- representing the truth table in hexadecimal;
|
|
164
|
+
- a Boolean polynomial -- the result is the corresponding Boolean function;
|
|
165
|
+
- a polynomial `P` over an extension of `\GF{2}` -- the result is
|
|
166
|
+
the Boolean function with truth table ``(Tr(P(x)) for x in
|
|
167
|
+
GF(2^k))``
|
|
168
|
+
|
|
169
|
+
EXAMPLES:
|
|
170
|
+
|
|
171
|
+
from the number of variables::
|
|
172
|
+
|
|
173
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
174
|
+
sage: BooleanFunction(5)
|
|
175
|
+
Boolean function with 5 variables
|
|
176
|
+
|
|
177
|
+
from a truth table::
|
|
178
|
+
|
|
179
|
+
sage: BooleanFunction([1,0,0,1])
|
|
180
|
+
Boolean function with 2 variables
|
|
181
|
+
|
|
182
|
+
note that elements can be of different types::
|
|
183
|
+
|
|
184
|
+
sage: B = BooleanFunction([False, sqrt(2)]); B # needs sage.symbolic
|
|
185
|
+
Boolean function with 1 variable
|
|
186
|
+
sage: [b for b in B] # needs sage.symbolic
|
|
187
|
+
[False, True]
|
|
188
|
+
|
|
189
|
+
from a string::
|
|
190
|
+
|
|
191
|
+
sage: BooleanFunction("111e")
|
|
192
|
+
Boolean function with 4 variables
|
|
193
|
+
|
|
194
|
+
from a :class:`sage.rings.polynomial.pbori.BooleanPolynomial`::
|
|
195
|
+
|
|
196
|
+
sage: R.<x,y,z> = BooleanPolynomialRing(3) # needs sage.rings.polynomial.pbori
|
|
197
|
+
sage: P = x*y # needs sage.rings.polynomial.pbori
|
|
198
|
+
sage: BooleanFunction(P) # needs sage.rings.polynomial.pbori
|
|
199
|
+
Boolean function with 3 variables
|
|
200
|
+
|
|
201
|
+
from a polynomial over a binary field::
|
|
202
|
+
|
|
203
|
+
sage: R.<x> = GF(2^8,'a')[] # needs sage.rings.finite_rings
|
|
204
|
+
sage: B = BooleanFunction(x^7); B # needs sage.rings.finite_rings
|
|
205
|
+
Boolean function with 8 variables
|
|
206
|
+
|
|
207
|
+
two failure cases::
|
|
208
|
+
|
|
209
|
+
sage: BooleanFunction(sqrt(2)) # needs sage.symbolic
|
|
210
|
+
Traceback (most recent call last):
|
|
211
|
+
...
|
|
212
|
+
TypeError: unable to init the Boolean function
|
|
213
|
+
|
|
214
|
+
sage: BooleanFunction([1, 0, 1])
|
|
215
|
+
Traceback (most recent call last):
|
|
216
|
+
...
|
|
217
|
+
ValueError: the length of the truth table must be a power of 2
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
cdef bitset_t _truth_table
|
|
221
|
+
cdef tuple _walsh_hadamard_transform
|
|
222
|
+
cdef object _nvariables
|
|
223
|
+
cdef object _nonlinearity
|
|
224
|
+
cdef object _correlation_immunity
|
|
225
|
+
cdef object _autocorrelation
|
|
226
|
+
cdef object _absolute_indicator
|
|
227
|
+
cdef object _sum_of_square_indicator
|
|
228
|
+
|
|
229
|
+
def __cinit__(self, x):
|
|
230
|
+
r"""
|
|
231
|
+
Construct a Boolean Function.
|
|
232
|
+
The input ``x`` can be either:
|
|
233
|
+
|
|
234
|
+
- an integer -- the result is the zero function with ``x`` variables;
|
|
235
|
+
- a list -- it is expected to be the truth table of the
|
|
236
|
+
result. Therefore it must be of length a power of 2, and its
|
|
237
|
+
elements are interpreted as Booleans;
|
|
238
|
+
- a Boolean polynomial -- the result is the corresponding Boolean function;
|
|
239
|
+
- a polynomial P over an extension of GF(2) -- the result is
|
|
240
|
+
the Boolean function with truth table ``( Tr(P(x)) for x in
|
|
241
|
+
GF(2^k) )``
|
|
242
|
+
|
|
243
|
+
EXAMPLES:
|
|
244
|
+
|
|
245
|
+
from the number of variables::
|
|
246
|
+
|
|
247
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
248
|
+
sage: BooleanFunction(5)
|
|
249
|
+
Boolean function with 5 variables
|
|
250
|
+
|
|
251
|
+
from a truth table::
|
|
252
|
+
|
|
253
|
+
sage: BooleanFunction([1,0,0,1])
|
|
254
|
+
Boolean function with 2 variables
|
|
255
|
+
|
|
256
|
+
note that elements can be of different types::
|
|
257
|
+
|
|
258
|
+
sage: B = BooleanFunction([False, sqrt(2)]); B # needs sage.symbolic
|
|
259
|
+
Boolean function with 1 variable
|
|
260
|
+
sage: [b for b in B] # needs sage.symbolic
|
|
261
|
+
[False, True]
|
|
262
|
+
|
|
263
|
+
from a :class:`sage.rings.polynomial.pbori.BooleanPolynomial`::
|
|
264
|
+
|
|
265
|
+
sage: R.<x,y,z> = BooleanPolynomialRing(3) # needs sage.rings.polynomial.pbori
|
|
266
|
+
sage: P = x*y # needs sage.rings.polynomial.pbori
|
|
267
|
+
sage: BooleanFunction(P) # needs sage.rings.polynomial.pbori
|
|
268
|
+
Boolean function with 3 variables
|
|
269
|
+
|
|
270
|
+
from a polynomial over a binary field::
|
|
271
|
+
|
|
272
|
+
sage: R.<x> = GF(2^8,'a')[] # needs sage.rings.finite_rings
|
|
273
|
+
sage: B = BooleanFunction(x^7); B # needs sage.rings.finite_rings
|
|
274
|
+
Boolean function with 8 variables
|
|
275
|
+
|
|
276
|
+
two failure cases::
|
|
277
|
+
|
|
278
|
+
sage: BooleanFunction(sqrt(2)) # needs sage.symbolic
|
|
279
|
+
Traceback (most recent call last):
|
|
280
|
+
...
|
|
281
|
+
TypeError: unable to init the Boolean function
|
|
282
|
+
|
|
283
|
+
sage: BooleanFunction([1, 0, 1])
|
|
284
|
+
Traceback (most recent call last):
|
|
285
|
+
...
|
|
286
|
+
ValueError: the length of the truth table must be a power of 2
|
|
287
|
+
"""
|
|
288
|
+
cdef mp_bitcnt_t i
|
|
289
|
+
if isinstance(x, str):
|
|
290
|
+
L = ZZ(len(x))
|
|
291
|
+
if L.is_power_of(2):
|
|
292
|
+
x = ZZ("0x" + x).digits(base=2, padto=4*L)
|
|
293
|
+
else:
|
|
294
|
+
raise ValueError("the length of the truth table must be a power of 2")
|
|
295
|
+
from types import GeneratorType
|
|
296
|
+
if isinstance(x, (list, tuple, GeneratorType)):
|
|
297
|
+
# initialisation from a truth table
|
|
298
|
+
|
|
299
|
+
# first, check the length
|
|
300
|
+
L = ZZ(len(x))
|
|
301
|
+
if L.is_power_of(2):
|
|
302
|
+
self._nvariables = L.exact_log(2)
|
|
303
|
+
else:
|
|
304
|
+
raise ValueError("the length of the truth table must be a power of 2")
|
|
305
|
+
|
|
306
|
+
# then, initialize our bitset
|
|
307
|
+
bitset_init(self._truth_table, <mp_bitcnt_t> L)
|
|
308
|
+
for i in range(L):
|
|
309
|
+
bitset_set_to(self._truth_table, i, x[i]) # int(x[i])&1)
|
|
310
|
+
|
|
311
|
+
elif isinstance(x, BooleanPolynomial):
|
|
312
|
+
# initialisation from a Boolean polynomial
|
|
313
|
+
self._nvariables = ZZ(x.parent().ngens())
|
|
314
|
+
bitset_init(self._truth_table, <mp_bitcnt_t> (1<<self._nvariables))
|
|
315
|
+
bitset_zero(self._truth_table)
|
|
316
|
+
for m in x:
|
|
317
|
+
i = sum([1<<k for k in m.iterindex()])
|
|
318
|
+
bitset_set(self._truth_table, i)
|
|
319
|
+
reed_muller(self._truth_table.bits,
|
|
320
|
+
ZZ(self._truth_table.limbs).exact_log(2))
|
|
321
|
+
|
|
322
|
+
elif isinstance(x, (int, Integer)):
|
|
323
|
+
# initialisation to the zero function
|
|
324
|
+
self._nvariables = ZZ(x)
|
|
325
|
+
bitset_init(self._truth_table, <mp_bitcnt_t> (1<<self._nvariables))
|
|
326
|
+
bitset_zero(self._truth_table)
|
|
327
|
+
|
|
328
|
+
elif isinstance(x, Polynomial):
|
|
329
|
+
K = x.base_ring()
|
|
330
|
+
if isinstance(K, FiniteField) and K.characteristic() == 2:
|
|
331
|
+
self._nvariables = K.degree()
|
|
332
|
+
bitset_init(self._truth_table, <mp_bitcnt_t> (1<<self._nvariables))
|
|
333
|
+
bitset_zero(self._truth_table)
|
|
334
|
+
try:
|
|
335
|
+
from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
|
|
336
|
+
except ImportError:
|
|
337
|
+
FiniteField_givaro = ()
|
|
338
|
+
if isinstance(K, FiniteField_givaro): # the ordering is not the same in this case
|
|
339
|
+
for u in K:
|
|
340
|
+
bitset_set_to(self._truth_table,
|
|
341
|
+
ZZ(u._vector_().list(), 2), (x(u)).trace())
|
|
342
|
+
else:
|
|
343
|
+
for i, u in enumerate(K):
|
|
344
|
+
bitset_set_to(self._truth_table, i, (x(u)).trace())
|
|
345
|
+
elif isinstance(x, BooleanFunction):
|
|
346
|
+
self._nvariables = x.nvariables()
|
|
347
|
+
bitset_init(self._truth_table, <mp_bitcnt_t> (1<<self._nvariables))
|
|
348
|
+
bitset_copy(self._truth_table, (<BooleanFunction>x)._truth_table)
|
|
349
|
+
else:
|
|
350
|
+
raise TypeError("unable to init the Boolean function")
|
|
351
|
+
|
|
352
|
+
def __dealloc__(self):
|
|
353
|
+
bitset_free(self._truth_table)
|
|
354
|
+
|
|
355
|
+
def _repr_(self):
|
|
356
|
+
"""
|
|
357
|
+
EXAMPLES::
|
|
358
|
+
|
|
359
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
360
|
+
sage: BooleanFunction(4) #indirect doctest
|
|
361
|
+
Boolean function with 4 variables
|
|
362
|
+
"""
|
|
363
|
+
r = "Boolean function with " + self._nvariables.str() + " variable"
|
|
364
|
+
if self._nvariables>1:
|
|
365
|
+
r += "s"
|
|
366
|
+
return r
|
|
367
|
+
|
|
368
|
+
def __invert__(self):
|
|
369
|
+
"""
|
|
370
|
+
Return the complement Boolean function of ``self``.
|
|
371
|
+
|
|
372
|
+
EXAMPLES::
|
|
373
|
+
|
|
374
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
375
|
+
sage: B = BooleanFunction([0, 1, 1, 0, 1, 0, 0, 0])
|
|
376
|
+
sage: (~B).truth_table(format='int')
|
|
377
|
+
(1, 0, 0, 1, 0, 1, 1, 1)
|
|
378
|
+
"""
|
|
379
|
+
cdef BooleanFunction res=BooleanFunction(self.nvariables())
|
|
380
|
+
bitset_complement(res._truth_table, self._truth_table)
|
|
381
|
+
return res
|
|
382
|
+
|
|
383
|
+
def __add__(self, BooleanFunction other):
|
|
384
|
+
"""
|
|
385
|
+
Return the element wise sum of ``self`` and ``other``,
|
|
386
|
+
which must have the same number of variables.
|
|
387
|
+
|
|
388
|
+
EXAMPLES::
|
|
389
|
+
|
|
390
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
391
|
+
sage: A = BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1])
|
|
392
|
+
sage: B = BooleanFunction([0, 1, 1, 0, 1, 0, 0, 0])
|
|
393
|
+
sage: (A+B).truth_table(format='int')
|
|
394
|
+
(0, 0, 1, 1, 0, 0, 0, 1)
|
|
395
|
+
|
|
396
|
+
it also corresponds to the addition of algebraic normal forms::
|
|
397
|
+
|
|
398
|
+
sage: S = A.algebraic_normal_form() + B.algebraic_normal_form() # needs sage.rings.polynomial.pbori
|
|
399
|
+
sage: (A+B).algebraic_normal_form() == S # needs sage.rings.polynomial.pbori
|
|
400
|
+
True
|
|
401
|
+
|
|
402
|
+
TESTS::
|
|
403
|
+
|
|
404
|
+
sage: A+BooleanFunction([0,1])
|
|
405
|
+
Traceback (most recent call last):
|
|
406
|
+
...
|
|
407
|
+
ValueError: the two Boolean functions must have the same number of variables
|
|
408
|
+
"""
|
|
409
|
+
if self.nvariables() != other.nvariables():
|
|
410
|
+
raise ValueError("the two Boolean functions must have the same number of variables")
|
|
411
|
+
cdef BooleanFunction res = BooleanFunction(self)
|
|
412
|
+
bitset_xor(res._truth_table, res._truth_table, other._truth_table)
|
|
413
|
+
return res
|
|
414
|
+
|
|
415
|
+
def __mul__(self, BooleanFunction other):
|
|
416
|
+
"""
|
|
417
|
+
Return the elementwise multiplication of ``self`` and ``other``,
|
|
418
|
+
which must have the same number of variables.
|
|
419
|
+
|
|
420
|
+
EXAMPLES::
|
|
421
|
+
|
|
422
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
423
|
+
sage: A = BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1])
|
|
424
|
+
sage: B = BooleanFunction([0, 1, 1, 0, 1, 0, 0, 0])
|
|
425
|
+
sage: (A*B).truth_table(format='int')
|
|
426
|
+
(0, 1, 0, 0, 1, 0, 0, 0)
|
|
427
|
+
|
|
428
|
+
it also corresponds to the multiplication of algebraic normal forms::
|
|
429
|
+
|
|
430
|
+
sage: P = A.algebraic_normal_form() * B.algebraic_normal_form() # needs sage.rings.polynomial.pbori
|
|
431
|
+
sage: (A*B).algebraic_normal_form() == P # needs sage.rings.polynomial.pbori
|
|
432
|
+
True
|
|
433
|
+
|
|
434
|
+
TESTS::
|
|
435
|
+
|
|
436
|
+
sage: A*BooleanFunction([0,1])
|
|
437
|
+
Traceback (most recent call last):
|
|
438
|
+
...
|
|
439
|
+
ValueError: the two Boolean functions must have the same number of variables
|
|
440
|
+
"""
|
|
441
|
+
if self.nvariables() != other.nvariables():
|
|
442
|
+
raise ValueError("the two Boolean functions must have the same number of variables")
|
|
443
|
+
cdef BooleanFunction res = BooleanFunction(self)
|
|
444
|
+
bitset_and(res._truth_table, res._truth_table, other._truth_table)
|
|
445
|
+
return res
|
|
446
|
+
|
|
447
|
+
def __or__(BooleanFunction self, BooleanFunction other):
|
|
448
|
+
"""
|
|
449
|
+
Return the concatenation of ``self`` and ``other``,
|
|
450
|
+
which must have the same number of variables.
|
|
451
|
+
|
|
452
|
+
EXAMPLES::
|
|
453
|
+
|
|
454
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
455
|
+
sage: A = BooleanFunction([0, 1, 0, 1])
|
|
456
|
+
sage: B = BooleanFunction([0, 1, 1, 0])
|
|
457
|
+
sage: (A|B).truth_table(format='int')
|
|
458
|
+
(0, 1, 0, 1, 0, 1, 1, 0)
|
|
459
|
+
|
|
460
|
+
sage: C = A.truth_table() + B.truth_table()
|
|
461
|
+
sage: (A|B).truth_table(format='int') == C
|
|
462
|
+
True
|
|
463
|
+
|
|
464
|
+
TESTS::
|
|
465
|
+
|
|
466
|
+
sage: A|BooleanFunction([0,1])
|
|
467
|
+
Traceback (most recent call last):
|
|
468
|
+
...
|
|
469
|
+
ValueError: the two Boolean functions must have the same number of variables
|
|
470
|
+
"""
|
|
471
|
+
if (self._nvariables != other.nvariables()):
|
|
472
|
+
raise ValueError("the two Boolean functions must have the same number of variables")
|
|
473
|
+
|
|
474
|
+
cdef BooleanFunction res=BooleanFunction(self.nvariables()+1)
|
|
475
|
+
cdef long i
|
|
476
|
+
|
|
477
|
+
nb_limbs = self._truth_table.limbs
|
|
478
|
+
if nb_limbs == 1:
|
|
479
|
+
L = len(self)
|
|
480
|
+
for i in range(L):
|
|
481
|
+
res[i ]=self[i]
|
|
482
|
+
res[i+L]=other[i]
|
|
483
|
+
return res
|
|
484
|
+
|
|
485
|
+
memcpy(res._truth_table.bits,
|
|
486
|
+
self._truth_table.bits, nb_limbs * sizeof(unsigned long))
|
|
487
|
+
memcpy(&(res._truth_table.bits[nb_limbs]),
|
|
488
|
+
other._truth_table.bits, nb_limbs * sizeof(unsigned long))
|
|
489
|
+
|
|
490
|
+
return res
|
|
491
|
+
|
|
492
|
+
def algebraic_normal_form(self):
|
|
493
|
+
"""
|
|
494
|
+
Return the :class:`sage.rings.polynomial.pbori.BooleanPolynomial`
|
|
495
|
+
corresponding to the algebraic normal form.
|
|
496
|
+
|
|
497
|
+
EXAMPLES::
|
|
498
|
+
|
|
499
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
500
|
+
sage: B = BooleanFunction([0,1,1,0,1,0,1,1])
|
|
501
|
+
sage: P = B.algebraic_normal_form(); P # needs sage.rings.polynomial.pbori
|
|
502
|
+
x0*x1*x2 + x0 + x1*x2 + x1 + x2
|
|
503
|
+
sage: [P(*ZZ(i).digits(base=2, padto=3)) for i in range(8)] # needs sage.rings.polynomial.pbori
|
|
504
|
+
[0, 1, 1, 0, 1, 0, 1, 1]
|
|
505
|
+
"""
|
|
506
|
+
cdef bitset_t anf
|
|
507
|
+
cdef mp_bitcnt_t inf, sup
|
|
508
|
+
bitset_init(anf, <mp_bitcnt_t> (1<<self._nvariables))
|
|
509
|
+
bitset_copy(anf, self._truth_table)
|
|
510
|
+
reed_muller(anf.bits, ZZ(anf.limbs).exact_log(2))
|
|
511
|
+
from sage.rings.polynomial.pbori.pbori import BooleanPolynomialRing
|
|
512
|
+
R = BooleanPolynomialRing(self._nvariables, "x")
|
|
513
|
+
G = R.gens()
|
|
514
|
+
P = R(0)
|
|
515
|
+
|
|
516
|
+
cdef long i, j, k
|
|
517
|
+
for i in range(anf.limbs):
|
|
518
|
+
if anf.bits[i]:
|
|
519
|
+
inf = i*sizeof(long)*8
|
|
520
|
+
sup = min((i+1)*sizeof(long)*8, (1<<self._nvariables))
|
|
521
|
+
for j in range(inf, sup):
|
|
522
|
+
if bitset_in(anf, j):
|
|
523
|
+
m = R(1)
|
|
524
|
+
for k in range(self._nvariables):
|
|
525
|
+
if (j>>k)&1:
|
|
526
|
+
m *= G[k]
|
|
527
|
+
P += m
|
|
528
|
+
bitset_free(anf)
|
|
529
|
+
return P
|
|
530
|
+
|
|
531
|
+
def nvariables(self):
|
|
532
|
+
"""
|
|
533
|
+
The number of variables of this function.
|
|
534
|
+
|
|
535
|
+
EXAMPLES::
|
|
536
|
+
|
|
537
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
538
|
+
sage: BooleanFunction(4).nvariables()
|
|
539
|
+
4
|
|
540
|
+
"""
|
|
541
|
+
return self._nvariables
|
|
542
|
+
|
|
543
|
+
def truth_table(self, format='bin'):
|
|
544
|
+
"""
|
|
545
|
+
The truth table of the Boolean function.
|
|
546
|
+
|
|
547
|
+
INPUT:
|
|
548
|
+
|
|
549
|
+
- ``format`` -- string representing the desired format; can be either
|
|
550
|
+
|
|
551
|
+
- ``'bin'`` -- (default) we return a tuple of Boolean values
|
|
552
|
+
- ``'int'`` -- we return a tuple of 0 or 1 values
|
|
553
|
+
- ``'hex'`` -- we return a string representing the truth table in
|
|
554
|
+
hexadecimal
|
|
555
|
+
|
|
556
|
+
EXAMPLES::
|
|
557
|
+
|
|
558
|
+
sage: # needs sage.rings.polynomial.pbori
|
|
559
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
560
|
+
sage: R.<x,y,z> = BooleanPolynomialRing(3)
|
|
561
|
+
sage: B = BooleanFunction(x*y*z + z + y + 1)
|
|
562
|
+
sage: B.truth_table()
|
|
563
|
+
(True, True, False, False, False, False, True, False)
|
|
564
|
+
sage: B.truth_table(format='int')
|
|
565
|
+
(1, 1, 0, 0, 0, 0, 1, 0)
|
|
566
|
+
sage: B.truth_table(format='hex')
|
|
567
|
+
'43'
|
|
568
|
+
|
|
569
|
+
sage: BooleanFunction('00ab').truth_table(format='hex') # needs sage.rings.polynomial.pbori
|
|
570
|
+
'00ab'
|
|
571
|
+
|
|
572
|
+
sage: # needs sage.rings.polynomial.pbori
|
|
573
|
+
sage: H = '0abbacadabbacad0'
|
|
574
|
+
sage: len(H)
|
|
575
|
+
16
|
|
576
|
+
sage: T = BooleanFunction(H).truth_table(format='hex')
|
|
577
|
+
sage: T == H
|
|
578
|
+
True
|
|
579
|
+
sage: H = H * 4
|
|
580
|
+
sage: T = BooleanFunction(H).truth_table(format='hex')
|
|
581
|
+
sage: T == H
|
|
582
|
+
True
|
|
583
|
+
sage: H = H * 4
|
|
584
|
+
sage: T = BooleanFunction(H).truth_table(format='hex')
|
|
585
|
+
sage: T == H
|
|
586
|
+
True
|
|
587
|
+
sage: len(T)
|
|
588
|
+
256
|
|
589
|
+
sage: B.truth_table(format='oct')
|
|
590
|
+
Traceback (most recent call last):
|
|
591
|
+
...
|
|
592
|
+
ValueError: unknown output format
|
|
593
|
+
"""
|
|
594
|
+
if format == 'bin':
|
|
595
|
+
return tuple(self)
|
|
596
|
+
if format == 'int':
|
|
597
|
+
return tuple(map(int, self))
|
|
598
|
+
if format == 'hex':
|
|
599
|
+
S = ZZ(self.truth_table(), 2).str(16)
|
|
600
|
+
S = "0"*((1<<(self._nvariables-2)) - len(S)) + S
|
|
601
|
+
return S
|
|
602
|
+
raise ValueError("unknown output format")
|
|
603
|
+
|
|
604
|
+
def __len__(self):
|
|
605
|
+
"""
|
|
606
|
+
Return the number of different input values.
|
|
607
|
+
|
|
608
|
+
EXAMPLES::
|
|
609
|
+
|
|
610
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
611
|
+
sage: len(BooleanFunction(4))
|
|
612
|
+
16
|
|
613
|
+
"""
|
|
614
|
+
return 2**self._nvariables
|
|
615
|
+
|
|
616
|
+
def __richcmp__(BooleanFunction self, other, int op):
|
|
617
|
+
"""
|
|
618
|
+
Boolean functions are considered to be equal if the number of
|
|
619
|
+
input variables is the same, and all the values are equal.
|
|
620
|
+
|
|
621
|
+
EXAMPLES::
|
|
622
|
+
|
|
623
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
624
|
+
sage: b1 = BooleanFunction([0,1,1,0])
|
|
625
|
+
sage: b2 = BooleanFunction([0,1,1,0])
|
|
626
|
+
sage: b3 = BooleanFunction([0,1,1,1])
|
|
627
|
+
sage: b4 = BooleanFunction([0,1])
|
|
628
|
+
sage: b1 == b2
|
|
629
|
+
True
|
|
630
|
+
sage: b1 == b3
|
|
631
|
+
False
|
|
632
|
+
sage: b1 == b4
|
|
633
|
+
False
|
|
634
|
+
"""
|
|
635
|
+
if not isinstance(other, BooleanFunction):
|
|
636
|
+
return NotImplemented
|
|
637
|
+
o = <BooleanFunction> other
|
|
638
|
+
return rich_to_bool(op, bitset_cmp(self._truth_table, o._truth_table))
|
|
639
|
+
|
|
640
|
+
def __call__(self, x):
|
|
641
|
+
"""
|
|
642
|
+
Return the value of the function for the given input.
|
|
643
|
+
|
|
644
|
+
INPUT:
|
|
645
|
+
|
|
646
|
+
- ``x`` -- either:
|
|
647
|
+
|
|
648
|
+
- a list: then all elements are evaluated as booleans
|
|
649
|
+
|
|
650
|
+
- an integer: then we consider its binary representation
|
|
651
|
+
|
|
652
|
+
EXAMPLES::
|
|
653
|
+
|
|
654
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
655
|
+
sage: B = BooleanFunction([0,1,0,0])
|
|
656
|
+
sage: B(1)
|
|
657
|
+
1
|
|
658
|
+
sage: B([1,0])
|
|
659
|
+
1
|
|
660
|
+
sage: B(4)
|
|
661
|
+
Traceback (most recent call last):
|
|
662
|
+
...
|
|
663
|
+
IndexError: index out of bound
|
|
664
|
+
"""
|
|
665
|
+
if isinstance(x, (int, Integer)):
|
|
666
|
+
if x >= self._truth_table.size:
|
|
667
|
+
raise IndexError("index out of bound")
|
|
668
|
+
return bitset_in(self._truth_table, <mp_bitcnt_t> x)
|
|
669
|
+
elif isinstance(x, list):
|
|
670
|
+
if len(x) != self._nvariables:
|
|
671
|
+
raise ValueError("bad number of inputs")
|
|
672
|
+
return self(ZZ([bool(_) for _ in x], 2))
|
|
673
|
+
else:
|
|
674
|
+
raise TypeError("cannot apply Boolean function to provided element")
|
|
675
|
+
|
|
676
|
+
def __iter__(self):
|
|
677
|
+
"""
|
|
678
|
+
Iterate through the value of the function.
|
|
679
|
+
|
|
680
|
+
EXAMPLES::
|
|
681
|
+
|
|
682
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
683
|
+
sage: B = BooleanFunction([0,1,1,0,1,0,1,0])
|
|
684
|
+
sage: [int(b) for b in B]
|
|
685
|
+
[0, 1, 1, 0, 1, 0, 1, 0]
|
|
686
|
+
"""
|
|
687
|
+
return BooleanFunctionIterator(self)
|
|
688
|
+
|
|
689
|
+
def _walsh_hadamard_transform_cached(self):
|
|
690
|
+
"""
|
|
691
|
+
Return the cached Walsh Hadamard transform. *Unsafe*, no check.
|
|
692
|
+
|
|
693
|
+
EXAMPLES::
|
|
694
|
+
|
|
695
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
696
|
+
sage: B = BooleanFunction(3)
|
|
697
|
+
sage: W = B.walsh_hadamard_transform()
|
|
698
|
+
sage: B._walsh_hadamard_transform_cached() is W
|
|
699
|
+
True
|
|
700
|
+
"""
|
|
701
|
+
return self._walsh_hadamard_transform
|
|
702
|
+
|
|
703
|
+
cpdef tuple walsh_hadamard_transform(self):
|
|
704
|
+
r"""
|
|
705
|
+
Compute the Walsh Hadamard transform `W` of the function `f`.
|
|
706
|
+
|
|
707
|
+
.. MATH:: W(j) = \sum_{i\in\{0,1\}^n} (-1)^{f(i)\oplus i \cdot j}
|
|
708
|
+
|
|
709
|
+
EXAMPLES::
|
|
710
|
+
|
|
711
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
712
|
+
sage: R.<x> = GF(2^3,'a')[] # needs sage.rings.finite_rings
|
|
713
|
+
sage: B = BooleanFunction(x^3) # needs sage.rings.finite_rings
|
|
714
|
+
sage: B.walsh_hadamard_transform() # needs sage.rings.finite_rings
|
|
715
|
+
(0, -4, 0, 4, 0, 4, 0, 4)
|
|
716
|
+
"""
|
|
717
|
+
cdef long *temp
|
|
718
|
+
cdef mp_bitcnt_t i, n
|
|
719
|
+
|
|
720
|
+
if self._walsh_hadamard_transform is None:
|
|
721
|
+
n = self._truth_table.size
|
|
722
|
+
temp = <long *>sig_malloc(sizeof(long)*n)
|
|
723
|
+
|
|
724
|
+
for i in range(n):
|
|
725
|
+
temp[i] = 1 - (bitset_in(self._truth_table, i) << 1)
|
|
726
|
+
|
|
727
|
+
walsh_hadamard(temp, self._nvariables)
|
|
728
|
+
self._walsh_hadamard_transform = tuple([temp[i] for i in range(n)])
|
|
729
|
+
sig_free(temp)
|
|
730
|
+
|
|
731
|
+
return self._walsh_hadamard_transform
|
|
732
|
+
|
|
733
|
+
def absolute_walsh_spectrum(self):
|
|
734
|
+
"""
|
|
735
|
+
Return the absolute Walsh spectrum fo the function.
|
|
736
|
+
|
|
737
|
+
EXAMPLES::
|
|
738
|
+
|
|
739
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
740
|
+
sage: B = BooleanFunction("7969817CC5893BA6AC326E47619F5AD0")
|
|
741
|
+
sage: sorted(B.absolute_walsh_spectrum().items())
|
|
742
|
+
[(0, 64), (16, 64)]
|
|
743
|
+
|
|
744
|
+
sage: B = BooleanFunction("0113077C165E76A8")
|
|
745
|
+
sage: B.absolute_walsh_spectrum()
|
|
746
|
+
{8: 64}
|
|
747
|
+
"""
|
|
748
|
+
d = {}
|
|
749
|
+
cdef long i
|
|
750
|
+
for i in self.walsh_hadamard_transform():
|
|
751
|
+
if abs(i) in d:
|
|
752
|
+
d[abs(i)] += 1
|
|
753
|
+
else:
|
|
754
|
+
d[abs(i)] = 1
|
|
755
|
+
return d
|
|
756
|
+
|
|
757
|
+
def is_balanced(self):
|
|
758
|
+
"""
|
|
759
|
+
Return ``True`` if the function takes the value ``True`` half of the time.
|
|
760
|
+
|
|
761
|
+
EXAMPLES::
|
|
762
|
+
|
|
763
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
764
|
+
sage: B = BooleanFunction(1)
|
|
765
|
+
sage: B.is_balanced()
|
|
766
|
+
False
|
|
767
|
+
sage: B[0] = True
|
|
768
|
+
sage: B.is_balanced()
|
|
769
|
+
True
|
|
770
|
+
"""
|
|
771
|
+
return self.walsh_hadamard_transform()[0] == 0
|
|
772
|
+
|
|
773
|
+
def is_symmetric(self):
|
|
774
|
+
"""
|
|
775
|
+
Return ``True`` if the function is symmetric, i.e. invariant under
|
|
776
|
+
permutation of its input bits.
|
|
777
|
+
|
|
778
|
+
Another way to see it is that the
|
|
779
|
+
output depends only on the Hamming weight of the input.
|
|
780
|
+
|
|
781
|
+
EXAMPLES::
|
|
782
|
+
|
|
783
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
784
|
+
sage: B = BooleanFunction(5)
|
|
785
|
+
sage: B[3] = 1
|
|
786
|
+
sage: B.is_symmetric()
|
|
787
|
+
False
|
|
788
|
+
sage: V_B = [0, 1, 1, 0, 1, 0]
|
|
789
|
+
sage: for i in srange(32): B[i] = V_B[i.popcount()]
|
|
790
|
+
sage: B.is_symmetric()
|
|
791
|
+
True
|
|
792
|
+
"""
|
|
793
|
+
cdef mp_bitcnt_t i
|
|
794
|
+
cdef list T = [self(2**i-1) for i in range(self._nvariables+1)]
|
|
795
|
+
for i in range(1 << self._nvariables):
|
|
796
|
+
sig_check()
|
|
797
|
+
if T[hamming_weight(i)] != bitset_in(self._truth_table, i):
|
|
798
|
+
return False
|
|
799
|
+
return True
|
|
800
|
+
|
|
801
|
+
def nonlinearity(self):
|
|
802
|
+
"""
|
|
803
|
+
Return the nonlinearity of the function.
|
|
804
|
+
|
|
805
|
+
This is the distance to the linear functions, or the number of
|
|
806
|
+
output ones need to change to obtain a linear function.
|
|
807
|
+
|
|
808
|
+
EXAMPLES::
|
|
809
|
+
|
|
810
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
811
|
+
sage: B = BooleanFunction(5)
|
|
812
|
+
sage: B[1] = B[3] = 1
|
|
813
|
+
sage: B.nonlinearity()
|
|
814
|
+
2
|
|
815
|
+
sage: B = BooleanFunction("0113077C165E76A8")
|
|
816
|
+
sage: B.nonlinearity()
|
|
817
|
+
28
|
|
818
|
+
"""
|
|
819
|
+
cdef long w
|
|
820
|
+
if self._nonlinearity is None:
|
|
821
|
+
self._nonlinearity = \
|
|
822
|
+
((1<<self._nvariables) - max(abs(w) for w in self.walsh_hadamard_transform())) >> 1
|
|
823
|
+
return self._nonlinearity
|
|
824
|
+
|
|
825
|
+
def is_bent(self):
|
|
826
|
+
"""
|
|
827
|
+
Return ``True`` if the function is bent.
|
|
828
|
+
|
|
829
|
+
EXAMPLES::
|
|
830
|
+
|
|
831
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
832
|
+
sage: B = BooleanFunction("0113077C165E76A8")
|
|
833
|
+
sage: B.is_bent()
|
|
834
|
+
True
|
|
835
|
+
"""
|
|
836
|
+
if (self._nvariables & 1):
|
|
837
|
+
return False
|
|
838
|
+
return self.nonlinearity() == ((1<<self._nvariables)-(1<<(self._nvariables//2)))>>1
|
|
839
|
+
|
|
840
|
+
def correlation_immunity(self):
|
|
841
|
+
"""
|
|
842
|
+
Return the maximum value `m` such that the function is
|
|
843
|
+
correlation immune of order `m`.
|
|
844
|
+
|
|
845
|
+
A Boolean function is said to be correlation immune of order
|
|
846
|
+
`m` if the output of the function is statistically
|
|
847
|
+
independent of the combination of any `m` of its inputs.
|
|
848
|
+
|
|
849
|
+
EXAMPLES::
|
|
850
|
+
|
|
851
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
852
|
+
sage: B = BooleanFunction("7969817CC5893BA6AC326E47619F5AD0")
|
|
853
|
+
sage: B.correlation_immunity()
|
|
854
|
+
2
|
|
855
|
+
"""
|
|
856
|
+
cdef long c, i
|
|
857
|
+
if self._correlation_immunity is None:
|
|
858
|
+
c = self._nvariables
|
|
859
|
+
W = self.walsh_hadamard_transform()
|
|
860
|
+
for i in range(len(W)):
|
|
861
|
+
sig_check()
|
|
862
|
+
if W[i]:
|
|
863
|
+
c = min(c, hamming_weight(i))
|
|
864
|
+
self._correlation_immunity = ZZ(c-1)
|
|
865
|
+
return self._correlation_immunity
|
|
866
|
+
|
|
867
|
+
def resiliency_order(self):
|
|
868
|
+
"""
|
|
869
|
+
Return the maximum value `m` such that the function is
|
|
870
|
+
resilient of order `m`.
|
|
871
|
+
|
|
872
|
+
A Boolean function is said to be resilient of order `m` if it
|
|
873
|
+
is balanced and correlation immune of order `m`.
|
|
874
|
+
|
|
875
|
+
If the function is not balanced, we return `-1`.
|
|
876
|
+
|
|
877
|
+
EXAMPLES::
|
|
878
|
+
|
|
879
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
880
|
+
sage: B = BooleanFunction("077CE5A2F8831A5DF8831A5D077CE5A26996699669699696669999665AA5A55A")
|
|
881
|
+
sage: B.resiliency_order()
|
|
882
|
+
3
|
|
883
|
+
"""
|
|
884
|
+
if not self.is_balanced():
|
|
885
|
+
return -1
|
|
886
|
+
return self.correlation_immunity()
|
|
887
|
+
|
|
888
|
+
def autocorrelation(self):
|
|
889
|
+
r"""
|
|
890
|
+
Return the autocorrelation of the function, defined by
|
|
891
|
+
|
|
892
|
+
.. MATH:: \Delta_f(j) = \sum_{i\in\{0,1\}^n} (-1)^{f(i)\oplus f(i\oplus j)}.
|
|
893
|
+
|
|
894
|
+
EXAMPLES::
|
|
895
|
+
|
|
896
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
897
|
+
sage: B = BooleanFunction("03")
|
|
898
|
+
sage: B.autocorrelation()
|
|
899
|
+
(8, 8, 0, 0, 0, 0, 0, 0)
|
|
900
|
+
"""
|
|
901
|
+
cdef long *temp
|
|
902
|
+
cdef long i
|
|
903
|
+
|
|
904
|
+
if self._autocorrelation is None:
|
|
905
|
+
n = self._truth_table.size
|
|
906
|
+
temp = <long *>sig_malloc(sizeof(long)*n)
|
|
907
|
+
W = self.walsh_hadamard_transform()
|
|
908
|
+
|
|
909
|
+
for i in range(n):
|
|
910
|
+
sig_check()
|
|
911
|
+
temp[i] = W[i]*W[i]
|
|
912
|
+
|
|
913
|
+
walsh_hadamard(temp, self._nvariables)
|
|
914
|
+
self._autocorrelation = tuple([temp[i] >> self._nvariables
|
|
915
|
+
for i in range(n)])
|
|
916
|
+
sig_free(temp)
|
|
917
|
+
|
|
918
|
+
return self._autocorrelation
|
|
919
|
+
|
|
920
|
+
def absolute_autocorrelation(self):
|
|
921
|
+
"""
|
|
922
|
+
Return the absolute autocorrelation of the function.
|
|
923
|
+
|
|
924
|
+
EXAMPLES::
|
|
925
|
+
|
|
926
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
927
|
+
sage: B = BooleanFunction("7969817CC5893BA6AC326E47619F5AD0")
|
|
928
|
+
sage: sorted(B.absolute_autocorrelation().items())
|
|
929
|
+
[(0, 33), (8, 58), (16, 28), (24, 6), (32, 2), (128, 1)]
|
|
930
|
+
"""
|
|
931
|
+
d = {}
|
|
932
|
+
cdef long i
|
|
933
|
+
for i in self.autocorrelation():
|
|
934
|
+
if abs(i) in d:
|
|
935
|
+
d[abs(i)] += 1
|
|
936
|
+
else:
|
|
937
|
+
d[abs(i)] = 1
|
|
938
|
+
return d
|
|
939
|
+
|
|
940
|
+
def absolute_indicator(self):
|
|
941
|
+
"""
|
|
942
|
+
Return the absolute indicator of the function.
|
|
943
|
+
|
|
944
|
+
The absolute indicator is defined as the maximal absolute value of
|
|
945
|
+
the autocorrelation.
|
|
946
|
+
|
|
947
|
+
EXAMPLES::
|
|
948
|
+
|
|
949
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
950
|
+
sage: B = BooleanFunction("7969817CC5893BA6AC326E47619F5AD0")
|
|
951
|
+
sage: B.absolute_indicator()
|
|
952
|
+
32
|
|
953
|
+
|
|
954
|
+
The old method's name contained a typo, it is deprecated::
|
|
955
|
+
|
|
956
|
+
sage: B.absolut_indicator()
|
|
957
|
+
doctest:warning
|
|
958
|
+
...
|
|
959
|
+
DeprecationWarning: absolut_indicator is deprecated. Please use absolute_indicator instead.
|
|
960
|
+
See https://github.com/sagemath/sage/issues/28001 for details.
|
|
961
|
+
32
|
|
962
|
+
"""
|
|
963
|
+
cdef long a
|
|
964
|
+
if self._absolute_indicator is None:
|
|
965
|
+
D = self.autocorrelation()
|
|
966
|
+
self._absolute_indicator = max([abs(a) for a in D[1:]])
|
|
967
|
+
return self._absolute_indicator
|
|
968
|
+
|
|
969
|
+
absolut_indicator = deprecated_function_alias(28001, absolute_indicator)
|
|
970
|
+
|
|
971
|
+
def sum_of_square_indicator(self):
|
|
972
|
+
"""
|
|
973
|
+
Return the sum of square indicator of the function.
|
|
974
|
+
|
|
975
|
+
EXAMPLES::
|
|
976
|
+
|
|
977
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
978
|
+
sage: B = BooleanFunction("7969817CC5893BA6AC326E47619F5AD0")
|
|
979
|
+
sage: B.sum_of_square_indicator()
|
|
980
|
+
32768
|
|
981
|
+
"""
|
|
982
|
+
cdef long a
|
|
983
|
+
if self._sum_of_square_indicator is None:
|
|
984
|
+
D = self.autocorrelation()
|
|
985
|
+
self._sum_of_square_indicator = sum(a**2 for a in D)
|
|
986
|
+
return self._sum_of_square_indicator
|
|
987
|
+
|
|
988
|
+
def annihilator(self, d, dim=False):
|
|
989
|
+
r"""
|
|
990
|
+
Return (if it exists) an annihilator of the boolean function of
|
|
991
|
+
degree at most `d`, that is a Boolean polynomial `g` such that
|
|
992
|
+
|
|
993
|
+
.. MATH::
|
|
994
|
+
|
|
995
|
+
f(x)g(x) = 0 \forall x.
|
|
996
|
+
|
|
997
|
+
INPUT:
|
|
998
|
+
|
|
999
|
+
- ``d`` -- integer
|
|
1000
|
+
- ``dim`` -- boolean (default: ``False``); if ``True``, return also
|
|
1001
|
+
the dimension of the annihilator vector space
|
|
1002
|
+
|
|
1003
|
+
EXAMPLES::
|
|
1004
|
+
|
|
1005
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1006
|
+
sage: f = BooleanFunction("7969817CC5893BA6AC326E47619F5AD0")
|
|
1007
|
+
sage: f.annihilator(1) is None # needs sage.rings.polynomial.pbori
|
|
1008
|
+
True
|
|
1009
|
+
sage: g = BooleanFunction(f.annihilator(3)) # needs sage.rings.polynomial.pbori
|
|
1010
|
+
sage: set(fi*g(i) for i,fi in enumerate(f)) # needs sage.rings.polynomial.pbori
|
|
1011
|
+
{0}
|
|
1012
|
+
"""
|
|
1013
|
+
# NOTE: this is a toy implementation
|
|
1014
|
+
from sage.rings.polynomial.polynomial_ring_constructor import BooleanPolynomialRing_constructor
|
|
1015
|
+
R = BooleanPolynomialRing_constructor(self._nvariables, 'x')
|
|
1016
|
+
G = R.gens()
|
|
1017
|
+
r = [R(1)]
|
|
1018
|
+
|
|
1019
|
+
from sage.modules.free_module_element import vector
|
|
1020
|
+
s = vector(self.truth_table()).support()
|
|
1021
|
+
|
|
1022
|
+
from sage.combinat.combination import Combinations
|
|
1023
|
+
from sage.misc.misc_c import prod
|
|
1024
|
+
|
|
1025
|
+
from sage.matrix.constructor import Matrix
|
|
1026
|
+
from sage.arith.misc import binomial
|
|
1027
|
+
M = Matrix(GF(2), sum(binomial(self._nvariables, i)
|
|
1028
|
+
for i in range(d+1)), len(s))
|
|
1029
|
+
|
|
1030
|
+
cdef long i
|
|
1031
|
+
for i in range(1, d+1):
|
|
1032
|
+
C = Combinations(self._nvariables, i)
|
|
1033
|
+
for c in C:
|
|
1034
|
+
sig_check()
|
|
1035
|
+
r.append(prod([G[i] for i in c]))
|
|
1036
|
+
|
|
1037
|
+
cdef BooleanFunction t
|
|
1038
|
+
|
|
1039
|
+
cdef long j
|
|
1040
|
+
cdef mp_bitcnt_t v
|
|
1041
|
+
|
|
1042
|
+
for i, m in enumerate(r):
|
|
1043
|
+
t = BooleanFunction(m)
|
|
1044
|
+
for j, v in enumerate(s):
|
|
1045
|
+
sig_check()
|
|
1046
|
+
M[i, j] = bitset_in(t._truth_table, v)
|
|
1047
|
+
|
|
1048
|
+
kg = M.kernel().gens()
|
|
1049
|
+
|
|
1050
|
+
if kg:
|
|
1051
|
+
res = sum([kg[0][i]*ri for i, ri in enumerate(r)])
|
|
1052
|
+
else:
|
|
1053
|
+
res = None
|
|
1054
|
+
|
|
1055
|
+
return (res, len(kg)) if dim else res
|
|
1056
|
+
|
|
1057
|
+
def algebraic_immunity(self, annihilator=False):
|
|
1058
|
+
"""
|
|
1059
|
+
Return the algebraic immunity of the Boolean function.
|
|
1060
|
+
|
|
1061
|
+
This is the smallest integer `i` such that there exists a
|
|
1062
|
+
nontrivial annihilator for ``self`` or ``~self``.
|
|
1063
|
+
|
|
1064
|
+
INPUT:
|
|
1065
|
+
|
|
1066
|
+
- ``annihilator`` -- boolean (default: ``False``); if ``True``,
|
|
1067
|
+
returns also an annihilator of minimal degree
|
|
1068
|
+
|
|
1069
|
+
EXAMPLES::
|
|
1070
|
+
|
|
1071
|
+
sage: # needs sage.rings.polynomial.pbori
|
|
1072
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1073
|
+
sage: R.<x0,x1,x2,x3,x4,x5> = BooleanPolynomialRing(6)
|
|
1074
|
+
sage: B = BooleanFunction(x0*x1 + x1*x2 + x2*x3 + x3*x4 + x4*x5)
|
|
1075
|
+
sage: B.algebraic_immunity(annihilator=True)
|
|
1076
|
+
(2, x0*x1 + x1*x2 + x2*x3 + x3*x4 + x4*x5 + 1)
|
|
1077
|
+
sage: B[0] += 1
|
|
1078
|
+
sage: B.algebraic_immunity()
|
|
1079
|
+
2
|
|
1080
|
+
|
|
1081
|
+
sage: # needs sage.rings.finite_rings sage.rings.polynomial.pbori
|
|
1082
|
+
sage: R.<x> = GF(2^8,'a')[]
|
|
1083
|
+
sage: B = BooleanFunction(x^31)
|
|
1084
|
+
sage: B.algebraic_immunity()
|
|
1085
|
+
4
|
|
1086
|
+
"""
|
|
1087
|
+
f = self
|
|
1088
|
+
g = ~self
|
|
1089
|
+
cdef long i
|
|
1090
|
+
for i in range(self._nvariables):
|
|
1091
|
+
for fun in [f, g]:
|
|
1092
|
+
A = fun.annihilator(i)
|
|
1093
|
+
if A is not None:
|
|
1094
|
+
if annihilator:
|
|
1095
|
+
return i, A
|
|
1096
|
+
else:
|
|
1097
|
+
return i
|
|
1098
|
+
assert False, "you just found a bug!"
|
|
1099
|
+
|
|
1100
|
+
def algebraic_degree(self):
|
|
1101
|
+
r"""
|
|
1102
|
+
Return the algebraic degree of this Boolean function.
|
|
1103
|
+
|
|
1104
|
+
The algebraic degree of a Boolean function is defined as the degree
|
|
1105
|
+
of its algebraic normal form. Note that the degree of the constant
|
|
1106
|
+
zero function is defined to be equal to `-1`.
|
|
1107
|
+
|
|
1108
|
+
EXAMPLES::
|
|
1109
|
+
|
|
1110
|
+
sage: # needs sage.rings.polynomial.pbori
|
|
1111
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1112
|
+
sage: B.<x0, x1, x2, x3> = BooleanPolynomialRing()
|
|
1113
|
+
sage: f = BooleanFunction(x1*x2 + x1*x2*x3 + x1)
|
|
1114
|
+
sage: f.algebraic_degree()
|
|
1115
|
+
3
|
|
1116
|
+
sage: g = BooleanFunction([0, 0])
|
|
1117
|
+
sage: g.algebraic_degree()
|
|
1118
|
+
-1
|
|
1119
|
+
"""
|
|
1120
|
+
return self.algebraic_normal_form().degree()
|
|
1121
|
+
|
|
1122
|
+
def is_plateaued(self):
|
|
1123
|
+
r"""
|
|
1124
|
+
Return ``True`` if this function is plateaued, i.e. its Walsh transform
|
|
1125
|
+
takes at most three values `0` and `\pm \lambda`, where `\lambda` is some
|
|
1126
|
+
positive integer.
|
|
1127
|
+
|
|
1128
|
+
EXAMPLES::
|
|
1129
|
+
|
|
1130
|
+
sage: # needs sage.rings.polynomial.pbori
|
|
1131
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1132
|
+
sage: R.<x0, x1, x2, x3> = BooleanPolynomialRing()
|
|
1133
|
+
sage: f = BooleanFunction(x0*x1 + x2 + x3)
|
|
1134
|
+
sage: f.walsh_hadamard_transform()
|
|
1135
|
+
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, -8)
|
|
1136
|
+
sage: f.is_plateaued()
|
|
1137
|
+
True
|
|
1138
|
+
"""
|
|
1139
|
+
W = self.absolute_walsh_spectrum()
|
|
1140
|
+
return (len(W) == 1) or (len(W) == 2 and 0 in W)
|
|
1141
|
+
|
|
1142
|
+
def is_linear_structure(self, val):
|
|
1143
|
+
r"""
|
|
1144
|
+
Return ``True`` if ``val`` is a linear structure of this Boolean
|
|
1145
|
+
function.
|
|
1146
|
+
|
|
1147
|
+
INPUT:
|
|
1148
|
+
|
|
1149
|
+
- ``val`` -- either an integer or a tuple/list of `\GF{2}` elements
|
|
1150
|
+
of length equal to the number of variables
|
|
1151
|
+
|
|
1152
|
+
.. SEEALSO::
|
|
1153
|
+
|
|
1154
|
+
:meth:`has_linear_structure`,
|
|
1155
|
+
:meth:`linear_structures`.
|
|
1156
|
+
|
|
1157
|
+
EXAMPLES::
|
|
1158
|
+
|
|
1159
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1160
|
+
sage: f = BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0])
|
|
1161
|
+
sage: f.is_linear_structure(1)
|
|
1162
|
+
True
|
|
1163
|
+
sage: l = [1, 0, 0, 1]
|
|
1164
|
+
sage: f.is_linear_structure(l)
|
|
1165
|
+
True
|
|
1166
|
+
sage: v = vector(GF(2), l)
|
|
1167
|
+
sage: f.is_linear_structure(v)
|
|
1168
|
+
True
|
|
1169
|
+
sage: f.is_linear_structure(7)
|
|
1170
|
+
False
|
|
1171
|
+
sage: f.is_linear_structure(20) # parameter is out of range
|
|
1172
|
+
Traceback (most recent call last):
|
|
1173
|
+
...
|
|
1174
|
+
IndexError: index out of range
|
|
1175
|
+
sage: v = vector(GF(3), [1, 0, 1, 1])
|
|
1176
|
+
sage: f.is_linear_structure(v)
|
|
1177
|
+
Traceback (most recent call last):
|
|
1178
|
+
...
|
|
1179
|
+
TypeError: base ring of input vector must be GF(2)
|
|
1180
|
+
sage: v = vector(GF(2), [1, 0, 1, 1, 1])
|
|
1181
|
+
sage: f.is_linear_structure(v)
|
|
1182
|
+
Traceback (most recent call last):
|
|
1183
|
+
...
|
|
1184
|
+
TypeError: input vector must be an element of a vector space with dimension 4
|
|
1185
|
+
sage: f.is_linear_structure('X') # failure case
|
|
1186
|
+
Traceback (most recent call last):
|
|
1187
|
+
...
|
|
1188
|
+
TypeError: cannot compute is_linear_structure() using parameter X
|
|
1189
|
+
"""
|
|
1190
|
+
from sage.structure.element import Vector
|
|
1191
|
+
nvars = self._nvariables
|
|
1192
|
+
|
|
1193
|
+
if isinstance(val, (tuple, list)):
|
|
1194
|
+
i = ZZ(val, base=2)
|
|
1195
|
+
elif isinstance(val, Vector):
|
|
1196
|
+
if val.base_ring() != GF(2):
|
|
1197
|
+
raise TypeError("base ring of input vector must be GF(2)")
|
|
1198
|
+
elif val.parent().dimension() != nvars:
|
|
1199
|
+
raise TypeError("input vector must be an element of a vector"
|
|
1200
|
+
" space with dimension %d" % (nvars,))
|
|
1201
|
+
i = ZZ(val.list(), base=2)
|
|
1202
|
+
else:
|
|
1203
|
+
i = val
|
|
1204
|
+
|
|
1205
|
+
a = self.autocorrelation()
|
|
1206
|
+
try:
|
|
1207
|
+
return abs(a[i]) == 1 << nvars
|
|
1208
|
+
except IndexError:
|
|
1209
|
+
raise IndexError("index out of range")
|
|
1210
|
+
except TypeError:
|
|
1211
|
+
raise TypeError("cannot compute is_linear_structure() using parameter %s" % (val,))
|
|
1212
|
+
|
|
1213
|
+
def has_linear_structure(self) -> bool:
|
|
1214
|
+
r"""
|
|
1215
|
+
Return ``True`` if this function has a linear structure.
|
|
1216
|
+
|
|
1217
|
+
An `n`-variable Boolean function `f` has a linear structure if
|
|
1218
|
+
there exists a nonzero `a \in \GF{2}^n` such that
|
|
1219
|
+
`f(x \oplus a) \oplus f(x)` is a constant function.
|
|
1220
|
+
|
|
1221
|
+
.. SEEALSO::
|
|
1222
|
+
|
|
1223
|
+
:meth:`is_linear_structure`,
|
|
1224
|
+
:meth:`linear_structures`.
|
|
1225
|
+
|
|
1226
|
+
EXAMPLES::
|
|
1227
|
+
|
|
1228
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1229
|
+
sage: f = BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0])
|
|
1230
|
+
sage: f.has_linear_structure()
|
|
1231
|
+
True
|
|
1232
|
+
sage: f.autocorrelation()
|
|
1233
|
+
(16, -16, 0, 0, 0, 0, 0, 0, -16, 16, 0, 0, 0, 0, 0, 0)
|
|
1234
|
+
sage: g = BooleanFunction([0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1])
|
|
1235
|
+
sage: g.has_linear_structure()
|
|
1236
|
+
False
|
|
1237
|
+
sage: g.autocorrelation()
|
|
1238
|
+
(16, 4, 4, 4, 4, -4, -4, -4, -4, 4, -4, -4, -4, 4, -4, -4)
|
|
1239
|
+
"""
|
|
1240
|
+
a = self.autocorrelation()
|
|
1241
|
+
nvars = self._nvariables
|
|
1242
|
+
cdef long i
|
|
1243
|
+
return any(abs(a[i]) == 1 << nvars for i in range(1, 1 << nvars))
|
|
1244
|
+
|
|
1245
|
+
def linear_structures(self):
|
|
1246
|
+
r"""
|
|
1247
|
+
Return all linear structures of this Boolean function as a
|
|
1248
|
+
vector subspace of `\GF{2}^n`.
|
|
1249
|
+
|
|
1250
|
+
.. SEEALSO::
|
|
1251
|
+
|
|
1252
|
+
:meth:`is_linear_structure`,
|
|
1253
|
+
:meth:`has_linear_structure`.
|
|
1254
|
+
|
|
1255
|
+
EXAMPLES::
|
|
1256
|
+
|
|
1257
|
+
sage: # needs sage.modules
|
|
1258
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1259
|
+
sage: f = BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0])
|
|
1260
|
+
sage: LS = f.linear_structures()
|
|
1261
|
+
sage: LS.dimension()
|
|
1262
|
+
2
|
|
1263
|
+
sage: LS.basis_matrix()
|
|
1264
|
+
[1 0 0 0]
|
|
1265
|
+
[0 0 0 1]
|
|
1266
|
+
sage: LS.list()
|
|
1267
|
+
[(0, 0, 0, 0), (1, 0, 0, 0), (0, 0, 0, 1), (1, 0, 0, 1)]
|
|
1268
|
+
"""
|
|
1269
|
+
from sage.modules.free_module import VectorSpace
|
|
1270
|
+
|
|
1271
|
+
cdef long i
|
|
1272
|
+
nvars = self.nvariables()
|
|
1273
|
+
a = self.autocorrelation()
|
|
1274
|
+
l = [ZZ(i).digits(base=2, padto=nvars) for i in range(1<<nvars) if abs(a[i]) == 1<<nvars]
|
|
1275
|
+
V = VectorSpace(GF(2), nvars)
|
|
1276
|
+
return V.subspace(l)
|
|
1277
|
+
|
|
1278
|
+
def derivative(self, u):
|
|
1279
|
+
r"""
|
|
1280
|
+
Return the derivative in direction of ``u``.
|
|
1281
|
+
|
|
1282
|
+
INPUT:
|
|
1283
|
+
|
|
1284
|
+
- ``u`` -- either an integer or a tuple/list of `\GF{2}` elements
|
|
1285
|
+
of length equal to the number of variables
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
The derivative of `f` in direction of `u` is defined as
|
|
1289
|
+
`x \mapsto f(x) + f(x + u)`.
|
|
1290
|
+
|
|
1291
|
+
EXAMPLES::
|
|
1292
|
+
|
|
1293
|
+
sage: # needs sage.rings.polynomial.pbori
|
|
1294
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1295
|
+
sage: f = BooleanFunction([0,1,0,1,0,1,0,1])
|
|
1296
|
+
sage: f.derivative(1).algebraic_normal_form()
|
|
1297
|
+
1
|
|
1298
|
+
sage: u = [1,0,0]
|
|
1299
|
+
sage: f.derivative(u).algebraic_normal_form()
|
|
1300
|
+
1
|
|
1301
|
+
sage: v = vector(GF(2), u) # needs sage.modules
|
|
1302
|
+
sage: f.derivative(v).algebraic_normal_form() # needs sage.modules
|
|
1303
|
+
1
|
|
1304
|
+
sage: f.derivative(8).algebraic_normal_form()
|
|
1305
|
+
Traceback (most recent call last):
|
|
1306
|
+
...
|
|
1307
|
+
IndexError: index out of bound
|
|
1308
|
+
"""
|
|
1309
|
+
from sage.structure.element import Vector
|
|
1310
|
+
nvars = self._nvariables
|
|
1311
|
+
|
|
1312
|
+
if isinstance(u, (tuple, list)):
|
|
1313
|
+
v = ZZ(u, base=2)
|
|
1314
|
+
elif isinstance(u, Vector):
|
|
1315
|
+
if u.base_ring() != GF(2):
|
|
1316
|
+
raise TypeError("base ring of input vector must be GF(2)")
|
|
1317
|
+
elif u.parent().dimension() != nvars:
|
|
1318
|
+
raise TypeError("input vector must be an element of a vector space with dimension %d" % (nvars,))
|
|
1319
|
+
v = ZZ(u.list(), base=2)
|
|
1320
|
+
else:
|
|
1321
|
+
v = u
|
|
1322
|
+
|
|
1323
|
+
return BooleanFunction([self(x) ^ self(x ^ v)
|
|
1324
|
+
for x in range(1 << nvars)])
|
|
1325
|
+
|
|
1326
|
+
def __setitem__(self, i, y):
|
|
1327
|
+
"""
|
|
1328
|
+
Set a value of the function.
|
|
1329
|
+
|
|
1330
|
+
EXAMPLES::
|
|
1331
|
+
|
|
1332
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1333
|
+
sage: B = BooleanFunction([0,0,1,1])
|
|
1334
|
+
sage: B[0] = 1
|
|
1335
|
+
sage: B[2] = (3**17 == 9)
|
|
1336
|
+
sage: [b for b in B]
|
|
1337
|
+
[True, False, False, True]
|
|
1338
|
+
|
|
1339
|
+
We take care to clear cached values::
|
|
1340
|
+
|
|
1341
|
+
sage: W = B.walsh_hadamard_transform()
|
|
1342
|
+
sage: B[2] = 1
|
|
1343
|
+
sage: B._walsh_hadamard_transform_cached() is None
|
|
1344
|
+
True
|
|
1345
|
+
"""
|
|
1346
|
+
self._clear_cache()
|
|
1347
|
+
bitset_set_to(self._truth_table, int(i), int(y)&1)
|
|
1348
|
+
|
|
1349
|
+
def __getitem__(self, i):
|
|
1350
|
+
"""
|
|
1351
|
+
Return the value of the function for the given input.
|
|
1352
|
+
|
|
1353
|
+
EXAMPLES::
|
|
1354
|
+
|
|
1355
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1356
|
+
sage: B = BooleanFunction([0,1,1,1])
|
|
1357
|
+
sage: [ int(B[i]) for i in range(len(B)) ]
|
|
1358
|
+
[0, 1, 1, 1]
|
|
1359
|
+
"""
|
|
1360
|
+
return self(i)
|
|
1361
|
+
|
|
1362
|
+
def _clear_cache(self):
|
|
1363
|
+
"""
|
|
1364
|
+
Clear cached values.
|
|
1365
|
+
|
|
1366
|
+
EXAMPLES::
|
|
1367
|
+
|
|
1368
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1369
|
+
sage: B = BooleanFunction([0,1,1,0])
|
|
1370
|
+
sage: W = B.walsh_hadamard_transform()
|
|
1371
|
+
sage: B._walsh_hadamard_transform_cached() is None
|
|
1372
|
+
False
|
|
1373
|
+
sage: B._clear_cache()
|
|
1374
|
+
sage: B._walsh_hadamard_transform_cached() is None
|
|
1375
|
+
True
|
|
1376
|
+
"""
|
|
1377
|
+
self._walsh_hadamard_transform = None
|
|
1378
|
+
self._nonlinearity = None
|
|
1379
|
+
self._correlation_immunity = None
|
|
1380
|
+
self._autocorrelation = None
|
|
1381
|
+
self._absolute_indicator = None
|
|
1382
|
+
self._sum_of_square_indicator = None
|
|
1383
|
+
|
|
1384
|
+
def __reduce__(self):
|
|
1385
|
+
"""
|
|
1386
|
+
EXAMPLES::
|
|
1387
|
+
|
|
1388
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1389
|
+
sage: B = BooleanFunction([0,1,1,0])
|
|
1390
|
+
sage: loads(dumps(B)) == B
|
|
1391
|
+
True
|
|
1392
|
+
"""
|
|
1393
|
+
return unpickle_BooleanFunction, (self.truth_table(format='hex'),)
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
def unpickle_BooleanFunction(bool_list):
|
|
1397
|
+
"""
|
|
1398
|
+
Specific function to unpickle Boolean functions.
|
|
1399
|
+
|
|
1400
|
+
EXAMPLES::
|
|
1401
|
+
|
|
1402
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1403
|
+
sage: B = BooleanFunction([0,1,1,0])
|
|
1404
|
+
sage: loads(dumps(B)) == B # indirect doctest
|
|
1405
|
+
True
|
|
1406
|
+
"""
|
|
1407
|
+
return BooleanFunction(bool_list)
|
|
1408
|
+
|
|
1409
|
+
|
|
1410
|
+
cdef class BooleanFunctionIterator:
|
|
1411
|
+
cdef long index, last
|
|
1412
|
+
cdef BooleanFunction f
|
|
1413
|
+
|
|
1414
|
+
def __init__(self, f):
|
|
1415
|
+
"""
|
|
1416
|
+
Iterator through the values of a Boolean function.
|
|
1417
|
+
|
|
1418
|
+
EXAMPLES::
|
|
1419
|
+
|
|
1420
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1421
|
+
sage: B = BooleanFunction(3)
|
|
1422
|
+
sage: type(B.__iter__())
|
|
1423
|
+
<class 'sage.crypto.boolean_function.BooleanFunctionIterator'>
|
|
1424
|
+
"""
|
|
1425
|
+
self.f = f
|
|
1426
|
+
self.index = -1
|
|
1427
|
+
self.last = self.f._truth_table.size-1
|
|
1428
|
+
|
|
1429
|
+
def __iter__(self):
|
|
1430
|
+
"""
|
|
1431
|
+
Iterator through the values of a Boolean function.
|
|
1432
|
+
|
|
1433
|
+
EXAMPLES::
|
|
1434
|
+
|
|
1435
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1436
|
+
sage: B = BooleanFunction(1)
|
|
1437
|
+
sage: [b for b in B] # indirect doctest
|
|
1438
|
+
[False, False]
|
|
1439
|
+
"""
|
|
1440
|
+
return self
|
|
1441
|
+
|
|
1442
|
+
def __next__(self):
|
|
1443
|
+
"""
|
|
1444
|
+
Next value.
|
|
1445
|
+
|
|
1446
|
+
EXAMPLES::
|
|
1447
|
+
|
|
1448
|
+
sage: from sage.crypto.boolean_function import BooleanFunction
|
|
1449
|
+
sage: B = BooleanFunction(1)
|
|
1450
|
+
sage: I = B.__iter__()
|
|
1451
|
+
sage: next(I)
|
|
1452
|
+
False
|
|
1453
|
+
"""
|
|
1454
|
+
if self.index == self.last:
|
|
1455
|
+
raise StopIteration
|
|
1456
|
+
self.index += 1
|
|
1457
|
+
return bitset_in(self.f._truth_table, self.index)
|
|
1458
|
+
|
|
1459
|
+
##########################################
|
|
1460
|
+
# Below we provide some constructions of #
|
|
1461
|
+
# cryptographic Boolean function. #
|
|
1462
|
+
##########################################
|
|
1463
|
+
|
|
1464
|
+
|
|
1465
|
+
def random_boolean_function(n):
|
|
1466
|
+
"""
|
|
1467
|
+
Return a random Boolean function with `n` variables.
|
|
1468
|
+
|
|
1469
|
+
EXAMPLES::
|
|
1470
|
+
|
|
1471
|
+
sage: from sage.crypto.boolean_function import random_boolean_function
|
|
1472
|
+
sage: B = random_boolean_function(9)
|
|
1473
|
+
sage: B.nvariables()
|
|
1474
|
+
9
|
|
1475
|
+
sage: while not (210 < B.nonlinearity() < 220):
|
|
1476
|
+
....: B = random_boolean_function(9)
|
|
1477
|
+
"""
|
|
1478
|
+
from sage.misc.randstate import current_randstate
|
|
1479
|
+
r = current_randstate().python_random()
|
|
1480
|
+
cdef BooleanFunction B = BooleanFunction(n)
|
|
1481
|
+
cdef bitset_t T
|
|
1482
|
+
cdef long i
|
|
1483
|
+
T[0] = B._truth_table[0]
|
|
1484
|
+
for i in range(T.limbs):
|
|
1485
|
+
sig_check()
|
|
1486
|
+
T.bits[i] = r.randrange(0, Integer(1)<<(sizeof(unsigned long)*8))
|
|
1487
|
+
return B
|