The Hermite Spline Approximating 
Exp[x] to 10^(-6) on [0,1]

Andy Long
MAT360
Spring, 2017

Having discovered the power of linear functions and numerical analysis in LinearSplineExample.nb, we improve things by moving to cubics (Hermite cubics), which provide not just a C^0 interpolator, but a C^1 interpolator (with slopes -- i.e., derivatives). Using these, we again find an approximation to e^x with a specified tolerance for error.

Let’s clear out some stuff, and set our initial endpoint: 600 knots gets us within 10^(-6) of the true value of Exp[x] on [0,1], with a little room to spare.

Thanks to Madison, who showed me that you can define a list on the fly!

Clear[l,x,xs,ys,i,j,k,top,linearExp,s]

n=5
xs[0]=0;
ys[0]=1.0;
h=1.0/n

Here we create the “knots” -- (x,y) pairs -- and the linear interpolators (I’ve left the linear interpolators in a slightly wasteful, Lagrange-suggestful form!)

Do [
xs[i]=i*h;
ys[i]=Exp[xs[i]];
j=i-1;
k=i;
m=(ys[k]-ys[j])*n;
l[j][x_]=(ys[j]*(x-xs[k])+ys[k]*(xs[j]-x))/(xs[j]-xs[k]);
c0[j][x_]=(ys[j]-m)*(x-xs[k])^2*(x-xs[j])*n^2;
c1[j][x_]=(ys[k]-m)*(x-xs[k])*(x-xs[j])^2*n^2;
hermite[j][x_]=l[j][x]+c0[j][x]+c1[j][x],
{i,n}
]
ListPlot[Table[{xs[i],ys[i]},{i,0,n}]]

Now we use the Floor function to create the spline. I hope that you’ll think that this is cool!:)

s[x_]:=l[Floor[x*n]][x]
super[x_]:=hermite[Floor[x*n]][x]
Plot[{s[x],Exp[x]},{x,0,1}]
Plot[{super[x],Exp[x]},{x,0,1}]
Plot[s[x]-Exp[x],{x,0,1}]
Plot[super[x]-Exp[x],{x,0,1}]

Now what’s REALLY COOL is that we can extend this function for all real numbers: values outside of [0,1]. Check out the errors as we switch from positive to negative values of x.

top=Exp[1];
linearExp[x_]:=If [x<0,
1/linearExp[-x],
If [x>=1,
top^Floor[x]*super[x-Floor[x]],
super[x]
]
]
linearExp[2]
Plot[{linearExp[x],Exp[x]},{x,-2,2}]
Plot[linearExp[x]-Exp[x],{x,-2,2}]

How about using linearExp to create the natural log function? 

Since Exp and Log are inverses of each other, we can use the equations
Log[x]=y  -> (e^y)-x=0  
and the secant method to create a good approximation to y=Log[x].

I swiped Joey, Zach, and Brooke’s Secant to start -- thanks!

secantMethod[f_,x0_,x1_,max_,eps_]:= 
Module[{k = 1,p0 = N[x0],p1 = N[x1], p2,f0,f1},
f0=f[p0];
f1=f[p1];
While[k < max && Abs[f1]>eps,
p2 = p1 - ((f1(p1 - p0))/(f1-f0));
p0 = p1;
p1 = p2;
f0=f1;
f1=f[p2];
k = k+1;];
p2
]
aroot=1.3;
f[x_]:=linearExp[x]-aroot
secantMethod[f,0,aroot,100,10^(-6)]
Log[aroot]

Okay, here’s our cheap and dirty Log: superCool!

linearLog[aroot_]:=
Module[{},
If[aroot>1, -linearLog[1/aroot],
f[x_]=linearExp[x]-aroot;
secantMethod[f,aroot,0,100,10^(-8)
]
]
]
Plot[{Log[x],linearLog[x]},{x,.0002,1}]
Plot[Log[x]-linearLog[x],{x,.0002,1}]
linearLog[12]