passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_categories-10.6.32.dist-info/METADATA +156 -0
- passagemath_categories-10.6.32.dist-info/RECORD +719 -0
- passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
- passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
- sage/all__sagemath_categories.py +28 -0
- sage/arith/all.py +38 -0
- sage/arith/constants.pxd +27 -0
- sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/functions.pxd +4 -0
- sage/arith/functions.pyx +221 -0
- sage/arith/misc.py +6552 -0
- sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/multi_modular.pxd +39 -0
- sage/arith/multi_modular.pyx +994 -0
- sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/rational_reconstruction.pxd +4 -0
- sage/arith/rational_reconstruction.pyx +115 -0
- sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/srange.pyx +571 -0
- sage/calculus/all__sagemath_categories.py +2 -0
- sage/calculus/functional.py +481 -0
- sage/calculus/functions.py +151 -0
- sage/categories/additive_groups.py +73 -0
- sage/categories/additive_magmas.py +1044 -0
- sage/categories/additive_monoids.py +114 -0
- sage/categories/additive_semigroups.py +184 -0
- sage/categories/affine_weyl_groups.py +238 -0
- sage/categories/algebra_ideals.py +95 -0
- sage/categories/algebra_modules.py +96 -0
- sage/categories/algebras.py +349 -0
- sage/categories/algebras_with_basis.py +377 -0
- sage/categories/all.py +160 -0
- sage/categories/aperiodic_semigroups.py +29 -0
- sage/categories/associative_algebras.py +47 -0
- sage/categories/bialgebras.py +101 -0
- sage/categories/bialgebras_with_basis.py +414 -0
- sage/categories/bimodules.py +206 -0
- sage/categories/chain_complexes.py +268 -0
- sage/categories/classical_crystals.py +480 -0
- sage/categories/coalgebras.py +405 -0
- sage/categories/coalgebras_with_basis.py +232 -0
- sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/coercion_methods.pyx +52 -0
- sage/categories/commutative_additive_groups.py +104 -0
- sage/categories/commutative_additive_monoids.py +45 -0
- sage/categories/commutative_additive_semigroups.py +48 -0
- sage/categories/commutative_algebra_ideals.py +87 -0
- sage/categories/commutative_algebras.py +94 -0
- sage/categories/commutative_ring_ideals.py +58 -0
- sage/categories/commutative_rings.py +736 -0
- sage/categories/complete_discrete_valuation.py +293 -0
- sage/categories/complex_reflection_groups.py +145 -0
- sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
- sage/categories/coxeter_group_algebras.py +186 -0
- sage/categories/coxeter_groups.py +3402 -0
- sage/categories/crystals.py +2628 -0
- sage/categories/cw_complexes.py +216 -0
- sage/categories/dedekind_domains.py +137 -0
- sage/categories/discrete_valuation.py +325 -0
- sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
- sage/categories/division_rings.py +114 -0
- sage/categories/domains.py +95 -0
- sage/categories/drinfeld_modules.py +789 -0
- sage/categories/dual.py +42 -0
- sage/categories/enumerated_sets.py +1146 -0
- sage/categories/euclidean_domains.py +271 -0
- sage/categories/examples/algebras_with_basis.py +102 -0
- sage/categories/examples/all.py +1 -0
- sage/categories/examples/commutative_additive_monoids.py +130 -0
- sage/categories/examples/commutative_additive_semigroups.py +199 -0
- sage/categories/examples/coxeter_groups.py +8 -0
- sage/categories/examples/crystals.py +236 -0
- sage/categories/examples/cw_complexes.py +163 -0
- sage/categories/examples/facade_sets.py +187 -0
- sage/categories/examples/filtered_algebras_with_basis.py +204 -0
- sage/categories/examples/filtered_modules_with_basis.py +154 -0
- sage/categories/examples/finite_coxeter_groups.py +252 -0
- sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
- sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
- sage/categories/examples/finite_enumerated_sets.py +208 -0
- sage/categories/examples/finite_monoids.py +150 -0
- sage/categories/examples/finite_semigroups.py +190 -0
- sage/categories/examples/finite_weyl_groups.py +191 -0
- sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
- sage/categories/examples/graded_modules_with_basis.py +168 -0
- sage/categories/examples/graphs.py +122 -0
- sage/categories/examples/hopf_algebras_with_basis.py +145 -0
- sage/categories/examples/infinite_enumerated_sets.py +190 -0
- sage/categories/examples/lie_algebras.py +352 -0
- sage/categories/examples/lie_algebras_with_basis.py +196 -0
- sage/categories/examples/magmas.py +162 -0
- sage/categories/examples/manifolds.py +94 -0
- sage/categories/examples/monoids.py +144 -0
- sage/categories/examples/posets.py +178 -0
- sage/categories/examples/semigroups.py +580 -0
- sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/examples/semigroups_cython.pyx +221 -0
- sage/categories/examples/semirings.py +249 -0
- sage/categories/examples/sets_cat.py +706 -0
- sage/categories/examples/sets_with_grading.py +101 -0
- sage/categories/examples/with_realizations.py +542 -0
- sage/categories/fields.py +991 -0
- sage/categories/filtered_algebras.py +63 -0
- sage/categories/filtered_algebras_with_basis.py +548 -0
- sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
- sage/categories/filtered_modules.py +210 -0
- sage/categories/filtered_modules_with_basis.py +1209 -0
- sage/categories/finite_complex_reflection_groups.py +1506 -0
- sage/categories/finite_coxeter_groups.py +1138 -0
- sage/categories/finite_crystals.py +103 -0
- sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
- sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
- sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
- sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
- sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
- sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
- sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
- sage/categories/finite_enumerated_sets.py +769 -0
- sage/categories/finite_fields.py +252 -0
- sage/categories/finite_groups.py +256 -0
- sage/categories/finite_lattice_posets.py +242 -0
- sage/categories/finite_monoids.py +316 -0
- sage/categories/finite_permutation_groups.py +339 -0
- sage/categories/finite_posets.py +1994 -0
- sage/categories/finite_semigroups.py +136 -0
- sage/categories/finite_sets.py +93 -0
- sage/categories/finite_weyl_groups.py +39 -0
- sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
- sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
- sage/categories/finitely_generated_magmas.py +57 -0
- sage/categories/finitely_generated_semigroups.py +214 -0
- sage/categories/function_fields.py +76 -0
- sage/categories/g_sets.py +77 -0
- sage/categories/gcd_domains.py +65 -0
- sage/categories/generalized_coxeter_groups.py +94 -0
- sage/categories/graded_algebras.py +85 -0
- sage/categories/graded_algebras_with_basis.py +258 -0
- sage/categories/graded_bialgebras.py +32 -0
- sage/categories/graded_bialgebras_with_basis.py +32 -0
- sage/categories/graded_coalgebras.py +65 -0
- sage/categories/graded_coalgebras_with_basis.py +51 -0
- sage/categories/graded_hopf_algebras.py +41 -0
- sage/categories/graded_hopf_algebras_with_basis.py +169 -0
- sage/categories/graded_lie_algebras.py +91 -0
- sage/categories/graded_lie_algebras_with_basis.py +44 -0
- sage/categories/graded_lie_conformal_algebras.py +74 -0
- sage/categories/graded_modules.py +133 -0
- sage/categories/graded_modules_with_basis.py +329 -0
- sage/categories/graphs.py +138 -0
- sage/categories/group_algebras.py +430 -0
- sage/categories/groupoid.py +94 -0
- sage/categories/groups.py +667 -0
- sage/categories/h_trivial_semigroups.py +64 -0
- sage/categories/hecke_modules.py +185 -0
- sage/categories/highest_weight_crystals.py +980 -0
- sage/categories/hopf_algebras.py +219 -0
- sage/categories/hopf_algebras_with_basis.py +309 -0
- sage/categories/infinite_enumerated_sets.py +115 -0
- sage/categories/integral_domains.py +203 -0
- sage/categories/j_trivial_semigroups.py +29 -0
- sage/categories/kac_moody_algebras.py +82 -0
- sage/categories/kahler_algebras.py +203 -0
- sage/categories/l_trivial_semigroups.py +63 -0
- sage/categories/lambda_bracket_algebras.py +280 -0
- sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
- sage/categories/lattice_posets.py +89 -0
- sage/categories/left_modules.py +49 -0
- sage/categories/lie_algebras.py +1070 -0
- sage/categories/lie_algebras_with_basis.py +261 -0
- sage/categories/lie_conformal_algebras.py +350 -0
- sage/categories/lie_conformal_algebras_with_basis.py +147 -0
- sage/categories/lie_groups.py +73 -0
- sage/categories/loop_crystals.py +1290 -0
- sage/categories/magmas.py +1189 -0
- sage/categories/magmas_and_additive_magmas.py +149 -0
- sage/categories/magmatic_algebras.py +365 -0
- sage/categories/manifolds.py +352 -0
- sage/categories/matrix_algebras.py +40 -0
- sage/categories/metric_spaces.py +387 -0
- sage/categories/modular_abelian_varieties.py +78 -0
- sage/categories/modules.py +989 -0
- sage/categories/modules_with_basis.py +2794 -0
- sage/categories/monoid_algebras.py +38 -0
- sage/categories/monoids.py +739 -0
- sage/categories/noetherian_rings.py +87 -0
- sage/categories/number_fields.py +242 -0
- sage/categories/ore_modules.py +189 -0
- sage/categories/partially_ordered_monoids.py +49 -0
- sage/categories/permutation_groups.py +63 -0
- sage/categories/pointed_sets.py +42 -0
- sage/categories/polyhedra.py +74 -0
- sage/categories/poor_man_map.py +270 -0
- sage/categories/posets.py +722 -0
- sage/categories/principal_ideal_domains.py +270 -0
- sage/categories/quantum_group_representations.py +543 -0
- sage/categories/quotient_fields.py +728 -0
- sage/categories/r_trivial_semigroups.py +45 -0
- sage/categories/regular_crystals.py +898 -0
- sage/categories/regular_supercrystals.py +170 -0
- sage/categories/right_modules.py +49 -0
- sage/categories/ring_ideals.py +74 -0
- sage/categories/rings.py +1904 -0
- sage/categories/rngs.py +175 -0
- sage/categories/schemes.py +393 -0
- sage/categories/semigroups.py +1060 -0
- sage/categories/semirings.py +71 -0
- sage/categories/semisimple_algebras.py +114 -0
- sage/categories/sets_with_grading.py +235 -0
- sage/categories/shephard_groups.py +43 -0
- sage/categories/signed_tensor.py +120 -0
- sage/categories/simplicial_complexes.py +134 -0
- sage/categories/simplicial_sets.py +1206 -0
- sage/categories/super_algebras.py +149 -0
- sage/categories/super_algebras_with_basis.py +144 -0
- sage/categories/super_hopf_algebras_with_basis.py +126 -0
- sage/categories/super_lie_conformal_algebras.py +193 -0
- sage/categories/super_modules.py +229 -0
- sage/categories/super_modules_with_basis.py +193 -0
- sage/categories/supercommutative_algebras.py +99 -0
- sage/categories/supercrystals.py +406 -0
- sage/categories/tensor.py +110 -0
- sage/categories/topological_spaces.py +170 -0
- sage/categories/triangular_kac_moody_algebras.py +439 -0
- sage/categories/tutorial.py +58 -0
- sage/categories/unique_factorization_domains.py +318 -0
- sage/categories/unital_algebras.py +426 -0
- sage/categories/vector_bundles.py +159 -0
- sage/categories/vector_spaces.py +357 -0
- sage/categories/weyl_groups.py +853 -0
- sage/combinat/all__sagemath_categories.py +34 -0
- sage/combinat/backtrack.py +180 -0
- sage/combinat/combinat.py +2269 -0
- sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/combinat_cython.pxd +6 -0
- sage/combinat/combinat_cython.pyx +390 -0
- sage/combinat/combination.py +796 -0
- sage/combinat/combinatorial_map.py +416 -0
- sage/combinat/composition.py +2192 -0
- sage/combinat/dlx.py +510 -0
- sage/combinat/integer_lists/__init__.py +7 -0
- sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/base.pxd +16 -0
- sage/combinat/integer_lists/base.pyx +713 -0
- sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/invlex.pxd +4 -0
- sage/combinat/integer_lists/invlex.pyx +1650 -0
- sage/combinat/integer_lists/lists.py +328 -0
- sage/combinat/integer_lists/nn.py +48 -0
- sage/combinat/integer_vector.py +1818 -0
- sage/combinat/integer_vector_weighted.py +413 -0
- sage/combinat/matrices/all__sagemath_categories.py +5 -0
- sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/matrices/dancing_links.pyx +1159 -0
- sage/combinat/matrices/dancing_links_c.h +380 -0
- sage/combinat/matrices/dlxcpp.py +136 -0
- sage/combinat/partition.py +10070 -0
- sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/partitions.pyx +743 -0
- sage/combinat/permutation.py +10168 -0
- sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/permutation_cython.pxd +11 -0
- sage/combinat/permutation_cython.pyx +407 -0
- sage/combinat/q_analogues.py +1090 -0
- sage/combinat/ranker.py +268 -0
- sage/combinat/subset.py +1561 -0
- sage/combinat/subsets_hereditary.py +202 -0
- sage/combinat/subsets_pairwise.py +184 -0
- sage/combinat/tools.py +63 -0
- sage/combinat/tuple.py +348 -0
- sage/data_structures/all.py +2 -0
- sage/data_structures/all__sagemath_categories.py +2 -0
- sage/data_structures/binary_matrix.pxd +138 -0
- sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/binary_search.pxd +3 -0
- sage/data_structures/binary_search.pyx +66 -0
- sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset.pxd +40 -0
- sage/data_structures/bitset.pyx +2385 -0
- sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset_base.pxd +926 -0
- sage/data_structures/bitset_base.pyx +117 -0
- sage/data_structures/bitset_intrinsics.h +487 -0
- sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/blas_dict.pxd +12 -0
- sage/data_structures/blas_dict.pyx +469 -0
- sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/list_of_pairs.pxd +16 -0
- sage/data_structures/list_of_pairs.pyx +122 -0
- sage/data_structures/mutable_poset.py +3312 -0
- sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/pairing_heap.h +346 -0
- sage/data_structures/pairing_heap.pxd +88 -0
- sage/data_structures/pairing_heap.pyx +1464 -0
- sage/data_structures/sparse_bitset.pxd +62 -0
- sage/data_structures/stream.py +5070 -0
- sage/databases/all__sagemath_categories.py +7 -0
- sage/databases/sql_db.py +2236 -0
- sage/ext/all__sagemath_categories.py +3 -0
- sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_callable.pxd +4 -0
- sage/ext/fast_callable.pyx +2746 -0
- sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_eval.pxd +1 -0
- sage/ext/fast_eval.pyx +102 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_categories.py +2 -0
- sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_el.pxd +18 -0
- sage/ext/interpreters/wrapper_el.pyx +148 -0
- sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_py.pxd +17 -0
- sage/ext/interpreters/wrapper_py.pyx +133 -0
- sage/functions/airy.py +937 -0
- sage/functions/all.py +97 -0
- sage/functions/bessel.py +2102 -0
- sage/functions/error.py +784 -0
- sage/functions/exp_integral.py +1529 -0
- sage/functions/gamma.py +1087 -0
- sage/functions/generalized.py +672 -0
- sage/functions/hyperbolic.py +747 -0
- sage/functions/hypergeometric.py +1156 -0
- sage/functions/jacobi.py +1705 -0
- sage/functions/log.py +1402 -0
- sage/functions/min_max.py +338 -0
- sage/functions/orthogonal_polys.py +3106 -0
- sage/functions/other.py +2303 -0
- sage/functions/piecewise.py +1505 -0
- sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/functions/prime_pi.pyx +262 -0
- sage/functions/special.py +1212 -0
- sage/functions/spike_function.py +278 -0
- sage/functions/transcendental.py +690 -0
- sage/functions/trig.py +1062 -0
- sage/functions/wigner.py +726 -0
- sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/geometry/abc.pyx +82 -0
- sage/geometry/all__sagemath_categories.py +1 -0
- sage/groups/all__sagemath_categories.py +11 -0
- sage/groups/generic.py +1733 -0
- sage/groups/groups_catalog.py +113 -0
- sage/groups/perm_gps/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/all.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
- sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
- sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
- sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
- sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
- sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
- sage/interfaces/abc.py +140 -0
- sage/interfaces/all.py +58 -0
- sage/interfaces/all__sagemath_categories.py +1 -0
- sage/interfaces/expect.py +1643 -0
- sage/interfaces/interface.py +1682 -0
- sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/process.pxd +5 -0
- sage/interfaces/process.pyx +288 -0
- sage/interfaces/quit.py +167 -0
- sage/interfaces/sage0.py +604 -0
- sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/sagespawn.pyx +308 -0
- sage/interfaces/tab_completion.py +101 -0
- sage/misc/all__sagemath_categories.py +78 -0
- sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/allocator.pxd +6 -0
- sage/misc/allocator.pyx +47 -0
- sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/binary_tree.pxd +29 -0
- sage/misc/binary_tree.pyx +537 -0
- sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/callable_dict.pyx +89 -0
- sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/citation.pyx +159 -0
- sage/misc/converting_dict.py +293 -0
- sage/misc/defaults.py +129 -0
- sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/derivative.pyx +223 -0
- sage/misc/functional.py +2005 -0
- sage/misc/html.py +589 -0
- sage/misc/latex.py +2673 -0
- sage/misc/latex_macros.py +236 -0
- sage/misc/latex_standalone.py +1833 -0
- sage/misc/map_threaded.py +38 -0
- sage/misc/mathml.py +76 -0
- sage/misc/method_decorator.py +88 -0
- sage/misc/mrange.py +755 -0
- sage/misc/multireplace.py +41 -0
- sage/misc/object_multiplexer.py +92 -0
- sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/parser.pyx +1107 -0
- sage/misc/random_testing.py +264 -0
- sage/misc/rest_index_of_methods.py +377 -0
- sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/search.pxd +2 -0
- sage/misc/search.pyx +68 -0
- sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/stopgap.pyx +95 -0
- sage/misc/table.py +853 -0
- sage/monoids/all__sagemath_categories.py +1 -0
- sage/monoids/indexed_free_monoid.py +1071 -0
- sage/monoids/monoid.py +82 -0
- sage/numerical/all__sagemath_categories.py +1 -0
- sage/numerical/backends/all__sagemath_categories.py +1 -0
- sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_backend.pxd +61 -0
- sage/numerical/backends/generic_backend.pyx +1893 -0
- sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_sdp_backend.pxd +38 -0
- sage/numerical/backends/generic_sdp_backend.pyx +755 -0
- sage/parallel/all.py +6 -0
- sage/parallel/decorate.py +575 -0
- sage/parallel/map_reduce.py +1997 -0
- sage/parallel/multiprocessing_sage.py +76 -0
- sage/parallel/ncpus.py +35 -0
- sage/parallel/parallelism.py +364 -0
- sage/parallel/reference.py +47 -0
- sage/parallel/use_fork.py +333 -0
- sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/abc.pxd +31 -0
- sage/rings/abc.pyx +526 -0
- sage/rings/algebraic_closure_finite_field.py +1154 -0
- sage/rings/all__sagemath_categories.py +91 -0
- sage/rings/big_oh.py +227 -0
- sage/rings/continued_fraction.py +2754 -0
- sage/rings/continued_fraction_gosper.py +220 -0
- sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/factorint.pyx +295 -0
- sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fast_arith.pxd +21 -0
- sage/rings/fast_arith.pyx +535 -0
- sage/rings/finite_rings/all__sagemath_categories.py +9 -0
- sage/rings/finite_rings/conway_polynomials.py +542 -0
- sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_base.pxd +12 -0
- sage/rings/finite_rings/element_base.pyx +1176 -0
- sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/finite_field_base.pxd +7 -0
- sage/rings/finite_rings/finite_field_base.pyx +2171 -0
- sage/rings/finite_rings/finite_field_constructor.py +827 -0
- sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
- sage/rings/finite_rings/galois_group.py +154 -0
- sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field.pxd +23 -0
- sage/rings/finite_rings/hom_finite_field.pyx +856 -0
- sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
- sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
- sage/rings/finite_rings/homset.py +357 -0
- sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/integer_mod.pxd +56 -0
- sage/rings/finite_rings/integer_mod.pyx +4586 -0
- sage/rings/finite_rings/integer_mod_limits.h +11 -0
- sage/rings/finite_rings/integer_mod_ring.py +2044 -0
- sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field.pxd +30 -0
- sage/rings/finite_rings/residue_field.pyx +1811 -0
- sage/rings/finite_rings/stdint.pxd +19 -0
- sage/rings/fraction_field.py +1452 -0
- sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fraction_field_element.pyx +1357 -0
- sage/rings/function_field/all.py +7 -0
- sage/rings/function_field/all__sagemath_categories.py +2 -0
- sage/rings/function_field/constructor.py +218 -0
- sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element.pxd +11 -0
- sage/rings/function_field/element.pyx +1008 -0
- sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element_rational.pyx +513 -0
- sage/rings/function_field/extensions.py +230 -0
- sage/rings/function_field/function_field.py +1468 -0
- sage/rings/function_field/function_field_rational.py +1005 -0
- sage/rings/function_field/ideal.py +1155 -0
- sage/rings/function_field/ideal_rational.py +629 -0
- sage/rings/function_field/jacobian_base.py +826 -0
- sage/rings/function_field/jacobian_hess.py +1053 -0
- sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
- sage/rings/function_field/maps.py +1039 -0
- sage/rings/function_field/order.py +281 -0
- sage/rings/function_field/order_basis.py +586 -0
- sage/rings/function_field/order_rational.py +576 -0
- sage/rings/function_field/place.py +426 -0
- sage/rings/function_field/place_rational.py +181 -0
- sage/rings/generic.py +320 -0
- sage/rings/homset.py +332 -0
- sage/rings/ideal.py +1885 -0
- sage/rings/ideal_monoid.py +215 -0
- sage/rings/infinity.py +1890 -0
- sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer.pxd +45 -0
- sage/rings/integer.pyx +7874 -0
- sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer_ring.pxd +8 -0
- sage/rings/integer_ring.pyx +1693 -0
- sage/rings/laurent_series_ring.py +931 -0
- sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/laurent_series_ring_element.pxd +11 -0
- sage/rings/laurent_series_ring_element.pyx +1927 -0
- sage/rings/lazy_series.py +7815 -0
- sage/rings/lazy_series_ring.py +4356 -0
- sage/rings/localization.py +1043 -0
- sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/morphism.pxd +39 -0
- sage/rings/morphism.pyx +3299 -0
- sage/rings/multi_power_series_ring.py +1145 -0
- sage/rings/multi_power_series_ring_element.py +2184 -0
- sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/noncommutative_ideals.pyx +423 -0
- sage/rings/number_field/all__sagemath_categories.py +1 -0
- sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_base.pxd +8 -0
- sage/rings/number_field/number_field_base.pyx +507 -0
- sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_element_base.pxd +6 -0
- sage/rings/number_field/number_field_element_base.pyx +36 -0
- sage/rings/number_field/number_field_ideal.py +3550 -0
- sage/rings/padics/all__sagemath_categories.py +4 -0
- sage/rings/padics/local_generic.py +1670 -0
- sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/local_generic_element.pxd +5 -0
- sage/rings/padics/local_generic_element.pyx +1017 -0
- sage/rings/padics/misc.py +256 -0
- sage/rings/padics/padic_generic.py +1911 -0
- sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer.pxd +38 -0
- sage/rings/padics/pow_computer.pyx +671 -0
- sage/rings/padics/precision_error.py +24 -0
- sage/rings/polynomial/all__sagemath_categories.py +25 -0
- sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/commutative_polynomial.pxd +6 -0
- sage/rings/polynomial/commutative_polynomial.pyx +24 -0
- sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/cyclotomic.pyx +404 -0
- sage/rings/polynomial/flatten.py +711 -0
- sage/rings/polynomial/ideal.py +102 -0
- sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
- sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
- sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial.pxd +18 -0
- sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
- sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
- sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
- sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
- sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial.pxd +12 -0
- sage/rings/polynomial/multi_polynomial.pyx +3082 -0
- sage/rings/polynomial/multi_polynomial_element.py +2570 -0
- sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
- sage/rings/polynomial/multi_polynomial_ring.py +947 -0
- sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
- sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
- sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polydict.pxd +45 -0
- sage/rings/polynomial/polydict.pyx +2701 -0
- sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_compiled.pxd +59 -0
- sage/rings/polynomial/polynomial_compiled.pyx +509 -0
- sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_element.pxd +64 -0
- sage/rings/polynomial/polynomial_element.pyx +13255 -0
- sage/rings/polynomial/polynomial_element_generic.py +1637 -0
- sage/rings/polynomial/polynomial_fateman.py +97 -0
- sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
- sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
- sage/rings/polynomial/polynomial_ring.py +3784 -0
- sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
- sage/rings/polynomial/polynomial_singular_interface.py +549 -0
- sage/rings/polynomial/symmetric_ideal.py +989 -0
- sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/symmetric_reduction.pxd +8 -0
- sage/rings/polynomial/symmetric_reduction.pyx +669 -0
- sage/rings/polynomial/term_order.py +2279 -0
- sage/rings/polynomial/toy_buchberger.py +449 -0
- sage/rings/polynomial/toy_d_basis.py +387 -0
- sage/rings/polynomial/toy_variety.py +362 -0
- sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_mpoly.pxd +9 -0
- sage/rings/power_series_mpoly.pyx +161 -0
- sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_poly.pxd +10 -0
- sage/rings/power_series_poly.pyx +1317 -0
- sage/rings/power_series_ring.py +1441 -0
- sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_ring_element.pxd +12 -0
- sage/rings/power_series_ring_element.pyx +3028 -0
- sage/rings/puiseux_series_ring.py +487 -0
- sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/puiseux_series_ring_element.pxd +7 -0
- sage/rings/puiseux_series_ring_element.pyx +1055 -0
- sage/rings/qqbar_decorators.py +167 -0
- sage/rings/quotient_ring.py +1598 -0
- sage/rings/quotient_ring_element.py +979 -0
- sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/rational.pxd +20 -0
- sage/rings/rational.pyx +4284 -0
- sage/rings/rational_field.py +1730 -0
- sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_double.pxd +16 -0
- sage/rings/real_double.pyx +2218 -0
- sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_lazy.pxd +30 -0
- sage/rings/real_lazy.pyx +1773 -0
- sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/ring.pxd +30 -0
- sage/rings/ring.pyx +850 -0
- sage/rings/semirings/all.py +3 -0
- sage/rings/semirings/non_negative_integer_semiring.py +107 -0
- sage/rings/semirings/tropical_mpolynomial.py +972 -0
- sage/rings/semirings/tropical_polynomial.py +997 -0
- sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/semirings/tropical_semiring.pyx +676 -0
- sage/rings/semirings/tropical_variety.py +1701 -0
- sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/sum_of_squares.pxd +3 -0
- sage/rings/sum_of_squares.pyx +336 -0
- sage/rings/tests.py +504 -0
- sage/schemes/affine/affine_homset.py +508 -0
- sage/schemes/affine/affine_morphism.py +1574 -0
- sage/schemes/affine/affine_point.py +460 -0
- sage/schemes/affine/affine_rational_point.py +308 -0
- sage/schemes/affine/affine_space.py +1264 -0
- sage/schemes/affine/affine_subscheme.py +592 -0
- sage/schemes/affine/all.py +25 -0
- sage/schemes/all__sagemath_categories.py +5 -0
- sage/schemes/generic/algebraic_scheme.py +2092 -0
- sage/schemes/generic/all.py +5 -0
- sage/schemes/generic/ambient_space.py +400 -0
- sage/schemes/generic/divisor.py +465 -0
- sage/schemes/generic/divisor_group.py +313 -0
- sage/schemes/generic/glue.py +84 -0
- sage/schemes/generic/homset.py +820 -0
- sage/schemes/generic/hypersurface.py +234 -0
- sage/schemes/generic/morphism.py +2107 -0
- sage/schemes/generic/point.py +237 -0
- sage/schemes/generic/scheme.py +1190 -0
- sage/schemes/generic/spec.py +199 -0
- sage/schemes/product_projective/all.py +6 -0
- sage/schemes/product_projective/homset.py +236 -0
- sage/schemes/product_projective/morphism.py +517 -0
- sage/schemes/product_projective/point.py +568 -0
- sage/schemes/product_projective/rational_point.py +550 -0
- sage/schemes/product_projective/space.py +1301 -0
- sage/schemes/product_projective/subscheme.py +466 -0
- sage/schemes/projective/all.py +24 -0
- sage/schemes/projective/proj_bdd_height.py +453 -0
- sage/schemes/projective/projective_homset.py +718 -0
- sage/schemes/projective/projective_morphism.py +2792 -0
- sage/schemes/projective/projective_point.py +1484 -0
- sage/schemes/projective/projective_rational_point.py +569 -0
- sage/schemes/projective/projective_space.py +2571 -0
- sage/schemes/projective/projective_subscheme.py +1574 -0
- sage/sets/all.py +17 -0
- sage/sets/cartesian_product.py +376 -0
- sage/sets/condition_set.py +525 -0
- sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/disjoint_set.pxd +36 -0
- sage/sets/disjoint_set.pyx +998 -0
- sage/sets/disjoint_union_enumerated_sets.py +625 -0
- sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/family.pxd +12 -0
- sage/sets/family.pyx +1556 -0
- sage/sets/finite_enumerated_set.py +406 -0
- sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/finite_set_map_cy.pxd +34 -0
- sage/sets/finite_set_map_cy.pyx +708 -0
- sage/sets/finite_set_maps.py +591 -0
- sage/sets/image_set.py +448 -0
- sage/sets/integer_range.py +829 -0
- sage/sets/non_negative_integers.py +241 -0
- sage/sets/positive_integers.py +93 -0
- sage/sets/primes.py +188 -0
- sage/sets/real_set.py +2760 -0
- sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/recursively_enumerated_set.pxd +31 -0
- sage/sets/recursively_enumerated_set.pyx +2082 -0
- sage/sets/set.py +2083 -0
- sage/sets/set_from_iterator.py +1021 -0
- sage/sets/totally_ordered_finite_set.py +329 -0
- sage/symbolic/all__sagemath_categories.py +1 -0
- sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/function.pxd +29 -0
- sage/symbolic/function.pyx +1488 -0
- sage/symbolic/symbols.py +56 -0
- sage/tests/all__sagemath_categories.py +1 -0
- sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/cython.pyx +37 -0
- sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/stl_vector.pyx +171 -0
- sage/typeset/all.py +6 -0
- sage/typeset/ascii_art.py +295 -0
- sage/typeset/character_art.py +789 -0
- sage/typeset/character_art_factory.py +572 -0
- sage/typeset/symbols.py +334 -0
- sage/typeset/unicode_art.py +183 -0
- sage/typeset/unicode_characters.py +101 -0
|
@@ -0,0 +1,1488 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Classes for symbolic functions
|
|
4
|
+
|
|
5
|
+
.. _symbolic-function-classes:
|
|
6
|
+
|
|
7
|
+
To enable their usage as part of symbolic expressions, symbolic function
|
|
8
|
+
classes are derived from one of the subclasses of :class:`Function`:
|
|
9
|
+
|
|
10
|
+
* :class:`BuiltinFunction`: the code of these functions is written in Python;
|
|
11
|
+
many :ref:`special functions<special-functions>` are of this type
|
|
12
|
+
* :class:`GinacFunction`: the code of these functions is written in C++ and
|
|
13
|
+
part of the Pynac support library; most elementary functions are of this type
|
|
14
|
+
* :class:`SymbolicFunction`: symbolic functions defined on the Sage command
|
|
15
|
+
line are of this type
|
|
16
|
+
|
|
17
|
+
Sage uses ``BuiltinFunction`` and ``GinacFunction`` for its symbolic builtin
|
|
18
|
+
functions. Users can define any other additional ``SymbolicFunction`` through
|
|
19
|
+
the ``function()`` factory, see :doc:`function_factory`
|
|
20
|
+
|
|
21
|
+
Several parameters are supported by the superclass' ``__init__()`` method.
|
|
22
|
+
Examples follow below.
|
|
23
|
+
|
|
24
|
+
* ``nargs``: the number of arguments
|
|
25
|
+
* ``name``: the string that is printed on the CLI; the name of the member
|
|
26
|
+
functions that are attempted for evaluation of Sage element arguments; also
|
|
27
|
+
the name of the Pynac function that is associated with a ``GinacFunction``
|
|
28
|
+
* ``alt_name``: the second name of the member functions that are attempted for
|
|
29
|
+
evaluation of Sage element arguments
|
|
30
|
+
* ``latex_name``: what is printed when ``latex(f(...))`` is called
|
|
31
|
+
* ``conversions``: a dict containing the function's name in other CAS
|
|
32
|
+
* ``evalf_params_first``: if ``False``, when floating-point evaluating the
|
|
33
|
+
expression do not evaluate function arguments before calling the
|
|
34
|
+
``_evalf_()`` member of the function
|
|
35
|
+
* ``preserved_arg``: if nonzero, the index (starting with ``1``) of the
|
|
36
|
+
function argument that determines the return type. Note that, e.g,
|
|
37
|
+
``atan2()`` uses both arguments to determine return type, through a
|
|
38
|
+
different mechanism
|
|
39
|
+
|
|
40
|
+
Function classes can define the following Python member functions:
|
|
41
|
+
|
|
42
|
+
* ``_eval_(*args)``: the only mandatory member function, evaluating the
|
|
43
|
+
argument and returning the result; if ``None`` is returned the expression
|
|
44
|
+
stays unevaluated
|
|
45
|
+
* ``_eval_numpy_(*args)``: evaluation of ``f(args)`` with arguments of numpy
|
|
46
|
+
type
|
|
47
|
+
* ``_evalf_(*args, **kwds)``: called when the expression is floating-point
|
|
48
|
+
evaluated; may receive a ``parent`` keyword specifying the expected parent
|
|
49
|
+
of the result. If not defined an attempt is made to convert the result of
|
|
50
|
+
``_eval_()``.
|
|
51
|
+
* ``_conjugate_(*args)``, ``_real_part_(*args)``, ``_imag_part_(*args)``:
|
|
52
|
+
return conjugate, real part, imaginary part of the expression ``f(args)``
|
|
53
|
+
* ``_derivative_(*args, index)``: return derivative with respect to the
|
|
54
|
+
parameter indexed by ``index`` (starting with 0) of ``f(args)``
|
|
55
|
+
* ``_tderivative_()``: same as ``_derivative_()`` but don't apply chain rule;
|
|
56
|
+
only one of the two functions may be defined
|
|
57
|
+
* ``_power_(*args, expo)``: return ``f(args)^expo``
|
|
58
|
+
* ``_series_(*args, **kwds)``: return the power series at ``at`` up to
|
|
59
|
+
``order`` with respect to ``var`` of ``f(args)``; these three values are
|
|
60
|
+
received in ``kwds``. If not defined the series is attempted to be computed
|
|
61
|
+
by differentiation.
|
|
62
|
+
* ``print(*args)``: return what should be printed on the CLI with ``f(args)``
|
|
63
|
+
* ``print_latex(*args)``: return what should be output with ``latex(f(args))``
|
|
64
|
+
|
|
65
|
+
The following examples are intended for Sage developers. Users can define
|
|
66
|
+
functions interactively through the ``function()`` factory, see
|
|
67
|
+
:doc:`function_factory`.
|
|
68
|
+
|
|
69
|
+
EXAMPLES:
|
|
70
|
+
|
|
71
|
+
The simplest example is a function returning nothing, it practically behaves
|
|
72
|
+
like a symbol. Setting ``nargs=0`` allows any number of arguments::
|
|
73
|
+
|
|
74
|
+
sage: from sage.symbolic.function import BuiltinFunction
|
|
75
|
+
sage: class Test1(BuiltinFunction):
|
|
76
|
+
....: def __init__(self):
|
|
77
|
+
....: BuiltinFunction.__init__(self, 'test', nargs=0)
|
|
78
|
+
....: def _eval_(self, *args):
|
|
79
|
+
....: pass
|
|
80
|
+
sage: f = Test1()
|
|
81
|
+
sage: f() # needs sage.symbolic
|
|
82
|
+
test()
|
|
83
|
+
sage: f(1,2,3)*f(1,2,3) # needs sage.symbolic
|
|
84
|
+
test(1, 2, 3)^2
|
|
85
|
+
|
|
86
|
+
In the following the ``sin`` function of ``CBF(0)`` is called because with
|
|
87
|
+
floating point arguments the ``CBF`` element's ``my_sin()`` member function
|
|
88
|
+
is attempted, and after that ``sin()`` which succeeds::
|
|
89
|
+
|
|
90
|
+
sage: class Test2(BuiltinFunction):
|
|
91
|
+
....: def __init__(self):
|
|
92
|
+
....: BuiltinFunction.__init__(self, 'my_sin', alt_name='sin',
|
|
93
|
+
....: latex_name=r'\SIN', nargs=1)
|
|
94
|
+
....: def _eval_(self, x):
|
|
95
|
+
....: return 5
|
|
96
|
+
....: def _evalf_(self, x, **kwds):
|
|
97
|
+
....: return 3.5
|
|
98
|
+
sage: f = Test2()
|
|
99
|
+
sage: f(0)
|
|
100
|
+
5
|
|
101
|
+
sage: f(0, hold=True) # needs sage.symbolic
|
|
102
|
+
my_sin(0)
|
|
103
|
+
sage: f(0, hold=True).n() # needs sage.rings.real_mpfr
|
|
104
|
+
3.50000000000000
|
|
105
|
+
sage: f(CBF(0)) # needs sage.libs.flint
|
|
106
|
+
0
|
|
107
|
+
|
|
108
|
+
sage: latex(f(0, hold=True)) # needs sage.symbolic
|
|
109
|
+
\SIN\left(0\right)
|
|
110
|
+
sage: f(1,2)
|
|
111
|
+
Traceback (most recent call last):
|
|
112
|
+
...
|
|
113
|
+
TypeError: Symbolic function my_sin takes exactly 1 arguments (2 given)
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
# ****************************************************************************
|
|
117
|
+
# Copyright (C) 2008 William Stein <wstein@gmail.com>
|
|
118
|
+
# Copyright (C) 2008-2012 Burcin Erocal <burcin@erocal.org>
|
|
119
|
+
# Copyright (C) 2009 Mike Hansen
|
|
120
|
+
# Copyright (C) 2010 Wilfried Huss
|
|
121
|
+
# Copyright (C) 2012 Michael Orlitzky
|
|
122
|
+
# Copyright (C) 2013 Eviatar Bach
|
|
123
|
+
# Copyright (C) 2013 Robert Bradshaw
|
|
124
|
+
# Copyright (C) 2014 Jeroen Demeyer
|
|
125
|
+
# Copyright (C) 2014 Martin von Gagern
|
|
126
|
+
# Copyright (C) 2015-2020 Frédéric Chapoton
|
|
127
|
+
# Copyright (C) 2016 Vincent Delecroix <vincent.delecroix@u-bordeaux.fr>
|
|
128
|
+
# Copyright (C) 2016-2018 Ralf Stephan
|
|
129
|
+
# Copyright (C) 2018 Erik M. Bray
|
|
130
|
+
# Copyright (C) 2019 Eric Gourgoulhon
|
|
131
|
+
# Copyright (C) 2019 Marc Mezzarobba
|
|
132
|
+
# Copyright (C) 2021 Matthias Koeppe
|
|
133
|
+
#
|
|
134
|
+
# This program is free software: you can redistribute it and/or modify
|
|
135
|
+
# it under the terms of the GNU General Public License as published by
|
|
136
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
137
|
+
# (at your option) any later version.
|
|
138
|
+
# https://www.gnu.org/licenses/
|
|
139
|
+
# ****************************************************************************
|
|
140
|
+
|
|
141
|
+
from sage.structure.sage_object cimport SageObject
|
|
142
|
+
from sage.structure.element cimport Element, parent, Expression
|
|
143
|
+
from sage.misc.lazy_attribute import lazy_attribute
|
|
144
|
+
|
|
145
|
+
from sage.structure.parent cimport Parent
|
|
146
|
+
from sage.structure.coerce cimport (coercion_model,
|
|
147
|
+
py_scalar_to_element, is_numpy_type, is_mpmath_type)
|
|
148
|
+
from sage.structure.richcmp cimport richcmp
|
|
149
|
+
|
|
150
|
+
from sage.misc.fpickle import pickle_function, unpickle_function
|
|
151
|
+
|
|
152
|
+
from sage.symbolic.symbols import symbol_table, register_symbol
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
from sage.symbolic.expression import (
|
|
156
|
+
call_registered_function, find_registered_function, register_or_update_function,
|
|
157
|
+
get_sfunction_from_hash, get_sfunction_from_serial as get_sfunction_from_serial
|
|
158
|
+
)
|
|
159
|
+
except ImportError:
|
|
160
|
+
call_registered_function = None
|
|
161
|
+
register_or_update_function = None
|
|
162
|
+
|
|
163
|
+
cdef object SR = None, PolynomialRing_commutative = None, MPolynomialRing_polydict_domain = None
|
|
164
|
+
|
|
165
|
+
# List of functions which ginac allows us to define custom behavior for.
|
|
166
|
+
# Changing the order of this list could cause problems unpickling old pickles.
|
|
167
|
+
sfunctions_funcs = ['eval', 'evalf', 'conjugate', 'real_part', 'imag_part',
|
|
168
|
+
'derivative', 'power', 'series', 'print', 'print_latex', 'tderivative']
|
|
169
|
+
|
|
170
|
+
cdef class Function(SageObject):
|
|
171
|
+
"""
|
|
172
|
+
Base class for symbolic functions defined through Pynac in Sage.
|
|
173
|
+
|
|
174
|
+
This is an abstract base class, with generic code for the interfaces
|
|
175
|
+
and a :meth:`__call__` method. Subclasses should implement the
|
|
176
|
+
:meth:`_is_registered` and :meth:`_register_function` methods.
|
|
177
|
+
|
|
178
|
+
This class is not intended for direct use, instead use one of the
|
|
179
|
+
subclasses :class:`BuiltinFunction` or :class:`SymbolicFunction`.
|
|
180
|
+
"""
|
|
181
|
+
def __init__(self, name, nargs, latex_name=None, conversions=None,
|
|
182
|
+
evalf_params_first=True, alt_name=None):
|
|
183
|
+
"""
|
|
184
|
+
This is an abstract base class. It's not possible to test it directly.
|
|
185
|
+
|
|
186
|
+
EXAMPLES::
|
|
187
|
+
|
|
188
|
+
sage: f = function('f', nargs=1, # indirect doctest # needs sage.symbolic
|
|
189
|
+
....: conjugate_func=lambda self, x: 2r*x)
|
|
190
|
+
sage: f(2) # needs sage.symbolic
|
|
191
|
+
f(2)
|
|
192
|
+
sage: f(2).conjugate() # needs sage.symbolic
|
|
193
|
+
4
|
|
194
|
+
|
|
195
|
+
TESTS::
|
|
196
|
+
|
|
197
|
+
# eval_func raises exception
|
|
198
|
+
sage: def ef(self, x): raise RuntimeError("foo")
|
|
199
|
+
sage: bar = function("bar", nargs=1, eval_func=ef) # needs sage.symbolic
|
|
200
|
+
sage: bar(x) # needs sage.symbolic
|
|
201
|
+
Traceback (most recent call last):
|
|
202
|
+
...
|
|
203
|
+
RuntimeError: foo
|
|
204
|
+
|
|
205
|
+
# eval_func returns non coercible
|
|
206
|
+
sage: def ef(self, x): return ZZ
|
|
207
|
+
sage: bar = function("bar", nargs=1, eval_func=ef) # needs sage.symbolic
|
|
208
|
+
sage: bar(x) # needs sage.symbolic
|
|
209
|
+
Traceback (most recent call last):
|
|
210
|
+
...
|
|
211
|
+
TypeError: function did not return a symbolic expression
|
|
212
|
+
or an element that can be coerced into a symbolic expression
|
|
213
|
+
|
|
214
|
+
# eval_func is not callable
|
|
215
|
+
sage: bar = function("bar", nargs=1, eval_func=5) # needs sage.symbolic
|
|
216
|
+
Traceback (most recent call last):
|
|
217
|
+
...
|
|
218
|
+
ValueError: eval_func parameter must be callable
|
|
219
|
+
"""
|
|
220
|
+
self._name = name
|
|
221
|
+
self._alt_name = alt_name
|
|
222
|
+
self._nargs = nargs
|
|
223
|
+
self._latex_name = latex_name
|
|
224
|
+
self._evalf_params_first = evalf_params_first
|
|
225
|
+
self._conversions = {} if conversions is None else conversions
|
|
226
|
+
|
|
227
|
+
# handle custom printing
|
|
228
|
+
# if print_func is defined, it is used instead of name
|
|
229
|
+
# latex printing can be customised either by setting a string latex_name
|
|
230
|
+
# or giving a custom function argument print_latex_func
|
|
231
|
+
if latex_name and hasattr(self, '_print_latex_'):
|
|
232
|
+
raise ValueError("only one of latex_name or _print_latex_ should be specified.")
|
|
233
|
+
|
|
234
|
+
# only one of derivative and tderivative should be defined
|
|
235
|
+
if hasattr(self, '_derivative_') and hasattr(self, '_tderivative_'):
|
|
236
|
+
raise ValueError("only one of _derivative_ or _tderivative_ should be defined.")
|
|
237
|
+
|
|
238
|
+
for fname in sfunctions_funcs:
|
|
239
|
+
real_fname = '_%s_' % fname
|
|
240
|
+
if hasattr(self, real_fname) and not \
|
|
241
|
+
callable(getattr(self, real_fname)):
|
|
242
|
+
raise ValueError(real_fname + " parameter must be callable")
|
|
243
|
+
|
|
244
|
+
symbol_table['functions'][self._name] = self
|
|
245
|
+
|
|
246
|
+
if register_or_update_function: # Symbolic subsystem present
|
|
247
|
+
if not self._is_registered():
|
|
248
|
+
self._register_function()
|
|
249
|
+
register_symbol(self, self._conversions)
|
|
250
|
+
|
|
251
|
+
cdef _is_registered(self):
|
|
252
|
+
"""
|
|
253
|
+
Check if this function is already registered. If it is, set
|
|
254
|
+
`self._serial` to the right value.
|
|
255
|
+
"""
|
|
256
|
+
raise NotImplementedError("this is an abstract base class, it shouldn't be initialized directly")
|
|
257
|
+
|
|
258
|
+
cdef _register_function(self):
|
|
259
|
+
"""
|
|
260
|
+
|
|
261
|
+
TESTS:
|
|
262
|
+
|
|
263
|
+
After :issue:`9240`, pickling and unpickling of symbolic
|
|
264
|
+
functions was broken. We check here that this is fixed
|
|
265
|
+
(:issue:`11919`)::
|
|
266
|
+
|
|
267
|
+
sage: # needs sage.symbolic
|
|
268
|
+
sage: f = function('f')(x)
|
|
269
|
+
sage: s = dumps(f)
|
|
270
|
+
sage: loads(s)
|
|
271
|
+
f(x)
|
|
272
|
+
sage: deepcopy(f)
|
|
273
|
+
f(x)
|
|
274
|
+
"""
|
|
275
|
+
self._serial = register_or_update_function(self, self._name, self._latex_name,
|
|
276
|
+
self._nargs, self._evalf_params_first,
|
|
277
|
+
False)
|
|
278
|
+
|
|
279
|
+
def _evalf_try_(self, *args):
|
|
280
|
+
"""
|
|
281
|
+
Call :meth:`_evalf_` if one the arguments is numerical and none
|
|
282
|
+
of the arguments are symbolic.
|
|
283
|
+
|
|
284
|
+
OUTPUT:
|
|
285
|
+
|
|
286
|
+
- ``None`` if we didn't succeed to call :meth:`_evalf_` or if
|
|
287
|
+
the input wasn't suitable for it.
|
|
288
|
+
|
|
289
|
+
- otherwise, a numerical value for the function.
|
|
290
|
+
|
|
291
|
+
TESTS::
|
|
292
|
+
|
|
293
|
+
sage: coth(5) # indirect doctest # needs sage.symbolic
|
|
294
|
+
coth(5)
|
|
295
|
+
sage: coth(0.5) # needs sage.rings.real_mpfr
|
|
296
|
+
2.16395341373865
|
|
297
|
+
sage: from sage.symbolic.function import BuiltinFunction
|
|
298
|
+
sage: class Test(BuiltinFunction):
|
|
299
|
+
....: def __init__(self):
|
|
300
|
+
....: BuiltinFunction.__init__(self, 'test', nargs=2)
|
|
301
|
+
....: def _evalf_(self, x, y, parent):
|
|
302
|
+
....: return x + 1
|
|
303
|
+
....: def _eval_(self, x, y):
|
|
304
|
+
....: res = self._evalf_try_(x, y)
|
|
305
|
+
....: if res:
|
|
306
|
+
....: return res
|
|
307
|
+
....: elif x == 2:
|
|
308
|
+
....: return 3
|
|
309
|
+
....: else:
|
|
310
|
+
....: return
|
|
311
|
+
sage: test = Test()
|
|
312
|
+
sage: test(1.3, 4) # needs sage.rings.real_mpfr
|
|
313
|
+
2.30000000000000
|
|
314
|
+
sage: test(pi, 4) # needs sage.symbolic
|
|
315
|
+
test(pi, 4)
|
|
316
|
+
sage: test(2, x) # needs sage.symbolic
|
|
317
|
+
3
|
|
318
|
+
sage: test(2., 4) # needs sage.rings.real_mpfr
|
|
319
|
+
3.00000000000000
|
|
320
|
+
sage: test(1 + 1.0*I, 2) # needs sage.symbolic
|
|
321
|
+
2.00000000000000 + 1.00000000000000*I
|
|
322
|
+
sage: class Test2(BuiltinFunction):
|
|
323
|
+
....: def __init__(self):
|
|
324
|
+
....: BuiltinFunction.__init__(self, 'test', nargs=1)
|
|
325
|
+
....: def _evalf_(self, x, parent):
|
|
326
|
+
....: return 0.5
|
|
327
|
+
....: def _eval_(self, x):
|
|
328
|
+
....: res = self._evalf_try_(x)
|
|
329
|
+
....: if res:
|
|
330
|
+
....: return res
|
|
331
|
+
....: else:
|
|
332
|
+
....: return 3
|
|
333
|
+
sage: test2 = Test2()
|
|
334
|
+
sage: test2(1.3) # needs sage.rings.real_mpfr
|
|
335
|
+
0.500000000000000
|
|
336
|
+
sage: test2(pi) # needs sage.symbolic
|
|
337
|
+
3
|
|
338
|
+
"""
|
|
339
|
+
# If any of the inputs is numerical and none is symbolic,
|
|
340
|
+
# try to call _evalf_() directly
|
|
341
|
+
try:
|
|
342
|
+
evalf = self._evalf_ # catch AttributeError early
|
|
343
|
+
if any(self._is_numerical(x) for x in args):
|
|
344
|
+
if not any(isinstance(x, Expression) for x in args):
|
|
345
|
+
p = coercion_model.common_parent(*args)
|
|
346
|
+
return evalf(*args, parent=p)
|
|
347
|
+
except Exception:
|
|
348
|
+
pass
|
|
349
|
+
|
|
350
|
+
def __hash__(self):
|
|
351
|
+
"""
|
|
352
|
+
EXAMPLES::
|
|
353
|
+
|
|
354
|
+
sage: f = function('f', nargs=1, conjugate_func=lambda self, x: 2r*x) # needs sage.symbolic
|
|
355
|
+
sage: f.__hash__() # random # needs sage.symbolic
|
|
356
|
+
-2224334885124003860
|
|
357
|
+
sage: hash(f(2)) # random # needs sage.symbolic
|
|
358
|
+
4168614485
|
|
359
|
+
"""
|
|
360
|
+
return hash(self._name)*(self._nargs+1)*self._serial
|
|
361
|
+
|
|
362
|
+
def __repr__(self):
|
|
363
|
+
"""
|
|
364
|
+
EXAMPLES::
|
|
365
|
+
|
|
366
|
+
sage: foo = function("foo", nargs=2); foo # needs sage.symbolic
|
|
367
|
+
foo
|
|
368
|
+
"""
|
|
369
|
+
return self._name
|
|
370
|
+
|
|
371
|
+
def _latex_(self):
|
|
372
|
+
r"""
|
|
373
|
+
EXAMPLES::
|
|
374
|
+
|
|
375
|
+
sage: from sage.symbolic.function import SymbolicFunction
|
|
376
|
+
sage: s = SymbolicFunction('foo'); s
|
|
377
|
+
foo
|
|
378
|
+
sage: latex(s)
|
|
379
|
+
foo
|
|
380
|
+
sage: s = SymbolicFunction('foo', latex_name=r'{\rm foo}')
|
|
381
|
+
sage: latex(s)
|
|
382
|
+
{\rm foo}
|
|
383
|
+
sage: s._latex_()
|
|
384
|
+
'{\\rm foo}'
|
|
385
|
+
"""
|
|
386
|
+
if self._latex_name is not None:
|
|
387
|
+
return self._latex_name
|
|
388
|
+
else:
|
|
389
|
+
return self._name
|
|
390
|
+
|
|
391
|
+
def __richcmp__(self, other, op):
|
|
392
|
+
"""
|
|
393
|
+
TESTS::
|
|
394
|
+
|
|
395
|
+
sage: # needs sage.symbolic
|
|
396
|
+
sage: foo = function("foo", nargs=2)
|
|
397
|
+
sage: foo == foo
|
|
398
|
+
True
|
|
399
|
+
sage: foo == 2
|
|
400
|
+
False
|
|
401
|
+
sage: foo(1, 2).operator() == foo
|
|
402
|
+
True
|
|
403
|
+
"""
|
|
404
|
+
try:
|
|
405
|
+
return richcmp((<Function>self)._serial,
|
|
406
|
+
(<Function>other)._serial, op)
|
|
407
|
+
except AttributeError:
|
|
408
|
+
return NotImplemented
|
|
409
|
+
|
|
410
|
+
def __call__(self, *args, bint coerce=True, bint hold=False, dont_call_method_on_arg=None):
|
|
411
|
+
"""
|
|
412
|
+
Evaluates this function at the given arguments.
|
|
413
|
+
|
|
414
|
+
We coerce the arguments into symbolic expressions if ``coerce=True``, then
|
|
415
|
+
call the Pynac evaluation method, which in turn passes the arguments to
|
|
416
|
+
a custom automatic evaluation method if ``_eval_()`` is defined.
|
|
417
|
+
|
|
418
|
+
EXAMPLES::
|
|
419
|
+
|
|
420
|
+
sage: # needs sage.symbolic
|
|
421
|
+
sage: foo = function("foo", nargs=2)
|
|
422
|
+
sage: x,y,z = var("x y z")
|
|
423
|
+
sage: foo(x, y)
|
|
424
|
+
foo(x, y)
|
|
425
|
+
sage: foo(y)
|
|
426
|
+
Traceback (most recent call last):
|
|
427
|
+
...
|
|
428
|
+
TypeError: Symbolic function foo takes exactly 2 arguments (1 given)
|
|
429
|
+
sage: bar = function("bar")
|
|
430
|
+
sage: bar(x)
|
|
431
|
+
bar(x)
|
|
432
|
+
sage: bar(x, y)
|
|
433
|
+
bar(x, y)
|
|
434
|
+
|
|
435
|
+
The `hold` argument prevents automatic evaluation of the function::
|
|
436
|
+
|
|
437
|
+
sage: exp(log(x)) # needs sage.symbolic
|
|
438
|
+
x
|
|
439
|
+
sage: exp(log(x), hold=True) # needs sage.symbolic
|
|
440
|
+
e^log(x)
|
|
441
|
+
|
|
442
|
+
We can also handle numpy types::
|
|
443
|
+
|
|
444
|
+
sage: import numpy # needs numpy
|
|
445
|
+
sage: sin(numpy.arange(5)) # needs numpy
|
|
446
|
+
array([ 0. , 0.84147098, 0.90929743, 0.14112001, -0.7568025 ])
|
|
447
|
+
|
|
448
|
+
Symbolic functions evaluate non-exact input numerically, and return
|
|
449
|
+
symbolic expressions on exact input, or if any input is symbolic::
|
|
450
|
+
|
|
451
|
+
sage: arctan(1) # needs sage.symbolic
|
|
452
|
+
1/4*pi
|
|
453
|
+
sage: arctan(float(1)) # needs sage.rings.complex_double
|
|
454
|
+
0.7853981633974483
|
|
455
|
+
sage: type(lambert_w(SR(0))) # needs sage.symbolic
|
|
456
|
+
<class 'sage.symbolic.expression.Expression'>
|
|
457
|
+
|
|
458
|
+
Precision of the result depends on the precision of the input::
|
|
459
|
+
|
|
460
|
+
sage: arctan(RR(1)) # needs sage.rings.real_mpfr
|
|
461
|
+
0.785398163397448
|
|
462
|
+
sage: arctan(RealField(100)(1)) # needs sage.rings.real_mpfr
|
|
463
|
+
0.78539816339744830961566084582
|
|
464
|
+
|
|
465
|
+
Return types for non-exact input depends on the input type::
|
|
466
|
+
|
|
467
|
+
sage: type(exp(float(0)))
|
|
468
|
+
<... 'float'>
|
|
469
|
+
sage: exp(RR(0)).parent()
|
|
470
|
+
Real Field with 53 bits of precision
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
TESTS:
|
|
474
|
+
|
|
475
|
+
Test coercion::
|
|
476
|
+
|
|
477
|
+
sage: bar(ZZ) # needs sage.symbolic
|
|
478
|
+
Traceback (most recent call last):
|
|
479
|
+
...
|
|
480
|
+
TypeError: cannot coerce arguments: ...
|
|
481
|
+
sage: exp(QQbar(I)) # needs sage.rings.number_field sage.symbolic
|
|
482
|
+
e^I
|
|
483
|
+
|
|
484
|
+
For functions with single argument, if coercion fails we try to call
|
|
485
|
+
a method with the name of the function on the object::
|
|
486
|
+
|
|
487
|
+
sage: M = matrix(SR, 2, 2, [x, 0, 0, I*pi]) # needs sage.modules sage.symbolic
|
|
488
|
+
sage: exp(M) # needs sage.modules sage.symbolic
|
|
489
|
+
[e^x 0]
|
|
490
|
+
[ 0 -1]
|
|
491
|
+
|
|
492
|
+
Make sure we can pass mpmath arguments (:issue:`13608`)::
|
|
493
|
+
|
|
494
|
+
sage: import mpmath # needs mpmath
|
|
495
|
+
sage: with mpmath.workprec(128): sin(mpmath.mpc('0.5', '1.2')) # needs mpmath
|
|
496
|
+
mpc(real='0.86807452059118713192871150787046523179886',
|
|
497
|
+
imag='1.3246769633571289324095313649562791720086')
|
|
498
|
+
|
|
499
|
+
Check that :issue:`10133` is fixed::
|
|
500
|
+
|
|
501
|
+
sage: # needs sage.symbolic
|
|
502
|
+
sage: out = sin(0)
|
|
503
|
+
sage: out, parent(out)
|
|
504
|
+
(0, Integer Ring)
|
|
505
|
+
sage: out = sin(int(0))
|
|
506
|
+
sage: (out, parent(out))
|
|
507
|
+
(0, <... 'int'>)
|
|
508
|
+
sage: out = arctan2(int(0), float(1))
|
|
509
|
+
sage: (out, parent(out))
|
|
510
|
+
(0, <... 'int'>)
|
|
511
|
+
sage: out = arctan2(int(0), RR(1))
|
|
512
|
+
sage: (out, parent(out))
|
|
513
|
+
(0, Integer Ring)
|
|
514
|
+
|
|
515
|
+
Check that ``real_part`` and ``imag_part`` still works after :issue:`21216`::
|
|
516
|
+
|
|
517
|
+
sage: # needs numpy sage.symbolic
|
|
518
|
+
sage: import numpy
|
|
519
|
+
sage: a = numpy.array([1+2*I, -2-3*I], dtype=complex)
|
|
520
|
+
sage: real_part(a)
|
|
521
|
+
array([ 1., -2.])
|
|
522
|
+
sage: imag_part(a)
|
|
523
|
+
array([ 2., -3.])
|
|
524
|
+
"""
|
|
525
|
+
if self._nargs > 0 and len(args) != self._nargs:
|
|
526
|
+
raise TypeError("Symbolic function %s takes exactly %s arguments (%s given)" % (self._name, self._nargs, len(args)))
|
|
527
|
+
|
|
528
|
+
# if the given input is a symbolic expression, we don't convert it back
|
|
529
|
+
# to a numeric type at the end
|
|
530
|
+
symbolic_input = any(isinstance(arg, Expression) for arg in args)
|
|
531
|
+
|
|
532
|
+
if call_registered_function is None:
|
|
533
|
+
try:
|
|
534
|
+
evalf = self._evalf_
|
|
535
|
+
except AttributeError:
|
|
536
|
+
if len(args) == 1 and not dont_call_method_on_arg:
|
|
537
|
+
method = getattr(args[0], self._name, None)
|
|
538
|
+
if callable(method):
|
|
539
|
+
return method()
|
|
540
|
+
else:
|
|
541
|
+
result = evalf(*args)
|
|
542
|
+
if result is not None:
|
|
543
|
+
return result
|
|
544
|
+
|
|
545
|
+
from sage.symbolic.ring import SR
|
|
546
|
+
|
|
547
|
+
if coerce:
|
|
548
|
+
try:
|
|
549
|
+
args = [SR.coerce(a) for a in args]
|
|
550
|
+
except TypeError as err:
|
|
551
|
+
# If the function takes only one argument, we try to call
|
|
552
|
+
# a method with the name of this function on the object.
|
|
553
|
+
# This makes the following work:
|
|
554
|
+
# sage: M = matrix(SR, 2, 2, [x, 0, 0, I*pi])
|
|
555
|
+
# sage: exp(M)
|
|
556
|
+
# [e^x 0]
|
|
557
|
+
# [ 0 -1]
|
|
558
|
+
if len(args) == 1:
|
|
559
|
+
method = getattr(args[0], self._name, None)
|
|
560
|
+
if callable(method):
|
|
561
|
+
return method()
|
|
562
|
+
raise TypeError("cannot coerce arguments: %s" % (err))
|
|
563
|
+
|
|
564
|
+
else: # coerce == False
|
|
565
|
+
for a in args:
|
|
566
|
+
if not isinstance(a, Expression):
|
|
567
|
+
raise TypeError("arguments must be symbolic expressions")
|
|
568
|
+
|
|
569
|
+
return call_registered_function(self._serial, self._nargs, args, hold,
|
|
570
|
+
not symbolic_input, SR)
|
|
571
|
+
|
|
572
|
+
def name(self):
|
|
573
|
+
"""
|
|
574
|
+
Return the name of this function.
|
|
575
|
+
|
|
576
|
+
EXAMPLES::
|
|
577
|
+
|
|
578
|
+
sage: foo = function("foo", nargs=2) # needs sage.symbolic
|
|
579
|
+
sage: foo.name() # needs sage.symbolic
|
|
580
|
+
'foo'
|
|
581
|
+
"""
|
|
582
|
+
return self._name
|
|
583
|
+
|
|
584
|
+
def number_of_arguments(self):
|
|
585
|
+
"""
|
|
586
|
+
Return the number of arguments that this function takes.
|
|
587
|
+
|
|
588
|
+
EXAMPLES::
|
|
589
|
+
|
|
590
|
+
sage: # needs sage.symbolic
|
|
591
|
+
sage: foo = function("foo", nargs=2)
|
|
592
|
+
sage: foo.number_of_arguments()
|
|
593
|
+
2
|
|
594
|
+
sage: foo(x, x)
|
|
595
|
+
foo(x, x)
|
|
596
|
+
sage: foo(x)
|
|
597
|
+
Traceback (most recent call last):
|
|
598
|
+
...
|
|
599
|
+
TypeError: Symbolic function foo takes exactly 2 arguments (1 given)
|
|
600
|
+
"""
|
|
601
|
+
return self._nargs
|
|
602
|
+
|
|
603
|
+
def variables(self):
|
|
604
|
+
"""
|
|
605
|
+
Return the variables (of which there are none) present in this function.
|
|
606
|
+
|
|
607
|
+
EXAMPLES::
|
|
608
|
+
|
|
609
|
+
sage: sin.variables()
|
|
610
|
+
()
|
|
611
|
+
"""
|
|
612
|
+
return ()
|
|
613
|
+
|
|
614
|
+
def default_variable(self):
|
|
615
|
+
"""
|
|
616
|
+
Return a default variable.
|
|
617
|
+
|
|
618
|
+
EXAMPLES::
|
|
619
|
+
|
|
620
|
+
sage: sin.default_variable() # needs sage.symbolic
|
|
621
|
+
x
|
|
622
|
+
"""
|
|
623
|
+
from sage.symbolic.ring import SR
|
|
624
|
+
return SR.var('x')
|
|
625
|
+
|
|
626
|
+
def _is_numerical(self, x):
|
|
627
|
+
"""
|
|
628
|
+
Return ``True`` if `x` is a numerical object.
|
|
629
|
+
|
|
630
|
+
This is used to determine whether to call the :meth:`_evalf_`
|
|
631
|
+
method instead of the :meth:`_eval_` method.
|
|
632
|
+
|
|
633
|
+
This is a non-static method since whether or not an argument is
|
|
634
|
+
considered numerical may depend on the specific function.
|
|
635
|
+
|
|
636
|
+
TESTS::
|
|
637
|
+
|
|
638
|
+
sage: [sin._is_numerical(a) for a in [5., 5.4r]]
|
|
639
|
+
[True, True]
|
|
640
|
+
sage: [sin._is_numerical(a) for a in [5, pi]] # needs sage.symbolic
|
|
641
|
+
[False, False]
|
|
642
|
+
sage: [sin._is_numerical(R(1)) for R in [RIF, CIF, RBF, CBF]] # needs sage.libs.flint
|
|
643
|
+
[False, False, False, False]
|
|
644
|
+
|
|
645
|
+
The following calls used to yield incorrect results because intervals
|
|
646
|
+
were considered numerical by this method::
|
|
647
|
+
|
|
648
|
+
sage: # needs sage.libs.flint
|
|
649
|
+
sage: b = RBF(3/2, 1e-10)
|
|
650
|
+
sage: airy_ai(b)
|
|
651
|
+
airy_ai([1.500000000 +/- 1.01e-10])
|
|
652
|
+
sage: gamma(b, 1) # abs tol 4.5e-9
|
|
653
|
+
[0.50728223 +/- 4.67e-9]
|
|
654
|
+
sage: hurwitz_zeta(b, b)
|
|
655
|
+
hurwitz_zeta([1.500000000 +/- 1.01e-10], [1.500000000 +/- 1.01e-10])
|
|
656
|
+
sage: hurwitz_zeta(1/2, b)
|
|
657
|
+
hurwitz_zeta(1/2, [1.500000000 +/- 1.01e-10])
|
|
658
|
+
|
|
659
|
+
sage: iv = RIF(1, 1.0001) # needs sage.rings.real_interval_field
|
|
660
|
+
|
|
661
|
+
sage: airy_ai(iv) # needs sage.rings.real_interval_field
|
|
662
|
+
airy_ai(1.0001?)
|
|
663
|
+
sage: airy_ai(CIF(iv)) # needs sage.rings.complex_interval_field sage.rings.real_interval_field
|
|
664
|
+
airy_ai(1.0001?)
|
|
665
|
+
"""
|
|
666
|
+
if isinstance(x, (float, complex)):
|
|
667
|
+
return True
|
|
668
|
+
if isinstance(x, Element):
|
|
669
|
+
xparent = (<Element>x)._parent
|
|
670
|
+
return hasattr(xparent, 'precision') and xparent._is_numerical()
|
|
671
|
+
return False
|
|
672
|
+
|
|
673
|
+
def _interface_init_(self, I=None):
|
|
674
|
+
"""
|
|
675
|
+
EXAMPLES::
|
|
676
|
+
|
|
677
|
+
sage: sin._interface_init_(maxima) # needs sage.symbolic
|
|
678
|
+
'sin'
|
|
679
|
+
"""
|
|
680
|
+
if I is None:
|
|
681
|
+
return self._name
|
|
682
|
+
return self._conversions.get(I.name(), self._name)
|
|
683
|
+
|
|
684
|
+
def _mathematica_init_(self):
|
|
685
|
+
"""
|
|
686
|
+
EXAMPLES::
|
|
687
|
+
|
|
688
|
+
sage: sin._mathematica_init_()
|
|
689
|
+
'Sin'
|
|
690
|
+
sage: exp._mathematica_init_()
|
|
691
|
+
'Exp'
|
|
692
|
+
sage: (exp(x) + sin(x) + tan(x))._mathematica_init_() # needs sage.symbolic
|
|
693
|
+
'(Exp[x])+(Sin[x])+(Tan[x])'
|
|
694
|
+
"""
|
|
695
|
+
s = self._conversions.get('mathematica', None)
|
|
696
|
+
return s if s is not None else repr(self).capitalize()
|
|
697
|
+
|
|
698
|
+
def _sympy_init_(self, I=None):
|
|
699
|
+
"""
|
|
700
|
+
EXAMPLES::
|
|
701
|
+
|
|
702
|
+
sage: arcsin._sympy_init_()
|
|
703
|
+
'asin'
|
|
704
|
+
sage: from sage.symbolic.function import SymbolicFunction
|
|
705
|
+
sage: g = SymbolicFunction('g', conversions=dict(sympy='gg'))
|
|
706
|
+
sage: g._sympy_init_()
|
|
707
|
+
'gg'
|
|
708
|
+
sage: g(x)._sympy_() # needs sage.symbolic
|
|
709
|
+
gg(x)
|
|
710
|
+
"""
|
|
711
|
+
return self._conversions.get('sympy', self._name)
|
|
712
|
+
|
|
713
|
+
@lazy_attribute
|
|
714
|
+
def _sympy_(self):
|
|
715
|
+
"""
|
|
716
|
+
EXAMPLES::
|
|
717
|
+
|
|
718
|
+
sage: cos._sympy_() # needs sympy
|
|
719
|
+
cos
|
|
720
|
+
sage: _(0) # needs sympy
|
|
721
|
+
1
|
|
722
|
+
"""
|
|
723
|
+
f = self._sympy_init_()
|
|
724
|
+
import sympy
|
|
725
|
+
if getattr(sympy, f, None):
|
|
726
|
+
def return_sympy():
|
|
727
|
+
return getattr(sympy, f)
|
|
728
|
+
return return_sympy
|
|
729
|
+
return NotImplemented
|
|
730
|
+
|
|
731
|
+
def _maxima_init_(self, I=None):
|
|
732
|
+
"""
|
|
733
|
+
EXAMPLES::
|
|
734
|
+
|
|
735
|
+
sage: exp._maxima_init_()
|
|
736
|
+
'exp'
|
|
737
|
+
sage: from sage.symbolic.function import SymbolicFunction
|
|
738
|
+
sage: f = SymbolicFunction('f', latex_name='f', conversions=dict(maxima='ff'))
|
|
739
|
+
sage: f._maxima_init_()
|
|
740
|
+
'ff'
|
|
741
|
+
"""
|
|
742
|
+
return self._conversions.get('maxima', self._name)
|
|
743
|
+
|
|
744
|
+
def _fast_callable_(self, etb):
|
|
745
|
+
r"""
|
|
746
|
+
Given an ExpressionTreeBuilder, return an Expression representing
|
|
747
|
+
this value.
|
|
748
|
+
|
|
749
|
+
EXAMPLES::
|
|
750
|
+
|
|
751
|
+
sage: from sage.ext.fast_callable import ExpressionTreeBuilder
|
|
752
|
+
sage: etb = ExpressionTreeBuilder(vars=['x','y'])
|
|
753
|
+
sage: sin._fast_callable_(etb)
|
|
754
|
+
sin(v_0)
|
|
755
|
+
sage: erf._fast_callable_(etb)
|
|
756
|
+
{erf}(v_0)
|
|
757
|
+
"""
|
|
758
|
+
args = [etb._var_number(n) for n in range(self.number_of_arguments())]
|
|
759
|
+
return etb.call(self, *args)
|
|
760
|
+
|
|
761
|
+
def _eval_numpy_(self, *args):
|
|
762
|
+
r"""
|
|
763
|
+
Evaluates this function at the given arguments.
|
|
764
|
+
|
|
765
|
+
At least one of elements of args is supposed to be a numpy array.
|
|
766
|
+
|
|
767
|
+
EXAMPLES::
|
|
768
|
+
|
|
769
|
+
sage: # needs numpy
|
|
770
|
+
sage: import numpy
|
|
771
|
+
sage: a = numpy.arange(5)
|
|
772
|
+
sage: csc(a)
|
|
773
|
+
doctest:...: RuntimeWarning: divide by zero encountered in ...divide
|
|
774
|
+
array([ inf, 1.18839511, 1.09975017, 7.0861674 , -1.32134871])
|
|
775
|
+
sage: factorial(a)
|
|
776
|
+
Traceback (most recent call last):
|
|
777
|
+
...
|
|
778
|
+
NotImplementedError: The Function factorial does
|
|
779
|
+
not support numpy arrays as arguments
|
|
780
|
+
"""
|
|
781
|
+
raise NotImplementedError("The Function %s does not support numpy arrays as arguments" % self.name())
|
|
782
|
+
|
|
783
|
+
def _eval_mpmath_(self, *args):
|
|
784
|
+
r"""
|
|
785
|
+
Evaluates this function for arguments of mpmath types.
|
|
786
|
+
|
|
787
|
+
This is only called when no such mpmath function exists. It casts its
|
|
788
|
+
arguments to sage reals of the appropriate precision.
|
|
789
|
+
|
|
790
|
+
EXAMPLES:
|
|
791
|
+
|
|
792
|
+
At the time of this writing, mpmath had no arcsin, only asin.
|
|
793
|
+
So the following call would actually fall back to the default
|
|
794
|
+
implementation, using sage reals instead of mpmath ones. This
|
|
795
|
+
might change when aliases for these functions are established::
|
|
796
|
+
|
|
797
|
+
sage: import mpmath # needs mpmath
|
|
798
|
+
sage: with mpmath.workprec(128): arcsin(mpmath.mpf('0.5')) # needs mpmath
|
|
799
|
+
mpf('0.52359877559829887307710723054658381403157')
|
|
800
|
+
|
|
801
|
+
TESTS:
|
|
802
|
+
|
|
803
|
+
To ensure that we actually can fall back to an implementation
|
|
804
|
+
not using mpmath, we have to create a custom function which
|
|
805
|
+
will certainly never get created in mpmath. ::
|
|
806
|
+
|
|
807
|
+
sage: # needs mpmath
|
|
808
|
+
sage: import mpmath
|
|
809
|
+
sage: from sage.symbolic.function import BuiltinFunction
|
|
810
|
+
sage: class NoMpmathFn(BuiltinFunction):
|
|
811
|
+
....: def _eval_(self, arg):
|
|
812
|
+
....: parent = arg.parent()
|
|
813
|
+
....: prec = parent.prec()
|
|
814
|
+
....: assert parent == RealField(prec)
|
|
815
|
+
....: return prec
|
|
816
|
+
sage: noMpmathFn = NoMpmathFn("noMpmathFn")
|
|
817
|
+
sage: with mpmath.workprec(64): noMpmathFn(sqrt(mpmath.mpf('2')))
|
|
818
|
+
64
|
|
819
|
+
sage: mpmath.noMpmathFn = lambda x: 123
|
|
820
|
+
sage: with mpmath.workprec(64): noMpmathFn(sqrt(mpmath.mpf('2')))
|
|
821
|
+
123
|
|
822
|
+
sage: del mpmath.noMpmathFn
|
|
823
|
+
"""
|
|
824
|
+
import mpmath
|
|
825
|
+
from sage.libs.mpmath.utils import mpmath_to_sage, sage_to_mpmath
|
|
826
|
+
prec = mpmath.mp.prec
|
|
827
|
+
args = [mpmath_to_sage(x, prec)
|
|
828
|
+
if isinstance(x, (mpmath.mpf, mpmath.mpc)) else x
|
|
829
|
+
for x in args]
|
|
830
|
+
res = self(*args)
|
|
831
|
+
res = sage_to_mpmath(res, prec)
|
|
832
|
+
return res
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
cdef class GinacFunction(BuiltinFunction):
|
|
836
|
+
"""
|
|
837
|
+
This class provides a wrapper around symbolic functions already defined in
|
|
838
|
+
Pynac/GiNaC.
|
|
839
|
+
|
|
840
|
+
GiNaC provides custom methods for these functions defined at the C++ level.
|
|
841
|
+
It is still possible to define new custom functionality or override those
|
|
842
|
+
already defined.
|
|
843
|
+
|
|
844
|
+
There is also no need to register these functions.
|
|
845
|
+
"""
|
|
846
|
+
def __init__(self, name, nargs=1, latex_name=None, conversions=None,
|
|
847
|
+
ginac_name=None, evalf_params_first=True, preserved_arg=None,
|
|
848
|
+
alt_name=None):
|
|
849
|
+
"""
|
|
850
|
+
TESTS::
|
|
851
|
+
|
|
852
|
+
sage: from sage.functions.trig import Function_sin
|
|
853
|
+
sage: s = Function_sin() # indirect doctest
|
|
854
|
+
sage: s(0) # needs sage.symbolic
|
|
855
|
+
0
|
|
856
|
+
sage: s(pi) # needs sage.symbolic
|
|
857
|
+
0
|
|
858
|
+
sage: s(pi/2) # needs sage.symbolic
|
|
859
|
+
1
|
|
860
|
+
"""
|
|
861
|
+
self._ginac_name = ginac_name
|
|
862
|
+
BuiltinFunction.__init__(self, name, nargs, latex_name, conversions,
|
|
863
|
+
evalf_params_first=evalf_params_first,
|
|
864
|
+
preserved_arg=preserved_arg, alt_name=alt_name)
|
|
865
|
+
|
|
866
|
+
cdef _is_registered(self):
|
|
867
|
+
# Since this is function is defined in C++, it is already in
|
|
868
|
+
# ginac's function registry
|
|
869
|
+
fname = self._ginac_name if self._ginac_name is not None else self._name
|
|
870
|
+
self._serial = find_registered_function(fname, self._nargs)
|
|
871
|
+
return bool(get_sfunction_from_serial(self._serial))
|
|
872
|
+
|
|
873
|
+
cdef _register_function(self):
|
|
874
|
+
# We don't need to add anything to GiNaC's function registry
|
|
875
|
+
# However, if any custom methods were provided in the python class,
|
|
876
|
+
# we should set the properties of the function_options object
|
|
877
|
+
# corresponding to this function
|
|
878
|
+
fname = self._ginac_name if self._ginac_name is not None else self._name
|
|
879
|
+
register_or_update_function(self, fname, self._latex_name,
|
|
880
|
+
self._nargs, self._evalf_params_first,
|
|
881
|
+
True)
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
cdef class BuiltinFunction(Function):
|
|
885
|
+
"""
|
|
886
|
+
This is the base class for symbolic functions defined in Sage.
|
|
887
|
+
|
|
888
|
+
If a function is provided by the Sage library, we don't need to pickle
|
|
889
|
+
the custom methods, since we can just initialize the same library function
|
|
890
|
+
again. This allows us to use Cython for custom methods.
|
|
891
|
+
|
|
892
|
+
We assume that each subclass of this class will define one symbolic
|
|
893
|
+
function. Make sure you use subclasses and not just call the initializer
|
|
894
|
+
of this class.
|
|
895
|
+
"""
|
|
896
|
+
def __init__(self, name, nargs=1, latex_name=None, conversions=None,
|
|
897
|
+
evalf_params_first=True, alt_name=None, preserved_arg=None):
|
|
898
|
+
"""
|
|
899
|
+
TESTS::
|
|
900
|
+
|
|
901
|
+
sage: from sage.functions.trig import Function_cot
|
|
902
|
+
sage: c = Function_cot() # indirect doctest
|
|
903
|
+
sage: c(pi/2) # needs sage.symbolic
|
|
904
|
+
0
|
|
905
|
+
"""
|
|
906
|
+
self._preserved_arg = 0 if preserved_arg is None else preserved_arg
|
|
907
|
+
if preserved_arg and (preserved_arg < 1 or preserved_arg > nargs):
|
|
908
|
+
raise ValueError("preserved_arg must be between 1 and nargs")
|
|
909
|
+
|
|
910
|
+
# If we have an _evalf_ method, change _eval_ to a
|
|
911
|
+
# wrapper function which first tries to call _evalf_.
|
|
912
|
+
if hasattr(self, '_evalf_'):
|
|
913
|
+
if hasattr(self, '_eval_'):
|
|
914
|
+
self._eval0_ = self._eval_
|
|
915
|
+
self._eval_ = self._evalf_or_eval_
|
|
916
|
+
else:
|
|
917
|
+
self._eval_ = self._evalf_try_
|
|
918
|
+
Function.__init__(self, name, nargs, latex_name, conversions,
|
|
919
|
+
evalf_params_first, alt_name = alt_name)
|
|
920
|
+
|
|
921
|
+
def _method_arguments(self, arg):
|
|
922
|
+
r"""
|
|
923
|
+
Rewrite the arguments before calling a specialized implementation.
|
|
924
|
+
|
|
925
|
+
Rewrite the list of arguments of this symbolic function in a form
|
|
926
|
+
suitable for calling dedicated implementations that come as methods of
|
|
927
|
+
a “main” argument.
|
|
928
|
+
|
|
929
|
+
The default implementation of this method handles the case of
|
|
930
|
+
univariate functions. Multivariate symbolic functions should override
|
|
931
|
+
it as appropriate.
|
|
932
|
+
|
|
933
|
+
Note that it is mandatory for multivariate symbolic functions to
|
|
934
|
+
override this function in order to allow delegating to the method
|
|
935
|
+
implemented on the element.
|
|
936
|
+
For example, ``binomial(n, k)`` tries to call ``n.binomial(k)``
|
|
937
|
+
because :meth:`sage.functions.other.Function_binomial._method_arguments`
|
|
938
|
+
is implemented.
|
|
939
|
+
|
|
940
|
+
EXAMPLES::
|
|
941
|
+
|
|
942
|
+
sage: zeta._method_arguments(1)
|
|
943
|
+
[1]
|
|
944
|
+
sage: zetaderiv._method_arguments(2, 3)
|
|
945
|
+
[3, 2]
|
|
946
|
+
sage: zeta._method_arguments(2, 3)
|
|
947
|
+
Traceback (most recent call last):
|
|
948
|
+
...
|
|
949
|
+
TypeError: ...
|
|
950
|
+
"""
|
|
951
|
+
return [arg]
|
|
952
|
+
|
|
953
|
+
def __call__(self, *args, bint coerce=True, bint hold=False,
|
|
954
|
+
bint dont_call_method_on_arg=False):
|
|
955
|
+
r"""
|
|
956
|
+
Evaluate this function on the given arguments and return the result.
|
|
957
|
+
|
|
958
|
+
EXAMPLES::
|
|
959
|
+
|
|
960
|
+
sage: exp(5) # needs sage.symbolic
|
|
961
|
+
e^5
|
|
962
|
+
sage: gamma(15)
|
|
963
|
+
87178291200
|
|
964
|
+
|
|
965
|
+
Python float, Python complex, mpmath mpf and mpc as well as numpy inputs
|
|
966
|
+
are sent to the relevant ``math``, ``cmath``, ``mpmath`` or ``numpy``
|
|
967
|
+
function::
|
|
968
|
+
|
|
969
|
+
sage: cos(1.r)
|
|
970
|
+
0.5403023058681398
|
|
971
|
+
sage: assert type(_) is float
|
|
972
|
+
sage: gamma(4.r)
|
|
973
|
+
6.0
|
|
974
|
+
sage: assert type(_) is float
|
|
975
|
+
|
|
976
|
+
sage: cos(1jr) # abstol 1e-15
|
|
977
|
+
(1.5430806348152437-0j)
|
|
978
|
+
sage: assert type(_) is complex
|
|
979
|
+
|
|
980
|
+
sage: # needs mpmath
|
|
981
|
+
sage: import mpmath
|
|
982
|
+
sage: cos(mpmath.mpf('1.321412'))
|
|
983
|
+
mpf('0.24680737898640387')
|
|
984
|
+
sage: cos(mpmath.mpc(1,1))
|
|
985
|
+
mpc(real='0.83373002513114902', imag='-0.98889770576286506')
|
|
986
|
+
|
|
987
|
+
sage: import numpy # needs numpy
|
|
988
|
+
sage: if int(numpy.version.short_version[0]) > 1: # needs numpy
|
|
989
|
+
....: __ = numpy.set_printoptions(legacy="1.25") # needs numpy
|
|
990
|
+
|
|
991
|
+
sage: sin(numpy.int32(0)) # needs numpy
|
|
992
|
+
0.0
|
|
993
|
+
sage: type(_) # needs numpy
|
|
994
|
+
<class 'numpy.float64'>
|
|
995
|
+
|
|
996
|
+
TESTS::
|
|
997
|
+
|
|
998
|
+
sage: from sage.symbolic.function import BuiltinFunction
|
|
999
|
+
sage: class A:
|
|
1000
|
+
....: def foo(self):
|
|
1001
|
+
....: return 'foo'
|
|
1002
|
+
sage: foo = BuiltinFunction(name='foo')
|
|
1003
|
+
sage: foo(A())
|
|
1004
|
+
'foo'
|
|
1005
|
+
sage: bar = BuiltinFunction(name='bar', alt_name='foo')
|
|
1006
|
+
sage: bar(A())
|
|
1007
|
+
'foo'
|
|
1008
|
+
"""
|
|
1009
|
+
res = None
|
|
1010
|
+
if args and not hold and not all(isinstance(arg, Element) for arg in args):
|
|
1011
|
+
# try calling the relevant math, cmath, mpmath or numpy function.
|
|
1012
|
+
# And as a fallback try the custom self._eval_numpy_ or
|
|
1013
|
+
# self._eval_mpmath_
|
|
1014
|
+
module = None
|
|
1015
|
+
custom = None
|
|
1016
|
+
if any(is_numpy_type(type(arg)) for arg in args):
|
|
1017
|
+
import numpy as module
|
|
1018
|
+
custom = self._eval_numpy_
|
|
1019
|
+
elif any(is_mpmath_type(type(arg)) for arg in args):
|
|
1020
|
+
import mpmath as module
|
|
1021
|
+
custom = self._eval_mpmath_
|
|
1022
|
+
elif all(isinstance(arg, float) for arg in args):
|
|
1023
|
+
# We do not include the factorial here as
|
|
1024
|
+
# factorial(integer-valued float) is deprecated in Python 3.9.
|
|
1025
|
+
# This special case should be removed when
|
|
1026
|
+
# Python always raise an error for factorial(float).
|
|
1027
|
+
# This case will be delegated to the gamma function.
|
|
1028
|
+
# see Github issue #30764
|
|
1029
|
+
if self._name != 'factorial':
|
|
1030
|
+
import math as module
|
|
1031
|
+
elif all(isinstance(arg, complex) for arg in args):
|
|
1032
|
+
import cmath as module
|
|
1033
|
+
|
|
1034
|
+
if module is not None:
|
|
1035
|
+
func = getattr(module, self._name, None)
|
|
1036
|
+
if func is None and self._alt_name is not None:
|
|
1037
|
+
func = getattr(module, self._alt_name, None)
|
|
1038
|
+
|
|
1039
|
+
if callable(func):
|
|
1040
|
+
try:
|
|
1041
|
+
return func(*args)
|
|
1042
|
+
except (ValueError, TypeError):
|
|
1043
|
+
pass
|
|
1044
|
+
|
|
1045
|
+
if custom is not None:
|
|
1046
|
+
return custom(*args)
|
|
1047
|
+
|
|
1048
|
+
if not hold and not dont_call_method_on_arg:
|
|
1049
|
+
try:
|
|
1050
|
+
method_args = self._method_arguments(*args)
|
|
1051
|
+
except TypeError:
|
|
1052
|
+
pass
|
|
1053
|
+
else:
|
|
1054
|
+
# then try to see whether there exists a method on the object
|
|
1055
|
+
# with the given name
|
|
1056
|
+
arg = py_scalar_to_element(method_args[0])
|
|
1057
|
+
method = getattr(arg, self._name, None)
|
|
1058
|
+
if method is None and self._alt_name is not None:
|
|
1059
|
+
method = getattr(arg, self._alt_name, None)
|
|
1060
|
+
|
|
1061
|
+
if callable(method):
|
|
1062
|
+
try:
|
|
1063
|
+
res = method(*method_args[1:])
|
|
1064
|
+
except (TypeError, ValueError, ArithmeticError):
|
|
1065
|
+
pass
|
|
1066
|
+
|
|
1067
|
+
if res is None:
|
|
1068
|
+
res = self._evalf_try_(*args)
|
|
1069
|
+
if res is None:
|
|
1070
|
+
res = super().__call__(
|
|
1071
|
+
*args, coerce=coerce, hold=hold, dont_call_method_on_arg=dont_call_method_on_arg)
|
|
1072
|
+
|
|
1073
|
+
cdef Parent arg_parent
|
|
1074
|
+
if any(isinstance(x, Element) for x in args):
|
|
1075
|
+
if (self._preserved_arg
|
|
1076
|
+
and isinstance(args[self._preserved_arg-1], Element)):
|
|
1077
|
+
arg_parent = parent(args[self._preserved_arg-1])
|
|
1078
|
+
global SR
|
|
1079
|
+
if SR is None:
|
|
1080
|
+
try:
|
|
1081
|
+
from sage.symbolic.ring import SR
|
|
1082
|
+
except ImportError:
|
|
1083
|
+
SR = None
|
|
1084
|
+
else:
|
|
1085
|
+
if arg_parent is SR:
|
|
1086
|
+
return res
|
|
1087
|
+
else:
|
|
1088
|
+
if arg_parent is SR:
|
|
1089
|
+
return res
|
|
1090
|
+
global PolynomialRing_commutative, MPolynomialRing_polydict_domain
|
|
1091
|
+
if PolynomialRing_commutative is None:
|
|
1092
|
+
from sage.rings.polynomial.polynomial_ring import PolynomialRing_commutative
|
|
1093
|
+
from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict_domain
|
|
1094
|
+
if SR is not None and isinstance(arg_parent, (PolynomialRing_commutative,
|
|
1095
|
+
MPolynomialRing_polydict_domain)):
|
|
1096
|
+
try:
|
|
1097
|
+
return SR(res).polynomial(ring=arg_parent)
|
|
1098
|
+
except TypeError:
|
|
1099
|
+
return res
|
|
1100
|
+
try:
|
|
1101
|
+
return arg_parent(res)
|
|
1102
|
+
except TypeError:
|
|
1103
|
+
return res
|
|
1104
|
+
return res
|
|
1105
|
+
if not isinstance(res, Element):
|
|
1106
|
+
return res
|
|
1107
|
+
|
|
1108
|
+
# Convert the output back to the corresponding
|
|
1109
|
+
# Python type if possible.
|
|
1110
|
+
p = res.parent()
|
|
1111
|
+
from sage.rings.integer_ring import ZZ
|
|
1112
|
+
if ZZ.has_coerce_map_from(p):
|
|
1113
|
+
return int(res)
|
|
1114
|
+
from sage.rings.real_double import RDF
|
|
1115
|
+
if RDF.has_coerce_map_from(p):
|
|
1116
|
+
return float(res)
|
|
1117
|
+
try:
|
|
1118
|
+
from sage.rings.complex_double import CDF
|
|
1119
|
+
except ImportError:
|
|
1120
|
+
pass
|
|
1121
|
+
else:
|
|
1122
|
+
if CDF.has_coerce_map_from(p):
|
|
1123
|
+
return complex(res)
|
|
1124
|
+
return res
|
|
1125
|
+
|
|
1126
|
+
cdef _is_registered(self):
|
|
1127
|
+
"""
|
|
1128
|
+
TESTS:
|
|
1129
|
+
|
|
1130
|
+
Check if :issue:`13586` is fixed::
|
|
1131
|
+
|
|
1132
|
+
sage: from sage.symbolic.function import BuiltinFunction
|
|
1133
|
+
sage: class AFunction(BuiltinFunction):
|
|
1134
|
+
....: def __init__(self, name, exp=1):
|
|
1135
|
+
....: self.exponent = exp
|
|
1136
|
+
....: BuiltinFunction.__init__(self, name, nargs=1)
|
|
1137
|
+
....: def _eval_(self, arg):
|
|
1138
|
+
....: return arg**self.exponent
|
|
1139
|
+
sage: p2 = AFunction('p2', 2)
|
|
1140
|
+
sage: p2(x) # needs sage.symbolic
|
|
1141
|
+
x^2
|
|
1142
|
+
sage: p3 = AFunction('p3', 3)
|
|
1143
|
+
sage: p3(x) # needs sage.symbolic
|
|
1144
|
+
x^3
|
|
1145
|
+
sage: loads(dumps(cot)) == cot # Issue #15138
|
|
1146
|
+
True
|
|
1147
|
+
"""
|
|
1148
|
+
# check if already defined
|
|
1149
|
+
cdef unsigned int serial
|
|
1150
|
+
|
|
1151
|
+
# search ginac registry for name and nargs
|
|
1152
|
+
try:
|
|
1153
|
+
serial = find_registered_function(self._name, self._nargs)
|
|
1154
|
+
except ValueError:
|
|
1155
|
+
return False
|
|
1156
|
+
|
|
1157
|
+
# if match, get operator from function table
|
|
1158
|
+
sfunc = get_sfunction_from_serial(serial)
|
|
1159
|
+
if sfunc.__class__ == self.__class__:
|
|
1160
|
+
# if the returned function is of the same type
|
|
1161
|
+
self._serial = serial
|
|
1162
|
+
return True
|
|
1163
|
+
|
|
1164
|
+
return False
|
|
1165
|
+
|
|
1166
|
+
def _evalf_or_eval_(self, *args):
|
|
1167
|
+
"""
|
|
1168
|
+
First try to call :meth:`_evalf_` and return the result if it
|
|
1169
|
+
was not ``None``. Otherwise, call :meth:`_eval0_`, which is the
|
|
1170
|
+
original version of :meth:`_eval_` saved in :meth:`__init__`.
|
|
1171
|
+
"""
|
|
1172
|
+
res = self._evalf_try_(*args)
|
|
1173
|
+
if res is None:
|
|
1174
|
+
return self._eval0_(*args)
|
|
1175
|
+
else:
|
|
1176
|
+
return res
|
|
1177
|
+
|
|
1178
|
+
def __reduce__(self):
|
|
1179
|
+
"""
|
|
1180
|
+
EXAMPLES::
|
|
1181
|
+
|
|
1182
|
+
sage: cot.__reduce__()
|
|
1183
|
+
(<class 'sage.functions.trig.Function_cot'>, ())
|
|
1184
|
+
|
|
1185
|
+
sage: f = loads(dumps(cot)) #indirect doctest
|
|
1186
|
+
sage: f(pi/2) # needs sage.symbolic
|
|
1187
|
+
0
|
|
1188
|
+
"""
|
|
1189
|
+
return self.__class__, tuple()
|
|
1190
|
+
|
|
1191
|
+
# this is required to read old pickles of erf, elliptic_ec, etc.
|
|
1192
|
+
def __setstate__(self, state):
|
|
1193
|
+
"""
|
|
1194
|
+
EXAMPLES::
|
|
1195
|
+
|
|
1196
|
+
sage: cot.__setstate__([1,0])
|
|
1197
|
+
Traceback (most recent call last):
|
|
1198
|
+
...
|
|
1199
|
+
ValueError: cannot read pickle
|
|
1200
|
+
sage: cot.__setstate__([0]) #don't try this at home
|
|
1201
|
+
"""
|
|
1202
|
+
if state[0] == 0:
|
|
1203
|
+
# old pickle data
|
|
1204
|
+
# we call __init__ since Python only allocates the class and does
|
|
1205
|
+
# not call __init__ before passing the pickled state to __setstate__
|
|
1206
|
+
self.__init__()
|
|
1207
|
+
else:
|
|
1208
|
+
# we should never end up here
|
|
1209
|
+
raise ValueError("cannot read pickle")
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
cdef class SymbolicFunction(Function):
|
|
1213
|
+
"""
|
|
1214
|
+
This is the basis for user defined symbolic functions. We try to pickle or
|
|
1215
|
+
hash the custom methods, so subclasses must be defined in Python not Cython.
|
|
1216
|
+
"""
|
|
1217
|
+
def __init__(self, name, nargs=0, latex_name=None, conversions=None,
|
|
1218
|
+
evalf_params_first=True):
|
|
1219
|
+
"""
|
|
1220
|
+
EXAMPLES::
|
|
1221
|
+
|
|
1222
|
+
sage: from sage.symbolic.function import SymbolicFunction
|
|
1223
|
+
sage: class my_function(SymbolicFunction):
|
|
1224
|
+
....: def __init__(self):
|
|
1225
|
+
....: SymbolicFunction.__init__(self, 'foo', nargs=2)
|
|
1226
|
+
....: def _evalf_(self, x, y, parent=None, algorithm=None):
|
|
1227
|
+
....: return x*y*2r
|
|
1228
|
+
....: def _conjugate_(self, x, y):
|
|
1229
|
+
....: return x
|
|
1230
|
+
sage: foo = my_function()
|
|
1231
|
+
sage: foo
|
|
1232
|
+
foo
|
|
1233
|
+
sage: foo(2, 3) # needs sage.symbolic
|
|
1234
|
+
foo(2, 3)
|
|
1235
|
+
sage: foo(2, 3).n() # needs sage.rings.real_mpfr
|
|
1236
|
+
12.0000000000000
|
|
1237
|
+
sage: foo(2, 3).conjugate() # needs sage.symbolic
|
|
1238
|
+
2
|
|
1239
|
+
"""
|
|
1240
|
+
self.__hinit = False
|
|
1241
|
+
Function.__init__(self, name, nargs, latex_name, conversions,
|
|
1242
|
+
evalf_params_first)
|
|
1243
|
+
|
|
1244
|
+
cdef _is_registered(SymbolicFunction self):
|
|
1245
|
+
# see if there is already a SymbolicFunction with the same state
|
|
1246
|
+
cdef long myhash = self._hash_()
|
|
1247
|
+
cdef SymbolicFunction sfunc = get_sfunction_from_hash(myhash)
|
|
1248
|
+
if sfunc is not None:
|
|
1249
|
+
# found one, set self._serial to be a copy
|
|
1250
|
+
self._serial = sfunc._serial
|
|
1251
|
+
return True
|
|
1252
|
+
return False
|
|
1253
|
+
|
|
1254
|
+
# cache the hash value of this function
|
|
1255
|
+
# this is used very often while unpickling to see if there is already
|
|
1256
|
+
# a function with the same properties
|
|
1257
|
+
cdef long _hash_(self) except -1:
|
|
1258
|
+
if not self.__hinit:
|
|
1259
|
+
# create a string representation of this SymbolicFunction
|
|
1260
|
+
slist = [self._nargs, self._name, str(self._latex_name),
|
|
1261
|
+
self._evalf_params_first]
|
|
1262
|
+
for fname in sfunctions_funcs:
|
|
1263
|
+
real_fname = '_%s_' % fname
|
|
1264
|
+
if hasattr(self, '%s' % real_fname):
|
|
1265
|
+
slist.append(hash(getattr(self, real_fname).__code__))
|
|
1266
|
+
else:
|
|
1267
|
+
slist.append(' ')
|
|
1268
|
+
self.__hcache = hash(tuple(slist))
|
|
1269
|
+
self.__hinit = True
|
|
1270
|
+
return self.__hcache
|
|
1271
|
+
|
|
1272
|
+
def __hash__(self):
|
|
1273
|
+
"""
|
|
1274
|
+
TESTS::
|
|
1275
|
+
|
|
1276
|
+
sage: foo = function("foo", nargs=2) # needs sage.symbolic
|
|
1277
|
+
sage: hash(foo) # random output # needs sage.symbolic
|
|
1278
|
+
-6859868030555295348
|
|
1279
|
+
|
|
1280
|
+
sage: def ev(self, x): return 2*x
|
|
1281
|
+
sage: foo = function("foo", nargs=2, eval_func=ev) # needs sage.symbolic
|
|
1282
|
+
sage: hash(foo) # random output # needs sage.symbolic
|
|
1283
|
+
-6859868030555295348
|
|
1284
|
+
"""
|
|
1285
|
+
return self._serial*self._hash_()
|
|
1286
|
+
|
|
1287
|
+
def __getstate__(self):
|
|
1288
|
+
"""
|
|
1289
|
+
Return a tuple describing the state of this object for pickling.
|
|
1290
|
+
|
|
1291
|
+
Pickling :class:`SymbolicFunction` objects is limited by the ability to pickle
|
|
1292
|
+
functions in python. We use :func:`~sage.misc.fpickle.pickle_function` for
|
|
1293
|
+
this purpose, which only works if there are no nested functions.
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
This should return all information that will be required to unpickle
|
|
1297
|
+
the object. The functionality for unpickling is implemented in
|
|
1298
|
+
:meth:`__setstate__`.
|
|
1299
|
+
|
|
1300
|
+
In order to pickle :class:`SymbolicFunction` objects, we return a tuple containing
|
|
1301
|
+
|
|
1302
|
+
* 0 - as pickle version number
|
|
1303
|
+
in case we decide to change the pickle format in the feature
|
|
1304
|
+
* name of this function
|
|
1305
|
+
* number of arguments
|
|
1306
|
+
* latex_name
|
|
1307
|
+
* a tuple containing attempts to pickle the following optional
|
|
1308
|
+
functions, in the order below
|
|
1309
|
+
* ``eval_f``
|
|
1310
|
+
* ``evalf_f``
|
|
1311
|
+
* ``conjugate_f``
|
|
1312
|
+
* ``real_part_f``
|
|
1313
|
+
* ``imag_part_f``
|
|
1314
|
+
* ``derivative_f``
|
|
1315
|
+
* ``power_f``
|
|
1316
|
+
* ``series_f``
|
|
1317
|
+
* ``print_f``
|
|
1318
|
+
* ``print_latex_f``
|
|
1319
|
+
|
|
1320
|
+
EXAMPLES::
|
|
1321
|
+
|
|
1322
|
+
sage: # needs sage.symbolic
|
|
1323
|
+
sage: foo = function("foo", nargs=2)
|
|
1324
|
+
sage: foo.__getstate__()
|
|
1325
|
+
(2, 'foo', 2, None, {}, True,
|
|
1326
|
+
[None, None, None, None, None, None, None, None, None, None, None])
|
|
1327
|
+
sage: t = loads(dumps(foo))
|
|
1328
|
+
sage: t == foo
|
|
1329
|
+
True
|
|
1330
|
+
sage: var('x,y')
|
|
1331
|
+
(x, y)
|
|
1332
|
+
sage: t(x, y)
|
|
1333
|
+
foo(x, y)
|
|
1334
|
+
|
|
1335
|
+
sage: def ev(self, x, y): return 2*x
|
|
1336
|
+
sage: foo = function("foo", nargs=2, eval_func=ev) # needs sage.symbolic
|
|
1337
|
+
sage: foo.__getstate__() # needs sage.symbolic
|
|
1338
|
+
(2, 'foo', 2, None, {}, True,
|
|
1339
|
+
[..., None, None, None, None, None, None, None, None, None, None])
|
|
1340
|
+
|
|
1341
|
+
sage: # needs sage.symbolic
|
|
1342
|
+
sage: u = loads(dumps(foo))
|
|
1343
|
+
sage: u == foo
|
|
1344
|
+
True
|
|
1345
|
+
sage: t == u
|
|
1346
|
+
False
|
|
1347
|
+
sage: u(y, x)
|
|
1348
|
+
2*y
|
|
1349
|
+
|
|
1350
|
+
sage: def evalf_f(self, x, **kwds): return int(6)
|
|
1351
|
+
sage: foo = function("foo", nargs=1, evalf_func=evalf_f) # needs sage.symbolic
|
|
1352
|
+
sage: foo.__getstate__() # needs sage.symbolic
|
|
1353
|
+
(2, 'foo', 1, None, {}, True,
|
|
1354
|
+
[None, ..., None, None, None, None, None, None, None, None, None])
|
|
1355
|
+
|
|
1356
|
+
sage: # needs sage.symbolic
|
|
1357
|
+
sage: v = loads(dumps(foo))
|
|
1358
|
+
sage: v == foo
|
|
1359
|
+
True
|
|
1360
|
+
sage: v == u
|
|
1361
|
+
False
|
|
1362
|
+
sage: foo(y).n()
|
|
1363
|
+
6
|
|
1364
|
+
sage: v(y).n()
|
|
1365
|
+
6
|
|
1366
|
+
|
|
1367
|
+
Test pickling expressions with symbolic functions::
|
|
1368
|
+
|
|
1369
|
+
sage: u = loads(dumps(foo(x)^2 + foo(y) + x^y)); u # needs sage.symbolic
|
|
1370
|
+
foo(x)^2 + x^y + foo(y)
|
|
1371
|
+
sage: u.subs(y=0) # needs sage.symbolic
|
|
1372
|
+
foo(x)^2 + foo(0) + 1
|
|
1373
|
+
sage: u.subs(y=0).n() # needs sage.symbolic
|
|
1374
|
+
43.0000000000000
|
|
1375
|
+
"""
|
|
1376
|
+
return (2, self._name, self._nargs, self._latex_name, self._conversions,
|
|
1377
|
+
self._evalf_params_first,
|
|
1378
|
+
[pickle_wrapper(getattr(self, '_%s_' % fname, None))
|
|
1379
|
+
for fname in sfunctions_funcs])
|
|
1380
|
+
|
|
1381
|
+
def __setstate__(self, state):
|
|
1382
|
+
"""
|
|
1383
|
+
Initialize the state of the object from data saved in a pickle.
|
|
1384
|
+
|
|
1385
|
+
During unpickling ``__init__`` methods of classes are not called, the saved
|
|
1386
|
+
data is passed to the class via this function instead.
|
|
1387
|
+
|
|
1388
|
+
TESTS::
|
|
1389
|
+
|
|
1390
|
+
sage: # needs sage.symbolic
|
|
1391
|
+
sage: var('x,y')
|
|
1392
|
+
(x, y)
|
|
1393
|
+
sage: foo = function("foo", nargs=2)
|
|
1394
|
+
sage: bar = function("bar", nargs=1)
|
|
1395
|
+
sage: bar.__setstate__(foo.__getstate__())
|
|
1396
|
+
|
|
1397
|
+
::
|
|
1398
|
+
|
|
1399
|
+
sage: # needs sage.symbolic
|
|
1400
|
+
sage: g = function('g', nargs=1, conjugate_func=lambda y, x: 2*x)
|
|
1401
|
+
sage: st = g.__getstate__()
|
|
1402
|
+
sage: f = function('f')
|
|
1403
|
+
sage: f(x)
|
|
1404
|
+
f(x)
|
|
1405
|
+
sage: f(x).conjugate() # no special conjugate method
|
|
1406
|
+
conjugate(f(x))
|
|
1407
|
+
sage: f.__setstate__(st)
|
|
1408
|
+
sage: f(x + 1).conjugate() # now there is a special method
|
|
1409
|
+
2*x + 2
|
|
1410
|
+
|
|
1411
|
+
Note that the other direction doesn't work here, since ``foo._hash_()``
|
|
1412
|
+
hash already been initialized.::
|
|
1413
|
+
|
|
1414
|
+
sage: bar # needs sage.symbolic
|
|
1415
|
+
foo
|
|
1416
|
+
sage: bar(x, y) # needs sage.symbolic
|
|
1417
|
+
foo(x, y)
|
|
1418
|
+
"""
|
|
1419
|
+
# check input
|
|
1420
|
+
if not ((state[0] == 1 and len(state) == 6) or
|
|
1421
|
+
(state[0] == 2 and len(state) == 7)):
|
|
1422
|
+
raise ValueError("unknown state information")
|
|
1423
|
+
|
|
1424
|
+
name = state[1]
|
|
1425
|
+
nargs = state[2]
|
|
1426
|
+
latex_name = state[3]
|
|
1427
|
+
conversions = state[4]
|
|
1428
|
+
|
|
1429
|
+
if state[0] == 1:
|
|
1430
|
+
evalf_params_first = True
|
|
1431
|
+
function_pickles = state[5]
|
|
1432
|
+
elif state[0] == 2:
|
|
1433
|
+
evalf_params_first = state[5]
|
|
1434
|
+
function_pickles = state[6]
|
|
1435
|
+
|
|
1436
|
+
for pickle, fname in zip(function_pickles, sfunctions_funcs):
|
|
1437
|
+
if pickle:
|
|
1438
|
+
real_fname = '_%s_' % fname
|
|
1439
|
+
setattr(self, real_fname, unpickle_function(pickle))
|
|
1440
|
+
|
|
1441
|
+
SymbolicFunction.__init__(self, name, nargs, latex_name,
|
|
1442
|
+
conversions, evalf_params_first)
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
def pickle_wrapper(f):
|
|
1446
|
+
"""
|
|
1447
|
+
Return a pickled version of the function ``f``.
|
|
1448
|
+
|
|
1449
|
+
If ``f`` is ``None``, just return ``None``.
|
|
1450
|
+
|
|
1451
|
+
This is a wrapper around :func:`pickle_function`.
|
|
1452
|
+
|
|
1453
|
+
EXAMPLES::
|
|
1454
|
+
|
|
1455
|
+
sage: from sage.symbolic.function import pickle_wrapper
|
|
1456
|
+
sage: def f(x): return x*x
|
|
1457
|
+
sage: isinstance(pickle_wrapper(f), bytes)
|
|
1458
|
+
True
|
|
1459
|
+
sage: pickle_wrapper(None) is None
|
|
1460
|
+
True
|
|
1461
|
+
"""
|
|
1462
|
+
if f is None:
|
|
1463
|
+
return None
|
|
1464
|
+
return pickle_function(f)
|
|
1465
|
+
|
|
1466
|
+
|
|
1467
|
+
def unpickle_wrapper(p):
|
|
1468
|
+
"""
|
|
1469
|
+
Return a unpickled version of the function defined by ``p``.
|
|
1470
|
+
|
|
1471
|
+
If ``p`` is ``None``, just return ``None``.
|
|
1472
|
+
|
|
1473
|
+
This is a wrapper around :func:`unpickle_function`.
|
|
1474
|
+
|
|
1475
|
+
EXAMPLES::
|
|
1476
|
+
|
|
1477
|
+
sage: from sage.symbolic.function import pickle_wrapper, unpickle_wrapper
|
|
1478
|
+
sage: def f(x): return x*x
|
|
1479
|
+
sage: s = pickle_wrapper(f)
|
|
1480
|
+
sage: g = unpickle_wrapper(s)
|
|
1481
|
+
sage: g(2)
|
|
1482
|
+
4
|
|
1483
|
+
sage: unpickle_wrapper(None) is None
|
|
1484
|
+
True
|
|
1485
|
+
"""
|
|
1486
|
+
if p is None:
|
|
1487
|
+
return None
|
|
1488
|
+
return unpickle_function(p)
|