Miscellaneous functions (Cython)¶
This file contains support for products, running totals, balanced sums, and also a function to flush output from external library calls.
AUTHORS:
William Stein (2005)
Joel B. Mohler (2007-10-03): Reimplemented in Cython and optimized
Robert Bradshaw (2007-10-26): Balanced product tree, other optimizations, (lazy) generator support
Robert Bradshaw (2008-03-26): Balanced product tree for generators and iterators
Stefan van Zwam (2013-06-06): Added bitset tests, some docstring cleanup
- class sage.misc.misc_c.NonAssociative(left, right=None)[source]¶
Bases:
object
This class is to test the balance nature of prod.
EXAMPLES:
sage: from sage.misc.misc_c import NonAssociative sage: L = [NonAssociative(label) for label in 'abcdef'] sage: prod(L) (((a*b)*c)*((d*e)*f)) sage: L = [NonAssociative(label) for label in range(20)] sage: prod(L, recursion_cutoff=5) ((((((0*1)*2)*3)*4)*((((5*6)*7)*8)*9))*(((((10*11)*12)*13)*14)*((((15*16)*17)*18)*19))) sage: prod(L, recursion_cutoff=1) (((((0*1)*2)*(3*4))*(((5*6)*7)*(8*9)))*((((10*11)*12)*(13*14))*(((15*16)*17)*(18*19)))) sage: L = [NonAssociative(label) for label in range(14)] sage: prod(L, recursion_cutoff=1) ((((0*1)*(2*3))*((4*5)*6))*(((7*8)*(9*10))*((11*12)*13)))
>>> from sage.all import * >>> from sage.misc.misc_c import NonAssociative >>> L = [NonAssociative(label) for label in 'abcdef'] >>> prod(L) (((a*b)*c)*((d*e)*f)) >>> L = [NonAssociative(label) for label in range(Integer(20))] >>> prod(L, recursion_cutoff=Integer(5)) ((((((0*1)*2)*3)*4)*((((5*6)*7)*8)*9))*(((((10*11)*12)*13)*14)*((((15*16)*17)*18)*19))) >>> prod(L, recursion_cutoff=Integer(1)) (((((0*1)*2)*(3*4))*(((5*6)*7)*(8*9)))*((((10*11)*12)*(13*14))*(((15*16)*17)*(18*19)))) >>> L = [NonAssociative(label) for label in range(Integer(14))] >>> prod(L, recursion_cutoff=Integer(1)) ((((0*1)*(2*3))*((4*5)*6))*(((7*8)*(9*10))*((11*12)*13)))
- sage.misc.misc_c.balanced_sum(x, z=None, recursion_cutoff=5)[source]¶
Return the sum of the elements in the list x. If optional argument z is not given, start the sum with the first element of the list, otherwise use z. The empty product is the int 0 if z is not specified, and is z if given. The sum is computed recursively, where the sum is split up if the list is greater than recursion_cutoff. recursion_cutoff must be at least 3.
This assumes that your addition is associative; we do not promise which end of the list we start at.
EXAMPLES:
sage: balanced_sum([1,2,34]) 37 sage: balanced_sum([2,3], 5) 10 sage: balanced_sum((1,2,3), 5) 11
>>> from sage.all import * >>> balanced_sum([Integer(1),Integer(2),Integer(34)]) 37 >>> balanced_sum([Integer(2),Integer(3)], Integer(5)) 10 >>> balanced_sum((Integer(1),Integer(2),Integer(3)), Integer(5)) 11
Order should be preserved:
sage: balanced_sum([[i] for i in range(10)], [], recursion_cutoff=3) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> from sage.all import * >>> balanced_sum([[i] for i in range(Integer(10))], [], recursion_cutoff=Integer(3)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
We make copies when appropriate so that we do not accidentally modify the arguments:
sage: list(range(10^5))==balanced_sum([[i] for i in range(10^5)], []) True sage: list(range(10^5))==balanced_sum([[i] for i in range(10^5)], []) True
>>> from sage.all import * >>> list(range(Integer(10)**Integer(5)))==balanced_sum([[i] for i in range(Integer(10)**Integer(5))], []) True >>> list(range(Integer(10)**Integer(5)))==balanced_sum([[i] for i in range(Integer(10)**Integer(5))], []) True
AUTHORS:
Joel B. Mohler (2007-10-03): Reimplemented in Cython and optimized
Robert Bradshaw (2007-10-26): Balanced product tree, other optimizations, (lazy) generator support
- sage.misc.misc_c.cyflush()[source]¶
Flush any output left over from external library calls.
Starting with Python 3, some output from external libraries (like FLINT) is not flushed, and so if a doctest produces such output, the output may not appear until a later doctest. See Issue #28649.
Use this function after a doctest which produces potentially unflushed output to force it to be flushed.
EXAMPLES:
sage: R.<t> = QQ[] sage: t^(sys.maxsize//2) # needs sage.libs.flint Traceback (most recent call last): ... RuntimeError: FLINT exception sage: from sage.misc.misc_c import cyflush sage: cyflush() ...
>>> from sage.all import * >>> R = QQ['t']; (t,) = R._first_ngens(1) >>> t**(sys.maxsize//Integer(2)) # needs sage.libs.flint Traceback (most recent call last): ... RuntimeError: FLINT exception >>> from sage.misc.misc_c import cyflush >>> cyflush() ...
- sage.misc.misc_c.iterator_prod(L, z=None)[source]¶
Attempt to do a balanced product of an arbitrary and unknown length sequence (such as a generator). Intermediate multiplications are always done with subproducts of the same size (measured by the number of original factors) up until the iterator terminates. This is optimal when and only when there are exactly a power of two number of terms.
A StopIteration is raised if the iterator is empty and z is not given.
EXAMPLES:
sage: from sage.misc.misc_c import iterator_prod sage: iterator_prod(1..5) 120 sage: iterator_prod([], z='anything') 'anything' sage: from sage.misc.misc_c import NonAssociative sage: L = [NonAssociative(label) for label in 'abcdef'] sage: iterator_prod(L) (((a*b)*(c*d))*(e*f))
>>> from sage.all import * >>> from sage.misc.misc_c import iterator_prod >>> iterator_prod(ellipsis_iter(Integer(1),Ellipsis,Integer(5))) 120 >>> iterator_prod([], z='anything') 'anything' >>> from sage.misc.misc_c import NonAssociative >>> L = [NonAssociative(label) for label in 'abcdef'] >>> iterator_prod(L) (((a*b)*(c*d))*(e*f))
- sage.misc.misc_c.normalize_index(key, size)[source]¶
Normalize an index key and return a valid index or list of indices within the range(0, size).
INPUT:
key
– the index key, which can be either an integer, a tuple/list of integers, or a slicesize
– the size of the collection
OUTPUT:
A tuple (SINGLE, VALUE), where SINGLE is True (i.e., 1) if VALUE is an integer and False (i.e., 0) if VALUE is a list.
EXAMPLES:
sage: from sage.misc.misc_c import normalize_index sage: normalize_index(-6,5) Traceback (most recent call last): ... IndexError: index out of range sage: normalize_index(-5,5) [0] sage: normalize_index(-4,5) [1] sage: normalize_index(-3,5) [2] sage: normalize_index(-2,5) [3] sage: normalize_index(-1,5) [4] sage: normalize_index(0,5) [0] sage: normalize_index(1,5) [1] sage: normalize_index(2,5) [2] sage: normalize_index(3,5) [3] sage: normalize_index(4,5) [4] sage: normalize_index(5,5) Traceback (most recent call last): ... IndexError: index out of range sage: normalize_index(6,5) Traceback (most recent call last): ... IndexError: index out of range sage: normalize_index((4,-6),5) Traceback (most recent call last): ... IndexError: index out of range sage: normalize_index((-2,3),5) [3, 3] sage: normalize_index((5,0),5) Traceback (most recent call last): ... IndexError: index out of range sage: normalize_index((-5,2),5) [0, 2] sage: normalize_index((0,-2),5) [0, 3] sage: normalize_index((2,-3),5) [2, 2] sage: normalize_index((3,3),5) [3, 3] sage: normalize_index((-2,-5),5) [3, 0] sage: normalize_index((-2,-4),5) [3, 1] sage: normalize_index([-2,-1,3],5) [3, 4, 3] sage: normalize_index([4,2,1],5) [4, 2, 1] sage: normalize_index([-2,-3,-4],5) [3, 2, 1] sage: normalize_index([3,-2,-3],5) [3, 3, 2] sage: normalize_index([-5,2,-3],5) [0, 2, 2] sage: normalize_index([4,4,-5],5) [4, 4, 0] sage: s=slice(None,None,None); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(None,None,-2); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(None,None,4); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(None,-2,None); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(None,-2,-2); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(None,-2,4); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(None,4,None); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(None,4,-2); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(None,4,4); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(-2,None,None); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(-2,None,-2); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(-2,None,4); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(-2,-2,None); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(-2,-2,-2); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(-2,-2,4); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(-2,4,None); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(-2,4,-2); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(-2,4,4); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(4,None,None); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(4,None,-2); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(4,None,4); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(4,-2,None); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(4,-2,-2); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(4,-2,4); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(4,4,None); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(4,4,-2); normalize_index(s,5)==list(range(5))[s] True sage: s=slice(4,4,4); normalize_index(s,5)==list(range(5))[s] True
>>> from sage.all import * >>> from sage.misc.misc_c import normalize_index >>> normalize_index(-Integer(6),Integer(5)) Traceback (most recent call last): ... IndexError: index out of range >>> normalize_index(-Integer(5),Integer(5)) [0] >>> normalize_index(-Integer(4),Integer(5)) [1] >>> normalize_index(-Integer(3),Integer(5)) [2] >>> normalize_index(-Integer(2),Integer(5)) [3] >>> normalize_index(-Integer(1),Integer(5)) [4] >>> normalize_index(Integer(0),Integer(5)) [0] >>> normalize_index(Integer(1),Integer(5)) [1] >>> normalize_index(Integer(2),Integer(5)) [2] >>> normalize_index(Integer(3),Integer(5)) [3] >>> normalize_index(Integer(4),Integer(5)) [4] >>> normalize_index(Integer(5),Integer(5)) Traceback (most recent call last): ... IndexError: index out of range >>> normalize_index(Integer(6),Integer(5)) Traceback (most recent call last): ... IndexError: index out of range >>> normalize_index((Integer(4),-Integer(6)),Integer(5)) Traceback (most recent call last): ... IndexError: index out of range >>> normalize_index((-Integer(2),Integer(3)),Integer(5)) [3, 3] >>> normalize_index((Integer(5),Integer(0)),Integer(5)) Traceback (most recent call last): ... IndexError: index out of range >>> normalize_index((-Integer(5),Integer(2)),Integer(5)) [0, 2] >>> normalize_index((Integer(0),-Integer(2)),Integer(5)) [0, 3] >>> normalize_index((Integer(2),-Integer(3)),Integer(5)) [2, 2] >>> normalize_index((Integer(3),Integer(3)),Integer(5)) [3, 3] >>> normalize_index((-Integer(2),-Integer(5)),Integer(5)) [3, 0] >>> normalize_index((-Integer(2),-Integer(4)),Integer(5)) [3, 1] >>> normalize_index([-Integer(2),-Integer(1),Integer(3)],Integer(5)) [3, 4, 3] >>> normalize_index([Integer(4),Integer(2),Integer(1)],Integer(5)) [4, 2, 1] >>> normalize_index([-Integer(2),-Integer(3),-Integer(4)],Integer(5)) [3, 2, 1] >>> normalize_index([Integer(3),-Integer(2),-Integer(3)],Integer(5)) [3, 3, 2] >>> normalize_index([-Integer(5),Integer(2),-Integer(3)],Integer(5)) [0, 2, 2] >>> normalize_index([Integer(4),Integer(4),-Integer(5)],Integer(5)) [4, 4, 0] >>> s=slice(None,None,None); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(None,None,-Integer(2)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(None,None,Integer(4)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(None,-Integer(2),None); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(None,-Integer(2),-Integer(2)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(None,-Integer(2),Integer(4)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(None,Integer(4),None); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(None,Integer(4),-Integer(2)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(None,Integer(4),Integer(4)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(-Integer(2),None,None); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(-Integer(2),None,-Integer(2)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(-Integer(2),None,Integer(4)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(-Integer(2),-Integer(2),None); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(-Integer(2),-Integer(2),-Integer(2)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(-Integer(2),-Integer(2),Integer(4)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(-Integer(2),Integer(4),None); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(-Integer(2),Integer(4),-Integer(2)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(-Integer(2),Integer(4),Integer(4)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(Integer(4),None,None); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(Integer(4),None,-Integer(2)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(Integer(4),None,Integer(4)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(Integer(4),-Integer(2),None); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(Integer(4),-Integer(2),-Integer(2)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(Integer(4),-Integer(2),Integer(4)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(Integer(4),Integer(4),None); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(Integer(4),Integer(4),-Integer(2)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True >>> s=slice(Integer(4),Integer(4),Integer(4)); normalize_index(s,Integer(5))==list(range(Integer(5)))[s] True
- sage.misc.misc_c.prod(x, z=None, recursion_cutoff=5)[source]¶
Return the product of the elements in the list x.
If optional argument z is not given, start the product with the first element of the list, otherwise use z. The empty product is the int 1 if z is not specified, and is z if given.
This assumes that your multiplication is associative; we do not promise which end of the list we start at.
See also
For the symbolic product function, see
sage.calculus.calculus.symbolic_product()
.EXAMPLES:
sage: prod([1,2,34]) 68 sage: prod([2,3], 5) 30 sage: prod((1,2,3), 5) 30 sage: F = factor(-2006); F -1 * 2 * 17 * 59 sage: prod(F) -2006
>>> from sage.all import * >>> prod([Integer(1),Integer(2),Integer(34)]) 68 >>> prod([Integer(2),Integer(3)], Integer(5)) 30 >>> prod((Integer(1),Integer(2),Integer(3)), Integer(5)) 30 >>> F = factor(-Integer(2006)); F -1 * 2 * 17 * 59 >>> prod(F) -2006
AUTHORS:
Joel B. Mohler (2007-10-03): Reimplemented in Cython and optimized
Robert Bradshaw (2007-10-26): Balanced product tree, other optimizations, (lazy) generator support
Robert Bradshaw (2008-03-26): Balanced product tree for generators and iterators
- sage.misc.misc_c.running_total(L, start=None)[source]¶
Return a list where the \(i\)-th entry is the sum of all entries up to (and including) \(i\).
INPUT:
L
– the liststart
– (optional) a default start value
EXAMPLES:
sage: running_total(range(5)) [0, 1, 3, 6, 10] sage: running_total("abcdef") ['a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef'] sage: running_total("abcdef", start="%") ['%a', '%ab', '%abc', '%abcd', '%abcde', '%abcdef'] sage: running_total([1..10], start=100) [101, 103, 106, 110, 115, 121, 128, 136, 145, 155] sage: running_total([]) []
>>> from sage.all import * >>> running_total(range(Integer(5))) [0, 1, 3, 6, 10] >>> running_total("abcdef") ['a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef'] >>> running_total("abcdef", start="%") ['%a', '%ab', '%abc', '%abcd', '%abcde', '%abcdef'] >>> running_total((ellipsis_range(Integer(1),Ellipsis,Integer(10))), start=Integer(100)) [101, 103, 106, 110, 115, 121, 128, 136, 145, 155] >>> running_total([]) []
- class sage.misc.misc_c.sized_iter[source]¶
Bases:
object
Wrapper for an iterator to verify that it has a specified length.
INPUT:
iterable
– object to be iterated overlength
– (optional) the required length; if this is not given, thenlen(iterable)
will be used
If the iterable does not have the given length, a
ValueError
is raised during iteration.EXAMPLES:
sage: from sage.misc.misc_c import sized_iter sage: list(sized_iter(range(4))) [0, 1, 2, 3] sage: list(sized_iter(range(4), 4)) [0, 1, 2, 3] sage: list(sized_iter(range(5), 4)) Traceback (most recent call last): ... ValueError: sequence too long (expected length 4, got more) sage: list(sized_iter(range(3), 4)) Traceback (most recent call last): ... ValueError: sequence too short (expected length 4, got 3)
>>> from sage.all import * >>> from sage.misc.misc_c import sized_iter >>> list(sized_iter(range(Integer(4)))) [0, 1, 2, 3] >>> list(sized_iter(range(Integer(4)), Integer(4))) [0, 1, 2, 3] >>> list(sized_iter(range(Integer(5)), Integer(4))) Traceback (most recent call last): ... ValueError: sequence too long (expected length 4, got more) >>> list(sized_iter(range(Integer(3)), Integer(4))) Traceback (most recent call last): ... ValueError: sequence too short (expected length 4, got 3)
If the iterable is too long, we get the error on the last entry:
sage: it = sized_iter(range(5), 2) sage: next(it) 0 sage: next(it) Traceback (most recent call last): ... ValueError: sequence too long (expected length 2, got more)
>>> from sage.all import * >>> it = sized_iter(range(Integer(5)), Integer(2)) >>> next(it) 0 >>> next(it) Traceback (most recent call last): ... ValueError: sequence too long (expected length 2, got more)
When the expected length is zero, the iterator is checked on construction:
sage: list(sized_iter([], 0)) [] sage: sized_iter([1], 0) Traceback (most recent call last): ... ValueError: sequence too long (expected length 0, got more)
>>> from sage.all import * >>> list(sized_iter([], Integer(0))) [] >>> sized_iter([Integer(1)], Integer(0)) Traceback (most recent call last): ... ValueError: sequence too long (expected length 0, got more)
If no
length
is given, the iterable must implement__len__
:sage: sized_iter(x for x in range(4)) Traceback (most recent call last): ... TypeError: object of type 'generator' has no len()
>>> from sage.all import * >>> sized_iter(x for x in range(Integer(4))) Traceback (most recent call last): ... TypeError: object of type 'generator' has no len()