% This file demonstrates rounding errors. Every computer
% with a floating point arithmetic makes errors due to
% rounding. EULER can get rid of some of these errors with
% the exact scalar product and the interval arithmetic.
% 
% First of all, we investigate the basic rounding error.
>a=1/3-0.33333333333333
% 1/3 is not exactly representable in the computer. However,
% if we multiply it by 3, we get 1 exactly. This is due
% to the rounding.
>(1/3)*3-1
% This does no longer work for 1/49.
>1/49*49-1
% By the way, there are not many numbers between 1 and
% 100 such that 1/n*n does not round to 1.
>n=1:100; nonzeros(1/n*n-1<>0)
% As you can see belowe, the sqrt function is a good function.
% The input error is divided by 2 in each iterations. Thus
% all values are correct.
>longestformat; p=niterate("sqrt(x)",2,20); p|2^(2^-(1:20))'
% However, going back with x^2 to 2 is not a good function.
% The error is multiplied by 2 this time. This accumulates
% to a surprising error.
>niterate("x^2",p[20],20)|2^(2^-(19:-1:0))'
% Another example is the subtraction of two large numbers.
>x=10864; y=18817; 9*x^4-y^4+2*y^2,
% The correct result is 1. We can obtain it in the following
% way.
>x=10864; y=18817; (3*x^2-y^2)*(3*x^2+y^2)+2*y^2,
% By transforming the problem into a linear system, we
% can get very good results and even inclusions.
% 
% The linear system is v[1]=x, v[2]=x*v[1], ..., v[5]=y,
% v[6]=y*v[5], ..., v[9]=9*v[4]-v[8]+2*v[2]
>x=10864; y=18817;
>A=id(9);
>A[2,1]=-x; A[3,2]=-x; A[4,3]=-x;
>A[6,5]=-y; A[7,6]=-y; A[8,7]=-y;
>A[9,4]=-9; A[9,8]=1; A[9,6]=-2;
>b=[x 0 0 0 y 0 0 0 0]';
>v=A\b; v[9],
% The first solution is wrong.
% 
% However, we can improve it with a residual iteration.
>w=v-A\residuum(A,v,b); w[9],
% This is correct.
% 
% The function xlusolve does the same.
>v=xlusolve(A,b); v[9]
>load "interval"
% Using ilgs, we get a bound for the solution.
>v=ilgs(A,b); v[9]
% We now try the following recursion: I[n+1]=1/(n+1)-5*I[n].
% It is true that I[n]=intergral(x^n/(x+5),x=0..1).
% 
% We compute the recursion with the following function.
>function I(n)
$a=log(1.2); x=[];
$loop 1 to n;
$a=(1/#-5*a); x=x|a;
$end;
$return x;
$endfunction
>I(20)
% The last number is completely wrong.
>romberg("x^20/(x+5)",0,1)
% However, if we compute the recursion backwards, we get
% I[0] exactely. We get even a proved inclusion for log(1.2).
>function J(n)
$a=~0,1~;
$loop 1 to n
$a=0.2*(1/(n-#+1)-a);
$end
$return a
$endfunction
>J(20)
>log(1.2)
% The file CHEBYSH.E contains functions for the Chebyshev
% polynomials.
>load "chebysh";
% We test is for degree 60 at 0.9.
>T(60,0.9)
% Surprisingly, the recursive version is also exact. This
% is surprising in view of the example above.
>Trek(60,0.9)
% However, if we compute the polynomial and evaluate it
% at 0.9 with polyval, the result is completely wrong.
>p=Tpoly(60);
>polyval(p,0.9)
% This is not due to the coefficients, as we see with interval
% aritmetic. This is slow because of the 60x60 matrix involved.
>ipolyval(p,0.9)
% xpolyval is fast, but less reliable.
>xpolyval(p,0.9)
% The difference to the correct value is due to the coefficients.
>cos(60*acos(0.9))
% Another example is the following polynomial.
>p=[-945804881,1753426039,-1083557822,223200658];
% We evaluate it in the following interval.
>t=linspace(1.61801916,1.61801917,100);
% The values are clearly wrong.
>xplot(t-1.61801916,polyval(p,t)); wait(20);
% The correct values are easily obtained with a little
% residual iteration.
>xplot(t-1.61801916,xpolyval(p,t)); wait(20);
>
