passagemath-singular 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-singular might be problematic. Click here for more details.
- PySingular.cpython-314-x86_64-linux-gnu.so +0 -0
- passagemath_singular-10.6.31rc3.dist-info/METADATA +183 -0
- passagemath_singular-10.6.31rc3.dist-info/RECORD +491 -0
- passagemath_singular-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_singular-10.6.31rc3.dist-info/top_level.txt +3 -0
- passagemath_singular.libs/libSingular-4-20aec911.4.1.so +0 -0
- passagemath_singular.libs/libcddgmp-21acf0c6.so.0.1.3 +0 -0
- passagemath_singular.libs/libfactory-4-fcee31da.4.1.so +0 -0
- passagemath_singular.libs/libflint-66e12231.so.21.0.0 +0 -0
- passagemath_singular.libs/libgf2x-a4cdec90.so.3.0.0 +0 -0
- passagemath_singular.libs/libgfortran-83c28eba.so.5.0.0 +0 -0
- passagemath_singular.libs/libgmp-6e109695.so.10.5.0 +0 -0
- passagemath_singular.libs/libgsl-cda90e79.so.28.0.0 +0 -0
- passagemath_singular.libs/libmpfr-82690d50.so.6.2.1 +0 -0
- passagemath_singular.libs/libntl-e6f0d543.so.44.0.1 +0 -0
- passagemath_singular.libs/libomalloc-0-5c9e866e.9.6.so +0 -0
- passagemath_singular.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
- passagemath_singular.libs/libpolys-4-5c0a87e0.4.1.so +0 -0
- passagemath_singular.libs/libquadmath-2284e583.so.0.0.0 +0 -0
- passagemath_singular.libs/libreadline-ea270e21.so.8.2 +0 -0
- passagemath_singular.libs/libsingular_resources-4-a1aafc6d.4.1.so +0 -0
- passagemath_singular.libs/libtinfo-ceb117d9.so.6.3 +0 -0
- sage/algebras/all__sagemath_singular.py +3 -0
- sage/algebras/fusion_rings/all.py +19 -0
- sage/algebras/fusion_rings/f_matrix.py +2448 -0
- sage/algebras/fusion_rings/fast_parallel_fmats_methods.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/fusion_rings/fast_parallel_fmats_methods.pxd +5 -0
- sage/algebras/fusion_rings/fast_parallel_fmats_methods.pyx +538 -0
- sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pxd +3 -0
- sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pyx +331 -0
- sage/algebras/fusion_rings/fusion_double.py +899 -0
- sage/algebras/fusion_rings/fusion_ring.py +1580 -0
- sage/algebras/fusion_rings/poly_tup_engine.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/fusion_rings/poly_tup_engine.pxd +24 -0
- sage/algebras/fusion_rings/poly_tup_engine.pyx +579 -0
- sage/algebras/fusion_rings/shm_managers.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/fusion_rings/shm_managers.pxd +24 -0
- sage/algebras/fusion_rings/shm_managers.pyx +780 -0
- sage/algebras/letterplace/all.py +1 -0
- sage/algebras/letterplace/free_algebra_element_letterplace.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/letterplace/free_algebra_element_letterplace.pxd +18 -0
- sage/algebras/letterplace/free_algebra_element_letterplace.pyx +755 -0
- sage/algebras/letterplace/free_algebra_letterplace.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/letterplace/free_algebra_letterplace.pxd +35 -0
- sage/algebras/letterplace/free_algebra_letterplace.pyx +914 -0
- sage/algebras/letterplace/letterplace_ideal.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/letterplace/letterplace_ideal.pyx +408 -0
- sage/algebras/quatalg/all.py +2 -0
- sage/algebras/quatalg/quaternion_algebra.py +4778 -0
- sage/algebras/quatalg/quaternion_algebra_cython.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/quatalg/quaternion_algebra_cython.pyx +261 -0
- sage/algebras/quatalg/quaternion_algebra_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/quatalg/quaternion_algebra_element.pxd +29 -0
- sage/algebras/quatalg/quaternion_algebra_element.pyx +2176 -0
- sage/all__sagemath_singular.py +11 -0
- sage/ext_data/all__sagemath_singular.py +1 -0
- sage/ext_data/singular/function_field/core.lib +98 -0
- sage/interfaces/all__sagemath_singular.py +1 -0
- sage/interfaces/singular.py +2835 -0
- sage/libs/all__sagemath_singular.py +1 -0
- sage/libs/singular/__init__.py +1 -0
- sage/libs/singular/decl.pxd +1168 -0
- sage/libs/singular/function.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/singular/function.pxd +87 -0
- sage/libs/singular/function.pyx +1901 -0
- sage/libs/singular/function_factory.py +61 -0
- sage/libs/singular/groebner_strategy.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/singular/groebner_strategy.pxd +22 -0
- sage/libs/singular/groebner_strategy.pyx +582 -0
- sage/libs/singular/option.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/singular/option.pyx +671 -0
- sage/libs/singular/polynomial.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/singular/polynomial.pxd +39 -0
- sage/libs/singular/polynomial.pyx +661 -0
- sage/libs/singular/ring.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/singular/ring.pxd +58 -0
- sage/libs/singular/ring.pyx +893 -0
- sage/libs/singular/singular.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/singular/singular.pxd +72 -0
- sage/libs/singular/singular.pyx +1944 -0
- sage/libs/singular/standard_options.py +145 -0
- sage/matrix/all__sagemath_singular.py +1 -0
- sage/matrix/matrix_mpolynomial_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_mpolynomial_dense.pxd +7 -0
- sage/matrix/matrix_mpolynomial_dense.pyx +615 -0
- sage/rings/all__sagemath_singular.py +1 -0
- sage/rings/function_field/all__sagemath_singular.py +1 -0
- sage/rings/function_field/derivations_polymod.py +911 -0
- sage/rings/function_field/element_polymod.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/function_field/element_polymod.pyx +406 -0
- sage/rings/function_field/function_field_polymod.py +2611 -0
- sage/rings/function_field/ideal_polymod.py +1775 -0
- sage/rings/function_field/order_polymod.py +1475 -0
- sage/rings/function_field/place_polymod.py +681 -0
- sage/rings/polynomial/all__sagemath_singular.py +1 -0
- sage/rings/polynomial/multi_polynomial_ideal_libsingular.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/multi_polynomial_ideal_libsingular.pxd +5 -0
- sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx +339 -0
- sage/rings/polynomial/multi_polynomial_libsingular.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/multi_polynomial_libsingular.pxd +30 -0
- sage/rings/polynomial/multi_polynomial_libsingular.pyx +6277 -0
- sage/rings/polynomial/plural.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/plural.pxd +48 -0
- sage/rings/polynomial/plural.pyx +3171 -0
- sage/symbolic/all__sagemath_singular.py +1 -0
- sage/symbolic/comparison_impl.pxi +428 -0
- sage/symbolic/constants_c_impl.pxi +178 -0
- sage/symbolic/expression.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/symbolic/expression.pxd +7 -0
- sage/symbolic/expression.pyx +14200 -0
- sage/symbolic/getitem_impl.pxi +202 -0
- sage/symbolic/pynac.pxi +572 -0
- sage/symbolic/pynac_constant_impl.pxi +133 -0
- sage/symbolic/pynac_function_impl.pxi +206 -0
- sage/symbolic/pynac_impl.pxi +2576 -0
- sage/symbolic/pynac_wrap.h +124 -0
- sage/symbolic/series_impl.pxi +272 -0
- sage/symbolic/substitution_map_impl.pxi +94 -0
- sage_wheels/bin/ESingular +0 -0
- sage_wheels/bin/Singular +0 -0
- sage_wheels/bin/TSingular +0 -0
- sage_wheels/lib/singular/MOD/cohomo.la +41 -0
- sage_wheels/lib/singular/MOD/cohomo.so +0 -0
- sage_wheels/lib/singular/MOD/customstd.la +41 -0
- sage_wheels/lib/singular/MOD/customstd.so +0 -0
- sage_wheels/lib/singular/MOD/freealgebra.la +41 -0
- sage_wheels/lib/singular/MOD/freealgebra.so +0 -0
- sage_wheels/lib/singular/MOD/gfanlib.la +41 -0
- sage_wheels/lib/singular/MOD/gfanlib.so +0 -0
- sage_wheels/lib/singular/MOD/gitfan.la +41 -0
- sage_wheels/lib/singular/MOD/gitfan.so +0 -0
- sage_wheels/lib/singular/MOD/interval.la +41 -0
- sage_wheels/lib/singular/MOD/interval.so +0 -0
- sage_wheels/lib/singular/MOD/loctriv.la +41 -0
- sage_wheels/lib/singular/MOD/loctriv.so +0 -0
- sage_wheels/lib/singular/MOD/machinelearning.la +41 -0
- sage_wheels/lib/singular/MOD/machinelearning.so +0 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.la +41 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.so +0 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.la +41 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.so +0 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldQ.la +41 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldQ.so +0 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldZp.la +41 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldZp.so +0 -0
- sage_wheels/lib/singular/MOD/partialgb.la +41 -0
- sage_wheels/lib/singular/MOD/partialgb.so +0 -0
- sage_wheels/lib/singular/MOD/pyobject.la +41 -0
- sage_wheels/lib/singular/MOD/pyobject.so +0 -0
- sage_wheels/lib/singular/MOD/singmathic.la +41 -0
- sage_wheels/lib/singular/MOD/singmathic.so +0 -0
- sage_wheels/lib/singular/MOD/sispasm.la +41 -0
- sage_wheels/lib/singular/MOD/sispasm.so +0 -0
- sage_wheels/lib/singular/MOD/subsets.la +41 -0
- sage_wheels/lib/singular/MOD/subsets.so +0 -0
- sage_wheels/lib/singular/MOD/systhreads.la +41 -0
- sage_wheels/lib/singular/MOD/systhreads.so +0 -0
- sage_wheels/lib/singular/MOD/syzextra.la +41 -0
- sage_wheels/lib/singular/MOD/syzextra.so +0 -0
- sage_wheels/libexec/singular/MOD/change_cost +0 -0
- sage_wheels/libexec/singular/MOD/singularsurf +11 -0
- sage_wheels/libexec/singular/MOD/singularsurf_jupyter +9 -0
- sage_wheels/libexec/singular/MOD/singularsurf_win +10 -0
- sage_wheels/libexec/singular/MOD/solve_IP +0 -0
- sage_wheels/libexec/singular/MOD/surfex +16 -0
- sage_wheels/libexec/singular/MOD/toric_ideal +0 -0
- sage_wheels/share/factory/gftables/10201 +342 -0
- sage_wheels/share/factory/gftables/1024 +37 -0
- sage_wheels/share/factory/gftables/10609 +356 -0
- sage_wheels/share/factory/gftables/11449 +384 -0
- sage_wheels/share/factory/gftables/11881 +398 -0
- sage_wheels/share/factory/gftables/121 +6 -0
- sage_wheels/share/factory/gftables/12167 +408 -0
- sage_wheels/share/factory/gftables/125 +7 -0
- sage_wheels/share/factory/gftables/12769 +428 -0
- sage_wheels/share/factory/gftables/128 +7 -0
- sage_wheels/share/factory/gftables/1331 +47 -0
- sage_wheels/share/factory/gftables/1369 +48 -0
- sage_wheels/share/factory/gftables/14641 +490 -0
- sage_wheels/share/factory/gftables/15625 +523 -0
- sage_wheels/share/factory/gftables/16 +3 -0
- sage_wheels/share/factory/gftables/16129 +540 -0
- sage_wheels/share/factory/gftables/16384 +549 -0
- sage_wheels/share/factory/gftables/16807 +563 -0
- sage_wheels/share/factory/gftables/1681 +58 -0
- sage_wheels/share/factory/gftables/169 +8 -0
- sage_wheels/share/factory/gftables/17161 +574 -0
- sage_wheels/share/factory/gftables/1849 +64 -0
- sage_wheels/share/factory/gftables/18769 +628 -0
- sage_wheels/share/factory/gftables/19321 +646 -0
- sage_wheels/share/factory/gftables/19683 +659 -0
- sage_wheels/share/factory/gftables/2048 +71 -0
- sage_wheels/share/factory/gftables/2187 +75 -0
- sage_wheels/share/factory/gftables/2197 +76 -0
- sage_wheels/share/factory/gftables/2209 +76 -0
- sage_wheels/share/factory/gftables/22201 +742 -0
- sage_wheels/share/factory/gftables/22801 +762 -0
- sage_wheels/share/factory/gftables/2401 +82 -0
- sage_wheels/share/factory/gftables/243 +11 -0
- sage_wheels/share/factory/gftables/24389 +815 -0
- sage_wheels/share/factory/gftables/24649 +824 -0
- sage_wheels/share/factory/gftables/25 +3 -0
- sage_wheels/share/factory/gftables/256 +11 -0
- sage_wheels/share/factory/gftables/26569 +888 -0
- sage_wheels/share/factory/gftables/27 +3 -0
- sage_wheels/share/factory/gftables/27889 +932 -0
- sage_wheels/share/factory/gftables/2809 +96 -0
- sage_wheels/share/factory/gftables/28561 +954 -0
- sage_wheels/share/factory/gftables/289 +12 -0
- sage_wheels/share/factory/gftables/29791 +995 -0
- sage_wheels/share/factory/gftables/29929 +1000 -0
- sage_wheels/share/factory/gftables/3125 +107 -0
- sage_wheels/share/factory/gftables/32 +4 -0
- sage_wheels/share/factory/gftables/32041 +1070 -0
- sage_wheels/share/factory/gftables/32761 +1094 -0
- sage_wheels/share/factory/gftables/32768 +1095 -0
- sage_wheels/share/factory/gftables/343 +14 -0
- sage_wheels/share/factory/gftables/3481 +118 -0
- sage_wheels/share/factory/gftables/361 +14 -0
- sage_wheels/share/factory/gftables/36481 +1218 -0
- sage_wheels/share/factory/gftables/3721 +126 -0
- sage_wheels/share/factory/gftables/37249 +1244 -0
- sage_wheels/share/factory/gftables/38809 +1296 -0
- sage_wheels/share/factory/gftables/39601 +1322 -0
- sage_wheels/share/factory/gftables/4 +3 -0
- sage_wheels/share/factory/gftables/4096 +139 -0
- sage_wheels/share/factory/gftables/44521 +1486 -0
- sage_wheels/share/factory/gftables/4489 +152 -0
- sage_wheels/share/factory/gftables/49 +4 -0
- sage_wheels/share/factory/gftables/4913 +166 -0
- sage_wheels/share/factory/gftables/49729 +1660 -0
- sage_wheels/share/factory/gftables/5041 +170 -0
- sage_wheels/share/factory/gftables/50653 +1691 -0
- sage_wheels/share/factory/gftables/512 +20 -0
- sage_wheels/share/factory/gftables/51529 +1720 -0
- sage_wheels/share/factory/gftables/52441 +1750 -0
- sage_wheels/share/factory/gftables/529 +20 -0
- sage_wheels/share/factory/gftables/5329 +180 -0
- sage_wheels/share/factory/gftables/54289 +1812 -0
- sage_wheels/share/factory/gftables/57121 +1906 -0
- sage_wheels/share/factory/gftables/58081 +1938 -0
- sage_wheels/share/factory/gftables/59049 +1971 -0
- sage_wheels/share/factory/gftables/6241 +210 -0
- sage_wheels/share/factory/gftables/625 +23 -0
- sage_wheels/share/factory/gftables/63001 +2102 -0
- sage_wheels/share/factory/gftables/64 +5 -0
- sage_wheels/share/factory/gftables/6561 +221 -0
- sage_wheels/share/factory/gftables/6859 +231 -0
- sage_wheels/share/factory/gftables/6889 +232 -0
- sage_wheels/share/factory/gftables/729 +27 -0
- sage_wheels/share/factory/gftables/7921 +266 -0
- sage_wheels/share/factory/gftables/8 +3 -0
- sage_wheels/share/factory/gftables/81 +5 -0
- sage_wheels/share/factory/gftables/8192 +276 -0
- sage_wheels/share/factory/gftables/841 +30 -0
- sage_wheels/share/factory/gftables/9 +3 -0
- sage_wheels/share/factory/gftables/9409 +316 -0
- sage_wheels/share/factory/gftables/961 +34 -0
- sage_wheels/share/info/singular.info +191898 -0
- sage_wheels/share/singular/LIB/GND.lib +1359 -0
- sage_wheels/share/singular/LIB/JMBTest.lib +976 -0
- sage_wheels/share/singular/LIB/JMSConst.lib +1363 -0
- sage_wheels/share/singular/LIB/KVequiv.lib +699 -0
- sage_wheels/share/singular/LIB/SingularityDBM.lib +491 -0
- sage_wheels/share/singular/LIB/VecField.lib +1542 -0
- sage_wheels/share/singular/LIB/absfact.lib +959 -0
- sage_wheels/share/singular/LIB/ainvar.lib +730 -0
- sage_wheels/share/singular/LIB/aksaka.lib +419 -0
- sage_wheels/share/singular/LIB/alexpoly.lib +2542 -0
- sage_wheels/share/singular/LIB/algebra.lib +1193 -0
- sage_wheels/share/singular/LIB/all.lib +136 -0
- sage_wheels/share/singular/LIB/arcpoint.lib +514 -0
- sage_wheels/share/singular/LIB/arnold.lib +4553 -0
- sage_wheels/share/singular/LIB/arnoldclassify.lib +2058 -0
- sage_wheels/share/singular/LIB/arr.lib +3486 -0
- sage_wheels/share/singular/LIB/assprimeszerodim.lib +755 -0
- sage_wheels/share/singular/LIB/autgradalg.lib +3361 -0
- sage_wheels/share/singular/LIB/bfun.lib +1964 -0
- sage_wheels/share/singular/LIB/bimodules.lib +774 -0
- sage_wheels/share/singular/LIB/brillnoether.lib +226 -0
- sage_wheels/share/singular/LIB/brnoeth.lib +5017 -0
- sage_wheels/share/singular/LIB/central.lib +2169 -0
- sage_wheels/share/singular/LIB/chern.lib +4162 -0
- sage_wheels/share/singular/LIB/cimonom.lib +571 -0
- sage_wheels/share/singular/LIB/cisimplicial.lib +1835 -0
- sage_wheels/share/singular/LIB/classify.lib +3239 -0
- sage_wheels/share/singular/LIB/classify2.lib +1462 -0
- sage_wheels/share/singular/LIB/classifyMapGerms.lib +1515 -0
- sage_wheels/share/singular/LIB/classify_aeq.lib +3253 -0
- sage_wheels/share/singular/LIB/classifyceq.lib +2092 -0
- sage_wheels/share/singular/LIB/classifyci.lib +1133 -0
- sage_wheels/share/singular/LIB/combinat.lib +91 -0
- sage_wheels/share/singular/LIB/compregb.lib +276 -0
- sage_wheels/share/singular/LIB/control.lib +1636 -0
- sage_wheels/share/singular/LIB/crypto.lib +3795 -0
- sage_wheels/share/singular/LIB/curveInv.lib +667 -0
- sage_wheels/share/singular/LIB/curvepar.lib +1817 -0
- sage_wheels/share/singular/LIB/customstd.lib +100 -0
- sage_wheels/share/singular/LIB/deRham.lib +5979 -0
- sage_wheels/share/singular/LIB/decodegb.lib +2134 -0
- sage_wheels/share/singular/LIB/decomp.lib +1655 -0
- sage_wheels/share/singular/LIB/deflation.lib +872 -0
- sage_wheels/share/singular/LIB/deform.lib +925 -0
- sage_wheels/share/singular/LIB/difform.lib +3055 -0
- sage_wheels/share/singular/LIB/divisors.lib +750 -0
- sage_wheels/share/singular/LIB/dmod.lib +5817 -0
- sage_wheels/share/singular/LIB/dmodapp.lib +3269 -0
- sage_wheels/share/singular/LIB/dmodideal.lib +1211 -0
- sage_wheels/share/singular/LIB/dmodloc.lib +2645 -0
- sage_wheels/share/singular/LIB/dmodvar.lib +818 -0
- sage_wheels/share/singular/LIB/dummy.lib +17 -0
- sage_wheels/share/singular/LIB/elim.lib +1009 -0
- sage_wheels/share/singular/LIB/ellipticcovers.lib +548 -0
- sage_wheels/share/singular/LIB/enumpoints.lib +146 -0
- sage_wheels/share/singular/LIB/equising.lib +2127 -0
- sage_wheels/share/singular/LIB/ffmodstd.lib +2384 -0
- sage_wheels/share/singular/LIB/ffsolve.lib +1289 -0
- sage_wheels/share/singular/LIB/findifs.lib +778 -0
- sage_wheels/share/singular/LIB/finitediff.lib +1768 -0
- sage_wheels/share/singular/LIB/finvar.lib +7989 -0
- sage_wheels/share/singular/LIB/fpadim.lib +2429 -0
- sage_wheels/share/singular/LIB/fpalgebras.lib +1666 -0
- sage_wheels/share/singular/LIB/fpaprops.lib +1462 -0
- sage_wheels/share/singular/LIB/freegb.lib +3853 -0
- sage_wheels/share/singular/LIB/general.lib +1350 -0
- sage_wheels/share/singular/LIB/gfan.lib +1768 -0
- sage_wheels/share/singular/LIB/gitfan.lib +3130 -0
- sage_wheels/share/singular/LIB/gkdim.lib +99 -0
- sage_wheels/share/singular/LIB/gmspoly.lib +589 -0
- sage_wheels/share/singular/LIB/gmssing.lib +1739 -0
- sage_wheels/share/singular/LIB/goettsche.lib +909 -0
- sage_wheels/share/singular/LIB/graal.lib +1366 -0
- sage_wheels/share/singular/LIB/gradedModules.lib +2541 -0
- sage_wheels/share/singular/LIB/graphics.lib +360 -0
- sage_wheels/share/singular/LIB/grobcov.lib +7706 -0
- sage_wheels/share/singular/LIB/groups.lib +1123 -0
- sage_wheels/share/singular/LIB/grwalk.lib +507 -0
- sage_wheels/share/singular/LIB/hdepth.lib +194 -0
- sage_wheels/share/singular/LIB/help.cnf +57 -0
- sage_wheels/share/singular/LIB/hess.lib +1946 -0
- sage_wheels/share/singular/LIB/hnoether.lib +4292 -0
- sage_wheels/share/singular/LIB/hodge.lib +400 -0
- sage_wheels/share/singular/LIB/homolog.lib +1965 -0
- sage_wheels/share/singular/LIB/hyperel.lib +975 -0
- sage_wheels/share/singular/LIB/inout.lib +679 -0
- sage_wheels/share/singular/LIB/integralbasis.lib +6224 -0
- sage_wheels/share/singular/LIB/interval.lib +1418 -0
- sage_wheels/share/singular/LIB/intprog.lib +778 -0
- sage_wheels/share/singular/LIB/invar.lib +443 -0
- sage_wheels/share/singular/LIB/involut.lib +980 -0
- sage_wheels/share/singular/LIB/jacobson.lib +1215 -0
- sage_wheels/share/singular/LIB/kskernel.lib +534 -0
- sage_wheels/share/singular/LIB/latex.lib +3146 -0
- sage_wheels/share/singular/LIB/lejeune.lib +651 -0
- sage_wheels/share/singular/LIB/linalg.lib +2040 -0
- sage_wheels/share/singular/LIB/locnormal.lib +212 -0
- sage_wheels/share/singular/LIB/lrcalc.lib +526 -0
- sage_wheels/share/singular/LIB/makedbm.lib +294 -0
- sage_wheels/share/singular/LIB/mathml.lib +813 -0
- sage_wheels/share/singular/LIB/matrix.lib +1372 -0
- sage_wheels/share/singular/LIB/maxlike.lib +1132 -0
- sage_wheels/share/singular/LIB/methods.lib +212 -0
- sage_wheels/share/singular/LIB/moddiq.lib +322 -0
- sage_wheels/share/singular/LIB/modfinduni.lib +181 -0
- sage_wheels/share/singular/LIB/modnormal.lib +218 -0
- sage_wheels/share/singular/LIB/modprimdec.lib +1278 -0
- sage_wheels/share/singular/LIB/modquotient.lib +269 -0
- sage_wheels/share/singular/LIB/modstd.lib +1024 -0
- sage_wheels/share/singular/LIB/modular.lib +545 -0
- sage_wheels/share/singular/LIB/modules.lib +2561 -0
- sage_wheels/share/singular/LIB/modwalk.lib +609 -0
- sage_wheels/share/singular/LIB/mondromy.lib +1016 -0
- sage_wheels/share/singular/LIB/monomialideal.lib +3851 -0
- sage_wheels/share/singular/LIB/mprimdec.lib +2353 -0
- sage_wheels/share/singular/LIB/mregular.lib +1863 -0
- sage_wheels/share/singular/LIB/multigrading.lib +5629 -0
- sage_wheels/share/singular/LIB/ncHilb.lib +777 -0
- sage_wheels/share/singular/LIB/ncModslimgb.lib +791 -0
- sage_wheels/share/singular/LIB/ncalg.lib +16311 -0
- sage_wheels/share/singular/LIB/ncall.lib +31 -0
- sage_wheels/share/singular/LIB/ncdecomp.lib +468 -0
- sage_wheels/share/singular/LIB/ncfactor.lib +13371 -0
- sage_wheels/share/singular/LIB/ncfrac.lib +1023 -0
- sage_wheels/share/singular/LIB/nchilbert.lib +448 -0
- sage_wheels/share/singular/LIB/nchomolog.lib +759 -0
- sage_wheels/share/singular/LIB/ncloc.lib +361 -0
- sage_wheels/share/singular/LIB/ncpreim.lib +795 -0
- sage_wheels/share/singular/LIB/ncrat.lib +2849 -0
- sage_wheels/share/singular/LIB/nctools.lib +1887 -0
- sage_wheels/share/singular/LIB/nets.lib +1456 -0
- sage_wheels/share/singular/LIB/nfmodstd.lib +1000 -0
- sage_wheels/share/singular/LIB/nfmodsyz.lib +732 -0
- sage_wheels/share/singular/LIB/noether.lib +1106 -0
- sage_wheels/share/singular/LIB/normal.lib +8700 -0
- sage_wheels/share/singular/LIB/normaliz.lib +2226 -0
- sage_wheels/share/singular/LIB/ntsolve.lib +362 -0
- sage_wheels/share/singular/LIB/numerAlg.lib +560 -0
- sage_wheels/share/singular/LIB/numerDecom.lib +2261 -0
- sage_wheels/share/singular/LIB/olga.lib +1933 -0
- sage_wheels/share/singular/LIB/orbitparam.lib +351 -0
- sage_wheels/share/singular/LIB/parallel.lib +319 -0
- sage_wheels/share/singular/LIB/paraplanecurves.lib +3110 -0
- sage_wheels/share/singular/LIB/perron.lib +202 -0
- sage_wheels/share/singular/LIB/pfd.lib +2223 -0
- sage_wheels/share/singular/LIB/phindex.lib +642 -0
- sage_wheels/share/singular/LIB/pointid.lib +673 -0
- sage_wheels/share/singular/LIB/polybori.lib +1430 -0
- sage_wheels/share/singular/LIB/polyclass.lib +525 -0
- sage_wheels/share/singular/LIB/polylib.lib +1174 -0
- sage_wheels/share/singular/LIB/polymake.lib +1902 -0
- sage_wheels/share/singular/LIB/presolve.lib +1533 -0
- sage_wheels/share/singular/LIB/primdec.lib +9576 -0
- sage_wheels/share/singular/LIB/primdecint.lib +1782 -0
- sage_wheels/share/singular/LIB/primitiv.lib +401 -0
- sage_wheels/share/singular/LIB/puiseuxexpansions.lib +1631 -0
- sage_wheels/share/singular/LIB/purityfiltration.lib +960 -0
- sage_wheels/share/singular/LIB/qhmoduli.lib +1561 -0
- sage_wheels/share/singular/LIB/qmatrix.lib +293 -0
- sage_wheels/share/singular/LIB/random.lib +455 -0
- sage_wheels/share/singular/LIB/ratgb.lib +489 -0
- sage_wheels/share/singular/LIB/realclassify.lib +5759 -0
- sage_wheels/share/singular/LIB/realizationMatroids.lib +772 -0
- sage_wheels/share/singular/LIB/realrad.lib +1197 -0
- sage_wheels/share/singular/LIB/recover.lib +2628 -0
- sage_wheels/share/singular/LIB/redcgs.lib +3984 -0
- sage_wheels/share/singular/LIB/reesclos.lib +465 -0
- sage_wheels/share/singular/LIB/resbinomial.lib +2802 -0
- sage_wheels/share/singular/LIB/resgraph.lib +789 -0
- sage_wheels/share/singular/LIB/resjung.lib +820 -0
- sage_wheels/share/singular/LIB/resolve.lib +5110 -0
- sage_wheels/share/singular/LIB/resources.lib +170 -0
- sage_wheels/share/singular/LIB/reszeta.lib +5473 -0
- sage_wheels/share/singular/LIB/ring.lib +1328 -0
- sage_wheels/share/singular/LIB/ringgb.lib +343 -0
- sage_wheels/share/singular/LIB/rinvar.lib +1153 -0
- sage_wheels/share/singular/LIB/rootisolation.lib +1481 -0
- sage_wheels/share/singular/LIB/rootsmr.lib +709 -0
- sage_wheels/share/singular/LIB/rootsur.lib +886 -0
- sage_wheels/share/singular/LIB/rstandard.lib +607 -0
- sage_wheels/share/singular/LIB/rwalk.lib +336 -0
- sage_wheels/share/singular/LIB/sagbi.lib +1353 -0
- sage_wheels/share/singular/LIB/sagbiNormaliz.lib +1622 -0
- sage_wheels/share/singular/LIB/sagbiNormaliz0.lib +1498 -0
- sage_wheels/share/singular/LIB/sagbigrob.lib +449 -0
- sage_wheels/share/singular/LIB/schreyer.lib +321 -0
- sage_wheels/share/singular/LIB/schubert.lib +2551 -0
- sage_wheels/share/singular/LIB/sets.lib +524 -0
- sage_wheels/share/singular/LIB/sheafcoh.lib +1663 -0
- sage_wheels/share/singular/LIB/signcond.lib +437 -0
- sage_wheels/share/singular/LIB/sing.lib +1094 -0
- sage_wheels/share/singular/LIB/sing4ti2.lib +419 -0
- sage_wheels/share/singular/LIB/solve.lib +2243 -0
- sage_wheels/share/singular/LIB/spcurve.lib +1077 -0
- sage_wheels/share/singular/LIB/spectrum.lib +62 -0
- sage_wheels/share/singular/LIB/sresext.lib +757 -0
- sage_wheels/share/singular/LIB/ssi.lib +143 -0
- sage_wheels/share/singular/LIB/standard.lib +2769 -0
- sage_wheels/share/singular/LIB/stanleyreisner.lib +473 -0
- sage_wheels/share/singular/LIB/stdmodule.lib +547 -0
- sage_wheels/share/singular/LIB/stratify.lib +1070 -0
- sage_wheels/share/singular/LIB/surf.lib +506 -0
- sage_wheels/share/singular/LIB/surf_jupyter.lib +223 -0
- sage_wheels/share/singular/LIB/surfacesignature.lib +522 -0
- sage_wheels/share/singular/LIB/surfex.lib +1462 -0
- sage_wheels/share/singular/LIB/swalk.lib +877 -0
- sage_wheels/share/singular/LIB/symodstd.lib +1570 -0
- sage_wheels/share/singular/LIB/systhreads.lib +74 -0
- sage_wheels/share/singular/LIB/tasks.lib +1324 -0
- sage_wheels/share/singular/LIB/tateProdCplxNegGrad.lib +2412 -0
- sage_wheels/share/singular/LIB/teachstd.lib +858 -0
- sage_wheels/share/singular/LIB/template.lib +116 -0
- sage_wheels/share/singular/LIB/toric.lib +1119 -0
- sage_wheels/share/singular/LIB/transformation.lib +116 -0
- sage_wheels/share/singular/LIB/triang.lib +1197 -0
- sage_wheels/share/singular/LIB/tropical.lib +8741 -0
- sage_wheels/share/singular/LIB/tropicalEllipticCovers.lib +2922 -0
- sage_wheels/share/singular/LIB/tropicalNewton.lib +1128 -0
- sage_wheels/share/singular/LIB/tst.lib +1108 -0
- sage_wheels/share/singular/LIB/weierstr.lib +241 -0
- sage_wheels/share/singular/LIB/zeroset.lib +1478 -0
- sage_wheels/share/singular/emacs/.emacs-general +184 -0
- sage_wheels/share/singular/emacs/.emacs-singular +234 -0
- sage_wheels/share/singular/emacs/COPYING +44 -0
- sage_wheels/share/singular/emacs/cmd-cmpl.el +241 -0
- sage_wheels/share/singular/emacs/ex-cmpl.el +1681 -0
- sage_wheels/share/singular/emacs/hlp-cmpl.el +4318 -0
- sage_wheels/share/singular/emacs/lib-cmpl.el +179 -0
- sage_wheels/share/singular/emacs/singular.el +4273 -0
- sage_wheels/share/singular/emacs/singular.xpm +39 -0
- sage_wheels/share/singular/singular.idx +5002 -0
|
@@ -0,0 +1,2576 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-singular
|
|
2
|
+
# sage.doctest: needs sage.symbolic
|
|
3
|
+
"""
|
|
4
|
+
Pynac interface
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# ****************************************************************************
|
|
8
|
+
# Copyright (C) 2008 William Stein <wstein@gmail.com>
|
|
9
|
+
# Copyright (C) 2008-2014 Burcin Erocal <burcin@erocal.org>
|
|
10
|
+
# Copyright (C) 2009 Carl Witty
|
|
11
|
+
# Copyright (C) 2009 Minh Van Nguyen
|
|
12
|
+
# Copyright (C) 2009-2011 Mike Hansen
|
|
13
|
+
# Copyright (C) 2010 Flavia Stan
|
|
14
|
+
# Copyright (C) 2010 Tom Coates
|
|
15
|
+
# Copyright (C) 2014 Eviatar Bach
|
|
16
|
+
# Copyright (C) 2014 Jean-Pierre Flori
|
|
17
|
+
# Copyright (C) 2014 R. Andrew Ohana
|
|
18
|
+
# Copyright (C) 2015-2017 Ralf Stephan
|
|
19
|
+
# Copyright (C) 2015-2018 Jeroen Demeyer <jdemeyer@cage.ugent.be>
|
|
20
|
+
# Copyright (C) 2015-2020 Marc Mezzarobba
|
|
21
|
+
# Copyright (C) 2016 Frédéric Chapoton
|
|
22
|
+
# Copyright (C) 2016 Jori Mäntysalo
|
|
23
|
+
# Copyright (C) 2016 Nils Bruin
|
|
24
|
+
# Copyright (C) 2016-2018 Frédéric Chapoton
|
|
25
|
+
# Copyright (C) 2017-2018 Erik M. Bray
|
|
26
|
+
# Copyright (C) 2019 Volker Braun
|
|
27
|
+
# Copyright (C) 2021 Jonathan Kliem
|
|
28
|
+
# Copyright (C) 2021 Matthias Koeppe
|
|
29
|
+
#
|
|
30
|
+
# This program is free software: you can redistribute it and/or modify
|
|
31
|
+
# it under the terms of the GNU General Public License as published by
|
|
32
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
33
|
+
# (at your option) any later version.
|
|
34
|
+
# https://www.gnu.org/licenses/
|
|
35
|
+
# ****************************************************************************
|
|
36
|
+
|
|
37
|
+
from cpython cimport *
|
|
38
|
+
from libc cimport math
|
|
39
|
+
|
|
40
|
+
from sage.arith.misc import bernoulli, factorial, GCD as gcd, is_prime
|
|
41
|
+
from sage.arith.functions import lcm
|
|
42
|
+
from sage.cpython.string cimport str_to_bytes, char_to_str
|
|
43
|
+
from sage.ext.stdsage cimport PY_NEW
|
|
44
|
+
from sage.libs.gmp.all cimport *
|
|
45
|
+
from sage.libs.gsl.complex cimport *
|
|
46
|
+
from sage.libs.gsl.gamma cimport gsl_sf_lngamma_complex_e
|
|
47
|
+
from sage.libs.mpmath import utils as mpmath_utils
|
|
48
|
+
from sage.misc.persist import loads, dumps
|
|
49
|
+
from sage.rings.integer_ring import ZZ
|
|
50
|
+
from sage.rings.integer cimport Integer, smallInteger
|
|
51
|
+
from sage.rings.rational cimport Rational
|
|
52
|
+
from sage.rings.real_mpfr import RR, RealField
|
|
53
|
+
from sage.rings.rational cimport rational_power_parts
|
|
54
|
+
from sage.rings.real_double cimport RealDoubleElement
|
|
55
|
+
from sage.rings.cc import CC
|
|
56
|
+
from sage.structure.coerce cimport coercion_model
|
|
57
|
+
from sage.structure.element cimport Element, parent
|
|
58
|
+
from sage.symbolic.function cimport Function
|
|
59
|
+
|
|
60
|
+
#################################################################
|
|
61
|
+
# Symbolic function helpers
|
|
62
|
+
#################################################################
|
|
63
|
+
|
|
64
|
+
cdef ex_to_pyExpression(GEx juice):
|
|
65
|
+
"""
|
|
66
|
+
Convert given GiNaC::ex object to a python Expression instance.
|
|
67
|
+
|
|
68
|
+
Used to pass parameters to custom power and series functions.
|
|
69
|
+
"""
|
|
70
|
+
cdef Expression nex
|
|
71
|
+
nex = <Expression>Expression.__new__(Expression)
|
|
72
|
+
nex._gobj = GEx(juice)
|
|
73
|
+
from sage.symbolic.ring import SR
|
|
74
|
+
nex._parent = SR
|
|
75
|
+
return nex
|
|
76
|
+
|
|
77
|
+
cdef exprseq_to_PyTuple(GEx seq):
|
|
78
|
+
"""
|
|
79
|
+
Convert an exprseq to a Python tuple.
|
|
80
|
+
|
|
81
|
+
Used while converting arguments of symbolic functions to Python objects.
|
|
82
|
+
|
|
83
|
+
EXAMPLES::
|
|
84
|
+
|
|
85
|
+
sage: from sage.symbolic.function import BuiltinFunction
|
|
86
|
+
sage: class TFunc(BuiltinFunction):
|
|
87
|
+
....: def __init__(self):
|
|
88
|
+
....: BuiltinFunction.__init__(self, 'tfunc', nargs=0)
|
|
89
|
+
....:
|
|
90
|
+
....: def _eval_(self, *args):
|
|
91
|
+
....: print("len(args): %s, types: %s"%(len(args), str(list(map(type, args)))))
|
|
92
|
+
....: for i, a in enumerate(args):
|
|
93
|
+
....: if isinstance(a, tuple):
|
|
94
|
+
....: print("argument %s is a tuple, with types %s"%(str(i), str(list(map(type, a)))))
|
|
95
|
+
....:
|
|
96
|
+
sage: tfunc = TFunc()
|
|
97
|
+
sage: u = SR._force_pyobject((1, x+1, 2))
|
|
98
|
+
sage: tfunc(u, x, SR._force_pyobject((3.0, 2^x)))
|
|
99
|
+
len(args): 3, types: [<... 'tuple'>, <class 'sage.symbolic.expression.Expression'>, <... 'tuple'>]
|
|
100
|
+
argument 0 is a tuple, with types [<class 'sage.rings.integer.Integer'>, <class 'sage.symbolic.expression.Expression'>, <class 'sage.rings.integer.Integer'>]
|
|
101
|
+
argument 2 is a tuple, with types [<class 'sage.rings.real_mpfr.RealLiteral'>, <class 'sage.symbolic.expression.Expression'>]
|
|
102
|
+
tfunc((1, x + 1, 2), x, (3.00000000000000, 2^x))
|
|
103
|
+
"""
|
|
104
|
+
from sage.symbolic.ring import SR
|
|
105
|
+
res = []
|
|
106
|
+
for i in range(seq.nops()):
|
|
107
|
+
if is_a_numeric(seq.op(i)):
|
|
108
|
+
res.append(py_object_from_numeric(seq.op(i)))
|
|
109
|
+
elif is_exactly_a_exprseq(seq.op(i)):
|
|
110
|
+
res.append(exprseq_to_PyTuple(seq.op(i)))
|
|
111
|
+
else:
|
|
112
|
+
res.append(new_Expression_from_GEx(SR, seq.op(i)))
|
|
113
|
+
return tuple(res)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def unpack_operands(Expression ex):
|
|
117
|
+
"""
|
|
118
|
+
EXAMPLES::
|
|
119
|
+
|
|
120
|
+
sage: from sage.symbolic.expression import unpack_operands
|
|
121
|
+
sage: t = SR._force_pyobject((1, 2, x, x+1, x+2))
|
|
122
|
+
sage: unpack_operands(t)
|
|
123
|
+
(1, 2, x, x + 1, x + 2)
|
|
124
|
+
sage: type(unpack_operands(t))
|
|
125
|
+
<... 'tuple'>
|
|
126
|
+
sage: list(map(type, unpack_operands(t)))
|
|
127
|
+
[<class 'sage.rings.integer.Integer'>, <class 'sage.rings.integer.Integer'>, <class 'sage.symbolic.expression.Expression'>, <class 'sage.symbolic.expression.Expression'>, <class 'sage.symbolic.expression.Expression'>]
|
|
128
|
+
sage: u = SR._force_pyobject((t, x^2))
|
|
129
|
+
sage: unpack_operands(u)
|
|
130
|
+
((1, 2, x, x + 1, x + 2), x^2)
|
|
131
|
+
sage: type(unpack_operands(u)[0])
|
|
132
|
+
<... 'tuple'>
|
|
133
|
+
"""
|
|
134
|
+
return exprseq_to_PyTuple(ex._gobj)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
cdef exvector_to_PyTuple(GExVector seq):
|
|
138
|
+
"""
|
|
139
|
+
Convert arguments list given to a function to a PyTuple.
|
|
140
|
+
|
|
141
|
+
Used to pass arguments to python methods assigned to custom
|
|
142
|
+
evaluation, derivative, etc. functions of symbolic functions.
|
|
143
|
+
|
|
144
|
+
We convert Python objects wrapped in symbolic expressions back to regular
|
|
145
|
+
Python objects.
|
|
146
|
+
|
|
147
|
+
EXAMPLES::
|
|
148
|
+
|
|
149
|
+
sage: from sage.symbolic.function import BuiltinFunction
|
|
150
|
+
sage: class TFunc(BuiltinFunction):
|
|
151
|
+
....: def __init__(self):
|
|
152
|
+
....: BuiltinFunction.__init__(self, 'tfunc', nargs=0)
|
|
153
|
+
....:
|
|
154
|
+
....: def _eval_(self, *args):
|
|
155
|
+
....: print("len(args): %s, types: %s"%(len(args), str(list(map(type, args)))))
|
|
156
|
+
sage: tfunc = TFunc()
|
|
157
|
+
sage: u = SR._force_pyobject((1, x+1, 2))
|
|
158
|
+
sage: tfunc(u, x, 3.0, 5.0r)
|
|
159
|
+
len(args): 4, types: [<... 'tuple'>, <class 'sage.symbolic.expression.Expression'>, <class 'sage.rings.real_mpfr.RealLiteral'>, <... 'float'>]
|
|
160
|
+
tfunc((1, x + 1, 2), x, 3.00000000000000, 5.0)
|
|
161
|
+
|
|
162
|
+
TESTS:
|
|
163
|
+
|
|
164
|
+
Check if symbolic functions in the arguments are preserved::
|
|
165
|
+
|
|
166
|
+
sage: tfunc(sin(x), tfunc(1, x^2))
|
|
167
|
+
len(args): 2, types: [<class 'sage.rings.integer.Integer'>, <class 'sage.symbolic.expression.Expression'>]
|
|
168
|
+
len(args): 2, types: [<class 'sage.symbolic.expression.Expression'>, <class 'sage.symbolic.expression.Expression'>]
|
|
169
|
+
tfunc(sin(x), tfunc(1, x^2))
|
|
170
|
+
"""
|
|
171
|
+
from sage.symbolic.ring import SR
|
|
172
|
+
res = []
|
|
173
|
+
for i in range(seq.size()):
|
|
174
|
+
if is_a_numeric(seq.at(i)):
|
|
175
|
+
res.append(py_object_from_numeric(seq.at(i)))
|
|
176
|
+
elif is_exactly_a_exprseq(seq.at(i)):
|
|
177
|
+
res.append(exprseq_to_PyTuple(seq.at(i)))
|
|
178
|
+
else:
|
|
179
|
+
res.append(new_Expression_from_GEx(SR, seq.at(i)))
|
|
180
|
+
return tuple(res)
|
|
181
|
+
|
|
182
|
+
cdef GEx pyExpression_to_ex(res) except *:
|
|
183
|
+
"""
|
|
184
|
+
Convert an Expression object to a GiNaC::ex.
|
|
185
|
+
|
|
186
|
+
Used to pass return values of custom python evaluation, derivation
|
|
187
|
+
functions back to C++ level.
|
|
188
|
+
"""
|
|
189
|
+
if res is None:
|
|
190
|
+
raise TypeError("function returned None, expected return value of type sage.symbolic.expression.Expression")
|
|
191
|
+
from sage.symbolic.ring import SR
|
|
192
|
+
try:
|
|
193
|
+
t = SR.coerce(res)
|
|
194
|
+
except TypeError as err:
|
|
195
|
+
raise TypeError("function did not return a symbolic expression or an element that can be coerced into a symbolic expression")
|
|
196
|
+
return (<Expression>t)._gobj
|
|
197
|
+
|
|
198
|
+
cdef paramset_to_PyTuple(const_paramset_ref s):
|
|
199
|
+
"""
|
|
200
|
+
Convert a std::multiset<unsigned> to a PyTuple.
|
|
201
|
+
|
|
202
|
+
Used to pass a list of parameter numbers with respect to which a function
|
|
203
|
+
is differentiated to the printing functions py_print_fderivative and
|
|
204
|
+
py_latex_fderivative.
|
|
205
|
+
"""
|
|
206
|
+
cdef GParamSetIter itr = s.begin()
|
|
207
|
+
res = []
|
|
208
|
+
while itr != s.end():
|
|
209
|
+
res.append(itr.obj())
|
|
210
|
+
itr.inc()
|
|
211
|
+
return res
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def paramset_from_Expression(Expression e):
|
|
215
|
+
"""
|
|
216
|
+
EXAMPLES::
|
|
217
|
+
|
|
218
|
+
sage: from sage.symbolic.expression import paramset_from_Expression
|
|
219
|
+
sage: f = function('f')
|
|
220
|
+
sage: paramset_from_Expression(f(x).diff(x))
|
|
221
|
+
[0]
|
|
222
|
+
"""
|
|
223
|
+
return paramset_to_PyTuple(ex_to_fderivative(e._gobj).get_parameter_set())
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
cdef int GINAC_FN_SERIAL = 0
|
|
227
|
+
|
|
228
|
+
cdef set_ginac_fn_serial():
|
|
229
|
+
"""
|
|
230
|
+
Initialize the GINAC_FN_SERIAL variable to the number of functions
|
|
231
|
+
defined by GiNaC. This allows us to prevent collisions with C++ level
|
|
232
|
+
special functions when a user asks to construct a symbolic function
|
|
233
|
+
with the same name.
|
|
234
|
+
"""
|
|
235
|
+
global GINAC_FN_SERIAL
|
|
236
|
+
GINAC_FN_SERIAL = g_registered_functions().size()
|
|
237
|
+
|
|
238
|
+
cdef int py_get_ginac_serial() noexcept:
|
|
239
|
+
"""
|
|
240
|
+
Return the number of C++ level functions defined by GiNaC.
|
|
241
|
+
|
|
242
|
+
EXAMPLES::
|
|
243
|
+
|
|
244
|
+
sage: from sage.symbolic.expression import get_ginac_serial
|
|
245
|
+
sage: get_ginac_serial() >= 35
|
|
246
|
+
True
|
|
247
|
+
"""
|
|
248
|
+
global GINAC_FN_SERIAL
|
|
249
|
+
return GINAC_FN_SERIAL
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def get_ginac_serial():
|
|
253
|
+
"""
|
|
254
|
+
Number of C++ level functions defined by GiNaC. (Defined mainly for testing.)
|
|
255
|
+
|
|
256
|
+
EXAMPLES::
|
|
257
|
+
|
|
258
|
+
sage: sage.symbolic.expression.get_ginac_serial() >= 35
|
|
259
|
+
True
|
|
260
|
+
"""
|
|
261
|
+
return py_get_ginac_serial()
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
cdef get_fn_serial_c():
|
|
265
|
+
"""
|
|
266
|
+
Return overall size of Pynac function registry.
|
|
267
|
+
"""
|
|
268
|
+
return g_registered_functions().size()
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def get_fn_serial():
|
|
272
|
+
"""
|
|
273
|
+
Return the overall size of the Pynac function registry which
|
|
274
|
+
corresponds to the last serial value plus one.
|
|
275
|
+
|
|
276
|
+
EXAMPLES::
|
|
277
|
+
|
|
278
|
+
sage: from sage.symbolic.expression import get_fn_serial
|
|
279
|
+
sage: from sage.symbolic.function import get_sfunction_from_serial
|
|
280
|
+
sage: get_fn_serial() > 125
|
|
281
|
+
True
|
|
282
|
+
sage: print(get_sfunction_from_serial(get_fn_serial()))
|
|
283
|
+
None
|
|
284
|
+
sage: get_sfunction_from_serial(get_fn_serial() - 1) is not None
|
|
285
|
+
True
|
|
286
|
+
"""
|
|
287
|
+
return get_fn_serial_c()
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
cdef subs_args_to_PyTuple(const GExMap& map, unsigned options, const GExVector& seq):
|
|
291
|
+
"""
|
|
292
|
+
Convert arguments from ``GiNaC::subs()`` to a PyTuple.
|
|
293
|
+
|
|
294
|
+
EXAMPLES::
|
|
295
|
+
|
|
296
|
+
sage: from sage.symbolic.function import BuiltinFunction
|
|
297
|
+
sage: class TFunc(BuiltinFunction):
|
|
298
|
+
....: def __init__(self):
|
|
299
|
+
....: BuiltinFunction.__init__(self, 'tfunc', nargs=0)
|
|
300
|
+
....:
|
|
301
|
+
....: def _subs_(self, *args):
|
|
302
|
+
....: print("len(args): %s, types: %s"%(len(args), str(list(map(type, args)))))
|
|
303
|
+
....: return args[-1]
|
|
304
|
+
sage: tfunc = TFunc()
|
|
305
|
+
sage: tfunc(x).subs(x=1)
|
|
306
|
+
len(args): 3, types: [<class 'sage.symbolic.expression.SubstitutionMap'>,
|
|
307
|
+
<class 'int'>,
|
|
308
|
+
<class 'sage.symbolic.expression.Expression'>]
|
|
309
|
+
x
|
|
310
|
+
"""
|
|
311
|
+
res = []
|
|
312
|
+
res.append(new_SubstitutionMap_from_GExMap(map))
|
|
313
|
+
res.append(options)
|
|
314
|
+
return tuple(res) + exvector_to_PyTuple(seq)
|
|
315
|
+
|
|
316
|
+
#################################################################
|
|
317
|
+
# Printing helpers
|
|
318
|
+
#################################################################
|
|
319
|
+
|
|
320
|
+
##########################################################################
|
|
321
|
+
# Pynac's precedence levels, as extracted from the raw source code on
|
|
322
|
+
# 2009-05-15. If this changes in Pynac it could cause a bug in
|
|
323
|
+
# printing. But it's hardcoded in Pynac now, so there's not much to
|
|
324
|
+
# be done (at present).
|
|
325
|
+
# Container: 10
|
|
326
|
+
# Expairseq: 10
|
|
327
|
+
# Relational: 20
|
|
328
|
+
# Numeric: 30
|
|
329
|
+
# Pseries: 38
|
|
330
|
+
# Addition: 40
|
|
331
|
+
# Integral: 45
|
|
332
|
+
# Multiplication: 50
|
|
333
|
+
# Noncummative mult: 50
|
|
334
|
+
# Index: 55
|
|
335
|
+
# Power: 60
|
|
336
|
+
# Clifford: 65
|
|
337
|
+
# Function: 70
|
|
338
|
+
# Structure: 70
|
|
339
|
+
##########################################################################
|
|
340
|
+
|
|
341
|
+
cdef stdstring* py_repr(o, int level) noexcept:
|
|
342
|
+
"""
|
|
343
|
+
Return string representation of o. If level > 0, possibly put
|
|
344
|
+
parentheses around the string.
|
|
345
|
+
"""
|
|
346
|
+
s = repr(o)
|
|
347
|
+
if level >= 20:
|
|
348
|
+
# s may need parens (e.g., is in an exponent), so decide if we
|
|
349
|
+
# have to put parentheses around s:
|
|
350
|
+
# A regexp might seem better, but I don't think it's really faster.
|
|
351
|
+
# It would be more readable. Python does the below (with in) very quickly.
|
|
352
|
+
if level <= 50:
|
|
353
|
+
t = s[1:] # ignore leading minus
|
|
354
|
+
else:
|
|
355
|
+
t = s
|
|
356
|
+
# Python complexes are always printed with parentheses
|
|
357
|
+
# we try to avoid double parentheses
|
|
358
|
+
if not isinstance(o, complex) and \
|
|
359
|
+
(' ' in t or '/' in t or '+' in t or '-' in t or '*' in t
|
|
360
|
+
or '^' in t):
|
|
361
|
+
s = '(%s)' % s
|
|
362
|
+
return string_from_pystr(s)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
cdef stdstring* py_latex(o, int level) noexcept:
|
|
366
|
+
"""
|
|
367
|
+
Return latex string representation of o. If level > 0, possibly
|
|
368
|
+
put parentheses around the string.
|
|
369
|
+
"""
|
|
370
|
+
from sage.misc.latex import latex
|
|
371
|
+
s = latex(o)
|
|
372
|
+
if level >= 20:
|
|
373
|
+
if ' ' in s or '/' in s or '+' in s or '-' in s or '*' in s or '^' in s or '\\frac' in s:
|
|
374
|
+
s = '\\left(%s\\right)' % s
|
|
375
|
+
return string_from_pystr(s)
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
cdef stdstring* string_from_pystr(py_str) except NULL:
|
|
379
|
+
"""
|
|
380
|
+
Create a C++ string with the same contents as the given python string.
|
|
381
|
+
|
|
382
|
+
Used when passing string output to Pynac for printing, since we don't want
|
|
383
|
+
to mess with reference counts of the python objects and we cannot guarantee
|
|
384
|
+
they won't be garbage collected before the output is printed.
|
|
385
|
+
"""
|
|
386
|
+
cdef bytes s
|
|
387
|
+
if isinstance(py_str, bytes):
|
|
388
|
+
s = <bytes>py_str
|
|
389
|
+
elif isinstance(py_str, str):
|
|
390
|
+
# Note: This should only by the case on Python 3 since on Python 2
|
|
391
|
+
# bytes is str
|
|
392
|
+
s = str_to_bytes(py_str)
|
|
393
|
+
else:
|
|
394
|
+
s = b"(INVALID)" # Avoid segfaults for invalid input
|
|
395
|
+
return new stdstring(s)
|
|
396
|
+
|
|
397
|
+
cdef stdstring* py_latex_variable(var_name) noexcept:
|
|
398
|
+
r"""
|
|
399
|
+
Return a c++ string containing the latex representation of the given
|
|
400
|
+
variable name.
|
|
401
|
+
|
|
402
|
+
Real work is done by the function sage.misc.latex.latex_variable_name.
|
|
403
|
+
|
|
404
|
+
EXAMPLES::
|
|
405
|
+
|
|
406
|
+
sage: from sage.symbolic.expression import py_latex_variable_for_doctests
|
|
407
|
+
sage: py_latex_variable = py_latex_variable_for_doctests
|
|
408
|
+
|
|
409
|
+
sage: py_latex_variable('a')
|
|
410
|
+
a
|
|
411
|
+
sage: py_latex_variable('abc')
|
|
412
|
+
\mathit{abc}
|
|
413
|
+
sage: py_latex_variable('a_00')
|
|
414
|
+
a_{00}
|
|
415
|
+
sage: py_latex_variable('sigma_k')
|
|
416
|
+
\sigma_{k}
|
|
417
|
+
sage: py_latex_variable('sigma389')
|
|
418
|
+
\sigma_{389}
|
|
419
|
+
sage: py_latex_variable('beta_00')
|
|
420
|
+
\beta_{00}
|
|
421
|
+
"""
|
|
422
|
+
from sage.misc.latex import latex_variable_name
|
|
423
|
+
py_vlatex = latex_variable_name(var_name)
|
|
424
|
+
return string_from_pystr(py_vlatex)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def py_latex_variable_for_doctests(x):
|
|
428
|
+
r"""
|
|
429
|
+
Internal function used so we can doctest a certain cdef'd method.
|
|
430
|
+
|
|
431
|
+
EXAMPLES::
|
|
432
|
+
|
|
433
|
+
sage: sage.symbolic.expression.py_latex_variable_for_doctests('x')
|
|
434
|
+
x
|
|
435
|
+
sage: sage.symbolic.expression.py_latex_variable_for_doctests('sigma')
|
|
436
|
+
\sigma
|
|
437
|
+
"""
|
|
438
|
+
cdef stdstring* ostr = py_latex_variable(x)
|
|
439
|
+
print(char_to_str(ostr.c_str()))
|
|
440
|
+
del ostr
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
def py_print_function_pystring(id, args, fname_paren=False):
|
|
444
|
+
"""
|
|
445
|
+
Return a string with the representation of the symbolic function specified
|
|
446
|
+
by the given id applied to args.
|
|
447
|
+
|
|
448
|
+
INPUT:
|
|
449
|
+
|
|
450
|
+
- ``id`` -- serial number of the corresponding symbolic function
|
|
451
|
+
- ``params`` -- set of parameter numbers with respect to which to take the
|
|
452
|
+
derivative
|
|
453
|
+
- ``args`` -- arguments of the function
|
|
454
|
+
|
|
455
|
+
EXAMPLES::
|
|
456
|
+
|
|
457
|
+
sage: from sage.symbolic.expression import py_print_function_pystring, get_ginac_serial, get_fn_serial
|
|
458
|
+
sage: from sage.symbolic.function import get_sfunction_from_serial
|
|
459
|
+
sage: var('x,y,z')
|
|
460
|
+
(x, y, z)
|
|
461
|
+
sage: foo = function('foo', nargs=2)
|
|
462
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
463
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
464
|
+
|
|
465
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
466
|
+
True
|
|
467
|
+
sage: py_print_function_pystring(i, (x,y))
|
|
468
|
+
'foo(x, y)'
|
|
469
|
+
sage: py_print_function_pystring(i, (x,y), True)
|
|
470
|
+
'(foo)(x, y)'
|
|
471
|
+
sage: def my_print(self, *args): return "my args are: " + ', '.join(map(repr, args))
|
|
472
|
+
sage: foo = function('foo', nargs=2, print_func=my_print)
|
|
473
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
474
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
475
|
+
|
|
476
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
477
|
+
True
|
|
478
|
+
sage: py_print_function_pystring(i, (x,y))
|
|
479
|
+
'my args are: x, y'
|
|
480
|
+
"""
|
|
481
|
+
cdef Function func = get_sfunction_from_serial(id)
|
|
482
|
+
# This function is called from two places, from function::print in Pynac
|
|
483
|
+
# and from py_print_fderivative. function::print checks if the serial
|
|
484
|
+
# belongs to a function defined at the C++ level. There are no C++ level
|
|
485
|
+
# functions that return an instance of fderivative when derivated. Hence,
|
|
486
|
+
# func will never be None.
|
|
487
|
+
assert(func is not None)
|
|
488
|
+
|
|
489
|
+
# if function has a custom print function call it
|
|
490
|
+
if hasattr(func,'_print_'):
|
|
491
|
+
res = func._print_(*args)
|
|
492
|
+
# make sure the output is a string
|
|
493
|
+
if res is None:
|
|
494
|
+
return ""
|
|
495
|
+
if not isinstance(res, str):
|
|
496
|
+
return str(res)
|
|
497
|
+
return res
|
|
498
|
+
|
|
499
|
+
# otherwise use default output
|
|
500
|
+
if fname_paren:
|
|
501
|
+
olist = ['(', func._name, ')']
|
|
502
|
+
else:
|
|
503
|
+
olist = [func._name]
|
|
504
|
+
olist.extend(['(', ', '.join(map(repr, args)), ')'])
|
|
505
|
+
return ''.join(olist)
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
cdef stdstring* py_print_function(unsigned id, args) noexcept:
|
|
509
|
+
return string_from_pystr(py_print_function_pystring(id, args))
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
def py_latex_function_pystring(id, args, fname_paren=False):
|
|
513
|
+
r"""
|
|
514
|
+
Return a string with the latex representation of the symbolic function
|
|
515
|
+
specified by the given id applied to args.
|
|
516
|
+
|
|
517
|
+
See documentation of py_print_function_pystring for more information.
|
|
518
|
+
|
|
519
|
+
EXAMPLES::
|
|
520
|
+
|
|
521
|
+
sage: from sage.symbolic.expression import py_latex_function_pystring, get_ginac_serial, get_fn_serial
|
|
522
|
+
sage: from sage.symbolic.function import get_sfunction_from_serial
|
|
523
|
+
sage: var('x,y,z')
|
|
524
|
+
(x, y, z)
|
|
525
|
+
sage: foo = function('foo', nargs=2)
|
|
526
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
527
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
528
|
+
|
|
529
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
530
|
+
True
|
|
531
|
+
sage: py_latex_function_pystring(i, (x,y^z))
|
|
532
|
+
'{\\rm foo}\\left(x, y^{z}\\right)'
|
|
533
|
+
sage: py_latex_function_pystring(i, (x,y^z), True)
|
|
534
|
+
'\\left({\\rm foo}\\right)\\left(x, y^{z}\\right)'
|
|
535
|
+
sage: py_latex_function_pystring(i, (int(0),x))
|
|
536
|
+
'{\\rm foo}\\left(0, x\\right)'
|
|
537
|
+
|
|
538
|
+
Test latex_name::
|
|
539
|
+
|
|
540
|
+
sage: foo = function('foo', nargs=2, latex_name=r'\mathrm{bar}')
|
|
541
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
542
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
543
|
+
|
|
544
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
545
|
+
True
|
|
546
|
+
sage: py_latex_function_pystring(i, (x,y^z))
|
|
547
|
+
'\\mathrm{bar}\\left(x, y^{z}\\right)'
|
|
548
|
+
|
|
549
|
+
Test custom func::
|
|
550
|
+
|
|
551
|
+
sage: def my_print(self, *args): return "my args are: " + ', '.join(map(repr, args))
|
|
552
|
+
sage: foo = function('foo', nargs=2, print_latex_func=my_print)
|
|
553
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
554
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
555
|
+
|
|
556
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
557
|
+
True
|
|
558
|
+
sage: py_latex_function_pystring(i, (x,y^z))
|
|
559
|
+
'my args are: x, y^z'
|
|
560
|
+
"""
|
|
561
|
+
cdef Function func = get_sfunction_from_serial(id)
|
|
562
|
+
# This function is called from two places, from function::print in Pynac
|
|
563
|
+
# and from py_latex_fderivative. function::print checks if the serial
|
|
564
|
+
# belongs to a function defined at the C++ level. There are no C++ level
|
|
565
|
+
# functions that return an instance of fderivative when derivated. Hence,
|
|
566
|
+
# func will never be None.
|
|
567
|
+
assert(func is not None)
|
|
568
|
+
|
|
569
|
+
# if function has a custom print method call it
|
|
570
|
+
if hasattr(func, '_print_latex_'):
|
|
571
|
+
res = func._print_latex_(*args)
|
|
572
|
+
# make sure the output is a string
|
|
573
|
+
if res is None:
|
|
574
|
+
return ""
|
|
575
|
+
if not isinstance(res, str):
|
|
576
|
+
return str(res)
|
|
577
|
+
return res
|
|
578
|
+
|
|
579
|
+
# otherwise, use the latex name if defined
|
|
580
|
+
if func._latex_name:
|
|
581
|
+
name = func._latex_name
|
|
582
|
+
else:
|
|
583
|
+
# if latex_name is not defined, then call
|
|
584
|
+
# latex_variable_name with "is_fname=True" flag
|
|
585
|
+
from sage.misc.latex import latex_variable_name
|
|
586
|
+
name = latex_variable_name(func._name, is_fname=True)
|
|
587
|
+
if fname_paren:
|
|
588
|
+
olist = [r'\left(', name, r'\right)']
|
|
589
|
+
else:
|
|
590
|
+
olist = [name]
|
|
591
|
+
# print the arguments
|
|
592
|
+
from sage.misc.latex import latex
|
|
593
|
+
olist.extend([r'\left(', ', '.join(latex(x) for x in args),
|
|
594
|
+
r'\right)'])
|
|
595
|
+
return ''.join(olist)
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
cdef stdstring* py_latex_function(unsigned id, args) noexcept:
|
|
599
|
+
return string_from_pystr(py_latex_function_pystring(id, args))
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
def tolerant_is_symbol(a):
|
|
603
|
+
"""
|
|
604
|
+
Utility function to test if something is a symbol.
|
|
605
|
+
|
|
606
|
+
Returns False for arguments that do not have an is_symbol attribute.
|
|
607
|
+
Returns the result of calling the is_symbol method otherwise.
|
|
608
|
+
|
|
609
|
+
EXAMPLES::
|
|
610
|
+
|
|
611
|
+
sage: from sage.symbolic.expression import tolerant_is_symbol
|
|
612
|
+
sage: tolerant_is_symbol(var("x"))
|
|
613
|
+
True
|
|
614
|
+
sage: tolerant_is_symbol(None)
|
|
615
|
+
False
|
|
616
|
+
sage: None.is_symbol()
|
|
617
|
+
Traceback (most recent call last):
|
|
618
|
+
...
|
|
619
|
+
AttributeError: 'NoneType' object has no attribute 'is_symbol'...
|
|
620
|
+
"""
|
|
621
|
+
try:
|
|
622
|
+
return a.is_symbol()
|
|
623
|
+
except AttributeError:
|
|
624
|
+
return False
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
cdef stdstring* py_print_fderivative(unsigned id, params,
|
|
628
|
+
args) noexcept:
|
|
629
|
+
"""
|
|
630
|
+
Return a string with the representation of the derivative of the symbolic
|
|
631
|
+
function specified by the given id, lists of params and args.
|
|
632
|
+
|
|
633
|
+
INPUT:
|
|
634
|
+
|
|
635
|
+
- ``id`` -- serial number of the corresponding symbolic function
|
|
636
|
+
- ``params`` -- set of parameter numbers with respect to which to take the
|
|
637
|
+
derivative
|
|
638
|
+
- ``args`` -- arguments of the function
|
|
639
|
+
"""
|
|
640
|
+
if all(tolerant_is_symbol(a) for a in args) and len(set(args)) == len(args):
|
|
641
|
+
diffvarstr = ', '.join(repr(args[i]) for i in params)
|
|
642
|
+
py_res = ''.join(['diff(', py_print_function_pystring(id, args, False),
|
|
643
|
+
', ', diffvarstr, ')'])
|
|
644
|
+
else:
|
|
645
|
+
ostr = ''.join(['D[', ', '.join(repr(int(x)) for x in params), ']'])
|
|
646
|
+
fstr = py_print_function_pystring(id, args, True)
|
|
647
|
+
py_res = ostr + fstr
|
|
648
|
+
return string_from_pystr(py_res)
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
def py_print_fderivative_for_doctests(id, params, args):
|
|
652
|
+
"""
|
|
653
|
+
Used for testing a cdef'd function.
|
|
654
|
+
|
|
655
|
+
EXAMPLES::
|
|
656
|
+
|
|
657
|
+
sage: from sage.symbolic.expression import py_print_fderivative_for_doctests as py_print_fderivative, get_ginac_serial, get_fn_serial
|
|
658
|
+
sage: var('x,y,z')
|
|
659
|
+
(x, y, z)
|
|
660
|
+
sage: from sage.symbolic.function import get_sfunction_from_serial
|
|
661
|
+
sage: foo = function('foo', nargs=2)
|
|
662
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
663
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
664
|
+
|
|
665
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
666
|
+
True
|
|
667
|
+
sage: py_print_fderivative(i, (0, 1, 0, 1), (x, y^z))
|
|
668
|
+
D[0, 1, 0, 1](foo)(x, y^z)
|
|
669
|
+
|
|
670
|
+
Test custom print function::
|
|
671
|
+
|
|
672
|
+
sage: def my_print(self, *args): return "func_with_args(" + ', '.join(map(repr, args)) +')'
|
|
673
|
+
sage: foo = function('foo', nargs=2, print_func=my_print)
|
|
674
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
675
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
676
|
+
|
|
677
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
678
|
+
True
|
|
679
|
+
sage: py_print_fderivative(i, (0, 1, 0, 1), (x, y^z))
|
|
680
|
+
D[0, 1, 0, 1]func_with_args(x, y^z)
|
|
681
|
+
"""
|
|
682
|
+
cdef stdstring* ostr = py_print_fderivative(id, params, args)
|
|
683
|
+
print(char_to_str(ostr.c_str()))
|
|
684
|
+
del ostr
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
cdef stdstring* py_latex_fderivative(unsigned id, params,
|
|
688
|
+
args) noexcept:
|
|
689
|
+
"""
|
|
690
|
+
Return a string with the latex representation of the derivative of the
|
|
691
|
+
symbolic function specified by the given id, lists of params and args.
|
|
692
|
+
|
|
693
|
+
See documentation of py_print_fderivative for more information.
|
|
694
|
+
"""
|
|
695
|
+
if all(tolerant_is_symbol(a) for a in args) and len(set(args)) == len(args):
|
|
696
|
+
param_iter = iter(params)
|
|
697
|
+
v = next(param_iter)
|
|
698
|
+
nv = 1
|
|
699
|
+
diff_args = []
|
|
700
|
+
for next_v in param_iter:
|
|
701
|
+
if next_v == v:
|
|
702
|
+
nv += 1
|
|
703
|
+
else:
|
|
704
|
+
if nv == 1:
|
|
705
|
+
diff_args.append(r"\partial %s" % (args[v]._latex_(),))
|
|
706
|
+
else:
|
|
707
|
+
diff_args.append(r"(\partial %s)^{%s}" % (args[v]._latex_(),nv))
|
|
708
|
+
v=next_v
|
|
709
|
+
nv=1
|
|
710
|
+
if nv == 1:
|
|
711
|
+
diff_args.append(r"\partial %s" % (args[v]._latex_(),))
|
|
712
|
+
else:
|
|
713
|
+
diff_args.append(r"(\partial %s)^{%s}" % (args[v]._latex_(),nv))
|
|
714
|
+
if len(params) == 1:
|
|
715
|
+
operator_string=r"\frac{\partial}{%s}" % (''.join(diff_args),)
|
|
716
|
+
else:
|
|
717
|
+
operator_string=r"\frac{\partial^{%s}}{%s}" % (len(params),''.join(diff_args))
|
|
718
|
+
py_res = operator_string+py_latex_function_pystring(id, args, False)
|
|
719
|
+
else:
|
|
720
|
+
ostr = ''.join([r'\mathrm{D}_{',
|
|
721
|
+
', '.join(repr(int(x)) for x in params), '}'])
|
|
722
|
+
fstr = py_latex_function_pystring(id, args, True)
|
|
723
|
+
py_res = ostr + fstr
|
|
724
|
+
return string_from_pystr(py_res)
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
def py_latex_fderivative_for_doctests(id, params, args):
|
|
728
|
+
r"""
|
|
729
|
+
Used internally for writing doctests for certain cdef'd functions.
|
|
730
|
+
|
|
731
|
+
EXAMPLES::
|
|
732
|
+
|
|
733
|
+
sage: from sage.symbolic.expression import py_latex_fderivative_for_doctests as py_latex_fderivative, get_ginac_serial, get_fn_serial
|
|
734
|
+
|
|
735
|
+
sage: var('x,y,z')
|
|
736
|
+
(x, y, z)
|
|
737
|
+
sage: from sage.symbolic.function import get_sfunction_from_serial
|
|
738
|
+
sage: foo = function('foo', nargs=2)
|
|
739
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
740
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
741
|
+
|
|
742
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
743
|
+
True
|
|
744
|
+
sage: py_latex_fderivative(i, (0, 1, 0, 1), (x, y^z))
|
|
745
|
+
\mathrm{D}_{0, 1, 0, 1}\left({\rm foo}\right)\left(x, y^{z}\right)
|
|
746
|
+
|
|
747
|
+
Test latex_name::
|
|
748
|
+
|
|
749
|
+
sage: foo = function('foo', nargs=2, latex_name=r'\mathrm{bar}')
|
|
750
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
751
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
752
|
+
|
|
753
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
754
|
+
True
|
|
755
|
+
sage: py_latex_fderivative(i, (0, 1, 0, 1), (x, y^z))
|
|
756
|
+
\mathrm{D}_{0, 1, 0, 1}\left(\mathrm{bar}\right)\left(x, y^{z}\right)
|
|
757
|
+
|
|
758
|
+
Test custom func::
|
|
759
|
+
|
|
760
|
+
sage: def my_print(self, *args): return "func_with_args(" + ', '.join(map(repr, args)) +')'
|
|
761
|
+
sage: foo = function('foo', nargs=2, print_latex_func=my_print)
|
|
762
|
+
sage: for i in range(get_ginac_serial(), get_fn_serial()):
|
|
763
|
+
....: if get_sfunction_from_serial(i) == foo: break
|
|
764
|
+
|
|
765
|
+
sage: get_sfunction_from_serial(i) == foo
|
|
766
|
+
True
|
|
767
|
+
sage: py_latex_fderivative(i, (0, 1, 0, 1), (x, y^z))
|
|
768
|
+
\mathrm{D}_{0, 1, 0, 1}func_with_args(x, y^z)
|
|
769
|
+
"""
|
|
770
|
+
cdef stdstring* ostr = py_latex_fderivative(id, params, args)
|
|
771
|
+
print(char_to_str(ostr.c_str()))
|
|
772
|
+
del ostr
|
|
773
|
+
|
|
774
|
+
#################################################################
|
|
775
|
+
# Archive helpers
|
|
776
|
+
#################################################################
|
|
777
|
+
|
|
778
|
+
cdef stdstring* py_dumps(o) noexcept:
|
|
779
|
+
s = dumps(o, compress=False)
|
|
780
|
+
# pynac archive format terminates atoms with zeroes.
|
|
781
|
+
# since pickle output can break the archive format
|
|
782
|
+
# we use the base64 data encoding
|
|
783
|
+
import base64
|
|
784
|
+
s = base64.b64encode(s)
|
|
785
|
+
return string_from_pystr(s)
|
|
786
|
+
|
|
787
|
+
cdef py_loads(s):
|
|
788
|
+
import base64
|
|
789
|
+
s = base64.b64decode(s)
|
|
790
|
+
return loads(s)
|
|
791
|
+
|
|
792
|
+
cdef py_get_sfunction_from_serial(unsigned s):
|
|
793
|
+
"""
|
|
794
|
+
Return the Python object associated with a serial.
|
|
795
|
+
"""
|
|
796
|
+
return get_sfunction_from_serial(s)
|
|
797
|
+
|
|
798
|
+
cdef unsigned py_get_serial_from_sfunction(f) noexcept:
|
|
799
|
+
"""
|
|
800
|
+
Given a Function object return its serial.
|
|
801
|
+
|
|
802
|
+
Python's unpickling mechanism is used to unarchive a symbolic function with
|
|
803
|
+
custom methods (evaluation, differentiation, etc.). Pynac extracts a string
|
|
804
|
+
representation from the archive, calls loads() to recreate the stored
|
|
805
|
+
function. This allows us to extract the serial from the Python object to
|
|
806
|
+
set the corresponding member variable of the C++ object representing this
|
|
807
|
+
function.
|
|
808
|
+
"""
|
|
809
|
+
return (<Function>f)._serial
|
|
810
|
+
|
|
811
|
+
cdef unsigned py_get_serial_for_new_sfunction(stdstring &s,
|
|
812
|
+
unsigned nargs) noexcept:
|
|
813
|
+
"""
|
|
814
|
+
Return a symbolic function with the given name and number of arguments.
|
|
815
|
+
|
|
816
|
+
When unarchiving a user defined symbolic function, Pynac goes through
|
|
817
|
+
the registry of existing functions. If there is no function already defined
|
|
818
|
+
with the archived name and number of arguments, this method is called to
|
|
819
|
+
create one and set up the function tables properly.
|
|
820
|
+
"""
|
|
821
|
+
from sage.symbolic.function_factory import function_factory
|
|
822
|
+
cdef Function fn = function_factory(s.c_str(), nargs)
|
|
823
|
+
return fn._serial
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
#################################################################
|
|
827
|
+
# Modular helpers
|
|
828
|
+
#################################################################
|
|
829
|
+
|
|
830
|
+
cdef int py_get_parent_char(o) except -1:
|
|
831
|
+
"""
|
|
832
|
+
TESTS:
|
|
833
|
+
|
|
834
|
+
:issue:`24072` fixes the workaround provided in :issue:`21187`::
|
|
835
|
+
|
|
836
|
+
sage: # needs sage.rings.finite_rings
|
|
837
|
+
sage: p = next_prime(2^100)
|
|
838
|
+
sage: R.<y> = FiniteField(p)[]
|
|
839
|
+
sage: y = SR(y)
|
|
840
|
+
Traceback (most recent call last):
|
|
841
|
+
...
|
|
842
|
+
TypeError: positive characteristic not allowed in symbolic computations
|
|
843
|
+
"""
|
|
844
|
+
if not isinstance(o, Element):
|
|
845
|
+
return 0
|
|
846
|
+
|
|
847
|
+
c = (<Element>o)._parent.characteristic()
|
|
848
|
+
|
|
849
|
+
# Pynac only differentiates between
|
|
850
|
+
# - characteristic 0
|
|
851
|
+
# - characteristic 2
|
|
852
|
+
# - characteristic > 0 but not 2
|
|
853
|
+
#
|
|
854
|
+
# To avoid integer overflow in the last case, we just return 3
|
|
855
|
+
# instead of the actual characteristic.
|
|
856
|
+
if not c:
|
|
857
|
+
return 0
|
|
858
|
+
elif c == 2:
|
|
859
|
+
return 2
|
|
860
|
+
else:
|
|
861
|
+
return 3
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
#################################################################
|
|
865
|
+
# power helpers
|
|
866
|
+
#################################################################
|
|
867
|
+
|
|
868
|
+
cdef py_rational_power_parts(base, exp):
|
|
869
|
+
if type(base) is not Rational:
|
|
870
|
+
base = Rational(base)
|
|
871
|
+
if type(exp) is not Rational:
|
|
872
|
+
exp = Rational(exp)
|
|
873
|
+
res= rational_power_parts(base, exp)
|
|
874
|
+
return res + (bool(res[0] == 1),)
|
|
875
|
+
|
|
876
|
+
#################################################################
|
|
877
|
+
# Binomial Coefficients
|
|
878
|
+
#################################################################
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
cdef py_binomial_int(int n, unsigned int k):
|
|
882
|
+
cdef bint sign
|
|
883
|
+
if n < 0:
|
|
884
|
+
n = -n + (k-1)
|
|
885
|
+
sign = k % 2
|
|
886
|
+
else:
|
|
887
|
+
sign = 0
|
|
888
|
+
cdef Integer ans = PY_NEW(Integer)
|
|
889
|
+
# Compute the binomial coefficient using GMP.
|
|
890
|
+
mpz_bin_uiui(ans.value, n, k)
|
|
891
|
+
# Return the answer or the negative of it (only if k is odd and n is negative).
|
|
892
|
+
if sign:
|
|
893
|
+
return -ans
|
|
894
|
+
else:
|
|
895
|
+
return ans
|
|
896
|
+
|
|
897
|
+
cdef py_binomial(n, k):
|
|
898
|
+
# Keep track of the sign we should use.
|
|
899
|
+
cdef bint sign
|
|
900
|
+
if n < 0:
|
|
901
|
+
n = k-n-1
|
|
902
|
+
sign = k % 2
|
|
903
|
+
else:
|
|
904
|
+
sign = 0
|
|
905
|
+
# Convert n and k to unsigned ints.
|
|
906
|
+
cdef unsigned int n_ = n, k_ = k
|
|
907
|
+
cdef Integer ans = PY_NEW(Integer)
|
|
908
|
+
# Compute the binomial coefficient using GMP.
|
|
909
|
+
mpz_bin_uiui(ans.value, n_, k_)
|
|
910
|
+
# Return the answer or the negative of it (only if k is odd and n is negative).
|
|
911
|
+
if sign:
|
|
912
|
+
return -ans
|
|
913
|
+
else:
|
|
914
|
+
return ans
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
def test_binomial(n, k):
|
|
918
|
+
"""
|
|
919
|
+
The Binomial coefficients. It computes the binomial coefficients. For
|
|
920
|
+
integer n and k and positive n this is the number of ways of choosing k
|
|
921
|
+
objects from n distinct objects. If n is negative, the formula
|
|
922
|
+
binomial(n,k) == (-1)^k*binomial(k-n-1,k) is used to compute the result.
|
|
923
|
+
|
|
924
|
+
INPUT:
|
|
925
|
+
|
|
926
|
+
- ``n``, ``k`` -- integers, with ``k >= 0``
|
|
927
|
+
|
|
928
|
+
OUTPUT: integer
|
|
929
|
+
|
|
930
|
+
EXAMPLES::
|
|
931
|
+
|
|
932
|
+
sage: import sage.symbolic.expression
|
|
933
|
+
sage: sage.symbolic.expression.test_binomial(5,2)
|
|
934
|
+
10
|
|
935
|
+
sage: sage.symbolic.expression.test_binomial(-5,3)
|
|
936
|
+
-35
|
|
937
|
+
sage: -sage.symbolic.expression.test_binomial(3-(-5)-1, 3)
|
|
938
|
+
-35
|
|
939
|
+
"""
|
|
940
|
+
return py_binomial(n, k)
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
#################################################################
|
|
944
|
+
# GCD
|
|
945
|
+
#################################################################
|
|
946
|
+
cdef py_gcd(n, k):
|
|
947
|
+
if isinstance(n, Integer) and isinstance(k, Integer):
|
|
948
|
+
if mpz_cmp_si((<Integer>n).value, 1) == 0:
|
|
949
|
+
return n
|
|
950
|
+
elif mpz_cmp_si((<Integer>k).value, 1) == 0:
|
|
951
|
+
return k
|
|
952
|
+
return n.gcd(k)
|
|
953
|
+
|
|
954
|
+
if type(n) is Rational and type(k) is Rational:
|
|
955
|
+
return n.content(k)
|
|
956
|
+
try:
|
|
957
|
+
return gcd(n, k)
|
|
958
|
+
except (TypeError, ValueError, AttributeError):
|
|
959
|
+
# some strange meaning in case of weird things with no usual lcm.
|
|
960
|
+
return 1
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
#################################################################
|
|
964
|
+
# LCM
|
|
965
|
+
#################################################################
|
|
966
|
+
cdef py_lcm(n, k):
|
|
967
|
+
if isinstance(n, Integer) and isinstance(k, Integer):
|
|
968
|
+
if mpz_cmp_si((<Integer>n).value, 1) == 0:
|
|
969
|
+
return k
|
|
970
|
+
elif mpz_cmp_si((<Integer>k).value, 1) == 0:
|
|
971
|
+
return n
|
|
972
|
+
return n.lcm(k)
|
|
973
|
+
try:
|
|
974
|
+
return lcm(n, k)
|
|
975
|
+
except (TypeError, ValueError, AttributeError):
|
|
976
|
+
# some strange meaning in case of weird things with no usual lcm, e.g.,
|
|
977
|
+
# elements of finite fields.
|
|
978
|
+
return 1
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
#################################################################
|
|
982
|
+
# Real Part
|
|
983
|
+
#################################################################
|
|
984
|
+
cdef py_real(x):
|
|
985
|
+
"""
|
|
986
|
+
Return the real part of x.
|
|
987
|
+
|
|
988
|
+
TESTS::
|
|
989
|
+
|
|
990
|
+
sage: from sage.symbolic.expression import py_real_for_doctests as py_real
|
|
991
|
+
sage: py_real(I)
|
|
992
|
+
0
|
|
993
|
+
sage: py_real(CC(1,5))
|
|
994
|
+
1.00000000000000
|
|
995
|
+
sage: py_real(CC(1))
|
|
996
|
+
1.00000000000000
|
|
997
|
+
sage: py_real(RR(1))
|
|
998
|
+
1.00000000000000
|
|
999
|
+
|
|
1000
|
+
sage: py_real(Mod(2,7))
|
|
1001
|
+
2
|
|
1002
|
+
|
|
1003
|
+
sage: py_real(QQ['x'].gen())
|
|
1004
|
+
x
|
|
1005
|
+
sage: py_real(float(2))
|
|
1006
|
+
2.0
|
|
1007
|
+
sage: py_real(complex(2,2))
|
|
1008
|
+
2.0
|
|
1009
|
+
"""
|
|
1010
|
+
if isinstance(x, (float, int)):
|
|
1011
|
+
return x
|
|
1012
|
+
elif isinstance(x, complex):
|
|
1013
|
+
return x.real
|
|
1014
|
+
|
|
1015
|
+
try:
|
|
1016
|
+
return x.real()
|
|
1017
|
+
except AttributeError:
|
|
1018
|
+
pass
|
|
1019
|
+
try:
|
|
1020
|
+
return x.real_part()
|
|
1021
|
+
except AttributeError:
|
|
1022
|
+
pass
|
|
1023
|
+
|
|
1024
|
+
return x # assume x is real
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
def py_real_for_doctests(x):
|
|
1028
|
+
"""
|
|
1029
|
+
Used for doctesting py_real.
|
|
1030
|
+
|
|
1031
|
+
TESTS::
|
|
1032
|
+
|
|
1033
|
+
sage: from sage.symbolic.expression import py_real_for_doctests
|
|
1034
|
+
sage: py_real_for_doctests(I)
|
|
1035
|
+
0
|
|
1036
|
+
"""
|
|
1037
|
+
return py_real(x)
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
#################################################################
|
|
1041
|
+
# Imaginary Part
|
|
1042
|
+
#################################################################
|
|
1043
|
+
cdef py_imag(x):
|
|
1044
|
+
"""
|
|
1045
|
+
Return the imaginary part of x.
|
|
1046
|
+
|
|
1047
|
+
TESTS::
|
|
1048
|
+
|
|
1049
|
+
sage: from sage.symbolic.expression import py_imag_for_doctests as py_imag
|
|
1050
|
+
sage: py_imag(I)
|
|
1051
|
+
1
|
|
1052
|
+
sage: py_imag(CC(1,5))
|
|
1053
|
+
5.00000000000000
|
|
1054
|
+
sage: py_imag(CC(1))
|
|
1055
|
+
0.000000000000000
|
|
1056
|
+
sage: py_imag(RR(1))
|
|
1057
|
+
0
|
|
1058
|
+
sage: py_imag(Mod(2,7))
|
|
1059
|
+
0
|
|
1060
|
+
|
|
1061
|
+
sage: py_imag(QQ['x'].gen())
|
|
1062
|
+
0
|
|
1063
|
+
sage: py_imag(float(2))
|
|
1064
|
+
0.0
|
|
1065
|
+
sage: py_imag(complex(2,2))
|
|
1066
|
+
2.0
|
|
1067
|
+
"""
|
|
1068
|
+
if isinstance(x, float):
|
|
1069
|
+
return 0.0
|
|
1070
|
+
if isinstance(x, complex):
|
|
1071
|
+
return x.imag
|
|
1072
|
+
try:
|
|
1073
|
+
return x.imag()
|
|
1074
|
+
except AttributeError:
|
|
1075
|
+
pass
|
|
1076
|
+
try:
|
|
1077
|
+
return x.imag_part()
|
|
1078
|
+
except AttributeError:
|
|
1079
|
+
pass
|
|
1080
|
+
|
|
1081
|
+
return 0 # assume x is real
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
def py_imag_for_doctests(x):
|
|
1085
|
+
"""
|
|
1086
|
+
Used for doctesting py_imag.
|
|
1087
|
+
|
|
1088
|
+
TESTS::
|
|
1089
|
+
|
|
1090
|
+
sage: from sage.symbolic.expression import py_imag_for_doctests
|
|
1091
|
+
sage: py_imag_for_doctests(I)
|
|
1092
|
+
1
|
|
1093
|
+
"""
|
|
1094
|
+
return py_imag(x)
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
#################################################################
|
|
1098
|
+
# Conjugate
|
|
1099
|
+
#################################################################
|
|
1100
|
+
cdef py_conjugate(x):
|
|
1101
|
+
try:
|
|
1102
|
+
return x.conjugate()
|
|
1103
|
+
except AttributeError:
|
|
1104
|
+
return x # assume is real since it doesn't have an imag attribute.
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
cdef bint py_is_rational(x) noexcept:
|
|
1108
|
+
return (type(x) is Rational or
|
|
1109
|
+
type(x) is Integer or
|
|
1110
|
+
isinstance(x, int))
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
cdef bint py_is_equal(x, y) noexcept:
|
|
1114
|
+
"""
|
|
1115
|
+
Return ``True`` precisely if x and y are equal.
|
|
1116
|
+
"""
|
|
1117
|
+
return bool(x == y)
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
cdef bint py_is_integer(x) noexcept:
|
|
1121
|
+
r"""
|
|
1122
|
+
Return ``True`` if pynac should treat this object as an integer.
|
|
1123
|
+
|
|
1124
|
+
EXAMPLES::
|
|
1125
|
+
|
|
1126
|
+
sage: from sage.symbolic.expression import py_is_integer_for_doctests
|
|
1127
|
+
sage: py_is_integer = py_is_integer_for_doctests
|
|
1128
|
+
|
|
1129
|
+
sage: py_is_integer(1r)
|
|
1130
|
+
True
|
|
1131
|
+
sage: py_is_integer(3^57)
|
|
1132
|
+
True
|
|
1133
|
+
sage: py_is_integer(SR(5))
|
|
1134
|
+
True
|
|
1135
|
+
sage: SCR = SR.subring(no_variables=True); SCR
|
|
1136
|
+
Symbolic Constants Subring
|
|
1137
|
+
sage: py_is_integer(SCR(5))
|
|
1138
|
+
True
|
|
1139
|
+
sage: py_is_integer(4/2)
|
|
1140
|
+
True
|
|
1141
|
+
sage: py_is_integer(QQbar(sqrt(2))^2) # needs sage.rings.number_field
|
|
1142
|
+
True
|
|
1143
|
+
sage: py_is_integer(3.0)
|
|
1144
|
+
False
|
|
1145
|
+
sage: py_is_integer(3.0r)
|
|
1146
|
+
False
|
|
1147
|
+
"""
|
|
1148
|
+
if isinstance(x, (int, Integer)):
|
|
1149
|
+
return True
|
|
1150
|
+
if not isinstance(x, Element):
|
|
1151
|
+
return False
|
|
1152
|
+
P = (<Element>x)._parent
|
|
1153
|
+
from sage.symbolic.ring import SymbolicRing
|
|
1154
|
+
return (isinstance(P, SymbolicRing) or P.is_exact()) and x in ZZ
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
def py_is_integer_for_doctests(x):
|
|
1158
|
+
"""
|
|
1159
|
+
Used internally for doctesting purposes.
|
|
1160
|
+
|
|
1161
|
+
TESTS::
|
|
1162
|
+
|
|
1163
|
+
sage: sage.symbolic.expression.py_is_integer_for_doctests(1r)
|
|
1164
|
+
True
|
|
1165
|
+
sage: sage.symbolic.expression.py_is_integer_for_doctests(1/3)
|
|
1166
|
+
False
|
|
1167
|
+
sage: sage.symbolic.expression.py_is_integer_for_doctests(2)
|
|
1168
|
+
True
|
|
1169
|
+
"""
|
|
1170
|
+
return py_is_integer(x)
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
cdef bint py_is_even(x) noexcept:
|
|
1174
|
+
try:
|
|
1175
|
+
return not(x % 2)
|
|
1176
|
+
except Exception:
|
|
1177
|
+
try:
|
|
1178
|
+
return not(ZZ(x) % 2)
|
|
1179
|
+
except Exception:
|
|
1180
|
+
pass
|
|
1181
|
+
return 0
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
cdef bint py_is_crational(x) noexcept:
|
|
1185
|
+
if py_is_rational(x):
|
|
1186
|
+
return True
|
|
1187
|
+
return isinstance(x, Element) and (<Element>x)._parent is pynac_I._parent
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
def py_is_crational_for_doctest(x):
|
|
1191
|
+
r"""
|
|
1192
|
+
Return ``True`` if pynac should treat this object as an element of `\QQ(i)`.
|
|
1193
|
+
|
|
1194
|
+
TESTS::
|
|
1195
|
+
|
|
1196
|
+
sage: from sage.symbolic.expression import py_is_crational_for_doctest
|
|
1197
|
+
sage: py_is_crational_for_doctest(1)
|
|
1198
|
+
True
|
|
1199
|
+
sage: py_is_crational_for_doctest(-2r)
|
|
1200
|
+
True
|
|
1201
|
+
sage: py_is_crational_for_doctest(1.5)
|
|
1202
|
+
False
|
|
1203
|
+
sage: py_is_crational_for_doctest(I)
|
|
1204
|
+
True
|
|
1205
|
+
sage: py_is_crational_for_doctest(I+1/2)
|
|
1206
|
+
True
|
|
1207
|
+
"""
|
|
1208
|
+
return py_is_crational(x)
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
cdef bint py_is_real(a) noexcept:
|
|
1212
|
+
if isinstance(a, (int, Integer, float)):
|
|
1213
|
+
return True
|
|
1214
|
+
try:
|
|
1215
|
+
P = parent(a)
|
|
1216
|
+
if P.is_field() and P.is_finite():
|
|
1217
|
+
return False
|
|
1218
|
+
except NotImplementedError:
|
|
1219
|
+
return False
|
|
1220
|
+
except (TypeError, AttributeError):
|
|
1221
|
+
pass
|
|
1222
|
+
return py_imag(a) == 0
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
cdef bint py_is_prime(n) noexcept:
|
|
1226
|
+
try:
|
|
1227
|
+
return n.is_prime()
|
|
1228
|
+
except Exception: # yes, I'm doing this on purpose.
|
|
1229
|
+
pass
|
|
1230
|
+
try:
|
|
1231
|
+
return is_prime(n)
|
|
1232
|
+
except Exception:
|
|
1233
|
+
pass
|
|
1234
|
+
return False
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
cdef bint py_is_exact(x) noexcept:
|
|
1238
|
+
if isinstance(x, (int, Integer)):
|
|
1239
|
+
return True
|
|
1240
|
+
if not isinstance(x, Element):
|
|
1241
|
+
return False
|
|
1242
|
+
P = (<Element>x)._parent
|
|
1243
|
+
from sage.symbolic.ring import SymbolicRing
|
|
1244
|
+
return isinstance(P, SymbolicRing) or P.is_exact()
|
|
1245
|
+
|
|
1246
|
+
|
|
1247
|
+
cdef py_numer(n):
|
|
1248
|
+
"""
|
|
1249
|
+
Return the numerator of the given object. This is called for
|
|
1250
|
+
typesetting coefficients.
|
|
1251
|
+
|
|
1252
|
+
TESTS::
|
|
1253
|
+
|
|
1254
|
+
sage: from sage.symbolic.expression import py_numer_for_doctests as py_numer
|
|
1255
|
+
sage: py_numer(2r)
|
|
1256
|
+
2
|
|
1257
|
+
sage: py_numer(3)
|
|
1258
|
+
3
|
|
1259
|
+
sage: py_numer(2/3)
|
|
1260
|
+
2
|
|
1261
|
+
sage: C.<i> = NumberField(x^2 + 1) # needs sage.rings.number_field
|
|
1262
|
+
sage: py_numer(2/3*i) # needs sage.rings.number_field
|
|
1263
|
+
2*i
|
|
1264
|
+
sage: class no_numer:
|
|
1265
|
+
....: def denominator(self):
|
|
1266
|
+
....: return 5
|
|
1267
|
+
....: def __mul__(left, right):
|
|
1268
|
+
....: return 42
|
|
1269
|
+
...
|
|
1270
|
+
sage: py_numer(no_numer())
|
|
1271
|
+
42
|
|
1272
|
+
"""
|
|
1273
|
+
if isinstance(n, (int, Integer)):
|
|
1274
|
+
return n
|
|
1275
|
+
try:
|
|
1276
|
+
return n.numerator()
|
|
1277
|
+
except AttributeError:
|
|
1278
|
+
try:
|
|
1279
|
+
return n*n.denominator()
|
|
1280
|
+
except AttributeError:
|
|
1281
|
+
return n
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
def py_numer_for_doctests(n):
|
|
1285
|
+
"""
|
|
1286
|
+
This function is used to test py_numer().
|
|
1287
|
+
|
|
1288
|
+
EXAMPLES::
|
|
1289
|
+
|
|
1290
|
+
sage: from sage.symbolic.expression import py_numer_for_doctests
|
|
1291
|
+
sage: py_numer_for_doctests(2/3)
|
|
1292
|
+
2
|
|
1293
|
+
"""
|
|
1294
|
+
return py_numer(n)
|
|
1295
|
+
|
|
1296
|
+
cdef py_denom(n):
|
|
1297
|
+
"""
|
|
1298
|
+
Return the denominator of the given object. This is called for
|
|
1299
|
+
typesetting coefficients.
|
|
1300
|
+
|
|
1301
|
+
TESTS::
|
|
1302
|
+
|
|
1303
|
+
sage: from sage.symbolic.expression import py_denom_for_doctests as py_denom
|
|
1304
|
+
sage: py_denom(5)
|
|
1305
|
+
1
|
|
1306
|
+
sage: py_denom(2/3)
|
|
1307
|
+
3
|
|
1308
|
+
sage: C.<i> = NumberField(x^2 + 1) # needs sage.rings.number_field
|
|
1309
|
+
sage: py_denom(2/3*i) # needs sage.rings.number_field
|
|
1310
|
+
3
|
|
1311
|
+
"""
|
|
1312
|
+
if isinstance(n, (int, Integer)):
|
|
1313
|
+
return 1
|
|
1314
|
+
try:
|
|
1315
|
+
return n.denominator()
|
|
1316
|
+
except AttributeError:
|
|
1317
|
+
return 1
|
|
1318
|
+
|
|
1319
|
+
|
|
1320
|
+
def py_denom_for_doctests(n):
|
|
1321
|
+
"""
|
|
1322
|
+
This function is used to test py_denom().
|
|
1323
|
+
|
|
1324
|
+
EXAMPLES::
|
|
1325
|
+
|
|
1326
|
+
sage: from sage.symbolic.expression import py_denom_for_doctests
|
|
1327
|
+
sage: py_denom_for_doctests(2/3)
|
|
1328
|
+
3
|
|
1329
|
+
"""
|
|
1330
|
+
return py_denom(n)
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
cdef bint py_is_cinteger(x) noexcept:
|
|
1334
|
+
return py_is_integer(x) or (py_is_crational(x) and py_denom(x) == 1)
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
def py_is_cinteger_for_doctest(x):
|
|
1338
|
+
r"""
|
|
1339
|
+
Return ``True`` if pynac should treat this object as an element of `\ZZ(i)`.
|
|
1340
|
+
|
|
1341
|
+
TESTS::
|
|
1342
|
+
|
|
1343
|
+
sage: from sage.symbolic.expression import py_is_cinteger_for_doctest
|
|
1344
|
+
sage: py_is_cinteger_for_doctest(1)
|
|
1345
|
+
True
|
|
1346
|
+
sage: py_is_cinteger_for_doctest(I)
|
|
1347
|
+
True
|
|
1348
|
+
sage: py_is_cinteger_for_doctest(I - 3)
|
|
1349
|
+
True
|
|
1350
|
+
sage: py_is_cinteger_for_doctest(I + 1/2)
|
|
1351
|
+
False
|
|
1352
|
+
"""
|
|
1353
|
+
return py_is_cinteger(x)
|
|
1354
|
+
|
|
1355
|
+
cdef py_float(n, PyObject* kwds):
|
|
1356
|
+
"""
|
|
1357
|
+
Evaluate pynac numeric objects numerically.
|
|
1358
|
+
|
|
1359
|
+
TESTS::
|
|
1360
|
+
|
|
1361
|
+
sage: from sage.symbolic.expression import py_float_for_doctests as py_float
|
|
1362
|
+
sage: py_float(I, {'parent':ComplexField(10)})
|
|
1363
|
+
1.0*I
|
|
1364
|
+
sage: py_float(pi, {'parent':RealField(100)})
|
|
1365
|
+
3.1415926535897932384626433833
|
|
1366
|
+
sage: py_float(10, {'parent':CDF})
|
|
1367
|
+
10.0
|
|
1368
|
+
sage: type(py_float(10, {'parent':CDF}))
|
|
1369
|
+
<class 'sage.rings.complex_double.ComplexDoubleElement'>
|
|
1370
|
+
sage: py_float(1/2, {'parent':CC})
|
|
1371
|
+
0.500000000000000
|
|
1372
|
+
sage: type(py_float(1/2, {'parent':CC}))
|
|
1373
|
+
<class 'sage.rings.complex_mpfr.ComplexNumber'>
|
|
1374
|
+
"""
|
|
1375
|
+
if kwds is not NULL:
|
|
1376
|
+
p = (<object>kwds)['parent']
|
|
1377
|
+
if p is float:
|
|
1378
|
+
try:
|
|
1379
|
+
return float(n)
|
|
1380
|
+
except TypeError:
|
|
1381
|
+
return complex(n)
|
|
1382
|
+
elif p is complex:
|
|
1383
|
+
return p(n)
|
|
1384
|
+
else:
|
|
1385
|
+
try:
|
|
1386
|
+
return p(n)
|
|
1387
|
+
except (TypeError,ValueError):
|
|
1388
|
+
return p.complex_field()(n)
|
|
1389
|
+
else:
|
|
1390
|
+
try:
|
|
1391
|
+
return RR(n)
|
|
1392
|
+
except TypeError:
|
|
1393
|
+
return CC(n)
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
def py_float_for_doctests(n, kwds):
|
|
1397
|
+
"""
|
|
1398
|
+
This function is for testing py_float.
|
|
1399
|
+
|
|
1400
|
+
EXAMPLES::
|
|
1401
|
+
|
|
1402
|
+
sage: from sage.symbolic.expression import py_float_for_doctests
|
|
1403
|
+
sage: py_float_for_doctests(pi, {'parent':RealField(80)})
|
|
1404
|
+
3.1415926535897932384626
|
|
1405
|
+
sage: py_float_for_doctests(I, {'parent':RealField(80)})
|
|
1406
|
+
1.0000000000000000000000*I
|
|
1407
|
+
sage: py_float_for_doctests(I, {'parent':float})
|
|
1408
|
+
1j
|
|
1409
|
+
sage: py_float_for_doctests(pi, {'parent':complex})
|
|
1410
|
+
(3.141592653589793+0j)
|
|
1411
|
+
"""
|
|
1412
|
+
return py_float(n, <PyObject*>kwds)
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
cdef py_RDF_from_double(double x):
|
|
1416
|
+
cdef RealDoubleElement r = RealDoubleElement.__new__(RealDoubleElement)
|
|
1417
|
+
r._value = x
|
|
1418
|
+
return r
|
|
1419
|
+
|
|
1420
|
+
#################################################################
|
|
1421
|
+
# SPECIAL FUNCTIONS
|
|
1422
|
+
#################################################################
|
|
1423
|
+
cdef py_tgamma(x):
|
|
1424
|
+
"""
|
|
1425
|
+
The gamma function exported to pynac.
|
|
1426
|
+
|
|
1427
|
+
TESTS::
|
|
1428
|
+
|
|
1429
|
+
sage: from sage.symbolic.expression import py_tgamma_for_doctests as py_tgamma
|
|
1430
|
+
sage: py_tgamma(4)
|
|
1431
|
+
6
|
|
1432
|
+
sage: py_tgamma(1/2)
|
|
1433
|
+
1.77245385090552
|
|
1434
|
+
"""
|
|
1435
|
+
if isinstance(x, int):
|
|
1436
|
+
x = float(x)
|
|
1437
|
+
if type(x) is float:
|
|
1438
|
+
return math.tgamma(PyFloat_AS_DOUBLE(x))
|
|
1439
|
+
|
|
1440
|
+
# try / except blocks are faster than
|
|
1441
|
+
# if hasattr(x, 'gamma')
|
|
1442
|
+
try:
|
|
1443
|
+
res = x.gamma()
|
|
1444
|
+
except AttributeError:
|
|
1445
|
+
return CC(x).gamma()
|
|
1446
|
+
|
|
1447
|
+
# the result should be numeric, however the gamma method of rationals may
|
|
1448
|
+
# return symbolic expressions. for example (1/2).gamma() -> sqrt(pi).
|
|
1449
|
+
if isinstance(res, Expression):
|
|
1450
|
+
try:
|
|
1451
|
+
return RR(res)
|
|
1452
|
+
except ValueError:
|
|
1453
|
+
return CC(res)
|
|
1454
|
+
return res
|
|
1455
|
+
|
|
1456
|
+
|
|
1457
|
+
def py_tgamma_for_doctests(x):
|
|
1458
|
+
"""
|
|
1459
|
+
This function is for testing py_tgamma().
|
|
1460
|
+
|
|
1461
|
+
TESTS::
|
|
1462
|
+
|
|
1463
|
+
sage: from sage.symbolic.expression import py_tgamma_for_doctests
|
|
1464
|
+
sage: py_tgamma_for_doctests(3)
|
|
1465
|
+
2
|
|
1466
|
+
"""
|
|
1467
|
+
return py_tgamma(x)
|
|
1468
|
+
|
|
1469
|
+
cdef py_factorial(x):
|
|
1470
|
+
"""
|
|
1471
|
+
The factorial function exported to pynac.
|
|
1472
|
+
|
|
1473
|
+
TESTS::
|
|
1474
|
+
|
|
1475
|
+
sage: from sage.symbolic.expression import py_factorial_py as py_factorial
|
|
1476
|
+
sage: py_factorial(4)
|
|
1477
|
+
24
|
|
1478
|
+
sage: py_factorial(-2/3)
|
|
1479
|
+
2.67893853470775
|
|
1480
|
+
"""
|
|
1481
|
+
# factorial(x) is only defined for nonnegative integers x
|
|
1482
|
+
# so we first test if x can be coerced into ZZ and is nonnegative.
|
|
1483
|
+
# If this is not the case then we return the symbolic expression gamma(x+1)
|
|
1484
|
+
# This fixes Issue 9240
|
|
1485
|
+
try:
|
|
1486
|
+
x_in_ZZ = ZZ(x)
|
|
1487
|
+
coercion_success = True
|
|
1488
|
+
except (TypeError, ValueError):
|
|
1489
|
+
coercion_success = False
|
|
1490
|
+
|
|
1491
|
+
if coercion_success and x_in_ZZ >= 0:
|
|
1492
|
+
return factorial(x)
|
|
1493
|
+
else:
|
|
1494
|
+
return py_tgamma(x+1)
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
def py_factorial_py(x):
|
|
1498
|
+
"""
|
|
1499
|
+
This function is a python wrapper around py_factorial(). This wrapper
|
|
1500
|
+
is needed when we override the eval() method for GiNaC's factorial
|
|
1501
|
+
function in sage.functions.other.Function_factorial.
|
|
1502
|
+
|
|
1503
|
+
TESTS::
|
|
1504
|
+
|
|
1505
|
+
sage: from sage.symbolic.expression import py_factorial_py
|
|
1506
|
+
sage: py_factorial_py(3)
|
|
1507
|
+
6
|
|
1508
|
+
"""
|
|
1509
|
+
return py_factorial(x)
|
|
1510
|
+
|
|
1511
|
+
cdef py_doublefactorial(x):
|
|
1512
|
+
n = Integer(x)
|
|
1513
|
+
if n < -1:
|
|
1514
|
+
raise ValueError("argument must be >= -1")
|
|
1515
|
+
from sage.misc.misc_c import prod # fast balanced product
|
|
1516
|
+
return prod([n - 2*i for i in range(n//2)])
|
|
1517
|
+
|
|
1518
|
+
|
|
1519
|
+
def doublefactorial(n):
|
|
1520
|
+
"""
|
|
1521
|
+
The double factorial combinatorial function:
|
|
1522
|
+
|
|
1523
|
+
n!! == n * (n-2) * (n-4) * ... * ({1|2}) with 0!! == (-1)!! == 1.
|
|
1524
|
+
|
|
1525
|
+
INPUT:
|
|
1526
|
+
|
|
1527
|
+
- ``n`` -- integer ``>= 1``
|
|
1528
|
+
|
|
1529
|
+
EXAMPLES::
|
|
1530
|
+
|
|
1531
|
+
sage: from sage.symbolic.expression import doublefactorial
|
|
1532
|
+
sage: doublefactorial(-1)
|
|
1533
|
+
1
|
|
1534
|
+
sage: doublefactorial(0)
|
|
1535
|
+
1
|
|
1536
|
+
sage: doublefactorial(1)
|
|
1537
|
+
1
|
|
1538
|
+
sage: doublefactorial(5)
|
|
1539
|
+
15
|
|
1540
|
+
sage: doublefactorial(20)
|
|
1541
|
+
3715891200
|
|
1542
|
+
sage: prod( [20,18,..,2] )
|
|
1543
|
+
3715891200
|
|
1544
|
+
"""
|
|
1545
|
+
return py_doublefactorial(n)
|
|
1546
|
+
|
|
1547
|
+
|
|
1548
|
+
cdef py_fibonacci(n):
|
|
1549
|
+
from sage.libs.pari import pari
|
|
1550
|
+
return Integer(pari(n).fibonacci())
|
|
1551
|
+
|
|
1552
|
+
cdef py_step(n):
|
|
1553
|
+
"""
|
|
1554
|
+
Return step function of n.
|
|
1555
|
+
"""
|
|
1556
|
+
from sage.symbolic.ring import SR
|
|
1557
|
+
if n < 0:
|
|
1558
|
+
return SR(0)
|
|
1559
|
+
elif n > 0:
|
|
1560
|
+
return SR(1)
|
|
1561
|
+
return SR(Rational((1,2)))
|
|
1562
|
+
|
|
1563
|
+
cdef py_bernoulli(x):
|
|
1564
|
+
return bernoulli(x)
|
|
1565
|
+
|
|
1566
|
+
cdef py_sin(x):
|
|
1567
|
+
"""
|
|
1568
|
+
TESTS::
|
|
1569
|
+
|
|
1570
|
+
sage: sin(float(2)) #indirect doctest
|
|
1571
|
+
0.9092974268256817
|
|
1572
|
+
sage: sin(2.)
|
|
1573
|
+
0.909297426825682
|
|
1574
|
+
sage: sin(2.*I)
|
|
1575
|
+
3.62686040784702*I
|
|
1576
|
+
sage: sin(QQbar(I)) # known bug
|
|
1577
|
+
I*sinh(1)
|
|
1578
|
+
"""
|
|
1579
|
+
try:
|
|
1580
|
+
return x.sin()
|
|
1581
|
+
except AttributeError:
|
|
1582
|
+
pass
|
|
1583
|
+
try:
|
|
1584
|
+
return RR(x).sin()
|
|
1585
|
+
except (TypeError, ValueError):
|
|
1586
|
+
return CC(x).sin()
|
|
1587
|
+
|
|
1588
|
+
cdef py_cos(x):
|
|
1589
|
+
"""
|
|
1590
|
+
TESTS::
|
|
1591
|
+
|
|
1592
|
+
sage: cos(float(2)) #indirect doctest
|
|
1593
|
+
-0.4161468365471424
|
|
1594
|
+
sage: cos(2.)
|
|
1595
|
+
-0.416146836547142
|
|
1596
|
+
sage: cos(2.*I)
|
|
1597
|
+
3.76219569108363
|
|
1598
|
+
sage: cos(QQbar(I)) # known bug
|
|
1599
|
+
cosh(1)
|
|
1600
|
+
"""
|
|
1601
|
+
try:
|
|
1602
|
+
return x.cos()
|
|
1603
|
+
except AttributeError:
|
|
1604
|
+
pass
|
|
1605
|
+
try:
|
|
1606
|
+
return RR(x).cos()
|
|
1607
|
+
except (TypeError, ValueError):
|
|
1608
|
+
return CC(x).cos()
|
|
1609
|
+
|
|
1610
|
+
cdef py_stieltjes(x):
|
|
1611
|
+
"""
|
|
1612
|
+
Return the Stieltjes constant of the given index.
|
|
1613
|
+
|
|
1614
|
+
The value is expected to be a nonnegative integer.
|
|
1615
|
+
|
|
1616
|
+
TESTS::
|
|
1617
|
+
|
|
1618
|
+
sage: from sage.symbolic.expression import py_stieltjes_for_doctests as py_stieltjes
|
|
1619
|
+
sage: py_stieltjes(0)
|
|
1620
|
+
0.577215664901533
|
|
1621
|
+
sage: py_stieltjes(1.0)
|
|
1622
|
+
-0.0728158454836767
|
|
1623
|
+
sage: py_stieltjes(RealField(100)(5))
|
|
1624
|
+
0.00079332381730106270175333487744
|
|
1625
|
+
sage: py_stieltjes(-1)
|
|
1626
|
+
Traceback (most recent call last):
|
|
1627
|
+
...
|
|
1628
|
+
ValueError: Stieltjes constant of negative index
|
|
1629
|
+
"""
|
|
1630
|
+
n = ZZ(x)
|
|
1631
|
+
if n < 0:
|
|
1632
|
+
raise ValueError("Stieltjes constant of negative index")
|
|
1633
|
+
import mpmath
|
|
1634
|
+
if isinstance(x, Element) and hasattr((<Element>x)._parent, 'prec'):
|
|
1635
|
+
prec = (<Element>x)._parent.prec()
|
|
1636
|
+
else:
|
|
1637
|
+
prec = 53
|
|
1638
|
+
return mpmath_utils.call(mpmath.stieltjes, n, prec=prec)
|
|
1639
|
+
|
|
1640
|
+
|
|
1641
|
+
def py_stieltjes_for_doctests(x):
|
|
1642
|
+
"""
|
|
1643
|
+
This function is for testing py_stieltjes().
|
|
1644
|
+
|
|
1645
|
+
EXAMPLES::
|
|
1646
|
+
|
|
1647
|
+
sage: from sage.symbolic.expression import py_stieltjes_for_doctests
|
|
1648
|
+
sage: py_stieltjes_for_doctests(0.0)
|
|
1649
|
+
0.577215664901533
|
|
1650
|
+
"""
|
|
1651
|
+
return py_stieltjes(x)
|
|
1652
|
+
|
|
1653
|
+
cdef py_zeta(x):
|
|
1654
|
+
"""
|
|
1655
|
+
Return the value of the zeta function at the given value.
|
|
1656
|
+
|
|
1657
|
+
The value is expected to be a numerical object, in RR, CC, RDF or CDF,
|
|
1658
|
+
different from 1.
|
|
1659
|
+
|
|
1660
|
+
TESTS::
|
|
1661
|
+
|
|
1662
|
+
sage: # needs sage.libs.pari
|
|
1663
|
+
sage: from sage.symbolic.expression import py_zeta_for_doctests as py_zeta
|
|
1664
|
+
sage: py_zeta(CC.0)
|
|
1665
|
+
0.00330022368532410 - 0.418155449141322*I
|
|
1666
|
+
sage: py_zeta(CDF(5))
|
|
1667
|
+
1.03692775514337
|
|
1668
|
+
sage: py_zeta(RealField(100)(5))
|
|
1669
|
+
1.0369277551433699263313654865
|
|
1670
|
+
"""
|
|
1671
|
+
try:
|
|
1672
|
+
return x.zeta()
|
|
1673
|
+
except AttributeError:
|
|
1674
|
+
return CC(x).zeta()
|
|
1675
|
+
|
|
1676
|
+
|
|
1677
|
+
def py_zeta_for_doctests(x):
|
|
1678
|
+
"""
|
|
1679
|
+
This function is for testing py_zeta().
|
|
1680
|
+
|
|
1681
|
+
EXAMPLES::
|
|
1682
|
+
|
|
1683
|
+
sage: # needs sage.libs.pari
|
|
1684
|
+
sage: from sage.symbolic.expression import py_zeta_for_doctests
|
|
1685
|
+
sage: py_zeta_for_doctests(CC.0)
|
|
1686
|
+
0.00330022368532410 - 0.418155449141322*I
|
|
1687
|
+
"""
|
|
1688
|
+
return py_zeta(x)
|
|
1689
|
+
|
|
1690
|
+
cdef py_exp(x):
|
|
1691
|
+
"""
|
|
1692
|
+
Return the value of the exp function at the given value.
|
|
1693
|
+
|
|
1694
|
+
The value is expected to be a numerical object, in RR, CC, RDF or CDF.
|
|
1695
|
+
|
|
1696
|
+
TESTS::
|
|
1697
|
+
|
|
1698
|
+
sage: from sage.symbolic.expression import py_exp_for_doctests as py_exp
|
|
1699
|
+
sage: py_exp(CC(1))
|
|
1700
|
+
2.71828182845905
|
|
1701
|
+
sage: py_exp(CC(.5*I))
|
|
1702
|
+
0.877582561890373 + 0.479425538604203*I
|
|
1703
|
+
sage: py_exp(float(1))
|
|
1704
|
+
2.718281828459045...
|
|
1705
|
+
sage: py_exp(QQbar(I))
|
|
1706
|
+
0.540302305868140 + 0.841470984807897*I
|
|
1707
|
+
"""
|
|
1708
|
+
if type(x) is float:
|
|
1709
|
+
return math.exp(PyFloat_AS_DOUBLE(x))
|
|
1710
|
+
try:
|
|
1711
|
+
return x.exp()
|
|
1712
|
+
except AttributeError:
|
|
1713
|
+
pass
|
|
1714
|
+
try:
|
|
1715
|
+
return RR(x).exp()
|
|
1716
|
+
except (TypeError, ValueError):
|
|
1717
|
+
return CC(x).exp()
|
|
1718
|
+
|
|
1719
|
+
|
|
1720
|
+
def py_exp_for_doctests(x):
|
|
1721
|
+
"""
|
|
1722
|
+
This function tests py_exp.
|
|
1723
|
+
|
|
1724
|
+
EXAMPLES::
|
|
1725
|
+
|
|
1726
|
+
sage: from sage.symbolic.expression import py_exp_for_doctests
|
|
1727
|
+
sage: py_exp_for_doctests(CC(2))
|
|
1728
|
+
7.38905609893065
|
|
1729
|
+
"""
|
|
1730
|
+
return py_exp(x)
|
|
1731
|
+
|
|
1732
|
+
cdef py_log(x):
|
|
1733
|
+
"""
|
|
1734
|
+
Return the value of the log function at the given value.
|
|
1735
|
+
|
|
1736
|
+
The value is expected to be a numerical object, in RR, CC, RDF or CDF.
|
|
1737
|
+
|
|
1738
|
+
TESTS::
|
|
1739
|
+
|
|
1740
|
+
sage: from sage.symbolic.expression import py_log_for_doctests as py_log
|
|
1741
|
+
sage: py_log(CC(e))
|
|
1742
|
+
1.00000000000000
|
|
1743
|
+
sage: py_log(CC.0)
|
|
1744
|
+
1.57079632679490*I
|
|
1745
|
+
sage: py_log(float(e))
|
|
1746
|
+
1.0
|
|
1747
|
+
sage: py_log(float(0))
|
|
1748
|
+
-inf
|
|
1749
|
+
sage: py_log(float(-1))
|
|
1750
|
+
3.141592653589793j
|
|
1751
|
+
sage: py_log(int(1))
|
|
1752
|
+
0.0
|
|
1753
|
+
sage: py_log(int(0))
|
|
1754
|
+
-inf
|
|
1755
|
+
sage: py_log(complex(0))
|
|
1756
|
+
-inf
|
|
1757
|
+
sage: py_log(2)
|
|
1758
|
+
0.693147180559945
|
|
1759
|
+
"""
|
|
1760
|
+
cdef gsl_complex res
|
|
1761
|
+
cdef double real, imag
|
|
1762
|
+
if isinstance(x, int):
|
|
1763
|
+
x = float(x)
|
|
1764
|
+
if type(x) is float:
|
|
1765
|
+
real = PyFloat_AS_DOUBLE(x)
|
|
1766
|
+
if real > 0:
|
|
1767
|
+
return math.log(real)
|
|
1768
|
+
elif real < 0:
|
|
1769
|
+
res = gsl_complex_log(gsl_complex_rect(real, 0))
|
|
1770
|
+
return PyComplex_FromDoubles(GSL_REAL(res), GSL_IMAG(res))
|
|
1771
|
+
else:
|
|
1772
|
+
return float('-inf')
|
|
1773
|
+
elif type(x) is complex:
|
|
1774
|
+
real = PyComplex_RealAsDouble(x)
|
|
1775
|
+
imag = PyComplex_ImagAsDouble(x)
|
|
1776
|
+
if real == 0 and imag == 0:
|
|
1777
|
+
return float('-inf')
|
|
1778
|
+
res = gsl_complex_log(gsl_complex_rect(real, imag))
|
|
1779
|
+
return PyComplex_FromDoubles(GSL_REAL(res), GSL_IMAG(res))
|
|
1780
|
+
elif isinstance(x, Integer):
|
|
1781
|
+
return x.log().n()
|
|
1782
|
+
elif hasattr(x, 'log'):
|
|
1783
|
+
return x.log()
|
|
1784
|
+
try:
|
|
1785
|
+
return RR(x).log()
|
|
1786
|
+
except (TypeError, ValueError):
|
|
1787
|
+
return CC(x).log()
|
|
1788
|
+
|
|
1789
|
+
|
|
1790
|
+
def py_log_for_doctests(x):
|
|
1791
|
+
"""
|
|
1792
|
+
This function tests py_log.
|
|
1793
|
+
|
|
1794
|
+
EXAMPLES::
|
|
1795
|
+
|
|
1796
|
+
sage: from sage.symbolic.expression import py_log_for_doctests
|
|
1797
|
+
sage: py_log_for_doctests(CC(e))
|
|
1798
|
+
1.00000000000000
|
|
1799
|
+
"""
|
|
1800
|
+
return py_log(x)
|
|
1801
|
+
|
|
1802
|
+
cdef py_tan(x):
|
|
1803
|
+
try:
|
|
1804
|
+
return x.tan()
|
|
1805
|
+
except AttributeError:
|
|
1806
|
+
pass
|
|
1807
|
+
try:
|
|
1808
|
+
return RR(x).tan()
|
|
1809
|
+
except TypeError:
|
|
1810
|
+
return CC(x).tan()
|
|
1811
|
+
|
|
1812
|
+
cdef py_asin(x):
|
|
1813
|
+
try:
|
|
1814
|
+
return x.arcsin()
|
|
1815
|
+
except AttributeError:
|
|
1816
|
+
return RR(x).arcsin()
|
|
1817
|
+
|
|
1818
|
+
|
|
1819
|
+
cdef py_acos(x):
|
|
1820
|
+
try:
|
|
1821
|
+
return x.arccos()
|
|
1822
|
+
except AttributeError:
|
|
1823
|
+
return RR(x).arccos()
|
|
1824
|
+
|
|
1825
|
+
|
|
1826
|
+
cdef py_atan(x):
|
|
1827
|
+
try:
|
|
1828
|
+
return x.arctan()
|
|
1829
|
+
except AttributeError:
|
|
1830
|
+
return RR(x).arctan()
|
|
1831
|
+
|
|
1832
|
+
|
|
1833
|
+
cdef py_atan2(x, y):
|
|
1834
|
+
"""
|
|
1835
|
+
Return the value of the two argument arctan function at the given values.
|
|
1836
|
+
|
|
1837
|
+
The values are expected to be numerical objects, for example in RR, CC,
|
|
1838
|
+
RDF or CDF.
|
|
1839
|
+
|
|
1840
|
+
Note that the usual call signature of this function has the arguments
|
|
1841
|
+
reversed.
|
|
1842
|
+
|
|
1843
|
+
TESTS::
|
|
1844
|
+
|
|
1845
|
+
sage: from sage.symbolic.expression import py_atan2_for_doctests as py_atan2
|
|
1846
|
+
sage: py_atan2(0, 1)
|
|
1847
|
+
1.57079632679490
|
|
1848
|
+
sage: py_atan2(0.r, 1.r)
|
|
1849
|
+
1.5707963267948966
|
|
1850
|
+
sage: CC100 = ComplexField(100)
|
|
1851
|
+
sage: py_atan2(CC100(0), CC100(1))
|
|
1852
|
+
1.5707963267948966192313216916
|
|
1853
|
+
sage: RR100 = RealField(100)
|
|
1854
|
+
sage: py_atan2(RR100(0), RR100(1))
|
|
1855
|
+
1.5707963267948966192313216916
|
|
1856
|
+
|
|
1857
|
+
Check that :issue:`21428` is fixed::
|
|
1858
|
+
|
|
1859
|
+
sage: plot(real(sqrt(x - 1.*I)), (x,0,1)) # needs sage.plot
|
|
1860
|
+
Graphics object consisting of 1 graphics primitive
|
|
1861
|
+
|
|
1862
|
+
Check that :issue:`22553` is fixed::
|
|
1863
|
+
|
|
1864
|
+
sage: arctan2(1.5, -1.300000000000001)
|
|
1865
|
+
2.284887025407...
|
|
1866
|
+
sage: atan2(2.1000000000000000000000000000000000000, -1.20000000000000000000000000000000)
|
|
1867
|
+
2.089942441041419571002776071...
|
|
1868
|
+
|
|
1869
|
+
Check that :issue:`22877` is fixed::
|
|
1870
|
+
|
|
1871
|
+
sage: atan2(CC(I), CC(I+1))
|
|
1872
|
+
0.553574358897045 + 0.402359478108525*I
|
|
1873
|
+
sage: atan2(CBF(I), CBF(I+1))
|
|
1874
|
+
[0.55357435889705 +/- ...] + [0.402359478108525 +/- ...]*I
|
|
1875
|
+
|
|
1876
|
+
Check that :issue:`23776` is fixed and RDF input gives real output::
|
|
1877
|
+
|
|
1878
|
+
sage: atan2(RDF(-3), RDF(-1))
|
|
1879
|
+
-1.8925468811915387
|
|
1880
|
+
"""
|
|
1881
|
+
from sage.symbolic.constants import I, pi, NaN
|
|
1882
|
+
P = coercion_model.common_parent(x, y)
|
|
1883
|
+
if P is ZZ:
|
|
1884
|
+
P = RR
|
|
1885
|
+
if y != 0:
|
|
1886
|
+
if RR.has_coerce_map_from(P):
|
|
1887
|
+
if x > 0:
|
|
1888
|
+
res = py_atan(abs(y/x))
|
|
1889
|
+
elif x < 0:
|
|
1890
|
+
res = P(pi) - py_atan(abs(y/x))
|
|
1891
|
+
else:
|
|
1892
|
+
res = P(pi)/2
|
|
1893
|
+
return res if y > 0 else -res
|
|
1894
|
+
else:
|
|
1895
|
+
return -I*py_log((x + I*y)/py_sqrt(x**2 + y**2))
|
|
1896
|
+
else:
|
|
1897
|
+
if x > 0:
|
|
1898
|
+
return P(0)
|
|
1899
|
+
elif x < 0:
|
|
1900
|
+
return P(pi)
|
|
1901
|
+
else:
|
|
1902
|
+
return P(NaN)
|
|
1903
|
+
|
|
1904
|
+
|
|
1905
|
+
def py_atan2_for_doctests(x, y):
|
|
1906
|
+
"""
|
|
1907
|
+
Wrapper function to test py_atan2.
|
|
1908
|
+
|
|
1909
|
+
TESTS::
|
|
1910
|
+
|
|
1911
|
+
sage: from sage.symbolic.expression import py_atan2_for_doctests
|
|
1912
|
+
sage: py_atan2_for_doctests(0., 1.)
|
|
1913
|
+
1.57079632679490
|
|
1914
|
+
"""
|
|
1915
|
+
return py_atan2(x, y)
|
|
1916
|
+
|
|
1917
|
+
|
|
1918
|
+
cdef py_sinh(x):
|
|
1919
|
+
try:
|
|
1920
|
+
return x.sinh()
|
|
1921
|
+
except AttributeError:
|
|
1922
|
+
return RR(x).sinh()
|
|
1923
|
+
|
|
1924
|
+
|
|
1925
|
+
cdef py_cosh(x):
|
|
1926
|
+
if type(x) is float:
|
|
1927
|
+
return math.cosh(PyFloat_AS_DOUBLE(x))
|
|
1928
|
+
try:
|
|
1929
|
+
return x.cosh()
|
|
1930
|
+
except AttributeError:
|
|
1931
|
+
return RR(x).cosh()
|
|
1932
|
+
|
|
1933
|
+
|
|
1934
|
+
cdef py_tanh(x):
|
|
1935
|
+
try:
|
|
1936
|
+
return x.tanh()
|
|
1937
|
+
except AttributeError:
|
|
1938
|
+
return RR(x).tanh()
|
|
1939
|
+
|
|
1940
|
+
|
|
1941
|
+
cdef py_asinh(x):
|
|
1942
|
+
try:
|
|
1943
|
+
return x.arcsinh()
|
|
1944
|
+
except AttributeError:
|
|
1945
|
+
pass
|
|
1946
|
+
try:
|
|
1947
|
+
return RR(x).arcsinh()
|
|
1948
|
+
except TypeError:
|
|
1949
|
+
return CC(x).arcsinh()
|
|
1950
|
+
|
|
1951
|
+
|
|
1952
|
+
cdef py_acosh(x):
|
|
1953
|
+
try:
|
|
1954
|
+
return x.arccosh()
|
|
1955
|
+
except AttributeError:
|
|
1956
|
+
pass
|
|
1957
|
+
try:
|
|
1958
|
+
return RR(x).arccosh()
|
|
1959
|
+
except TypeError:
|
|
1960
|
+
return CC(x).arccosh()
|
|
1961
|
+
|
|
1962
|
+
|
|
1963
|
+
cdef py_atanh(x):
|
|
1964
|
+
try:
|
|
1965
|
+
return x.arctanh()
|
|
1966
|
+
except AttributeError:
|
|
1967
|
+
pass
|
|
1968
|
+
try:
|
|
1969
|
+
return RR(x).arctanh()
|
|
1970
|
+
except TypeError:
|
|
1971
|
+
return CC(x).arctanh()
|
|
1972
|
+
|
|
1973
|
+
|
|
1974
|
+
cdef py_lgamma(x):
|
|
1975
|
+
"""
|
|
1976
|
+
Return the value of the principal branch of the log gamma function at the
|
|
1977
|
+
given value.
|
|
1978
|
+
|
|
1979
|
+
The value is expected to be a numerical object, in RR, CC, RDF or CDF, or
|
|
1980
|
+
of the Python ``float`` or ``complex`` type.
|
|
1981
|
+
|
|
1982
|
+
EXAMPLES::
|
|
1983
|
+
|
|
1984
|
+
sage: from sage.symbolic.expression import py_lgamma_for_doctests as py_lgamma
|
|
1985
|
+
sage: py_lgamma(4)
|
|
1986
|
+
1.79175946922805
|
|
1987
|
+
sage: py_lgamma(4.r) # abs tol 2e-14
|
|
1988
|
+
1.79175946922805
|
|
1989
|
+
sage: py_lgamma(4r) # abs tol 2e-14
|
|
1990
|
+
1.79175946922805
|
|
1991
|
+
sage: py_lgamma(CC.0)
|
|
1992
|
+
-0.650923199301856 - 1.87243664726243*I
|
|
1993
|
+
sage: py_lgamma(ComplexField(100).0)
|
|
1994
|
+
-0.65092319930185633888521683150 - 1.8724366472624298171188533494*I
|
|
1995
|
+
"""
|
|
1996
|
+
from mpmath import loggamma
|
|
1997
|
+
|
|
1998
|
+
try:
|
|
1999
|
+
return x.log_gamma()
|
|
2000
|
+
except AttributeError:
|
|
2001
|
+
pass
|
|
2002
|
+
try:
|
|
2003
|
+
return RR(x).log_gamma()
|
|
2004
|
+
except TypeError:
|
|
2005
|
+
return mpmath_utils.call(loggamma, x, parent=parent(x))
|
|
2006
|
+
|
|
2007
|
+
|
|
2008
|
+
def py_lgamma_for_doctests(x):
|
|
2009
|
+
"""
|
|
2010
|
+
This function tests py_lgamma.
|
|
2011
|
+
|
|
2012
|
+
EXAMPLES::
|
|
2013
|
+
|
|
2014
|
+
sage: from sage.symbolic.expression import py_lgamma_for_doctests
|
|
2015
|
+
sage: py_lgamma_for_doctests(CC(I))
|
|
2016
|
+
-0.650923199301856 - 1.87243664726243*I
|
|
2017
|
+
"""
|
|
2018
|
+
return py_lgamma(x)
|
|
2019
|
+
|
|
2020
|
+
|
|
2021
|
+
cdef py_isqrt(x):
|
|
2022
|
+
return Integer(x).isqrt()
|
|
2023
|
+
|
|
2024
|
+
|
|
2025
|
+
cdef py_sqrt(x):
|
|
2026
|
+
try:
|
|
2027
|
+
# WORRY: What if Integer's sqrt calls symbolic one and we go in circle?
|
|
2028
|
+
return x.sqrt()
|
|
2029
|
+
except AttributeError as msg:
|
|
2030
|
+
return math.sqrt(float(x))
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
cdef py_abs(x):
|
|
2034
|
+
return abs(x)
|
|
2035
|
+
|
|
2036
|
+
|
|
2037
|
+
cdef py_mod(x, n):
|
|
2038
|
+
"""
|
|
2039
|
+
Return x mod n. Both x and n are assumed to be integers.
|
|
2040
|
+
|
|
2041
|
+
EXAMPLES::
|
|
2042
|
+
|
|
2043
|
+
sage: from sage.symbolic.expression import py_mod_for_doctests as py_mod
|
|
2044
|
+
sage: py_mod(I.parent(5), 4)
|
|
2045
|
+
1
|
|
2046
|
+
sage: py_mod(3, -2)
|
|
2047
|
+
-1
|
|
2048
|
+
sage: py_mod(3/2, 2)
|
|
2049
|
+
Traceback (most recent call last):
|
|
2050
|
+
...
|
|
2051
|
+
TypeError: no conversion of this rational to integer
|
|
2052
|
+
|
|
2053
|
+
|
|
2054
|
+
Note: The original code for this function in GiNaC checks if the arguments
|
|
2055
|
+
are integers, and returns 0 otherwise. We omit this check, since all the
|
|
2056
|
+
calls to py_mod are preceded by an integer check. We also raise an error
|
|
2057
|
+
if converting the arguments to integers fails, since silently returning 0
|
|
2058
|
+
would hide possible misuses of this function.
|
|
2059
|
+
|
|
2060
|
+
Regarding the sign of the return value, the CLN reference manual says:
|
|
2061
|
+
|
|
2062
|
+
If x and y are both >= 0, mod(x,y) = rem(x,y) >= 0. In general,
|
|
2063
|
+
mod(x,y) has the sign of y or is zero, and rem(x,y) has the sign of
|
|
2064
|
+
x or is zero.
|
|
2065
|
+
|
|
2066
|
+
This matches the behavior of the % operator for integers in Sage.
|
|
2067
|
+
"""
|
|
2068
|
+
return Integer(x) % Integer(n)
|
|
2069
|
+
|
|
2070
|
+
|
|
2071
|
+
def py_mod_for_doctests(x, n):
|
|
2072
|
+
"""
|
|
2073
|
+
This function is a python wrapper so py_mod can be tested. The real tests
|
|
2074
|
+
are in the docstring for py_mod.
|
|
2075
|
+
|
|
2076
|
+
EXAMPLES::
|
|
2077
|
+
|
|
2078
|
+
sage: from sage.symbolic.expression import py_mod_for_doctests
|
|
2079
|
+
sage: py_mod_for_doctests(5, 2)
|
|
2080
|
+
1
|
|
2081
|
+
"""
|
|
2082
|
+
return py_mod(x, n)
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
cdef py_smod(a, b):
|
|
2086
|
+
# Modulus (in symmetric representation).
|
|
2087
|
+
# Equivalent to Maple's mods.
|
|
2088
|
+
# returns a mod b in the range [-iquo(abs(b)-1,2), iquo(abs(b),2)]
|
|
2089
|
+
a = Integer(a)
|
|
2090
|
+
b = Integer(b)
|
|
2091
|
+
b = abs(b)
|
|
2092
|
+
c = a % b
|
|
2093
|
+
if c > b // 2:
|
|
2094
|
+
c -= b
|
|
2095
|
+
return c
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
cdef py_irem(x, n):
|
|
2099
|
+
return Integer(x) % Integer(n)
|
|
2100
|
+
|
|
2101
|
+
|
|
2102
|
+
cdef py_iquo(x, n):
|
|
2103
|
+
return Integer(x)//Integer(n)
|
|
2104
|
+
|
|
2105
|
+
|
|
2106
|
+
cdef py_iquo2(x, n):
|
|
2107
|
+
x = Integer(x)
|
|
2108
|
+
n = Integer(n)
|
|
2109
|
+
try:
|
|
2110
|
+
q = x//n
|
|
2111
|
+
r = x - q*n
|
|
2112
|
+
return q, r
|
|
2113
|
+
except (TypeError, ValueError):
|
|
2114
|
+
return 0, 0
|
|
2115
|
+
|
|
2116
|
+
|
|
2117
|
+
cdef int py_int_length(x) except -1:
|
|
2118
|
+
# Size in binary notation. For integers, this is the smallest n >= 0 such
|
|
2119
|
+
# that -2^n <= x < 2^n. If x > 0, this is the unique n > 0 such that
|
|
2120
|
+
# 2^(n-1) <= x < 2^n. This returns 0 if x is not an integer.
|
|
2121
|
+
return Integer(x).nbits()
|
|
2122
|
+
|
|
2123
|
+
|
|
2124
|
+
cdef py_li(x, n, parent):
|
|
2125
|
+
"""
|
|
2126
|
+
Return a numerical approximation of polylog(n, x) with precision given
|
|
2127
|
+
by the ``parent`` argument.
|
|
2128
|
+
|
|
2129
|
+
EXAMPLES::
|
|
2130
|
+
|
|
2131
|
+
sage: from sage.symbolic.expression import py_li_for_doctests as py_li
|
|
2132
|
+
sage: py_li(0,2,RR)
|
|
2133
|
+
0.000000000000000
|
|
2134
|
+
sage: py_li(-1,2,RR)
|
|
2135
|
+
-0.822467033424113
|
|
2136
|
+
sage: py_li(0, 1, float)
|
|
2137
|
+
0.000000000000000
|
|
2138
|
+
"""
|
|
2139
|
+
import mpmath
|
|
2140
|
+
try:
|
|
2141
|
+
prec = parent.prec()
|
|
2142
|
+
except AttributeError:
|
|
2143
|
+
prec = 53
|
|
2144
|
+
return mpmath_utils.call(mpmath.polylog, n, x, prec=prec)
|
|
2145
|
+
|
|
2146
|
+
|
|
2147
|
+
def py_li_for_doctests(x, n, parent):
|
|
2148
|
+
"""
|
|
2149
|
+
This function is a python wrapper so py_li can be tested. The real tests
|
|
2150
|
+
are in the docstring for py_li.
|
|
2151
|
+
|
|
2152
|
+
EXAMPLES::
|
|
2153
|
+
|
|
2154
|
+
sage: from sage.symbolic.expression import py_li_for_doctests
|
|
2155
|
+
sage: py_li_for_doctests(0,2,float)
|
|
2156
|
+
0.000000000000000
|
|
2157
|
+
"""
|
|
2158
|
+
return py_li(x, n, parent)
|
|
2159
|
+
|
|
2160
|
+
|
|
2161
|
+
cdef py_psi(x):
|
|
2162
|
+
"""
|
|
2163
|
+
EXAMPLES::
|
|
2164
|
+
|
|
2165
|
+
sage: from sage.symbolic.expression import py_psi_for_doctests as py_psi
|
|
2166
|
+
sage: py_psi(0)
|
|
2167
|
+
Traceback (most recent call last):
|
|
2168
|
+
...
|
|
2169
|
+
ValueError: polygamma pole
|
|
2170
|
+
sage: py_psi(1)
|
|
2171
|
+
-0.577215664901533
|
|
2172
|
+
sage: euler_gamma.n()
|
|
2173
|
+
0.577215664901533
|
|
2174
|
+
"""
|
|
2175
|
+
import mpmath
|
|
2176
|
+
if isinstance(x, Element) and hasattr((<Element>x)._parent, 'prec'):
|
|
2177
|
+
prec = (<Element>x)._parent.prec()
|
|
2178
|
+
else:
|
|
2179
|
+
prec = 53
|
|
2180
|
+
return mpmath_utils.call(mpmath.psi, 0, x, prec=prec)
|
|
2181
|
+
|
|
2182
|
+
|
|
2183
|
+
def py_psi_for_doctests(x):
|
|
2184
|
+
"""
|
|
2185
|
+
This function is a python wrapper so py_psi can be tested. The real tests
|
|
2186
|
+
are in the docstring for py_psi.
|
|
2187
|
+
|
|
2188
|
+
EXAMPLES::
|
|
2189
|
+
|
|
2190
|
+
sage: from sage.symbolic.expression import py_psi_for_doctests
|
|
2191
|
+
sage: py_psi_for_doctests(2)
|
|
2192
|
+
0.422784335098467
|
|
2193
|
+
"""
|
|
2194
|
+
return py_psi(x)
|
|
2195
|
+
|
|
2196
|
+
cdef py_psi2(n, x):
|
|
2197
|
+
"""
|
|
2198
|
+
EXAMPLES::
|
|
2199
|
+
|
|
2200
|
+
sage: from sage.symbolic.expression import py_psi2_for_doctests as py_psi2
|
|
2201
|
+
sage: py_psi2(2, 1)
|
|
2202
|
+
-2.40411380631919
|
|
2203
|
+
"""
|
|
2204
|
+
import mpmath
|
|
2205
|
+
if isinstance(x, Element) and hasattr((<Element>x)._parent, 'prec'):
|
|
2206
|
+
prec = (<Element>x)._parent.prec()
|
|
2207
|
+
else:
|
|
2208
|
+
prec = 53
|
|
2209
|
+
return mpmath_utils.call(mpmath.psi, n, x, prec=prec)
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
def py_psi2_for_doctests(n, x):
|
|
2213
|
+
"""
|
|
2214
|
+
This function is a python wrapper so py_psi2 can be tested. The real tests
|
|
2215
|
+
are in the docstring for py_psi2.
|
|
2216
|
+
|
|
2217
|
+
EXAMPLES::
|
|
2218
|
+
|
|
2219
|
+
sage: from sage.symbolic.expression import py_psi2_for_doctests
|
|
2220
|
+
sage: py_psi2_for_doctests(1, 2)
|
|
2221
|
+
0.644934066848226
|
|
2222
|
+
"""
|
|
2223
|
+
return py_psi2(n, x)
|
|
2224
|
+
|
|
2225
|
+
cdef py_li2(x):
|
|
2226
|
+
"""
|
|
2227
|
+
EXAMPLES::
|
|
2228
|
+
|
|
2229
|
+
sage: from sage.symbolic.expression import py_li2_for_doctests as py_li2
|
|
2230
|
+
sage: py_li2(-1.1)
|
|
2231
|
+
-0.890838090262283
|
|
2232
|
+
"""
|
|
2233
|
+
import mpmath
|
|
2234
|
+
if isinstance(x, Element) and hasattr((<Element>x)._parent, 'prec'):
|
|
2235
|
+
prec = (<Element>x)._parent.prec()
|
|
2236
|
+
else:
|
|
2237
|
+
prec = 53
|
|
2238
|
+
return mpmath_utils.call(mpmath.polylog, 2, x, prec=prec)
|
|
2239
|
+
|
|
2240
|
+
|
|
2241
|
+
def py_li2_for_doctests(x):
|
|
2242
|
+
"""
|
|
2243
|
+
This function is a python wrapper so py_psi2 can be tested. The real tests
|
|
2244
|
+
are in the docstring for py_psi2.
|
|
2245
|
+
|
|
2246
|
+
EXAMPLES::
|
|
2247
|
+
|
|
2248
|
+
sage: from sage.symbolic.expression import py_li2_for_doctests
|
|
2249
|
+
sage: py_li2_for_doctests(-1.1)
|
|
2250
|
+
-0.890838090262283
|
|
2251
|
+
"""
|
|
2252
|
+
return py_li2(x)
|
|
2253
|
+
|
|
2254
|
+
|
|
2255
|
+
##################################################################
|
|
2256
|
+
# Constants
|
|
2257
|
+
##################################################################
|
|
2258
|
+
|
|
2259
|
+
cdef GConstant py_get_constant(const char* name) noexcept:
|
|
2260
|
+
"""
|
|
2261
|
+
Return a constant given its name. This is called by constant::unarchive in
|
|
2262
|
+
constant.cpp in Pynac and is used for pickling.
|
|
2263
|
+
"""
|
|
2264
|
+
from sage.symbolic.constants import constants_name_table
|
|
2265
|
+
cdef PynacConstant pc
|
|
2266
|
+
c = constants_name_table.get(char_to_str(name), None)
|
|
2267
|
+
if c is None:
|
|
2268
|
+
raise RuntimeError
|
|
2269
|
+
else:
|
|
2270
|
+
pc = c._pynac
|
|
2271
|
+
return pc.pointer[0]
|
|
2272
|
+
|
|
2273
|
+
cdef py_eval_constant(unsigned serial, kwds):
|
|
2274
|
+
from sage.symbolic.constants import constants_table
|
|
2275
|
+
constant = constants_table[serial]
|
|
2276
|
+
return kwds['parent'](constant)
|
|
2277
|
+
|
|
2278
|
+
cdef py_eval_unsigned_infinity():
|
|
2279
|
+
"""
|
|
2280
|
+
Return ``unsigned_infinity``.
|
|
2281
|
+
"""
|
|
2282
|
+
from sage.rings.infinity import unsigned_infinity
|
|
2283
|
+
return unsigned_infinity
|
|
2284
|
+
|
|
2285
|
+
|
|
2286
|
+
def py_eval_unsigned_infinity_for_doctests():
|
|
2287
|
+
"""
|
|
2288
|
+
This function tests py_eval_unsigned_infinity.
|
|
2289
|
+
|
|
2290
|
+
TESTS::
|
|
2291
|
+
|
|
2292
|
+
sage: from sage.symbolic.expression import py_eval_unsigned_infinity_for_doctests as py_eval_unsigned_infinity
|
|
2293
|
+
sage: py_eval_unsigned_infinity()
|
|
2294
|
+
Infinity
|
|
2295
|
+
"""
|
|
2296
|
+
return py_eval_unsigned_infinity()
|
|
2297
|
+
|
|
2298
|
+
cdef py_eval_infinity():
|
|
2299
|
+
"""
|
|
2300
|
+
Return positive infinity, i.e., oo.
|
|
2301
|
+
"""
|
|
2302
|
+
from sage.rings.infinity import infinity
|
|
2303
|
+
return infinity
|
|
2304
|
+
|
|
2305
|
+
|
|
2306
|
+
def py_eval_infinity_for_doctests():
|
|
2307
|
+
"""
|
|
2308
|
+
This function tests py_eval_infinity.
|
|
2309
|
+
|
|
2310
|
+
TESTS::
|
|
2311
|
+
|
|
2312
|
+
sage: from sage.symbolic.expression import py_eval_infinity_for_doctests as py_eval_infinity
|
|
2313
|
+
sage: py_eval_infinity()
|
|
2314
|
+
+Infinity
|
|
2315
|
+
"""
|
|
2316
|
+
return py_eval_infinity()
|
|
2317
|
+
|
|
2318
|
+
cdef py_eval_neg_infinity():
|
|
2319
|
+
"""
|
|
2320
|
+
Return ``minus_infinity``.
|
|
2321
|
+
"""
|
|
2322
|
+
from sage.rings.infinity import minus_infinity
|
|
2323
|
+
return minus_infinity
|
|
2324
|
+
|
|
2325
|
+
|
|
2326
|
+
def py_eval_neg_infinity_for_doctests():
|
|
2327
|
+
"""
|
|
2328
|
+
This function tests py_eval_neg_infinity.
|
|
2329
|
+
|
|
2330
|
+
TESTS::
|
|
2331
|
+
|
|
2332
|
+
sage: from sage.symbolic.expression import py_eval_neg_infinity_for_doctests as py_eval_neg_infinity
|
|
2333
|
+
sage: py_eval_neg_infinity()
|
|
2334
|
+
-Infinity
|
|
2335
|
+
"""
|
|
2336
|
+
return py_eval_neg_infinity()
|
|
2337
|
+
|
|
2338
|
+
##################################################################
|
|
2339
|
+
# Constructors
|
|
2340
|
+
##################################################################
|
|
2341
|
+
|
|
2342
|
+
cdef py_integer_from_long(long x):
|
|
2343
|
+
return smallInteger(x)
|
|
2344
|
+
|
|
2345
|
+
cdef py_integer_from_python_obj(x):
|
|
2346
|
+
return Integer(x)
|
|
2347
|
+
|
|
2348
|
+
cdef py_integer_from_mpz(mpz_t bigint):
|
|
2349
|
+
cdef Integer z = PY_NEW(Integer)
|
|
2350
|
+
mpz_set(z.value, bigint)
|
|
2351
|
+
return z
|
|
2352
|
+
|
|
2353
|
+
cdef py_rational_from_mpq(mpq_t bigrat):
|
|
2354
|
+
cdef Rational rat = Rational.__new__(Rational)
|
|
2355
|
+
mpq_set(rat.value, bigrat)
|
|
2356
|
+
mpq_canonicalize(rat.value)
|
|
2357
|
+
return rat
|
|
2358
|
+
|
|
2359
|
+
|
|
2360
|
+
cdef bint py_is_Integer(x) noexcept:
|
|
2361
|
+
return isinstance(x, Integer)
|
|
2362
|
+
|
|
2363
|
+
|
|
2364
|
+
cdef bint py_is_Rational(x) noexcept:
|
|
2365
|
+
return isinstance(x, Rational)
|
|
2366
|
+
|
|
2367
|
+
|
|
2368
|
+
cdef mpz_ptr py_mpz_from_integer(x) noexcept:
|
|
2369
|
+
return <mpz_ptr>((<Integer>x).value)
|
|
2370
|
+
|
|
2371
|
+
|
|
2372
|
+
cdef mpq_ptr py_mpq_from_rational(x) noexcept:
|
|
2373
|
+
return <mpq_ptr>((<Rational>x).value)
|
|
2374
|
+
|
|
2375
|
+
|
|
2376
|
+
import sage.rings.integer
|
|
2377
|
+
ginac_pyinit_Integer(sage.rings.integer.Integer)
|
|
2378
|
+
|
|
2379
|
+
import sage.rings.real_double
|
|
2380
|
+
ginac_pyinit_Float(sage.rings.real_double.RDF)
|
|
2381
|
+
|
|
2382
|
+
cdef Element pynac_I
|
|
2383
|
+
|
|
2384
|
+
|
|
2385
|
+
def init_pynac_I():
|
|
2386
|
+
"""
|
|
2387
|
+
Initialize the numeric ``I`` object in pynac. We use the generator of ``QQ(i)``.
|
|
2388
|
+
|
|
2389
|
+
EXAMPLES::
|
|
2390
|
+
|
|
2391
|
+
sage: from sage.symbolic.constants import I as symbolic_I
|
|
2392
|
+
sage: symbolic_I
|
|
2393
|
+
I
|
|
2394
|
+
sage: symbolic_I^2
|
|
2395
|
+
-1
|
|
2396
|
+
|
|
2397
|
+
Note that conversions to real fields will give :exc:`TypeError`::
|
|
2398
|
+
|
|
2399
|
+
sage: float(symbolic_I)
|
|
2400
|
+
Traceback (most recent call last):
|
|
2401
|
+
...
|
|
2402
|
+
TypeError: unable to simplify to float approximation
|
|
2403
|
+
sage: gp(symbolic_I) # needs sage.libs.pari
|
|
2404
|
+
I
|
|
2405
|
+
sage: RR(symbolic_I)
|
|
2406
|
+
Traceback (most recent call last):
|
|
2407
|
+
...
|
|
2408
|
+
TypeError: unable to convert '1.00000000000000*I' to a real number
|
|
2409
|
+
|
|
2410
|
+
We can convert to complex fields::
|
|
2411
|
+
|
|
2412
|
+
sage: C = ComplexField(200); C
|
|
2413
|
+
Complex Field with 200 bits of precision
|
|
2414
|
+
sage: C(symbolic_I)
|
|
2415
|
+
1.0000000000000000000000000000000000000000000000000000000000*I
|
|
2416
|
+
sage: symbolic_I._complex_mpfr_field_(ComplexField(53))
|
|
2417
|
+
1.00000000000000*I
|
|
2418
|
+
|
|
2419
|
+
sage: symbolic_I._complex_double_(CDF)
|
|
2420
|
+
1.0*I
|
|
2421
|
+
sage: CDF(symbolic_I)
|
|
2422
|
+
1.0*I
|
|
2423
|
+
|
|
2424
|
+
sage: z = symbolic_I + symbolic_I; z
|
|
2425
|
+
2*I
|
|
2426
|
+
sage: C(z)
|
|
2427
|
+
2.0000000000000000000000000000000000000000000000000000000000*I
|
|
2428
|
+
sage: 1e8*symbolic_I
|
|
2429
|
+
1.00000000000000e8*I
|
|
2430
|
+
|
|
2431
|
+
sage: complex(symbolic_I)
|
|
2432
|
+
1j
|
|
2433
|
+
|
|
2434
|
+
sage: QQbar(symbolic_I)
|
|
2435
|
+
I
|
|
2436
|
+
|
|
2437
|
+
sage: abs(symbolic_I)
|
|
2438
|
+
1
|
|
2439
|
+
|
|
2440
|
+
sage: symbolic_I.minpoly()
|
|
2441
|
+
x^2 + 1
|
|
2442
|
+
sage: maxima(2*symbolic_I)
|
|
2443
|
+
2*%i
|
|
2444
|
+
|
|
2445
|
+
TESTS::
|
|
2446
|
+
|
|
2447
|
+
sage: repr(symbolic_I)
|
|
2448
|
+
'I'
|
|
2449
|
+
sage: latex(symbolic_I)
|
|
2450
|
+
i
|
|
2451
|
+
|
|
2452
|
+
sage: I = sage.symbolic.expression.init_pynac_I()
|
|
2453
|
+
sage: type(I)
|
|
2454
|
+
<class 'sage.symbolic.expression.Expression'>
|
|
2455
|
+
sage: type(I.pyobject())
|
|
2456
|
+
<class 'sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_gaussian'>
|
|
2457
|
+
|
|
2458
|
+
Check that :issue:`10064` is fixed::
|
|
2459
|
+
|
|
2460
|
+
sage: y = symbolic_I*symbolic_I*x / x # so y is the expression -1
|
|
2461
|
+
sage: y.is_positive()
|
|
2462
|
+
False
|
|
2463
|
+
sage: z = -x / x
|
|
2464
|
+
sage: z.is_positive()
|
|
2465
|
+
False
|
|
2466
|
+
sage: bool(z == y)
|
|
2467
|
+
True
|
|
2468
|
+
|
|
2469
|
+
Check that :issue:`31869` is fixed::
|
|
2470
|
+
|
|
2471
|
+
sage: x * ((3*I + 4)*x - 5)
|
|
2472
|
+
((3*I + 4)*x - 5)*x
|
|
2473
|
+
"""
|
|
2474
|
+
global pynac_I
|
|
2475
|
+
from sage.rings.number_field.number_field import GaussianField
|
|
2476
|
+
pynac_I = GaussianField().gen()
|
|
2477
|
+
ginac_pyinit_I(pynac_I)
|
|
2478
|
+
from sage.symbolic.ring import SR
|
|
2479
|
+
return new_Expression_from_GEx(SR, g_I)
|
|
2480
|
+
|
|
2481
|
+
|
|
2482
|
+
def init_function_table():
|
|
2483
|
+
"""
|
|
2484
|
+
Initialize the function pointer table in Pynac. This must be
|
|
2485
|
+
called before Pynac is used; otherwise, there will be segfaults.
|
|
2486
|
+
"""
|
|
2487
|
+
|
|
2488
|
+
py_funcs.py_gcd = &py_gcd
|
|
2489
|
+
py_funcs.py_lcm = &py_lcm
|
|
2490
|
+
py_funcs.py_real = &py_real
|
|
2491
|
+
py_funcs.py_imag = &py_imag
|
|
2492
|
+
py_funcs.py_numer = &py_numer
|
|
2493
|
+
py_funcs.py_denom = &py_denom
|
|
2494
|
+
|
|
2495
|
+
py_funcs.py_is_rational = &py_is_rational
|
|
2496
|
+
py_funcs.py_is_real = &py_is_real
|
|
2497
|
+
py_funcs.py_is_integer = &py_is_integer
|
|
2498
|
+
py_funcs.py_is_equal = &py_is_equal
|
|
2499
|
+
py_funcs.py_is_even = &py_is_even
|
|
2500
|
+
py_funcs.py_is_prime = &py_is_prime
|
|
2501
|
+
py_funcs.py_is_exact = &py_is_exact
|
|
2502
|
+
|
|
2503
|
+
py_funcs.py_integer_from_mpz = &py_integer_from_mpz
|
|
2504
|
+
py_funcs.py_rational_from_mpq = &py_rational_from_mpq
|
|
2505
|
+
py_funcs.py_integer_from_long = &py_integer_from_long
|
|
2506
|
+
py_funcs.py_integer_from_python_obj = &py_integer_from_python_obj
|
|
2507
|
+
py_funcs.py_is_Integer = &py_is_Integer
|
|
2508
|
+
py_funcs.py_is_Rational = &py_is_Rational
|
|
2509
|
+
py_funcs.py_mpz_from_integer = &py_mpz_from_integer
|
|
2510
|
+
py_funcs.py_mpq_from_rational = &py_mpq_from_rational
|
|
2511
|
+
|
|
2512
|
+
py_funcs.py_float = &py_float
|
|
2513
|
+
|
|
2514
|
+
py_funcs.py_factorial = &py_factorial
|
|
2515
|
+
py_funcs.py_doublefactorial = &py_doublefactorial
|
|
2516
|
+
py_funcs.py_fibonacci = &py_fibonacci
|
|
2517
|
+
py_funcs.py_step = &py_step
|
|
2518
|
+
py_funcs.py_bernoulli = &py_bernoulli
|
|
2519
|
+
py_funcs.py_sin = &py_sin
|
|
2520
|
+
py_funcs.py_cos = &py_cos
|
|
2521
|
+
py_funcs.py_stieltjes = &py_stieltjes
|
|
2522
|
+
py_funcs.py_zeta = &py_zeta
|
|
2523
|
+
py_funcs.py_exp = &py_exp
|
|
2524
|
+
py_funcs.py_log = &py_log
|
|
2525
|
+
py_funcs.py_tan = &py_tan
|
|
2526
|
+
py_funcs.py_asin = &py_asin
|
|
2527
|
+
py_funcs.py_acos = &py_acos
|
|
2528
|
+
py_funcs.py_atan = &py_atan
|
|
2529
|
+
py_funcs.py_atan2 = &py_atan2
|
|
2530
|
+
py_funcs.py_sinh = &py_sinh
|
|
2531
|
+
py_funcs.py_cosh = &py_cosh
|
|
2532
|
+
py_funcs.py_tanh = &py_tanh
|
|
2533
|
+
py_funcs.py_asinh = &py_asinh
|
|
2534
|
+
py_funcs.py_acosh = &py_acosh
|
|
2535
|
+
py_funcs.py_atanh = &py_atanh
|
|
2536
|
+
py_funcs.py_isqrt = &py_isqrt
|
|
2537
|
+
py_funcs.py_sqrt = &py_sqrt
|
|
2538
|
+
py_funcs.py_mod = &py_mod
|
|
2539
|
+
py_funcs.py_smod = &py_smod
|
|
2540
|
+
py_funcs.py_irem = &py_irem
|
|
2541
|
+
py_funcs.py_psi = &py_psi
|
|
2542
|
+
py_funcs.py_psi2 = &py_psi2
|
|
2543
|
+
|
|
2544
|
+
py_funcs.py_eval_constant = &py_eval_constant
|
|
2545
|
+
py_funcs.py_eval_unsigned_infinity = &py_eval_unsigned_infinity
|
|
2546
|
+
py_funcs.py_eval_infinity = &py_eval_infinity
|
|
2547
|
+
py_funcs.py_eval_neg_infinity = &py_eval_neg_infinity
|
|
2548
|
+
|
|
2549
|
+
py_funcs.py_get_parent_char = &py_get_parent_char
|
|
2550
|
+
|
|
2551
|
+
py_funcs.py_latex = &py_latex
|
|
2552
|
+
py_funcs.py_repr = &py_repr
|
|
2553
|
+
|
|
2554
|
+
py_funcs.py_dumps = &py_dumps
|
|
2555
|
+
py_funcs.py_loads = &py_loads
|
|
2556
|
+
|
|
2557
|
+
py_funcs.exvector_to_PyTuple = &exvector_to_PyTuple
|
|
2558
|
+
py_funcs.pyExpression_to_ex = &pyExpression_to_ex
|
|
2559
|
+
py_funcs.ex_to_pyExpression = &ex_to_pyExpression
|
|
2560
|
+
py_funcs.subs_args_to_PyTuple = &subs_args_to_PyTuple
|
|
2561
|
+
py_funcs.py_print_function = &py_print_function
|
|
2562
|
+
py_funcs.py_latex_function = &py_latex_function
|
|
2563
|
+
py_funcs.py_get_ginac_serial = &py_get_ginac_serial
|
|
2564
|
+
py_funcs.py_get_sfunction_from_serial = &py_get_sfunction_from_serial
|
|
2565
|
+
py_funcs.py_get_serial_from_sfunction = &py_get_serial_from_sfunction
|
|
2566
|
+
py_funcs.py_get_serial_for_new_sfunction = &py_get_serial_for_new_sfunction
|
|
2567
|
+
|
|
2568
|
+
py_funcs.py_get_constant = &py_get_constant
|
|
2569
|
+
py_funcs.py_print_fderivative = &py_print_fderivative
|
|
2570
|
+
py_funcs.py_latex_fderivative = &py_latex_fderivative
|
|
2571
|
+
py_funcs.paramset_to_PyTuple = ¶mset_to_PyTuple
|
|
2572
|
+
|
|
2573
|
+
|
|
2574
|
+
init_function_table()
|
|
2575
|
+
|
|
2576
|
+
set_ginac_fn_serial()
|