function result = muller ( f, x0, x1, x2, FATOL, XRTOL, ITMAX) % % MULLER carries out Muller's method for seeking a real root of a nonlinear function. % This is a "stripped down" version with little error checking. % % original written by John Burkardt % % Thu Oct 13 23:40:41 EDT 2005 % Modified by Andy Long, to comply with Newton's form of the interpolating % polynomial, using divided differences; also to compute complex roots. Note % that this algorithm works with arbitrary functions! % y0 = feval ( f, x0); y1 = feval ( f, x1); y2 = feval ( f, x2); % Check to see if we've got a root at the outset: if ( y0 == 0 ) result = x0; return elseif ( y1 == 0 ) result = x1; return elseif ( y2 == 0 ) result = x2; return end % Compute some differences: x10=(x1-x0); x21=(x2-x1); y10=(y1-y0); y21=(y2-y1); % divided differences: f01 = y10/x10; f12 = y21/x21; f012 = (f12-f01)/(x2-x0); it = 0; format long while ( it <= ITMAX ) it = it + 1; % Determine the coefficients A, B, C % of (Newton's form of) the polynomial % which goes through the data (X0,Y0), (X1,Y1), (X2,Y2). % Newton's form: % Y(X) = A*(X-X2)(X-X1) + B*(X-X2) + C % add the appropriate form of zero: % Y(X) = A*(X-X2)(X-X2+X2-X1) + B*(X-X2) + C % regroup: % Y(X) = A*(X-X2)(X-X2) + (B+A*(X2-X1))*(X-X2) + C a = f012; b = f12+a*x21; c = y2; if ( a ~= 0 ) % we're really quadratic: disc = b * b - 4.0 * a * c; % Here we check to see which root is closer to the approximate root x2: % choose the roots of the quadratic polynomial, and choose the one that makes %the LEAST change to X2 q1 = ( b + sqrt ( disc ) ); q2 = ( b - sqrt ( disc ) ); if ( abs ( q1 ) < abs ( q2 ) ) dx = - 2.0 * c / q2; else dx = - 2.0 * c / q1; end elseif ( b ~= 0 ) % We're linear: dx = - c / b; else % We're constant! Whooooooooooooooooooooaaaaaaaaaa..... '(Muller algorithm broke down, results unreliable.)' result = x2; return end tmp = x2 + dx; x0 = x1; x1 = x2; x2 = tmp; y0 = y1; y1 = y2; y2 = feval ( f, x2); % Report the current iteration: [ x2, y2 ] % Declare victory if the most recent change in X is small, and % the size of the function is small: if ( abs ( dx ) < XRTOL * ( abs ( x2 ) + 1.0 ) & abs ( y2 ) < FATOL ) result = x2; return end % Otherwise, update! Move values down in order where possible, and % calculate the new: x10=x21; x21=(x2-x1); y10=y21; y21=(y2-y1); f01 = f12; f12= y21/x21; f012 = (f12-f01)/(x2-x0); end % If maxits has been exceeded, then result = x2; '(Maximum number of iterations taken, results unreliable.)' endfunction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'Some examples: notice that only one is a polynomial.... ael' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'zero of sine:' muller("sin",.1,.2,.3,1e-6,1e-6,10) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'zero of cosine:' muller("cos",.1,.2,.3,1e-6,1e-6,10) 'true value: pi/2:' pi/2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'finding real and complex roots: (x-1)*(x^2+1)' function f = f(x) f=(x-1)*(x^2+1); endfunction 'Looking for that real root...' muller("f",.1,.2,.3,1e-6,1e-6,10) 'Looking for a complex root...' muller("f",.1,.2,.3+i,1e-6,1e-6,10) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'Another non-polynomial function: exp(x)-21' function f = f(x) f=exp(x)-21; endfunction muller("f",.1,.2,.3,1e-17,1e-17,10) feval("log",21.0)