passagemath-flint 10.6.1rc10__cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_flint-10.6.1rc10.dist-info/METADATA +122 -0
- passagemath_flint-10.6.1rc10.dist-info/RECORD +360 -0
- passagemath_flint-10.6.1rc10.dist-info/WHEEL +6 -0
- passagemath_flint-10.6.1rc10.dist-info/top_level.txt +2 -0
- passagemath_flint.libs/libflint-3701249d.so.21.0.0 +0 -0
- passagemath_flint.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
- passagemath_flint.libs/libgfortran-8a9a71bc.so.5.0.0 +0 -0
- passagemath_flint.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
- passagemath_flint.libs/libgsl-e3525837.so.28.0.0 +0 -0
- passagemath_flint.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
- passagemath_flint.libs/libmpfr-e0f11cf3.so.6.2.1 +0 -0
- passagemath_flint.libs/libntl-1004113e.so.44.0.1 +0 -0
- passagemath_flint.libs/libopenblasp-r0-4c5b64b1.3.29.so +0 -0
- sage/all__sagemath_flint.py +29 -0
- sage/combinat/all__sagemath_flint.py +1 -0
- sage/combinat/posets/all__sagemath_flint.py +1 -0
- sage/combinat/posets/hasse_cython_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/hasse_cython_flint.pyx +194 -0
- sage/data_structures/all__sagemath_flint.py +1 -0
- sage/data_structures/bounded_integer_sequences.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/data_structures/bounded_integer_sequences.pxd +62 -0
- sage/data_structures/bounded_integer_sequences.pyx +1418 -0
- sage/graphs/all__sagemath_flint.py +1 -0
- sage/graphs/chrompoly.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/graphs/chrompoly.pyx +555 -0
- sage/graphs/matchpoly.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/graphs/matchpoly.pyx +412 -0
- sage/libs/all__sagemath_flint.py +17 -0
- sage/libs/arb/__init__.py +1 -0
- sage/libs/arb/acb.pxd +154 -0
- sage/libs/arb/acb_calc.pxd +9 -0
- sage/libs/arb/acb_elliptic.pxd +25 -0
- sage/libs/arb/acb_hypgeom.pxd +74 -0
- sage/libs/arb/acb_mat.pxd +62 -0
- sage/libs/arb/acb_modular.pxd +17 -0
- sage/libs/arb/acb_poly.pxd +216 -0
- sage/libs/arb/arb.pxd +240 -0
- sage/libs/arb/arb_fmpz_poly.pxd +21 -0
- sage/libs/arb/arb_hypgeom.pxd +83 -0
- sage/libs/arb/arb_wrap.h +34 -0
- sage/libs/arb/arf.pxd +131 -0
- sage/libs/arb/arith.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/arb/arith.pyx +87 -0
- sage/libs/arb/bernoulli.pxd +6 -0
- sage/libs/arb/mag.pxd +77 -0
- sage/libs/arb/types.pxd +37 -0
- sage/libs/flint/__init__.py +1 -0
- sage/libs/flint/acb.pxd +270 -0
- sage/libs/flint/acb_calc.pxd +22 -0
- sage/libs/flint/acb_dft.pxd +51 -0
- sage/libs/flint/acb_dirichlet.pxd +112 -0
- sage/libs/flint/acb_elliptic.pxd +42 -0
- sage/libs/flint/acb_hypgeom.pxd +169 -0
- sage/libs/flint/acb_macros.pxd +9 -0
- sage/libs/flint/acb_mat.pxd +136 -0
- sage/libs/flint/acb_mat_macros.pxd +10 -0
- sage/libs/flint/acb_modular.pxd +62 -0
- sage/libs/flint/acb_poly.pxd +251 -0
- sage/libs/flint/acb_poly_macros.pxd +8 -0
- sage/libs/flint/acb_theta.pxd +124 -0
- sage/libs/flint/acf.pxd +32 -0
- sage/libs/flint/aprcl.pxd +84 -0
- sage/libs/flint/arb.pxd +382 -0
- sage/libs/flint/arb_calc.pxd +31 -0
- sage/libs/flint/arb_fmpz_poly.pxd +34 -0
- sage/libs/flint/arb_fpwrap.pxd +215 -0
- sage/libs/flint/arb_hypgeom.pxd +147 -0
- sage/libs/flint/arb_macros.pxd +9 -0
- sage/libs/flint/arb_mat.pxd +140 -0
- sage/libs/flint/arb_mat_macros.pxd +10 -0
- sage/libs/flint/arb_poly.pxd +237 -0
- sage/libs/flint/arf.pxd +167 -0
- sage/libs/flint/arith.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/arith.pxd +76 -0
- sage/libs/flint/arith.pyx +77 -0
- sage/libs/flint/arith_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/arith_sage.pyx +308 -0
- sage/libs/flint/bernoulli.pxd +28 -0
- sage/libs/flint/bool_mat.pxd +52 -0
- sage/libs/flint/ca.pxd +203 -0
- sage/libs/flint/ca_ext.pxd +34 -0
- sage/libs/flint/ca_field.pxd +32 -0
- sage/libs/flint/ca_mat.pxd +117 -0
- sage/libs/flint/ca_poly.pxd +104 -0
- sage/libs/flint/ca_vec.pxd +46 -0
- sage/libs/flint/calcium.pxd +27 -0
- sage/libs/flint/d_mat.pxd +39 -0
- sage/libs/flint/d_vec.pxd +32 -0
- sage/libs/flint/dirichlet.pxd +57 -0
- sage/libs/flint/dlog.pxd +53 -0
- sage/libs/flint/double_extras.pxd +24 -0
- sage/libs/flint/double_interval.pxd +36 -0
- sage/libs/flint/fexpr.pxd +104 -0
- sage/libs/flint/fexpr_builtin.pxd +20 -0
- sage/libs/flint/fft.pxd +66 -0
- sage/libs/flint/flint.pxd +36 -0
- sage/libs/flint/flint_ntl_wrap.h +35 -0
- sage/libs/flint/flint_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/flint_sage.pyx +163 -0
- sage/libs/flint/flint_wrap.h +190 -0
- sage/libs/flint/fmpq.pxd +137 -0
- sage/libs/flint/fmpq_mat.pxd +105 -0
- sage/libs/flint/fmpq_mat_macros.pxd +10 -0
- sage/libs/flint/fmpq_mpoly.pxd +165 -0
- sage/libs/flint/fmpq_mpoly_factor.pxd +30 -0
- sage/libs/flint/fmpq_poly.pxd +241 -0
- sage/libs/flint/fmpq_poly_macros.pxd +9 -0
- sage/libs/flint/fmpq_poly_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/fmpq_poly_sage.pxd +31 -0
- sage/libs/flint/fmpq_poly_sage.pyx +48 -0
- sage/libs/flint/fmpq_vec.pxd +27 -0
- sage/libs/flint/fmpz.pxd +256 -0
- sage/libs/flint/fmpz_extras.pxd +32 -0
- sage/libs/flint/fmpz_factor.pxd +42 -0
- sage/libs/flint/fmpz_factor_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_factor_sage.pxd +4 -0
- sage/libs/flint/fmpz_factor_sage.pyx +29 -0
- sage/libs/flint/fmpz_lll.pxd +49 -0
- sage/libs/flint/fmpz_macros.pxd +8 -0
- sage/libs/flint/fmpz_mat.pxd +184 -0
- sage/libs/flint/fmpz_mat_macros.pxd +10 -0
- sage/libs/flint/fmpz_mod.pxd +46 -0
- sage/libs/flint/fmpz_mod_mat.pxd +71 -0
- sage/libs/flint/fmpz_mod_mpoly.pxd +161 -0
- sage/libs/flint/fmpz_mod_mpoly_factor.pxd +28 -0
- sage/libs/flint/fmpz_mod_poly.pxd +249 -0
- sage/libs/flint/fmpz_mod_poly_factor.pxd +46 -0
- sage/libs/flint/fmpz_mod_vec.pxd +27 -0
- sage/libs/flint/fmpz_mpoly.pxd +224 -0
- sage/libs/flint/fmpz_mpoly_factor.pxd +29 -0
- sage/libs/flint/fmpz_mpoly_q.pxd +57 -0
- sage/libs/flint/fmpz_poly.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_poly.pxd +407 -0
- sage/libs/flint/fmpz_poly.pyx +19 -0
- sage/libs/flint/fmpz_poly_factor.pxd +33 -0
- sage/libs/flint/fmpz_poly_macros.pxd +8 -0
- sage/libs/flint/fmpz_poly_mat.pxd +71 -0
- sage/libs/flint/fmpz_poly_q.pxd +55 -0
- sage/libs/flint/fmpz_poly_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_poly_sage.pxd +20 -0
- sage/libs/flint/fmpz_poly_sage.pyx +500 -0
- sage/libs/flint/fmpz_vec.pxd +80 -0
- sage/libs/flint/fmpzi.pxd +52 -0
- sage/libs/flint/fq.pxd +97 -0
- sage/libs/flint/fq_default.pxd +84 -0
- sage/libs/flint/fq_default_mat.pxd +70 -0
- sage/libs/flint/fq_default_poly.pxd +97 -0
- sage/libs/flint/fq_default_poly_factor.pxd +39 -0
- sage/libs/flint/fq_embed.pxd +28 -0
- sage/libs/flint/fq_mat.pxd +83 -0
- sage/libs/flint/fq_nmod.pxd +95 -0
- sage/libs/flint/fq_nmod_embed.pxd +28 -0
- sage/libs/flint/fq_nmod_mat.pxd +83 -0
- sage/libs/flint/fq_nmod_mpoly.pxd +130 -0
- sage/libs/flint/fq_nmod_mpoly_factor.pxd +28 -0
- sage/libs/flint/fq_nmod_poly.pxd +202 -0
- sage/libs/flint/fq_nmod_poly_factor.pxd +47 -0
- sage/libs/flint/fq_nmod_vec.pxd +33 -0
- sage/libs/flint/fq_poly.pxd +204 -0
- sage/libs/flint/fq_poly_factor.pxd +47 -0
- sage/libs/flint/fq_vec.pxd +33 -0
- sage/libs/flint/fq_zech.pxd +99 -0
- sage/libs/flint/fq_zech_embed.pxd +28 -0
- sage/libs/flint/fq_zech_mat.pxd +78 -0
- sage/libs/flint/fq_zech_poly.pxd +198 -0
- sage/libs/flint/fq_zech_poly_factor.pxd +47 -0
- sage/libs/flint/fq_zech_vec.pxd +33 -0
- sage/libs/flint/gr.pxd +174 -0
- sage/libs/flint/gr_generic.pxd +215 -0
- sage/libs/flint/gr_mat.pxd +161 -0
- sage/libs/flint/gr_mpoly.pxd +68 -0
- sage/libs/flint/gr_poly.pxd +276 -0
- sage/libs/flint/gr_special.pxd +237 -0
- sage/libs/flint/gr_vec.pxd +120 -0
- sage/libs/flint/hypgeom.pxd +24 -0
- sage/libs/flint/long_extras.pxd +23 -0
- sage/libs/flint/mag.pxd +131 -0
- sage/libs/flint/mag_macros.pxd +8 -0
- sage/libs/flint/mpf_mat.pxd +36 -0
- sage/libs/flint/mpf_vec.pxd +34 -0
- sage/libs/flint/mpfr_mat.pxd +27 -0
- sage/libs/flint/mpfr_vec.pxd +25 -0
- sage/libs/flint/mpn_extras.pxd +41 -0
- sage/libs/flint/mpoly.pxd +72 -0
- sage/libs/flint/nf.pxd +19 -0
- sage/libs/flint/nf_elem.pxd +74 -0
- sage/libs/flint/nmod.pxd +35 -0
- sage/libs/flint/nmod_mat.pxd +104 -0
- sage/libs/flint/nmod_mpoly.pxd +144 -0
- sage/libs/flint/nmod_mpoly_factor.pxd +28 -0
- sage/libs/flint/nmod_poly.pxd +339 -0
- sage/libs/flint/nmod_poly_factor.pxd +44 -0
- sage/libs/flint/nmod_poly_linkage.pxi +710 -0
- sage/libs/flint/nmod_poly_mat.pxd +76 -0
- sage/libs/flint/nmod_vec.pxd +40 -0
- sage/libs/flint/ntl_interface.pxd +17 -0
- sage/libs/flint/padic.pxd +93 -0
- sage/libs/flint/padic_mat.pxd +64 -0
- sage/libs/flint/padic_poly.pxd +88 -0
- sage/libs/flint/partitions.pxd +23 -0
- sage/libs/flint/perm.pxd +26 -0
- sage/libs/flint/profiler.pxd +24 -0
- sage/libs/flint/qadic.pxd +77 -0
- sage/libs/flint/qfb.pxd +44 -0
- sage/libs/flint/qqbar.pxd +172 -0
- sage/libs/flint/qsieve.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/qsieve.pxd +41 -0
- sage/libs/flint/qsieve.pyx +21 -0
- sage/libs/flint/qsieve_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/qsieve_sage.pyx +67 -0
- sage/libs/flint/thread_pool.pxd +25 -0
- sage/libs/flint/types.pxd +2076 -0
- sage/libs/flint/ulong_extras.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/ulong_extras.pxd +141 -0
- sage/libs/flint/ulong_extras.pyx +21 -0
- sage/libs/flint/ulong_extras_sage.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/libs/flint/ulong_extras_sage.pyx +21 -0
- sage/matrix/all__sagemath_flint.py +1 -0
- sage/matrix/change_ring.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/change_ring.pyx +43 -0
- sage/matrix/matrix_complex_ball_dense.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_complex_ball_dense.pxd +14 -0
- sage/matrix/matrix_complex_ball_dense.pyx +973 -0
- sage/matrix/matrix_cyclo_dense.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_cyclo_dense.pxd +16 -0
- sage/matrix/matrix_cyclo_dense.pyx +1761 -0
- sage/matrix/matrix_integer_dense.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_dense.pxd +32 -0
- sage/matrix/matrix_integer_dense.pyx +5801 -0
- sage/matrix/matrix_integer_dense_hnf.py +1294 -0
- sage/matrix/matrix_integer_dense_saturation.py +346 -0
- sage/matrix/matrix_integer_sparse.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_sparse.pxd +9 -0
- sage/matrix/matrix_integer_sparse.pyx +1090 -0
- sage/matrix/matrix_rational_dense.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_rational_dense.pxd +23 -0
- sage/matrix/matrix_rational_dense.pyx +2995 -0
- sage/matrix/matrix_rational_sparse.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_rational_sparse.pxd +11 -0
- sage/matrix/matrix_rational_sparse.pyx +789 -0
- sage/matrix/misc_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/matrix/misc_flint.pyx +109 -0
- sage/modular/all__sagemath_flint.py +1 -0
- sage/modular/modform/all__sagemath_flint.py +1 -0
- sage/modular/modform/eis_series_cython.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/modular/modform/eis_series_cython.pyx +226 -0
- sage/modular/modsym/all__sagemath_flint.py +1 -0
- sage/modular/modsym/apply.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/modular/modsym/apply.pxd +6 -0
- sage/modular/modsym/apply.pyx +113 -0
- sage/modular/modsym/heilbronn.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/modular/modsym/heilbronn.pyx +966 -0
- sage/modular/pollack_stevens/all__sagemath_flint.py +1 -0
- sage/modular/pollack_stevens/dist.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/modular/pollack_stevens/dist.pxd +38 -0
- sage/modular/pollack_stevens/dist.pyx +1439 -0
- sage/quivers/algebra.py +691 -0
- sage/quivers/algebra_elements.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/quivers/algebra_elements.pxd +97 -0
- sage/quivers/algebra_elements.pxi +1324 -0
- sage/quivers/algebra_elements.pyx +1424 -0
- sage/quivers/all.py +1 -0
- sage/quivers/ar_quiver.py +917 -0
- sage/quivers/homspace.py +640 -0
- sage/quivers/morphism.py +1282 -0
- sage/quivers/path_semigroup.py +1155 -0
- sage/quivers/paths.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/quivers/paths.pxd +13 -0
- sage/quivers/paths.pyx +809 -0
- sage/quivers/representation.py +2975 -0
- sage/rings/all__sagemath_flint.py +37 -0
- sage/rings/cif.py +4 -0
- sage/rings/complex_arb.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/complex_arb.pxd +29 -0
- sage/rings/complex_arb.pyx +5176 -0
- sage/rings/complex_interval.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/complex_interval.pxd +30 -0
- sage/rings/complex_interval.pyx +2475 -0
- sage/rings/complex_interval_field.py +711 -0
- sage/rings/convert/all.py +1 -0
- sage/rings/convert/mpfi.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/convert/mpfi.pxd +6 -0
- sage/rings/convert/mpfi.pyx +576 -0
- sage/rings/factorint_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/factorint_flint.pyx +99 -0
- sage/rings/fraction_field_FpT.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/fraction_field_FpT.pxd +28 -0
- sage/rings/fraction_field_FpT.pyx +2043 -0
- sage/rings/imaginary_unit.py +5 -0
- sage/rings/monomials.py +73 -0
- sage/rings/number_field/S_unit_solver.py +2870 -0
- sage/rings/number_field/all__sagemath_flint.py +7 -0
- sage/rings/number_field/bdd_height.py +664 -0
- sage/rings/number_field/class_group.py +762 -0
- sage/rings/number_field/galois_group.py +1307 -0
- sage/rings/number_field/homset.py +612 -0
- sage/rings/number_field/maps.py +687 -0
- sage/rings/number_field/morphism.py +272 -0
- sage/rings/number_field/number_field.py +12820 -0
- sage/rings/number_field/number_field_element.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_element.pxd +59 -0
- sage/rings/number_field/number_field_element.pyx +5735 -0
- sage/rings/number_field/number_field_element_quadratic.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_element_quadratic.pxd +34 -0
- sage/rings/number_field/number_field_element_quadratic.pyx +3185 -0
- sage/rings/number_field/number_field_ideal_rel.py +925 -0
- sage/rings/number_field/number_field_morphisms.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_morphisms.pyx +781 -0
- sage/rings/number_field/number_field_rel.py +2734 -0
- sage/rings/number_field/order.py +2981 -0
- sage/rings/number_field/order_ideal.py +804 -0
- sage/rings/number_field/selmer_group.py +715 -0
- sage/rings/number_field/small_primes_of_degree_one.py +242 -0
- sage/rings/number_field/splitting_field.py +606 -0
- sage/rings/number_field/structure.py +380 -0
- sage/rings/number_field/unit_group.py +721 -0
- sage/rings/padics/all__sagemath_flint.py +3 -0
- sage/rings/polynomial/all__sagemath_flint.py +1 -0
- sage/rings/polynomial/complex_roots.py +312 -0
- sage/rings/polynomial/evaluation_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/evaluation_flint.pxd +7 -0
- sage/rings/polynomial/evaluation_flint.pyx +68 -0
- sage/rings/polynomial/hilbert.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/hilbert.pyx +602 -0
- sage/rings/polynomial/polynomial_complex_arb.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_complex_arb.pxd +7 -0
- sage/rings/polynomial/polynomial_complex_arb.pyx +963 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.pxd +13 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.pyx +1881 -0
- sage/rings/polynomial/polynomial_number_field.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_number_field.pyx +345 -0
- sage/rings/polynomial/polynomial_rational_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_rational_flint.pxd +20 -0
- sage/rings/polynomial/polynomial_rational_flint.pyx +2598 -0
- sage/rings/polynomial/polynomial_zmod_flint.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_zmod_flint.pxd +20 -0
- sage/rings/polynomial/polynomial_zmod_flint.pyx +1063 -0
- sage/rings/polynomial/real_roots.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/real_roots.pxd +81 -0
- sage/rings/polynomial/real_roots.pyx +4704 -0
- sage/rings/polynomial/refine_root.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/refine_root.pyx +142 -0
- sage/rings/polynomial/weil/all.py +4 -0
- sage/rings/polynomial/weil/power_sums.h +46 -0
- sage/rings/polynomial/weil/weil_polynomials.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/weil/weil_polynomials.pyx +596 -0
- sage/rings/qqbar.py +9025 -0
- sage/rings/real_arb.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/real_arb.pxd +21 -0
- sage/rings/real_arb.pyx +4065 -0
- sage/rings/real_interval_absolute.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/real_interval_absolute.pyx +1073 -0
- sage/rings/real_mpfi.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/rings/real_mpfi.pyx +5428 -0
- sage/schemes/all__sagemath_flint.py +1 -0
- sage/schemes/elliptic_curves/all__sagemath_flint.py +1 -0
- sage/schemes/elliptic_curves/descent_two_isogeny.cpython-313-aarch64-linux-gnu.so +0 -0
- sage/schemes/elliptic_curves/descent_two_isogeny.pyx +1387 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.pxd +5 -0
@@ -0,0 +1,1324 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-flint
|
2
|
+
# sage.doctest: needs sage.graphs
|
3
|
+
"""
|
4
|
+
Boilerplate functions for a cython implementation of elements of path algebras
|
5
|
+
|
6
|
+
AUTHORS:
|
7
|
+
|
8
|
+
- Simon King (2015-08)
|
9
|
+
"""
|
10
|
+
|
11
|
+
# ****************************************************************************
|
12
|
+
# Copyright (C) 2015 Simon King <simon.king@uni-jena.de>
|
13
|
+
#
|
14
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
15
|
+
# as published by the Free Software Foundation; either version 2 of
|
16
|
+
# the License, or (at your option) any later version.
|
17
|
+
# https://www.gnu.org/licenses/
|
18
|
+
# ****************************************************************************
|
19
|
+
|
20
|
+
from cysignals.memory cimport check_malloc, check_allocarray, sig_free
|
21
|
+
from cysignals.signals cimport sig_check, sig_on, sig_off
|
22
|
+
|
23
|
+
from cpython.ref cimport *
|
24
|
+
from cython.operator cimport predecrement as predec, postincrement as postinc
|
25
|
+
|
26
|
+
from sage.data_structures.bitset_base cimport *
|
27
|
+
from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool
|
28
|
+
from sage.libs.gmp.mpn cimport mpn_cmp
|
29
|
+
from libc.stdlib cimport free
|
30
|
+
|
31
|
+
cdef extern from *: # Defined by Cython
|
32
|
+
int unlikely(int) nogil
|
33
|
+
int likely(int) nogil
|
34
|
+
|
35
|
+
########################################
|
36
|
+
#
|
37
|
+
# Allocation and Deallocation of monomials
|
38
|
+
#
|
39
|
+
# Monomials are expensive, hence, copying will just be done by increasing a
|
40
|
+
# reference counter.
|
41
|
+
|
42
|
+
# Create a monomial by copying the given bounded integer sequence
|
43
|
+
cdef bint mon_create(path_mon_t out, biseq_t Mon, long Pos, mp_size_t L_len, mp_size_t S_len) except -1:
|
44
|
+
biseq_init_copy(out.path, Mon)
|
45
|
+
out.pos = Pos
|
46
|
+
out.l_len = L_len
|
47
|
+
out.s_len = S_len
|
48
|
+
|
49
|
+
# The following is only used in the free-list for terms.
|
50
|
+
# It changes an existing monomial in-place (which should NEVER
|
51
|
+
# be done on a monomial that is in use), re-allocating memory
|
52
|
+
# and filling it with a copy of the given bounded integer sequence.
|
53
|
+
cdef bint mon_realloc(path_mon_t out, biseq_t Mon, long Pos, mp_size_t L_len, mp_size_t S_len) except -1:
|
54
|
+
biseq_dealloc(out.path)
|
55
|
+
sig_check()
|
56
|
+
biseq_init_copy(out.path, Mon)
|
57
|
+
out.pos = Pos
|
58
|
+
out.l_len = L_len
|
59
|
+
out.s_len = S_len
|
60
|
+
|
61
|
+
# Create a monomial without copying the given bounded integer sequence
|
62
|
+
cdef bint mon_create_keep(path_mon_t out, biseq_t Mon, long Pos, mp_size_t L_len, mp_size_t S_len) except -1:
|
63
|
+
out.path[0] = Mon[0]
|
64
|
+
out.pos = Pos
|
65
|
+
out.l_len = L_len
|
66
|
+
out.s_len = S_len
|
67
|
+
|
68
|
+
# The following is only used in the free-list for terms.
|
69
|
+
# It changes an existing monomial in-place (which should NEVER
|
70
|
+
# be done on a monomial that is in use), re-allocating memory
|
71
|
+
# and filling it with the given bounded integer sequence (not a copy).
|
72
|
+
cdef bint mon_realloc_keep(path_mon_t out, biseq_t Mon, long Pos, mp_size_t L_len, mp_size_t S_len) noexcept:
|
73
|
+
biseq_dealloc(out.path)
|
74
|
+
out.path[0] = Mon[0]
|
75
|
+
out.pos = Pos
|
76
|
+
out.l_len = L_len
|
77
|
+
out.s_len = S_len
|
78
|
+
return True
|
79
|
+
|
80
|
+
cdef inline bint mon_copy(path_mon_t out, path_mon_t M) except -1:
|
81
|
+
out.pos = M.pos
|
82
|
+
out.l_len = M.l_len
|
83
|
+
out.s_len = M.s_len
|
84
|
+
biseq_init_copy(out.path, M.path)
|
85
|
+
|
86
|
+
# Deallocate the monomial, which means to decrease the reference count,
|
87
|
+
# or to actually deallocate the data if there is no reference left.
|
88
|
+
cdef inline void mon_free(path_mon_t M) noexcept:
|
89
|
+
biseq_dealloc(M.path)
|
90
|
+
|
91
|
+
# Linearisation
|
92
|
+
cdef inline tuple mon_pickle(path_mon_t M):
|
93
|
+
return (bitset_pickle(M.path.data) if M.path.length>0 else (),
|
94
|
+
M.path.itembitsize, M.path.length, M.pos, M.l_len, M.s_len)
|
95
|
+
|
96
|
+
# De-linearisation
|
97
|
+
cdef bint mon_unpickle(path_mon_t out, tuple data) except -1:
|
98
|
+
cdef tuple bitset_data
|
99
|
+
cdef mp_bitcnt_t itembitsize
|
100
|
+
cdef mp_size_t length
|
101
|
+
cdef long Pos
|
102
|
+
cdef mp_size_t L_len
|
103
|
+
cdef mp_size_t S_len
|
104
|
+
bitset_data, itembitsize, length, Pos, L_len, S_len = data
|
105
|
+
out.path.itembitsize = itembitsize
|
106
|
+
out.path.mask_item = limb_lower_bits_up(itembitsize)
|
107
|
+
out.path.length = length
|
108
|
+
|
109
|
+
# bitset_unpickle assumes that out.path.data is initialised.
|
110
|
+
bitset_init(out.path.data, GMP_LIMB_BITS)
|
111
|
+
if bitset_data:
|
112
|
+
sig_on()
|
113
|
+
bitset_unpickle(out.path.data, bitset_data)
|
114
|
+
sig_off()
|
115
|
+
out.pos = Pos
|
116
|
+
out.l_len = L_len
|
117
|
+
out.s_len = S_len
|
118
|
+
|
119
|
+
|
120
|
+
########################################
|
121
|
+
#
|
122
|
+
# Monomial orders---we only use degree orders
|
123
|
+
|
124
|
+
# Negative degree reverse lexicographic ordering
|
125
|
+
cdef int negdegrevlex(path_mon_t M1, path_mon_t M2) except -2:
|
126
|
+
# a*s_i*b<c*s_j*d <=>
|
127
|
+
# 1. deg(a*b) > deg(c*d), otherwise
|
128
|
+
# 2. deg(a) > deg(c) (note that one of them may be -1), otherwise
|
129
|
+
# 3. deg(s_i) < deg(s_j), otherwise
|
130
|
+
# 4. a*s_i*b <_revlex c*s_j*d, otherwise
|
131
|
+
# 5. i<j
|
132
|
+
cdef mp_size_t l1 = M1.path.length + M2.s_len # sic!
|
133
|
+
cdef mp_size_t l2 = M2.path.length + M1.s_len
|
134
|
+
if l1 != l2:
|
135
|
+
if l2 < l1:
|
136
|
+
return -1
|
137
|
+
return 1
|
138
|
+
if M2.l_len != M1.l_len:
|
139
|
+
if M2.l_len < M1.l_len:
|
140
|
+
return -1
|
141
|
+
return 1
|
142
|
+
if M1.s_len != M2.s_len:
|
143
|
+
if M1.s_len < M2.s_len:
|
144
|
+
return -1
|
145
|
+
return 1
|
146
|
+
# mpn_cmp does comparison of long integers. If the two long integers have
|
147
|
+
# the same number of digits (this is the case her), it is the same as
|
148
|
+
# lexicographic comparison of the numbers. The highest digit corresponds
|
149
|
+
# to the right-most item in the path. Hence, it becomes
|
150
|
+
# reverse-lexicographic order.
|
151
|
+
sig_on()
|
152
|
+
cdef int c = mpn_cmp(M1.path.data.bits, M2.path.data.bits, M1.path.data.limbs)
|
153
|
+
sig_off()
|
154
|
+
if c!=0:
|
155
|
+
return c
|
156
|
+
if M1.pos != M2.pos:
|
157
|
+
if M1.pos < M2.pos:
|
158
|
+
return -1
|
159
|
+
return 1
|
160
|
+
return 0
|
161
|
+
|
162
|
+
# Degree reverse lexicographic ordering
|
163
|
+
cdef int degrevlex(path_mon_t M1, path_mon_t M2) except -2:
|
164
|
+
# a*s_i*b<c*s_j*d <=>
|
165
|
+
# 1. deg(a*b) < deg(c*d), otherwise
|
166
|
+
# 2. deg(a) < deg(c) (note that one of them may be -1), otherwise
|
167
|
+
# 3. deg(s_i) > deg(s_j), otherwise
|
168
|
+
# 4. a*s_i*b <_revlex c*s_j*d, otherwise
|
169
|
+
# 5. i<j
|
170
|
+
cdef mp_size_t l1 = M1.path.length + M2.s_len # sic!
|
171
|
+
cdef mp_size_t l2 = M2.path.length + M1.s_len
|
172
|
+
if l2 != l1:
|
173
|
+
if l2 < l1:
|
174
|
+
return 1
|
175
|
+
return -1
|
176
|
+
if M2.l_len != M1.l_len:
|
177
|
+
if M2.l_len < M1.l_len:
|
178
|
+
return 1
|
179
|
+
return -1
|
180
|
+
if M1.s_len != M2.s_len:
|
181
|
+
if M1.s_len < M2.s_len:
|
182
|
+
return 1
|
183
|
+
return -1
|
184
|
+
# mpn_cmp does comparison of long integers. If the two long integers have
|
185
|
+
# the same number of digits (this is the case her), it is the same as
|
186
|
+
# lexicographic comparison of the numbers. The highest digit corresponds
|
187
|
+
# to the right-most item in the path. Hence, it becomes
|
188
|
+
# reverse-lexicographic order.
|
189
|
+
sig_on()
|
190
|
+
cdef int c = mpn_cmp(M1.path.data.bits, M2.path.data.bits, M1.path.data.limbs)
|
191
|
+
sig_off()
|
192
|
+
if c!=0:
|
193
|
+
return c
|
194
|
+
if M1.pos != M2.pos:
|
195
|
+
if M1.pos < M2.pos:
|
196
|
+
return -1
|
197
|
+
return 1
|
198
|
+
return 0
|
199
|
+
|
200
|
+
# Negative degree lexicographic ordering
|
201
|
+
cdef int negdeglex(path_mon_t M1, path_mon_t M2) except -2:
|
202
|
+
# a*s_i*b<c*s_j*d <=>
|
203
|
+
# 1. deg(a*b) > deg(c*d), otherwise
|
204
|
+
# 2. deg(a) > deg(c) (note that one of them may be -1), otherwise
|
205
|
+
# 3. deg(s_i) < deg(s_j), otherwise
|
206
|
+
# 4. a*s_i*b <_lex c*s_j*d, otherwise
|
207
|
+
# 5. i<j
|
208
|
+
cdef mp_size_t l1 = M1.path.length + M2.s_len # sic!
|
209
|
+
cdef mp_size_t l2 = M2.path.length + M1.s_len
|
210
|
+
cdef size_t item1, item2
|
211
|
+
if l2 != l1:
|
212
|
+
if l2 < l1:
|
213
|
+
return -1
|
214
|
+
return 1
|
215
|
+
if M2.l_len != M1.l_len:
|
216
|
+
if M2.l_len < M1.l_len:
|
217
|
+
return -1
|
218
|
+
return 1
|
219
|
+
if M1.s_len != M2.s_len:
|
220
|
+
if M1.s_len < M2.s_len:
|
221
|
+
return -1
|
222
|
+
return 1
|
223
|
+
for index in range(M1.path.length):
|
224
|
+
item1 = biseq_getitem(M1.path, index)
|
225
|
+
item2 = biseq_getitem(M2.path, index)
|
226
|
+
sig_check()
|
227
|
+
if item1 != item2:
|
228
|
+
if item1 < item2:
|
229
|
+
return -1
|
230
|
+
return 1
|
231
|
+
if M1.pos != M2.pos:
|
232
|
+
if M1.pos < M2.pos:
|
233
|
+
return -1
|
234
|
+
return 1
|
235
|
+
return 0
|
236
|
+
|
237
|
+
# Degree lexicographic ordering
|
238
|
+
cdef int deglex(path_mon_t M1, path_mon_t M2) except -2:
|
239
|
+
# a*s_i*b<c*s_j*d <=>
|
240
|
+
# 1. deg(a*b) < deg(c*d), otherwise
|
241
|
+
# 2. deg(a) < deg(c) (note that one of them may be -1), otherwise
|
242
|
+
# 3. deg(s_i) > deg(s_j), otherwise
|
243
|
+
# 4. a*s_i*b <_lex c*s_j*d, otherwise
|
244
|
+
# 5. i<j
|
245
|
+
cdef mp_size_t l1 = M1.path.length + M2.s_len # sic!
|
246
|
+
cdef mp_size_t l2 = M2.path.length + M1.s_len
|
247
|
+
cdef size_t item1, item2
|
248
|
+
if l2 != l1:
|
249
|
+
if l2 < l1:
|
250
|
+
return 1
|
251
|
+
return -1
|
252
|
+
if M2.l_len != M1.l_len:
|
253
|
+
if M2.l_len < M1.l_len:
|
254
|
+
return 1
|
255
|
+
return -1
|
256
|
+
if M1.s_len != M2.s_len:
|
257
|
+
if M1.s_len < M2.s_len:
|
258
|
+
return 1
|
259
|
+
return -1
|
260
|
+
for index in range(M1.path.length):
|
261
|
+
item1 = biseq_getitem(M1.path, index)
|
262
|
+
item2 = biseq_getitem(M2.path, index)
|
263
|
+
sig_check()
|
264
|
+
if item1 != item2:
|
265
|
+
if item1 < item2:
|
266
|
+
return -1
|
267
|
+
return 1
|
268
|
+
if M1.pos != M2.pos:
|
269
|
+
if M1.pos < M2.pos:
|
270
|
+
return -1
|
271
|
+
return 1
|
272
|
+
return 0
|
273
|
+
|
274
|
+
########################################
|
275
|
+
#
|
276
|
+
# Allocation and Deallocation of terms
|
277
|
+
###########################
|
278
|
+
# We use a freelist for terms
|
279
|
+
|
280
|
+
cdef struct freelist_t:
|
281
|
+
path_term_t **pool
|
282
|
+
size_t used
|
283
|
+
cdef size_t poolsize = 5000 # The freelist contains at most that many terms.
|
284
|
+
|
285
|
+
cdef freelist_t *freelist = <freelist_t*>check_malloc(sizeof(freelist_t))
|
286
|
+
freelist.used = 0
|
287
|
+
freelist.pool = <path_term_t**>check_allocarray(poolsize, sizeof(path_term_t*))
|
288
|
+
|
289
|
+
# Deallocate the term, and return the pointer .nxt, without using kill list
|
290
|
+
cdef inline path_term_t *term_free_force(path_term_t *T) noexcept:
|
291
|
+
mon_free(T.mon)
|
292
|
+
cdef path_term_t *out = T.nxt
|
293
|
+
sig_free(T)
|
294
|
+
return out
|
295
|
+
|
296
|
+
cdef class _FreeListProtector:
|
297
|
+
"""
|
298
|
+
The purpose of this class is to deallocate our freelist
|
299
|
+
of path algebra terms. When its only instance is deleted (which
|
300
|
+
should only happen when a SageMath session ends), then the
|
301
|
+
freelist is cleared.
|
302
|
+
"""
|
303
|
+
def __dealloc__(self):
|
304
|
+
"""
|
305
|
+
TESTS::
|
306
|
+
|
307
|
+
sage: s = Sage()
|
308
|
+
sage: s.eval("P = DiGraph({1:{1:['x','y','z']}}).path_semigroup().algebra(GF(25,'t'))")
|
309
|
+
''
|
310
|
+
sage: s.eval("P.inject_variables()")
|
311
|
+
'Defining e_1, x, y, z'
|
312
|
+
sage: s.eval("x*y+y*z*x")
|
313
|
+
'x*y + y*z*x'
|
314
|
+
sage: s.quit() # indirect doctest
|
315
|
+
"""
|
316
|
+
cdef size_t i
|
317
|
+
for i in range(freelist.used):
|
318
|
+
term_free_force(freelist.pool[i])
|
319
|
+
sig_check()
|
320
|
+
sig_free(freelist.pool)
|
321
|
+
sig_free(freelist)
|
322
|
+
|
323
|
+
_freelist_protector = _FreeListProtector()
|
324
|
+
|
325
|
+
# Put the term on the freelist (unless the list is full),
|
326
|
+
# and return the pointer .nxt
|
327
|
+
cdef inline path_term_t *term_free(path_term_t *T) noexcept:
|
328
|
+
if T.coef!=NULL:
|
329
|
+
Py_XDECREF(T.coef)
|
330
|
+
if likely(freelist.used < poolsize):
|
331
|
+
freelist.pool[postinc(freelist.used)] = T
|
332
|
+
return T.nxt
|
333
|
+
return term_free_force(T)
|
334
|
+
|
335
|
+
# Create a term by copying the given bounded integer sequence,
|
336
|
+
# with the given coefficient
|
337
|
+
cdef path_term_t *term_create(object coef, biseq_t Mon, long Pos, mp_size_t L_len, mp_size_t S_len) except NULL:
|
338
|
+
cdef path_term_t *out
|
339
|
+
if likely(freelist.used > 0):
|
340
|
+
out = freelist.pool[predec(freelist.used)]
|
341
|
+
mon_realloc(out.mon, Mon, Pos, L_len, S_len)
|
342
|
+
else:
|
343
|
+
out = <path_term_t*>check_malloc(sizeof(path_term_t))
|
344
|
+
mon_create(out.mon, Mon, Pos, L_len, S_len)
|
345
|
+
Py_INCREF(coef)
|
346
|
+
out.coef = <PyObject*>coef
|
347
|
+
out.nxt = NULL
|
348
|
+
return out
|
349
|
+
|
350
|
+
# Create a term without copying the given bounded integer sequence
|
351
|
+
cdef path_term_t *term_create_keep(object coef, biseq_t Mon, long Pos, mp_size_t L_len, mp_size_t S_len) except NULL:
|
352
|
+
cdef path_term_t *out
|
353
|
+
if likely(freelist.used) > 0:
|
354
|
+
out = freelist.pool[predec(freelist.used)]
|
355
|
+
mon_realloc_keep(out.mon, Mon, Pos, L_len, S_len)
|
356
|
+
else:
|
357
|
+
out = <path_term_t*>check_malloc(sizeof(path_term_t))
|
358
|
+
mon_create_keep(out.mon, Mon, Pos, L_len, S_len)
|
359
|
+
Py_INCREF(coef)
|
360
|
+
out.coef = <PyObject*>coef
|
361
|
+
# out.nxt = NULL # to be taken care of externally
|
362
|
+
return out
|
363
|
+
|
364
|
+
# Create a term with a given coefficient, but empty monomial
|
365
|
+
cdef path_term_t *term_create_blank(object coef) except NULL:
|
366
|
+
cdef path_term_t *out
|
367
|
+
if likely(freelist.used > 0):
|
368
|
+
out = freelist.pool[predec(freelist.used)]
|
369
|
+
mon_free(out.mon)
|
370
|
+
else:
|
371
|
+
out = <path_term_t*>check_malloc(sizeof(path_term_t))
|
372
|
+
Py_INCREF(coef)
|
373
|
+
out.coef = <PyObject*>coef
|
374
|
+
# out.nxt = NULL # to be taken care of externally
|
375
|
+
return out
|
376
|
+
|
377
|
+
######################################################################
|
378
|
+
######################################################################
|
379
|
+
|
380
|
+
# Copy a term; recall that copying the underlying monomial
|
381
|
+
# just means to increase its reference count. However,
|
382
|
+
# the copied TERM is new.
|
383
|
+
# The .nxt attribute is NOT defined on the copy of the term.
|
384
|
+
cdef path_term_t *term_copy(path_term_t *T) except NULL:
|
385
|
+
cdef path_term_t *out
|
386
|
+
if likely(freelist.used > 0):
|
387
|
+
out = freelist.pool[predec(freelist.used)]
|
388
|
+
mon_free(out.mon)
|
389
|
+
else:
|
390
|
+
out = <path_term_t*>check_malloc(sizeof(path_term_t))
|
391
|
+
sig_on()
|
392
|
+
mon_copy(out.mon, T.mon)
|
393
|
+
sig_off()
|
394
|
+
Py_XINCREF(T.coef)
|
395
|
+
out.coef = T.coef
|
396
|
+
# out.nxt is supposed to be taken care of externally
|
397
|
+
return out
|
398
|
+
|
399
|
+
# Create a copy of T and recursively of T.nxt
|
400
|
+
cdef path_term_t *term_copy_recursive(path_term_t *T) except NULL:
|
401
|
+
cdef path_term_t *out = term_copy(T)
|
402
|
+
cdef path_term_t *first = out
|
403
|
+
T = T.nxt
|
404
|
+
while T!=NULL:
|
405
|
+
out.nxt = term_copy(T)
|
406
|
+
out = out.nxt
|
407
|
+
T = T.nxt
|
408
|
+
out.nxt = NULL
|
409
|
+
return first
|
410
|
+
|
411
|
+
# Hash of a term; probably not a good one.
|
412
|
+
cdef inline long term_hash(path_term_t *T) noexcept:
|
413
|
+
return (<long>hash(<object>T.coef)+(T.mon.l_len<<5)+(T.mon.pos<<10))^bitset_hash(T.mon.path.data)
|
414
|
+
|
415
|
+
# Recall that a monomial a*I*b (with I a generator of a free module)
|
416
|
+
# is encoded by a path a*s*b for some monomial s that refers to a
|
417
|
+
# so-called Schreyer ordering. The total degree of a*I*b is the length
|
418
|
+
# of a plus the length of b.
|
419
|
+
cdef inline mp_size_t term_total_degree(path_term_t *T) noexcept:
|
420
|
+
return T.mon.path.length-T.mon.s_len
|
421
|
+
|
422
|
+
# Linearisation
|
423
|
+
cdef inline tuple term_pickle(path_term_t *T):
|
424
|
+
return (<object>T.coef, mon_pickle(T.mon))
|
425
|
+
|
426
|
+
# De-linearisation
|
427
|
+
cdef inline path_term_t *term_unpickle(object coef, tuple mon_data) except NULL:
|
428
|
+
cdef path_term_t *out = term_create_blank(coef)
|
429
|
+
mon_unpickle(out.mon, mon_data)
|
430
|
+
return out
|
431
|
+
|
432
|
+
########################################
|
433
|
+
#
|
434
|
+
# Multiplication of monomials
|
435
|
+
|
436
|
+
# Return T*p, for a path p and a monomial T.
|
437
|
+
cdef bint mon_mul_path(path_mon_t out, path_mon_t T, biseq_t p) except -1:
|
438
|
+
if unlikely(p.length == 0):
|
439
|
+
return mon_copy(out, T)
|
440
|
+
biseq_init_concat(out.path, T.path, p)
|
441
|
+
out.pos = T.pos
|
442
|
+
out.l_len = T.l_len
|
443
|
+
out.s_len = T.s_len
|
444
|
+
|
445
|
+
# Return p*T, for a path p and a monomial T.
|
446
|
+
cdef bint path_mul_mon(path_mon_t out, biseq_t p, path_mon_t T) except -1:
|
447
|
+
if unlikely(p.length == 0):
|
448
|
+
return mon_copy(out, T)
|
449
|
+
biseq_init_concat(out.path, p, T.path)
|
450
|
+
out.pos = T.pos
|
451
|
+
out.l_len = 0 if T.pos==-1 else T.l_len+p.length
|
452
|
+
out.s_len = T.s_len
|
453
|
+
|
454
|
+
# Return p*T*q, for paths p,q and a monomial T.
|
455
|
+
cdef bint path_mul_mon_mul_path(path_mon_t out, biseq_t p, path_mon_t T, biseq_t q) except -1:
|
456
|
+
# .l_len and .s_len are taken care of externally!
|
457
|
+
if unlikely(p.length==0 and q.length==0):
|
458
|
+
return mon_copy(out, T)
|
459
|
+
if unlikely(p.length == 0):
|
460
|
+
return mon_mul_path(out, T, q)
|
461
|
+
if unlikely(q.length == 0):
|
462
|
+
return path_mul_mon(out, p, T)
|
463
|
+
out.pos = T.pos
|
464
|
+
if unlikely(T.path.length == 0):
|
465
|
+
biseq_init_concat(out.path, p, q)
|
466
|
+
return True
|
467
|
+
cdef mp_size_t pTlength = p.length + T.path.length
|
468
|
+
cdef mp_size_t res_length = pTlength + q.length
|
469
|
+
biseq_init(out.path, res_length, p.itembitsize)
|
470
|
+
if res_length == 0:
|
471
|
+
return False
|
472
|
+
cdef mp_bitcnt_t pTsize = p.data.size+T.path.data.size
|
473
|
+
sig_on()
|
474
|
+
bitset_lshift(out.path.data, q.data, pTsize)
|
475
|
+
cdef mp_bitcnt_t p_offset = p.data.size % GMP_LIMB_BITS
|
476
|
+
# p_limbs gives the index of the limb that will store the first bit of the
|
477
|
+
# shifted version of T.
|
478
|
+
cdef mp_bitcnt_t p_limbs = (p.data.limbs - 1) if p_offset>0 else p.data.limbs
|
479
|
+
|
480
|
+
# pT_limbs gives the index of the last limb used to store p+T
|
481
|
+
cdef mp_bitcnt_t pT_limbs = (pTsize-1)//GMP_LIMB_BITS
|
482
|
+
if ((T.path.data.size-1) % GMP_LIMB_BITS) + p_offset >= GMP_LIMB_BITS:
|
483
|
+
# We shift all limbs of T. The highest bits of the highest limbs are
|
484
|
+
# pushed out and returned by mpn_lshift. We need to assign them to the
|
485
|
+
# beginning of the last limb that is (partially) occupied by p+T
|
486
|
+
out.path.data.bits[pT_limbs] |= mpn_lshift(out.path.data.bits+p_limbs,
|
487
|
+
T.path.data.bits,
|
488
|
+
T.path.data.limbs, p_offset)
|
489
|
+
else:
|
490
|
+
if T.path.data.limbs>1:
|
491
|
+
# If we would move all limbs of T, then the result would override
|
492
|
+
# the lowest limb of the shifted copy of q. We thus only move all
|
493
|
+
# but the last limb of T, assigning to the beginning of the last
|
494
|
+
# limb of p+T the bits that have been pushed out.
|
495
|
+
out.path.data.bits[pT_limbs] |= mpn_lshift(out.path.data.bits+p_limbs,
|
496
|
+
T.path.data.bits,
|
497
|
+
T.path.data.limbs-1,
|
498
|
+
p_offset)
|
499
|
+
# Last, we need to move the last limb of T (which is only
|
500
|
+
# partially occupied), namely into the spot between the previously
|
501
|
+
# moved parts of T and the beginning of the shifted copy of q.
|
502
|
+
out.path.data.bits[pT_limbs] |= (T.path.data.bits[T.path.data.limbs-1]<<p_offset)
|
503
|
+
else:
|
504
|
+
out.path.data.bits[p_limbs] |= (T.path.data.bits[T.path.data.limbs-1]<<p_offset)
|
505
|
+
bitset_or(out.path.data, out.path.data, p.data)
|
506
|
+
sig_off()
|
507
|
+
|
508
|
+
########################################
|
509
|
+
# Addition and scaling of terms
|
510
|
+
|
511
|
+
# Return -T
|
512
|
+
cdef path_term_t *term_neg(path_term_t *T) except NULL:
|
513
|
+
cdef path_term_t *out
|
514
|
+
if likely(freelist.used > 0):
|
515
|
+
out = freelist.pool[predec(freelist.used)]
|
516
|
+
mon_free(out.mon)
|
517
|
+
else:
|
518
|
+
out = <path_term_t*>check_malloc(sizeof(path_term_t))
|
519
|
+
cdef object coef = -<object>T.coef
|
520
|
+
out.coef = <PyObject*>coef
|
521
|
+
Py_INCREF(coef)
|
522
|
+
mon_copy(out.mon, T.mon)
|
523
|
+
# out.nxt is supposed to be taken care of externally
|
524
|
+
return out
|
525
|
+
|
526
|
+
# Return -T, and recurse over T.nxt
|
527
|
+
cdef path_term_t *term_neg_recursive(path_term_t *T) except NULL:
|
528
|
+
cdef path_term_t *out = term_neg(T)
|
529
|
+
cdef path_term_t *first = out
|
530
|
+
T = T.nxt
|
531
|
+
while T!=NULL:
|
532
|
+
sig_check()
|
533
|
+
out.nxt = term_neg(T)
|
534
|
+
out = out.nxt
|
535
|
+
T = T.nxt
|
536
|
+
out.nxt = NULL
|
537
|
+
return first
|
538
|
+
|
539
|
+
# Return coef*T
|
540
|
+
cdef path_term_t *term_scale(path_term_t *T, object coef) except NULL:
|
541
|
+
cdef path_term_t *out
|
542
|
+
if likely(freelist.used > 0):
|
543
|
+
out = freelist.pool[predec(freelist.used)]
|
544
|
+
mon_free(out.mon)
|
545
|
+
else:
|
546
|
+
out = <path_term_t*>check_malloc(sizeof(path_term_t))
|
547
|
+
cdef object new_coef = coef*<object>T.coef
|
548
|
+
if new_coef:
|
549
|
+
out.coef = <PyObject*>new_coef
|
550
|
+
Py_INCREF(new_coef)
|
551
|
+
mon_copy(out.mon, T.mon)
|
552
|
+
else:
|
553
|
+
out.coef = NULL
|
554
|
+
# out.nxt is supposed to be taken care of externally
|
555
|
+
return out
|
556
|
+
|
557
|
+
# Return coef*T and recurse over T.nxt
|
558
|
+
cdef path_term_t *term_scale_recursive(path_term_t *T, object coef) except NULL:
|
559
|
+
cdef path_term_t *out = term_scale(T, coef)
|
560
|
+
cdef path_term_t *first = out
|
561
|
+
T = T.nxt
|
562
|
+
while T!=NULL:
|
563
|
+
sig_check()
|
564
|
+
out.nxt = term_scale(T, coef)
|
565
|
+
if out.nxt.coef == NULL:
|
566
|
+
term_free(out.nxt)
|
567
|
+
out.nxt = NULL
|
568
|
+
else:
|
569
|
+
out = out.nxt
|
570
|
+
T = T.nxt
|
571
|
+
out.nxt = NULL
|
572
|
+
return first
|
573
|
+
|
574
|
+
# Return T1*T2.
|
575
|
+
# An error is raised if both T1 and T2 belong to a free module over a
|
576
|
+
# path algebra (but not to the path algebra itself). Hence, this function
|
577
|
+
# implements multiplication of a term in a path algebra, and the action
|
578
|
+
# of a term of a path algebra on a term in a free module.
|
579
|
+
cdef path_term_t *term_mul_term(path_term_t *T1, path_term_t *T2) except NULL:
|
580
|
+
cdef mp_size_t new_l_len
|
581
|
+
cdef long new_pos
|
582
|
+
cdef mp_size_t new_s_len
|
583
|
+
if T1.mon.pos!=-1:
|
584
|
+
if T2.mon.pos!=-1:
|
585
|
+
raise ValueError("we cannot multiply two module elements")
|
586
|
+
new_l_len = T1.mon.l_len
|
587
|
+
new_pos = T1.mon.pos
|
588
|
+
new_s_len = T1.mon.s_len
|
589
|
+
elif T2.mon.pos!=-1:
|
590
|
+
new_l_len = T2.mon.l_len+T1.mon.path.length
|
591
|
+
new_pos = T2.mon.pos
|
592
|
+
new_s_len = T2.mon.s_len
|
593
|
+
else:
|
594
|
+
new_l_len = 0
|
595
|
+
new_pos = -1
|
596
|
+
new_s_len = 0
|
597
|
+
cdef object new_coef = (<object>T1.coef)*(<object>T2.coef)
|
598
|
+
|
599
|
+
cdef path_term_t *out
|
600
|
+
if likely(freelist.used > 0):
|
601
|
+
out = freelist.pool[predec(freelist.used)]
|
602
|
+
if new_coef:
|
603
|
+
out.coef = <PyObject*>(new_coef)
|
604
|
+
Py_INCREF(new_coef)
|
605
|
+
biseq_dealloc(out.mon.path)
|
606
|
+
biseq_init_concat(out.mon.path, T1.mon.path, T2.mon.path)
|
607
|
+
else:
|
608
|
+
out.coef = NULL
|
609
|
+
else:
|
610
|
+
out = <path_term_t*>check_malloc(sizeof(path_term_t))
|
611
|
+
if new_coef:
|
612
|
+
out.coef = <PyObject*>(new_coef)
|
613
|
+
Py_INCREF(new_coef)
|
614
|
+
biseq_init_concat(out.mon.path, T1.mon.path, T2.mon.path)
|
615
|
+
else:
|
616
|
+
out.coef = NULL
|
617
|
+
out.mon.pos = new_pos
|
618
|
+
out.mon.l_len = new_l_len
|
619
|
+
out.mon.s_len = new_s_len
|
620
|
+
out.nxt = NULL
|
621
|
+
return out
|
622
|
+
|
623
|
+
########################################
|
624
|
+
#
|
625
|
+
# Basics for polynomials
|
626
|
+
|
627
|
+
# Create an empty polynomial
|
628
|
+
cdef inline path_poly_t *poly_create() except NULL:
|
629
|
+
cdef path_poly_t *out = <path_poly_t*>check_malloc(sizeof(path_poly_t))
|
630
|
+
out.lead = NULL
|
631
|
+
out.nterms = 0
|
632
|
+
return out
|
633
|
+
|
634
|
+
# Deallocate all terms of the polynomial, but NOT the polynomial itself
|
635
|
+
cdef inline void poly_dealloc(path_poly_t *P) noexcept:
|
636
|
+
cdef path_term_t *T = P.lead
|
637
|
+
while T!=NULL:
|
638
|
+
T = term_free(T)
|
639
|
+
|
640
|
+
# Deallocate all terms of the polynomial, and free the chunk of memory
|
641
|
+
# used by the polynomial.
|
642
|
+
cdef inline void poly_free(path_poly_t *P) noexcept:
|
643
|
+
poly_dealloc(P)
|
644
|
+
sig_free(P)
|
645
|
+
|
646
|
+
# Fill "out" with a copy of the terms of P. Note that previous contents
|
647
|
+
# of "out" will NOT be freed---this function should thus only be called
|
648
|
+
# when "out" is empty.
|
649
|
+
cdef inline bint poly_icopy(path_poly_t *out, path_poly_t *P) except -1:
|
650
|
+
cdef path_term_t *T = P.lead
|
651
|
+
out.nterms = P.nterms
|
652
|
+
out.lead = term_copy_recursive(T)
|
653
|
+
return True
|
654
|
+
|
655
|
+
# Fill "out" with a copy of the terms of -P. Note that previous contents
|
656
|
+
# of "out" will NOT be freed---this function should thus only be called
|
657
|
+
# when "out" is empty.
|
658
|
+
cdef inline bint poly_icopy_neg(path_poly_t *out, path_poly_t *P) except -1:
|
659
|
+
cdef path_term_t *T = P.lead
|
660
|
+
out.nterms = P.nterms
|
661
|
+
out.lead = term_neg_recursive(T)
|
662
|
+
return True
|
663
|
+
|
664
|
+
# Fill "out" with a copy of the terms of coef*P. Note that previous contents
|
665
|
+
# of "out" will NOT be freed---this function should thus only be called
|
666
|
+
# when "out" is empty.
|
667
|
+
cdef bint poly_icopy_scale(path_poly_t *out, path_poly_t *P, object coef) except -1:
|
668
|
+
cdef path_term_t *T = P.lead
|
669
|
+
cdef path_term_t *res = term_scale(T, coef)
|
670
|
+
out.nterms = 0
|
671
|
+
out.lead = NULL
|
672
|
+
while res.coef == NULL:
|
673
|
+
sig_check()
|
674
|
+
sig_free(res)
|
675
|
+
T = T.nxt
|
676
|
+
if T == NULL:
|
677
|
+
return True
|
678
|
+
res = term_scale(T, coef)
|
679
|
+
out.lead = res
|
680
|
+
out.nterms += 1
|
681
|
+
T = T.nxt
|
682
|
+
while T != NULL:
|
683
|
+
sig_check()
|
684
|
+
res.nxt = term_scale(T, coef)
|
685
|
+
if res.nxt.coef == NULL:
|
686
|
+
sig_free(res.nxt)
|
687
|
+
else:
|
688
|
+
res = res.nxt
|
689
|
+
out.nterms += 1
|
690
|
+
T = T.nxt
|
691
|
+
if res != NULL:
|
692
|
+
res.nxt = NULL
|
693
|
+
return True
|
694
|
+
|
695
|
+
# Linearisation of a path polynomials
|
696
|
+
cdef list poly_pickle(path_poly_t *P):
|
697
|
+
cdef list L = []
|
698
|
+
cdef path_term_t *T = P.lead
|
699
|
+
while T != NULL:
|
700
|
+
L.append(term_pickle(T))
|
701
|
+
T = T.nxt
|
702
|
+
return L
|
703
|
+
|
704
|
+
# De-linearisation
|
705
|
+
cdef bint poly_inplace_unpickle(path_poly_t *P, list data) except -1:
|
706
|
+
cdef tuple term_data
|
707
|
+
cdef object coef
|
708
|
+
cdef path_term_t *T
|
709
|
+
if not data:
|
710
|
+
P.nterms = 0
|
711
|
+
P.lead = NULL
|
712
|
+
return True
|
713
|
+
P.nterms = len(data)
|
714
|
+
coef, term_data = data.pop(0)
|
715
|
+
P.lead = term_unpickle(coef, term_data)
|
716
|
+
T = P.lead
|
717
|
+
for coef, term_data in data:
|
718
|
+
T.nxt = term_unpickle(coef, term_data)
|
719
|
+
T = T.nxt
|
720
|
+
T.nxt = NULL
|
721
|
+
return True
|
722
|
+
|
723
|
+
############################################
|
724
|
+
#
|
725
|
+
# Polynomial arithmetics
|
726
|
+
|
727
|
+
# Rich comparison of P1 and P2, using the given monomial ordering cmp_terms.
|
728
|
+
# Return a boolean.
|
729
|
+
cdef bint poly_richcmp(path_poly_t *P1, path_poly_t *P2, path_order_t cmp_terms, int op) noexcept:
|
730
|
+
cdef path_term_t *T1 = P1.lead
|
731
|
+
cdef path_term_t *T2 = P2.lead
|
732
|
+
cdef int c
|
733
|
+
cdef object t1
|
734
|
+
cdef object t2
|
735
|
+
while T1 != NULL and T2 != NULL:
|
736
|
+
sig_check()
|
737
|
+
c = cmp_terms(T1.mon, T2.mon)
|
738
|
+
if c:
|
739
|
+
return rich_to_bool(op, c)
|
740
|
+
|
741
|
+
t1 = <object>T1.coef
|
742
|
+
t2 = <object>T2.coef
|
743
|
+
if t1 != t2:
|
744
|
+
return richcmp_not_equal(t1, t2, op)
|
745
|
+
T1 = T1.nxt
|
746
|
+
T2 = T2.nxt
|
747
|
+
if T1 == NULL:
|
748
|
+
if T2 == NULL:
|
749
|
+
return rich_to_bool(op, 0)
|
750
|
+
return rich_to_bool(op, -1)
|
751
|
+
return rich_to_bool(op, 1)
|
752
|
+
|
753
|
+
# Hash of a polynomial. Probably not a very strong hash.
|
754
|
+
cdef inline long poly_hash(path_poly_t *P) noexcept:
|
755
|
+
cdef path_term_t *T = P.lead
|
756
|
+
cdef long out = 0
|
757
|
+
while T != NULL:
|
758
|
+
out = out<<7 | (out>>(sizeof(long)-7))
|
759
|
+
out += term_hash(T)
|
760
|
+
T = T.nxt
|
761
|
+
return out
|
762
|
+
|
763
|
+
# Change T1 inplace to T1+T2.coeff*T1. If the new coefficient is zero,
|
764
|
+
# then T1.coef becomes NULL
|
765
|
+
cdef inline void term_iadd(path_term_t *T1, path_term_t *T2) noexcept:
|
766
|
+
cdef object coef = <object>(T1.coef) + <object>(T2.coef)
|
767
|
+
Py_XDECREF(T1.coef)
|
768
|
+
if coef:
|
769
|
+
Py_INCREF(coef)
|
770
|
+
T1.coef = <PyObject*>coef
|
771
|
+
else:
|
772
|
+
T1.coef = NULL
|
773
|
+
|
774
|
+
# Change P inplace to P+T. It is assumed that initially the terms of P are
|
775
|
+
# decreasingly sorted wrt. cmp_terms, and then it is guaranteed that they
|
776
|
+
# are decreasingly sorted wrt. cmp_terms after adding T.
|
777
|
+
# The addition is "destructive" for T, which means that one MUST NOT
|
778
|
+
# call term_free(T) after the addition!
|
779
|
+
cdef bint poly_iadd_term_d(path_poly_t *P, path_term_t *T, path_order_t cmp_terms) except -1:
|
780
|
+
if P.lead == NULL:
|
781
|
+
P.nterms += 1
|
782
|
+
T.nxt = NULL
|
783
|
+
P.lead = T
|
784
|
+
return True
|
785
|
+
cdef path_term_t *tmp = P.lead
|
786
|
+
cdef int c
|
787
|
+
cdef object coef
|
788
|
+
c = cmp_terms(tmp.mon, T.mon)
|
789
|
+
if c==-1:
|
790
|
+
# The poly's lead term is smaller than T. Hence, we need to prepend
|
791
|
+
# it.
|
792
|
+
P.nterms += 1
|
793
|
+
T.nxt = tmp
|
794
|
+
P.lead = T
|
795
|
+
return True
|
796
|
+
elif c==0:
|
797
|
+
sig_on()
|
798
|
+
term_iadd(tmp, T)
|
799
|
+
term_free(T)
|
800
|
+
if tmp.coef==NULL:
|
801
|
+
P.nterms -= 1
|
802
|
+
P.lead = term_free(tmp)
|
803
|
+
elif <object>(tmp.coef)==0:
|
804
|
+
sig_off()
|
805
|
+
raise RuntimeError("this should never happen")
|
806
|
+
sig_off()
|
807
|
+
return True
|
808
|
+
while True:
|
809
|
+
# At this point, we have tmp>T.
|
810
|
+
#
|
811
|
+
# We need to append the term, or continue until we can
|
812
|
+
# insert/append
|
813
|
+
sig_check()
|
814
|
+
if tmp.nxt == NULL:
|
815
|
+
P.nterms += 1
|
816
|
+
T.nxt = NULL
|
817
|
+
tmp.nxt = T
|
818
|
+
return True
|
819
|
+
c = cmp_terms(tmp.nxt.mon, T.mon)
|
820
|
+
if c==-1:
|
821
|
+
P.nterms += 1
|
822
|
+
T.nxt = tmp.nxt
|
823
|
+
tmp.nxt = T
|
824
|
+
return True
|
825
|
+
elif c==0:
|
826
|
+
term_iadd(tmp.nxt, T)
|
827
|
+
term_free(T)
|
828
|
+
if tmp.nxt.coef==NULL:
|
829
|
+
P.nterms -= 1
|
830
|
+
tmp.nxt = term_free(tmp.nxt)
|
831
|
+
elif <object>(tmp.coef)==0:
|
832
|
+
raise RuntimeError("this should never happen")
|
833
|
+
return True
|
834
|
+
# otherwise, tmp is still larger than T. Hence, move to the next term
|
835
|
+
# of P.
|
836
|
+
tmp = tmp.nxt
|
837
|
+
|
838
|
+
# Change P1 inplace to P1+P2. It is assumed that both P1's and P2's terms
|
839
|
+
# are decreasingly sorted wrt. cmp_terms, and after the operation P1's terms
|
840
|
+
# will still be decreasingly sorted. After the operation, one MUST NOT
|
841
|
+
# call poly_free(P2)!
|
842
|
+
cdef bint poly_iadd_d(path_poly_t *P1, path_poly_t *P2, path_order_t cmp_terms) except -1:
|
843
|
+
# Terms of P2 will be moved to P1, so that deallocation of P2 will not be
|
844
|
+
# needed.
|
845
|
+
if P1.lead == NULL:
|
846
|
+
P1.lead = P2.lead
|
847
|
+
P1.nterms = P2.nterms
|
848
|
+
P2.nterms = 0
|
849
|
+
P2.lead = NULL
|
850
|
+
return 1
|
851
|
+
if P2.lead == NULL:
|
852
|
+
return 1
|
853
|
+
cdef path_term_t *T1 = P1.lead
|
854
|
+
cdef path_term_t *T2 = P2.lead
|
855
|
+
cdef path_term_t *prev = NULL
|
856
|
+
cdef int c
|
857
|
+
cdef object new_coef
|
858
|
+
while True:
|
859
|
+
# Is one of the summands consumed already? Then we can use an easier
|
860
|
+
# method.
|
861
|
+
sig_check()
|
862
|
+
if T1 == NULL:
|
863
|
+
if prev==NULL:
|
864
|
+
P1.lead = T2
|
865
|
+
else:
|
866
|
+
prev.nxt = T2
|
867
|
+
P1.nterms += P2.nterms
|
868
|
+
P2.nterms = 0
|
869
|
+
P2.lead = NULL
|
870
|
+
return 1
|
871
|
+
elif T2 == NULL:
|
872
|
+
if P2.nterms != 0:
|
873
|
+
print("term counting of second summand was wrong! " +
|
874
|
+
str(P2.nterms))
|
875
|
+
P2.lead = NULL
|
876
|
+
return 1
|
877
|
+
c = cmp_terms(T1.mon, T2.mon)
|
878
|
+
if c == 0:
|
879
|
+
# T1==T2 --- We need to add
|
880
|
+
new_coef = <object>(T1.coef)+<object>(T2.coef)
|
881
|
+
if new_coef:
|
882
|
+
Py_INCREF(new_coef)
|
883
|
+
Py_XDECREF(T1.coef)
|
884
|
+
T1.coef = <PyObject*>new_coef
|
885
|
+
prev = T1
|
886
|
+
T1 = T1.nxt
|
887
|
+
else:
|
888
|
+
T1 = term_free(T1)
|
889
|
+
if prev==NULL:
|
890
|
+
P1.lead = T1
|
891
|
+
else:
|
892
|
+
prev.nxt = T1
|
893
|
+
P1.nterms -= 1
|
894
|
+
P2.nterms -= 1
|
895
|
+
T2 = term_free(T2)
|
896
|
+
elif c == 1:
|
897
|
+
# We move the prev/T1 through P1, until prev>T2>=T1. But now,
|
898
|
+
# T1>T2. So, we move prev/T1 further down.
|
899
|
+
prev = T1
|
900
|
+
T1 = T1.nxt
|
901
|
+
else:
|
902
|
+
# prev > T2 > T1. Hence, we insert T2, without copying
|
903
|
+
if prev==NULL:
|
904
|
+
P1.lead = T2
|
905
|
+
T2 = T2.nxt
|
906
|
+
prev = P1.lead
|
907
|
+
else:
|
908
|
+
prev.nxt = T2
|
909
|
+
T2 = T2.nxt
|
910
|
+
prev = prev.nxt
|
911
|
+
prev.nxt = T1
|
912
|
+
P1.nterms += 1
|
913
|
+
P2.nterms -= 1
|
914
|
+
|
915
|
+
# Return P1+P2 (a new polynomial, and after the operation it is still safe
|
916
|
+
# to call poly_free(P2)). Both P1's and P2's terms are supposed to be
|
917
|
+
# decreasingly sorted wrt. cmp_terms, and so will be the terms of P1+P2.
|
918
|
+
cdef path_poly_t *poly_add(path_poly_t *P1, path_poly_t *P2, path_order_t cmp_terms) except NULL:
|
919
|
+
cdef path_poly_t *out = poly_create()
|
920
|
+
cdef path_term_t *T1 = P1.lead
|
921
|
+
cdef path_term_t *T2 = P2.lead
|
922
|
+
cdef path_term_t *T = NULL
|
923
|
+
cdef path_term_t *res
|
924
|
+
cdef size_t count1, count2 # How many terms of P1/P2 have been considered?
|
925
|
+
count1 = 0
|
926
|
+
count2 = 0
|
927
|
+
cdef object coef
|
928
|
+
cdef int c
|
929
|
+
while True:
|
930
|
+
sig_check()
|
931
|
+
if T1 == NULL:
|
932
|
+
out.nterms += (P2.nterms-count2)
|
933
|
+
if T == NULL:
|
934
|
+
if T2 == NULL:
|
935
|
+
out.lead = NULL
|
936
|
+
else:
|
937
|
+
out.lead = term_copy_recursive(T2)
|
938
|
+
else:
|
939
|
+
if T2 == NULL:
|
940
|
+
T.nxt = NULL
|
941
|
+
else:
|
942
|
+
T.nxt = term_copy_recursive(T2)
|
943
|
+
return out
|
944
|
+
if T2 == NULL:
|
945
|
+
out.nterms += (P1.nterms-count1)
|
946
|
+
if T == NULL:
|
947
|
+
out.lead = term_copy_recursive(T1)
|
948
|
+
else:
|
949
|
+
T.nxt = term_copy_recursive(T1)
|
950
|
+
return out
|
951
|
+
|
952
|
+
c = cmp_terms(T1.mon, T2.mon)
|
953
|
+
if c == 1:
|
954
|
+
if T == NULL:
|
955
|
+
out.lead = term_copy(T1)
|
956
|
+
T = out.lead
|
957
|
+
else:
|
958
|
+
T.nxt = term_copy(T1)
|
959
|
+
T = T.nxt
|
960
|
+
T1 = T1.nxt
|
961
|
+
count1 += 1
|
962
|
+
out.nterms += 1
|
963
|
+
elif c == -1:
|
964
|
+
if T == NULL:
|
965
|
+
out.lead = term_copy(T2)
|
966
|
+
T = out.lead
|
967
|
+
else:
|
968
|
+
T.nxt = term_copy(T2)
|
969
|
+
T = T.nxt
|
970
|
+
T2 = T2.nxt
|
971
|
+
count2 += 1
|
972
|
+
out.nterms += 1
|
973
|
+
else:
|
974
|
+
coef = (<object>T1.coef)+(<object>T2.coef)
|
975
|
+
if coef:
|
976
|
+
out.nterms += 1
|
977
|
+
if T == NULL:
|
978
|
+
out.lead = term_create(coef, T1.mon.path, T1.mon.pos, T1.mon.l_len, T1.mon.s_len)
|
979
|
+
T = out.lead
|
980
|
+
else:
|
981
|
+
T.nxt = term_create(coef, T1.mon.path, T1.mon.pos, T1.mon.l_len, T1.mon.s_len)
|
982
|
+
T = T.nxt
|
983
|
+
count1 += 1
|
984
|
+
count2 += 1
|
985
|
+
T1 = T1.nxt
|
986
|
+
T2 = T2.nxt
|
987
|
+
|
988
|
+
# Return P1-P2 (a new polynomial, and after the operation it is still safe
|
989
|
+
# to call poly_free(P2)). Both P1's and P2's terms are supposed to be
|
990
|
+
# decreasingly sorted wrt. cmp_terms, and so will be the terms of P1-P2.
|
991
|
+
cdef path_poly_t *poly_sub(path_poly_t *P1, path_poly_t *P2, path_order_t cmp_terms) except NULL:
|
992
|
+
cdef path_poly_t *out = poly_create()
|
993
|
+
cdef path_term_t *T1 = P1.lead
|
994
|
+
cdef path_term_t *T2 = P2.lead
|
995
|
+
cdef path_term_t *T = NULL
|
996
|
+
cdef path_term_t *res
|
997
|
+
cdef size_t count1, count2 # How many terms of P1/P2 have been considered?
|
998
|
+
count1 = 0
|
999
|
+
count2 = 0
|
1000
|
+
cdef object coef
|
1001
|
+
cdef int c
|
1002
|
+
while True:
|
1003
|
+
sig_check()
|
1004
|
+
if T1 == NULL:
|
1005
|
+
out.nterms += (P2.nterms-count2)
|
1006
|
+
if T == NULL:
|
1007
|
+
if T2 == NULL:
|
1008
|
+
out.lead = NULL
|
1009
|
+
else:
|
1010
|
+
out.lead = term_neg_recursive(T2)
|
1011
|
+
else:
|
1012
|
+
if T2 == NULL:
|
1013
|
+
T.nxt = NULL
|
1014
|
+
else:
|
1015
|
+
T.nxt = term_neg_recursive(T2)
|
1016
|
+
return out
|
1017
|
+
if T2 == NULL:
|
1018
|
+
out.nterms += (P1.nterms-count1)
|
1019
|
+
if T == NULL:
|
1020
|
+
out.lead = term_copy_recursive(T1)
|
1021
|
+
else:
|
1022
|
+
T.nxt = term_copy_recursive(T1)
|
1023
|
+
return out
|
1024
|
+
|
1025
|
+
c = cmp_terms(T1.mon, T2.mon)
|
1026
|
+
if c == 1:
|
1027
|
+
if T == NULL:
|
1028
|
+
out.lead = term_copy(T1)
|
1029
|
+
T = out.lead
|
1030
|
+
else:
|
1031
|
+
T.nxt = term_copy(T1)
|
1032
|
+
T = T.nxt
|
1033
|
+
T1 = T1.nxt
|
1034
|
+
count1 += 1
|
1035
|
+
out.nterms += 1
|
1036
|
+
elif c == -1:
|
1037
|
+
if T == NULL:
|
1038
|
+
out.lead = term_neg(T2)
|
1039
|
+
T = out.lead
|
1040
|
+
else:
|
1041
|
+
T.nxt = term_neg(T2)
|
1042
|
+
T = T.nxt
|
1043
|
+
T2 = T2.nxt
|
1044
|
+
count2 += 1
|
1045
|
+
out.nterms += 1
|
1046
|
+
else:
|
1047
|
+
coef = (<object>T1.coef)-(<object>T2.coef)
|
1048
|
+
if coef:
|
1049
|
+
out.nterms += 1
|
1050
|
+
if T == NULL:
|
1051
|
+
out.lead = term_create(coef, T1.mon.path, T1.mon.pos, T1.mon.l_len, T1.mon.s_len)
|
1052
|
+
T = out.lead
|
1053
|
+
else:
|
1054
|
+
T.nxt = term_create(coef, T1.mon.path, T1.mon.pos, T1.mon.l_len, T1.mon.s_len)
|
1055
|
+
T = T.nxt
|
1056
|
+
count1 += 1
|
1057
|
+
count2 += 1
|
1058
|
+
T1 = T1.nxt
|
1059
|
+
T2 = T2.nxt
|
1060
|
+
|
1061
|
+
#
|
1062
|
+
# In-place addition of a multiple of a polynomial
|
1063
|
+
# Replace P1 by P1+coef*P2*R. Return a pointer to the first term of P1
|
1064
|
+
# that may be involved in a change when calling the function again with
|
1065
|
+
# P1, P2 and a cofactor that is smaller than R wrt. cmp_terms.
|
1066
|
+
# The return value should then be provided as argument "P1start" of the
|
1067
|
+
# next function call.
|
1068
|
+
#
|
1069
|
+
# We return P1start if P2.lead is NULL. Otherwise, if P1.lead becomes NULL
|
1070
|
+
# during addition, then we return P2.lead.
|
1071
|
+
#
|
1072
|
+
# Let m be a monomial of P2. If it is of module-type (i.e., m.pos!=-1),
|
1073
|
+
# then it is clear what m2=m*R is (m2.l_len and m2.s_len are obtained from
|
1074
|
+
# m.l_len and m.s_len). Otherwise, however, it could be that we
|
1075
|
+
# want m2=m*R to denote a module-type monomial. In that case, "m2.l_len"
|
1076
|
+
# and "m2.s_len" are given by the respective arguments.
|
1077
|
+
|
1078
|
+
cdef path_term_t *poly_iadd_lmul(path_poly_t *P1, object coef, path_poly_t *P2, biseq_t R, path_order_t cmp_terms, long pos, mp_size_t l_len, mp_size_t s_len, path_term_t *P1start) except NULL:
|
1079
|
+
if not coef or P2.lead==NULL:
|
1080
|
+
return P1start
|
1081
|
+
cdef path_mon_t new_mon
|
1082
|
+
cdef object new_coef
|
1083
|
+
cdef path_term_t *prev = NULL
|
1084
|
+
cdef path_term_t *T1
|
1085
|
+
if P1start == NULL:
|
1086
|
+
T1 = P1.lead
|
1087
|
+
else:
|
1088
|
+
T1 = P1start
|
1089
|
+
cdef path_term_t *T2 = P2.lead
|
1090
|
+
cdef int c
|
1091
|
+
cdef path_term_t *out = P1start
|
1092
|
+
while T2!=NULL:
|
1093
|
+
sig_check()
|
1094
|
+
new_coef = coef*<object>(T2.coef)
|
1095
|
+
if not new_coef:
|
1096
|
+
T2 = T2.nxt
|
1097
|
+
continue
|
1098
|
+
|
1099
|
+
if T2.mon.pos!=-1:
|
1100
|
+
mon_mul_path(new_mon, T2.mon, R)
|
1101
|
+
new_mon.pos = T2.mon.pos
|
1102
|
+
new_mon.l_len = T2.mon.l_len
|
1103
|
+
new_mon.s_len = T2.mon.s_len
|
1104
|
+
else:
|
1105
|
+
mon_mul_path(new_mon, T2.mon, R)
|
1106
|
+
new_mon.pos = pos
|
1107
|
+
new_mon.l_len = l_len
|
1108
|
+
new_mon.s_len = s_len
|
1109
|
+
# Now new_term is T2*R
|
1110
|
+
# We go down in P1 until we may append, insert or add
|
1111
|
+
while T1!=NULL:
|
1112
|
+
sig_check()
|
1113
|
+
c = cmp_terms(T1.mon, new_mon)
|
1114
|
+
if c!=1:
|
1115
|
+
break
|
1116
|
+
prev = T1
|
1117
|
+
T1 = prev.nxt
|
1118
|
+
if T1==NULL:
|
1119
|
+
# We need to append to P1
|
1120
|
+
if prev==NULL:
|
1121
|
+
P1.lead = term_create_blank(new_coef)
|
1122
|
+
P1.lead.mon[0] = new_mon[0]
|
1123
|
+
prev = P1.lead
|
1124
|
+
else:
|
1125
|
+
prev.nxt = term_create_blank(new_coef)
|
1126
|
+
prev.nxt.mon[0] = new_mon[0]
|
1127
|
+
prev = prev.nxt
|
1128
|
+
if T2 == P2.lead:
|
1129
|
+
out = prev
|
1130
|
+
prev.nxt = NULL
|
1131
|
+
P1.nterms += 1
|
1132
|
+
elif c==-1:
|
1133
|
+
# We need to insert between prev and T1
|
1134
|
+
if prev==NULL:
|
1135
|
+
P1.lead = term_create_blank(new_coef)
|
1136
|
+
P1.lead.mon[0] = new_mon[0]
|
1137
|
+
prev = P1.lead
|
1138
|
+
else:
|
1139
|
+
prev.nxt = term_create_blank(new_coef)
|
1140
|
+
prev.nxt.mon[0] = new_mon[0]
|
1141
|
+
prev = prev.nxt
|
1142
|
+
if T2 == P2.lead:
|
1143
|
+
out = prev
|
1144
|
+
prev.nxt = T1
|
1145
|
+
P1.nterms += 1
|
1146
|
+
else:
|
1147
|
+
# we add the coefficients and see what happens
|
1148
|
+
new_coef+=<object>(T1.coef)
|
1149
|
+
mon_free(new_mon)
|
1150
|
+
if new_coef:
|
1151
|
+
Py_INCREF(new_coef)
|
1152
|
+
Py_XDECREF(T1.coef)
|
1153
|
+
T1.coef = <PyObject*>new_coef
|
1154
|
+
if T2 == P2.lead:
|
1155
|
+
out = T1
|
1156
|
+
prev = T1
|
1157
|
+
T1 = T1.nxt
|
1158
|
+
else:
|
1159
|
+
P1.nterms -= 1
|
1160
|
+
T1 = term_free(T1)
|
1161
|
+
if prev==NULL:
|
1162
|
+
P1.lead = T1
|
1163
|
+
else:
|
1164
|
+
prev.nxt = T1
|
1165
|
+
if T2 == P2.lead:
|
1166
|
+
out = prev
|
1167
|
+
T2 = T2.nxt
|
1168
|
+
if out == NULL:
|
1169
|
+
return P2.lead
|
1170
|
+
return out
|
1171
|
+
|
1172
|
+
########################################
|
1173
|
+
#
|
1174
|
+
# Basics for homogeneous polynomials
|
1175
|
+
|
1176
|
+
# Create an empty polynomial whose to-be-inserted terms
|
1177
|
+
# have start- and end-points of the given integer labels
|
1178
|
+
# start and end.
|
1179
|
+
cdef path_homog_poly_t *homog_poly_create(int start, int end) except NULL:
|
1180
|
+
cdef path_homog_poly_t *out = <path_homog_poly_t*>check_malloc(sizeof(path_homog_poly_t))
|
1181
|
+
out.poly = poly_create()
|
1182
|
+
out.start = start
|
1183
|
+
out.end = end
|
1184
|
+
out.nxt = NULL
|
1185
|
+
return out
|
1186
|
+
|
1187
|
+
# Create a new homogeneous polynomial from a given polynomial P.
|
1188
|
+
# It is assumed that all terms of P have start- and end-points
|
1189
|
+
# with integer labels start and end. This assumption is NOT checked!
|
1190
|
+
# P is inserted, not copied.
|
1191
|
+
cdef path_homog_poly_t *homog_poly_init_poly(int start, int end, path_poly_t *P) except NULL:
|
1192
|
+
cdef path_homog_poly_t *out = <path_homog_poly_t*>check_malloc(sizeof(path_homog_poly_t))
|
1193
|
+
out.poly = P
|
1194
|
+
out.start = start
|
1195
|
+
out.end = end
|
1196
|
+
out.nxt = NULL
|
1197
|
+
return out
|
1198
|
+
|
1199
|
+
# L provides a list of pairs (P,coef), where P is a path
|
1200
|
+
# and coef the coefficient of the corresponding term.
|
1201
|
+
# With this function, one can create elements of a path algebra (pos==-1),
|
1202
|
+
# or elements of free modules over a path algebra in summand pos.
|
1203
|
+
# In either case, the length of left cofactors of each monomial will
|
1204
|
+
# be zero, and also the length of Schreyer monomials will be zero.
|
1205
|
+
cdef path_homog_poly_t *homog_poly_init_list(int start, int end, list L, path_order_t cmp_terms, long pos) except NULL:
|
1206
|
+
cdef path_homog_poly_t * out = homog_poly_create(start, end)
|
1207
|
+
cdef QuiverPath P
|
1208
|
+
for P, coef in L:
|
1209
|
+
poly_iadd_term_d(out.poly, term_create(coef, P._path, pos, 0, 0), cmp_terms)
|
1210
|
+
return out
|
1211
|
+
|
1212
|
+
cdef void homog_poly_free(path_homog_poly_t *P) noexcept:
|
1213
|
+
cdef path_homog_poly_t *nxt
|
1214
|
+
while P!=NULL:
|
1215
|
+
nxt = P.nxt
|
1216
|
+
poly_free(P.poly)
|
1217
|
+
sig_free(P)
|
1218
|
+
P = nxt
|
1219
|
+
|
1220
|
+
# Return a copy of H
|
1221
|
+
cdef path_homog_poly_t *homog_poly_copy(path_homog_poly_t *H) except NULL:
|
1222
|
+
cdef path_homog_poly_t *out
|
1223
|
+
cdef path_homog_poly_t *tmp
|
1224
|
+
if H == NULL:
|
1225
|
+
raise ValueError("the polynomial to be copied is the NULL pointer")
|
1226
|
+
out = homog_poly_create(H.start, H.end)
|
1227
|
+
poly_icopy(out.poly, H.poly)
|
1228
|
+
tmp = out
|
1229
|
+
H = H.nxt
|
1230
|
+
while H != NULL:
|
1231
|
+
sig_check()
|
1232
|
+
tmp.nxt = homog_poly_create(H.start, H.end)
|
1233
|
+
tmp = tmp.nxt
|
1234
|
+
poly_icopy(tmp.poly, H.poly)
|
1235
|
+
H = H.nxt
|
1236
|
+
return out
|
1237
|
+
|
1238
|
+
# Linearisation
|
1239
|
+
cdef list homog_poly_pickle(path_homog_poly_t *H):
|
1240
|
+
cdef list L = []
|
1241
|
+
while H != NULL:
|
1242
|
+
L.append((H.start, H.end, poly_pickle(H.poly)))
|
1243
|
+
H = H.nxt
|
1244
|
+
return L
|
1245
|
+
|
1246
|
+
# De-linearisation
|
1247
|
+
cdef path_homog_poly_t *homog_poly_unpickle(list data) except NULL:
|
1248
|
+
# ASSUMPTION: data is not empty
|
1249
|
+
cdef int start, end
|
1250
|
+
cdef list poly_data
|
1251
|
+
cdef path_homog_poly_t *out
|
1252
|
+
start, end, poly_data = data.pop(0)
|
1253
|
+
out = homog_poly_create(start, end)
|
1254
|
+
poly_inplace_unpickle(out.poly, poly_data)
|
1255
|
+
cdef path_homog_poly_t *tmp = out
|
1256
|
+
for start, end, poly_data in data:
|
1257
|
+
sig_check()
|
1258
|
+
tmp.nxt = homog_poly_create(start, end)
|
1259
|
+
tmp = tmp.nxt
|
1260
|
+
poly_inplace_unpickle(tmp.poly, poly_data)
|
1261
|
+
return out
|
1262
|
+
|
1263
|
+
# Return -H
|
1264
|
+
cdef path_homog_poly_t *homog_poly_neg(path_homog_poly_t *H) except NULL:
|
1265
|
+
cdef path_homog_poly_t *out
|
1266
|
+
cdef path_homog_poly_t *tmp
|
1267
|
+
if H == NULL:
|
1268
|
+
raise ValueError("the polynomial to be copied is the NULL pointer")
|
1269
|
+
out = homog_poly_create(H.start, H.end)
|
1270
|
+
poly_icopy_neg(out.poly, H.poly)
|
1271
|
+
tmp = out
|
1272
|
+
H = H.nxt
|
1273
|
+
while H != NULL:
|
1274
|
+
sig_check()
|
1275
|
+
tmp.nxt = homog_poly_create(H.start, H.end)
|
1276
|
+
tmp = tmp.nxt
|
1277
|
+
poly_icopy_neg(tmp.poly, H.poly)
|
1278
|
+
H = H.nxt
|
1279
|
+
return out
|
1280
|
+
|
1281
|
+
# Return coef*H
|
1282
|
+
cdef path_homog_poly_t *homog_poly_scale(path_homog_poly_t *H, object coef) except NULL:
|
1283
|
+
# The first component may be zero, all other zero components are removed.
|
1284
|
+
cdef path_homog_poly_t *out
|
1285
|
+
cdef path_homog_poly_t *tmp
|
1286
|
+
if H == NULL:
|
1287
|
+
raise ValueError("the polynomial to be copied is the NULL pointer")
|
1288
|
+
out = homog_poly_create(H.start, H.end)
|
1289
|
+
poly_icopy_scale(out.poly, H.poly, coef)
|
1290
|
+
tmp = out
|
1291
|
+
H = H.nxt
|
1292
|
+
while H != NULL:
|
1293
|
+
sig_check()
|
1294
|
+
tmp.nxt = homog_poly_create(H.start, H.end)
|
1295
|
+
poly_icopy_scale(tmp.nxt.poly, H.poly, coef)
|
1296
|
+
if tmp.nxt.poly.nterms == 0:
|
1297
|
+
homog_poly_free(tmp.nxt)
|
1298
|
+
tmp.nxt = NULL
|
1299
|
+
else:
|
1300
|
+
tmp = tmp.nxt
|
1301
|
+
H = H.nxt
|
1302
|
+
return out
|
1303
|
+
|
1304
|
+
cdef path_homog_poly_t *homog_poly_get_predecessor_of_component(path_homog_poly_t *H, int s, int e) noexcept:
|
1305
|
+
# Search through H.nxt.nxt... and return the pointer C to a component of H
|
1306
|
+
# such that either C.nxt.start==s and C.nxt.end==e, or the component for
|
1307
|
+
# (s,e) should be inserted between C and C.nxt. Return NULL if H==NULL or
|
1308
|
+
# (s,e) should be inserted in front of H.
|
1309
|
+
if H == NULL:
|
1310
|
+
return NULL
|
1311
|
+
if H.start > s:
|
1312
|
+
return NULL
|
1313
|
+
elif H.start == s and H.end >= e:
|
1314
|
+
return NULL
|
1315
|
+
while True:
|
1316
|
+
sig_check()
|
1317
|
+
if H.nxt == NULL:
|
1318
|
+
return H
|
1319
|
+
if H.nxt.start == s:
|
1320
|
+
if H.nxt.end >= e:
|
1321
|
+
return H
|
1322
|
+
elif H.nxt.start > s:
|
1323
|
+
return H
|
1324
|
+
H = H.nxt
|