[3/06] 5. $makepoly$ and $evalpoly$ examples from E8.1/P4.2; error-checking _______________________________________________________________________________ 5.1 loop invariant example: $makepoly$ function p = makepoly(p) % note: $p$ is both input and output variable p = [p 0]; % to be friendly: in case $p=[]$ was passed in % inv: deleting trailing 0s except for possibly $p(1)$ in vector $p$ % would yield the canonical form for the original value of $p$ % bound: number of trailing 0s in $p$ while length(p)>1 & p(end) == 0 p(end) = []; end note: + invariant does not explain how to make progress + *we* know progress is made because each loop iteration decreases the number of trailing 0s: this *bounds* the remaining number of loop iterations + it is often helpful to include the *bound (function)* along with the invariant, but we won't talk about it much in cs100m. _______________________________________________________________________________ 5.2 loop invariant example: $evalpoly$ version 1: function v = evalpoly(p,x) v = 0; i = 0; % inv: v = sum of the first $i$ terms of polynomial $p$ evaluated at $x$ while i ~= length(x) v = v + p(i+1) * x^i; i = i+1; end version 2: function v = evalpoly(p,x) v = 0; i = length(p); % inv: v + the first $i$ terms of $p$ evaluated at $x$ % = polynomial $p$ evaluated at $x$ while i ~= 0 v = v + p(i) * x^i; i = i-1; end version 3: function v = evalpoly(p,x) v = p(end); i = length(p); % inv: v * x^(i-1) + the first $i$ terms of $p$ evaluated at $x$ % = polynomial $p$ evaluated at $x$ while i ~= 0 v = v*x + p(i); i = i-1; end version 4 (without loops): function v = evalpoly(p,x) v = sum(x .^ (0:length(p)-1) .* p); _______________________________________________________________________________ 5.3 error-checking with multiple versions setting + suppose we start with one version of $evalpoly$ + suppose we decide to try another another version + and/or suppose there is a pre-defined version, e.g. $polyval$ + then we can try to use the multiple versions to partially check one another for errors function v = evalpoly(p,x) v = p(end); i = length(p); % inv: v * x^(i-1) + the first $i$ terms = polynomial $p$ evaluated at $x$ while i ~= 0 v = v*x + p(i); i = i-1; end v2 = sum(x .^ (0:length(p)-1) .* p); v3 = polyval(fliplr(p),x); if v ~= v2 | v ~= v3 error('the three versions of evalpoly do not agree'); end note: + finite machine precision :( + probably ok if coefficients and $x$ are "small" integers + otherwise, if we are worried only about "large" errors, we can try: epsilon = 1e-8; % required precision if abs(v-v2)>epsilon | abs(v-v3)>epsilon etc. _______________________________________________________________________________ 5.4 error-checking with inverses + suppose we had an "inverse" (opposite) function: e.g. $cumsum$ and $diff$ are roughly inverses + we can test to see if they undo each other, e.g. suppose $x$ holds a non-empty vector: epsilon = 1e-8; % required precision y = cumsum([x(1) diff(x)]); if any (abs(x-y) > epsilon) error('cumsum did not undo diff'); end epsilon = 1e-8; % required precision y = diff(cumsum([0 x])); if any (abs(x-y) > epsilon) error('diff did not undo cumsum'); end _______________________________________________________________________________ 5.5 connections with P4.2: use error-checking ideas above in $testpoly$ + compare $mulpoly$ and $divpoly$ against $conv$, $deconv$ + test if inverses undo each other + be careful about finite machine precision