# Several root-finding methods # The algorithms are described in: # Numerical Analysis, 5th edition # by Richard L. Burden and J. Douglas Faires # PWS Publishing Company, Boston, 1993. # Library of congress: QA 297 B84 1993 # In the below, f indicates the function whose root we wish to find, # a,b indicate the left and right endpoints of the interval in which we # wish to find the solution, TOL is the tolerance -- to what precision # we want the answer, and N is the maximum number of iterations # (0 means infinite). # These methods all return two values: # success:boolean, last value:real, iteration:natural # success is true iff last value is within tolerance of a zero # last value is the last value computed # iteration is the number of iterations performed # Currently only works for real functions of a real variable # The Bisection Method, Section 2.1, Algorithm 2.1, pp. 41-42 SetHelp ("FindRootBisection", "equation_solving", "Find root of a function using the bisection method") function FindRootBisection(f,a,b,TOL,N) = ( # check arguments ## check types if(not IsFunction(f)) then (error("find_root_bisection: argument 1 must be a function");bailout) else if(not IsReal(a) or not IsReal(b) or not IsReal(TOL)) then (error("find_root_bisection: arguments 2, 3, 4 must be real values");bailout) else if(not IsInteger(N)) then (error("find_root_bisection: argument 5 must be an integer");bailout); ## check bounds if(a>b) then (error("find_root_bisection: argument 2 must be less than or equal to argument 3");bailout) else if(f(a)*f(b)>0) then (error("find_root_bisection: value of endpoints must have differing sign");bailout); # Start calculating iteration=1; p=a; while((iteration <= N) or (N==0)) do ( diff=(b-a)/2; p=a+diff; if(f(p)==0 or diff0) then (a=p) else (b=p) ); [0,p,iteration] ) protect ("FindRootBisection") #function root_find_newton #FIXME: I can't take derivatives, so this doesn't work # The Secant Method, Section 2.3, Algorithm 2.4, p. 62 #FIXME: doesn't work right, check this SetHelp ("FindRootSecant", "equation_solving", "Find root of a function using the secant method") function FindRootSecant(f,a,b,TOL,N) = ( # check arguments ## check types if(not IsFunction(f)) then (error("find_root_secant: argument 1 must be a function");bailout) else if(not IsReal(a) or not IsReal(b) or not IsReal(TOL)) then (error("find_root_secant: arguments 2, 3, 4 must be real values");bailout) else if(not IsInteger(N)) then (error("find_root_secant: argument 5 must be an integer");bailout); ## check bounds if(a>b) then (error("find_root_secant: argument 2 must be less than or equal to argument 3");bailout) else if(f(a)*f(b)>0) then (error("find_root_secant: value of endpoints must have differing sign");bailout); # Start calculating iteration=2; qa=f(a); qb=f(b); p=a; while((iteration <= N) or (N==0)) do ( p=b-qb*(b-a)/(qb-qa); if(|p-b|b) then (error("find_root_false_position: argument 2 must be less than or equal to argument 3");bailout) else if(f(a)*f(b)>0) then (error("find_root_false_position: value of endpoints must have differing sign");bailout); # Start calculating iteration=2; qa=f(a); qb=f(b); p=a; while((iteration <= N) or (N==0)) do ( p=b-qb*(b-a)/(qb-qa); if(|p-b|