home *** CD-ROM | disk | FTP | other *** search
- PROCEDURE Newton_Raphson(Guess : Real;
- Tol : Real;
- MaxIter : Integer;
- VAR Root : Real;
- VAR Value : Real;
- VAR Deriv : Real;
- VAR Iter : Integer;
- VAR Error : Byte);
-
- {------------------------------------------------------------------}
- {- -}
- {- Turbo Pascal Numerical Methods Toolbox -}
- {- (C) Copyright 1986 Borland International. -}
- {- -}
- {- Input: Guess, Tol, MaxIter -}
- {- Output: Root, Value, Deriv, Iter, Error -}
- {- -}
- {- Purpose: This unit provides a procedure for finding a single -}
- {- real root of a user specified function with a known -}
- {- continuous first derivative, given a user -}
- {- specified initial guess. The procedure implements -}
- {- Newton-Raphson's algorithm for finding a single -}
- {- zero of a function. -}
- {- The user must specify the desired tolerance -}
- {- in the answer. -}
- {- -}
- {- Global Variables: -}
- {- Guess : real; user's estimate of root -}
- {- Tol : real; tolerance in answer -}
- {- MaxIter : integer; maximum number of iterations -}
- {- Root : real; real part of calculated roots -}
- {- Value : real; value of the polynomial at root -}
- {- Deriv : real; value of the derivative at root -}
- {- Iter : real; number of iterations it took -}
- {- to find root -}
- {- Error : byte; flags if something went wrong -}
- {- -}
- {- Errors: 1: Iter >= MaxIter -}
- {- 2: The slope was zero at some point -}
- {- 3: Tol <= 0 -}
- {- 4: MaxIter < 0 -}
- {- -}
- {- Version Date: 26 January 1987 -}
- {- -}
- {------------------------------------------------------------------}
-
- CONST
- TNNearlyZero = 1E-015; { If you get a syntax error here, you are }
- { not running TURBO-87. }
- { TNNearlyZero = 1E-015 if using the 8087 }
- { math co-processor. }
- { TNNearlyZero = 1E-07 if not using the 8087 }
- { math co-processor. }
-
- VAR
- Found : Boolean; { Flags that a root has been Found }
- OldX, OldY, OldDeriv,
- NewX, NewY, NewDeriv : Real; { Iteration variables }
-
- PROCEDURE CheckSlope(Slope : Real;
- VAR Error : Byte);
-
- {---------------------------------------------------}
- {- Input: Slope -}
- {- Output: Error -}
- {- -}
- {- This procedure checks the slope to see if it is -}
- {- zero. The Newton Raphson algorithm may not be -}
- {- applied at a point where the slope is zero. -}
- {---------------------------------------------------}
-
- BEGIN
- IF Abs(Slope) <= TNNearlyZero THEN
- Error := 2; { Slope is zero }
- END; { procedure CheckSlope }
-
- PROCEDURE Initial(Guess : Real;
- Tol : Real;
- MaxIter : Integer;
- VAR OldX : Real;
- VAR OldY : Real;
- VAR OldDeriv : Real;
- VAR Found : Boolean;
- VAR Iter : Integer;
- VAR Error : Byte);
-
-
- {-------------------------------------------------------------}
- {- Input: Guess, Tol, MaxIter -}
- {- Output: OldX, OldY, OldDeriv, Found, Iter, Error -}
- {- -}
- {- This procedure sets the initial values of the above -}
- {- variables. If OldY is zero, then a root has been -}
- {- Found and Found = TRUE. This procedure also checks -}
- {- the tolerance (Tol) and the maximum number of iterations -}
- {- (MaxIter) for errors. -}
- {-------------------------------------------------------------}
-
- BEGIN
- Found := False;
- Iter := 0;
- Error := 0;
- OldX := Guess;
- OldY := TNTargetF(OldX);
- OldDeriv := TNDerivF(OldX);
- IF Abs(OldY) <= TNNearlyZero THEN
- Found := True
- ELSE
- CheckSlope(OldDeriv, Error);
- IF Tol <= 0 THEN
- Error := 3;
- IF MaxIter < 0 THEN
- Error := 4;
- END; { procedure Initial }
-
- FUNCTION TestForRoot(X, OldX, Y, Tol : Real) : Boolean;
-
- {-----------------------------------------------------------------}
- {- These are the stopping criteria. Four different ones are -}
- {- provided. If you wish to change the active criteria, simply -}
- {- comment off the current criteria (including the preceding OR) -}
- {- and remove the comment brackets from the criteria (including -}
- {- the following OR) you wish to be active. -}
- {-----------------------------------------------------------------}
-
- BEGIN
-
- TestForRoot := {---------------------------}
- (ABS(Y) <= TNNearlyZero) {- Y = 0 -}
- {- -}
- or {- -}
- {- -}
- (ABS(X - OldX) < ABS(OldX*Tol)) {- Relative change in X -}
- {- -}
- (* or *) {- -}
- (* *) {- -}
- (* (ABS(OldX - X) < Tol) *) {- Absolute change in X -}
- (* *) {- -}
- (* or *) {- -}
- (* *) {- -}
- (* (ABS(Y) <= Tol) *) {- Absolute change in Y -}
- {---------------------------}
-
- {-------------------------------------------------------------------}
- {- The first criteria simply checks to see if the value of the -}
- {- function is zero. You should probably always keep this -}
- {- criteria active. -}
- {- -}
- {- The second criteria checks relative error in X. This criteria -}
- {- evaluates the fractional change in X between interations. -}
- {- Note that X has been multiplied throught the inequality to -}
- {- avoid divide by zero errors. -}
- {- -}
- {- The third criteria checks the absolute difference in X -}
- {- between iterations. -}
- {- -}
- {- The fourth criteria checks the absolute difference between -}
- {- the value of the function and zero. -}
- {- -}
- {-------------------------------------------------------------------}
-
- END; { procedure TestForRoot }
-
-
- BEGIN { procedure Newton_Raphson }
- Initial(Guess, Tol, MaxIter, OldX, OldY, OldDeriv,
- Found, Iter, Error);
-
- WHILE NOT(Found) AND (Error = 0) AND (Iter < MaxIter) DO
- BEGIN
- Iter := Succ(Iter);
- NewX := OldX-OldY/OldDeriv;
- NewY := TNTargetF(NewX);
- NewDeriv := TNDerivF(NewX);
- Found := TestForRoot(NewX, OldX, NewY, Tol);
- OldX := NewX;
- OldY := NewY;
- OldDeriv := NewDeriv;
- IF NOT(Found) THEN
- CheckSlope(OldDeriv, Error);
- END;
- Root := OldX;
- Value := OldY;
- Deriv := OldDeriv;
- IF NOT(Found) AND (Error = 0) AND (Iter >= MaxIter) THEN
- Error := 1;
- END; { procedure Newton_Raphson }