Solution (source code)

= Solution

Use an <Oberon> record containing an active coefficient count and a bounded <array> of coefficients in ascending power order. A count of zero represents the zero <polynomial>; a count $n+1$ represents $a_0+\cdots+a_nx^n$. Trailing zero coefficients are allowed, so the count need not be the <degree of a polynomial> plus one.

``
CONST Capacity = 1024;
TYPE Polynomial = RECORD
  len: INTEGER;
  coeff: ARRAY Capacity OF REAL
END;

PROCEDURE Horner(VAR p: Polynomial; x: REAL): REAL;
  VAR i: INTEGER; value: REAL;
BEGIN
  i := p.len; value := 0.0;
  WHILE i > 0 DO
    i := i-1;
    value := p.coeff[i] + x*value
  END;
  RETURN value
END Horner;
``

The <representation invariant> is $0\leq\texttt{len}\leq\texttt{Capacity}$, with only indices below `len` significant. The parameter is passed by reference to avoid a full record copy; the procedure does not modify it.

Let $L$ be the original coefficient count. At each guard test the <loop invariant> is
$$
0\leq i\leq L,\qquad
v=\sum_{j=i}^{L-1}a_jx^{j-i}.
$$
The empty sum is zero initially. If the old index is $i>0$, after decrementing and updating,
$$
v_{\mathrm{new}}=a_{i-1}+x\sum_{j=i}^{L-1}a_jx^{j-i}
=\sum_{j=i-1}^{L-1}a_jx^{j-(i-1)},
$$
which preserves the <loop invariant>. The <loop variant> is $i$, decreasing by one until zero. At exit,
$$
\boxed{v=\sum_{j=0}^{L-1}a_jx^j=p(x).}
$$
This is exactly the right-to-left nesting of <Horner's method>, matching the supplied <right fold>. It uses $O(L)$ arithmetic operations and $O(1)$ additional scalar storage. `REAL` gives ordinary floating-point evaluation; the displayed identities specify the ideal arithmetic calculation, with the usual rounding in an actual floating-point implementation.