passagemath-objects 10.6.44__cp314-cp314t-macosx_13_0_arm64.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_objects/.dylibs/libgmp.10.dylib +0 -0
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.44.dist-info/METADATA +115 -0
- passagemath_objects-10.6.44.dist-info/RECORD +280 -0
- passagemath_objects-10.6.44.dist-info/WHEEL +6 -0
- passagemath_objects-10.6.44.dist-info/top_level.txt +3 -0
- sage/all__sagemath_objects.py +37 -0
- sage/arith/all__sagemath_objects.py +5 -0
- sage/arith/long.pxd +411 -0
- sage/arith/numerical_approx.cpython-314t-darwin.so +0 -0
- sage/arith/numerical_approx.pxd +35 -0
- sage/arith/numerical_approx.pyx +75 -0
- sage/arith/power.cpython-314t-darwin.so +0 -0
- sage/arith/power.pxd +31 -0
- sage/arith/power.pyx +127 -0
- sage/categories/action.cpython-314t-darwin.so +0 -0
- sage/categories/action.pxd +29 -0
- sage/categories/action.pyx +641 -0
- sage/categories/algebra_functor.py +745 -0
- sage/categories/all__sagemath_objects.py +33 -0
- sage/categories/basic.py +62 -0
- sage/categories/cartesian_product.py +295 -0
- sage/categories/category.py +3401 -0
- sage/categories/category_cy_helper.cpython-314t-darwin.so +0 -0
- sage/categories/category_cy_helper.pxd +8 -0
- sage/categories/category_cy_helper.pyx +322 -0
- sage/categories/category_singleton.cpython-314t-darwin.so +0 -0
- sage/categories/category_singleton.pxd +3 -0
- sage/categories/category_singleton.pyx +342 -0
- sage/categories/category_types.py +637 -0
- sage/categories/category_with_axiom.py +2876 -0
- sage/categories/covariant_functorial_construction.py +703 -0
- sage/categories/facade_sets.py +228 -0
- sage/categories/functor.cpython-314t-darwin.so +0 -0
- sage/categories/functor.pxd +7 -0
- sage/categories/functor.pyx +691 -0
- sage/categories/homset.py +1338 -0
- sage/categories/homsets.py +364 -0
- sage/categories/isomorphic_objects.py +73 -0
- sage/categories/map.cpython-314t-darwin.so +0 -0
- sage/categories/map.pxd +34 -0
- sage/categories/map.pyx +2106 -0
- sage/categories/morphism.cpython-314t-darwin.so +0 -0
- sage/categories/morphism.pxd +14 -0
- sage/categories/morphism.pyx +895 -0
- sage/categories/objects.py +167 -0
- sage/categories/primer.py +1696 -0
- sage/categories/pushout.py +4834 -0
- sage/categories/quotients.py +64 -0
- sage/categories/realizations.py +200 -0
- sage/categories/sets_cat.py +3290 -0
- sage/categories/sets_with_partial_maps.py +52 -0
- sage/categories/subobjects.py +64 -0
- sage/categories/subquotients.py +21 -0
- sage/categories/with_realizations.py +311 -0
- sage/cpython/__init__.py +19 -0
- sage/cpython/_py2_random.py +619 -0
- sage/cpython/all.py +3 -0
- sage/cpython/atexit.cpython-314t-darwin.so +0 -0
- sage/cpython/atexit.pyx +269 -0
- sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
- sage/cpython/builtin_types.pyx +7 -0
- sage/cpython/cython_metaclass.cpython-314t-darwin.so +0 -0
- sage/cpython/cython_metaclass.h +117 -0
- sage/cpython/cython_metaclass.pxd +3 -0
- sage/cpython/cython_metaclass.pyx +130 -0
- sage/cpython/debug.cpython-314t-darwin.so +0 -0
- sage/cpython/debug.pyx +302 -0
- sage/cpython/dict_del_by_value.cpython-314t-darwin.so +0 -0
- sage/cpython/dict_del_by_value.pxd +9 -0
- sage/cpython/dict_del_by_value.pyx +191 -0
- sage/cpython/dict_internal.h +245 -0
- sage/cpython/getattr.cpython-314t-darwin.so +0 -0
- sage/cpython/getattr.pxd +9 -0
- sage/cpython/getattr.pyx +439 -0
- sage/cpython/pycore_long.h +97 -0
- sage/cpython/pycore_long.pxd +10 -0
- sage/cpython/python_debug.h +44 -0
- sage/cpython/python_debug.pxd +47 -0
- sage/cpython/pyx_visit.h +13 -0
- sage/cpython/string.cpython-314t-darwin.so +0 -0
- sage/cpython/string.pxd +76 -0
- sage/cpython/string.pyx +34 -0
- sage/cpython/string_impl.h +60 -0
- sage/cpython/type.cpython-314t-darwin.so +0 -0
- sage/cpython/type.pxd +2 -0
- sage/cpython/type.pyx +40 -0
- sage/cpython/wrapperdescr.pxd +67 -0
- sage/ext/all__sagemath_objects.py +3 -0
- sage/ext/ccobject.h +64 -0
- sage/ext/cplusplus.pxd +17 -0
- sage/ext/mod_int.h +30 -0
- sage/ext/mod_int.pxd +24 -0
- sage/ext/stdsage.pxd +39 -0
- sage/groups/all__sagemath_objects.py +1 -0
- sage/groups/group.cpython-314t-darwin.so +0 -0
- sage/groups/group.pxd +14 -0
- sage/groups/group.pyx +322 -0
- sage/groups/old.cpython-314t-darwin.so +0 -0
- sage/groups/old.pxd +14 -0
- sage/groups/old.pyx +219 -0
- sage/libs/all__sagemath_objects.py +3 -0
- sage/libs/gmp/__init__.py +1 -0
- sage/libs/gmp/all.pxd +6 -0
- sage/libs/gmp/binop.pxd +23 -0
- sage/libs/gmp/misc.pxd +8 -0
- sage/libs/gmp/mpf.pxd +88 -0
- sage/libs/gmp/mpn.pxd +57 -0
- sage/libs/gmp/mpq.pxd +57 -0
- sage/libs/gmp/mpz.pxd +202 -0
- sage/libs/gmp/pylong.cpython-314t-darwin.so +0 -0
- sage/libs/gmp/pylong.pxd +12 -0
- sage/libs/gmp/pylong.pyx +150 -0
- sage/libs/gmp/random.pxd +25 -0
- sage/libs/gmp/randomize.pxd +59 -0
- sage/libs/gmp/types.pxd +53 -0
- sage/libs/gmpxx.pxd +19 -0
- sage/misc/abstract_method.py +276 -0
- sage/misc/all__sagemath_objects.py +43 -0
- sage/misc/bindable_class.py +253 -0
- sage/misc/c3_controlled.cpython-314t-darwin.so +0 -0
- sage/misc/c3_controlled.pxd +2 -0
- sage/misc/c3_controlled.pyx +1402 -0
- sage/misc/cachefunc.cpython-314t-darwin.so +0 -0
- sage/misc/cachefunc.pxd +43 -0
- sage/misc/cachefunc.pyx +3781 -0
- sage/misc/call.py +188 -0
- sage/misc/classcall_metaclass.cpython-314t-darwin.so +0 -0
- sage/misc/classcall_metaclass.pxd +14 -0
- sage/misc/classcall_metaclass.pyx +599 -0
- sage/misc/constant_function.cpython-314t-darwin.so +0 -0
- sage/misc/constant_function.pyx +130 -0
- sage/misc/decorators.py +747 -0
- sage/misc/fast_methods.cpython-314t-darwin.so +0 -0
- sage/misc/fast_methods.pxd +20 -0
- sage/misc/fast_methods.pyx +351 -0
- sage/misc/flatten.py +90 -0
- sage/misc/fpickle.cpython-314t-darwin.so +0 -0
- sage/misc/fpickle.pyx +177 -0
- sage/misc/function_mangling.cpython-314t-darwin.so +0 -0
- sage/misc/function_mangling.pxd +11 -0
- sage/misc/function_mangling.pyx +308 -0
- sage/misc/inherit_comparison.cpython-314t-darwin.so +0 -0
- sage/misc/inherit_comparison.pxd +5 -0
- sage/misc/inherit_comparison.pyx +105 -0
- sage/misc/instancedoc.cpython-314t-darwin.so +0 -0
- sage/misc/instancedoc.pyx +331 -0
- sage/misc/lazy_attribute.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_attribute.pyx +607 -0
- sage/misc/lazy_format.py +135 -0
- sage/misc/lazy_import.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_import.pyx +1299 -0
- sage/misc/lazy_import_cache.py +36 -0
- sage/misc/lazy_list.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_list.pxd +19 -0
- sage/misc/lazy_list.pyx +1187 -0
- sage/misc/lazy_string.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_string.pxd +7 -0
- sage/misc/lazy_string.pyx +546 -0
- sage/misc/misc.py +1066 -0
- sage/misc/misc_c.cpython-314t-darwin.so +0 -0
- sage/misc/misc_c.pxd +3 -0
- sage/misc/misc_c.pyx +766 -0
- sage/misc/namespace_package.py +37 -0
- sage/misc/nested_class.cpython-314t-darwin.so +0 -0
- sage/misc/nested_class.pxd +3 -0
- sage/misc/nested_class.pyx +394 -0
- sage/misc/persist.cpython-314t-darwin.so +0 -0
- sage/misc/persist.pyx +1251 -0
- sage/misc/prandom.py +418 -0
- sage/misc/randstate.cpython-314t-darwin.so +0 -0
- sage/misc/randstate.pxd +30 -0
- sage/misc/randstate.pyx +1059 -0
- sage/misc/repr.py +203 -0
- sage/misc/reset.cpython-314t-darwin.so +0 -0
- sage/misc/reset.pyx +196 -0
- sage/misc/sage_ostools.cpython-314t-darwin.so +0 -0
- sage/misc/sage_ostools.pyx +323 -0
- sage/misc/sage_timeit.py +275 -0
- sage/misc/sage_timeit_class.cpython-314t-darwin.so +0 -0
- sage/misc/sage_timeit_class.pyx +120 -0
- sage/misc/sage_unittest.py +637 -0
- sage/misc/sageinspect.py +2768 -0
- sage/misc/session.cpython-314t-darwin.so +0 -0
- sage/misc/session.pyx +392 -0
- sage/misc/superseded.py +557 -0
- sage/misc/test_nested_class.py +228 -0
- sage/misc/timing.py +264 -0
- sage/misc/unknown.py +222 -0
- sage/misc/verbose.py +253 -0
- sage/misc/weak_dict.cpython-314t-darwin.so +0 -0
- sage/misc/weak_dict.pxd +15 -0
- sage/misc/weak_dict.pyx +1231 -0
- sage/modules/all__sagemath_objects.py +1 -0
- sage/modules/module.cpython-314t-darwin.so +0 -0
- sage/modules/module.pxd +5 -0
- sage/modules/module.pyx +329 -0
- sage/rings/all__sagemath_objects.py +3 -0
- sage/rings/integer_fake.h +22 -0
- sage/rings/integer_fake.pxd +55 -0
- sage/sets/all__sagemath_objects.py +3 -0
- sage/sets/pythonclass.cpython-314t-darwin.so +0 -0
- sage/sets/pythonclass.pxd +9 -0
- sage/sets/pythonclass.pyx +247 -0
- sage/structure/__init__.py +4 -0
- sage/structure/all.py +30 -0
- sage/structure/category_object.cpython-314t-darwin.so +0 -0
- sage/structure/category_object.pxd +28 -0
- sage/structure/category_object.pyx +1087 -0
- sage/structure/coerce.cpython-314t-darwin.so +0 -0
- sage/structure/coerce.pxd +44 -0
- sage/structure/coerce.pyx +2107 -0
- sage/structure/coerce_actions.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_actions.pxd +27 -0
- sage/structure/coerce_actions.pyx +988 -0
- sage/structure/coerce_dict.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_dict.pxd +51 -0
- sage/structure/coerce_dict.pyx +1557 -0
- sage/structure/coerce_exceptions.py +23 -0
- sage/structure/coerce_maps.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_maps.pxd +28 -0
- sage/structure/coerce_maps.pyx +718 -0
- sage/structure/debug_options.cpython-314t-darwin.so +0 -0
- sage/structure/debug_options.pxd +6 -0
- sage/structure/debug_options.pyx +54 -0
- sage/structure/dynamic_class.py +541 -0
- sage/structure/element.cpython-314t-darwin.so +0 -0
- sage/structure/element.pxd +272 -0
- sage/structure/element.pyx +4772 -0
- sage/structure/element_wrapper.cpython-314t-darwin.so +0 -0
- sage/structure/element_wrapper.pxd +12 -0
- sage/structure/element_wrapper.pyx +582 -0
- sage/structure/factorization.py +1422 -0
- sage/structure/factorization_integer.py +105 -0
- sage/structure/factory.cpython-314t-darwin.so +0 -0
- sage/structure/factory.pyx +786 -0
- sage/structure/formal_sum.py +489 -0
- sage/structure/gens_py.py +73 -0
- sage/structure/global_options.py +1743 -0
- sage/structure/indexed_generators.py +863 -0
- sage/structure/list_clone.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone.pxd +65 -0
- sage/structure/list_clone.pyx +1867 -0
- sage/structure/list_clone_demo.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_demo.pyx +248 -0
- sage/structure/list_clone_timings.py +179 -0
- sage/structure/list_clone_timings_cy.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_timings_cy.pyx +86 -0
- sage/structure/mutability.cpython-314t-darwin.so +0 -0
- sage/structure/mutability.pxd +21 -0
- sage/structure/mutability.pyx +348 -0
- sage/structure/nonexact.py +69 -0
- sage/structure/parent.cpython-314t-darwin.so +0 -0
- sage/structure/parent.pxd +112 -0
- sage/structure/parent.pyx +3093 -0
- sage/structure/parent_base.cpython-314t-darwin.so +0 -0
- sage/structure/parent_base.pxd +13 -0
- sage/structure/parent_base.pyx +44 -0
- sage/structure/parent_gens.cpython-314t-darwin.so +0 -0
- sage/structure/parent_gens.pxd +22 -0
- sage/structure/parent_gens.pyx +377 -0
- sage/structure/parent_old.cpython-314t-darwin.so +0 -0
- sage/structure/parent_old.pxd +25 -0
- sage/structure/parent_old.pyx +294 -0
- sage/structure/proof/__init__.py +1 -0
- sage/structure/proof/all.py +243 -0
- sage/structure/proof/proof.py +300 -0
- sage/structure/richcmp.cpython-314t-darwin.so +0 -0
- sage/structure/richcmp.pxd +213 -0
- sage/structure/richcmp.pyx +495 -0
- sage/structure/sage_object.cpython-314t-darwin.so +0 -0
- sage/structure/sage_object.pxd +3 -0
- sage/structure/sage_object.pyx +988 -0
- sage/structure/sage_object_test.py +19 -0
- sage/structure/sequence.py +937 -0
- sage/structure/set_factories.py +1178 -0
- sage/structure/set_factories_example.py +527 -0
- sage/structure/support_view.py +179 -0
- sage/structure/test_factory.py +56 -0
- sage/structure/unique_representation.py +1359 -0
sage/misc/misc_c.pyx
ADDED
|
@@ -0,0 +1,766 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
"""
|
|
3
|
+
Miscellaneous functions (Cython)
|
|
4
|
+
|
|
5
|
+
This file contains support for products, running totals, balanced
|
|
6
|
+
sums, and also a function to flush output from external library calls.
|
|
7
|
+
|
|
8
|
+
AUTHORS:
|
|
9
|
+
|
|
10
|
+
- William Stein (2005)
|
|
11
|
+
- Joel B. Mohler (2007-10-03): Reimplemented in Cython and optimized
|
|
12
|
+
- Robert Bradshaw (2007-10-26): Balanced product tree, other optimizations, (lazy) generator support
|
|
13
|
+
- Robert Bradshaw (2008-03-26): Balanced product tree for generators and iterators
|
|
14
|
+
- Stefan van Zwam (2013-06-06): Added bitset tests, some docstring cleanup
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# ****************************************************************************
|
|
18
|
+
# Copyright (C) 2005 William Stein <wstein@gmail.com>
|
|
19
|
+
#
|
|
20
|
+
# This program is free software: you can redistribute it and/or modify
|
|
21
|
+
# it under the terms of the GNU General Public License as published by
|
|
22
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
23
|
+
# (at your option) any later version.
|
|
24
|
+
# https://www.gnu.org/licenses/
|
|
25
|
+
# ****************************************************************************
|
|
26
|
+
from copy import copy
|
|
27
|
+
|
|
28
|
+
from cpython.sequence cimport *
|
|
29
|
+
from cpython.list cimport *
|
|
30
|
+
from cpython.tuple cimport *
|
|
31
|
+
from cpython.number cimport *
|
|
32
|
+
from libc.stdio cimport fflush
|
|
33
|
+
|
|
34
|
+
cdef extern from *:
|
|
35
|
+
bint PyGen_Check(x)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def running_total(L, start=None):
|
|
39
|
+
"""
|
|
40
|
+
Return a list where the `i`-th entry is the sum of all entries up to (and
|
|
41
|
+
including) `i`.
|
|
42
|
+
|
|
43
|
+
INPUT:
|
|
44
|
+
|
|
45
|
+
- ``L`` -- the list
|
|
46
|
+
- ``start`` -- (optional) a default start value
|
|
47
|
+
|
|
48
|
+
EXAMPLES::
|
|
49
|
+
|
|
50
|
+
sage: running_total(range(5))
|
|
51
|
+
[0, 1, 3, 6, 10]
|
|
52
|
+
sage: running_total("abcdef")
|
|
53
|
+
['a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef']
|
|
54
|
+
sage: running_total("abcdef", start="%")
|
|
55
|
+
['%a', '%ab', '%abc', '%abcd', '%abcde', '%abcdef']
|
|
56
|
+
sage: running_total([1..10], start=100)
|
|
57
|
+
[101, 103, 106, 110, 115, 121, 128, 136, 145, 155]
|
|
58
|
+
sage: running_total([])
|
|
59
|
+
[]
|
|
60
|
+
"""
|
|
61
|
+
running = []
|
|
62
|
+
total = start
|
|
63
|
+
for x in L:
|
|
64
|
+
if total is None:
|
|
65
|
+
# This is the first entry
|
|
66
|
+
total = x
|
|
67
|
+
else:
|
|
68
|
+
total += x
|
|
69
|
+
PyList_Append(running, total)
|
|
70
|
+
return running
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def prod(x, z=None, Py_ssize_t recursion_cutoff=5):
|
|
74
|
+
"""
|
|
75
|
+
Return the product of the elements in the list x.
|
|
76
|
+
|
|
77
|
+
If optional argument z is not given, start the product with the first
|
|
78
|
+
element of the list, otherwise use z. The empty product is the int 1 if z
|
|
79
|
+
is not specified, and is z if given.
|
|
80
|
+
|
|
81
|
+
This assumes that your multiplication is associative; we do not promise
|
|
82
|
+
which end of the list we start at.
|
|
83
|
+
|
|
84
|
+
.. SEEALSO::
|
|
85
|
+
|
|
86
|
+
For the symbolic product function, see :func:`sage.calculus.calculus.symbolic_product`.
|
|
87
|
+
|
|
88
|
+
EXAMPLES::
|
|
89
|
+
|
|
90
|
+
sage: prod([1,2,34])
|
|
91
|
+
68
|
|
92
|
+
sage: prod([2,3], 5)
|
|
93
|
+
30
|
|
94
|
+
sage: prod((1,2,3), 5)
|
|
95
|
+
30
|
|
96
|
+
sage: F = factor(-2006); F
|
|
97
|
+
-1 * 2 * 17 * 59
|
|
98
|
+
sage: prod(F)
|
|
99
|
+
-2006
|
|
100
|
+
|
|
101
|
+
AUTHORS:
|
|
102
|
+
|
|
103
|
+
- Joel B. Mohler (2007-10-03): Reimplemented in Cython and optimized
|
|
104
|
+
- Robert Bradshaw (2007-10-26): Balanced product tree, other optimizations, (lazy) generator support
|
|
105
|
+
- Robert Bradshaw (2008-03-26): Balanced product tree for generators and iterators
|
|
106
|
+
"""
|
|
107
|
+
cdef Py_ssize_t n
|
|
108
|
+
|
|
109
|
+
if type(x) is not list and type(x) is not tuple:
|
|
110
|
+
|
|
111
|
+
if not PyGen_Check(x):
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
return x.prod()
|
|
115
|
+
except AttributeError:
|
|
116
|
+
pass
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
return x.mul()
|
|
120
|
+
except AttributeError:
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
n = len(x)
|
|
125
|
+
if n < 1000: # arbitrary limit
|
|
126
|
+
x = list(x)
|
|
127
|
+
except TypeError:
|
|
128
|
+
pass
|
|
129
|
+
|
|
130
|
+
if type(x) is not list:
|
|
131
|
+
try:
|
|
132
|
+
return iterator_prod(x, z)
|
|
133
|
+
except StopIteration:
|
|
134
|
+
x = []
|
|
135
|
+
|
|
136
|
+
n = len(x)
|
|
137
|
+
|
|
138
|
+
if n == 0:
|
|
139
|
+
if z is None:
|
|
140
|
+
import sage.rings.integer
|
|
141
|
+
return sage.rings.integer.Integer(1)
|
|
142
|
+
else:
|
|
143
|
+
return z
|
|
144
|
+
|
|
145
|
+
prod = balanced_list_prod(x, 0, n, recursion_cutoff)
|
|
146
|
+
|
|
147
|
+
if z is not None:
|
|
148
|
+
prod = z * prod
|
|
149
|
+
|
|
150
|
+
return prod
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
cdef balanced_list_prod(L, Py_ssize_t offset, Py_ssize_t count, Py_ssize_t cutoff):
|
|
154
|
+
"""
|
|
155
|
+
INPUT:
|
|
156
|
+
|
|
157
|
+
- ``L`` -- the terms (MUST be a tuple or list)
|
|
158
|
+
- ``off`` -- offset in the list from which to start
|
|
159
|
+
- ``count`` -- how many terms in the product
|
|
160
|
+
- ``cutoff`` -- the minimum count to recurse on
|
|
161
|
+
|
|
162
|
+
OUTPUT:
|
|
163
|
+
|
|
164
|
+
``L[offset] * L[offset+1] * ... * L[offset+count-1]``
|
|
165
|
+
|
|
166
|
+
.. NOTE::
|
|
167
|
+
|
|
168
|
+
The parameter cutoff must be at least 1, and there is no reason to
|
|
169
|
+
ever make it less than 3. However, there are at least two advantages
|
|
170
|
+
to setting it higher (and consequently not recursing all the way
|
|
171
|
+
down the tree). First, one avoids the overhead of the function
|
|
172
|
+
calls at the base of the tree (which is the majority of them) and
|
|
173
|
+
second, it allows one to save on object creation if inplace
|
|
174
|
+
operations are used. The asymptotic gains should usually be at the
|
|
175
|
+
top of the tree anyway.
|
|
176
|
+
"""
|
|
177
|
+
cdef Py_ssize_t k
|
|
178
|
+
if count <= cutoff:
|
|
179
|
+
prod = <object>PySequence_Fast_GET_ITEM(L, offset)
|
|
180
|
+
for k from offset < k < offset + count:
|
|
181
|
+
prod *= <object>PySequence_Fast_GET_ITEM(L, k)
|
|
182
|
+
return prod
|
|
183
|
+
else:
|
|
184
|
+
k = (1 + count) >> 1
|
|
185
|
+
return balanced_list_prod(L, offset, k, cutoff) * balanced_list_prod(L, offset + k, count - k, cutoff)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
cpdef iterator_prod(L, z=None, bint multiply=True):
|
|
189
|
+
"""
|
|
190
|
+
Attempt to do a balanced product of an arbitrary and unknown length
|
|
191
|
+
sequence (such as a generator). Intermediate multiplications are always
|
|
192
|
+
done with subproducts of the same size (measured by the number of original
|
|
193
|
+
factors) up until the iterator terminates. This is optimal when and only
|
|
194
|
+
when there are exactly a power of two number of terms.
|
|
195
|
+
|
|
196
|
+
A StopIteration is raised if the iterator is empty and z is not given.
|
|
197
|
+
|
|
198
|
+
EXAMPLES::
|
|
199
|
+
|
|
200
|
+
sage: from sage.misc.misc_c import iterator_prod
|
|
201
|
+
sage: iterator_prod(1..5)
|
|
202
|
+
120
|
|
203
|
+
sage: iterator_prod([], z='anything')
|
|
204
|
+
'anything'
|
|
205
|
+
|
|
206
|
+
sage: from sage.misc.misc_c import NonAssociative
|
|
207
|
+
sage: L = [NonAssociative(label) for label in 'abcdef']
|
|
208
|
+
sage: iterator_prod(L)
|
|
209
|
+
(((a*b)*(c*d))*(e*f))
|
|
210
|
+
|
|
211
|
+
When ``multiply=False``, the items are added up instead (however this
|
|
212
|
+
interface should not be used directly, use :func:`balanced_sum` instead)::
|
|
213
|
+
|
|
214
|
+
sage: iterator_prod((1..5), multiply=False)
|
|
215
|
+
15
|
|
216
|
+
"""
|
|
217
|
+
cdef list sub_prods
|
|
218
|
+
L = iter(L)
|
|
219
|
+
if z is None:
|
|
220
|
+
sub_prods = [next(L)] * 10 # only take one element from L, the rest are just placeholders
|
|
221
|
+
# the list size can be dynamically increased later
|
|
222
|
+
else:
|
|
223
|
+
sub_prods = [z] * 10
|
|
224
|
+
|
|
225
|
+
cdef Py_ssize_t j
|
|
226
|
+
cdef Py_ssize_t i = 1
|
|
227
|
+
cdef Py_ssize_t tip = 0
|
|
228
|
+
|
|
229
|
+
for x in L:
|
|
230
|
+
i += 1
|
|
231
|
+
if i & 1:
|
|
232
|
+
# for odd i we extend the stack
|
|
233
|
+
tip += 1
|
|
234
|
+
if len(sub_prods) == tip:
|
|
235
|
+
sub_prods.append(x)
|
|
236
|
+
else:
|
|
237
|
+
sub_prods[tip] = x
|
|
238
|
+
continue
|
|
239
|
+
else:
|
|
240
|
+
# for even i we multiply the stack down
|
|
241
|
+
# by the number of factors of 2 in i
|
|
242
|
+
if multiply:
|
|
243
|
+
x = sub_prods[tip] * x
|
|
244
|
+
else:
|
|
245
|
+
x = sub_prods[tip] + x
|
|
246
|
+
for j from 1 <= j < 64:
|
|
247
|
+
if i & (1 << j):
|
|
248
|
+
break
|
|
249
|
+
tip -= 1
|
|
250
|
+
if multiply:
|
|
251
|
+
x = sub_prods[tip] * x
|
|
252
|
+
else:
|
|
253
|
+
x = sub_prods[tip] + x
|
|
254
|
+
sub_prods[tip] = x
|
|
255
|
+
|
|
256
|
+
while tip > 0:
|
|
257
|
+
tip -= 1
|
|
258
|
+
if multiply:
|
|
259
|
+
sub_prods[tip] *= sub_prods[tip + 1]
|
|
260
|
+
else:
|
|
261
|
+
sub_prods[tip] += sub_prods[tip + 1]
|
|
262
|
+
|
|
263
|
+
return sub_prods[0]
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class NonAssociative:
|
|
267
|
+
"""
|
|
268
|
+
This class is to test the balance nature of prod.
|
|
269
|
+
|
|
270
|
+
EXAMPLES::
|
|
271
|
+
|
|
272
|
+
sage: from sage.misc.misc_c import NonAssociative
|
|
273
|
+
sage: L = [NonAssociative(label) for label in 'abcdef']
|
|
274
|
+
sage: prod(L)
|
|
275
|
+
(((a*b)*c)*((d*e)*f))
|
|
276
|
+
sage: L = [NonAssociative(label) for label in range(20)]
|
|
277
|
+
sage: prod(L, recursion_cutoff=5)
|
|
278
|
+
((((((0*1)*2)*3)*4)*((((5*6)*7)*8)*9))*(((((10*11)*12)*13)*14)*((((15*16)*17)*18)*19)))
|
|
279
|
+
sage: prod(L, recursion_cutoff=1)
|
|
280
|
+
(((((0*1)*2)*(3*4))*(((5*6)*7)*(8*9)))*((((10*11)*12)*(13*14))*(((15*16)*17)*(18*19))))
|
|
281
|
+
sage: L = [NonAssociative(label) for label in range(14)]
|
|
282
|
+
sage: prod(L, recursion_cutoff=1)
|
|
283
|
+
((((0*1)*(2*3))*((4*5)*6))*(((7*8)*(9*10))*((11*12)*13)))
|
|
284
|
+
"""
|
|
285
|
+
def __init__(self, left, right=None):
|
|
286
|
+
"""
|
|
287
|
+
EXAMPLES::
|
|
288
|
+
|
|
289
|
+
sage: from sage.misc.misc_c import NonAssociative
|
|
290
|
+
sage: NonAssociative('a')
|
|
291
|
+
a
|
|
292
|
+
sage: NonAssociative('a','b')
|
|
293
|
+
(a*b)
|
|
294
|
+
"""
|
|
295
|
+
self.left = left
|
|
296
|
+
self.right = right
|
|
297
|
+
|
|
298
|
+
def __repr__(self):
|
|
299
|
+
"""
|
|
300
|
+
EXAMPLES::
|
|
301
|
+
|
|
302
|
+
sage: from sage.misc.misc_c import NonAssociative
|
|
303
|
+
sage: NonAssociative(1)
|
|
304
|
+
1
|
|
305
|
+
sage: NonAssociative(2,3)
|
|
306
|
+
(2*3)
|
|
307
|
+
"""
|
|
308
|
+
if self.right is None:
|
|
309
|
+
return str(self.left)
|
|
310
|
+
else:
|
|
311
|
+
return "(%s*%s)" % (self.left, self.right)
|
|
312
|
+
|
|
313
|
+
def __mul__(self, other):
|
|
314
|
+
"""
|
|
315
|
+
EXAMPLES::
|
|
316
|
+
|
|
317
|
+
sage: from sage.misc.misc_c import NonAssociative
|
|
318
|
+
sage: a, b, c = [NonAssociative(label) for label in 'abc']
|
|
319
|
+
sage: (a*b)*c
|
|
320
|
+
((a*b)*c)
|
|
321
|
+
sage: a*(b*c)
|
|
322
|
+
(a*(b*c))
|
|
323
|
+
"""
|
|
324
|
+
return NonAssociative(self, other)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def balanced_sum(x, z=None, Py_ssize_t recursion_cutoff=5):
|
|
328
|
+
"""
|
|
329
|
+
Return the sum of the elements in the list x. If optional
|
|
330
|
+
argument z is not given, start the sum with the first element of
|
|
331
|
+
the list, otherwise use z. The empty product is the int 0 if z is
|
|
332
|
+
not specified, and is z if given. The sum is computed
|
|
333
|
+
recursively, where the sum is split up if the list is greater than
|
|
334
|
+
recursion_cutoff. recursion_cutoff must be at least 3.
|
|
335
|
+
|
|
336
|
+
This assumes that your addition is associative; we do not promise
|
|
337
|
+
which end of the list we start at.
|
|
338
|
+
|
|
339
|
+
EXAMPLES::
|
|
340
|
+
|
|
341
|
+
sage: balanced_sum([1,2,34])
|
|
342
|
+
37
|
|
343
|
+
sage: balanced_sum([2,3], 5)
|
|
344
|
+
10
|
|
345
|
+
sage: balanced_sum((1,2,3), 5)
|
|
346
|
+
11
|
|
347
|
+
|
|
348
|
+
Order should be preserved::
|
|
349
|
+
|
|
350
|
+
sage: balanced_sum([[i] for i in range(10)], [], recursion_cutoff=3)
|
|
351
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
352
|
+
|
|
353
|
+
We make copies when appropriate so that we do not accidentally
|
|
354
|
+
modify the arguments::
|
|
355
|
+
|
|
356
|
+
sage: list(range(10^5))==balanced_sum([[i] for i in range(10^5)], [])
|
|
357
|
+
True
|
|
358
|
+
sage: list(range(10^5))==balanced_sum([[i] for i in range(10^5)], [])
|
|
359
|
+
True
|
|
360
|
+
|
|
361
|
+
TESTS::
|
|
362
|
+
|
|
363
|
+
sage: balanced_sum((1..3)) # nonempty, z=None
|
|
364
|
+
6
|
|
365
|
+
sage: balanced_sum((1..-1)) # empty, z=None
|
|
366
|
+
0
|
|
367
|
+
sage: balanced_sum((1..3), 5) # nonempty, z is not None
|
|
368
|
+
11
|
|
369
|
+
sage: balanced_sum((1..-1), 5) # empty, z is not None
|
|
370
|
+
5
|
|
371
|
+
sage: balanced_sum([1])
|
|
372
|
+
1
|
|
373
|
+
|
|
374
|
+
AUTHORS:
|
|
375
|
+
|
|
376
|
+
- Joel B. Mohler (2007-10-03): Reimplemented in Cython and optimized
|
|
377
|
+
- Robert Bradshaw (2007-10-26): Balanced product tree, other optimizations, (lazy) generator support
|
|
378
|
+
"""
|
|
379
|
+
if recursion_cutoff < 3:
|
|
380
|
+
raise ValueError("recursion_cutoff must be at least 3")
|
|
381
|
+
|
|
382
|
+
if type(x) is not list and type(x) is not tuple:
|
|
383
|
+
|
|
384
|
+
if PyGen_Check(x):
|
|
385
|
+
return iterator_prod(x, z, multiply=False)
|
|
386
|
+
else:
|
|
387
|
+
try:
|
|
388
|
+
return x.sum()
|
|
389
|
+
except AttributeError:
|
|
390
|
+
pass
|
|
391
|
+
|
|
392
|
+
x = list(x)
|
|
393
|
+
|
|
394
|
+
cdef Py_ssize_t n = len(x)
|
|
395
|
+
|
|
396
|
+
if n == 0:
|
|
397
|
+
if z is None:
|
|
398
|
+
import sage.rings.integer
|
|
399
|
+
return sage.rings.integer.Integer(0)
|
|
400
|
+
else:
|
|
401
|
+
return z
|
|
402
|
+
|
|
403
|
+
sum = balanced_list_sum(x, 0, n, recursion_cutoff)
|
|
404
|
+
|
|
405
|
+
if z is not None:
|
|
406
|
+
sum = z + sum
|
|
407
|
+
|
|
408
|
+
return sum
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
cdef balanced_list_sum(L, Py_ssize_t offset, Py_ssize_t count, Py_ssize_t cutoff):
|
|
412
|
+
"""
|
|
413
|
+
INPUT:
|
|
414
|
+
|
|
415
|
+
- ``L`` -- the terms (MUST be a tuple or list)
|
|
416
|
+
- ``off`` -- offset in the list from which to start
|
|
417
|
+
- ``count`` -- how many terms in the sum; must be positive
|
|
418
|
+
- ``cutoff`` -- the minimum count to recurse on; must be at least 2
|
|
419
|
+
|
|
420
|
+
OUTPUT:
|
|
421
|
+
|
|
422
|
+
``L[offset] + L[offset+1] + ... + L[offset+count-1]``
|
|
423
|
+
|
|
424
|
+
.. NOTE::
|
|
425
|
+
|
|
426
|
+
The parameter cutoff must be at least 3. However, there are
|
|
427
|
+
at least two advantages to setting it higher (and
|
|
428
|
+
consequently not recursing all the way down the
|
|
429
|
+
tree). First, one avoids the overhead of the function calls
|
|
430
|
+
at the base of the tree (which is the majority of them) and
|
|
431
|
+
second, it allows one to save on object creation if inplace
|
|
432
|
+
operations are used. The asymptotic gains should usually be
|
|
433
|
+
at the top of the tree anyway.
|
|
434
|
+
"""
|
|
435
|
+
cdef Py_ssize_t k
|
|
436
|
+
if count <= cutoff:
|
|
437
|
+
sum = <object>PySequence_Fast_GET_ITEM(L, offset)
|
|
438
|
+
for k in range(offset + 1, offset + count):
|
|
439
|
+
sum += <object>PySequence_Fast_GET_ITEM(L, k)
|
|
440
|
+
return sum
|
|
441
|
+
else:
|
|
442
|
+
k = (1 + count) >> 1
|
|
443
|
+
return balanced_list_sum(L, offset, k, cutoff) + balanced_list_sum(L, offset + k, count - k, cutoff)
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
cpdef list normalize_index(object key, int size):
|
|
447
|
+
"""
|
|
448
|
+
Normalize an index key and return a valid index or list of indices
|
|
449
|
+
within the range(0, size).
|
|
450
|
+
|
|
451
|
+
INPUT:
|
|
452
|
+
|
|
453
|
+
- ``key`` -- the index key, which can be either an integer, a tuple/list of
|
|
454
|
+
integers, or a slice
|
|
455
|
+
- ``size`` -- the size of the collection
|
|
456
|
+
|
|
457
|
+
OUTPUT:
|
|
458
|
+
|
|
459
|
+
A tuple (SINGLE, VALUE), where SINGLE is True (i.e., 1) if VALUE
|
|
460
|
+
is an integer and False (i.e., 0) if VALUE is a list.
|
|
461
|
+
|
|
462
|
+
EXAMPLES::
|
|
463
|
+
|
|
464
|
+
sage: from sage.misc.misc_c import normalize_index
|
|
465
|
+
sage: normalize_index(-6,5)
|
|
466
|
+
Traceback (most recent call last):
|
|
467
|
+
...
|
|
468
|
+
IndexError: index out of range
|
|
469
|
+
sage: normalize_index(-5,5)
|
|
470
|
+
[0]
|
|
471
|
+
sage: normalize_index(-4,5)
|
|
472
|
+
[1]
|
|
473
|
+
sage: normalize_index(-3,5)
|
|
474
|
+
[2]
|
|
475
|
+
sage: normalize_index(-2,5)
|
|
476
|
+
[3]
|
|
477
|
+
sage: normalize_index(-1,5)
|
|
478
|
+
[4]
|
|
479
|
+
sage: normalize_index(0,5)
|
|
480
|
+
[0]
|
|
481
|
+
sage: normalize_index(1,5)
|
|
482
|
+
[1]
|
|
483
|
+
sage: normalize_index(2,5)
|
|
484
|
+
[2]
|
|
485
|
+
sage: normalize_index(3,5)
|
|
486
|
+
[3]
|
|
487
|
+
sage: normalize_index(4,5)
|
|
488
|
+
[4]
|
|
489
|
+
sage: normalize_index(5,5)
|
|
490
|
+
Traceback (most recent call last):
|
|
491
|
+
...
|
|
492
|
+
IndexError: index out of range
|
|
493
|
+
sage: normalize_index(6,5)
|
|
494
|
+
Traceback (most recent call last):
|
|
495
|
+
...
|
|
496
|
+
IndexError: index out of range
|
|
497
|
+
sage: normalize_index((4,-6),5)
|
|
498
|
+
Traceback (most recent call last):
|
|
499
|
+
...
|
|
500
|
+
IndexError: index out of range
|
|
501
|
+
sage: normalize_index((-2,3),5)
|
|
502
|
+
[3, 3]
|
|
503
|
+
sage: normalize_index((5,0),5)
|
|
504
|
+
Traceback (most recent call last):
|
|
505
|
+
...
|
|
506
|
+
IndexError: index out of range
|
|
507
|
+
sage: normalize_index((-5,2),5)
|
|
508
|
+
[0, 2]
|
|
509
|
+
sage: normalize_index((0,-2),5)
|
|
510
|
+
[0, 3]
|
|
511
|
+
sage: normalize_index((2,-3),5)
|
|
512
|
+
[2, 2]
|
|
513
|
+
sage: normalize_index((3,3),5)
|
|
514
|
+
[3, 3]
|
|
515
|
+
sage: normalize_index((-2,-5),5)
|
|
516
|
+
[3, 0]
|
|
517
|
+
sage: normalize_index((-2,-4),5)
|
|
518
|
+
[3, 1]
|
|
519
|
+
sage: normalize_index([-2,-1,3],5)
|
|
520
|
+
[3, 4, 3]
|
|
521
|
+
sage: normalize_index([4,2,1],5)
|
|
522
|
+
[4, 2, 1]
|
|
523
|
+
sage: normalize_index([-2,-3,-4],5)
|
|
524
|
+
[3, 2, 1]
|
|
525
|
+
sage: normalize_index([3,-2,-3],5)
|
|
526
|
+
[3, 3, 2]
|
|
527
|
+
sage: normalize_index([-5,2,-3],5)
|
|
528
|
+
[0, 2, 2]
|
|
529
|
+
sage: normalize_index([4,4,-5],5)
|
|
530
|
+
[4, 4, 0]
|
|
531
|
+
sage: s=slice(None,None,None); normalize_index(s,5)==list(range(5))[s]
|
|
532
|
+
True
|
|
533
|
+
sage: s=slice(None,None,-2); normalize_index(s,5)==list(range(5))[s]
|
|
534
|
+
True
|
|
535
|
+
sage: s=slice(None,None,4); normalize_index(s,5)==list(range(5))[s]
|
|
536
|
+
True
|
|
537
|
+
sage: s=slice(None,-2,None); normalize_index(s,5)==list(range(5))[s]
|
|
538
|
+
True
|
|
539
|
+
sage: s=slice(None,-2,-2); normalize_index(s,5)==list(range(5))[s]
|
|
540
|
+
True
|
|
541
|
+
sage: s=slice(None,-2,4); normalize_index(s,5)==list(range(5))[s]
|
|
542
|
+
True
|
|
543
|
+
sage: s=slice(None,4,None); normalize_index(s,5)==list(range(5))[s]
|
|
544
|
+
True
|
|
545
|
+
sage: s=slice(None,4,-2); normalize_index(s,5)==list(range(5))[s]
|
|
546
|
+
True
|
|
547
|
+
sage: s=slice(None,4,4); normalize_index(s,5)==list(range(5))[s]
|
|
548
|
+
True
|
|
549
|
+
sage: s=slice(-2,None,None); normalize_index(s,5)==list(range(5))[s]
|
|
550
|
+
True
|
|
551
|
+
sage: s=slice(-2,None,-2); normalize_index(s,5)==list(range(5))[s]
|
|
552
|
+
True
|
|
553
|
+
sage: s=slice(-2,None,4); normalize_index(s,5)==list(range(5))[s]
|
|
554
|
+
True
|
|
555
|
+
sage: s=slice(-2,-2,None); normalize_index(s,5)==list(range(5))[s]
|
|
556
|
+
True
|
|
557
|
+
sage: s=slice(-2,-2,-2); normalize_index(s,5)==list(range(5))[s]
|
|
558
|
+
True
|
|
559
|
+
sage: s=slice(-2,-2,4); normalize_index(s,5)==list(range(5))[s]
|
|
560
|
+
True
|
|
561
|
+
sage: s=slice(-2,4,None); normalize_index(s,5)==list(range(5))[s]
|
|
562
|
+
True
|
|
563
|
+
sage: s=slice(-2,4,-2); normalize_index(s,5)==list(range(5))[s]
|
|
564
|
+
True
|
|
565
|
+
sage: s=slice(-2,4,4); normalize_index(s,5)==list(range(5))[s]
|
|
566
|
+
True
|
|
567
|
+
sage: s=slice(4,None,None); normalize_index(s,5)==list(range(5))[s]
|
|
568
|
+
True
|
|
569
|
+
sage: s=slice(4,None,-2); normalize_index(s,5)==list(range(5))[s]
|
|
570
|
+
True
|
|
571
|
+
sage: s=slice(4,None,4); normalize_index(s,5)==list(range(5))[s]
|
|
572
|
+
True
|
|
573
|
+
sage: s=slice(4,-2,None); normalize_index(s,5)==list(range(5))[s]
|
|
574
|
+
True
|
|
575
|
+
sage: s=slice(4,-2,-2); normalize_index(s,5)==list(range(5))[s]
|
|
576
|
+
True
|
|
577
|
+
sage: s=slice(4,-2,4); normalize_index(s,5)==list(range(5))[s]
|
|
578
|
+
True
|
|
579
|
+
sage: s=slice(4,4,None); normalize_index(s,5)==list(range(5))[s]
|
|
580
|
+
True
|
|
581
|
+
sage: s=slice(4,4,-2); normalize_index(s,5)==list(range(5))[s]
|
|
582
|
+
True
|
|
583
|
+
sage: s=slice(4,4,4); normalize_index(s,5)==list(range(5))[s]
|
|
584
|
+
True
|
|
585
|
+
"""
|
|
586
|
+
cdef tuple index_tuple
|
|
587
|
+
cdef list return_list = []
|
|
588
|
+
cdef Py_ssize_t index
|
|
589
|
+
cdef Py_ssize_t i
|
|
590
|
+
cdef object index_obj
|
|
591
|
+
|
|
592
|
+
if PyIndex_Check(key):
|
|
593
|
+
index = key
|
|
594
|
+
if index < 0:
|
|
595
|
+
index += size
|
|
596
|
+
if index < 0 or index >= size:
|
|
597
|
+
raise IndexError("index out of range")
|
|
598
|
+
return [index]
|
|
599
|
+
elif isinstance(key, slice):
|
|
600
|
+
return list(range(*key.indices(size)))
|
|
601
|
+
elif type(key) is tuple:
|
|
602
|
+
index_tuple = key
|
|
603
|
+
elif type(key) is list:
|
|
604
|
+
index_tuple = PyList_AsTuple(key)
|
|
605
|
+
elif type(key) is range:
|
|
606
|
+
index_tuple = tuple(key)
|
|
607
|
+
else:
|
|
608
|
+
raise TypeError("index must be an integer or slice or a tuple/list of integers and slices")
|
|
609
|
+
|
|
610
|
+
# Cython does not automatically use PyTuple_GET_SIZE, even though
|
|
611
|
+
# it knows that index_tuple is tuple
|
|
612
|
+
for i in range(PyTuple_GET_SIZE(index_tuple)):
|
|
613
|
+
index_obj = index_tuple[i]
|
|
614
|
+
if PyIndex_Check(index_obj):
|
|
615
|
+
index = index_obj
|
|
616
|
+
if index < 0:
|
|
617
|
+
index += size
|
|
618
|
+
if index < 0 or index >= size:
|
|
619
|
+
raise IndexError("index out of range")
|
|
620
|
+
return_list.append(index)
|
|
621
|
+
elif isinstance(index_obj, slice):
|
|
622
|
+
return_list.extend(range(*index_obj.indices(size)))
|
|
623
|
+
else:
|
|
624
|
+
raise TypeError("index must be an integer or slice")
|
|
625
|
+
return return_list
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
cdef class sized_iter:
|
|
629
|
+
"""
|
|
630
|
+
Wrapper for an iterator to verify that it has a specified length.
|
|
631
|
+
|
|
632
|
+
INPUT:
|
|
633
|
+
|
|
634
|
+
- ``iterable`` -- object to be iterated over
|
|
635
|
+
|
|
636
|
+
- ``length`` -- (optional) the required length; if this is not
|
|
637
|
+
given, then ``len(iterable)`` will be used
|
|
638
|
+
|
|
639
|
+
If the iterable does not have the given length, a :exc:`ValueError` is
|
|
640
|
+
raised during iteration.
|
|
641
|
+
|
|
642
|
+
EXAMPLES::
|
|
643
|
+
|
|
644
|
+
sage: from sage.misc.misc_c import sized_iter
|
|
645
|
+
sage: list(sized_iter(range(4)))
|
|
646
|
+
[0, 1, 2, 3]
|
|
647
|
+
sage: list(sized_iter(range(4), 4))
|
|
648
|
+
[0, 1, 2, 3]
|
|
649
|
+
sage: list(sized_iter(range(5), 4))
|
|
650
|
+
Traceback (most recent call last):
|
|
651
|
+
...
|
|
652
|
+
ValueError: sequence too long (expected length 4, got more)
|
|
653
|
+
sage: list(sized_iter(range(3), 4))
|
|
654
|
+
Traceback (most recent call last):
|
|
655
|
+
...
|
|
656
|
+
ValueError: sequence too short (expected length 4, got 3)
|
|
657
|
+
|
|
658
|
+
If the iterable is too long, we get the error on the last entry::
|
|
659
|
+
|
|
660
|
+
sage: it = sized_iter(range(5), 2)
|
|
661
|
+
sage: next(it)
|
|
662
|
+
0
|
|
663
|
+
sage: next(it)
|
|
664
|
+
Traceback (most recent call last):
|
|
665
|
+
...
|
|
666
|
+
ValueError: sequence too long (expected length 2, got more)
|
|
667
|
+
|
|
668
|
+
When the expected length is zero, the iterator is checked on
|
|
669
|
+
construction::
|
|
670
|
+
|
|
671
|
+
sage: list(sized_iter([], 0))
|
|
672
|
+
[]
|
|
673
|
+
sage: sized_iter([1], 0)
|
|
674
|
+
Traceback (most recent call last):
|
|
675
|
+
...
|
|
676
|
+
ValueError: sequence too long (expected length 0, got more)
|
|
677
|
+
|
|
678
|
+
If no ``length`` is given, the iterable must implement ``__len__``::
|
|
679
|
+
|
|
680
|
+
sage: sized_iter(x for x in range(4))
|
|
681
|
+
Traceback (most recent call last):
|
|
682
|
+
...
|
|
683
|
+
TypeError: object of type 'generator' has no len()
|
|
684
|
+
"""
|
|
685
|
+
cdef iterator
|
|
686
|
+
cdef Py_ssize_t index, size
|
|
687
|
+
|
|
688
|
+
def __init__(self, iterable, length=None):
|
|
689
|
+
self.iterator = iter(iterable)
|
|
690
|
+
self.index = 0
|
|
691
|
+
if length is None:
|
|
692
|
+
self.size = len(iterable)
|
|
693
|
+
else:
|
|
694
|
+
self.size = length
|
|
695
|
+
self.check()
|
|
696
|
+
|
|
697
|
+
def __iter__(self):
|
|
698
|
+
return self
|
|
699
|
+
|
|
700
|
+
def __len__(self):
|
|
701
|
+
"""
|
|
702
|
+
Number of entries remaining, assuming that the expected length
|
|
703
|
+
is the actual length.
|
|
704
|
+
|
|
705
|
+
EXAMPLES::
|
|
706
|
+
|
|
707
|
+
sage: from sage.misc.misc_c import sized_iter
|
|
708
|
+
sage: it = sized_iter(range(4), 4)
|
|
709
|
+
sage: len(it)
|
|
710
|
+
4
|
|
711
|
+
sage: next(it)
|
|
712
|
+
0
|
|
713
|
+
sage: len(it)
|
|
714
|
+
3
|
|
715
|
+
"""
|
|
716
|
+
return self.size - self.index
|
|
717
|
+
|
|
718
|
+
cdef inline int check(self) except -1:
|
|
719
|
+
"""
|
|
720
|
+
If the iterator is supposed to be exhausted, check that it is.
|
|
721
|
+
"""
|
|
722
|
+
if self.index < self.size:
|
|
723
|
+
return 0
|
|
724
|
+
try:
|
|
725
|
+
next(self.iterator)
|
|
726
|
+
except StopIteration:
|
|
727
|
+
pass
|
|
728
|
+
else:
|
|
729
|
+
raise ValueError(f"sequence too long (expected length {self.size}, got more)")
|
|
730
|
+
|
|
731
|
+
def __next__(self):
|
|
732
|
+
if self.index >= self.size:
|
|
733
|
+
raise StopIteration
|
|
734
|
+
try:
|
|
735
|
+
x = next(self.iterator)
|
|
736
|
+
except StopIteration:
|
|
737
|
+
raise ValueError(f"sequence too short (expected length {self.size}, got {self.index})")
|
|
738
|
+
self.index += 1
|
|
739
|
+
self.check()
|
|
740
|
+
return x
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
def cyflush():
|
|
744
|
+
"""
|
|
745
|
+
Flush any output left over from external library calls.
|
|
746
|
+
|
|
747
|
+
Starting with Python 3, some output from external libraries (like
|
|
748
|
+
FLINT) is not flushed, and so if a doctest produces such output,
|
|
749
|
+
the output may not appear until a later doctest. See
|
|
750
|
+
:issue:`28649`.
|
|
751
|
+
|
|
752
|
+
Use this function after a doctest which produces potentially
|
|
753
|
+
unflushed output to force it to be flushed.
|
|
754
|
+
|
|
755
|
+
EXAMPLES::
|
|
756
|
+
|
|
757
|
+
sage: R.<t> = QQ[]
|
|
758
|
+
sage: t^(sys.maxsize//2) # needs sage.libs.flint
|
|
759
|
+
Traceback (most recent call last):
|
|
760
|
+
...
|
|
761
|
+
RuntimeError: FLINT exception
|
|
762
|
+
sage: from sage.misc.misc_c import cyflush
|
|
763
|
+
sage: cyflush()
|
|
764
|
+
...
|
|
765
|
+
"""
|
|
766
|
+
fflush(NULL)
|