@@ -195,7 +195,7 @@ loops that truncate the stream.
195
195
if n < 1:
196
196
raise ValueError('n must be at least one')
197
197
it = iter(iterable)
198
- while ( batch := tuple(islice(it, n) )):
198
+ while batch := tuple(islice(it, n)):
199
199
yield batch
200
200
201
201
.. versionadded :: 3.12
@@ -866,26 +866,29 @@ which incur interpreter overhead.
866
866
window.append(x)
867
867
yield math.sumprod(kernel, window)
868
868
869
- def polynomial_eval(coefficients, x):
870
- "Evaluate a polynomial at a specific value."
871
- # polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125 x³ -4x² -17x + 60
872
- n = len(coefficients)
873
- if n == 0:
874
- return x * 0 # coerce zero to the type of x
875
- powers = list(accumulate(repeat(x, n - 1), operator.mul, initial=1))
876
- return math.sumprod(coefficients, reversed(powers))
877
-
878
869
def polynomial_from_roots(roots):
879
870
"""Compute a polynomial's coefficients from its roots.
880
871
881
872
(x - 5) (x + 4) (x - 3) expands to: x³ -4x² -17x + 60
882
873
"""
883
874
# polynomial_from_roots([5, -4, 3]) --> [1, -4, -17, 60]
884
- roots = list(map(operator.neg, roots))
885
- return [
886
- sum(map(math.prod, combinations(roots, k)))
887
- for k in range(len(roots) + 1)
888
- ]
875
+ expansion = [1]
876
+ for r in roots:
877
+ expansion = convolve(expansion, (1, -r))
878
+ return list(expansion)
879
+
880
+ def polynomial_eval(coefficients, x):
881
+ """Evaluate a polynomial at a specific value.
882
+
883
+ Computes with better numeric stability than Horner's method.
884
+ """
885
+ # Evaluate x³ -4x² -17x + 60 at x = 2.5
886
+ # polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
887
+ n = len(coefficients)
888
+ if n == 0:
889
+ return x * 0 # coerce zero to the type of x
890
+ powers = map(pow, repeat(x), reversed(range(n)))
891
+ return math.sumprod(coefficients, powers)
889
892
890
893
def iter_index(iterable, value, start=0):
891
894
"Return indices where a value occurs in a sequence or iterable."
0 commit comments