size : 6768 uploaded_on : Sat Jun 20 00:00:00 1998 modified_on : Wed Dec 8 14:03:36 1999 title : Trig functions/Arithmetic expression evaluator org_filename : ExtMath.pas author : PasWiz authoremail : description : New trig functions and an arithmetic expression evaluator keywords : tested : Borland Pascal 7.0 submitted_by : The CKB Crew submitted_by_email : ckb@netalive.org uploaded_by : nobody modified_by : nobody owner : nobody lang : pas file-type : text/plain category : pascal-alg-maths __END_OF_HEADER__ {Extended math: This unit contains procedures and functions that implement extensions to Pascal's built-in math (new trig functions, et al) and an arithmetic expression evaluator. The latter is loosely based on EXPR.C from Dr. Dobb's Journal, Sept 1985, p.25. } UNIT ExtMath; INTERFACE FUNCTION ArcCos (Number: Real): Real; FUNCTION ArcCosH (Number: Real): Real; FUNCTION ArcCot (Number: Real): Real; FUNCTION ArcCotH (Number: Real): Real; FUNCTION ArcCsc (Number: Real): Real; FUNCTION ArcCscH (Number: Real): Real; FUNCTION ArcSec (Number: Real): Real; FUNCTION ArcSecH (Number: Real): Real; FUNCTION ArcSin (Number: Real): Real; FUNCTION ArcSinH (Number: Real): Real; FUNCTION ArcTanH (Number: Real): Real; FUNCTION Ceil (Number: Real): Real; FUNCTION CosH (Number: Real): Real; FUNCTION Cot (Number: Real): Real; FUNCTION CotH (Number: Real): Real; FUNCTION Csc (Number: Real): Real; FUNCTION CscH (Number: Real): Real; FUNCTION Deg2Rad (Number: Real): Real; FUNCTION e: Real; FUNCTION Erf (Number: Real): Real; FUNCTION Fact (Number: Integer): Real; FUNCTION Floor (Number: Real): Real; FUNCTION Log (Number: Real): Real; FUNCTION Rad2Deg (Number: Real): Real; FUNCTION Raise (Number: Real; Power: Integer): Real; FUNCTION Sec (Number: Real): Real; FUNCTION SecH (Number: Real): Real; FUNCTION SgnI (Number: Integer): Integer; FUNCTION SgnR (Number: Real): Integer; FUNCTION SinH (Number: Real): Real; FUNCTION Tan (Number: Real): Real; FUNCTION TanH (Number: Real): Real; PROCEDURE Evaluate (Expr: String; VAR Result: Real; VAR ErrCode: Integer); { --------------------------------------------------------------------------- } IMPLEMENTATION { forward declarations for the Evaluate procedure } FUNCTION Eval (VAR Expr: String; VAR ErrCode: Integer): Real; FORWARD; FUNCTION Factor (VAR Expr: String; VAR ErrCode: Integer): Real; FORWARD; FUNCTION IsDigit (Expr: String): Boolean; FORWARD; FUNCTION Locase (Ch: Char): Char; FORWARD; FUNCTION ParensOk (Expr: String): Boolean; FORWARD; FUNCTION Term (VAR Expr: String; VAR ErrCode: Integer): Real; FORWARD; PROCEDURE AddParen (VAR Expr: String; Posn, WhichWay: Integer); FORWARD; PROCEDURE FixPrecedence (VAR Expr: String); FORWARD; { ----- Ceiling ----- } FUNCTION Ceil (Number: Real): Real; BEGIN IF Number = INT(Number) THEN Ceil := Number ELSE Ceil := INT(Number) + 1.0; END; { ----- Floor ----- } FUNCTION Floor (Number: Real): Real; BEGIN IF Number = INT(Number) THEN Floor := Number ELSE Floor := INT(Number) - 1.0; END; { ----- Inverse cosine ----- } FUNCTION ArcCos (Number: Real): Real; BEGIN IF (Number < -1.0) OR (Number > 1.0) THEN { error } ArcCos := 99999.0 ELSE ArcCos := PI / 2.0 - ArcSin(Number); END; { ----- Inverse hyperbolic cosine ----- } FUNCTION ArcCosH (Number: Real): Real; BEGIN ArcCosH := Log(Number + SQRT(SQR(Number) - 1.0)); END; { ----- Inverse cotangent ----- } FUNCTION ArcCot (Number: Real): Real; BEGIN ArcCot := -ARCTAN(Number) + PI / 2.0; END; { ----- Inverse hyperbolic cotangent ----- } FUNCTION ArcCotH (Number: Real): Real; BEGIN ArcCotH := LN((Number + 1.0) / (Number - 1.0)) / 2.0; END; { ----- Inverse cosecant ----- } FUNCTION ArcCsc (Number: Real): Real; BEGIN ArcCsc := ARCTAN(1.0 / SQRT(1.0 - SQR(Number))) + (SgnR(Number) - 1.0) * (PI / 2.0); END; { ----- Inverse hyperbolic cosecant ----- } FUNCTION ArcCscH (Number: Real): Real; BEGIN ArcCscH := LN((SgnR(Number) * SQRT(SQR(Number) + 1.0) + 1.0) / Number); END; { ----- Inverse secant ----- } FUNCTION ArcSec (Number: Real): Real; BEGIN ArcSec := ARCTAN(Number / SQRT(1.0 - SQR(Number))) + (SgnR(Number) - 1.0) * (PI / 2.0); END; { ----- Inverse hyperbolic secant ----- } FUNCTION ArcSecH (Number: Real): Real; BEGIN ArcSecH := LN((SQRT(1.0 - SQR(Number)) + 1.0) / Number); END; { ----- Inverse sine ----- } FUNCTION ArcSin (Number: Real): Real; VAR Negate: Boolean; tmp: Real; BEGIN IF Number < 0.0 THEN BEGIN Number := -Number; Negate := TRUE; END ELSE Negate := FALSE; IF Number > 1.0 THEN BEGIN tmp := 99999.0; Negate := FALSE; END ELSE BEGIN tmp := SQRT(1.0 - SQR(Number)); IF Number > 0.7 THEN tmp := PI / 2.0 - ARCTAN(tmp / Number) ELSE tmp := ARCTAN(Number / tmp); END; IF Negate THEN ArcSin := -tmp ELSE ArcSin := tmp; END; { ----- Inverse hyperbolic sine ----- } FUNCTION ArcSinH (Number: Real): Real; BEGIN ArcSinH := Log(Number + SQRT(SQR(Number) + 1.0)); END; { ----- Inverse hyperbolic tangent ----- } FUNCTION ArcTanH (Number: Real): Real; BEGIN ArcTanH := Log((1.0 + Number) / (1.0 - Number)) / 2.0; END; { ----- Convert degrees to radians ----- } FUNCTION Deg2Rad (Number: Real): Real; BEGIN Deg2Rad := Number * PI / 180.0; END; { ----- e (base of the natural logarithms) ----- } FUNCTION e: Real; BEGIN e := 2.7182818284590452353602874713526624977572470936999595749669676; END; { ----- Hyperbolic cosine ----- } FUNCTION CosH (Number: Real): Real; BEGIN IF Number < 0.0 THEN Number := - Number; IF Number > 21.0 THEN CosH := Exp(Number) / 2.0 ELSE CosH := (Exp(Number) + Exp(-Number)) / 2.0; END; { ----- Cotangent ----- } FUNCTION Cot (Number: Real): Real; BEGIN Cot := 1.0 / Tan(Number); END; { ----- Hyperbolic cotangent ----- } FUNCTION CotH (Number: Real): Real; VAR tmp: REAL; BEGIN tmp := EXP(-Number); CotH := tmp / (EXP(Number) - tmp) * 2.0 + 1.0; END; { ----- Cosecant ----- } FUNCTION Csc (Number: Real): Real; BEGIN Csc := 1.0 / Sin(Number); END; { ----- Hyperbolic cosecant ----- } FUNCTION CscH (Number: Real): Real; BEGIN CscH := 2.0 / (EXP(Number) - EXP(-Number)); END; { ----- Error Function ----- } FUNCTION Erf (Number: Real): Real; VAR J, N: Integer; S: Real; BEGIN N := Trunc(14.0 * Number + 3.0); S := 1.0 / (2.0 * N - 1.0); FOR J := N - 1 DOWNTO 1 DO S := 1.0 / (2.0 * J - 1.0) - SQR(Number) / J * S; Erf := Number / 0.8862269254527581 * S; END; { ----- Factorial ----- } FUNCTION Fact (Number: Integer): Real; VAR Result: Real; tmp: Integer; BEGIN Result := 1.0; FOR tmp := 2 TO Number DO Result := Result * tmp; Fact := Result; END; { ----- Logarithm (base 10) ----- } FUNCTION Log (Number: Real): Real; BEGIN Log := Ln(Number) / Ln(10.0); END; { ----- Convert radians to degrees ----- } FUNCTION Rad2Deg (Number: Real): Real; BEGIN Rad2Deg := Number * 180.0 / PI; END; { ----- Raise a number to a power (a feature oddly lacking in Pascal). } FUNCTION Raise (Number: Real; Power: Integer): Real; VAR tmp: Integer; Result: Real; BEGIN Result := 1.