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,1505 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
# sage.doctest: needs sage.symbolic
|
|
3
|
+
r"""
|
|
4
|
+
Piecewise functions
|
|
5
|
+
|
|
6
|
+
This module implement piecewise functions in a single variable. See
|
|
7
|
+
:mod:`sage.sets.real_set` for more information about how to construct
|
|
8
|
+
subsets of the real line for the domains.
|
|
9
|
+
|
|
10
|
+
EXAMPLES::
|
|
11
|
+
|
|
12
|
+
sage: f = piecewise([((0,1), x^3), ([-1,0], -x^2)]); f
|
|
13
|
+
piecewise(x|-->x^3 on (0, 1), x|-->-x^2 on [-1, 0]; x)
|
|
14
|
+
sage: 2*f
|
|
15
|
+
2*piecewise(x|-->x^3 on (0, 1), x|-->-x^2 on [-1, 0]; x)
|
|
16
|
+
sage: f(x=1/2)
|
|
17
|
+
1/8
|
|
18
|
+
sage: plot(f) # not tested
|
|
19
|
+
|
|
20
|
+
.. TODO::
|
|
21
|
+
|
|
22
|
+
Implement max/min location and values,
|
|
23
|
+
|
|
24
|
+
AUTHORS:
|
|
25
|
+
|
|
26
|
+
- David Joyner (2006-04): initial version
|
|
27
|
+
|
|
28
|
+
- David Joyner (2006-09): added __eq__, extend_by_zero_to, unextend,
|
|
29
|
+
convolution, trapezoid, trapezoid_integral_approximation,
|
|
30
|
+
riemann_sum, riemann_sum_integral_approximation, tangent_line fixed
|
|
31
|
+
bugs in __mul__, __add__
|
|
32
|
+
|
|
33
|
+
- David Joyner (2007-03): adding Hann filter for FS, added general FS
|
|
34
|
+
filter methods for computing and plotting, added options to plotting
|
|
35
|
+
of FS (eg, specifying rgb values are now allowed). Fixed bug in
|
|
36
|
+
documentation reported by Pablo De Napoli.
|
|
37
|
+
|
|
38
|
+
- David Joyner (2007-09): bug fixes due to behaviour of
|
|
39
|
+
SymbolicArithmetic
|
|
40
|
+
|
|
41
|
+
- David Joyner (2008-04): fixed docstring bugs reported by J Morrow; added
|
|
42
|
+
support for Laplace transform of functions with infinite support.
|
|
43
|
+
|
|
44
|
+
- David Joyner (2008-07): fixed a left multiplication bug reported by
|
|
45
|
+
C. Boncelet (by defining __rmul__ = __mul__).
|
|
46
|
+
|
|
47
|
+
- Paul Butler (2009-01): added indefinite integration and default_variable
|
|
48
|
+
|
|
49
|
+
- Volker Braun (2013): Complete rewrite
|
|
50
|
+
|
|
51
|
+
- Ralf Stephan (2015): Rewrite of convolution() and other calculus
|
|
52
|
+
functions; many doctest adaptations
|
|
53
|
+
|
|
54
|
+
- Eric Gourgoulhon (2017): Improve documentation and user interface of
|
|
55
|
+
Fourier series
|
|
56
|
+
|
|
57
|
+
TESTS::
|
|
58
|
+
|
|
59
|
+
sage: fast_callable(f, vars=[x])(0.5)
|
|
60
|
+
0.125000000000...
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
# ****************************************************************************
|
|
64
|
+
# Copyright (C) 2006 William Stein <wstein@gmail.com>
|
|
65
|
+
# 2006 David Joyner <wdjoyner@gmail.com>
|
|
66
|
+
# 2013 Volker Braun <vbraun.name@gmail.com>
|
|
67
|
+
#
|
|
68
|
+
# This program is free software: you can redistribute it and/or modify
|
|
69
|
+
# it under the terms of the GNU General Public License as published by
|
|
70
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
71
|
+
# (at your option) any later version.
|
|
72
|
+
# https://www.gnu.org/licenses/
|
|
73
|
+
# ****************************************************************************
|
|
74
|
+
|
|
75
|
+
from sage.misc.lazy_import import lazy_import
|
|
76
|
+
from sage.rings.infinity import minus_infinity, infinity
|
|
77
|
+
from sage.sets.real_set import RealSet
|
|
78
|
+
from sage.symbolic.function import BuiltinFunction
|
|
79
|
+
|
|
80
|
+
lazy_import('sage.symbolic.ring', 'SR')
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class PiecewiseFunction(BuiltinFunction):
|
|
84
|
+
def __init__(self):
|
|
85
|
+
"""
|
|
86
|
+
Piecewise function.
|
|
87
|
+
|
|
88
|
+
EXAMPLES::
|
|
89
|
+
|
|
90
|
+
sage: var('x, y')
|
|
91
|
+
(x, y)
|
|
92
|
+
sage: f = piecewise([((0,1), x^2*y), ([-1,0], -x*y^2)], var=x); f
|
|
93
|
+
piecewise(x|-->x^2*y on (0, 1), x|-->-x*y^2 on [-1, 0]; x)
|
|
94
|
+
sage: f(1/2)
|
|
95
|
+
1/4*y
|
|
96
|
+
sage: f(-1/2)
|
|
97
|
+
1/2*y^2
|
|
98
|
+
"""
|
|
99
|
+
BuiltinFunction.__init__(self, "piecewise",
|
|
100
|
+
latex_name='piecewise',
|
|
101
|
+
conversions=dict(), nargs=2)
|
|
102
|
+
|
|
103
|
+
def __call__(self, function_pieces, **kwds):
|
|
104
|
+
r"""
|
|
105
|
+
Piecewise functions.
|
|
106
|
+
|
|
107
|
+
INPUT:
|
|
108
|
+
|
|
109
|
+
- ``function_pieces`` -- list of pairs consisting of a
|
|
110
|
+
domain and a symbolic function
|
|
111
|
+
|
|
112
|
+
- ``var=x`` -- a symbolic variable or ``None`` (default); the
|
|
113
|
+
real variable in which the function is piecewise in
|
|
114
|
+
|
|
115
|
+
OUTPUT:
|
|
116
|
+
|
|
117
|
+
A piecewise-defined function. A :exc:`ValueError` will be raised
|
|
118
|
+
if the domains of the pieces are not pairwise disjoint.
|
|
119
|
+
|
|
120
|
+
EXAMPLES::
|
|
121
|
+
|
|
122
|
+
sage: my_abs = piecewise([((-1, 0), -x), ([0, 1], x)], var=x); my_abs
|
|
123
|
+
piecewise(x|-->-x on (-1, 0), x|-->x on [0, 1]; x)
|
|
124
|
+
sage: [ my_abs(i/5) for i in range(-4, 5)]
|
|
125
|
+
[4/5, 3/5, 2/5, 1/5, 0, 1/5, 2/5, 3/5, 4/5]
|
|
126
|
+
|
|
127
|
+
TESTS::
|
|
128
|
+
|
|
129
|
+
sage: piecewise([([-1, 0], -x), ([0, 1], x)], var=x)
|
|
130
|
+
Traceback (most recent call last):
|
|
131
|
+
...
|
|
132
|
+
ValueError: domains must be pairwise disjoint
|
|
133
|
+
|
|
134
|
+
sage: step = piecewise([((-1, 0), -1), ([0, 0], 0), ((0, 1), 1)], var=x); step
|
|
135
|
+
piecewise(x|-->-1 on (-1, 0), x|-->0 on {0}, x|-->1 on (0, 1); x)
|
|
136
|
+
sage: step(-1/2), step(0), step(1/2)
|
|
137
|
+
(-1, 0, 1)
|
|
138
|
+
"""
|
|
139
|
+
from types import FunctionType
|
|
140
|
+
var = kwds.pop('var', None)
|
|
141
|
+
parameters = []
|
|
142
|
+
domain_list = []
|
|
143
|
+
for piece in function_pieces:
|
|
144
|
+
domain, function = piece
|
|
145
|
+
if not isinstance(domain, RealSet):
|
|
146
|
+
domain = RealSet(domain)
|
|
147
|
+
if domain.is_empty():
|
|
148
|
+
continue
|
|
149
|
+
if isinstance(function, FunctionType):
|
|
150
|
+
if var is None:
|
|
151
|
+
var = SR.var('x')
|
|
152
|
+
if function.__code__.co_argcount == 0:
|
|
153
|
+
function = function()
|
|
154
|
+
else:
|
|
155
|
+
function = function(var)
|
|
156
|
+
function = SR(function)
|
|
157
|
+
if var is None and len(function.variables()) > 0:
|
|
158
|
+
var = function.variables()[0]
|
|
159
|
+
parameters.append((domain, function))
|
|
160
|
+
domain_list.append(domain)
|
|
161
|
+
if not RealSet.are_pairwise_disjoint(*domain_list):
|
|
162
|
+
raise ValueError('domains must be pairwise disjoint')
|
|
163
|
+
if var is None:
|
|
164
|
+
var = self.default_variable()
|
|
165
|
+
parameters = SR._force_pyobject(tuple(parameters), recursive=False)
|
|
166
|
+
return BuiltinFunction.__call__(self, parameters, var, **kwds)
|
|
167
|
+
|
|
168
|
+
def _print_(self, parameters, variable):
|
|
169
|
+
"""
|
|
170
|
+
Return a string representation.
|
|
171
|
+
|
|
172
|
+
OUTPUT: string
|
|
173
|
+
|
|
174
|
+
EXAMPLES::
|
|
175
|
+
|
|
176
|
+
sage: p = piecewise([((-2, 0), -x), ([0, 4], x)], var=x)
|
|
177
|
+
sage: str(p) # indirect doctest
|
|
178
|
+
'piecewise(x|-->-x on (-2, 0), x|-->x on [0, 4]; x)'
|
|
179
|
+
"""
|
|
180
|
+
s = 'piecewise('
|
|
181
|
+
# NOTE : could use ⟼ instead of |-->
|
|
182
|
+
args = (f'{variable}|-->{func} on {domain}'
|
|
183
|
+
for domain, func in parameters)
|
|
184
|
+
s += ', '.join(args) + f'; {variable})'
|
|
185
|
+
return s
|
|
186
|
+
|
|
187
|
+
def _subs_(self, subs_map, options, parameters, x):
|
|
188
|
+
"""
|
|
189
|
+
Callback from Pynac ``subs()``.
|
|
190
|
+
|
|
191
|
+
EXAMPLES:
|
|
192
|
+
|
|
193
|
+
If the substitution changes the piecewise variable, it must
|
|
194
|
+
evaluate to a number so that we know which component we are
|
|
195
|
+
on::
|
|
196
|
+
|
|
197
|
+
sage: p = piecewise([((-2, 0), -x), ([0, 4], x)], var=x)
|
|
198
|
+
sage: p.subs(x=-1)
|
|
199
|
+
1
|
|
200
|
+
sage: (10+p).subs(x=-1)
|
|
201
|
+
11
|
|
202
|
+
sage: p.subs(x=pi)
|
|
203
|
+
pi
|
|
204
|
+
|
|
205
|
+
Auxiliary variables can be substituted arbitrarily::
|
|
206
|
+
|
|
207
|
+
sage: var('x,y')
|
|
208
|
+
(x, y)
|
|
209
|
+
sage: p = piecewise([((-2, 0), -x^y), ([0, 2], x-y)], var=x); p
|
|
210
|
+
piecewise(x|-->-x^y on (-2, 0), x|-->x - y on [0, 2]; x)
|
|
211
|
+
sage: p.subs(y=sin(y))
|
|
212
|
+
piecewise(x|-->-x^sin(y) on (-2, 0), x|-->x - sin(y) on [0, 2]; x)
|
|
213
|
+
|
|
214
|
+
One can change the variable as follows::
|
|
215
|
+
|
|
216
|
+
sage: p = piecewise([((-2, 0), -x), ([0, 4], x)], var=x)
|
|
217
|
+
sage: y = SR.var('y')
|
|
218
|
+
sage: p(y)
|
|
219
|
+
piecewise(y|-->-y on (-2, 0), y|-->y on [0, 4]; y)
|
|
220
|
+
"""
|
|
221
|
+
point = subs_map.apply_to(x, 0)
|
|
222
|
+
|
|
223
|
+
if point.is_symbol(): # avoid to compare with x (see #37925)
|
|
224
|
+
new_params = [(domain, subs_map.apply_to(func, 0))
|
|
225
|
+
for domain, func in parameters]
|
|
226
|
+
return piecewise(new_params, var=point)
|
|
227
|
+
|
|
228
|
+
if (point.is_numeric() or point.is_constant()) and point.is_real():
|
|
229
|
+
if hasattr(point, 'pyobject'):
|
|
230
|
+
# unwrap any numeric values
|
|
231
|
+
point = point.pyobject()
|
|
232
|
+
for domain, func in parameters:
|
|
233
|
+
if domain.contains(point):
|
|
234
|
+
return subs_map.apply_to(func, 0)
|
|
235
|
+
raise ValueError(f'point {point} is not in the domain')
|
|
236
|
+
|
|
237
|
+
raise ValueError('substitution not allowed')
|
|
238
|
+
|
|
239
|
+
@staticmethod
|
|
240
|
+
def in_operands(ex):
|
|
241
|
+
"""
|
|
242
|
+
Return whether a symbolic expression contains a piecewise
|
|
243
|
+
function as operand.
|
|
244
|
+
|
|
245
|
+
INPUT:
|
|
246
|
+
|
|
247
|
+
- ``ex`` -- a symbolic expression
|
|
248
|
+
|
|
249
|
+
OUTPUT: boolean
|
|
250
|
+
|
|
251
|
+
EXAMPLES::
|
|
252
|
+
|
|
253
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]); f
|
|
254
|
+
piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
|
|
255
|
+
sage: piecewise.in_operands(f)
|
|
256
|
+
True
|
|
257
|
+
sage: piecewise.in_operands(1+sin(f))
|
|
258
|
+
True
|
|
259
|
+
sage: piecewise.in_operands(1+sin(0*f))
|
|
260
|
+
False
|
|
261
|
+
"""
|
|
262
|
+
def is_piecewise(ex):
|
|
263
|
+
if ex.operator() is piecewise:
|
|
264
|
+
return True
|
|
265
|
+
for op in ex.operands():
|
|
266
|
+
if is_piecewise(op):
|
|
267
|
+
return True
|
|
268
|
+
return False
|
|
269
|
+
return is_piecewise(ex)
|
|
270
|
+
|
|
271
|
+
@staticmethod
|
|
272
|
+
def simplify(ex):
|
|
273
|
+
"""
|
|
274
|
+
Combine piecewise operands into single piecewise function.
|
|
275
|
+
|
|
276
|
+
OUTPUT:
|
|
277
|
+
|
|
278
|
+
A piecewise function whose operands are not piecewise if
|
|
279
|
+
possible, that is, as long as the piecewise variable is the same.
|
|
280
|
+
|
|
281
|
+
EXAMPLES::
|
|
282
|
+
|
|
283
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))])
|
|
284
|
+
sage: piecewise.simplify(f)
|
|
285
|
+
Traceback (most recent call last):
|
|
286
|
+
...
|
|
287
|
+
NotImplementedError
|
|
288
|
+
"""
|
|
289
|
+
raise NotImplementedError
|
|
290
|
+
|
|
291
|
+
def _tderivative_(self, parameters, variable, *args, **kwds):
|
|
292
|
+
"""
|
|
293
|
+
Return the derivative of the piecewise function by applying the
|
|
294
|
+
derivative to each piece.
|
|
295
|
+
|
|
296
|
+
EXAMPLES::
|
|
297
|
+
|
|
298
|
+
sage: f = piecewise([[(-1,1), x**2], [(1,3), x**3]])
|
|
299
|
+
sage: f.diff()
|
|
300
|
+
piecewise(x|-->2*x on (-1, 1), x|-->3*x^2 on (1, 3); x)
|
|
301
|
+
sage: f.diff(x,x)
|
|
302
|
+
piecewise(x|-->2 on (-1, 1), x|-->6*x on (1, 3); x)
|
|
303
|
+
|
|
304
|
+
This still fails miserably::
|
|
305
|
+
|
|
306
|
+
sage: y = SR.var('y')
|
|
307
|
+
sage: f = piecewise([[(-6,0), x+y], [(0,8), x*y]],var=x)
|
|
308
|
+
sage: f.derivative(x) # known bug
|
|
309
|
+
piecewise(x|-->1 on (-6, 0), x|-->y on (0, 8); x)
|
|
310
|
+
sage: f.derivative(y) # known bug
|
|
311
|
+
piecewise(x|-->1 on (-6, 0), x|-->x on (0, 8); x)
|
|
312
|
+
|
|
313
|
+
TESTS::
|
|
314
|
+
|
|
315
|
+
sage: f = piecewise([((-oo, -1), 0), ((-1, 1), exp(-1/(1 - x^2))), ((1, oo), 0)])
|
|
316
|
+
sage: f.diff()
|
|
317
|
+
piecewise(x|-->0 on (-oo, -1), x|-->-2*x*e^(1/(x^2 - 1))/(x^2 - 1)^2 on (-1, 1), x|-->0 on (1, +oo); x)
|
|
318
|
+
"""
|
|
319
|
+
return piecewise([(domain, func.derivative(*args))
|
|
320
|
+
for domain, func in parameters],
|
|
321
|
+
var=variable)
|
|
322
|
+
|
|
323
|
+
class EvaluationMethods:
|
|
324
|
+
|
|
325
|
+
def __pow__(self, parameters, variable, n):
|
|
326
|
+
"""
|
|
327
|
+
Return the `n`-th power of the piecewise function by applying the
|
|
328
|
+
operation to each piece.
|
|
329
|
+
|
|
330
|
+
INPUT:
|
|
331
|
+
|
|
332
|
+
- ``n`` -- number or symbolic expression
|
|
333
|
+
|
|
334
|
+
EXAMPLES::
|
|
335
|
+
|
|
336
|
+
sage: f1(x) = -abs(x) + 1; f2(x) = abs(x - 2) - 1
|
|
337
|
+
sage: f = piecewise([[(-1,1), f1], [(1,3), f2]])
|
|
338
|
+
sage: (f^2).integral(definite=True)
|
|
339
|
+
4/3
|
|
340
|
+
"""
|
|
341
|
+
return piecewise(zip(self.domains(),
|
|
342
|
+
[ex**n for ex in self.expressions()]),
|
|
343
|
+
var=variable)
|
|
344
|
+
|
|
345
|
+
def expression_at(self, parameters, variable, point):
|
|
346
|
+
"""
|
|
347
|
+
Return the expression defining the piecewise function at
|
|
348
|
+
``value``.
|
|
349
|
+
|
|
350
|
+
INPUT:
|
|
351
|
+
|
|
352
|
+
- ``point`` -- a real number
|
|
353
|
+
|
|
354
|
+
OUTPUT:
|
|
355
|
+
|
|
356
|
+
The symbolic expression defining the function value at the
|
|
357
|
+
given ``point``.
|
|
358
|
+
|
|
359
|
+
EXAMPLES::
|
|
360
|
+
|
|
361
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]); f
|
|
362
|
+
piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
|
|
363
|
+
sage: f.expression_at(0)
|
|
364
|
+
sin(x)
|
|
365
|
+
sage: f.expression_at(1)
|
|
366
|
+
cos(x)
|
|
367
|
+
sage: f.expression_at(2)
|
|
368
|
+
Traceback (most recent call last):
|
|
369
|
+
...
|
|
370
|
+
ValueError: point is not in the domain
|
|
371
|
+
"""
|
|
372
|
+
for domain, func in parameters:
|
|
373
|
+
if domain.contains(point):
|
|
374
|
+
return func
|
|
375
|
+
raise ValueError('point is not in the domain')
|
|
376
|
+
|
|
377
|
+
which_function = expression_at
|
|
378
|
+
|
|
379
|
+
def domains(self, parameters, variable):
|
|
380
|
+
"""
|
|
381
|
+
Return the individual domains.
|
|
382
|
+
|
|
383
|
+
See also :meth:`~expressions`.
|
|
384
|
+
|
|
385
|
+
OUTPUT:
|
|
386
|
+
|
|
387
|
+
The collection of domains of the component functions as a
|
|
388
|
+
tuple of :class:`~sage.sets.real_set.RealSet`.
|
|
389
|
+
|
|
390
|
+
EXAMPLES::
|
|
391
|
+
|
|
392
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]); f
|
|
393
|
+
piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
|
|
394
|
+
sage: f.domains()
|
|
395
|
+
({0}, (0, 2))
|
|
396
|
+
"""
|
|
397
|
+
return tuple(dom for dom, fun in parameters)
|
|
398
|
+
|
|
399
|
+
def domain(self, parameters, variable):
|
|
400
|
+
"""
|
|
401
|
+
Return the domain.
|
|
402
|
+
|
|
403
|
+
OUTPUT:
|
|
404
|
+
|
|
405
|
+
The union of the domains of the individual pieces as a
|
|
406
|
+
:class:`~sage.sets.real_set.RealSet`.
|
|
407
|
+
|
|
408
|
+
EXAMPLES::
|
|
409
|
+
|
|
410
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]); f
|
|
411
|
+
piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
|
|
412
|
+
sage: f.domain()
|
|
413
|
+
[0, 2)
|
|
414
|
+
"""
|
|
415
|
+
intervals = []
|
|
416
|
+
for domain, func in parameters:
|
|
417
|
+
intervals += list(domain)
|
|
418
|
+
return RealSet(*intervals)
|
|
419
|
+
|
|
420
|
+
def __len__(self, parameters, variable):
|
|
421
|
+
"""
|
|
422
|
+
Return the number of "pieces".
|
|
423
|
+
|
|
424
|
+
OUTPUT: integer
|
|
425
|
+
|
|
426
|
+
EXAMPLES::
|
|
427
|
+
|
|
428
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]); f
|
|
429
|
+
piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
|
|
430
|
+
sage: len(f)
|
|
431
|
+
2
|
|
432
|
+
"""
|
|
433
|
+
return len(parameters)
|
|
434
|
+
|
|
435
|
+
def expressions(self, parameters, variable):
|
|
436
|
+
"""
|
|
437
|
+
Return the individual domains.
|
|
438
|
+
|
|
439
|
+
See also :meth:`~domains`.
|
|
440
|
+
|
|
441
|
+
OUTPUT: the collection of expressions of the component functions
|
|
442
|
+
|
|
443
|
+
EXAMPLES::
|
|
444
|
+
|
|
445
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]); f
|
|
446
|
+
piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
|
|
447
|
+
sage: f.expressions()
|
|
448
|
+
(sin(x), cos(x))
|
|
449
|
+
"""
|
|
450
|
+
return tuple(fun for dom, fun in parameters)
|
|
451
|
+
|
|
452
|
+
def items(self, parameters, variable):
|
|
453
|
+
"""
|
|
454
|
+
Iterate over the pieces of the piecewise function.
|
|
455
|
+
|
|
456
|
+
.. NOTE::
|
|
457
|
+
|
|
458
|
+
You should probably use :meth:`pieces` instead, which
|
|
459
|
+
offers a nicer interface.
|
|
460
|
+
|
|
461
|
+
OUTPUT:
|
|
462
|
+
|
|
463
|
+
This method iterates over pieces of the piecewise
|
|
464
|
+
function, each represented by a pair. The first element is
|
|
465
|
+
the support, and the second the function over that
|
|
466
|
+
support.
|
|
467
|
+
|
|
468
|
+
EXAMPLES::
|
|
469
|
+
|
|
470
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))])
|
|
471
|
+
sage: for support, function in f.items():
|
|
472
|
+
....: print('support is {0}, function is {1}'.format(support, function))
|
|
473
|
+
support is {0}, function is sin(x)
|
|
474
|
+
support is (0, 2), function is cos(x)
|
|
475
|
+
"""
|
|
476
|
+
yield from parameters
|
|
477
|
+
|
|
478
|
+
def __call__(self, parameters, variable, value=None, **kwds):
|
|
479
|
+
"""
|
|
480
|
+
Call the piecewise function.
|
|
481
|
+
|
|
482
|
+
EXAMPLES::
|
|
483
|
+
|
|
484
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]); f
|
|
485
|
+
piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
|
|
486
|
+
sage: f(0)
|
|
487
|
+
0
|
|
488
|
+
sage: f(1)
|
|
489
|
+
cos(1)
|
|
490
|
+
sage: f(2)
|
|
491
|
+
Traceback (most recent call last):
|
|
492
|
+
...
|
|
493
|
+
ValueError: point 2 is not in the domain
|
|
494
|
+
"""
|
|
495
|
+
self = piecewise(parameters, var=variable)
|
|
496
|
+
substitution = dict()
|
|
497
|
+
for k, v in kwds.items():
|
|
498
|
+
substitution[SR.var(k)] = v
|
|
499
|
+
if value is not None:
|
|
500
|
+
substitution[variable] = value
|
|
501
|
+
return self.subs(substitution)
|
|
502
|
+
|
|
503
|
+
def _fast_callable_(self, parameters, variable, etb):
|
|
504
|
+
"""
|
|
505
|
+
Override the ``fast_callable``.
|
|
506
|
+
|
|
507
|
+
OUTPUT:
|
|
508
|
+
|
|
509
|
+
A :class:`~sage.ext.fast_callable.ExpressionCall`
|
|
510
|
+
representing the piecewise function in the expression
|
|
511
|
+
tree.
|
|
512
|
+
|
|
513
|
+
EXAMPLES::
|
|
514
|
+
|
|
515
|
+
sage: p = piecewise([((-1, 0), -x), ([0, 1], x)], var=x)
|
|
516
|
+
sage: from sage.ext.fast_callable import ExpressionTreeBuilder
|
|
517
|
+
sage: etb = ExpressionTreeBuilder(vars=['x'])
|
|
518
|
+
sage: p._fast_callable_(etb)
|
|
519
|
+
{piecewise(x|-->-x on (-1, 0), x|-->x on [0, 1]; x)}(v_0)
|
|
520
|
+
"""
|
|
521
|
+
self = piecewise(parameters, var=variable)
|
|
522
|
+
return etb.call(self, variable)
|
|
523
|
+
|
|
524
|
+
def restriction(self, parameters, variable, restricted_domain):
|
|
525
|
+
"""
|
|
526
|
+
Restrict the domain.
|
|
527
|
+
|
|
528
|
+
INPUT:
|
|
529
|
+
|
|
530
|
+
- ``restricted_domain`` -- a
|
|
531
|
+
:class:`~sage.sets.real_set.RealSet` or something that
|
|
532
|
+
defines one.
|
|
533
|
+
|
|
534
|
+
OUTPUT: a new piecewise function obtained by restricting the domain
|
|
535
|
+
|
|
536
|
+
EXAMPLES::
|
|
537
|
+
|
|
538
|
+
sage: f = piecewise([((-oo, oo), x)]); f
|
|
539
|
+
piecewise(x|-->x on (-oo, +oo); x)
|
|
540
|
+
sage: f.restriction([[-1,1], [3,3]])
|
|
541
|
+
piecewise(x|-->x on [-1, 1] ∪ {3}; x)
|
|
542
|
+
"""
|
|
543
|
+
restricted_domain = RealSet(*restricted_domain)
|
|
544
|
+
new_param = []
|
|
545
|
+
for domain, func in parameters:
|
|
546
|
+
domain = domain.intersection(restricted_domain)
|
|
547
|
+
new_param.append((domain, func))
|
|
548
|
+
return piecewise(new_param, var=variable)
|
|
549
|
+
|
|
550
|
+
def extension(self, parameters, variable, extension, extension_domain=None):
|
|
551
|
+
"""
|
|
552
|
+
Extend the function.
|
|
553
|
+
|
|
554
|
+
INPUT:
|
|
555
|
+
|
|
556
|
+
- ``extension`` -- a symbolic expression
|
|
557
|
+
|
|
558
|
+
- ``extension_domain`` -- a
|
|
559
|
+
:class:`~sage.sets.real_set.RealSet` or ``None``
|
|
560
|
+
(default). The domain of the extension. By default, the
|
|
561
|
+
entire complement of the current domain.
|
|
562
|
+
|
|
563
|
+
EXAMPLES::
|
|
564
|
+
|
|
565
|
+
sage: f = piecewise([((-1,1), x)]); f
|
|
566
|
+
piecewise(x|-->x on (-1, 1); x)
|
|
567
|
+
sage: f(3)
|
|
568
|
+
Traceback (most recent call last):
|
|
569
|
+
...
|
|
570
|
+
ValueError: point 3 is not in the domain
|
|
571
|
+
|
|
572
|
+
sage: g = f.extension(0); g
|
|
573
|
+
piecewise(x|-->x on (-1, 1), x|-->0 on (-oo, -1] ∪ [1, +oo); x)
|
|
574
|
+
sage: g(3)
|
|
575
|
+
0
|
|
576
|
+
|
|
577
|
+
sage: h = f.extension(1, RealSet.unbounded_above_closed(1)); h
|
|
578
|
+
piecewise(x|-->x on (-1, 1), x|-->1 on [1, +oo); x)
|
|
579
|
+
sage: h(3)
|
|
580
|
+
1
|
|
581
|
+
"""
|
|
582
|
+
self = piecewise(parameters, var=variable)
|
|
583
|
+
if extension_domain is None:
|
|
584
|
+
extension_domain = self.domain().complement()
|
|
585
|
+
ext = ((extension_domain, SR(extension)),)
|
|
586
|
+
return piecewise(parameters + ext, var=variable)
|
|
587
|
+
|
|
588
|
+
def unextend_zero(self, parameters, variable):
|
|
589
|
+
"""
|
|
590
|
+
Remove zero pieces.
|
|
591
|
+
|
|
592
|
+
EXAMPLES::
|
|
593
|
+
|
|
594
|
+
sage: f = piecewise([((-1,1), x)]); f
|
|
595
|
+
piecewise(x|-->x on (-1, 1); x)
|
|
596
|
+
sage: g = f.extension(0); g
|
|
597
|
+
piecewise(x|-->x on (-1, 1), x|-->0 on (-oo, -1] ∪ [1, +oo); x)
|
|
598
|
+
sage: g(3)
|
|
599
|
+
0
|
|
600
|
+
sage: h = g.unextend_zero()
|
|
601
|
+
sage: bool(h == f)
|
|
602
|
+
True
|
|
603
|
+
"""
|
|
604
|
+
result = [(domain, func) for domain, func in parameters
|
|
605
|
+
if func != 0]
|
|
606
|
+
if len(result) == len(self):
|
|
607
|
+
return self
|
|
608
|
+
return piecewise(result, var=variable)
|
|
609
|
+
|
|
610
|
+
def pieces(self, parameters, variable):
|
|
611
|
+
"""
|
|
612
|
+
Return the "pieces".
|
|
613
|
+
|
|
614
|
+
OUTPUT:
|
|
615
|
+
|
|
616
|
+
A tuple of piecewise functions, each having only a single
|
|
617
|
+
expression.
|
|
618
|
+
|
|
619
|
+
EXAMPLES::
|
|
620
|
+
|
|
621
|
+
sage: p = piecewise([((-1, 0), -x), ([0, 1], x)], var=x)
|
|
622
|
+
sage: p.pieces()
|
|
623
|
+
(piecewise(x|-->-x on (-1, 0); x),
|
|
624
|
+
piecewise(x|-->x on [0, 1]; x))
|
|
625
|
+
"""
|
|
626
|
+
return tuple(piecewise([(domain, func)], var=variable)
|
|
627
|
+
for domain, func in parameters)
|
|
628
|
+
|
|
629
|
+
def end_points(self, parameters, variable) -> list:
|
|
630
|
+
"""
|
|
631
|
+
Return a list of all interval endpoints for this function.
|
|
632
|
+
|
|
633
|
+
EXAMPLES::
|
|
634
|
+
|
|
635
|
+
sage: f1(x) = 1
|
|
636
|
+
sage: f2(x) = 1 - x
|
|
637
|
+
sage: f3(x) = x^2 - 5
|
|
638
|
+
sage: f = piecewise([[(0,1), f1], [(1,2), f2], [(2,3), f3]])
|
|
639
|
+
sage: f.end_points()
|
|
640
|
+
[0, 1, 2, 3]
|
|
641
|
+
sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]); f
|
|
642
|
+
piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
|
|
643
|
+
sage: f.end_points()
|
|
644
|
+
[0, 2]
|
|
645
|
+
"""
|
|
646
|
+
s = set()
|
|
647
|
+
for domain, func in parameters:
|
|
648
|
+
for interval in domain:
|
|
649
|
+
s.add(interval.lower())
|
|
650
|
+
s.add(interval.upper())
|
|
651
|
+
s.discard(minus_infinity)
|
|
652
|
+
s.discard(infinity)
|
|
653
|
+
return sorted(s)
|
|
654
|
+
|
|
655
|
+
def piecewise_add(self, parameters, variable, other):
|
|
656
|
+
"""
|
|
657
|
+
Return a new piecewise function with domain the union
|
|
658
|
+
of the original domains and functions summed. Undefined
|
|
659
|
+
intervals in the union domain get function value `0`.
|
|
660
|
+
|
|
661
|
+
EXAMPLES::
|
|
662
|
+
|
|
663
|
+
sage: f = piecewise([([0,1], 1), ((2,3), x)])
|
|
664
|
+
sage: g = piecewise([((1/2, 2), x)])
|
|
665
|
+
sage: f.piecewise_add(g).unextend_zero()
|
|
666
|
+
piecewise(x|-->1 on (0, 1/2],
|
|
667
|
+
x|-->x + 1 on (1/2, 1],
|
|
668
|
+
x|-->x on (1, 2) ∪ (2, 3); x)
|
|
669
|
+
"""
|
|
670
|
+
points = ([minus_infinity] +
|
|
671
|
+
sorted(set(self.end_points() + other.end_points())) +
|
|
672
|
+
[infinity])
|
|
673
|
+
domain = []
|
|
674
|
+
funcs = []
|
|
675
|
+
contains_lower = False
|
|
676
|
+
contains_upper = False
|
|
677
|
+
for i in range(len(points) - 1):
|
|
678
|
+
a, b = points[i], points[i + 1]
|
|
679
|
+
try:
|
|
680
|
+
contains_lower = (self.domain().contains(a) or
|
|
681
|
+
other.domain().contains(a)) and not contains_upper
|
|
682
|
+
contains_upper = (self.domain().contains(b) or
|
|
683
|
+
other.domain().contains(b))
|
|
684
|
+
if contains_lower:
|
|
685
|
+
if contains_upper:
|
|
686
|
+
rs = RealSet.closed(a, b)
|
|
687
|
+
else:
|
|
688
|
+
rs = RealSet.closed_open(a, b)
|
|
689
|
+
else:
|
|
690
|
+
if contains_upper:
|
|
691
|
+
rs = RealSet.open_closed(a, b)
|
|
692
|
+
else:
|
|
693
|
+
rs = RealSet.open(a, b)
|
|
694
|
+
point = (b + a) / 2
|
|
695
|
+
except ValueError:
|
|
696
|
+
if a == minus_infinity and b == infinity:
|
|
697
|
+
rs = RealSet.open(minus_infinity, infinity)
|
|
698
|
+
point = 0
|
|
699
|
+
elif a == minus_infinity:
|
|
700
|
+
if contains_lower:
|
|
701
|
+
rs = RealSet.unbounded_below_closed(b)
|
|
702
|
+
else:
|
|
703
|
+
rs = RealSet.unbounded_below_open(b)
|
|
704
|
+
point = b - 1
|
|
705
|
+
elif b == infinity:
|
|
706
|
+
if contains_upper:
|
|
707
|
+
rs = RealSet.unbounded_above_closed(a)
|
|
708
|
+
else:
|
|
709
|
+
rs = RealSet.unbounded_above_open(a)
|
|
710
|
+
point = a + 1
|
|
711
|
+
else:
|
|
712
|
+
raise
|
|
713
|
+
try:
|
|
714
|
+
ex1 = self.expression_at(point)
|
|
715
|
+
except ValueError:
|
|
716
|
+
ex1 = 0
|
|
717
|
+
try:
|
|
718
|
+
ex2 = other.expression_at(point)
|
|
719
|
+
except ValueError:
|
|
720
|
+
ex2 = 0
|
|
721
|
+
ex = ex1 + ex2
|
|
722
|
+
if i > 0 and funcs[-1] == ex:
|
|
723
|
+
# extend the previous domain
|
|
724
|
+
rs += domain[-1]
|
|
725
|
+
domain[-1] = rs
|
|
726
|
+
else:
|
|
727
|
+
domain += rs
|
|
728
|
+
funcs.append(ex)
|
|
729
|
+
return piecewise(zip(domain, funcs))
|
|
730
|
+
|
|
731
|
+
def integral(self, parameters, variable, x=None, a=None, b=None, definite=False, **kwds):
|
|
732
|
+
r"""
|
|
733
|
+
By default, return the indefinite integral of the function.
|
|
734
|
+
|
|
735
|
+
If ``definite=True`` is given, returns the definite integral.
|
|
736
|
+
|
|
737
|
+
AUTHOR:
|
|
738
|
+
|
|
739
|
+
- Paul Butler
|
|
740
|
+
|
|
741
|
+
EXAMPLES::
|
|
742
|
+
|
|
743
|
+
sage: f1(x) = 1 - x
|
|
744
|
+
sage: f = piecewise([((0,1), 1), ((1,2), f1)])
|
|
745
|
+
sage: f.integral(definite=True)
|
|
746
|
+
1/2
|
|
747
|
+
|
|
748
|
+
::
|
|
749
|
+
|
|
750
|
+
sage: f1(x) = -1
|
|
751
|
+
sage: f2(x) = 2
|
|
752
|
+
sage: f = piecewise([((0,pi/2), f1), ((pi/2,pi), f2)])
|
|
753
|
+
sage: f.integral(definite=True)
|
|
754
|
+
1/2*pi
|
|
755
|
+
|
|
756
|
+
sage: f1(x) = 2
|
|
757
|
+
sage: f2(x) = 3 - x
|
|
758
|
+
sage: f = piecewise([[(-2, 0), f1], [(0, 3), f2]])
|
|
759
|
+
sage: f.integral()
|
|
760
|
+
piecewise(x|-->2*x + 4 on (-2, 0),
|
|
761
|
+
x|-->-1/2*x^2 + 3*x + 4 on (0, 3); x)
|
|
762
|
+
|
|
763
|
+
sage: f1(y) = -1
|
|
764
|
+
sage: f2(y) = y + 3
|
|
765
|
+
sage: f3(y) = -y - 1
|
|
766
|
+
sage: f4(y) = y^2 - 1
|
|
767
|
+
sage: f5(y) = 3
|
|
768
|
+
sage: f = piecewise([[[-4,-3], f1], [(-3,-2), f2], [[-2,0], f3],
|
|
769
|
+
....: [(0,2), f4], [[2,3], f5]])
|
|
770
|
+
sage: F = f.integral(y); F
|
|
771
|
+
piecewise(y|-->-y - 4 on [-4, -3],
|
|
772
|
+
y|-->1/2*y^2 + 3*y + 7/2 on (-3, -2),
|
|
773
|
+
y|-->-1/2*y^2 - y - 1/2 on [-2, 0],
|
|
774
|
+
y|-->1/3*y^3 - y - 1/2 on (0, 2),
|
|
775
|
+
y|-->3*y - 35/6 on [2, 3]; y)
|
|
776
|
+
|
|
777
|
+
Ensure results are consistent with FTC::
|
|
778
|
+
|
|
779
|
+
sage: F(-3) - F(-4)
|
|
780
|
+
-1
|
|
781
|
+
sage: F(-1) - F(-3)
|
|
782
|
+
1
|
|
783
|
+
sage: F(2) - F(0)
|
|
784
|
+
2/3
|
|
785
|
+
sage: f.integral(y, 0, 2)
|
|
786
|
+
2/3
|
|
787
|
+
sage: F(3) - F(-4)
|
|
788
|
+
19/6
|
|
789
|
+
sage: f.integral(y, -4, 3)
|
|
790
|
+
19/6
|
|
791
|
+
sage: f.integral(definite=True)
|
|
792
|
+
19/6
|
|
793
|
+
|
|
794
|
+
::
|
|
795
|
+
|
|
796
|
+
sage: f1(y) = (y+3)^2
|
|
797
|
+
sage: f2(y) = y+3
|
|
798
|
+
sage: f3(y) = 3
|
|
799
|
+
sage: f = piecewise([[(-infinity, -3), f1], [(-3, 0), f2],
|
|
800
|
+
....: [(0, infinity), f3]])
|
|
801
|
+
sage: f.integral()
|
|
802
|
+
piecewise(y|-->1/3*y^3 + 3*y^2 + 9*y + 9 on (-oo, -3),
|
|
803
|
+
y|-->1/2*y^2 + 3*y + 9/2 on (-3, 0),
|
|
804
|
+
y|-->3*y + 9/2 on (0, +oo); y)
|
|
805
|
+
|
|
806
|
+
::
|
|
807
|
+
|
|
808
|
+
sage: f1(x) = e^(-abs(x))
|
|
809
|
+
sage: f = piecewise([[(-infinity, infinity), f1]])
|
|
810
|
+
sage: result = f.integral(definite=True)
|
|
811
|
+
...
|
|
812
|
+
sage: result
|
|
813
|
+
2
|
|
814
|
+
sage: f.integral()
|
|
815
|
+
piecewise(x|-->-integrate(e^(-abs(x)), x, x, +Infinity) on (-oo, +oo); x)
|
|
816
|
+
|
|
817
|
+
::
|
|
818
|
+
|
|
819
|
+
sage: f = piecewise([((0, 5), cos(x))])
|
|
820
|
+
sage: f.integral()
|
|
821
|
+
piecewise(x|-->sin(x) on (0, 5); x)
|
|
822
|
+
|
|
823
|
+
TESTS:
|
|
824
|
+
|
|
825
|
+
Verify that piecewise integrals of zero work (:issue:`10841`)::
|
|
826
|
+
|
|
827
|
+
sage: f0(x) = 0
|
|
828
|
+
sage: f = piecewise([[[0,1], f0]])
|
|
829
|
+
sage: f.integral(x,0,1)
|
|
830
|
+
0
|
|
831
|
+
sage: f = piecewise([[[0,1], 0]])
|
|
832
|
+
sage: f.integral(x,0,1)
|
|
833
|
+
0
|
|
834
|
+
sage: f = piecewise([[[0,1], SR(0)]])
|
|
835
|
+
sage: f.integral(x,0,1)
|
|
836
|
+
0
|
|
837
|
+
|
|
838
|
+
Check that the algorithm keyword can be used::
|
|
839
|
+
|
|
840
|
+
sage: # needs sage.libs.giac
|
|
841
|
+
sage: ex = piecewise([([0, 1], 1), ((1, oo), 1/x**2)])
|
|
842
|
+
sage: integral(ex, x, 0, 100, algorithm='sympy')
|
|
843
|
+
199/100
|
|
844
|
+
sage: integral(ex, x, algorithm='sympy')
|
|
845
|
+
piecewise(x|-->x on [0, 1], x|-->-1/x + 2 on (1, +oo); x)
|
|
846
|
+
"""
|
|
847
|
+
if a is not None and b is not None:
|
|
848
|
+
F = self.integral(x, **kwds)
|
|
849
|
+
return F(b) - F(a)
|
|
850
|
+
|
|
851
|
+
if a is not None or b is not None:
|
|
852
|
+
raise TypeError('only one endpoint given')
|
|
853
|
+
|
|
854
|
+
area = 0
|
|
855
|
+
new_pieces = []
|
|
856
|
+
|
|
857
|
+
if x is None:
|
|
858
|
+
x = self.default_variable()
|
|
859
|
+
|
|
860
|
+
# The integral is computed by iterating over the pieces in order.
|
|
861
|
+
# The definite integral for each piece is calculated and accumulated in `area`.
|
|
862
|
+
# The indefinite integral of each piece is also calculated,
|
|
863
|
+
# and the `area` before each piece is added to the piece.
|
|
864
|
+
#
|
|
865
|
+
# If a definite integral is requested, `area` is returned.
|
|
866
|
+
# Otherwise, a piecewise function is constructed from the indefinite integrals
|
|
867
|
+
# and returned.
|
|
868
|
+
#
|
|
869
|
+
# An exception is made if integral is called on a piecewise function
|
|
870
|
+
# that starts at -infinity. In this case, we do not try to calculate the
|
|
871
|
+
# definite integral of the first piece, and the value of `area` remains 0
|
|
872
|
+
# after the first piece.
|
|
873
|
+
|
|
874
|
+
from sage.symbolic.assumptions import assume, forget
|
|
875
|
+
for domain, fun in parameters:
|
|
876
|
+
for interval in domain:
|
|
877
|
+
start = interval.lower()
|
|
878
|
+
end = interval.upper()
|
|
879
|
+
if start == -infinity and not definite:
|
|
880
|
+
fun_integrated = fun.integral(x, end, x, **kwds)
|
|
881
|
+
else:
|
|
882
|
+
try:
|
|
883
|
+
assume(start < x)
|
|
884
|
+
except ValueError: # Assumption is redundant
|
|
885
|
+
pass
|
|
886
|
+
fun_integrated = fun.integral(x, start, x, **kwds) + area
|
|
887
|
+
forget(start < x)
|
|
888
|
+
if definite or end != infinity:
|
|
889
|
+
area += fun.integral(x, start, end, **kwds)
|
|
890
|
+
new_pieces.append([interval, SR(fun_integrated).function(x)])
|
|
891
|
+
|
|
892
|
+
if definite:
|
|
893
|
+
return SR(area)
|
|
894
|
+
else:
|
|
895
|
+
return piecewise(new_pieces)
|
|
896
|
+
|
|
897
|
+
def critical_points(self, parameters, variable):
|
|
898
|
+
"""
|
|
899
|
+
Return the critical points of this piecewise function.
|
|
900
|
+
|
|
901
|
+
EXAMPLES::
|
|
902
|
+
|
|
903
|
+
sage: R.<x> = QQ[]
|
|
904
|
+
sage: f1 = x^0
|
|
905
|
+
sage: f2 = 10*x - x^2
|
|
906
|
+
sage: f3 = 3*x^4 - 156*x^3 + 3036*x^2 - 26208*x
|
|
907
|
+
sage: f = piecewise([[(0,3), f1], [(3,10), f2], [(10,20), f3]])
|
|
908
|
+
sage: expected = [5, 12, 13, 14]
|
|
909
|
+
sage: all(abs(e-a) < 0.001 for e,a in zip(expected, f.critical_points()))
|
|
910
|
+
True
|
|
911
|
+
|
|
912
|
+
TESTS:
|
|
913
|
+
|
|
914
|
+
Use variables other than x (:issue:`13836`)::
|
|
915
|
+
|
|
916
|
+
sage: R.<y> = QQ[]
|
|
917
|
+
sage: f1 = y^0
|
|
918
|
+
sage: f2 = 10*y - y^2
|
|
919
|
+
sage: f3 = 3*y^4 - 156*y^3 + 3036*y^2 - 26208*y
|
|
920
|
+
sage: f = piecewise([[(0,3), f1], [(3,10), f2], [(10,20), f3]])
|
|
921
|
+
sage: expected = [5, 12, 13, 14]
|
|
922
|
+
sage: all(abs(e-a) < 0.001 for e,a in zip(expected, f.critical_points()))
|
|
923
|
+
True
|
|
924
|
+
"""
|
|
925
|
+
from sage.calculus.calculus import maxima
|
|
926
|
+
x = self.default_variable()
|
|
927
|
+
crit_pts = []
|
|
928
|
+
for domain, f in parameters:
|
|
929
|
+
for interval in domain:
|
|
930
|
+
a = interval.lower()
|
|
931
|
+
b = interval.upper()
|
|
932
|
+
for root in maxima.allroots(SR(f).diff(x) == 0):
|
|
933
|
+
root = float(root.rhs())
|
|
934
|
+
if a < root < b:
|
|
935
|
+
crit_pts.append(root)
|
|
936
|
+
return crit_pts
|
|
937
|
+
|
|
938
|
+
def convolution(self, parameters, variable, other):
|
|
939
|
+
r"""
|
|
940
|
+
Return the convolution function,
|
|
941
|
+
`f*g(t)=\int_{-\infty}^\infty f(u)g(t-u)du`, for compactly
|
|
942
|
+
supported `f,g`.
|
|
943
|
+
|
|
944
|
+
EXAMPLES::
|
|
945
|
+
|
|
946
|
+
sage: x = PolynomialRing(QQ, 'x').gen()
|
|
947
|
+
|
|
948
|
+
Example 0::
|
|
949
|
+
|
|
950
|
+
sage: f = piecewise([[[0,1], 1]])
|
|
951
|
+
sage: g = f.convolution(f); g
|
|
952
|
+
piecewise(x|-->x on (0, 1],
|
|
953
|
+
x|-->-x + 2 on (1, 2]; x)
|
|
954
|
+
sage: h = f.convolution(g); h
|
|
955
|
+
piecewise(x|-->1/2*x^2 on (0, 1],
|
|
956
|
+
x|-->-x^2 + 3*x - 3/2 on (1, 2],
|
|
957
|
+
x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x)
|
|
958
|
+
|
|
959
|
+
Example 1::
|
|
960
|
+
|
|
961
|
+
sage: f = piecewise([[(0,1), 1], [(1,2), 2], [(2,3), 1]])
|
|
962
|
+
sage: g = f.convolution(f)
|
|
963
|
+
sage: h = f.convolution(g); h
|
|
964
|
+
piecewise(x|-->1/2*x^2 on (0, 1],
|
|
965
|
+
x|-->2*x^2 - 3*x + 3/2 on (1, 3],
|
|
966
|
+
x|-->-2*x^2 + 21*x - 69/2 on (3, 4],
|
|
967
|
+
x|-->-5*x^2 + 45*x - 165/2 on (4, 5],
|
|
968
|
+
x|-->-2*x^2 + 15*x - 15/2 on (5, 6],
|
|
969
|
+
x|-->2*x^2 - 33*x + 273/2 on (6, 8],
|
|
970
|
+
x|-->1/2*x^2 - 9*x + 81/2 on (8, 9]; x)
|
|
971
|
+
|
|
972
|
+
Example 2::
|
|
973
|
+
|
|
974
|
+
sage: f = piecewise([[(-1,1), 1]])
|
|
975
|
+
sage: g = piecewise([[(0,3), x]])
|
|
976
|
+
sage: f.convolution(g)
|
|
977
|
+
piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 1],
|
|
978
|
+
x|-->2*x on (1, 2],
|
|
979
|
+
x|-->-1/2*x^2 + x + 4 on (2, 4]; x)
|
|
980
|
+
sage: g = piecewise([[(0,3), 1], [(3,4), 2]])
|
|
981
|
+
sage: f.convolution(g)
|
|
982
|
+
piecewise(x|-->x + 1 on (-1, 1],
|
|
983
|
+
x|-->2 on (1, 2],
|
|
984
|
+
x|-->x on (2, 3],
|
|
985
|
+
x|-->-x + 6 on (3, 4],
|
|
986
|
+
x|-->-2*x + 10 on (4, 5]; x)
|
|
987
|
+
|
|
988
|
+
Some unbounded but convergent cases now work::
|
|
989
|
+
|
|
990
|
+
sage: p = piecewise([[(2,oo),exp(-x)]])
|
|
991
|
+
sage: q = piecewise([[[2,3],x]])
|
|
992
|
+
sage: p.convolution(q)
|
|
993
|
+
piecewise(x|-->(x - 3)*e^(-2) - e^(-x + 2) on (4, 5]; x)
|
|
994
|
+
sage: q.convolution(p)
|
|
995
|
+
piecewise(x|-->(x - 3)*e^(-2) - e^(-x + 2) on (4, 5]; x)
|
|
996
|
+
|
|
997
|
+
TESTS:
|
|
998
|
+
|
|
999
|
+
Check that the bugs raised in :issue:`12123` are fixed::
|
|
1000
|
+
|
|
1001
|
+
sage: f = piecewise([[(-2, 2), 2]])
|
|
1002
|
+
sage: g = piecewise([[(0, 2), 3/4]])
|
|
1003
|
+
sage: f.convolution(g)
|
|
1004
|
+
piecewise(x|-->3/2*x + 3 on (-2, 0],
|
|
1005
|
+
x|-->3 on (0, 2],
|
|
1006
|
+
x|-->-3/2*x + 6 on (2, 4]; x)
|
|
1007
|
+
sage: f = piecewise([[(-1, 1), 1]])
|
|
1008
|
+
sage: g = piecewise([[(0, 1), x], [(1, 2), -x + 2]])
|
|
1009
|
+
sage: f.convolution(g)
|
|
1010
|
+
piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 0],
|
|
1011
|
+
x|-->-1/2*x^2 + x + 1/2 on (0, 2],
|
|
1012
|
+
x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x)
|
|
1013
|
+
"""
|
|
1014
|
+
from sage.symbolic.integration.integral import definite_integral
|
|
1015
|
+
f = self
|
|
1016
|
+
g = other
|
|
1017
|
+
if not f.end_points() or not g.end_points():
|
|
1018
|
+
raise ValueError('one of the piecewise functions is nowhere defined')
|
|
1019
|
+
fd, f0 = parameters[0]
|
|
1020
|
+
gd, g0 = next(other.items())
|
|
1021
|
+
if len(f) == 1 == len(g):
|
|
1022
|
+
a1 = fd[0].lower()
|
|
1023
|
+
a2 = fd[0].upper()
|
|
1024
|
+
b1 = gd[0].lower()
|
|
1025
|
+
b2 = gd[0].upper()
|
|
1026
|
+
a1b1 = a1 + b1
|
|
1027
|
+
a2b2 = a2 + b2
|
|
1028
|
+
delta_a = a2 - a1
|
|
1029
|
+
delta_b = b2 - b1
|
|
1030
|
+
|
|
1031
|
+
# this fails in some unbounded cases:
|
|
1032
|
+
a1b2 = a1 + b2
|
|
1033
|
+
a2b1 = a2 + b1
|
|
1034
|
+
|
|
1035
|
+
todo = []
|
|
1036
|
+
if delta_a > delta_b:
|
|
1037
|
+
if a1b2 is not minus_infinity:
|
|
1038
|
+
todo.append((a1b1, a1b2, a1, variable - b1))
|
|
1039
|
+
todo.append((a1b2, a2b1, variable - b2, variable - b1))
|
|
1040
|
+
if a2b1 is not infinity:
|
|
1041
|
+
todo.append((a2b1, a2b2, variable - b2, a2))
|
|
1042
|
+
elif delta_a < delta_b:
|
|
1043
|
+
if a2b1 is not minus_infinity:
|
|
1044
|
+
todo.append((a1b1, a2b1, a1, variable - b1))
|
|
1045
|
+
todo.append((a2b1, a1b2, a1, a2))
|
|
1046
|
+
if a1b2 is not infinity:
|
|
1047
|
+
todo.append((a1b2, a2b2, variable - b2, a2))
|
|
1048
|
+
else:
|
|
1049
|
+
if a2b1 is not minus_infinity:
|
|
1050
|
+
todo.append((a1b1, a2b1, a1, variable - b1))
|
|
1051
|
+
todo.append((a2b1, a2b2, variable - b2, a2))
|
|
1052
|
+
|
|
1053
|
+
if not todo:
|
|
1054
|
+
raise ValueError("no domain of integration")
|
|
1055
|
+
|
|
1056
|
+
with SR.temp_var() as uu:
|
|
1057
|
+
i1 = f0.subs({variable: uu})
|
|
1058
|
+
i2 = g0.subs({variable: variable - uu})
|
|
1059
|
+
expr = i1 * i2
|
|
1060
|
+
h = piecewise([[(start, stop),
|
|
1061
|
+
definite_integral(expr, uu, mini, maxi)]
|
|
1062
|
+
for start, stop, mini, maxi in todo])
|
|
1063
|
+
flat_zero = piecewise([[(minus_infinity, infinity), 0]])
|
|
1064
|
+
return (flat_zero.piecewise_add(h)).unextend_zero() # why ?
|
|
1065
|
+
|
|
1066
|
+
z = piecewise([[(0, 0), 0]])
|
|
1067
|
+
for fpiece in f.pieces():
|
|
1068
|
+
for gpiece in g.pieces():
|
|
1069
|
+
h = gpiece.convolution(fpiece)
|
|
1070
|
+
z = z.piecewise_add(h)
|
|
1071
|
+
return z.unextend_zero()
|
|
1072
|
+
|
|
1073
|
+
def trapezoid(self, parameters, variable, N):
|
|
1074
|
+
"""
|
|
1075
|
+
Return the piecewise line function defined by the trapezoid rule
|
|
1076
|
+
for numerical integration based on a subdivision of each domain
|
|
1077
|
+
interval into N subintervals.
|
|
1078
|
+
|
|
1079
|
+
EXAMPLES::
|
|
1080
|
+
|
|
1081
|
+
sage: f = piecewise([[[0,1], x^2],
|
|
1082
|
+
....: [RealSet.open_closed(1,2), 5 - x^2]])
|
|
1083
|
+
sage: f.trapezoid(2)
|
|
1084
|
+
piecewise(x|-->1/2*x on (0, 1/2),
|
|
1085
|
+
x|-->3/2*x - 1/2 on (1/2, 1),
|
|
1086
|
+
x|-->7/2*x - 5/2 on (1, 3/2),
|
|
1087
|
+
x|-->-7/2*x + 8 on (3/2, 2); x)
|
|
1088
|
+
sage: f = piecewise([[[-1,1], 1 - x^2]])
|
|
1089
|
+
sage: f.trapezoid(4).integral(definite=True)
|
|
1090
|
+
5/4
|
|
1091
|
+
sage: f = piecewise([[[-1,1], 1/2 + x - x^3]]) ## example 3
|
|
1092
|
+
sage: f.trapezoid(6).integral(definite=True)
|
|
1093
|
+
1
|
|
1094
|
+
|
|
1095
|
+
TESTS:
|
|
1096
|
+
|
|
1097
|
+
Use variables or rings other than x (:issue:`13836`)::
|
|
1098
|
+
|
|
1099
|
+
sage: R.<y> = QQ[]
|
|
1100
|
+
sage: f1 = y^2
|
|
1101
|
+
sage: f2 = 5 - y^2
|
|
1102
|
+
sage: f = piecewise([[[0,1], f1], [RealSet.open_closed(1,2), f2]])
|
|
1103
|
+
sage: f.trapezoid(2)
|
|
1104
|
+
piecewise(y|-->1/2*y on (0, 1/2),
|
|
1105
|
+
y|-->3/2*y - 1/2 on (1/2, 1),
|
|
1106
|
+
y|-->7/2*y - 5/2 on (1, 3/2),
|
|
1107
|
+
y|-->-7/2*y + 8 on (3/2, 2); y)
|
|
1108
|
+
"""
|
|
1109
|
+
def func(x0, x1):
|
|
1110
|
+
f0, f1 = self(x0), self(x1)
|
|
1111
|
+
return [[(x0, x1), f0 + (f1-f0) * (x1-x0)**(-1)
|
|
1112
|
+
* (self.default_variable()-x0)]]
|
|
1113
|
+
rsum = []
|
|
1114
|
+
for domain, f in parameters:
|
|
1115
|
+
for interval in domain:
|
|
1116
|
+
a = interval.lower()
|
|
1117
|
+
b = interval.upper()
|
|
1118
|
+
h = (b-a)/N
|
|
1119
|
+
for i in range(N):
|
|
1120
|
+
x0 = a+i*h
|
|
1121
|
+
x1 = a+(i+1)*h
|
|
1122
|
+
rsum += func(x0, x1)
|
|
1123
|
+
return piecewise(rsum)
|
|
1124
|
+
|
|
1125
|
+
def laplace(self, parameters, variable, x='x', s='t'):
|
|
1126
|
+
r"""
|
|
1127
|
+
Return the Laplace transform of ``self`` with respect to the variable
|
|
1128
|
+
var.
|
|
1129
|
+
|
|
1130
|
+
INPUT:
|
|
1131
|
+
|
|
1132
|
+
- ``x`` -- variable of ``self``
|
|
1133
|
+
|
|
1134
|
+
- ``s`` -- variable of Laplace transform
|
|
1135
|
+
|
|
1136
|
+
We assume that a piecewise function is 0 outside of its domain and
|
|
1137
|
+
that the left-most endpoint of the domain is 0.
|
|
1138
|
+
|
|
1139
|
+
EXAMPLES::
|
|
1140
|
+
|
|
1141
|
+
sage: x, s, w = var('x, s, w')
|
|
1142
|
+
sage: f = piecewise([[(0,1), 1], [[1,2], 1 - x]])
|
|
1143
|
+
sage: f.laplace(x, s)
|
|
1144
|
+
-e^(-s)/s + (s + 1)*e^(-2*s)/s^2 + 1/s - e^(-s)/s^2
|
|
1145
|
+
sage: f.laplace(x, w)
|
|
1146
|
+
-e^(-w)/w + (w + 1)*e^(-2*w)/w^2 + 1/w - e^(-w)/w^2
|
|
1147
|
+
|
|
1148
|
+
::
|
|
1149
|
+
|
|
1150
|
+
sage: y, t = var('y, t')
|
|
1151
|
+
sage: f = piecewise([[[1,2], 1 - y]])
|
|
1152
|
+
sage: f.laplace(y, t)
|
|
1153
|
+
(t + 1)*e^(-2*t)/t^2 - e^(-t)/t^2
|
|
1154
|
+
|
|
1155
|
+
::
|
|
1156
|
+
|
|
1157
|
+
sage: s = var('s')
|
|
1158
|
+
sage: t = var('t')
|
|
1159
|
+
sage: f1(t) = -t
|
|
1160
|
+
sage: f2(t) = 2
|
|
1161
|
+
sage: f = piecewise([[[0,1], f1], [(1,infinity), f2]])
|
|
1162
|
+
sage: f.laplace(t, s)
|
|
1163
|
+
(s + 1)*e^(-s)/s^2 + 2*e^(-s)/s - 1/s^2
|
|
1164
|
+
"""
|
|
1165
|
+
from sage.symbolic.assumptions import assume, forget
|
|
1166
|
+
|
|
1167
|
+
x = SR.var(x)
|
|
1168
|
+
s = SR.var(s)
|
|
1169
|
+
assume(s > 0)
|
|
1170
|
+
exp_sx = (-s * x).exp()
|
|
1171
|
+
result = 0
|
|
1172
|
+
for domain, f in parameters:
|
|
1173
|
+
for interval in domain:
|
|
1174
|
+
a = interval.lower()
|
|
1175
|
+
b = interval.upper()
|
|
1176
|
+
result += (SR(f) * exp_sx).integral(x, a, b)
|
|
1177
|
+
forget(s > 0)
|
|
1178
|
+
return result
|
|
1179
|
+
|
|
1180
|
+
def fourier_series_cosine_coefficient(self, parameters,
|
|
1181
|
+
variable, n, L=None):
|
|
1182
|
+
r"""
|
|
1183
|
+
Return the `n`-th cosine coefficient of the Fourier series of
|
|
1184
|
+
the periodic function `f` extending the piecewise-defined
|
|
1185
|
+
function ``self``.
|
|
1186
|
+
|
|
1187
|
+
Given an integer `n\geq 0`, the `n`-th cosine coefficient of
|
|
1188
|
+
the Fourier series of `f` is defined by
|
|
1189
|
+
|
|
1190
|
+
.. MATH::
|
|
1191
|
+
|
|
1192
|
+
a_n = \frac{1}{L}\int_{-L}^L
|
|
1193
|
+
f(x)\cos\left(\frac{n\pi x}{L}\right) dx,
|
|
1194
|
+
|
|
1195
|
+
where `L` is the half-period of `f`. For `n\geq 1`, `a_n` is
|
|
1196
|
+
the coefficient of `\cos(n\pi x/L)` in the Fourier series of
|
|
1197
|
+
`f`, while `a_0` is twice the coefficient of the constant
|
|
1198
|
+
term `\cos(0 x)`, i.e. twice the mean value of `f` over one
|
|
1199
|
+
period (cf. :meth:`fourier_series_partial_sum`).
|
|
1200
|
+
|
|
1201
|
+
INPUT:
|
|
1202
|
+
|
|
1203
|
+
- ``n`` -- nonnegative integer
|
|
1204
|
+
|
|
1205
|
+
- ``L`` -- (default: ``None``) the half-period of `f`; if none
|
|
1206
|
+
is provided, `L` is assumed to be the half-width of the domain
|
|
1207
|
+
of ``self``
|
|
1208
|
+
|
|
1209
|
+
OUTPUT: the Fourier coefficient `a_n`, as defined above
|
|
1210
|
+
|
|
1211
|
+
EXAMPLES:
|
|
1212
|
+
|
|
1213
|
+
A triangle wave function of period 2::
|
|
1214
|
+
|
|
1215
|
+
sage: f = piecewise([((0,1), x), ((1,2), 2 - x)])
|
|
1216
|
+
sage: f.fourier_series_cosine_coefficient(0)
|
|
1217
|
+
1
|
|
1218
|
+
sage: f.fourier_series_cosine_coefficient(3)
|
|
1219
|
+
-4/9/pi^2
|
|
1220
|
+
|
|
1221
|
+
If the domain of the piecewise-defined function encompasses
|
|
1222
|
+
more than one period, the half-period must be passed as the
|
|
1223
|
+
second argument; for instance::
|
|
1224
|
+
|
|
1225
|
+
sage: f2 = piecewise([((0,1), x), ((1,2), 2 - x),
|
|
1226
|
+
....: ((2,3), x - 2), ((3,4), 2 - (x-2))])
|
|
1227
|
+
sage: bool(f2.restriction((0,2)) == f) # f2 extends f on (0,4)
|
|
1228
|
+
True
|
|
1229
|
+
sage: f2.fourier_series_cosine_coefficient(3, 1) # half-period = 1
|
|
1230
|
+
-4/9/pi^2
|
|
1231
|
+
|
|
1232
|
+
The default half-period is 2 and one has::
|
|
1233
|
+
|
|
1234
|
+
sage: f2.fourier_series_cosine_coefficient(3) # half-period = 2
|
|
1235
|
+
0
|
|
1236
|
+
|
|
1237
|
+
The Fourier coefficient `-4/(9\pi^2)` obtained above is actually
|
|
1238
|
+
recovered for `n=6`::
|
|
1239
|
+
|
|
1240
|
+
sage: f2.fourier_series_cosine_coefficient(6)
|
|
1241
|
+
-4/9/pi^2
|
|
1242
|
+
|
|
1243
|
+
Other examples::
|
|
1244
|
+
|
|
1245
|
+
sage: f(x) = x^2
|
|
1246
|
+
sage: f = piecewise([[(-1,1), f]])
|
|
1247
|
+
sage: f.fourier_series_cosine_coefficient(2)
|
|
1248
|
+
pi^(-2)
|
|
1249
|
+
sage: f1(x) = -1
|
|
1250
|
+
sage: f2(x) = 2
|
|
1251
|
+
sage: f = piecewise([[(-pi, pi/2), f1], [(pi/2, pi), f2]])
|
|
1252
|
+
sage: f.fourier_series_cosine_coefficient(5, pi)
|
|
1253
|
+
-3/5/pi
|
|
1254
|
+
"""
|
|
1255
|
+
from sage.functions.trig import cos
|
|
1256
|
+
from sage.symbolic.constants import pi
|
|
1257
|
+
L0 = (self.domain().sup() - self.domain().inf()) / 2
|
|
1258
|
+
if not L:
|
|
1259
|
+
L = L0
|
|
1260
|
+
else:
|
|
1261
|
+
m = L0 / L
|
|
1262
|
+
if not (m.is_integer() and m > 0):
|
|
1263
|
+
raise ValueError("the width of the domain of " +
|
|
1264
|
+
"{} is not a multiple ".format(self) +
|
|
1265
|
+
"of the given period")
|
|
1266
|
+
result = 0
|
|
1267
|
+
for domain, f in parameters:
|
|
1268
|
+
for interval in domain:
|
|
1269
|
+
a = interval.lower()
|
|
1270
|
+
b = interval.upper()
|
|
1271
|
+
result += (f*cos(pi*variable*n/L)).integrate(variable, a, b)
|
|
1272
|
+
return SR(result / L0).simplify_trig()
|
|
1273
|
+
|
|
1274
|
+
def fourier_series_sine_coefficient(self, parameters, variable,
|
|
1275
|
+
n, L=None):
|
|
1276
|
+
r"""
|
|
1277
|
+
Return the `n`-th sine coefficient of the Fourier series of
|
|
1278
|
+
the periodic function `f` extending the piecewise-defined
|
|
1279
|
+
function ``self``.
|
|
1280
|
+
|
|
1281
|
+
Given an integer `n\geq 0`, the `n`-th sine coefficient of
|
|
1282
|
+
the Fourier series of `f` is defined by
|
|
1283
|
+
|
|
1284
|
+
.. MATH::
|
|
1285
|
+
|
|
1286
|
+
b_n = \frac{1}{L}\int_{-L}^L
|
|
1287
|
+
f(x)\sin\left(\frac{n\pi x}{L}\right) dx,
|
|
1288
|
+
|
|
1289
|
+
where `L` is the half-period of `f`. The number `b_n` is
|
|
1290
|
+
the coefficient of `\sin(n\pi x/L)` in the Fourier
|
|
1291
|
+
series of `f` (cf. :meth:`fourier_series_partial_sum`).
|
|
1292
|
+
|
|
1293
|
+
INPUT:
|
|
1294
|
+
|
|
1295
|
+
- ``n`` -- nonnegative integer
|
|
1296
|
+
|
|
1297
|
+
- ``L`` -- (default: ``None``) the half-period of `f`; if none
|
|
1298
|
+
is provided, `L` is assumed to be the half-width of the domain
|
|
1299
|
+
of ``self``
|
|
1300
|
+
|
|
1301
|
+
OUTPUT: the Fourier coefficient `b_n`, as defined above
|
|
1302
|
+
|
|
1303
|
+
EXAMPLES:
|
|
1304
|
+
|
|
1305
|
+
A square wave function of period 2::
|
|
1306
|
+
|
|
1307
|
+
sage: f = piecewise([((-1,0), -1), ((0,1), 1)])
|
|
1308
|
+
sage: f.fourier_series_sine_coefficient(1)
|
|
1309
|
+
4/pi
|
|
1310
|
+
sage: f.fourier_series_sine_coefficient(2)
|
|
1311
|
+
0
|
|
1312
|
+
sage: f.fourier_series_sine_coefficient(3)
|
|
1313
|
+
4/3/pi
|
|
1314
|
+
|
|
1315
|
+
If the domain of the piecewise-defined function encompasses
|
|
1316
|
+
more than one period, the half-period must be passed as the
|
|
1317
|
+
second argument; for instance::
|
|
1318
|
+
|
|
1319
|
+
sage: f2 = piecewise([((-1,0), -1), ((0,1), 1),
|
|
1320
|
+
....: ((1,2), -1), ((2,3), 1)])
|
|
1321
|
+
sage: bool(f2.restriction((-1,1)) == f) # f2 extends f on (-1,3)
|
|
1322
|
+
True
|
|
1323
|
+
sage: f2.fourier_series_sine_coefficient(1, 1) # half-period = 1
|
|
1324
|
+
4/pi
|
|
1325
|
+
sage: f2.fourier_series_sine_coefficient(3, 1) # half-period = 1
|
|
1326
|
+
4/3/pi
|
|
1327
|
+
|
|
1328
|
+
The default half-period is 2 and one has::
|
|
1329
|
+
|
|
1330
|
+
sage: f2.fourier_series_sine_coefficient(1) # half-period = 2
|
|
1331
|
+
0
|
|
1332
|
+
sage: f2.fourier_series_sine_coefficient(3) # half-period = 2
|
|
1333
|
+
0
|
|
1334
|
+
|
|
1335
|
+
The Fourier coefficients obtained from ``f`` are actually
|
|
1336
|
+
recovered for `n=2` and `n=6` respectively::
|
|
1337
|
+
|
|
1338
|
+
sage: f2.fourier_series_sine_coefficient(2)
|
|
1339
|
+
4/pi
|
|
1340
|
+
sage: f2.fourier_series_sine_coefficient(6)
|
|
1341
|
+
4/3/pi
|
|
1342
|
+
"""
|
|
1343
|
+
from sage.functions.trig import sin
|
|
1344
|
+
from sage.symbolic.constants import pi
|
|
1345
|
+
L0 = (self.domain().sup() - self.domain().inf()) / 2
|
|
1346
|
+
if not L:
|
|
1347
|
+
L = L0
|
|
1348
|
+
else:
|
|
1349
|
+
m = L0 / L
|
|
1350
|
+
if not (m.is_integer() and m > 0):
|
|
1351
|
+
raise ValueError("the width of the domain of " +
|
|
1352
|
+
"{} is not a multiple ".format(self) +
|
|
1353
|
+
"of the given period")
|
|
1354
|
+
result = 0
|
|
1355
|
+
for domain, f in parameters:
|
|
1356
|
+
for interval in domain:
|
|
1357
|
+
a = interval.lower()
|
|
1358
|
+
b = interval.upper()
|
|
1359
|
+
result += (f*sin(pi*variable*n/L)).integrate(variable, a, b)
|
|
1360
|
+
return SR(result/L0).simplify_trig()
|
|
1361
|
+
|
|
1362
|
+
def fourier_series_partial_sum(self, parameters, variable, N,
|
|
1363
|
+
L=None):
|
|
1364
|
+
r"""
|
|
1365
|
+
Return the partial sum up to a given order of the Fourier series
|
|
1366
|
+
of the periodic function `f` extending the piecewise-defined
|
|
1367
|
+
function ``self``.
|
|
1368
|
+
|
|
1369
|
+
The Fourier partial sum of order `N` is defined as
|
|
1370
|
+
|
|
1371
|
+
.. MATH::
|
|
1372
|
+
|
|
1373
|
+
S_{N}(x) = \frac{a_0}{2} + \sum_{n=1}^{N} \left[
|
|
1374
|
+
a_n\cos\left(\frac{n\pi x}{L}\right)
|
|
1375
|
+
+ b_n\sin\left(\frac{n\pi x}{L}\right)\right],
|
|
1376
|
+
|
|
1377
|
+
where `L` is the half-period of `f` and the `a_n`'s and `b_n`'s
|
|
1378
|
+
are respectively the cosine coefficients and sine coefficients
|
|
1379
|
+
of the Fourier series of `f` (cf.
|
|
1380
|
+
:meth:`fourier_series_cosine_coefficient` and
|
|
1381
|
+
:meth:`fourier_series_sine_coefficient`).
|
|
1382
|
+
|
|
1383
|
+
INPUT:
|
|
1384
|
+
|
|
1385
|
+
- ``N`` -- positive integer; the order of the partial sum
|
|
1386
|
+
|
|
1387
|
+
- ``L`` -- (default: ``None``) the half-period of `f`; if none
|
|
1388
|
+
is provided, `L` is assumed to be the half-width of the domain
|
|
1389
|
+
of ``self``
|
|
1390
|
+
|
|
1391
|
+
OUTPUT:
|
|
1392
|
+
|
|
1393
|
+
- the partial sum `S_{N}(x)`, as a symbolic expression
|
|
1394
|
+
|
|
1395
|
+
EXAMPLES:
|
|
1396
|
+
|
|
1397
|
+
A square wave function of period 2::
|
|
1398
|
+
|
|
1399
|
+
sage: f = piecewise([((-1,0), -1), ((0,1), 1)])
|
|
1400
|
+
sage: f.fourier_series_partial_sum(5)
|
|
1401
|
+
4/5*sin(5*pi*x)/pi + 4/3*sin(3*pi*x)/pi + 4*sin(pi*x)/pi
|
|
1402
|
+
|
|
1403
|
+
If the domain of the piecewise-defined function encompasses
|
|
1404
|
+
more than one period, the half-period must be passed as the
|
|
1405
|
+
second argument; for instance::
|
|
1406
|
+
|
|
1407
|
+
sage: f2 = piecewise([((-1,0), -1), ((0,1), 1),
|
|
1408
|
+
....: ((1,2), -1), ((2,3), 1)])
|
|
1409
|
+
sage: bool(f2.restriction((-1,1)) == f) # f2 extends f on (-1,3)
|
|
1410
|
+
True
|
|
1411
|
+
sage: f2.fourier_series_partial_sum(5, 1) # half-period = 1
|
|
1412
|
+
4/5*sin(5*pi*x)/pi + 4/3*sin(3*pi*x)/pi + 4*sin(pi*x)/pi
|
|
1413
|
+
sage: bool(f2.fourier_series_partial_sum(5, 1) ==
|
|
1414
|
+
....: f.fourier_series_partial_sum(5))
|
|
1415
|
+
True
|
|
1416
|
+
|
|
1417
|
+
The default half-period is 2, so that skipping the second
|
|
1418
|
+
argument yields a different result::
|
|
1419
|
+
|
|
1420
|
+
sage: f2.fourier_series_partial_sum(5) # half-period = 2
|
|
1421
|
+
4*sin(pi*x)/pi
|
|
1422
|
+
|
|
1423
|
+
An example of partial sum involving both cosine and sine terms::
|
|
1424
|
+
|
|
1425
|
+
sage: f = piecewise([((-1,0), 0), ((0,1/2), 2*x),
|
|
1426
|
+
....: ((1/2,1), 2*(1-x))])
|
|
1427
|
+
sage: f.fourier_series_partial_sum(5)
|
|
1428
|
+
-2*cos(2*pi*x)/pi^2 + 4/25*sin(5*pi*x)/pi^2
|
|
1429
|
+
- 4/9*sin(3*pi*x)/pi^2 + 4*sin(pi*x)/pi^2 + 1/4
|
|
1430
|
+
"""
|
|
1431
|
+
from sage.symbolic.constants import pi
|
|
1432
|
+
from sage.functions.trig import cos, sin
|
|
1433
|
+
from sage.arith.srange import srange
|
|
1434
|
+
|
|
1435
|
+
if not L:
|
|
1436
|
+
L = (self.domain().sup() - self.domain().inf()) / 2
|
|
1437
|
+
x = self.default_variable()
|
|
1438
|
+
a0 = self.fourier_series_cosine_coefficient(0, L)
|
|
1439
|
+
result = a0/2 + sum([(self.fourier_series_cosine_coefficient(n, L)*cos(n*pi*x/L) +
|
|
1440
|
+
self.fourier_series_sine_coefficient(n, L)*sin(n*pi*x/L))
|
|
1441
|
+
for n in srange(1, N+1)])
|
|
1442
|
+
return SR(result).expand()
|
|
1443
|
+
|
|
1444
|
+
def _sympy_(self, parameters, variable):
|
|
1445
|
+
"""
|
|
1446
|
+
Convert this piecewise expression to its SymPy equivalent.
|
|
1447
|
+
|
|
1448
|
+
EXAMPLES::
|
|
1449
|
+
|
|
1450
|
+
sage: ex = piecewise([((0, 1), pi), ([1, 2], x)])
|
|
1451
|
+
sage: f = ex._sympy_(); f # needs sympy
|
|
1452
|
+
Piecewise((pi, (x > 0) & (x < 1)), (x, (x >= 1) & (x <= 2)))
|
|
1453
|
+
sage: f.diff() # needs sympy
|
|
1454
|
+
Piecewise((0, (x > 0) & (x < 1)), (1, (x >= 1) & (x <= 2)))
|
|
1455
|
+
|
|
1456
|
+
sage: ex = piecewise([((-100, -2), 1/x), ((1, +oo), cos(x))])
|
|
1457
|
+
sage: g = ex._sympy_(); g # needs sympy
|
|
1458
|
+
Piecewise((1/x, (x > -100) & (x < -2)), (cos(x), x > 1))
|
|
1459
|
+
sage: g.diff() # needs sympy
|
|
1460
|
+
Piecewise((-1/x**2, (x > -100) & (x < -2)), (-sin(x), x > 1))
|
|
1461
|
+
"""
|
|
1462
|
+
from sympy import Piecewise as pw
|
|
1463
|
+
args = [(func._sympy_(),
|
|
1464
|
+
domain._sympy_condition_(variable))
|
|
1465
|
+
for domain, func in parameters]
|
|
1466
|
+
return pw(*args)
|
|
1467
|
+
|
|
1468
|
+
def _giac_init_(self, parameters, variable):
|
|
1469
|
+
"""
|
|
1470
|
+
Convert this piecewise expression to its Giac equivalent.
|
|
1471
|
+
|
|
1472
|
+
Backward conversion is not yet implemented.
|
|
1473
|
+
|
|
1474
|
+
EXAMPLES::
|
|
1475
|
+
|
|
1476
|
+
sage: # needs giac
|
|
1477
|
+
sage: ex = piecewise([((0, 1), pi), ([1, 2], x)])
|
|
1478
|
+
sage: f = ex._giac_(); f
|
|
1479
|
+
piecewise(((sageVARx>0) and (1>sageVARx)),pi,((sageVARx>=1) and (2>=sageVARx)),sageVARx)
|
|
1480
|
+
sage: f.diff(x)
|
|
1481
|
+
piecewise(((sageVARx>0) and (1>sageVARx)),0,((sageVARx>=1) and (2>=sageVARx)),1)
|
|
1482
|
+
|
|
1483
|
+
sage: # needs giac
|
|
1484
|
+
sage: ex = piecewise([((-100, -2), 1/x), ((1, +oo), cos(x))])
|
|
1485
|
+
sage: g = ex._giac_(); g
|
|
1486
|
+
piecewise(((sageVARx>-100) and ((-2)>sageVARx)),1/sageVARx,sageVARx>1,cos(sageVARx))
|
|
1487
|
+
sage: g.diff(x)
|
|
1488
|
+
piecewise(((sageVARx>-100) and ((-2)>sageVARx)),-1/sageVARx^2,sageVARx>1,-sin(sageVARx))
|
|
1489
|
+
|
|
1490
|
+
TESTS::
|
|
1491
|
+
|
|
1492
|
+
sage: f = piecewise([([0,1], x), ((1,2), 3*x)])
|
|
1493
|
+
sage: a = libgiac(f) # random because verbose # needs sage.libs.giac
|
|
1494
|
+
sage: a # needs sage.libs.giac
|
|
1495
|
+
piecewise(((sageVARx>=0) and (1>=sageVARx)),sageVARx,((sageVARx>1) and (2>sageVARx)),sageVARx*3)
|
|
1496
|
+
"""
|
|
1497
|
+
from sage.misc.flatten import flatten
|
|
1498
|
+
args = [(domain._giac_condition_(variable),
|
|
1499
|
+
func._giac_init_())
|
|
1500
|
+
for domain, func in parameters]
|
|
1501
|
+
args = ",".join(flatten(args))
|
|
1502
|
+
return f"piecewise({args})"
|
|
1503
|
+
|
|
1504
|
+
|
|
1505
|
+
piecewise = PiecewiseFunction()
|