[Back to MATH SWAG index] [Back to Main SWAG index] [Original]

    {   +----------------------------------------------------------------------+
        |                                                                      |
        |   PasWiz  (C) Copyright 1996 Charon Software, All Rights Reserved    |
        |                                                                      |
        +----------------------------------------------------------------------+

    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.0;
       FOR tmp := 1 TO Power DO
          Result := Result * Number;
       Raise := Result;
    END;     { Raise }

    { ----- Secant ----- }
    FUNCTION Sec (Number: Real): Real;
    BEGIN
       Sec := 1.0 / Cos(Number);
    END;

    { ----- Hyperbolic secant ----- }
    FUNCTION SecH (Number: Real): Real;
    BEGIN
       SecH := 2.0 / (EXP(Number) + EXP(-Number));
    END;

    { ----- Signum (integer) ----- }
    FUNCTION SgnI (Number: Integer): Integer;
    BEGIN
       IF Number < 0 THEN
          SgnI := -1
       ELSE IF Number > 0 THEN
          SgnI := 1
       ELSE
          SgnI := 0;
    END;

    { ----- Signum (real) ----- }
    FUNCTION SgnR (Number: Real): Integer;
    BEGIN
       IF Number < 0.0 THEN
          SgnR := -1
       ELSE IF Number > 0.0 THEN
          SgnR := 1
       ELSE
          SgnR := 0;
    END;

    { ----- Hyperbolic sine ----- }
    FUNCTION SinH (Number: Real): Real;
    VAR
       Negate: Boolean;
       p0, p1, p2, p3, q0, q1, q2, tmp, tmp1, tmp2, tmpsq: Real;
    BEGIN
       p0 := -630767.3640497716991184787251;
       p1 := -89912.72022039509355398013511;
       p2 := -2894.211355989563807284660366;
       p3 := -26.30563213397497062819489;
       q0 := -630767.3640497716991212077277;
       q1 := 15215.17378790019070696485176;
       q2 := -173.678953558233699533450911;
       IF Number < 0.0 THEN BEGIN
          Number := -Number;
          Negate := TRUE;
       END
       ELSE
          Negate := FALSE;
       IF Number > 21.0 THEN
          tmp := Exp(Number) / 2.0
       ELSE IF Number > 0.5 THEN
          tmp := (Exp(Number) - Exp(-Number)) / 2.0
       ELSE BEGIN
          tmpsq := SQR(Number);
          tmp1 := (((tmpsq * p3 + p2) * tmpsq + p1) * tmpsq + p0) * Number;
          tmp2 := ((tmpsq + q2) * tmpsq + q1) * tmpsq + q0;
          tmp := tmp1 / tmp2;
       END;
       IF Negate THEN
          SinH := -tmp
       ELSE
          SinH := tmp;
    END;

    { ----- Tangent ----- }
    FUNCTION Tan (Number: Real): Real;
    BEGIN
       Tan := Sin(Number) / Cos(Number);
    END;

    { ----- Hyperbolic tangent ----- }
    FUNCTION TanH (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 > 21.0 THEN     { error }
          TanH := 99999
       ELSE BEGIN
          tmp := SinH(Number) / CosH(Number);
          IF Negate THEN
             TanH := -tmp
          ELSE
             TanH := tmp;
       END;
    END;

    { =========================================================================== }

    { ----- This is the main evaluation routine ----- }
    PROCEDURE Evaluate (Expr: String; VAR Result: Real; VAR ErrCode: Integer);
    VAR
       tmp: Integer;
    BEGIN
       WHILE (Pos(' ', Expr) > 0) DO
          Delete(Expr, Pos(' ', Expr), 1);
       WHILE (Pos('**', Expr) > 0) DO BEGIN
          tmp := Pos('**', Expr);
          Delete(Expr, tmp, 1);
          Expr[tmp] := '^';
       END;
       IF Length(Expr) > 0 THEN
          IF ParensOk(Expr) THEN BEGIN
             FOR tmp := 1 TO Length(Expr) DO
                Expr[tmp] := Upcase(Expr[tmp]);
             ErrCode := 0;
             FixPrecedence(Expr);
             Result := Eval(Expr, ErrCode);
          END
          ELSE
             ErrCode := 4
       ELSE
          ErrCode := 8;
    END;     { Evaluate }

    { ----- This adds parentheses to force evaluation by normal algebraic
            precedence (negation, exponentiation, multiplication and division,
            addition and subtraction) }
    PROCEDURE AddParen (VAR Expr: String; Posn, WhichWay: Integer);
    VAR
       Done: Boolean;
       ch: Char;
       Depth: Integer;
    BEGIN
       Done := FALSE;
       IF WhichWay < 0 THEN BEGIN
          REPEAT
             Dec(Posn);
             IF Posn < 1 THEN BEGIN
                Expr := '(' + Expr;
                Done := TRUE;
             END
             ELSE BEGIN
                ch := Expr[Posn];
                IF Pos(ch, '^*/+-') > 0 THEN BEGIN
                   Insert('(', Expr, Posn + 1);
                   Done := TRUE;
                END
                ELSE IF ch = ')' THEN BEGIN
                   Depth := 1;
                   REPEAT
                      Dec(Posn);
                      IF Posn > 0 THEN BEGIN
                         ch := Expr[Posn];
                         IF ch = '(' THEN
                            Dec(Depth)
                         ELSE IF ch = ')' THEN
                            Inc(Depth);
                      END
                      ELSE
                         Depth := 0;
                   UNTIL Depth = 0;
                   IF Posn < 1 THEN
                      Posn := 1;
                   Insert('(', Expr, Posn + 1);
                   Done := TRUE;
                END;
             END;
          UNTIL Done;
       END
       ELSE
          REPEAT
             Inc(Posn);
             IF Posn > Length(Expr) THEN BEGIN
                Expr := Expr + ')';
                Done := TRUE;
             END
             ELSE BEGIN
                ch := Expr[Posn];
                IF Pos(ch, '^*/+-') > 0 THEN BEGIN
                   Insert(')', Expr, Posn);
                   Done := TRUE;
                END
                ELSE IF ch = '(' THEN BEGIN
                   Depth := 1;
                   REPEAT
                      Inc(Posn);
                      IF Posn <= Length(Expr) THEN BEGIN
                         ch := Expr[Posn];
                         IF ch = ')' THEN
                            Dec(Depth)
                         ELSE IF ch = '(' THEN
                            Inc(Depth);
                      END
                      ELSE
                         Depth := 0;
                   UNTIL Depth = 0;
                   IF Posn > Length(Expr) THEN
                      Posn := Length(Expr);
                   Insert(')', Expr, Posn);
                   Done := TRUE;
                END;
             END;
          UNTIL Done;
    END;    { AddParen }

    { ----- This recursive function is the heart of the expression evaluator. }
    FUNCTION Eval (VAR Expr: String; VAR ErrCode: Integer): Real;
    VAR
       LVal, tmp: Real;
    BEGIN
       LVal := Factor(Expr, ErrCode);
       IF ErrCode = 0 THEN
          CASE Expr[1] OF
             '+': BEGIN
                     Delete(Expr, 1, 1);
                     LVal := LVal + Eval(Expr, ErrCode);
                  END;
             '-': BEGIN
                     Delete(Expr, 1, 1);
                     LVal := LVal - Eval(Expr, ErrCode);
                  END;
             '*': BEGIN
                     Delete(Expr, 1, 1);
                     LVal := LVal * Eval(Expr, ErrCode);
                  END;
             '/': BEGIN
                     Delete(Expr, 1, 1);
                     tmp := Eval(Expr, ErrCode);
                     IF ErrCode = 0 THEN
                        IF tmp = 0.0 THEN
                           ErrCode := 9
                        ELSE
                           LVal := LVal / tmp;
                  END;
             '^': BEGIN
                     Delete(Expr, 1, 1);
                     LVal := Raise(LVal, Trunc(Eval(Expr, ErrCode)));
                  END;
             ')': Delete(Expr, 1, 1);
          END;     { CASE }
       Eval := LVal;
    END;     { Eval }

    { ----- A recursive evaluation helper, this function gets the leftmost term
            that can be dealt with at this point in the evaluation. }
    FUNCTION Factor (VAR Expr: String; VAR ErrCode: Integer): Real;
    VAR
       Negate: Boolean;
       RVal: Real;
    BEGIN
       RVal := 0.0;
       IF Expr[1] = '-' THEN BEGIN
          Negate := TRUE;
          Delete(Expr, 1, 1);
       END
       ELSE
          Negate := FALSE;
       IF Expr[1] <> '(' THEN
          RVal := Term(Expr, ErrCode)
       ELSE BEGIN
          Delete(Expr, 1, 1);
          RVal := Eval(Expr, ErrCode);
       END;
       IF Negate THEN
          Factor := -RVal
       ELSE
          Factor := RVal;
    END;     { Factor }

    { ----- Since the evaluation function doesn't naturally evaluate expressions
            using algebraic precedence, but does understand parentheses...
            This routine adds parentheses to force the proper precedence. }
    PROCEDURE FixPrecedence (VAR Expr: String);
    VAR
       Posn, tmp: Integer;
    BEGIN
       Expr := '(' + Expr + ')';
       Posn := 2;
       REPEAT
          IF Expr[Posn] = '-' THEN
             IF NOT(Expr[Posn - 1] IN ['0'..'9','A'..'Z']) THEN BEGIN
                AddParen(Expr, Posn, 1);
                AddParen(Expr, Posn, -1);
                Inc(Posn, 2);
             END
             ELSE
                Inc(Posn)
          ELSE
             Inc(Posn);
       UNTIL Posn > Length(Expr);
       Posn := 1;
       REPEAT
          IF Expr[Posn] <> Locase(Expr[Posn]) THEN BEGIN
             AddParen(Expr, Posn, 1);
             AddParen(Expr, Posn, -1);
             Inc(Posn, 2);
          END
          ELSE
             Inc(Posn);
       UNTIL Posn > Length(Expr);
       Posn := 1;
       REPEAT
          IF Expr[Posn] = '^' THEN BEGIN
             AddParen(Expr, Posn, 1);
             AddParen(Expr, Posn, -1);
             Inc(Posn, 2);
          END
          ELSE
             Inc(Posn);
       UNTIL Posn > Length(Expr);
       Posn := 1;
       REPEAT
          IF Pos(Expr[Posn], '*/') > 0 THEN BEGIN
             AddParen(Expr, Posn, 1);
             AddParen(Expr, Posn, -1);
             Inc(Posn, 2);
          END
          ELSE
             Inc(Posn);
       UNTIL Posn > Length(Expr);
       Posn := 1;
       REPEAT
          IF Pos(Expr[Posn], '+-') > 0 THEN BEGIN
             AddParen(Expr, Posn, 1);
             AddParen(Expr, Posn, -1);
             Inc(Posn, 2);
          END
          ELSE
             Inc(Posn);
       UNTIL Posn > Length(Expr);
       Delete(Expr, 1, 1);
       Delete(Expr, Length(Expr), 1);
    END;     { FixPrecedence }

    { ----- Determine whether a character may be construed as being numeric. }
    FUNCTION IsDigit (Expr: String): Boolean;
    BEGIN
       IF Length(Expr) > 0 THEN
          IsDigit := (Pos(Expr[1], '0123456789.') > 0)
       ELSE
          IsDigit := FALSE;
    END;     { IsDigit }

    { ----- Convert a character to lowercase. }
    FUNCTION LoCase (ch: Char): Char;
    BEGIN
       IF ch IN ['A'..'Z'] THEN
          LoCase := CHR(ORD(ch) XOR 32)
       ELSE
          LoCase := ch
    END;     { LoCase }

    { ----- Check to make sure parentheses are balanced. }
    FUNCTION ParensOk (Expr: String): Boolean;
    VAR
       Parens, Posn: Integer;
    BEGIN
       Parens := 0;
       FOR Posn := 1 TO Length(Expr) DO
          IF Expr[Posn] = '(' THEN
             Inc(Parens)
          ELSE IF Expr[Posn] = ')' THEN
             Dec(Parens);
       ParensOk := (Parens = 0);
    END;     { ParensOk }

    { ----- This grabs a number from the expression. }
    FUNCTION Term (VAR Expr: String; VAR ErrCode: Integer): Real;
    VAR
       junk: Integer;
       RVal: Real;
       ch: char;
       tmp: String;
    BEGIN
       RVal := 0.0;
       ch := Upcase(Expr[1]);
       IF ch <> Locase(ch) THEN BEGIN
          tmp := '';
          REPEAT
             tmp := tmp + ch;
             Delete(Expr, 1, 1);
             ch := Upcase(Expr[1]);
          UNTIL (ch = Locase(ch)) OR (Length(Expr) = 0);
          IF tmp = 'ABS' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := ABS(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'ACOS' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := ArcCos(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'ASIN' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := ArcSin(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'ATAN' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := ARCTAN(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'COS' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := COS(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'FRAC' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := Eval(Expr, ErrCode);
                RVal := RVal - INT(RVal);
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'INT' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := INT(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'LOG' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := LOG(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'PI' THEN
             RVal := 3.141593
          ELSE IF tmp = 'SIN' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := SIN(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'SQRT' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := SQRT(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE IF tmp = 'TAN' THEN
             IF ch = '(' THEN BEGIN
                Delete(Expr, 1, 1);
                RVal := TAN(Eval(Expr, ErrCode))
             END
             ELSE
                ErrCode := 1
          ELSE
             ErrCode := 3
       END
       ELSE IF IsDigit(Expr) THEN BEGIN
          tmp := '';
          WHILE IsDigit(Expr) DO BEGIN
             tmp := tmp + Expr[1];
             Delete(Expr, 1, 1);
          END;
          Val(tmp, RVal, junk);
       END
       ELSE
          ErrCode := 2;
       Term := RVal;
    END;     { Term }

    END.     { ExtMath UNIT }

[Back to MATH SWAG index] [Back to Main SWAG index] [Original]