home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
borland
/
jnfb88.arc
/
SKYDIV.ARC
/
RAPHSON.INC
< prev
next >
Wrap
Text File
|
1987-10-22
|
9KB
|
188 lines
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 }