[3.11] Backport itertool recipe updates (GH-102881)

This commit is contained in:
Raymond Hettinger 2023-03-21 13:44:32 -05:00 committed by GitHub
parent d149f15d63
commit e6e3b1b27d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 18 additions and 6 deletions

View File

@ -805,7 +805,7 @@ which incur interpreter overhead.
if n < 1:
raise ValueError('n must be at least one')
it = iter(iterable)
while (batch := tuple(islice(it, n))):
while batch := tuple(islice(it, n)):
yield batch
def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
@ -861,11 +861,23 @@ which incur interpreter overhead.
(x - 5) (x + 4) (x - 3) expands to: x³ -4x² -17x + 60
"""
# polynomial_from_roots([5, -4, 3]) --> [1, -4, -17, 60]
roots = list(map(operator.neg, roots))
return [
sum(map(math.prod, combinations(roots, k)))
for k in range(len(roots) + 1)
]
expansion = [1]
for r in roots:
expansion = convolve(expansion, (1, -r))
return list(expansion)
def polynomial_eval(coefficients, x):
"""Evaluate a polynomial at a specific value.
Computes with better numeric stability than Horner's method.
"""
# Evaluate x³ -4x² -17x + 60 at x = 2.5
# polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
n = len(coefficients)
if n == 0:
return x * 0 # coerce zero to the type of x
powers = map(pow, repeat(x), reversed(range(n)))
return sumprod(coefficients, powers)
def iter_index(iterable, value, start=0):
"Return indices where a value occurs in a sequence or iterable."