home *** CD-ROM | disk | FTP | other *** search
-
- PROCEDURE Bisect(LeftEnd : Real;
- RightEnd : Real;
- Tol : Real;
- MaxIter : Integer;
- VAR Answer : Real;
- VAR fAnswer : Real;
- VAR Iter : Integer;
- VAR Error : Byte);
-
- {----------------------------------------------------------------}
- {- -}
- {- Turbo Pascal Numerical Methods Toolbox -}
- {- (C) Copyright 1986 Borland International. -}
- {- -}
- {- Input: LeftEnd, RightEnd, Tol, MaxIter -}
- {- Output: Answer, fAnswer, Iter, Error -}
- {- -}
- {- Purpose: This unit provides a procedure for finding a root -}
- {- of a user specified function, for a user specified -}
- {- interval, [a,b], where f(a) and f(b) are of opposite -}
- {- signs. The algorithm successively bisects the -}
- {- interval, closing in on the root. The user must -}
- {- supply the desired tolerance to which the root should -}
- {- be found. -}
- {- -}
- {- Global Variables: LeftEnd : real left endpoint -}
- {- RightEnd : real right endpoint -}
- {- Tol : real tolerance of error -}
- {- MaxIter : real max number iterations -}
- {- Answer : real root of TNTargetF -}
- {- fAnswer : real TNTargetF(Answer) -}
- {- (should be close to 0) -}
- {- Iter :integer number of iterations -}
- {- Error : byte error flags -}
- {- -}
- {- Errors: 0: No error -}
- {- 1: maximum number of iterations exceeded -}
- {- 2: f(a) and f(b) are not of opposite signs -}
- {- 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;
-
- PROCEDURE TestInput(LeftEndpoint : Real;
- RightEndpoint : Real;
- Tol : Real;
- MaxIter : Integer;
- VAR Answer : Real;
- VAR fAnswer : Real;
- VAR Error : Byte;
- VAR Found : Boolean);
-
- {------------------------------------------------------------}
- {- Input: LeftEndpoint, RightEndpoint, Tol, MaxIter -}
- {- Output: Answer, fAnswer, Error, Found -}
- {- -}
- {- This procedure tests the input data for errors. If -}
- {- LeftEndpoint > RightEndpoint, Tol <= 0, or MaxIter < 0, -}
- {- then an error is returned. If one the of the endpoints -}
- {- (LeftEndpoint, RightEndpoint) is a root, then Found=TRUE -}
- {- and Answer and fAnswer are returned. -}
- {------------------------------------------------------------}
-
- VAR
- yLeft, yRight : Real; { The values of function at endpoints. }
-
- BEGIN
- yLeft := TNTargetF(LeftEndpoint);
- yRight := TNTargetF(RightEndpoint);
-
- IF Abs(yLeft) <= TNNearlyZero THEN
- BEGIN
- Answer := LeftEndpoint;
- fAnswer := TNTargetF(Answer);
- Found := True;
- END;
-
- IF Abs(yRight) <= TNNearlyZero THEN
- BEGIN
- Answer := RightEndpoint;
- fAnswer := TNTargetF(Answer);
- Found := True;
- END;
-
- IF NOT Found THEN { Test for errors }
- BEGIN
- IF yLeft*yRight > 0 THEN
- Error := 2;
- IF Tol <= 0 THEN
- Error := 3;
- IF MaxIter < 0 THEN
- Error := 4;
- END;
- END; { procedure Tests }
-
- PROCEDURE Converge(VAR LeftEndpoint : Real;
- VAR RightEndpoint : Real;
- Tol : Real;
- VAR Found : Boolean;
- MaxIter : Integer;
- VAR Answer : Real;
- VAR fAnswer : Real;
- VAR Iter : Integer;
- VAR Error : Byte);
-
- {-------------------------------------------------------------}
- {- Input: LeftEndpoint, RightEndpoint, Tol, MaxIter -}
- {- Output: Found, Answer, fAnswer, Iter, Error -}
- {- -}
- {- This procedure applies the bisection method to find a -}
- {- root to TNTargetF(x) on the interval [LeftEndpoint, -}
- {- RightEndpoint]. The root must be found within MaxIter -}
- {- iterations to a tolerance of Tol. If root found, then it -}
- {- is returned in Answer, the value of the function at the -}
- {- approximated root is fAnswer (should be close to -}
- {- zero), and the number of iterations is returned in Iter. -}
- {-------------------------------------------------------------}
-
- VAR
- yLeft : Real;
- MidPoint, yMidPoint : Real;
-
- PROCEDURE Initial(LeftEndpoint : Real;
- VAR Iter : Integer;
- VAR yLeft : Real);
- { Initialize variables. }
- BEGIN
- Iter := 0;
- yLeft := TNTargetF(LeftEndpoint);
- 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 current criteria (including the appropriate OR) -}
- {- and remove the comment brackets from the criteria (including -}
- {- the appropriate 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(X - OldX) < 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 -}
- {- x has been multiplied through 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; { function TestForRoot }
-
-
- BEGIN { procedure Converge }
- Initial(LeftEndpoint, Iter, yLeft);
- WHILE NOT(Found) AND (Iter < MaxIter) DO
- BEGIN
- Iter := Succ(Iter);
- MidPoint := (LeftEndpoint+RightEndpoint)/2;
- yMidPoint := TNTargetF(MidPoint);
- Found :=TestForRoot(MidPoint, LeftEndpoint, yMidPoint, Tol);
- IF (yLeft*yMidPoint) < 0 THEN
- RightEndpoint := MidPoint
- ELSE
- BEGIN
- LeftEndpoint := MidPoint;
- yLeft := yMidPoint;
- END;
- END;
- Answer := MidPoint;
- fAnswer := yMidPoint;
- IF Iter >= MaxIter THEN
- Error := 1;
- END; { procedure Converge }
-
- BEGIN { procedure Bisect }
- Found := False;
- TestInput(LeftEnd, RightEnd, Tol, MaxIter, Answer,
- fAnswer, Error, Found);
- IF (Error = 0) AND (Found = False) THEN { i.e. no error }
- Converge(LeftEnd, RightEnd, Tol, Found, MaxIter,
- Answer, fAnswer, Iter, Error);
- END; { procedure Bisect }