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,2754 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Continued fractions
|
|
4
|
+
|
|
5
|
+
A continued fraction is a representation of a real number in terms of a sequence
|
|
6
|
+
of integers denoted `[a_0; a_1, a_2, \ldots]`. The well known decimal expansion
|
|
7
|
+
is another way of representing a real number by a sequence of integers. The
|
|
8
|
+
value of a continued fraction is defined recursively as:
|
|
9
|
+
|
|
10
|
+
.. MATH::
|
|
11
|
+
|
|
12
|
+
[a_0; a_1, a_2, \ldots] = a_0 + \frac{1}{[a_1; a_2, \ldots]} = a_0 +
|
|
13
|
+
\frac{\displaystyle 1}
|
|
14
|
+
{\displaystyle a_1 + \frac{\displaystyle 1}
|
|
15
|
+
{\displaystyle a_2 + \frac{\displaystyle 1}
|
|
16
|
+
{\ldots}}}
|
|
17
|
+
|
|
18
|
+
In this expansion, all coefficients `a_n` are integers and only the value `a_0`
|
|
19
|
+
may be non positive. Note that `a_0` is nothing else but the floor (this remark
|
|
20
|
+
provides a way to build the continued fraction expansion from a given real
|
|
21
|
+
number). As examples
|
|
22
|
+
|
|
23
|
+
.. MATH::
|
|
24
|
+
|
|
25
|
+
\frac{45}{38} = 1 + \frac{\displaystyle 1}
|
|
26
|
+
{\displaystyle 5 + \frac{\displaystyle 1}
|
|
27
|
+
{\displaystyle 2 + \frac{\displaystyle 1}
|
|
28
|
+
{\displaystyle 3}}}
|
|
29
|
+
|
|
30
|
+
.. MATH::
|
|
31
|
+
|
|
32
|
+
\pi = 3 + \frac{\displaystyle 1}
|
|
33
|
+
{\displaystyle 7 + \frac{\displaystyle 1}
|
|
34
|
+
{\displaystyle 15 + \frac{\displaystyle 1}
|
|
35
|
+
{\displaystyle 1 + \frac{\displaystyle 1}
|
|
36
|
+
{\displaystyle 292 + \frac{\displaystyle 1}
|
|
37
|
+
{\ldots}}}}}
|
|
38
|
+
|
|
39
|
+
It is quite remarkable that
|
|
40
|
+
|
|
41
|
+
- any real number admits a unique continued fraction expansion
|
|
42
|
+
- finite expansions correspond to rationals
|
|
43
|
+
- ultimately periodic expansions correspond to quadratic numbers (ie numbers of
|
|
44
|
+
the form `a + b \sqrt{D}` with `a` and `b` rationals and `D` square free
|
|
45
|
+
positive integer)
|
|
46
|
+
- two real numbers `x` and `y` have the same tail (up to a shift) in their
|
|
47
|
+
continued fraction expansion if and only if there are integers `a,b,c,d` with
|
|
48
|
+
`|ad - bc| = 1` and such that `y = (ax + b) / (cx + d)`.
|
|
49
|
+
|
|
50
|
+
Moreover, the rational numbers obtained by truncation of the expansion of a real
|
|
51
|
+
number gives its so-called best approximations. For more informations on
|
|
52
|
+
continued fractions, you may have a look at :wikipedia:`Continued_fraction`.
|
|
53
|
+
|
|
54
|
+
EXAMPLES:
|
|
55
|
+
|
|
56
|
+
If you want to create the continued fraction of some real number you may either
|
|
57
|
+
use its method continued_fraction (if it exists) or call
|
|
58
|
+
:func:`continued_fraction`::
|
|
59
|
+
|
|
60
|
+
sage: (13/27).continued_fraction()
|
|
61
|
+
[0; 2, 13]
|
|
62
|
+
sage: 0 + 1/(2 + 1/13)
|
|
63
|
+
13/27
|
|
64
|
+
|
|
65
|
+
sage: continued_fraction(22/45)
|
|
66
|
+
[0; 2, 22]
|
|
67
|
+
sage: 0 + 1/(2 + 1/22)
|
|
68
|
+
22/45
|
|
69
|
+
|
|
70
|
+
sage: continued_fraction(pi) # needs sage.symbolic
|
|
71
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
72
|
+
sage: continued_fraction_list(pi, nterms=5) # needs sage.symbolic
|
|
73
|
+
[3, 7, 15, 1, 292]
|
|
74
|
+
|
|
75
|
+
sage: x = polygen(ZZ, 'x')
|
|
76
|
+
sage: K.<cbrt5> = NumberField(x^3 - 5, embedding=1.709) # needs sage.rings.number_field
|
|
77
|
+
sage: continued_fraction(cbrt5) # needs sage.rings.number_field
|
|
78
|
+
[1; 1, 2, 2, 4, 3, 3, 1, 5, 1, 1, 4, 10, 17, 1, 14, 1, 1, 3052, 1, ...]
|
|
79
|
+
|
|
80
|
+
It is also possible to create a continued fraction from a list of partial
|
|
81
|
+
quotients::
|
|
82
|
+
|
|
83
|
+
sage: continued_fraction([-3,1,2,3,4,1,2])
|
|
84
|
+
[-3; 1, 2, 3, 4, 1, 2]
|
|
85
|
+
|
|
86
|
+
Even infinite::
|
|
87
|
+
|
|
88
|
+
sage: w = words.ThueMorseWord([1,2]); w # needs sage.combinat
|
|
89
|
+
word: 1221211221121221211212211221211221121221...
|
|
90
|
+
sage: continued_fraction(w) # needs sage.combinat
|
|
91
|
+
[1; 2, 2, 1, 2, 1, 1, 2, 2, 1...]
|
|
92
|
+
|
|
93
|
+
To go back and forth between the value (as a real number) and the partial
|
|
94
|
+
quotients (seen as a finite or infinite list) you can use the methods
|
|
95
|
+
``quotients`` and ``value``::
|
|
96
|
+
|
|
97
|
+
sage: cf = (13/27).continued_fraction()
|
|
98
|
+
sage: cf.quotients()
|
|
99
|
+
[0, 2, 13]
|
|
100
|
+
sage: cf.value()
|
|
101
|
+
13/27
|
|
102
|
+
|
|
103
|
+
sage: cf = continued_fraction(pi) # needs sage.symbolic
|
|
104
|
+
sage: cf.quotients() # needs sage.symbolic
|
|
105
|
+
lazy list [3, 7, 15, ...]
|
|
106
|
+
sage: cf.value() # needs sage.symbolic
|
|
107
|
+
pi
|
|
108
|
+
|
|
109
|
+
sage: # needs sage.combinat
|
|
110
|
+
sage: w = words.FibonacciWord([1,2])
|
|
111
|
+
sage: cf = continued_fraction(w)
|
|
112
|
+
sage: cf.quotients()
|
|
113
|
+
word: 1211212112112121121211211212112112121121...
|
|
114
|
+
sage: v = cf.value(); v
|
|
115
|
+
1.387954587967143?
|
|
116
|
+
sage: v.n(digits=100)
|
|
117
|
+
1.387954587967142336919313859873185477878152452498532271894917289826418577622648932169885237034242967
|
|
118
|
+
sage: v.continued_fraction()
|
|
119
|
+
[1; 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2...]
|
|
120
|
+
|
|
121
|
+
Recall that quadratic numbers correspond to ultimately periodic continued
|
|
122
|
+
fractions. For them special methods give access to preperiod and period::
|
|
123
|
+
|
|
124
|
+
sage: # needs sage.rings.number_field
|
|
125
|
+
sage: K.<sqrt2> = QuadraticField(2)
|
|
126
|
+
sage: cf = continued_fraction(sqrt2); cf
|
|
127
|
+
[1; (2)*]
|
|
128
|
+
sage: cf.value()
|
|
129
|
+
sqrt2
|
|
130
|
+
sage: cf.preperiod()
|
|
131
|
+
(1,)
|
|
132
|
+
sage: cf.period()
|
|
133
|
+
(2,)
|
|
134
|
+
|
|
135
|
+
sage: cf = (3*sqrt2 + 1/2).continued_fraction(); cf # needs sage.rings.number_field
|
|
136
|
+
[4; (1, 2, 1, 7)*]
|
|
137
|
+
|
|
138
|
+
sage: cf = continued_fraction([(1,2,3),(1,4)]); cf
|
|
139
|
+
[1; 2, 3, (1, 4)*]
|
|
140
|
+
sage: cf.value() # needs sage.rings.number_field
|
|
141
|
+
-2/23*sqrt2 + 36/23
|
|
142
|
+
|
|
143
|
+
On the following we can remark how the tail may change even in the same
|
|
144
|
+
quadratic field::
|
|
145
|
+
|
|
146
|
+
sage: for i in range(20): print(continued_fraction(i*sqrt2)) # needs sage.rings.number_field
|
|
147
|
+
[0]
|
|
148
|
+
[1; (2)*]
|
|
149
|
+
[2; (1, 4)*]
|
|
150
|
+
[4; (4, 8)*]
|
|
151
|
+
[5; (1, 1, 1, 10)*]
|
|
152
|
+
[7; (14)*]
|
|
153
|
+
...
|
|
154
|
+
[24; (24, 48)*]
|
|
155
|
+
[25; (2, 5, 6, 5, 2, 50)*]
|
|
156
|
+
[26; (1, 6, 1, 2, 3, 2, 26, 2, 3, 2, 1, 6, 1, 52)*]
|
|
157
|
+
|
|
158
|
+
Nevertheless, the tail is preserved under invertible integer homographies::
|
|
159
|
+
|
|
160
|
+
sage: # needs sage.modular sage.rings.number_field
|
|
161
|
+
sage: apply_homography = lambda m,z: (m[0,0]*z + m[0,1]) / (m[1,0]*z + m[1,1])
|
|
162
|
+
sage: m1 = SL2Z([60,13,83,18])
|
|
163
|
+
sage: m2 = SL2Z([27,80,28,83])
|
|
164
|
+
sage: a = sqrt2/3
|
|
165
|
+
sage: a.continued_fraction()
|
|
166
|
+
[0; 2, (8, 4)*]
|
|
167
|
+
sage: b = apply_homography(m1, a)
|
|
168
|
+
sage: b.continued_fraction()
|
|
169
|
+
[0; 1, 2, 1, 1, 1, 1, 6, (8, 4)*]
|
|
170
|
+
sage: c = apply_homography(m2, a)
|
|
171
|
+
sage: c.continued_fraction()
|
|
172
|
+
[0; 1, 26, 1, 2, 2, (8, 4)*]
|
|
173
|
+
sage: d = apply_homography(m1**2*m2**3, a)
|
|
174
|
+
sage: d.continued_fraction()
|
|
175
|
+
[0; 1, 2, 1, 1, 1, 1, 5, 2, 1, 1, 1, 1, 5, 26, 1, 2, 1, 26, 1, 2, 1, 26, 1, 2, 2, (8, 4)*]
|
|
176
|
+
|
|
177
|
+
.. TODO::
|
|
178
|
+
|
|
179
|
+
- Improve numerical approximation (the method
|
|
180
|
+
:meth:`~ContinuedFraction_base._mpfr_` is quite slow compared to the
|
|
181
|
+
same method for an element of a number field)
|
|
182
|
+
|
|
183
|
+
- Make a class for generalized continued fractions of the form `a_0 +
|
|
184
|
+
b_0/(a_1 + b_1/(...))` (the standard continued fractions are when all
|
|
185
|
+
`b_n= 1` while the Hirzebruch-Jung continued fractions are the one for
|
|
186
|
+
which `b_n = -1` for all `n`). See
|
|
187
|
+
:wikipedia:`Generalized_continued_fraction`.
|
|
188
|
+
|
|
189
|
+
- look at the function ContinuedFractionApproximationOfRoot in GAP
|
|
190
|
+
|
|
191
|
+
AUTHORS:
|
|
192
|
+
|
|
193
|
+
- Vincent Delecroix (2014): cleaning, refactorisation, documentation from the
|
|
194
|
+
old implementation in ``contfrac`` (:issue:`14567`).
|
|
195
|
+
"""
|
|
196
|
+
# ****************************************************************************
|
|
197
|
+
# Copyright (C) 2007 William Stein <wstein@gmail.com>
|
|
198
|
+
# Copyright (C) 2014-2020 Vincent Delecroix <20100.delecroix@gmail.com>
|
|
199
|
+
# Copyright (C) 2020 Frédéric Chapoton <chapoton@math.unistra.fr>
|
|
200
|
+
# Copyright (C) 2016 Moritz Firsching <moritz@math.fu-berlin.de>
|
|
201
|
+
#
|
|
202
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
203
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
204
|
+
# the License, or (at your option) any later version.
|
|
205
|
+
# https://www.gnu.org/licenses/
|
|
206
|
+
# ****************************************************************************
|
|
207
|
+
|
|
208
|
+
import numbers
|
|
209
|
+
|
|
210
|
+
import sage.rings.abc
|
|
211
|
+
|
|
212
|
+
from sage.misc.lazy_import import lazy_import
|
|
213
|
+
from sage.rings.infinity import Infinity
|
|
214
|
+
from sage.rings.integer import Integer
|
|
215
|
+
from sage.rings.integer_ring import ZZ
|
|
216
|
+
from sage.structure.richcmp import rich_to_bool, richcmp_method
|
|
217
|
+
from sage.structure.sage_object import SageObject
|
|
218
|
+
|
|
219
|
+
lazy_import('sage.combinat.words.abstract_word', 'Word_class')
|
|
220
|
+
lazy_import('sage.combinat.words.finite_word', 'FiniteWord_class')
|
|
221
|
+
lazy_import('sage.combinat.words.infinite_word', 'InfiniteWord_class')
|
|
222
|
+
lazy_import('sage.combinat.words.word', 'Word')
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
ZZ_0 = Integer(0)
|
|
226
|
+
ZZ_1 = Integer(1)
|
|
227
|
+
ZZ_m1 = Integer(-1)
|
|
228
|
+
ZZ_2 = Integer(2)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def last_two_convergents(x):
|
|
232
|
+
"""
|
|
233
|
+
Given the list ``x`` that consists of numbers, return the two last
|
|
234
|
+
convergents `p_{n-1}, q_{n-1}, p_n, q_n`.
|
|
235
|
+
|
|
236
|
+
This function is principally used to compute the value of a ultimately
|
|
237
|
+
periodic continued fraction.
|
|
238
|
+
|
|
239
|
+
OUTPUT: a 4-tuple of Sage integers
|
|
240
|
+
|
|
241
|
+
EXAMPLES::
|
|
242
|
+
|
|
243
|
+
sage: from sage.rings.continued_fraction import last_two_convergents
|
|
244
|
+
sage: last_two_convergents([])
|
|
245
|
+
(0, 1, 1, 0)
|
|
246
|
+
sage: last_two_convergents([0])
|
|
247
|
+
(1, 0, 0, 1)
|
|
248
|
+
sage: last_two_convergents([-1,1,3,2])
|
|
249
|
+
(-1, 4, -2, 9)
|
|
250
|
+
|
|
251
|
+
TESTS::
|
|
252
|
+
|
|
253
|
+
sage: all(type(x) is Integer for x in last_two_convergents([]))
|
|
254
|
+
True
|
|
255
|
+
"""
|
|
256
|
+
p0, p1 = ZZ_0, ZZ_1
|
|
257
|
+
q0, q1 = ZZ_1, ZZ_0
|
|
258
|
+
for a in x:
|
|
259
|
+
p0, p1 = p1, a * p1 + p0
|
|
260
|
+
q0, q1 = q1, a * q1 + q0
|
|
261
|
+
return p0, q0, p1, q1
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def rat_interval_cf_list(r1, r2):
|
|
265
|
+
r"""
|
|
266
|
+
Return the common prefix of the rationals ``r1`` and ``r2`` seen as
|
|
267
|
+
continued fractions.
|
|
268
|
+
|
|
269
|
+
OUTPUT: list of Sage integers
|
|
270
|
+
|
|
271
|
+
EXAMPLES::
|
|
272
|
+
|
|
273
|
+
sage: from sage.rings.continued_fraction import rat_interval_cf_list
|
|
274
|
+
sage: rat_interval_cf_list(257/113, 5224/2297)
|
|
275
|
+
[2, 3, 1, 1, 1, 4]
|
|
276
|
+
sage: for prec in range(10,54): # needs sage.rings.real_interval_field
|
|
277
|
+
....: R = RealIntervalField(prec)
|
|
278
|
+
....: for _ in range(100):
|
|
279
|
+
....: x = R.random_element() * R.random_element() + R.random_element() / 100
|
|
280
|
+
....: l = x.lower().exact_rational()
|
|
281
|
+
....: u = x.upper().exact_rational()
|
|
282
|
+
....: if l.floor() != u.floor():
|
|
283
|
+
....: continue
|
|
284
|
+
....: cf = rat_interval_cf_list(l,u)
|
|
285
|
+
....: a = continued_fraction(cf).value()
|
|
286
|
+
....: b = continued_fraction(cf+[1]).value()
|
|
287
|
+
....: if a > b:
|
|
288
|
+
....: a,b = b,a
|
|
289
|
+
....: assert a <= l
|
|
290
|
+
....: assert b >= u
|
|
291
|
+
"""
|
|
292
|
+
l = []
|
|
293
|
+
c1 = r1.floor()
|
|
294
|
+
c2 = r2.floor()
|
|
295
|
+
while c1 == c2:
|
|
296
|
+
l.append(c1)
|
|
297
|
+
r1 -= c1
|
|
298
|
+
if not r1:
|
|
299
|
+
break
|
|
300
|
+
r2 -= c2
|
|
301
|
+
if not r2:
|
|
302
|
+
break
|
|
303
|
+
|
|
304
|
+
r1 = ~r1
|
|
305
|
+
r2 = ~r2
|
|
306
|
+
|
|
307
|
+
c1 = r1.floor()
|
|
308
|
+
c2 = r2.floor()
|
|
309
|
+
return l
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
@richcmp_method
|
|
313
|
+
class ContinuedFraction_base(SageObject):
|
|
314
|
+
r"""
|
|
315
|
+
Base class for (standard) continued fractions.
|
|
316
|
+
|
|
317
|
+
If you want to implement your own continued fraction, simply derived from
|
|
318
|
+
this class and implement the following methods:
|
|
319
|
+
|
|
320
|
+
- ``def quotient(self, n)``: return the ``n``-th quotient of ``self`` as a
|
|
321
|
+
Sage integer
|
|
322
|
+
|
|
323
|
+
- ``def length(self)``: the number of partial quotients of ``self`` as a
|
|
324
|
+
Sage integer or ``Infinity``.
|
|
325
|
+
|
|
326
|
+
and optionally:
|
|
327
|
+
|
|
328
|
+
- ``def value(self)``: return the value of ``self`` (an exact real number)
|
|
329
|
+
|
|
330
|
+
This base class will provide:
|
|
331
|
+
|
|
332
|
+
- computation of convergents in :meth:`convergent`, :meth:`numerator` and
|
|
333
|
+
:meth:`denominator`
|
|
334
|
+
|
|
335
|
+
- comparison with other continued fractions (see :meth:`__richcmp__`)
|
|
336
|
+
|
|
337
|
+
- elementary arithmetic function :meth:`floor`, :meth:`ceil`, :meth:`sign`
|
|
338
|
+
|
|
339
|
+
- accurate numerical approximations :meth:`_mpfr_`
|
|
340
|
+
|
|
341
|
+
All other methods, in particular the ones involving binary operations like
|
|
342
|
+
sum or product, rely on the optional method :meth:`value` (and not on
|
|
343
|
+
convergents) and may fail at execution if it is not implemented.
|
|
344
|
+
"""
|
|
345
|
+
def __init__(self):
|
|
346
|
+
r"""
|
|
347
|
+
INPUT:
|
|
348
|
+
|
|
349
|
+
- ``parent`` -- the parent of ``self``
|
|
350
|
+
|
|
351
|
+
TESTS::
|
|
352
|
+
|
|
353
|
+
sage: TestSuite(continued_fraction(3)).run()
|
|
354
|
+
"""
|
|
355
|
+
self._pn = [ZZ_0, ZZ_1]
|
|
356
|
+
self._qn = [ZZ_1, ZZ_0]
|
|
357
|
+
|
|
358
|
+
def str(self, nterms=10, unicode=False, join=True):
|
|
359
|
+
r"""
|
|
360
|
+
Return a string representing this continued fraction.
|
|
361
|
+
|
|
362
|
+
INPUT:
|
|
363
|
+
|
|
364
|
+
- ``nterms`` -- the maximum number of terms to use
|
|
365
|
+
|
|
366
|
+
- ``unicode`` -- (default: ``False``) whether to use unicode character
|
|
367
|
+
|
|
368
|
+
- ``join`` -- (default: ``True``) if ``False`` instead of returning a
|
|
369
|
+
string return a list of string, each of them representing a line
|
|
370
|
+
|
|
371
|
+
EXAMPLES::
|
|
372
|
+
|
|
373
|
+
sage: print(continued_fraction(pi).str()) # needs sage.symbolic
|
|
374
|
+
1
|
|
375
|
+
3 + ----------------------------------------------------
|
|
376
|
+
1
|
|
377
|
+
7 + -----------------------------------------------
|
|
378
|
+
1
|
|
379
|
+
15 + -----------------------------------------
|
|
380
|
+
1
|
|
381
|
+
1 + ------------------------------------
|
|
382
|
+
1
|
|
383
|
+
292 + -----------------------------
|
|
384
|
+
1
|
|
385
|
+
1 + ------------------------
|
|
386
|
+
1
|
|
387
|
+
1 + -------------------
|
|
388
|
+
1
|
|
389
|
+
1 + --------------
|
|
390
|
+
1
|
|
391
|
+
2 + ---------
|
|
392
|
+
1 + ...
|
|
393
|
+
sage: print(continued_fraction(pi).str(nterms=1)) # needs sage.symbolic
|
|
394
|
+
3 + ...
|
|
395
|
+
sage: print(continued_fraction(pi).str(nterms=2)) # needs sage.symbolic
|
|
396
|
+
1
|
|
397
|
+
3 + ---------
|
|
398
|
+
7 + ...
|
|
399
|
+
|
|
400
|
+
sage: print(continued_fraction(243/354).str())
|
|
401
|
+
1
|
|
402
|
+
-----------------------
|
|
403
|
+
1
|
|
404
|
+
1 + ------------------
|
|
405
|
+
1
|
|
406
|
+
2 + -------------
|
|
407
|
+
1
|
|
408
|
+
5 + --------
|
|
409
|
+
1
|
|
410
|
+
3 + ---
|
|
411
|
+
2
|
|
412
|
+
sage: continued_fraction(243/354).str(join=False)
|
|
413
|
+
[' 1 ',
|
|
414
|
+
'-----------------------',
|
|
415
|
+
' 1 ',
|
|
416
|
+
' 1 + ------------------',
|
|
417
|
+
' 1 ',
|
|
418
|
+
' 2 + -------------',
|
|
419
|
+
' 1 ',
|
|
420
|
+
' 5 + --------',
|
|
421
|
+
' 1 ',
|
|
422
|
+
' 3 + ---',
|
|
423
|
+
' 2 ']
|
|
424
|
+
|
|
425
|
+
sage: print(continued_fraction(243/354).str(unicode=True))
|
|
426
|
+
1
|
|
427
|
+
───────────────────────
|
|
428
|
+
1
|
|
429
|
+
1 + ──────────────────
|
|
430
|
+
1
|
|
431
|
+
2 + ─────────────
|
|
432
|
+
1
|
|
433
|
+
5 + ────────
|
|
434
|
+
1
|
|
435
|
+
3 + ───
|
|
436
|
+
2
|
|
437
|
+
"""
|
|
438
|
+
nterms = int(nterms)
|
|
439
|
+
if nterms < 0:
|
|
440
|
+
raise ValueError("nterms must be positive")
|
|
441
|
+
|
|
442
|
+
if unicode:
|
|
443
|
+
import unicodedata
|
|
444
|
+
frac = unicodedata.lookup('BOX DRAWINGS LIGHT HORIZONTAL')
|
|
445
|
+
else:
|
|
446
|
+
frac = '-'
|
|
447
|
+
|
|
448
|
+
# get the partial quotients
|
|
449
|
+
cf = [self.quotient(i) for i in range(nterms)]
|
|
450
|
+
continued = self.quotient(nterms) is not Infinity
|
|
451
|
+
while cf[-1] is Infinity:
|
|
452
|
+
cf.pop()
|
|
453
|
+
|
|
454
|
+
# write the lines starting from the end
|
|
455
|
+
a = cf.pop()
|
|
456
|
+
lines = [' {} + ... '.format(a) if continued else ' {} '.format(a)]
|
|
457
|
+
w = len(lines[0])
|
|
458
|
+
for a in reversed(cf):
|
|
459
|
+
s = ' {} + '.format(a) if a else ' '
|
|
460
|
+
w1 = len(s)
|
|
461
|
+
s += frac * w
|
|
462
|
+
lines.append(s)
|
|
463
|
+
lines.append(' ' * w1 + '{:^{width}}'.format(1, width=w))
|
|
464
|
+
w += w1
|
|
465
|
+
|
|
466
|
+
# change the order
|
|
467
|
+
lines.reverse()
|
|
468
|
+
|
|
469
|
+
# remove extra whitespaces and equalize the width
|
|
470
|
+
if len(lines) == 1:
|
|
471
|
+
lines[0] = lines[0].strip()
|
|
472
|
+
else:
|
|
473
|
+
lines[0] = lines[0][1:]
|
|
474
|
+
lines[1] = lines[1][1:]
|
|
475
|
+
w = len(lines[0])
|
|
476
|
+
for i, l in enumerate(lines):
|
|
477
|
+
lines[i] = ' ' * (w - len(l)) + l
|
|
478
|
+
|
|
479
|
+
return '\n'.join(lines) if join else lines
|
|
480
|
+
|
|
481
|
+
def _ascii_art_(self):
|
|
482
|
+
r"""
|
|
483
|
+
EXAMPLES::
|
|
484
|
+
|
|
485
|
+
sage: ascii_art(continued_fraction(43/30))
|
|
486
|
+
1
|
|
487
|
+
1 + -------------
|
|
488
|
+
1
|
|
489
|
+
2 + --------
|
|
490
|
+
1
|
|
491
|
+
3 + ---
|
|
492
|
+
4
|
|
493
|
+
"""
|
|
494
|
+
from sage.typeset.ascii_art import AsciiArt
|
|
495
|
+
return AsciiArt(self.str(unicode=False, join=False))
|
|
496
|
+
|
|
497
|
+
def _unicode_art_(self):
|
|
498
|
+
r"""
|
|
499
|
+
EXAMPLES::
|
|
500
|
+
|
|
501
|
+
sage: unicode_art(continued_fraction(43/30))
|
|
502
|
+
1
|
|
503
|
+
1 + ─────────────
|
|
504
|
+
1
|
|
505
|
+
2 + ────────
|
|
506
|
+
1
|
|
507
|
+
3 + ───
|
|
508
|
+
4
|
|
509
|
+
"""
|
|
510
|
+
from sage.typeset.unicode_art import UnicodeArt
|
|
511
|
+
return UnicodeArt(self.str(unicode=True, join=False))
|
|
512
|
+
|
|
513
|
+
def _latex_(self, nterms=10):
|
|
514
|
+
r"""
|
|
515
|
+
EXAMPLES::
|
|
516
|
+
|
|
517
|
+
sage: cf_pi = continued_fraction(pi) # needs sage.symbolic
|
|
518
|
+
sage: latex(cf_pi) # needs sage.symbolic
|
|
519
|
+
3
|
|
520
|
+
+ \frac{\displaystyle 1}{\displaystyle 7
|
|
521
|
+
+ \frac{\displaystyle 1}{\displaystyle 15
|
|
522
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
523
|
+
+ \frac{\displaystyle 1}{\displaystyle 292
|
|
524
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
525
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
526
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
527
|
+
+ \frac{\displaystyle 1}{\displaystyle 2
|
|
528
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
529
|
+
+ \frac{\displaystyle 1}{\displaystyle \dots}}}}}}}}}}
|
|
530
|
+
sage: print(cf_pi._latex_(nterms=3)) # needs sage.symbolic
|
|
531
|
+
3
|
|
532
|
+
+ \frac{\displaystyle 1}{\displaystyle 7
|
|
533
|
+
+ \frac{\displaystyle 1}{\displaystyle 15
|
|
534
|
+
+ \frac{\displaystyle 1}{\displaystyle \dots}}}
|
|
535
|
+
"""
|
|
536
|
+
nterms = int(nterms)
|
|
537
|
+
if nterms <= 0:
|
|
538
|
+
raise ValueError("nterms must be positive")
|
|
539
|
+
v = [self.quotient(i) for i in range(nterms + 1)]
|
|
540
|
+
s = str(v[0]) + '\n'
|
|
541
|
+
for i in range(1, min(len(v) - 1, nterms)):
|
|
542
|
+
s += '+ \\frac{\\displaystyle 1}{\\displaystyle %s\n' % v[i]
|
|
543
|
+
s += '+ \\frac{\\displaystyle 1}{\\displaystyle \\dots'
|
|
544
|
+
s += '}' * (len(v) - 1)
|
|
545
|
+
return s
|
|
546
|
+
|
|
547
|
+
def __abs__(self):
|
|
548
|
+
"""
|
|
549
|
+
Return absolute value of ``self``.
|
|
550
|
+
|
|
551
|
+
EXAMPLES::
|
|
552
|
+
|
|
553
|
+
sage: a = continued_fraction(-17/389); a
|
|
554
|
+
[-1; 1, 21, 1, 7, 2]
|
|
555
|
+
sage: abs(a)
|
|
556
|
+
[0; 22, 1, 7, 2]
|
|
557
|
+
sage: QQ(abs(a))
|
|
558
|
+
17/389
|
|
559
|
+
"""
|
|
560
|
+
if self.quotient(0) >= 0:
|
|
561
|
+
return self
|
|
562
|
+
return -self
|
|
563
|
+
|
|
564
|
+
def __richcmp__(self, other, op):
|
|
565
|
+
"""
|
|
566
|
+
Rich comparison.
|
|
567
|
+
|
|
568
|
+
EXAMPLES::
|
|
569
|
+
|
|
570
|
+
sage: a = continued_fraction(-17/389)
|
|
571
|
+
sage: b = continued_fraction(1/389)
|
|
572
|
+
sage: c = continued_fraction([(),(1,)]) # the golden ratio
|
|
573
|
+
sage: d = continued_fraction([(-1,),(1,)])
|
|
574
|
+
sage: d < a and a < b and b < c
|
|
575
|
+
True
|
|
576
|
+
sage: d >= a
|
|
577
|
+
False
|
|
578
|
+
sage: d == d
|
|
579
|
+
True
|
|
580
|
+
|
|
581
|
+
sage: a == 'nothing'
|
|
582
|
+
False
|
|
583
|
+
"""
|
|
584
|
+
if not isinstance(other, ContinuedFraction_base):
|
|
585
|
+
return NotImplemented
|
|
586
|
+
|
|
587
|
+
i = 0
|
|
588
|
+
while True:
|
|
589
|
+
a = self.quotient(i)
|
|
590
|
+
b = other.quotient(i)
|
|
591
|
+
if a > b:
|
|
592
|
+
return rich_to_bool(op, -1 if i % 2 else 1)
|
|
593
|
+
if b > a:
|
|
594
|
+
return rich_to_bool(op, 1 if i % 2 else -1)
|
|
595
|
+
if a == ZZ_0 and b == ZZ_0 and i: # rational case
|
|
596
|
+
return rich_to_bool(op, 0)
|
|
597
|
+
i += 1
|
|
598
|
+
|
|
599
|
+
def _mpfr_(self, R):
|
|
600
|
+
r"""
|
|
601
|
+
Return a correctly-rounded numerical approximation of ``self``
|
|
602
|
+
in the real mpfr ring ``R``.
|
|
603
|
+
|
|
604
|
+
EXAMPLES::
|
|
605
|
+
|
|
606
|
+
sage: continued_fraction(1/2).n() # needs sage.rings.real_mpfr
|
|
607
|
+
0.500000000000000
|
|
608
|
+
sage: continued_fraction([0,4]).n() # needs sage.rings.real_mpfr
|
|
609
|
+
0.250000000000000
|
|
610
|
+
sage: continued_fraction([12,1,3,4,2,2,3,1,2]).n(digits=4) # needs sage.rings.real_mpfr
|
|
611
|
+
12.76
|
|
612
|
+
|
|
613
|
+
sage: continued_fraction(12/7).n(digits=13) == (12/7).n(digits=13) # needs sage.rings.real_mpfr
|
|
614
|
+
True
|
|
615
|
+
sage: continued_fraction(-14/333).n(digits=21) == (-14/333).n(digits=21) # needs sage.rings.real_mpfr
|
|
616
|
+
True
|
|
617
|
+
|
|
618
|
+
sage: # needs sage.symbolic
|
|
619
|
+
sage: a = (106*pi - 333) / (355 - 113*pi) - 292
|
|
620
|
+
sage: cf = continued_fraction(a); cf
|
|
621
|
+
[0; 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, 1, 84, 2, 1, ...]
|
|
622
|
+
sage: cf.n(digits=3)
|
|
623
|
+
0.635
|
|
624
|
+
sage: cf.n(digits=4)
|
|
625
|
+
0.6346
|
|
626
|
+
sage: cf.n(digits=5)
|
|
627
|
+
0.63459
|
|
628
|
+
sage: cf.n(digits=6)
|
|
629
|
+
0.634591
|
|
630
|
+
sage: cf.n(digits=7)
|
|
631
|
+
0.6345910
|
|
632
|
+
sage: cf.n(digits=8)
|
|
633
|
+
0.63459101
|
|
634
|
+
|
|
635
|
+
sage: # needs sage.rings.number_field
|
|
636
|
+
sage: x = polygen(ZZ, 'x')
|
|
637
|
+
sage: K.<a> = NumberField(x^3 - 2, 'a', embedding=1.25)
|
|
638
|
+
sage: b = 504/253*a^2 + 635/253*a + 661/253
|
|
639
|
+
sage: cf = continued_fraction(b); cf
|
|
640
|
+
[8; 1, 14, 1, 10, 2, 1, 4, 12, 2, 3, 2, 1, 3, 4, 1, 1, 2, 14, 3, ...]
|
|
641
|
+
sage: cf.n(digits=3)
|
|
642
|
+
8.94
|
|
643
|
+
sage: cf.n(digits=6)
|
|
644
|
+
8.93715
|
|
645
|
+
sage: cf.n(digits=7)
|
|
646
|
+
8.937154
|
|
647
|
+
sage: cf.n(digits=8)
|
|
648
|
+
8.9371541
|
|
649
|
+
sage: cf.n(digits=9)
|
|
650
|
+
8.93715414
|
|
651
|
+
sage: cf.n(digits=10)
|
|
652
|
+
8.937154138
|
|
653
|
+
sage: cf.n(digits=11)
|
|
654
|
+
8.9371541378
|
|
655
|
+
|
|
656
|
+
TESTS:
|
|
657
|
+
|
|
658
|
+
Check that the rounding works as expected (at least in the
|
|
659
|
+
rational case)::
|
|
660
|
+
|
|
661
|
+
sage: fields = []
|
|
662
|
+
sage: for prec in [17, 24, 53, 128, 256]: # needs sage.rings.real_mpfr
|
|
663
|
+
....: for rnd in ['RNDN', 'RNDD', 'RNDU', 'RNDZ', 'RNDA']:
|
|
664
|
+
....: fields.append(RealField(prec=prec, rnd=rnd))
|
|
665
|
+
sage: for n in range(3000): # long time, not tested, known bug (see :issue:`29957`)
|
|
666
|
+
....: a = QQ.random_element(num_bound=2^(n%100))
|
|
667
|
+
....: if a.denominator() % 8 == 0: # not precise enough # :issue:`29957`
|
|
668
|
+
....: continue
|
|
669
|
+
....: cf = continued_fraction(a)
|
|
670
|
+
....: for R in fields:
|
|
671
|
+
....: try:
|
|
672
|
+
....: assert R(cf) == R(a)
|
|
673
|
+
....: except ZeroDivisionError: # :issue:`29957`
|
|
674
|
+
....: pass
|
|
675
|
+
"""
|
|
676
|
+
# 1. integer case
|
|
677
|
+
if self.quotient(1) is Infinity:
|
|
678
|
+
return R(self.quotient(0))
|
|
679
|
+
|
|
680
|
+
rnd = R.rounding_mode()
|
|
681
|
+
|
|
682
|
+
# 2. negative numbers: reduce to the positive case
|
|
683
|
+
if self.quotient(0) < 0:
|
|
684
|
+
sgn = -1
|
|
685
|
+
self = -self
|
|
686
|
+
# Adjust rounding for change in sign
|
|
687
|
+
if rnd == 'RNDD':
|
|
688
|
+
rnd = 'RNDA'
|
|
689
|
+
elif rnd == 'RNDU':
|
|
690
|
+
rnd = 'RNDZ'
|
|
691
|
+
else:
|
|
692
|
+
sgn = 1
|
|
693
|
+
|
|
694
|
+
# 3. positive non integer
|
|
695
|
+
if self.quotient(0) == 0: # 0 <= self < 1
|
|
696
|
+
N = R.prec() + self.quotient(1).nbits() - 1
|
|
697
|
+
if self.quotient(2) is Infinity and self.quotient(1) % (1 << (self.quotient(1).nbits() - 1)) == 0:
|
|
698
|
+
# if self is of the form [0; 2^N] then we need the following
|
|
699
|
+
N -= 1
|
|
700
|
+
else: # self > 1
|
|
701
|
+
N = R.prec() - self.quotient(0).nbits()
|
|
702
|
+
|
|
703
|
+
# even/odd convergents are respectively below/above
|
|
704
|
+
k = 0
|
|
705
|
+
p_even = self.numerator(2 * k)
|
|
706
|
+
p_odd = self.numerator(2 * k + 1)
|
|
707
|
+
q_even = self.denominator(2 * k)
|
|
708
|
+
q_odd = self.denominator(2 * k + 1)
|
|
709
|
+
m_even = (p_even << N) // q_even # floor((2^N p_even) / q_even)
|
|
710
|
+
m_odd = (p_odd << N + q_odd - 1) // q_odd # ceil((2^N p_odd) / q_odd)
|
|
711
|
+
while m_odd - m_even > 1:
|
|
712
|
+
k += 1
|
|
713
|
+
p_even = self.numerator(2 * k)
|
|
714
|
+
p_odd = self.numerator(2 * k + 1)
|
|
715
|
+
q_even = self.denominator(2 * k)
|
|
716
|
+
q_odd = self.denominator(2 * k + 1)
|
|
717
|
+
m_even = (p_even << N) // q_even
|
|
718
|
+
m_odd = ((p_odd << N) + q_odd - 1) // q_odd
|
|
719
|
+
|
|
720
|
+
assert m_odd.nbits() == R.prec() or m_even.nbits() == R.prec()
|
|
721
|
+
|
|
722
|
+
if m_even == m_odd: # no need to worry (we have an exact number)
|
|
723
|
+
return R(sgn * m_even) >> N
|
|
724
|
+
|
|
725
|
+
# check ordering
|
|
726
|
+
# m_even/2^N <= p_even/q_even <= self <= p_odd/q_odd <= m_odd/2^N
|
|
727
|
+
assert m_odd == m_even + 1
|
|
728
|
+
assert m_even / (ZZ_1 << N) <= p_even / q_even
|
|
729
|
+
assert p_even / q_even <= p_odd / q_odd
|
|
730
|
+
assert p_odd / q_odd <= m_odd / (ZZ_1 << N)
|
|
731
|
+
|
|
732
|
+
if rnd == 'RNDN': # round to the nearest
|
|
733
|
+
# in order to find the nearest approximation we possibly need to
|
|
734
|
+
# augment our precision on convergents.
|
|
735
|
+
while True:
|
|
736
|
+
assert not (p_odd << (N+1) <= (2*m_odd-1) * q_odd) or not (p_even << (N+1) >= (2*m_even+1) * q_even)
|
|
737
|
+
if p_odd << (N+1) <= (2*m_odd-1) * q_odd:
|
|
738
|
+
return R(sgn * m_even) >> N
|
|
739
|
+
if p_even << (N+1) >= (2*m_even+1) * q_even:
|
|
740
|
+
return R(sgn * m_odd) >> N
|
|
741
|
+
k += 1
|
|
742
|
+
p_even = self.numerator(2*k)
|
|
743
|
+
p_odd = self.numerator(2*k+1)
|
|
744
|
+
q_even = self.denominator(2*k)
|
|
745
|
+
q_odd = self.denominator(2*k+1)
|
|
746
|
+
elif rnd == 'RNDU' or rnd == 'RNDA': # round up
|
|
747
|
+
return R(sgn * m_odd) >> N
|
|
748
|
+
elif rnd == 'RNDD' or rnd == 'RNDZ': # round down
|
|
749
|
+
return R(sgn * m_even) >> N
|
|
750
|
+
else:
|
|
751
|
+
raise ValueError("%s unknown rounding mode" % rnd)
|
|
752
|
+
|
|
753
|
+
def __float__(self):
|
|
754
|
+
"""
|
|
755
|
+
EXAMPLES::
|
|
756
|
+
|
|
757
|
+
sage: a = continued_fraction(-17/389); a
|
|
758
|
+
[-1; 1, 21, 1, 7, 2]
|
|
759
|
+
sage: float(a) # needs sage.rings.real_mpfr
|
|
760
|
+
-0.043701799485861184
|
|
761
|
+
sage: float(-17/389)
|
|
762
|
+
-0.043701799485861184
|
|
763
|
+
"""
|
|
764
|
+
from sage.rings.real_mpfr import RR
|
|
765
|
+
return float(self._mpfr_(RR))
|
|
766
|
+
|
|
767
|
+
def numerator(self, n):
|
|
768
|
+
"""
|
|
769
|
+
Return the numerator of the `n`-th partial convergent of ``self``.
|
|
770
|
+
|
|
771
|
+
EXAMPLES::
|
|
772
|
+
|
|
773
|
+
sage: # needs sage.symbolic
|
|
774
|
+
sage: c = continued_fraction(pi); c
|
|
775
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
776
|
+
sage: c.numerator(0)
|
|
777
|
+
3
|
|
778
|
+
sage: c.numerator(12)
|
|
779
|
+
80143857
|
|
780
|
+
sage: c.numerator(152)
|
|
781
|
+
3943771611212266962743738812600748213157266596588744951727393497446921245353005283
|
|
782
|
+
"""
|
|
783
|
+
n = Integer(n)
|
|
784
|
+
|
|
785
|
+
p = self._pn
|
|
786
|
+
q = self._qn
|
|
787
|
+
|
|
788
|
+
if n < -2:
|
|
789
|
+
raise ValueError("n must be at least -2")
|
|
790
|
+
|
|
791
|
+
for k in range(len(p), n + 3):
|
|
792
|
+
x = self.quotient(k-2)
|
|
793
|
+
if x is Infinity and k != 2:
|
|
794
|
+
return p[-1]
|
|
795
|
+
p.append(x*p[k-1] + p[k-2])
|
|
796
|
+
q.append(x*q[k-1] + q[k-2])
|
|
797
|
+
|
|
798
|
+
return p[n+2]
|
|
799
|
+
|
|
800
|
+
p = numerator
|
|
801
|
+
|
|
802
|
+
def denominator(self, n):
|
|
803
|
+
"""
|
|
804
|
+
Return the denominator of the ``n``-th partial convergent of ``self``.
|
|
805
|
+
|
|
806
|
+
EXAMPLES::
|
|
807
|
+
|
|
808
|
+
sage: # needs sage.symbolic
|
|
809
|
+
sage: c = continued_fraction(pi); c
|
|
810
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
811
|
+
sage: c.denominator(0)
|
|
812
|
+
1
|
|
813
|
+
sage: c.denominator(12)
|
|
814
|
+
25510582
|
|
815
|
+
sage: c.denominator(152)
|
|
816
|
+
1255341492699841451528811722575401081588363886480089431843026103930863337221076748
|
|
817
|
+
"""
|
|
818
|
+
self.numerator(n) # ! silent computation of qn
|
|
819
|
+
if len(self._qn) < n+3:
|
|
820
|
+
return self._qn[-1]
|
|
821
|
+
return self._qn[n+2]
|
|
822
|
+
|
|
823
|
+
q = denominator
|
|
824
|
+
|
|
825
|
+
def convergent(self, n):
|
|
826
|
+
"""
|
|
827
|
+
Return the ``n``-th partial convergent to ``self``.
|
|
828
|
+
|
|
829
|
+
EXAMPLES::
|
|
830
|
+
|
|
831
|
+
sage: a = continued_fraction(pi); a # needs sage.symbolic
|
|
832
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
833
|
+
sage: a.convergent(3) # needs sage.symbolic
|
|
834
|
+
355/113
|
|
835
|
+
sage: a.convergent(15) # needs sage.symbolic
|
|
836
|
+
411557987/131002976
|
|
837
|
+
"""
|
|
838
|
+
return self.numerator(n) / self.denominator(n)
|
|
839
|
+
|
|
840
|
+
def convergents(self):
|
|
841
|
+
"""
|
|
842
|
+
Return the list of partial convergents of ``self``.
|
|
843
|
+
|
|
844
|
+
If ``self`` is an infinite continued fraction, then the object returned
|
|
845
|
+
is a :class:`~sage.misc.lazy_list.lazy_list_generic` which
|
|
846
|
+
behave like an infinite list.
|
|
847
|
+
|
|
848
|
+
EXAMPLES::
|
|
849
|
+
|
|
850
|
+
sage: a = continued_fraction(23/157); a
|
|
851
|
+
[0; 6, 1, 4, 1, 3]
|
|
852
|
+
sage: a.convergents()
|
|
853
|
+
[0, 1/6, 1/7, 5/34, 6/41, 23/157]
|
|
854
|
+
|
|
855
|
+
.. TODO::
|
|
856
|
+
|
|
857
|
+
Add an example with infinite list.
|
|
858
|
+
"""
|
|
859
|
+
if self.length() == Infinity:
|
|
860
|
+
from itertools import count
|
|
861
|
+
|
|
862
|
+
from sage.misc.lazy_list import lazy_list
|
|
863
|
+
return lazy_list(self.numerator(n) / self.denominator(n)
|
|
864
|
+
for n in count())
|
|
865
|
+
return [self.numerator(n) / self.denominator(n)
|
|
866
|
+
for n in range(len(self))]
|
|
867
|
+
|
|
868
|
+
def quotients(self):
|
|
869
|
+
r"""
|
|
870
|
+
Return the list of partial quotients of ``self``.
|
|
871
|
+
|
|
872
|
+
If ``self`` is an infinite continued fraction, then the object returned
|
|
873
|
+
is a :class:`~sage.misc.lazy_list.lazy_list_generic` which behaves
|
|
874
|
+
like an infinite list.
|
|
875
|
+
|
|
876
|
+
EXAMPLES::
|
|
877
|
+
|
|
878
|
+
sage: a = continued_fraction(23/157); a
|
|
879
|
+
[0; 6, 1, 4, 1, 3]
|
|
880
|
+
sage: a.quotients()
|
|
881
|
+
[0, 6, 1, 4, 1, 3]
|
|
882
|
+
|
|
883
|
+
.. TODO::
|
|
884
|
+
|
|
885
|
+
Add an example with infinite list.
|
|
886
|
+
"""
|
|
887
|
+
if self.length() == Infinity:
|
|
888
|
+
from itertools import count
|
|
889
|
+
|
|
890
|
+
from sage.misc.lazy_list import lazy_list
|
|
891
|
+
return lazy_list(self.quotient(n) for n in count())
|
|
892
|
+
return [self.quotient(n) for n in range(len(self))]
|
|
893
|
+
|
|
894
|
+
def __getitem__(self, n):
|
|
895
|
+
r"""
|
|
896
|
+
Return the ``n``-th partial quotient of ``self`` or a continued fraction
|
|
897
|
+
associated to a sublist of the partial quotients of ``self``.
|
|
898
|
+
|
|
899
|
+
TESTS::
|
|
900
|
+
|
|
901
|
+
sage: cf1 = continued_fraction(pi); cf1 # needs sage.symbolic
|
|
902
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
903
|
+
sage: cf2 = continued_fraction(QuadraticField(2).gen()); cf2 # needs sage.rings.number_field
|
|
904
|
+
[1; (2)*]
|
|
905
|
+
sage: cf3 = continued_fraction(4/17); cf3
|
|
906
|
+
[0; 4, 4]
|
|
907
|
+
sage: cf1[3:17] # needs sage.symbolic
|
|
908
|
+
[1; 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2]
|
|
909
|
+
sage: cf2[:10] # needs sage.rings.number_field
|
|
910
|
+
[1; 2, 2, 2, 2, 2, 2, 2, 2, 2]
|
|
911
|
+
sage: cf3[1:16]
|
|
912
|
+
[4; 4]
|
|
913
|
+
|
|
914
|
+
Be careful that the truncation of an infinite continued fraction might
|
|
915
|
+
be shorter by one::
|
|
916
|
+
|
|
917
|
+
sage: len(continued_fraction(golden_ratio)[:8]) # needs sage.symbolic
|
|
918
|
+
7
|
|
919
|
+
"""
|
|
920
|
+
if isinstance(n, slice):
|
|
921
|
+
quots = self.quotients()[n]
|
|
922
|
+
if n.stop is not None:
|
|
923
|
+
quots = list(quots)
|
|
924
|
+
return continued_fraction(quots)
|
|
925
|
+
|
|
926
|
+
try:
|
|
927
|
+
n = n.__index__()
|
|
928
|
+
except (AttributeError, ValueError):
|
|
929
|
+
raise ValueError("n (=%s) should be an integer" % n)
|
|
930
|
+
if n < 0:
|
|
931
|
+
raise ValueError("n (=%s) should be positive" % n)
|
|
932
|
+
q = self.quotient(n)
|
|
933
|
+
if q is Infinity:
|
|
934
|
+
raise IndexError("index out of range")
|
|
935
|
+
|
|
936
|
+
return q
|
|
937
|
+
|
|
938
|
+
def __iter__(self):
|
|
939
|
+
r"""
|
|
940
|
+
Iterate over the partial quotient of ``self``.
|
|
941
|
+
|
|
942
|
+
EXAMPLES::
|
|
943
|
+
|
|
944
|
+
sage: # needs sage.symbolic
|
|
945
|
+
sage: cf = continued_fraction(pi)
|
|
946
|
+
sage: i = iter(cf)
|
|
947
|
+
sage: [next(i) for _ in range(10)]
|
|
948
|
+
[3, 7, 15, 1, 292, 1, 1, 1, 2, 1]
|
|
949
|
+
sage: [next(i) for _ in range(10)]
|
|
950
|
+
[3, 1, 14, 2, 1, 1, 2, 2, 2, 2]
|
|
951
|
+
sage: [next(i) for _ in range(10)]
|
|
952
|
+
[1, 84, 2, 1, 1, 15, 3, 13, 1, 4]
|
|
953
|
+
"""
|
|
954
|
+
yield self.quotient(0)
|
|
955
|
+
i = 1
|
|
956
|
+
while True:
|
|
957
|
+
q = self.quotient(i)
|
|
958
|
+
if q is Infinity:
|
|
959
|
+
break
|
|
960
|
+
yield q
|
|
961
|
+
i += 1
|
|
962
|
+
|
|
963
|
+
def __int__(self):
|
|
964
|
+
"""
|
|
965
|
+
EXAMPLES::
|
|
966
|
+
|
|
967
|
+
sage: a = continued_fraction(-17/389); a
|
|
968
|
+
[-1; 1, 21, 1, 7, 2]
|
|
969
|
+
sage: int(a)
|
|
970
|
+
-1
|
|
971
|
+
"""
|
|
972
|
+
return int(self.quotient(0))
|
|
973
|
+
|
|
974
|
+
def sign(self):
|
|
975
|
+
r"""
|
|
976
|
+
Return the sign of ``self`` as an Integer.
|
|
977
|
+
|
|
978
|
+
The sign is defined to be ``0`` if ``self`` is ``0``, ``1`` if ``self``
|
|
979
|
+
is positive and ``-1`` if ``self`` is negative.
|
|
980
|
+
|
|
981
|
+
EXAMPLES::
|
|
982
|
+
|
|
983
|
+
sage: continued_fraction(tan(pi/7)).sign() # needs sage.symbolic
|
|
984
|
+
1
|
|
985
|
+
sage: continued_fraction(-34/2115).sign()
|
|
986
|
+
-1
|
|
987
|
+
sage: continued_fraction([0]).sign()
|
|
988
|
+
0
|
|
989
|
+
"""
|
|
990
|
+
if self.quotient(0) == 0:
|
|
991
|
+
if self.quotient(1) is Infinity:
|
|
992
|
+
return ZZ_0
|
|
993
|
+
return ZZ_1
|
|
994
|
+
return self.quotient(0).sign()
|
|
995
|
+
|
|
996
|
+
def floor(self):
|
|
997
|
+
r"""
|
|
998
|
+
Return the floor of ``self``.
|
|
999
|
+
|
|
1000
|
+
EXAMPLES::
|
|
1001
|
+
|
|
1002
|
+
sage: cf = continued_fraction([2,1,2,3])
|
|
1003
|
+
sage: cf.floor()
|
|
1004
|
+
2
|
|
1005
|
+
"""
|
|
1006
|
+
return self.quotient(0)
|
|
1007
|
+
|
|
1008
|
+
def ceil(self):
|
|
1009
|
+
r"""
|
|
1010
|
+
Return the ceil of ``self``.
|
|
1011
|
+
|
|
1012
|
+
EXAMPLES::
|
|
1013
|
+
|
|
1014
|
+
sage: cf = continued_fraction([2,1,3,4])
|
|
1015
|
+
sage: cf.ceil()
|
|
1016
|
+
3
|
|
1017
|
+
"""
|
|
1018
|
+
if self.length() == 1:
|
|
1019
|
+
return self.quotient(0)
|
|
1020
|
+
return self.quotient(0)+1
|
|
1021
|
+
|
|
1022
|
+
def __bool__(self):
|
|
1023
|
+
"""
|
|
1024
|
+
Return ``False`` if ``self`` is zero.
|
|
1025
|
+
|
|
1026
|
+
EXAMPLES::
|
|
1027
|
+
|
|
1028
|
+
sage: continued_fraction(0).is_zero() # indirect doctest
|
|
1029
|
+
True
|
|
1030
|
+
sage: continued_fraction(1).is_zero() # indirect doctest
|
|
1031
|
+
False
|
|
1032
|
+
sage: continued_fraction([(),(1,)]).is_zero() # indirect doctest
|
|
1033
|
+
False
|
|
1034
|
+
sage: continued_fraction([(0,),(1,2)]).is_zero() # indirect doctest
|
|
1035
|
+
False
|
|
1036
|
+
"""
|
|
1037
|
+
return bool(self.quotient(0)) or self.quotient(1) is not Infinity
|
|
1038
|
+
|
|
1039
|
+
def is_zero(self):
|
|
1040
|
+
r"""
|
|
1041
|
+
Test whether ``self`` is zero.
|
|
1042
|
+
|
|
1043
|
+
EXAMPLES::
|
|
1044
|
+
|
|
1045
|
+
sage: continued_fraction(0).is_zero()
|
|
1046
|
+
True
|
|
1047
|
+
sage: continued_fraction((0,1)).is_zero()
|
|
1048
|
+
False
|
|
1049
|
+
sage: continued_fraction(-1/2).is_zero()
|
|
1050
|
+
False
|
|
1051
|
+
sage: continued_fraction(pi).is_zero() # needs sage.symbolic
|
|
1052
|
+
False
|
|
1053
|
+
"""
|
|
1054
|
+
return self.quotient(0) == ZZ_0 and self.quotient(1) is Infinity
|
|
1055
|
+
|
|
1056
|
+
def is_one(self):
|
|
1057
|
+
r"""
|
|
1058
|
+
Test whether ``self`` is one.
|
|
1059
|
+
|
|
1060
|
+
EXAMPLES::
|
|
1061
|
+
|
|
1062
|
+
sage: continued_fraction(1).is_one()
|
|
1063
|
+
True
|
|
1064
|
+
sage: continued_fraction(5/4).is_one()
|
|
1065
|
+
False
|
|
1066
|
+
sage: continued_fraction(0).is_one()
|
|
1067
|
+
False
|
|
1068
|
+
sage: continued_fraction(pi).is_one() # needs sage.symbolic
|
|
1069
|
+
False
|
|
1070
|
+
"""
|
|
1071
|
+
return self.quotient(0) == ZZ_1 and self.quotient(1) is Infinity
|
|
1072
|
+
|
|
1073
|
+
def is_minus_one(self):
|
|
1074
|
+
r"""
|
|
1075
|
+
Test whether ``self`` is minus one.
|
|
1076
|
+
|
|
1077
|
+
EXAMPLES::
|
|
1078
|
+
|
|
1079
|
+
sage: continued_fraction(-1).is_minus_one()
|
|
1080
|
+
True
|
|
1081
|
+
sage: continued_fraction(1).is_minus_one()
|
|
1082
|
+
False
|
|
1083
|
+
sage: continued_fraction(0).is_minus_one()
|
|
1084
|
+
False
|
|
1085
|
+
sage: continued_fraction(-2).is_minus_one()
|
|
1086
|
+
False
|
|
1087
|
+
sage: continued_fraction([-1,1]).is_minus_one()
|
|
1088
|
+
False
|
|
1089
|
+
"""
|
|
1090
|
+
return self.quotient(0) == ZZ_m1 and self.quotient(1) is Infinity
|
|
1091
|
+
|
|
1092
|
+
def additive_order(self):
|
|
1093
|
+
"""
|
|
1094
|
+
Return the additive order of this continued fraction,
|
|
1095
|
+
which we defined to be the additive order of its value.
|
|
1096
|
+
|
|
1097
|
+
EXAMPLES::
|
|
1098
|
+
|
|
1099
|
+
sage: continued_fraction(-1).additive_order()
|
|
1100
|
+
+Infinity
|
|
1101
|
+
sage: continued_fraction(0).additive_order()
|
|
1102
|
+
1
|
|
1103
|
+
"""
|
|
1104
|
+
return Infinity if self else ZZ_1
|
|
1105
|
+
|
|
1106
|
+
def multiplicative_order(self):
|
|
1107
|
+
"""
|
|
1108
|
+
Return the multiplicative order of this continued fraction,
|
|
1109
|
+
which we defined to be the multiplicative order of its value.
|
|
1110
|
+
|
|
1111
|
+
EXAMPLES::
|
|
1112
|
+
|
|
1113
|
+
sage: continued_fraction(-1).multiplicative_order()
|
|
1114
|
+
2
|
|
1115
|
+
sage: continued_fraction(1).multiplicative_order()
|
|
1116
|
+
1
|
|
1117
|
+
sage: continued_fraction(pi).multiplicative_order() # needs sage.symbolic
|
|
1118
|
+
+Infinity
|
|
1119
|
+
"""
|
|
1120
|
+
if self.is_zero():
|
|
1121
|
+
return Infinity
|
|
1122
|
+
if self.is_one():
|
|
1123
|
+
return ZZ_1
|
|
1124
|
+
if self.is_minus_one():
|
|
1125
|
+
return ZZ_2
|
|
1126
|
+
return Infinity
|
|
1127
|
+
|
|
1128
|
+
def numerical_approx(self, prec=None, digits=None, algorithm=None):
|
|
1129
|
+
"""
|
|
1130
|
+
Return a numerical approximation of this continued fraction with
|
|
1131
|
+
``prec`` bits (or decimal ``digits``) of precision.
|
|
1132
|
+
|
|
1133
|
+
INPUT:
|
|
1134
|
+
|
|
1135
|
+
- ``prec`` -- precision in bits
|
|
1136
|
+
|
|
1137
|
+
- ``digits`` -- precision in decimal digits (only used if
|
|
1138
|
+
``prec`` is not given)
|
|
1139
|
+
|
|
1140
|
+
- ``algorithm`` -- ignored for continued fractions
|
|
1141
|
+
|
|
1142
|
+
If neither ``prec`` nor ``digits`` is given, the default
|
|
1143
|
+
precision is 53 bits (roughly 16 digits).
|
|
1144
|
+
|
|
1145
|
+
EXAMPLES::
|
|
1146
|
+
|
|
1147
|
+
sage: w = words.FibonacciWord([1,3]) # needs sage.combinat
|
|
1148
|
+
sage: cf = continued_fraction(w); cf # needs sage.combinat
|
|
1149
|
+
[1; 3, 1, 1, 3, 1, 3, 1, 1, 3, 1, 1, 3, 1, 3, 1, 1, 3, 1, 3...]
|
|
1150
|
+
sage: cf.numerical_approx(prec=53) # needs sage.combinat
|
|
1151
|
+
1.28102513329557
|
|
1152
|
+
|
|
1153
|
+
The method `n` is a shortcut to this one::
|
|
1154
|
+
|
|
1155
|
+
sage: cf.n(digits=25) # needs sage.combinat
|
|
1156
|
+
1.281025133295569815552930
|
|
1157
|
+
sage: cf.n(digits=33) # needs sage.combinat
|
|
1158
|
+
1.28102513329556981555293038097590
|
|
1159
|
+
"""
|
|
1160
|
+
from sage.arith.numerical_approx import digits_to_bits, numerical_approx_generic
|
|
1161
|
+
if prec is None:
|
|
1162
|
+
prec = digits_to_bits(digits)
|
|
1163
|
+
return numerical_approx_generic(self, prec)
|
|
1164
|
+
|
|
1165
|
+
n = numerical_approx
|
|
1166
|
+
|
|
1167
|
+
def apply_homography(self, a, b, c, d, forward_value=False):
|
|
1168
|
+
"""
|
|
1169
|
+
Return the continued fraction of `(ax + b)/(cx + d)`.
|
|
1170
|
+
|
|
1171
|
+
This is computed using Gosper's algorithm, see
|
|
1172
|
+
:mod:`~sage.rings.continued_fraction_gosper`.
|
|
1173
|
+
|
|
1174
|
+
INPUT:
|
|
1175
|
+
|
|
1176
|
+
- ``a``, ``b``, ``c``, ``d`` -- integers
|
|
1177
|
+
|
|
1178
|
+
- ``forward_value`` -- boolean (default: ``False``); whether the
|
|
1179
|
+
returned continued fraction is given the symbolic value of
|
|
1180
|
+
`(a x + b)/(cx + d)` and not only the list of partial quotients
|
|
1181
|
+
obtained from Gosper's algorithm
|
|
1182
|
+
|
|
1183
|
+
EXAMPLES::
|
|
1184
|
+
|
|
1185
|
+
sage: (5 * 13/6 - 2) / (3 * 13/6 - 4)
|
|
1186
|
+
53/15
|
|
1187
|
+
sage: continued_fraction(13/6).apply_homography(5, -2, 3, -4).value()
|
|
1188
|
+
53/15
|
|
1189
|
+
|
|
1190
|
+
We demonstrate now the effect of the optional argument ``forward_value``::
|
|
1191
|
+
|
|
1192
|
+
sage: cf = continued_fraction(pi) # needs sage.symbolic
|
|
1193
|
+
sage: h1 = cf.apply_homography(35, -27, 12, -5); h1 # needs sage.symbolic
|
|
1194
|
+
[2; 1, 1, 6, 3, 1, 2, 1, 5, 3, 1, 1, 1, 1, 9, 12, 1, 1, 1, 3...]
|
|
1195
|
+
sage: h1.value() # needs sage.symbolic
|
|
1196
|
+
2.536941776086946?
|
|
1197
|
+
|
|
1198
|
+
sage: h2 = cf.apply_homography(35, -27, 12, -5, forward_value=True); h2 # needs sage.symbolic
|
|
1199
|
+
[2; 1, 1, 6, 3, 1, 2, 1, 5, 3, 1, 1, 1, 1, 9, 12, 1, 1, 1, 3...]
|
|
1200
|
+
sage: h2.value() # needs sage.symbolic
|
|
1201
|
+
(35*pi - 27)/(12*pi - 5)
|
|
1202
|
+
|
|
1203
|
+
TESTS::
|
|
1204
|
+
|
|
1205
|
+
sage: # needs sage.combinat sage.rings.number_field sage.symbolic
|
|
1206
|
+
sage: CF = [continued_fraction(x) for x in [sqrt(2), AA(3).sqrt(),
|
|
1207
|
+
....: AA(3)**(1/3), QuadraticField(37).gen(), pi, 113/27,
|
|
1208
|
+
....: [3,1,2,2], words.FibonacciWord([1,3])]]
|
|
1209
|
+
sage: for _ in range(100): # not tested, known bug (see :issue:`32086`)
|
|
1210
|
+
....: cf = choice(CF)
|
|
1211
|
+
....: forward_value = choice([True, False])
|
|
1212
|
+
....: a = ZZ.random_element(-30, 30)
|
|
1213
|
+
....: b = ZZ.random_element(-30, 30)
|
|
1214
|
+
....: c = ZZ.random_element(-30, 30)
|
|
1215
|
+
....: d = ZZ.random_element(-30, 30)
|
|
1216
|
+
....: if not c and not d:
|
|
1217
|
+
....: continue
|
|
1218
|
+
....: cf_gosper = cf.apply_homography(a, b, c, d, forward_value)
|
|
1219
|
+
....: x = cf.value()
|
|
1220
|
+
....: cf_hom = continued_fraction((a*x + b) / (c*x + d))
|
|
1221
|
+
....: assert cf_gosper[:30] == cf_hom[:30]
|
|
1222
|
+
|
|
1223
|
+
sage: continued_fraction(13/25).apply_homography(0, 1, 25, -13)
|
|
1224
|
+
Traceback (most recent call last):
|
|
1225
|
+
...
|
|
1226
|
+
ValueError: continued fraction can not represent infinity
|
|
1227
|
+
|
|
1228
|
+
sage: continued_fraction(pi).apply_homography(0, 1, 0, 0) # needs sage.symbolic
|
|
1229
|
+
Traceback (most recent call last):
|
|
1230
|
+
...
|
|
1231
|
+
ZeroDivisionError: division by zero
|
|
1232
|
+
|
|
1233
|
+
REFERENCES:
|
|
1234
|
+
|
|
1235
|
+
- [Gos1972]_
|
|
1236
|
+
- [Knu1998]_ Exercise 4.5.3.15
|
|
1237
|
+
- [LS1998]_
|
|
1238
|
+
"""
|
|
1239
|
+
from .continued_fraction_gosper import gosper_iterator
|
|
1240
|
+
|
|
1241
|
+
if not all(isinstance(x, numbers.Integral) for x in (a, b, c, d)):
|
|
1242
|
+
raise TypeError("a, b, c and d must be integral")
|
|
1243
|
+
|
|
1244
|
+
a = ZZ(a)
|
|
1245
|
+
b = ZZ(b)
|
|
1246
|
+
c = ZZ(c)
|
|
1247
|
+
d = ZZ(d)
|
|
1248
|
+
if not c and not d:
|
|
1249
|
+
raise ZeroDivisionError("division by zero")
|
|
1250
|
+
|
|
1251
|
+
_i = iter(gosper_iterator(a, b, c, d, self))
|
|
1252
|
+
value = None
|
|
1253
|
+
if isinstance(self, ContinuedFraction_periodic):
|
|
1254
|
+
l = list(_i)
|
|
1255
|
+
preperiod_length = _i.output_preperiod_length
|
|
1256
|
+
preperiod = l[:preperiod_length]
|
|
1257
|
+
period = l[preperiod_length:]
|
|
1258
|
+
return continued_fraction((preperiod, period), value)
|
|
1259
|
+
else:
|
|
1260
|
+
if forward_value:
|
|
1261
|
+
if isinstance(self, ContinuedFraction_real):
|
|
1262
|
+
# self._x0 is an exact number, ie with infinite precision
|
|
1263
|
+
x = self._x0
|
|
1264
|
+
value = (a * x + b) / (c * x + d)
|
|
1265
|
+
elif isinstance(self, ContinuedFraction_infinite) and self._value is not None:
|
|
1266
|
+
# if present, self._value is an exact number, ie with infinite precision
|
|
1267
|
+
x = self._value
|
|
1268
|
+
value = (a * x + b) / (c * x + d)
|
|
1269
|
+
|
|
1270
|
+
from sage.misc.lazy_list import lazy_list
|
|
1271
|
+
return continued_fraction(lazy_list(_i), value)
|
|
1272
|
+
|
|
1273
|
+
def __neg__(self):
|
|
1274
|
+
"""
|
|
1275
|
+
Return the additive inverse of ``self``.
|
|
1276
|
+
|
|
1277
|
+
EXAMPLES::
|
|
1278
|
+
|
|
1279
|
+
sage: -continued_fraction(e) # needs sage.symbolic
|
|
1280
|
+
[-3; 3, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, 14...]
|
|
1281
|
+
sage: -continued_fraction(sqrt(7)) # needs sage.symbolic
|
|
1282
|
+
[-3; 2, 1, 4, 1, 1, 1, 4, 1, 1, 1, 4, 1, 1, 1, 4, 1, 1, 1, 4...]
|
|
1283
|
+
"""
|
|
1284
|
+
return self.apply_homography(-1, 0, 0, 1)
|
|
1285
|
+
|
|
1286
|
+
def __invert__(self):
|
|
1287
|
+
"""
|
|
1288
|
+
Return the multiplicative inverse of ``self``.
|
|
1289
|
+
|
|
1290
|
+
EXAMPLES::
|
|
1291
|
+
|
|
1292
|
+
sage: ~continued_fraction(e) # needs sage.symbolic
|
|
1293
|
+
[0; 2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1...]
|
|
1294
|
+
sage: ~continued_fraction(sqrt(7)) # needs sage.symbolic
|
|
1295
|
+
[0; 2, 1, 1, 1, 4, 1, 1, 1, 4, 1, 1, 1, 4, 1, 1, 1, 4, 1, 1...]
|
|
1296
|
+
"""
|
|
1297
|
+
return self.apply_homography(0, 1, 1, 0)
|
|
1298
|
+
|
|
1299
|
+
|
|
1300
|
+
class ContinuedFraction_periodic(ContinuedFraction_base):
|
|
1301
|
+
r"""
|
|
1302
|
+
Continued fraction associated with rational or quadratic number.
|
|
1303
|
+
|
|
1304
|
+
A rational number has a finite continued fraction expansion (or ultimately
|
|
1305
|
+
0). The one of a quadratic number, ie a number of the form `a + b \sqrt{D}`
|
|
1306
|
+
with `a` and `b` rational, is ultimately periodic.
|
|
1307
|
+
|
|
1308
|
+
.. NOTE::
|
|
1309
|
+
|
|
1310
|
+
This class stores a tuple ``_x1`` for the preperiod and a tuple ``_x2``
|
|
1311
|
+
for the period. In the purely periodic case ``_x1`` is empty while in
|
|
1312
|
+
the rational case ``_x2`` is the tuple ``(0,)``.
|
|
1313
|
+
"""
|
|
1314
|
+
def __init__(self, x1, x2=None, check=True):
|
|
1315
|
+
r"""
|
|
1316
|
+
INPUT:
|
|
1317
|
+
|
|
1318
|
+
- ``x1`` -- tuple of integers
|
|
1319
|
+
|
|
1320
|
+
- ``x2`` -- tuple of integers
|
|
1321
|
+
|
|
1322
|
+
TESTS::
|
|
1323
|
+
|
|
1324
|
+
sage: cf = continued_fraction((1,1,2,3,4)) # indirect doctest
|
|
1325
|
+
sage: loads(dumps(cf)) == cf
|
|
1326
|
+
True
|
|
1327
|
+
sage: cf = continued_fraction((1,5),(3,2)) # indirect doctest
|
|
1328
|
+
sage: loads(dumps(cf)) == cf
|
|
1329
|
+
True
|
|
1330
|
+
"""
|
|
1331
|
+
ContinuedFraction_base.__init__(self)
|
|
1332
|
+
self._x1 = tuple(x1)
|
|
1333
|
+
if not x2:
|
|
1334
|
+
self._x2 = (Infinity,)
|
|
1335
|
+
else:
|
|
1336
|
+
self._x2 = tuple(x2)
|
|
1337
|
+
|
|
1338
|
+
def period(self):
|
|
1339
|
+
r"""
|
|
1340
|
+
Return the periodic part of ``self``.
|
|
1341
|
+
|
|
1342
|
+
EXAMPLES::
|
|
1343
|
+
|
|
1344
|
+
sage: # needs sage.rings.number_field
|
|
1345
|
+
sage: K.<sqrt3> = QuadraticField(3)
|
|
1346
|
+
sage: cf = continued_fraction(sqrt3); cf
|
|
1347
|
+
[1; (1, 2)*]
|
|
1348
|
+
sage: cf.period()
|
|
1349
|
+
(1, 2)
|
|
1350
|
+
sage: for k in xsrange(2,40):
|
|
1351
|
+
....: if not k.is_square():
|
|
1352
|
+
....: s = QuadraticField(k).gen()
|
|
1353
|
+
....: cf = continued_fraction(s)
|
|
1354
|
+
....: print('%2d %d %s' % (k, len(cf.period()), cf))
|
|
1355
|
+
2 1 [1; (2)*]
|
|
1356
|
+
3 2 [1; (1, 2)*]
|
|
1357
|
+
5 1 [2; (4)*]
|
|
1358
|
+
6 2 [2; (2, 4)*]
|
|
1359
|
+
7 4 [2; (1, 1, 1, 4)*]
|
|
1360
|
+
8 2 [2; (1, 4)*]
|
|
1361
|
+
10 1 [3; (6)*]
|
|
1362
|
+
11 2 [3; (3, 6)*]
|
|
1363
|
+
12 2 [3; (2, 6)*]
|
|
1364
|
+
13 5 [3; (1, 1, 1, 1, 6)*]
|
|
1365
|
+
14 4 [3; (1, 2, 1, 6)*]
|
|
1366
|
+
...
|
|
1367
|
+
35 2 [5; (1, 10)*]
|
|
1368
|
+
37 1 [6; (12)*]
|
|
1369
|
+
38 2 [6; (6, 12)*]
|
|
1370
|
+
39 2 [6; (4, 12)*]
|
|
1371
|
+
"""
|
|
1372
|
+
if self._x2[0] is Infinity:
|
|
1373
|
+
return ()
|
|
1374
|
+
return self._x2
|
|
1375
|
+
|
|
1376
|
+
def preperiod(self):
|
|
1377
|
+
r"""
|
|
1378
|
+
Return the preperiodic part of ``self``.
|
|
1379
|
+
|
|
1380
|
+
EXAMPLES::
|
|
1381
|
+
|
|
1382
|
+
sage: # needs sage.rings.number_field
|
|
1383
|
+
sage: K.<sqrt3> = QuadraticField(3)
|
|
1384
|
+
sage: cf = continued_fraction(sqrt3); cf
|
|
1385
|
+
[1; (1, 2)*]
|
|
1386
|
+
sage: cf.preperiod()
|
|
1387
|
+
(1,)
|
|
1388
|
+
sage: cf = continued_fraction(sqrt3/7); cf
|
|
1389
|
+
[0; 4, (24, 8)*]
|
|
1390
|
+
sage: cf.preperiod()
|
|
1391
|
+
(0, 4)
|
|
1392
|
+
"""
|
|
1393
|
+
return self._x1
|
|
1394
|
+
|
|
1395
|
+
def quotient(self, n):
|
|
1396
|
+
r"""
|
|
1397
|
+
Return the ``n``-th partial quotient of ``self``.
|
|
1398
|
+
|
|
1399
|
+
EXAMPLES::
|
|
1400
|
+
|
|
1401
|
+
sage: cf = continued_fraction([(12,5),(1,3)])
|
|
1402
|
+
sage: [cf.quotient(i) for i in range(10)]
|
|
1403
|
+
[12, 5, 1, 3, 1, 3, 1, 3, 1, 3]
|
|
1404
|
+
"""
|
|
1405
|
+
n = int(n)
|
|
1406
|
+
if n < 0:
|
|
1407
|
+
raise ValueError("n (=%d) should be positive" % n)
|
|
1408
|
+
if n < len(self._x1):
|
|
1409
|
+
return self._x1[n]
|
|
1410
|
+
return self._x2[(n-len(self._x1)) % len(self._x2)]
|
|
1411
|
+
|
|
1412
|
+
def length(self):
|
|
1413
|
+
r"""
|
|
1414
|
+
Return the number of partial quotients of ``self``.
|
|
1415
|
+
|
|
1416
|
+
EXAMPLES::
|
|
1417
|
+
|
|
1418
|
+
sage: continued_fraction(2/5).length()
|
|
1419
|
+
3
|
|
1420
|
+
sage: cf = continued_fraction([(0,1),(2,)]); cf
|
|
1421
|
+
[0; 1, (2)*]
|
|
1422
|
+
sage: cf.length()
|
|
1423
|
+
+Infinity
|
|
1424
|
+
"""
|
|
1425
|
+
if len(self._x2) > 1 or self._x2[0] is not Infinity:
|
|
1426
|
+
return Infinity
|
|
1427
|
+
return Integer(len(self._x1))
|
|
1428
|
+
|
|
1429
|
+
def preperiod_length(self):
|
|
1430
|
+
r"""
|
|
1431
|
+
Return the number of partial quotients of the preperiodic part of ``self``.
|
|
1432
|
+
|
|
1433
|
+
EXAMPLES::
|
|
1434
|
+
|
|
1435
|
+
sage: continued_fraction(2/5).preperiod_length()
|
|
1436
|
+
3
|
|
1437
|
+
sage: cf = continued_fraction([(0,1),(2,)]); cf
|
|
1438
|
+
[0; 1, (2)*]
|
|
1439
|
+
sage: cf.preperiod_length()
|
|
1440
|
+
2
|
|
1441
|
+
"""
|
|
1442
|
+
return Integer(len(self._x1))
|
|
1443
|
+
|
|
1444
|
+
def period_length(self):
|
|
1445
|
+
r"""
|
|
1446
|
+
Return the number of partial quotients of the preperiodic part of ``self``.
|
|
1447
|
+
|
|
1448
|
+
EXAMPLES::
|
|
1449
|
+
|
|
1450
|
+
sage: continued_fraction(2/5).period_length()
|
|
1451
|
+
1
|
|
1452
|
+
sage: cf = continued_fraction([(0,1),(2,)]); cf
|
|
1453
|
+
[0; 1, (2)*]
|
|
1454
|
+
sage: cf.period_length()
|
|
1455
|
+
1
|
|
1456
|
+
"""
|
|
1457
|
+
return Integer(len(self._x2))
|
|
1458
|
+
|
|
1459
|
+
def __richcmp__(self, other, op):
|
|
1460
|
+
r"""
|
|
1461
|
+
Rich comparison.
|
|
1462
|
+
|
|
1463
|
+
EXAMPLES::
|
|
1464
|
+
|
|
1465
|
+
sage: # needs sage.rings.real_mpfr
|
|
1466
|
+
sage: a = continued_fraction([(0,),(1,2,3,1,2,3,1)]); a.n()
|
|
1467
|
+
0.694249167819459
|
|
1468
|
+
sage: b = continued_fraction([(0,),(1,2,3)]); b.n()
|
|
1469
|
+
0.694254176766073
|
|
1470
|
+
sage: c = continued_fraction([(0,1),(2,3)]); c.n()
|
|
1471
|
+
0.696140478029631
|
|
1472
|
+
sage: d = continued_fraction([(0,1,2),(3,)]); d.n()
|
|
1473
|
+
0.697224362268005
|
|
1474
|
+
sage: a < b and a < c and a < d
|
|
1475
|
+
True
|
|
1476
|
+
sage: b < c and b < d and c < d
|
|
1477
|
+
True
|
|
1478
|
+
sage: b == c
|
|
1479
|
+
False
|
|
1480
|
+
sage: c > c
|
|
1481
|
+
False
|
|
1482
|
+
sage: b >= d
|
|
1483
|
+
False
|
|
1484
|
+
"""
|
|
1485
|
+
if isinstance(other, ContinuedFraction_periodic):
|
|
1486
|
+
n = max(len(self._x1) + 2 * len(self._x2),
|
|
1487
|
+
len(other._x1) + 2 * len(other._x2))
|
|
1488
|
+
for i in range(n):
|
|
1489
|
+
a = self.quotient(i)
|
|
1490
|
+
b = other.quotient(i)
|
|
1491
|
+
if a > b:
|
|
1492
|
+
return rich_to_bool(op, -1 if i % 2 else 1)
|
|
1493
|
+
if b > a:
|
|
1494
|
+
return rich_to_bool(op, 1 if i % 2 else -1)
|
|
1495
|
+
return rich_to_bool(op, 0)
|
|
1496
|
+
|
|
1497
|
+
return ContinuedFraction_base.__richcmp__(self, other, op)
|
|
1498
|
+
|
|
1499
|
+
def value(self):
|
|
1500
|
+
r"""
|
|
1501
|
+
Return the value of ``self`` as a quadratic number (with square free
|
|
1502
|
+
discriminant).
|
|
1503
|
+
|
|
1504
|
+
EXAMPLES:
|
|
1505
|
+
|
|
1506
|
+
Some purely periodic examples::
|
|
1507
|
+
|
|
1508
|
+
sage: cf = continued_fraction([(),(2,)]); cf
|
|
1509
|
+
[(2)*]
|
|
1510
|
+
sage: v = cf.value(); v # needs sage.rings.number_field
|
|
1511
|
+
sqrt2 + 1
|
|
1512
|
+
sage: v.continued_fraction() # needs sage.rings.number_field
|
|
1513
|
+
[(2)*]
|
|
1514
|
+
|
|
1515
|
+
sage: cf = continued_fraction([(),(1,2)]); cf
|
|
1516
|
+
[(1, 2)*]
|
|
1517
|
+
sage: v = cf.value(); v # needs sage.rings.number_field
|
|
1518
|
+
1/2*sqrt3 + 1/2
|
|
1519
|
+
sage: v.continued_fraction() # needs sage.rings.number_field
|
|
1520
|
+
[(1, 2)*]
|
|
1521
|
+
|
|
1522
|
+
The number ``sqrt3`` that appear above is actually internal to the
|
|
1523
|
+
continued fraction. In order to be access it from the console::
|
|
1524
|
+
|
|
1525
|
+
sage: cf.value().parent().inject_variables() # needs sage.rings.number_field
|
|
1526
|
+
Defining sqrt3
|
|
1527
|
+
sage: sqrt3 # needs sage.rings.number_field
|
|
1528
|
+
sqrt3
|
|
1529
|
+
sage: ((sqrt3+1)/2).continued_fraction() # needs sage.rings.number_field
|
|
1530
|
+
[(1, 2)*]
|
|
1531
|
+
|
|
1532
|
+
Some ultimately periodic but non periodic examples::
|
|
1533
|
+
|
|
1534
|
+
sage: cf = continued_fraction([(1,),(2,)]); cf
|
|
1535
|
+
[1; (2)*]
|
|
1536
|
+
sage: v = cf.value(); v # needs sage.rings.number_field
|
|
1537
|
+
sqrt2
|
|
1538
|
+
sage: v.continued_fraction() # needs sage.rings.number_field
|
|
1539
|
+
[1; (2)*]
|
|
1540
|
+
|
|
1541
|
+
sage: cf = continued_fraction([(1,3),(1,2)]); cf
|
|
1542
|
+
[1; 3, (1, 2)*]
|
|
1543
|
+
sage: v = cf.value(); v # needs sage.rings.number_field
|
|
1544
|
+
-sqrt3 + 3
|
|
1545
|
+
sage: v.continued_fraction() # needs sage.rings.number_field
|
|
1546
|
+
[1; 3, (1, 2)*]
|
|
1547
|
+
|
|
1548
|
+
sage: cf = continued_fraction([(-5,18), (1,3,1,5)])
|
|
1549
|
+
sage: cf.value().continued_fraction() == cf # needs sage.rings.number_field
|
|
1550
|
+
True
|
|
1551
|
+
sage: cf = continued_fraction([(-1,),(1,)])
|
|
1552
|
+
sage: cf.value().continued_fraction() == cf # needs sage.rings.number_field
|
|
1553
|
+
True
|
|
1554
|
+
|
|
1555
|
+
TESTS::
|
|
1556
|
+
|
|
1557
|
+
sage: a1 = ((0,1),(2,3))
|
|
1558
|
+
sage: a2 = ((-12,1,1),(2,3,2,4))
|
|
1559
|
+
sage: a3 = ((1,),(1,2))
|
|
1560
|
+
sage: a4 = ((-2,2),(1,124,13))
|
|
1561
|
+
sage: a5 = ((0,),(1,))
|
|
1562
|
+
sage: for a in a1,a2,a3,a4,a5: # needs sage.rings.number_field
|
|
1563
|
+
....: cf = continued_fraction(a)
|
|
1564
|
+
....: assert cf.value().continued_fraction() == cf
|
|
1565
|
+
"""
|
|
1566
|
+
if self._x1 and self._x1[0] < 0:
|
|
1567
|
+
return -(-self).value()
|
|
1568
|
+
|
|
1569
|
+
if self._x2[0] is Infinity:
|
|
1570
|
+
return self._rational_()
|
|
1571
|
+
|
|
1572
|
+
# determine the equation for the purely periodic cont. frac. determined
|
|
1573
|
+
# by self._x2
|
|
1574
|
+
p0, q0, p1, q1 = last_two_convergents(self._x2)
|
|
1575
|
+
|
|
1576
|
+
# now x is one of the root of the equation
|
|
1577
|
+
# q1 x^2 + (q0 - p1) x - p0 = 0
|
|
1578
|
+
from sage.misc.functional import squarefree_part
|
|
1579
|
+
from sage.rings.number_field.number_field import QuadraticField
|
|
1580
|
+
D = (q0-p1)**2 + 4*q1*p0
|
|
1581
|
+
DD = squarefree_part(D)
|
|
1582
|
+
Q = QuadraticField(DD, 'sqrt%d' % DD)
|
|
1583
|
+
x = ((p1 - q0) + (D/DD).sqrt() * Q.gen()) / (2*q1)
|
|
1584
|
+
|
|
1585
|
+
# we add the preperiod
|
|
1586
|
+
p0, q0, p1, q1 = last_two_convergents(self._x1)
|
|
1587
|
+
return (p1*x + p0) / (q1*x + q0)
|
|
1588
|
+
|
|
1589
|
+
def _repr_(self):
|
|
1590
|
+
r"""
|
|
1591
|
+
TESTS::
|
|
1592
|
+
|
|
1593
|
+
sage: a = continued_fraction(pi.n()); a # needs sage.symbolic
|
|
1594
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3]
|
|
1595
|
+
sage: a.rename('continued fraction of pi') # needs sage.symbolic
|
|
1596
|
+
sage: a # needs sage.symbolic
|
|
1597
|
+
continued fraction of pi
|
|
1598
|
+
|
|
1599
|
+
sage: continued_fraction([(0,1),(2,)])
|
|
1600
|
+
[0; 1, (2)*]
|
|
1601
|
+
sage: continued_fraction([(),(1,3)])
|
|
1602
|
+
[(1, 3)*]
|
|
1603
|
+
"""
|
|
1604
|
+
if self._x2[0] is Infinity: # rational case
|
|
1605
|
+
if len(self._x1) == 1:
|
|
1606
|
+
return '[%d]' % self._x1[0]
|
|
1607
|
+
return '[%d; ' % self._x1[0] + ', '.join(str(a) for a in self._x1[1:]) + ']'
|
|
1608
|
+
|
|
1609
|
+
period = '(' + ', '.join(str(a) for a in self._x2) + ')*'
|
|
1610
|
+
if not self._x1: # purely periodic case
|
|
1611
|
+
return '[' + period + ']'
|
|
1612
|
+
|
|
1613
|
+
if len(self._x1) == 1:
|
|
1614
|
+
return '[%d; ' % self._x1[0] + period + ']'
|
|
1615
|
+
return '[%d; ' % self._x1[0] + ', '.join(str(a) for a in self._x1[1:]) + ', ' + period + ']'
|
|
1616
|
+
|
|
1617
|
+
def __len__(self):
|
|
1618
|
+
"""
|
|
1619
|
+
Return the number of terms in this continued fraction.
|
|
1620
|
+
|
|
1621
|
+
EXAMPLES::
|
|
1622
|
+
|
|
1623
|
+
sage: len(continued_fraction([1,2,3,4,5]) )
|
|
1624
|
+
5
|
|
1625
|
+
|
|
1626
|
+
sage: len(continued_fraction(([],[1])))
|
|
1627
|
+
Traceback (most recent call last):
|
|
1628
|
+
...
|
|
1629
|
+
ValueError: the length is infinite
|
|
1630
|
+
"""
|
|
1631
|
+
if self._x2[0] is Infinity: # rational case
|
|
1632
|
+
return len(self._x1)
|
|
1633
|
+
raise ValueError("the length is infinite")
|
|
1634
|
+
|
|
1635
|
+
def _rational_(self):
|
|
1636
|
+
"""
|
|
1637
|
+
EXAMPLES::
|
|
1638
|
+
|
|
1639
|
+
sage: a = continued_fraction(-17/389); a
|
|
1640
|
+
[-1; 1, 21, 1, 7, 2]
|
|
1641
|
+
sage: a._rational_()
|
|
1642
|
+
-17/389
|
|
1643
|
+
sage: QQ(a)
|
|
1644
|
+
-17/389
|
|
1645
|
+
|
|
1646
|
+
sage: a = continued_fraction([2,3,4,5,2])
|
|
1647
|
+
sage: QQ(a)
|
|
1648
|
+
344/149
|
|
1649
|
+
|
|
1650
|
+
sage: a = continued_fraction(([2,3],[1]))
|
|
1651
|
+
sage: QQ(a)
|
|
1652
|
+
Traceback (most recent call last):
|
|
1653
|
+
...
|
|
1654
|
+
ValueError: this is not a rational!
|
|
1655
|
+
"""
|
|
1656
|
+
if self._x2[0] is not Infinity:
|
|
1657
|
+
raise ValueError("this is not a rational!")
|
|
1658
|
+
n = len(self)
|
|
1659
|
+
return self.numerator(n-1) / self.denominator(n-1)
|
|
1660
|
+
|
|
1661
|
+
def _latex_(self):
|
|
1662
|
+
r"""
|
|
1663
|
+
EXAMPLES::
|
|
1664
|
+
|
|
1665
|
+
sage: a = continued_fraction(-17/389)
|
|
1666
|
+
sage: latex(a)
|
|
1667
|
+
-1
|
|
1668
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
1669
|
+
+ \frac{\displaystyle 1}{\displaystyle 21
|
|
1670
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
1671
|
+
+ \frac{\displaystyle 1}{\displaystyle 7
|
|
1672
|
+
+ \frac{\displaystyle 1}{\displaystyle 2
|
|
1673
|
+
}}}}}
|
|
1674
|
+
sage: K.<a> = QuadraticField(1234) # needs sage.rings.number_field
|
|
1675
|
+
sage: cf = continued_fraction(a); cf # needs sage.rings.number_field
|
|
1676
|
+
[35; (7, 1, 3, 1, 4, 4, 2, 9, 1, 1, 2, 3, 1, 1, 34, 1, 1, 3, 2, 1, 1, 9, 2, 4, 4, 1, 3, 1, 7, 70)*]
|
|
1677
|
+
sage: latex(cf) # needs sage.rings.number_field
|
|
1678
|
+
35
|
|
1679
|
+
+ \frac{\displaystyle 1}{\displaystyle 7
|
|
1680
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
1681
|
+
+ \frac{\displaystyle 1}{\displaystyle 3
|
|
1682
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
1683
|
+
+ \frac{\displaystyle 1}{\displaystyle 4
|
|
1684
|
+
+ \frac{\displaystyle 1}{\displaystyle 4
|
|
1685
|
+
+ \frac{\displaystyle 1}{\displaystyle 2
|
|
1686
|
+
+ \frac{\displaystyle 1}{\displaystyle 9
|
|
1687
|
+
+ \frac{\displaystyle 1}{\displaystyle 1
|
|
1688
|
+
+ \frac{\displaystyle 1}{\displaystyle \dots}}}}}}}}}}
|
|
1689
|
+
"""
|
|
1690
|
+
if self._x2[0] is not Infinity:
|
|
1691
|
+
return super()._latex_()
|
|
1692
|
+
v = self._x1
|
|
1693
|
+
if len(v) == 0:
|
|
1694
|
+
return '0'
|
|
1695
|
+
s = str(v[0]) + '\n'
|
|
1696
|
+
for i in range(1, len(v)):
|
|
1697
|
+
s += '+ \\frac{\\displaystyle 1}{\\displaystyle %s\n' % v[i]
|
|
1698
|
+
s += '}'*(len(v)-1)
|
|
1699
|
+
return s
|
|
1700
|
+
|
|
1701
|
+
def __invert__(self):
|
|
1702
|
+
"""
|
|
1703
|
+
Return the multiplicative inverse of ``self``.
|
|
1704
|
+
|
|
1705
|
+
EXAMPLES::
|
|
1706
|
+
|
|
1707
|
+
sage: a = continued_fraction(13/25)
|
|
1708
|
+
sage: ~a == continued_fraction(25/13)
|
|
1709
|
+
True
|
|
1710
|
+
sage: a.value() * (~a).value()
|
|
1711
|
+
1
|
|
1712
|
+
|
|
1713
|
+
sage: a = continued_fraction(-17/253)
|
|
1714
|
+
sage: ~a == continued_fraction(-253/17)
|
|
1715
|
+
True
|
|
1716
|
+
sage: a.value() * (~a).value()
|
|
1717
|
+
1
|
|
1718
|
+
|
|
1719
|
+
sage: # needs sage.rings.number_field
|
|
1720
|
+
sage: K.<sqrt5> = QuadraticField(5)
|
|
1721
|
+
sage: a1 = (sqrt5+1)/2
|
|
1722
|
+
sage: c1 = a1.continued_fraction(); c1
|
|
1723
|
+
[(1)*]
|
|
1724
|
+
sage: ~c1
|
|
1725
|
+
[0; (1)*]
|
|
1726
|
+
sage: c1.value() * (~c1).value()
|
|
1727
|
+
1
|
|
1728
|
+
|
|
1729
|
+
sage: c2 = (sqrt5/3 + 1/7).continued_fraction(); c2 # needs sage.rings.number_field
|
|
1730
|
+
[0; 1, (7, 1, 17, ..., 1, 2)*]
|
|
1731
|
+
sage: c2.value() * (~c2).value() # needs sage.rings.number_field
|
|
1732
|
+
1
|
|
1733
|
+
"""
|
|
1734
|
+
if not self:
|
|
1735
|
+
raise ZeroDivisionError("rational division by zero")
|
|
1736
|
+
if self._x1:
|
|
1737
|
+
if self._x1[0] < 0:
|
|
1738
|
+
return -~-self
|
|
1739
|
+
if self._x1[0] == 0:
|
|
1740
|
+
return self.__class__(self._x1[1:], self._x2)
|
|
1741
|
+
return self.__class__((0,) + self._x1, self._x2)
|
|
1742
|
+
|
|
1743
|
+
def __neg__(self):
|
|
1744
|
+
"""
|
|
1745
|
+
Return the additive inverse of ``self``.
|
|
1746
|
+
|
|
1747
|
+
TESTS::
|
|
1748
|
+
|
|
1749
|
+
sage: quots1 = [(0,),(1,),(2,),(0,1),(1,1),(2,1),(1,2),
|
|
1750
|
+
....: (0,1,1),(1,1,1),(1,1,1,1),(1,2)]
|
|
1751
|
+
sage: for q in quots1:
|
|
1752
|
+
....: cf = continued_fraction(q)
|
|
1753
|
+
....: ncf = -cf
|
|
1754
|
+
....: nncf = -ncf
|
|
1755
|
+
....: assert cf == nncf
|
|
1756
|
+
....: assert ncf.value() == -cf.value()
|
|
1757
|
+
....: assert cf.length() < 2 or cf.quotients()[-1] != 1
|
|
1758
|
+
....: assert ncf.length() < 2 or ncf.quotients()[-1] != 1
|
|
1759
|
+
....: assert nncf.length() < 2 or nncf.quotients()[-1] != 1
|
|
1760
|
+
|
|
1761
|
+
sage: quots2 = [((),(1,)), ((), (1,2)), ((0,),(1,)),
|
|
1762
|
+
....: ((),(2,1)), ((3,),(2,1))]
|
|
1763
|
+
sage: for q in quots2: # needs sage.rings.number_field
|
|
1764
|
+
....: cf = continued_fraction(q)
|
|
1765
|
+
....: ncf = -cf
|
|
1766
|
+
....: nncf = -ncf
|
|
1767
|
+
....: assert cf == nncf
|
|
1768
|
+
....: assert ncf.value() == -cf.value()
|
|
1769
|
+
"""
|
|
1770
|
+
x1 = self._x1
|
|
1771
|
+
x2 = self._x2
|
|
1772
|
+
|
|
1773
|
+
if x2[0] is Infinity:
|
|
1774
|
+
if len(x1) == 1:
|
|
1775
|
+
xx1 = (-x1[0],)
|
|
1776
|
+
|
|
1777
|
+
elif x1[1] == 1:
|
|
1778
|
+
xx1 = (-x1[0] - 1, x1[2] + 1) + x1[3:]
|
|
1779
|
+
|
|
1780
|
+
elif len(x1) == 2 and x1[1] == 2:
|
|
1781
|
+
xx1 = (-x1[0] - 1, ZZ_2)
|
|
1782
|
+
|
|
1783
|
+
else:
|
|
1784
|
+
xx1 = (-x1[0] - 1, ZZ_1, x1[1] - 1) + x1[2:]
|
|
1785
|
+
|
|
1786
|
+
return self.__class__(xx1, x2)
|
|
1787
|
+
|
|
1788
|
+
# to make the quadratic case work, we need 3 elements in x1
|
|
1789
|
+
if len(x1) < 3:
|
|
1790
|
+
x1 += x2
|
|
1791
|
+
if len(x1) < 3:
|
|
1792
|
+
x1 += x2
|
|
1793
|
+
if len(x1) < 3:
|
|
1794
|
+
x1 += x2
|
|
1795
|
+
|
|
1796
|
+
if x1[1] == 1:
|
|
1797
|
+
xx1 = (-x1[0] - 1, x1[2] + 1) + x1[3:]
|
|
1798
|
+
else:
|
|
1799
|
+
xx1 = (-x1[0] - 1, ZZ_1, x1[1] - 1) + x1[2:]
|
|
1800
|
+
xx1, xx2 = check_and_reduce_pair(xx1, x2)
|
|
1801
|
+
return self.__class__(xx1, xx2)
|
|
1802
|
+
|
|
1803
|
+
|
|
1804
|
+
class ContinuedFraction_real(ContinuedFraction_base):
|
|
1805
|
+
r"""
|
|
1806
|
+
Continued fraction of a real (exact) number.
|
|
1807
|
+
|
|
1808
|
+
This class simply wraps a real number into an attribute (that can be
|
|
1809
|
+
accessed through the method :meth:`value`). The number is assumed to be
|
|
1810
|
+
irrational.
|
|
1811
|
+
|
|
1812
|
+
EXAMPLES::
|
|
1813
|
+
|
|
1814
|
+
sage: cf = continued_fraction(pi); cf # needs sage.symbolic
|
|
1815
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
1816
|
+
sage: cf.value() # needs sage.symbolic
|
|
1817
|
+
pi
|
|
1818
|
+
|
|
1819
|
+
sage: cf = continued_fraction(e); cf # needs sage.symbolic
|
|
1820
|
+
[2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, ...]
|
|
1821
|
+
sage: cf.value() # needs sage.symbolic
|
|
1822
|
+
e
|
|
1823
|
+
"""
|
|
1824
|
+
def __init__(self, x):
|
|
1825
|
+
r"""
|
|
1826
|
+
INPUT:
|
|
1827
|
+
|
|
1828
|
+
- ``x`` -- the real number from which we want the continued fraction
|
|
1829
|
+
|
|
1830
|
+
TESTS::
|
|
1831
|
+
|
|
1832
|
+
sage: TestSuite(continued_fraction(pi)).run() # needs sage.symbolic
|
|
1833
|
+
"""
|
|
1834
|
+
ContinuedFraction_base.__init__(self)
|
|
1835
|
+
self._x0 = x
|
|
1836
|
+
|
|
1837
|
+
from .real_mpfi import RealIntervalField
|
|
1838
|
+
self._xa = RealIntervalField(53)(self._x0)
|
|
1839
|
+
# an approximation of the last element of the orbit under the
|
|
1840
|
+
# Gauss map
|
|
1841
|
+
|
|
1842
|
+
self._quotients = []
|
|
1843
|
+
|
|
1844
|
+
def length(self):
|
|
1845
|
+
r"""
|
|
1846
|
+
Return infinity.
|
|
1847
|
+
|
|
1848
|
+
EXAMPLES::
|
|
1849
|
+
|
|
1850
|
+
sage: continued_fraction(pi).length() # needs sage.symbolic
|
|
1851
|
+
+Infinity
|
|
1852
|
+
"""
|
|
1853
|
+
return Infinity
|
|
1854
|
+
|
|
1855
|
+
def __len__(self):
|
|
1856
|
+
r"""
|
|
1857
|
+
TESTS::
|
|
1858
|
+
|
|
1859
|
+
sage: len(continued_fraction(pi)) # needs sage.symbolic
|
|
1860
|
+
Traceback (most recent call last):
|
|
1861
|
+
...
|
|
1862
|
+
ValueError: the length is infinite!
|
|
1863
|
+
"""
|
|
1864
|
+
raise ValueError("the length is infinite!")
|
|
1865
|
+
|
|
1866
|
+
def __richcmp__(self, other, op):
|
|
1867
|
+
r"""
|
|
1868
|
+
Rich comparison.
|
|
1869
|
+
|
|
1870
|
+
EXAMPLES::
|
|
1871
|
+
|
|
1872
|
+
sage: continued_fraction(pi) > continued_fraction(e) # needs sage.symbolic
|
|
1873
|
+
True
|
|
1874
|
+
sage: continued_fraction(pi) > continued_fraction(e+4) # needs sage.symbolic
|
|
1875
|
+
False
|
|
1876
|
+
"""
|
|
1877
|
+
try:
|
|
1878
|
+
if self.value() == other.value():
|
|
1879
|
+
return rich_to_bool(op, 0)
|
|
1880
|
+
if self.value() - other.value() > 0:
|
|
1881
|
+
return rich_to_bool(op, 1)
|
|
1882
|
+
return rich_to_bool(op, -1)
|
|
1883
|
+
except Exception:
|
|
1884
|
+
return ContinuedFraction_base.__richcmp__(self, other, op)
|
|
1885
|
+
|
|
1886
|
+
def _repr_(self):
|
|
1887
|
+
r"""
|
|
1888
|
+
String representation.
|
|
1889
|
+
|
|
1890
|
+
EXAMPLES::
|
|
1891
|
+
|
|
1892
|
+
sage: continued_fraction(pi) # indirect doctest # needs sage.symbolic
|
|
1893
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
1894
|
+
"""
|
|
1895
|
+
return '[%d; ' % self.quotient(0) + ', '.join(str(self.quotient(i)) for i in range(1, 20)) + ", ...]"
|
|
1896
|
+
|
|
1897
|
+
def quotient(self, n):
|
|
1898
|
+
r"""
|
|
1899
|
+
Return the ``n``-th quotient of ``self``.
|
|
1900
|
+
|
|
1901
|
+
EXAMPLES::
|
|
1902
|
+
|
|
1903
|
+
sage: # needs sage.symbolic
|
|
1904
|
+
sage: cf = continued_fraction(pi)
|
|
1905
|
+
sage: cf.quotient(27)
|
|
1906
|
+
13
|
|
1907
|
+
sage: cf.quotient(2552)
|
|
1908
|
+
152
|
|
1909
|
+
sage: cf.quotient(10000) # long time
|
|
1910
|
+
5
|
|
1911
|
+
|
|
1912
|
+
The algorithm is not efficient with element of the symbolic ring and,
|
|
1913
|
+
if possible, one can always prefer number fields elements. The reason is
|
|
1914
|
+
that, given a symbolic element ``x``, there is no automatic way to
|
|
1915
|
+
evaluate in ``RIF`` an expression of the form ``(a*x+b)/(c*x+d)`` where
|
|
1916
|
+
both the numerator and the denominator are extremely small::
|
|
1917
|
+
|
|
1918
|
+
sage: # needs sage.symbolic
|
|
1919
|
+
sage: a1 = pi
|
|
1920
|
+
sage: c1 = continued_fraction(a1)
|
|
1921
|
+
sage: p0 = c1.numerator(12); q0 = c1.denominator(12)
|
|
1922
|
+
sage: p1 = c1.numerator(13); q1 = c1.denominator(13)
|
|
1923
|
+
sage: num = (q0*a1 - p0); num.n()
|
|
1924
|
+
1.49011611938477e-8
|
|
1925
|
+
sage: den = (q1*a1 - p1); den.n()
|
|
1926
|
+
-2.98023223876953e-8
|
|
1927
|
+
sage: a1 = -num/den
|
|
1928
|
+
sage: RIF(a1)
|
|
1929
|
+
[-infinity .. +infinity]
|
|
1930
|
+
|
|
1931
|
+
The same computation with an element of a number field instead of
|
|
1932
|
+
``pi`` gives a very satisfactory answer::
|
|
1933
|
+
|
|
1934
|
+
sage: # needs sage.rings.number_field
|
|
1935
|
+
sage: x = polygen(ZZ, 'x')
|
|
1936
|
+
sage: K.<a2> = NumberField(x^3 - 2, embedding=1.25)
|
|
1937
|
+
sage: c2 = continued_fraction(a2)
|
|
1938
|
+
sage: p0 = c2.numerator(111); q0 = c2.denominator(111)
|
|
1939
|
+
sage: p1 = c2.numerator(112); q1 = c2.denominator(112)
|
|
1940
|
+
sage: num = (q0*a2 - p0); num.n()
|
|
1941
|
+
-4.56719261665907e46
|
|
1942
|
+
sage: den = (q1*a2 - p1); den.n()
|
|
1943
|
+
-3.65375409332726e47
|
|
1944
|
+
sage: a2 = -num/den
|
|
1945
|
+
sage: b2 = RIF(a2); b2
|
|
1946
|
+
1.002685823312715?
|
|
1947
|
+
sage: b2.absolute_diameter()
|
|
1948
|
+
8.88178419700125e-16
|
|
1949
|
+
|
|
1950
|
+
The consequence is that the precision needed with ``c1`` grows when we
|
|
1951
|
+
compute larger and larger partial quotients::
|
|
1952
|
+
|
|
1953
|
+
sage: # needs sage.symbolic
|
|
1954
|
+
sage: c1.quotient(100)
|
|
1955
|
+
2
|
|
1956
|
+
sage: c1._xa.parent()
|
|
1957
|
+
Real Interval Field with 353 bits of precision
|
|
1958
|
+
sage: c1.quotient(200)
|
|
1959
|
+
3
|
|
1960
|
+
sage: c1._xa.parent()
|
|
1961
|
+
Real Interval Field with 753 bits of precision
|
|
1962
|
+
sage: c1.quotient(300)
|
|
1963
|
+
5
|
|
1964
|
+
sage: c1._xa.parent()
|
|
1965
|
+
Real Interval Field with 1053 bits of precision
|
|
1966
|
+
|
|
1967
|
+
sage: # needs sage.rings.number_field
|
|
1968
|
+
sage: c2.quotient(200)
|
|
1969
|
+
6
|
|
1970
|
+
sage: c2._xa.parent()
|
|
1971
|
+
Real Interval Field with 53 bits of precision
|
|
1972
|
+
sage: c2.quotient(500)
|
|
1973
|
+
1
|
|
1974
|
+
sage: c2._xa.parent()
|
|
1975
|
+
Real Interval Field with 53 bits of precision
|
|
1976
|
+
sage: c2.quotient(1000)
|
|
1977
|
+
1
|
|
1978
|
+
sage: c2._xa.parent()
|
|
1979
|
+
Real Interval Field with 53 bits of precision
|
|
1980
|
+
"""
|
|
1981
|
+
x = self._xa
|
|
1982
|
+
|
|
1983
|
+
if len(self._quotients) > 1 and n >= len(self._quotients) and self._quotients[-1] == 0:
|
|
1984
|
+
return ZZ_0
|
|
1985
|
+
|
|
1986
|
+
for k in range(len(self._quotients), n+1):
|
|
1987
|
+
if x.lower().is_infinity() or x.upper().is_infinity() or x.lower().floor() != x.upper().floor():
|
|
1988
|
+
|
|
1989
|
+
def orbit(z):
|
|
1990
|
+
return -(self.denominator(k-2)*z-self.numerator(k-2))/(self.denominator(k-1)*z-self.numerator(k-1))
|
|
1991
|
+
x = x.parent()(orbit(self._x0))
|
|
1992
|
+
|
|
1993
|
+
# It may happen that the above line fails to give an
|
|
1994
|
+
# approximation with the expected number of digits (see the
|
|
1995
|
+
# examples). In that case, we augment the precision.
|
|
1996
|
+
while x.lower().is_infinity() or x.upper().is_infinity() or x.lower().floor() != x.upper().floor():
|
|
1997
|
+
from .real_mpfi import RealIntervalField
|
|
1998
|
+
self._prec = x.parent().prec() + 100
|
|
1999
|
+
x = RealIntervalField(self._prec)(orbit(self._x0))
|
|
2000
|
+
|
|
2001
|
+
self._quotients.append(x.unique_floor())
|
|
2002
|
+
x = (x - x.unique_floor())
|
|
2003
|
+
if not x:
|
|
2004
|
+
self._quotients.append(ZZ_0)
|
|
2005
|
+
return ZZ_0
|
|
2006
|
+
x = ~x
|
|
2007
|
+
|
|
2008
|
+
self._xa = x
|
|
2009
|
+
return self._quotients[n]
|
|
2010
|
+
|
|
2011
|
+
def value(self):
|
|
2012
|
+
r"""
|
|
2013
|
+
Return the value of ``self`` (the number from which it was built).
|
|
2014
|
+
|
|
2015
|
+
EXAMPLES::
|
|
2016
|
+
|
|
2017
|
+
sage: cf = continued_fraction(e) # needs sage.symbolic
|
|
2018
|
+
sage: cf.value() # needs sage.symbolic
|
|
2019
|
+
e
|
|
2020
|
+
"""
|
|
2021
|
+
return self._x0
|
|
2022
|
+
|
|
2023
|
+
|
|
2024
|
+
class ContinuedFraction_infinite(ContinuedFraction_base):
|
|
2025
|
+
r"""
|
|
2026
|
+
A continued fraction defined by an infinite sequence of partial quotients.
|
|
2027
|
+
|
|
2028
|
+
EXAMPLES::
|
|
2029
|
+
|
|
2030
|
+
sage: t = continued_fraction(words.ThueMorseWord([1,2])); t # needs sage.combinat
|
|
2031
|
+
[1; 2, 2, 1, 2, 1, 1, 2, 2, 1...]
|
|
2032
|
+
sage: t.n(digits=100) # needs sage.combinat
|
|
2033
|
+
1.422388736882785488341547116024565825306879108991711829311892452916456747272565883312455412962072042
|
|
2034
|
+
|
|
2035
|
+
We check that comparisons work well::
|
|
2036
|
+
|
|
2037
|
+
sage: t > continued_fraction(1) and t < continued_fraction(3/2) # needs sage.combinat
|
|
2038
|
+
True
|
|
2039
|
+
sage: t < continued_fraction(1) or t > continued_fraction(2) # needs sage.combinat
|
|
2040
|
+
False
|
|
2041
|
+
|
|
2042
|
+
Can also be called with a ``value`` option::
|
|
2043
|
+
|
|
2044
|
+
sage: def f(n):
|
|
2045
|
+
....: if n % 3 == 2: return 2*(n+1)//3
|
|
2046
|
+
....: return 1
|
|
2047
|
+
sage: w = Word(f, alphabet=NN); w # needs sage.combinat
|
|
2048
|
+
word: 1,1,2,1,1,4,1,1,6,1,1,8,1,1,10,1,1,12,1,1,14,1,1,16,1,1,18,1,1,20,1,1,22,1,1,24,1,1,26,1,...
|
|
2049
|
+
sage: cf = continued_fraction(w, value=e-1); cf # needs sage.combinat sage.symbolic
|
|
2050
|
+
[1; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1...]
|
|
2051
|
+
|
|
2052
|
+
In that case a small check is done on the input::
|
|
2053
|
+
|
|
2054
|
+
sage: cf = continued_fraction(w, value=pi) # needs sage.combinat sage.symbolic
|
|
2055
|
+
Traceback (most recent call last):
|
|
2056
|
+
...
|
|
2057
|
+
ValueError: value evaluates to 3.141592653589794? while the continued
|
|
2058
|
+
fraction evaluates to 1.718281828459046? in Real Interval Field
|
|
2059
|
+
with 53 bits of precision.
|
|
2060
|
+
"""
|
|
2061
|
+
def __init__(self, w, value=None, check=True):
|
|
2062
|
+
r"""
|
|
2063
|
+
INPUT:
|
|
2064
|
+
|
|
2065
|
+
- ``parent`` -- a parent
|
|
2066
|
+
|
|
2067
|
+
- ``w`` -- an infinite list
|
|
2068
|
+
|
|
2069
|
+
- ``value`` -- an optional known value
|
|
2070
|
+
|
|
2071
|
+
- ``check`` -- whether the constructor checks the input (default: ``True``)
|
|
2072
|
+
|
|
2073
|
+
TESTS::
|
|
2074
|
+
|
|
2075
|
+
sage: w = words.FibonacciWord(['a','b']) # needs sage.combinat
|
|
2076
|
+
sage: continued_fraction(w) # needs sage.combinat
|
|
2077
|
+
Traceback (most recent call last):
|
|
2078
|
+
...
|
|
2079
|
+
ValueError: the sequence must consist of integers
|
|
2080
|
+
|
|
2081
|
+
sage: from itertools import count
|
|
2082
|
+
sage: w = Word(count(), length='infinite') # needs sage.combinat
|
|
2083
|
+
sage: continued_fraction(w) # needs sage.combinat
|
|
2084
|
+
[0; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19...]
|
|
2085
|
+
|
|
2086
|
+
sage: w = Word(count(), length='unknown') # needs sage.combinat
|
|
2087
|
+
sage: continued_fraction(w) # needs sage.combinat
|
|
2088
|
+
Traceback (most recent call last):
|
|
2089
|
+
...
|
|
2090
|
+
ValueError: word with unknown length cannot be converted to
|
|
2091
|
+
continued fractions
|
|
2092
|
+
|
|
2093
|
+
sage: continued_fraction(words.FibonacciWord([0,1])) # needs sage.combinat
|
|
2094
|
+
Traceback (most recent call last):
|
|
2095
|
+
...
|
|
2096
|
+
ValueError: only the first partial quotient can be null
|
|
2097
|
+
|
|
2098
|
+
sage: w = words.ThueMorseWord([int(1), int(2)]) # needs sage.combinat
|
|
2099
|
+
sage: t = continued_fraction(w) # needs sage.combinat
|
|
2100
|
+
sage: type(t.quotient(1)) # needs sage.combinat
|
|
2101
|
+
<class 'sage.rings.integer.Integer'>
|
|
2102
|
+
"""
|
|
2103
|
+
ContinuedFraction_base.__init__(self)
|
|
2104
|
+
self._w = w
|
|
2105
|
+
|
|
2106
|
+
if check:
|
|
2107
|
+
for i in range(10):
|
|
2108
|
+
k = w[i]
|
|
2109
|
+
if not isinstance(k, Integer):
|
|
2110
|
+
try:
|
|
2111
|
+
k = Integer(w[i])
|
|
2112
|
+
except (TypeError, ValueError):
|
|
2113
|
+
raise ValueError("the sequence must consist of"
|
|
2114
|
+
" integers")
|
|
2115
|
+
self.quotient = self._Integer_quotient
|
|
2116
|
+
|
|
2117
|
+
if not k and i:
|
|
2118
|
+
raise ValueError("only the first partial quotient can"
|
|
2119
|
+
" be null")
|
|
2120
|
+
|
|
2121
|
+
if check and value is not None:
|
|
2122
|
+
from sage.rings.real_mpfi import RealIntervalField
|
|
2123
|
+
R = RealIntervalField(53)
|
|
2124
|
+
x = R(value)
|
|
2125
|
+
y = R(self)
|
|
2126
|
+
if x.lower() > y.lower() or x.upper() < y.upper():
|
|
2127
|
+
raise ValueError("value evaluates to %s while the continued fraction evaluates to %s in %s." % (x, y, R))
|
|
2128
|
+
|
|
2129
|
+
self._value = value
|
|
2130
|
+
|
|
2131
|
+
def _repr_(self):
|
|
2132
|
+
r"""
|
|
2133
|
+
String representation.
|
|
2134
|
+
|
|
2135
|
+
EXAMPLES::
|
|
2136
|
+
|
|
2137
|
+
sage: w = words.FibonacciWord([3,13]) # needs sage.combinat
|
|
2138
|
+
sage: cf = continued_fraction(w); cf # needs sage.combinat
|
|
2139
|
+
[3; 13, 3, 3, 13, 3, 13, 3, 3, 13, 3, 3, 13, 3, 13, 3, 3, 13, 3, 13...]
|
|
2140
|
+
"""
|
|
2141
|
+
return "[" + str(self._w[0]) + "; " + ", ".join(map(str, self._w[1:20])) + "...]"
|
|
2142
|
+
|
|
2143
|
+
def length(self):
|
|
2144
|
+
r"""
|
|
2145
|
+
Return infinity.
|
|
2146
|
+
|
|
2147
|
+
EXAMPLES::
|
|
2148
|
+
|
|
2149
|
+
sage: w = words.FibonacciWord([3,13]) # needs sage.combinat
|
|
2150
|
+
sage: cf = continued_fraction(w) # needs sage.combinat
|
|
2151
|
+
sage: cf.length() # needs sage.combinat
|
|
2152
|
+
+Infinity
|
|
2153
|
+
"""
|
|
2154
|
+
return Infinity
|
|
2155
|
+
|
|
2156
|
+
def quotient(self, n):
|
|
2157
|
+
r"""
|
|
2158
|
+
Return the ``n``-th partial quotient of ``self``.
|
|
2159
|
+
|
|
2160
|
+
INPUT:
|
|
2161
|
+
|
|
2162
|
+
- ``n`` -- integer
|
|
2163
|
+
|
|
2164
|
+
EXAMPLES::
|
|
2165
|
+
|
|
2166
|
+
sage: # needs sage.combinat
|
|
2167
|
+
sage: w = words.FibonacciWord([1,3])
|
|
2168
|
+
sage: cf = continued_fraction(w)
|
|
2169
|
+
sage: cf.quotient(0)
|
|
2170
|
+
1
|
|
2171
|
+
sage: cf.quotient(1)
|
|
2172
|
+
3
|
|
2173
|
+
sage: cf.quotient(2)
|
|
2174
|
+
1
|
|
2175
|
+
"""
|
|
2176
|
+
return self._w[n]
|
|
2177
|
+
|
|
2178
|
+
def quotients(self):
|
|
2179
|
+
r"""
|
|
2180
|
+
Return the infinite list from which this continued fraction was built.
|
|
2181
|
+
|
|
2182
|
+
EXAMPLES::
|
|
2183
|
+
|
|
2184
|
+
sage: w = words.FibonacciWord([1,5]) # needs sage.combinat
|
|
2185
|
+
sage: cf = continued_fraction(w) # needs sage.combinat
|
|
2186
|
+
sage: cf.quotients() # needs sage.combinat
|
|
2187
|
+
word: 1511515115115151151511511515115115151151...
|
|
2188
|
+
"""
|
|
2189
|
+
return self._w
|
|
2190
|
+
|
|
2191
|
+
def _Integer_quotient(self, n):
|
|
2192
|
+
r"""
|
|
2193
|
+
Return the ``n``-th partial quotient of ``self``.
|
|
2194
|
+
|
|
2195
|
+
INPUT:
|
|
2196
|
+
|
|
2197
|
+
- ``n`` -- integer
|
|
2198
|
+
|
|
2199
|
+
EXAMPLES::
|
|
2200
|
+
|
|
2201
|
+
sage: # needs sage.combinat
|
|
2202
|
+
sage: w = words.ThueMorseWord([int(1), int(2)])
|
|
2203
|
+
sage: t = continued_fraction(w)
|
|
2204
|
+
sage: t.quotient(0)
|
|
2205
|
+
1
|
|
2206
|
+
sage: t.quotient(1)
|
|
2207
|
+
2
|
|
2208
|
+
sage: type(t.quotient(1)) # indirect doctest
|
|
2209
|
+
<class 'sage.rings.integer.Integer'>
|
|
2210
|
+
"""
|
|
2211
|
+
return Integer(self._w[n])
|
|
2212
|
+
|
|
2213
|
+
def value(self):
|
|
2214
|
+
r"""
|
|
2215
|
+
Return the value of ``self``.
|
|
2216
|
+
|
|
2217
|
+
If this value was provided on initialization, just return this value
|
|
2218
|
+
otherwise return an element of the real lazy field.
|
|
2219
|
+
|
|
2220
|
+
EXAMPLES::
|
|
2221
|
+
|
|
2222
|
+
sage: def f(n):
|
|
2223
|
+
....: if n % 3 == 2: return 2*(n+1)//3
|
|
2224
|
+
....: return 1
|
|
2225
|
+
sage: w = Word(f, alphabet=NN); w # needs sage.combinat
|
|
2226
|
+
word: 1,1,2,1,1,4,1,1,6,1,1,8,1,1,10,1,1,12,1,1,14,1,1,16,1,1,18,1,1,20,1,1,22,1,1,24,1,1,26,1,...
|
|
2227
|
+
sage: cf = continued_fraction(w, value=e-1); cf # needs sage.combinat sage.symbolic
|
|
2228
|
+
[1; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1...]
|
|
2229
|
+
sage: cf.value() # needs sage.combinat sage.symbolic
|
|
2230
|
+
e - 1
|
|
2231
|
+
|
|
2232
|
+
sage: w = words.FibonacciWord([2,5]) # needs sage.combinat
|
|
2233
|
+
sage: cf = continued_fraction(w); cf # needs sage.combinat
|
|
2234
|
+
[2; 5, 2, 2, 5, 2, 5, 2, 2, 5, 2, 2, 5, 2, 5, 2, 2, 5, 2, 5...]
|
|
2235
|
+
sage: cf.value() # needs sage.combinat
|
|
2236
|
+
2.184951302409338?
|
|
2237
|
+
"""
|
|
2238
|
+
if self._value is not None:
|
|
2239
|
+
return self._value
|
|
2240
|
+
else:
|
|
2241
|
+
from sage.rings.real_lazy import RLF
|
|
2242
|
+
if self._w[0] < 0:
|
|
2243
|
+
return -RLF(-self)
|
|
2244
|
+
return RLF(self)
|
|
2245
|
+
|
|
2246
|
+
def __neg__(self):
|
|
2247
|
+
"""
|
|
2248
|
+
Return the opposite of ``self``.
|
|
2249
|
+
|
|
2250
|
+
EXAMPLES::
|
|
2251
|
+
|
|
2252
|
+
sage: -continued_fraction(words.FibonacciWord([2,5])) # needs sage.combinat
|
|
2253
|
+
[-3; 1, 4, 2, 2, 5, 2, 5, 2, 2, 5, 2, 2, 5, 2, 5, 2, 2, 5, 2...]
|
|
2254
|
+
|
|
2255
|
+
sage: from sage.misc.lazy_list import lazy_list
|
|
2256
|
+
sage: l = lazy_list(lambda n: (n**2)%17)
|
|
2257
|
+
sage: -continued_fraction(l) # needs sage.combinat
|
|
2258
|
+
[-1; 5, 9, 16, 8, 2, 15, 13, 13, 15, 2, 8, 16, 9, 4, 1, 0, 1, 4, 9...]
|
|
2259
|
+
"""
|
|
2260
|
+
from sage.combinat.words.word import Word
|
|
2261
|
+
_w = self._w
|
|
2262
|
+
if _w[1] == 1:
|
|
2263
|
+
_w = Word((-_w[0] - 1, _w[2] + 1)).concatenate(Word(_w[3:]))
|
|
2264
|
+
else:
|
|
2265
|
+
_w = Word((-_w[0] - 1, ZZ_1, _w[1] - 1)).concatenate(Word(_w[2:]))
|
|
2266
|
+
return self.__class__(_w)
|
|
2267
|
+
|
|
2268
|
+
|
|
2269
|
+
def check_and_reduce_pair(x1, x2=None):
|
|
2270
|
+
r"""
|
|
2271
|
+
There are often two ways to represent a given continued fraction. This
|
|
2272
|
+
function makes it canonical.
|
|
2273
|
+
|
|
2274
|
+
In the very special case of the number `0` we return the pair
|
|
2275
|
+
``((0,),(0,))``.
|
|
2276
|
+
|
|
2277
|
+
TESTS::
|
|
2278
|
+
|
|
2279
|
+
sage: from sage.rings.continued_fraction import check_and_reduce_pair
|
|
2280
|
+
sage: check_and_reduce_pair([])
|
|
2281
|
+
Traceback (most recent call last):
|
|
2282
|
+
...
|
|
2283
|
+
ValueError: continued fraction can not represent infinity
|
|
2284
|
+
sage: check_and_reduce_pair([-1,1])
|
|
2285
|
+
((0,), (+Infinity,))
|
|
2286
|
+
sage: check_and_reduce_pair([1,1,1])
|
|
2287
|
+
((1, 2), (+Infinity,))
|
|
2288
|
+
sage: check_and_reduce_pair([1,3],[2,3])
|
|
2289
|
+
((1,), (3, 2))
|
|
2290
|
+
sage: check_and_reduce_pair([1,2,3],[2,3,2,3,2,3])
|
|
2291
|
+
((1,), (2, 3))
|
|
2292
|
+
sage: check_and_reduce_pair([1,2],[])
|
|
2293
|
+
((1, 2), (+Infinity,))
|
|
2294
|
+
"""
|
|
2295
|
+
y1 = [Integer(x) for x in x1]
|
|
2296
|
+
|
|
2297
|
+
if x2 is None or not x2 or x2[0] is Infinity:
|
|
2298
|
+
y2 = [Infinity]
|
|
2299
|
+
if not y1:
|
|
2300
|
+
raise ValueError("continued fraction can not represent infinity")
|
|
2301
|
+
elif len(y1) > 1 and y1[-1] == 1:
|
|
2302
|
+
y1.pop()
|
|
2303
|
+
y1[-1] += 1
|
|
2304
|
+
|
|
2305
|
+
else:
|
|
2306
|
+
y2 = [Integer(x) for x in x2]
|
|
2307
|
+
if any(b <= ZZ_0 for b in y2):
|
|
2308
|
+
raise ValueError("the elements of the period cannot be negative")
|
|
2309
|
+
|
|
2310
|
+
# add possibly some element of x1 into the period
|
|
2311
|
+
while y1 and y1[-1] == y2[-1]:
|
|
2312
|
+
y1.pop()
|
|
2313
|
+
y2.insert(0, y2.pop())
|
|
2314
|
+
|
|
2315
|
+
# some special cases to treat
|
|
2316
|
+
if len(y2) == 1 and y2[0] == 0:
|
|
2317
|
+
if not y1:
|
|
2318
|
+
y1 = [ZZ_0]
|
|
2319
|
+
elif len(y1) > 1 and y1[-1] == 1:
|
|
2320
|
+
y1.pop()
|
|
2321
|
+
y1[-1] += 1
|
|
2322
|
+
|
|
2323
|
+
# check that y2 is not a pure power (in a very naive way!!)
|
|
2324
|
+
n2 = len(y2)
|
|
2325
|
+
for i in range(1, (n2 + 2) // 2):
|
|
2326
|
+
if n2 % i == 0 and y2[:-i] == y2[i:]:
|
|
2327
|
+
y2 = y2[:i]
|
|
2328
|
+
break
|
|
2329
|
+
|
|
2330
|
+
# check that at the end y1 has no zeros in it
|
|
2331
|
+
for i in range(1, len(y1)):
|
|
2332
|
+
if y1[i] <= 0:
|
|
2333
|
+
raise ValueError("all quotient except the first must be positive")
|
|
2334
|
+
|
|
2335
|
+
return tuple(y1), tuple(y2)
|
|
2336
|
+
|
|
2337
|
+
|
|
2338
|
+
def continued_fraction_list(x, type='std', partial_convergents=False,
|
|
2339
|
+
bits=None, nterms=None):
|
|
2340
|
+
r"""
|
|
2341
|
+
Return the (finite) continued fraction of ``x`` as a list.
|
|
2342
|
+
|
|
2343
|
+
The continued fraction expansion of ``x`` are the coefficients `a_i` in
|
|
2344
|
+
|
|
2345
|
+
.. MATH::
|
|
2346
|
+
|
|
2347
|
+
x = a_0 + 1/(a_1 + 1/(...))
|
|
2348
|
+
|
|
2349
|
+
with `a_0` integer and `a_1`, `...` positive integers. The Hirzebruch-Jung
|
|
2350
|
+
continued fraction is the one for which the `+` signs are replaced with `-`
|
|
2351
|
+
signs
|
|
2352
|
+
|
|
2353
|
+
.. MATH::
|
|
2354
|
+
|
|
2355
|
+
x = a_0 - 1/(a_1 - 1/(...))
|
|
2356
|
+
|
|
2357
|
+
.. SEEALSO::
|
|
2358
|
+
|
|
2359
|
+
:func:`continued_fraction`
|
|
2360
|
+
|
|
2361
|
+
INPUT:
|
|
2362
|
+
|
|
2363
|
+
- ``x`` -- exact rational or floating-point number; the number to
|
|
2364
|
+
compute the continued fraction of
|
|
2365
|
+
|
|
2366
|
+
- ``type`` -- either ``'std'`` (default) for standard continued fractions or
|
|
2367
|
+
``'hj'`` for Hirzebruch-Jung ones
|
|
2368
|
+
|
|
2369
|
+
- ``partial_convergents`` -- boolean; whether to return the
|
|
2370
|
+
partial convergents
|
|
2371
|
+
|
|
2372
|
+
- ``bits`` -- an optional integer that specify a precision for the real
|
|
2373
|
+
interval field that is used internally
|
|
2374
|
+
|
|
2375
|
+
- ``nterms`` -- integer; the upper bound on the number of terms in
|
|
2376
|
+
the continued fraction expansion to return
|
|
2377
|
+
|
|
2378
|
+
OUTPUT:
|
|
2379
|
+
|
|
2380
|
+
A list of integers, the coefficients in the continued fraction expansion of
|
|
2381
|
+
``x``. If ``partial_convergents`` is set to ``True``, then return a pair
|
|
2382
|
+
containing the coefficient list and the partial convergents list is
|
|
2383
|
+
returned.
|
|
2384
|
+
|
|
2385
|
+
EXAMPLES::
|
|
2386
|
+
|
|
2387
|
+
sage: continued_fraction_list(45/19)
|
|
2388
|
+
[2, 2, 1, 2, 2]
|
|
2389
|
+
sage: 2 + 1/(2 + 1/(1 + 1/(2 + 1/2)))
|
|
2390
|
+
45/19
|
|
2391
|
+
|
|
2392
|
+
sage: continued_fraction_list(45/19, type='hj')
|
|
2393
|
+
[3, 2, 3, 2, 3]
|
|
2394
|
+
sage: 3 - 1/(2 - 1/(3 - 1/(2 - 1/3)))
|
|
2395
|
+
45/19
|
|
2396
|
+
|
|
2397
|
+
Specifying ``bits`` or ``nterms`` modify the length of the output::
|
|
2398
|
+
|
|
2399
|
+
sage: # needs sage.symbolic
|
|
2400
|
+
sage: continued_fraction_list(e, bits=20)
|
|
2401
|
+
[2, 1, 2, 1, 1, 4, 2]
|
|
2402
|
+
sage: continued_fraction_list(sqrt(2) + sqrt(3), bits=30)
|
|
2403
|
+
[3, 6, 1, 5, 7, 2]
|
|
2404
|
+
sage: continued_fraction_list(pi, bits=53)
|
|
2405
|
+
[3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14]
|
|
2406
|
+
sage: continued_fraction_list(log(3/2), nterms=15)
|
|
2407
|
+
[0, 2, 2, 6, 1, 11, 2, 1, 2, 2, 1, 4, 3, 1, 1]
|
|
2408
|
+
sage: continued_fraction_list(tan(sqrt(pi)), nterms=20)
|
|
2409
|
+
[-5, 9, 4, 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 2, 4, 3, 1, 63]
|
|
2410
|
+
|
|
2411
|
+
When the continued fraction is infinite (ie ``x`` is an irrational number)
|
|
2412
|
+
and the parameters ``bits`` and ``nterms`` are not specified then a warning
|
|
2413
|
+
is raised::
|
|
2414
|
+
|
|
2415
|
+
sage: continued_fraction_list(sqrt(2)) # needs sage.symbolic
|
|
2416
|
+
doctest:...: UserWarning: the continued fraction of sqrt(2) seems infinite,
|
|
2417
|
+
return only the first 20 terms
|
|
2418
|
+
[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
|
|
2419
|
+
sage: continued_fraction_list(sqrt(4/19)) # needs sage.symbolic
|
|
2420
|
+
doctest:...: UserWarning: the continued fraction of 2*sqrt(1/19) seems infinite,
|
|
2421
|
+
return only the first 20 terms
|
|
2422
|
+
[0, 2, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1, 16]
|
|
2423
|
+
|
|
2424
|
+
An examples with the list of partial convergents::
|
|
2425
|
+
|
|
2426
|
+
sage: continued_fraction_list(RR(pi), partial_convergents=True) # needs sage.symbolic
|
|
2427
|
+
([3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3],
|
|
2428
|
+
[(3, 1),
|
|
2429
|
+
(22, 7),
|
|
2430
|
+
(333, 106),
|
|
2431
|
+
(355, 113),
|
|
2432
|
+
(103993, 33102),
|
|
2433
|
+
(104348, 33215),
|
|
2434
|
+
(208341, 66317),
|
|
2435
|
+
(312689, 99532),
|
|
2436
|
+
(833719, 265381),
|
|
2437
|
+
(1146408, 364913),
|
|
2438
|
+
(4272943, 1360120),
|
|
2439
|
+
(5419351, 1725033),
|
|
2440
|
+
(80143857, 25510582),
|
|
2441
|
+
(245850922, 78256779)])
|
|
2442
|
+
|
|
2443
|
+
TESTS::
|
|
2444
|
+
|
|
2445
|
+
sage: continued_fraction_list(1 + 10^-10, nterms=3)
|
|
2446
|
+
[1, 10000000000]
|
|
2447
|
+
sage: continued_fraction_list(1 + 10^-20 - e^-100, nterms=3) # needs sage.symbolic
|
|
2448
|
+
[1, 100000000000000000000, 2688]
|
|
2449
|
+
sage: continued_fraction_list(1 + 10^-20 - e^-100, nterms=5) # needs sage.symbolic
|
|
2450
|
+
[1, 100000000000000000000, 2688, 8, 1]
|
|
2451
|
+
sage: continued_fraction_list(1 + 10^-20 - e^-100, nterms=5) # needs sage.symbolic
|
|
2452
|
+
[1, 100000000000000000000, 2688, 8, 1]
|
|
2453
|
+
|
|
2454
|
+
Fixed :issue:`18901`::
|
|
2455
|
+
|
|
2456
|
+
sage: a = 1.575709393346379
|
|
2457
|
+
sage: type(a) # needs sage.rings.real_mpfr
|
|
2458
|
+
<class 'sage.rings.real_mpfr.RealLiteral'>
|
|
2459
|
+
sage: continued_fraction_list(a)
|
|
2460
|
+
[1, 1, 1, 2, 1, 4, 18, 1, 5, 2, 25037802, 7, 1, 3, 1, 28, 1, 8, 2]
|
|
2461
|
+
|
|
2462
|
+
Check that this works for arb elements (:issue:`20069`)::
|
|
2463
|
+
|
|
2464
|
+
sage: continued_fraction(RBF(e)) # needs sage.symbolic
|
|
2465
|
+
[2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12]
|
|
2466
|
+
"""
|
|
2467
|
+
from .rational_field import QQ
|
|
2468
|
+
|
|
2469
|
+
try:
|
|
2470
|
+
return x.continued_fraction_list(type=type)
|
|
2471
|
+
except AttributeError:
|
|
2472
|
+
pass
|
|
2473
|
+
|
|
2474
|
+
if bits is not None:
|
|
2475
|
+
from .real_mpfi import RealIntervalField
|
|
2476
|
+
x = RealIntervalField(bits)(x)
|
|
2477
|
+
|
|
2478
|
+
if type == "hj":
|
|
2479
|
+
l = QQ(x).continued_fraction_list("hj")
|
|
2480
|
+
# The C-code in sage.rings.rational is much more faster than the pure
|
|
2481
|
+
# Python below
|
|
2482
|
+
# v = []
|
|
2483
|
+
# while True:
|
|
2484
|
+
# div, mod = divmod(x.numerator(), x.denominator())
|
|
2485
|
+
# if mod == 0:
|
|
2486
|
+
# v.append(div)
|
|
2487
|
+
# break
|
|
2488
|
+
# v.append(div+1)
|
|
2489
|
+
# if nterms is not None and len(v) >= nterms:
|
|
2490
|
+
# break
|
|
2491
|
+
# x = 1/(div+1-x)
|
|
2492
|
+
# return v
|
|
2493
|
+
if nterms is None:
|
|
2494
|
+
return l
|
|
2495
|
+
return l[:nterms]
|
|
2496
|
+
|
|
2497
|
+
if type != "std":
|
|
2498
|
+
raise ValueError("type must be either \"std\" or \"hj\"")
|
|
2499
|
+
|
|
2500
|
+
cf = None
|
|
2501
|
+
|
|
2502
|
+
try:
|
|
2503
|
+
from sage.rings.real_mpfr import RealLiteral
|
|
2504
|
+
except ImportError:
|
|
2505
|
+
RealLiteral = ()
|
|
2506
|
+
if isinstance(x, RealLiteral):
|
|
2507
|
+
from sage.rings.real_mpfi import RealIntervalField
|
|
2508
|
+
x = RealIntervalField(x.prec())(x)
|
|
2509
|
+
if isinstance(x.parent(), (sage.rings.abc.RealIntervalField, sage.rings.abc.RealBallField)):
|
|
2510
|
+
cf = continued_fraction(rat_interval_cf_list(
|
|
2511
|
+
x.lower().exact_rational(),
|
|
2512
|
+
x.upper().exact_rational()))
|
|
2513
|
+
|
|
2514
|
+
if cf is None:
|
|
2515
|
+
try:
|
|
2516
|
+
cf = continued_fraction(x)
|
|
2517
|
+
except ValueError:
|
|
2518
|
+
pass
|
|
2519
|
+
|
|
2520
|
+
if cf is None:
|
|
2521
|
+
raise ValueError("does not know how to compute the continued fraction of %s" % x)
|
|
2522
|
+
|
|
2523
|
+
if nterms:
|
|
2524
|
+
limit = min(cf.length(), nterms)
|
|
2525
|
+
elif cf.length() != Infinity:
|
|
2526
|
+
limit = cf.length()
|
|
2527
|
+
else:
|
|
2528
|
+
import warnings
|
|
2529
|
+
warnings.warn("the continued fraction of %s seems infinite, return only the first 20 terms" % x)
|
|
2530
|
+
limit = 20
|
|
2531
|
+
if partial_convergents:
|
|
2532
|
+
return ([cf.quotient(i) for i in range(limit)],
|
|
2533
|
+
[(cf.numerator(i), cf.denominator(i)) for i in range(limit)])
|
|
2534
|
+
return [cf.quotient(i) for i in range(limit)]
|
|
2535
|
+
|
|
2536
|
+
|
|
2537
|
+
def continued_fraction(x, value=None):
|
|
2538
|
+
r"""
|
|
2539
|
+
Return the continued fraction of `x`.
|
|
2540
|
+
|
|
2541
|
+
INPUT:
|
|
2542
|
+
|
|
2543
|
+
- ``x`` -- a number or a list of partial quotients (for finite
|
|
2544
|
+
development) or two list of partial quotients (preperiod and period
|
|
2545
|
+
for ultimately periodic development)
|
|
2546
|
+
|
|
2547
|
+
EXAMPLES:
|
|
2548
|
+
|
|
2549
|
+
A finite continued fraction may be initialized by a number or by its list of
|
|
2550
|
+
partial quotients::
|
|
2551
|
+
|
|
2552
|
+
sage: continued_fraction(12/571)
|
|
2553
|
+
[0; 47, 1, 1, 2, 2]
|
|
2554
|
+
sage: continued_fraction([3,2,1,4])
|
|
2555
|
+
[3; 2, 1, 4]
|
|
2556
|
+
|
|
2557
|
+
It can be called with elements defined from symbolic values, in which case
|
|
2558
|
+
the partial quotients are evaluated in a lazy way::
|
|
2559
|
+
|
|
2560
|
+
sage: c = continued_fraction(golden_ratio); c # needs sage.symbolic
|
|
2561
|
+
[1; 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...]
|
|
2562
|
+
sage: c.convergent(12) # needs sage.symbolic
|
|
2563
|
+
377/233
|
|
2564
|
+
sage: fibonacci(14)/fibonacci(13) # needs sage.libs.pari
|
|
2565
|
+
377/233
|
|
2566
|
+
|
|
2567
|
+
sage: # needs sage.symbolic
|
|
2568
|
+
sage: continued_fraction(pi)
|
|
2569
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
2570
|
+
sage: c = continued_fraction(pi); c
|
|
2571
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
2572
|
+
sage: a = c.convergent(3); a
|
|
2573
|
+
355/113
|
|
2574
|
+
sage: a.n()
|
|
2575
|
+
3.14159292035398
|
|
2576
|
+
sage: pi.n()
|
|
2577
|
+
3.14159265358979
|
|
2578
|
+
|
|
2579
|
+
sage: # needs sage.symbolic
|
|
2580
|
+
sage: continued_fraction(sqrt(2))
|
|
2581
|
+
[1; 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...]
|
|
2582
|
+
sage: continued_fraction(tan(1))
|
|
2583
|
+
[1; 1, 1, 3, 1, 5, 1, 7, 1, 9, 1, 11, 1, 13, 1, 15, 1, 17, 1, 19, ...]
|
|
2584
|
+
sage: continued_fraction(tanh(1))
|
|
2585
|
+
[0; 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, ...]
|
|
2586
|
+
sage: continued_fraction(e)
|
|
2587
|
+
[2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, ...]
|
|
2588
|
+
|
|
2589
|
+
If you want to play with quadratic numbers (such as ``golden_ratio`` and
|
|
2590
|
+
``sqrt(2)`` above), it is much more convenient to use number fields as
|
|
2591
|
+
follows since preperiods and periods are computed::
|
|
2592
|
+
|
|
2593
|
+
sage: # needs sage.rings.number_field
|
|
2594
|
+
sage: x = polygen(ZZ, 'x')
|
|
2595
|
+
sage: K.<sqrt5> = NumberField(x^2 - 5, embedding=2.23)
|
|
2596
|
+
sage: my_golden_ratio = (1 + sqrt5)/2
|
|
2597
|
+
sage: cf = continued_fraction((1+sqrt5)/2); cf
|
|
2598
|
+
[(1)*]
|
|
2599
|
+
sage: cf.convergent(12)
|
|
2600
|
+
377/233
|
|
2601
|
+
sage: cf.period()
|
|
2602
|
+
(1,)
|
|
2603
|
+
sage: cf = continued_fraction(2/3+sqrt5/5); cf
|
|
2604
|
+
[1; 8, (1, 3, 1, 1, 3, 9)*]
|
|
2605
|
+
sage: cf.preperiod()
|
|
2606
|
+
(1, 8)
|
|
2607
|
+
sage: cf.period()
|
|
2608
|
+
(1, 3, 1, 1, 3, 9)
|
|
2609
|
+
|
|
2610
|
+
sage: # needs sage.rings.number_field
|
|
2611
|
+
sage: L.<sqrt2> = NumberField(x^2 - 2, embedding=1.41)
|
|
2612
|
+
sage: cf = continued_fraction(sqrt2); cf
|
|
2613
|
+
[1; (2)*]
|
|
2614
|
+
sage: cf.period()
|
|
2615
|
+
(2,)
|
|
2616
|
+
sage: cf = continued_fraction(sqrt2/3); cf
|
|
2617
|
+
[0; 2, (8, 4)*]
|
|
2618
|
+
sage: cf.period()
|
|
2619
|
+
(8, 4)
|
|
2620
|
+
|
|
2621
|
+
It is also possible to go the other way around, build a ultimately periodic
|
|
2622
|
+
continued fraction from its preperiod and its period and get its value
|
|
2623
|
+
back::
|
|
2624
|
+
|
|
2625
|
+
sage: cf = continued_fraction([(1,1), (2,8)]); cf
|
|
2626
|
+
[1; 1, (2, 8)*]
|
|
2627
|
+
sage: cf.value() # needs sage.rings.number_field
|
|
2628
|
+
2/11*sqrt5 + 14/11
|
|
2629
|
+
|
|
2630
|
+
It is possible to deal with higher degree number fields but in that case the
|
|
2631
|
+
continued fraction expansion is known to be aperiodic::
|
|
2632
|
+
|
|
2633
|
+
sage: K.<a> = NumberField(x^3 - 2, embedding=1.25) # needs sage.rings.number_field
|
|
2634
|
+
sage: cf = continued_fraction(a); cf # needs sage.rings.number_field
|
|
2635
|
+
[1; 3, 1, 5, 1, 1, 4, 1, 1, 8, 1, 14, 1, 10, 2, 1, 4, 12, 2, 3, ...]
|
|
2636
|
+
|
|
2637
|
+
Note that initial rounding can result in incorrect trailing partial
|
|
2638
|
+
quotients::
|
|
2639
|
+
|
|
2640
|
+
sage: continued_fraction(RealField(39)(e)) # needs sage.symbolic
|
|
2641
|
+
[2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 2]
|
|
2642
|
+
|
|
2643
|
+
Note the value returned for floating point number is the continued fraction
|
|
2644
|
+
associated to the rational number you obtain with a conversion::
|
|
2645
|
+
|
|
2646
|
+
sage: for _ in range(10):
|
|
2647
|
+
....: x = RR.random_element()
|
|
2648
|
+
....: cff = continued_fraction(x)
|
|
2649
|
+
....: cfe = QQ(x).continued_fraction()
|
|
2650
|
+
....: assert cff == cfe, "%s %s %s"%(x,cff,cfe)
|
|
2651
|
+
|
|
2652
|
+
TESTS:
|
|
2653
|
+
|
|
2654
|
+
Fixed :issue:`18901`. For RealLiteral, continued_fraction calls
|
|
2655
|
+
continued_fraction_list::
|
|
2656
|
+
|
|
2657
|
+
sage: continued_fraction(1.575709393346379)
|
|
2658
|
+
[1; 1, 1, 2, 1, 4, 18, 1, 5, 2, 25037802, 7, 1, 3, 1, 28, 1, 8, 2]
|
|
2659
|
+
|
|
2660
|
+
Constants in symbolic subrings work like constants in ``SR``::
|
|
2661
|
+
|
|
2662
|
+
sage: SCR = SR.subring(no_variables=True) # needs sage.symbolic
|
|
2663
|
+
sage: continued_fraction(SCR(pi)) # needs sage.symbolic
|
|
2664
|
+
[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...]
|
|
2665
|
+
"""
|
|
2666
|
+
|
|
2667
|
+
if isinstance(x, ContinuedFraction_base):
|
|
2668
|
+
return x
|
|
2669
|
+
|
|
2670
|
+
try:
|
|
2671
|
+
return x.continued_fraction()
|
|
2672
|
+
except AttributeError:
|
|
2673
|
+
pass
|
|
2674
|
+
|
|
2675
|
+
# input for finite or ultimately periodic partial quotient expansion
|
|
2676
|
+
if isinstance(x, FiniteWord_class):
|
|
2677
|
+
x = list(x)
|
|
2678
|
+
|
|
2679
|
+
if isinstance(x, (list, tuple)):
|
|
2680
|
+
if len(x) == 2 and isinstance(x[0], (list, tuple)) and isinstance(x[1], (list, tuple)):
|
|
2681
|
+
x1 = tuple(Integer(a) for a in x[0])
|
|
2682
|
+
x2 = tuple(Integer(a) for a in x[1])
|
|
2683
|
+
x1, x2 = check_and_reduce_pair(x1, x2)
|
|
2684
|
+
else:
|
|
2685
|
+
x1, x2 = check_and_reduce_pair(x)
|
|
2686
|
+
return ContinuedFraction_periodic(x1, x2)
|
|
2687
|
+
|
|
2688
|
+
# input for infinite partial quotient expansion
|
|
2689
|
+
from sage.misc.lazy_list import lazy_list_generic
|
|
2690
|
+
if isinstance(x, (lazy_list_generic, InfiniteWord_class)):
|
|
2691
|
+
return ContinuedFraction_infinite(x, value)
|
|
2692
|
+
|
|
2693
|
+
if isinstance(x, Word_class):
|
|
2694
|
+
raise ValueError("word with unknown length cannot be converted "
|
|
2695
|
+
"to continued fractions")
|
|
2696
|
+
|
|
2697
|
+
# input for numbers
|
|
2698
|
+
# TODO: the approach used below might be not what the user expects as we
|
|
2699
|
+
# have currently in sage (version 6.8)
|
|
2700
|
+
#
|
|
2701
|
+
# sage: RR.random_element() in QQ
|
|
2702
|
+
# True
|
|
2703
|
+
#
|
|
2704
|
+
# But, be careful with real literals
|
|
2705
|
+
#
|
|
2706
|
+
# sage: a = 1.575709393346379
|
|
2707
|
+
# sage: a in QQ
|
|
2708
|
+
# False
|
|
2709
|
+
from .rational_field import QQ
|
|
2710
|
+
if x in QQ:
|
|
2711
|
+
return QQ(x).continued_fraction()
|
|
2712
|
+
|
|
2713
|
+
is_real = False
|
|
2714
|
+
try:
|
|
2715
|
+
is_real = x.is_real()
|
|
2716
|
+
except AttributeError:
|
|
2717
|
+
pass
|
|
2718
|
+
|
|
2719
|
+
if is_real is False:
|
|
2720
|
+
from .real_mpfi import RealIntervalField
|
|
2721
|
+
# we cannot rely on the answer of .is_real() for elements of the
|
|
2722
|
+
# symbolic ring. The thing below is a dirty temporary hack.
|
|
2723
|
+
RIF = RealIntervalField(53)
|
|
2724
|
+
try:
|
|
2725
|
+
RIF(x)
|
|
2726
|
+
is_real = True
|
|
2727
|
+
except (AttributeError, ValueError):
|
|
2728
|
+
pass
|
|
2729
|
+
|
|
2730
|
+
if is_real is False:
|
|
2731
|
+
raise ValueError("the number %s does not seem to be a real number" % x)
|
|
2732
|
+
|
|
2733
|
+
if x.parent().is_exact():
|
|
2734
|
+
return ContinuedFraction_real(x)
|
|
2735
|
+
|
|
2736
|
+
# We treat the Symbolic Ring and its subrings separately. They hold all constants and
|
|
2737
|
+
# are not exact.
|
|
2738
|
+
if isinstance(x.parent(), sage.rings.abc.SymbolicRing):
|
|
2739
|
+
return ContinuedFraction_real(x)
|
|
2740
|
+
|
|
2741
|
+
return continued_fraction(continued_fraction_list(x))
|
|
2742
|
+
|
|
2743
|
+
|
|
2744
|
+
def convergents(x):
|
|
2745
|
+
r"""
|
|
2746
|
+
Return the (partial) convergents of the number ``x``.
|
|
2747
|
+
|
|
2748
|
+
EXAMPLES::
|
|
2749
|
+
|
|
2750
|
+
sage: from sage.rings.continued_fraction import convergents
|
|
2751
|
+
sage: convergents(143/255)
|
|
2752
|
+
[0, 1, 1/2, 4/7, 5/9, 9/16, 14/25, 23/41, 60/107, 143/255]
|
|
2753
|
+
"""
|
|
2754
|
+
return continued_fraction(x).convergents()
|