home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Merciful 3
/
Merciful_Release_3.bin
/
software
/
e
/
excalcv1.2reg.lha
/
ExCalcV1.2
/
Source
/
ExMathLib0.mod
< prev
next >
Wrap
Text File
|
1995-10-07
|
8KB
|
352 lines
MODULE ExMathLib0;
IMPORT LR := LongRealConversions, LM := MathIEEEDoubTrans,
X := ExNumbers;
VAR
ToRadians : X.ExNumType;
ToDegrees : X.ExNumType;
Fact500 : X.ExNumType;
Fact1000 : X.ExNumType;
Fact2000 : X.ExNumType;
Fact3000 : X.ExNumType;
PROCEDURE ExNumToLongReal*(x : X.ExNumType) : LONGREAL;
VAR
Num : LONGREAL;
Str : ARRAY 81 OF CHAR;
BEGIN
(* Convert ExNum into LONGREAL via a string *)
X.ExNumToStr(x, 0, 0, Str);
IF LR.StringToReal(Str, Num) THEN
RETURN Num;
ELSE
RETURN 0.0D;
END;
END ExNumToLongReal;
PROCEDURE LongRealToExNum*(x : LONGREAL; VAR Result : X.ExNumType);
VAR
Str : ARRAY 81 OF CHAR;
BEGIN
(* Convert LONGREAL into an ExNum via a string *)
IF LR.RealToString(x, Str, 1, 52, TRUE) THEN
X.StrToExNum(Str, Result);
ELSE
Result := X.Ex0;
END;
END LongRealToExNum;
PROCEDURE xtoi*(VAR Result : X.ExNumType; x : X.ExNumType; i : LONGINT);
(* From Knuth, slightly altered : p442, The Art Of Computer Programming, Vol 2 *)
VAR
Y : X.ExNumType;
negative : BOOLEAN;
BEGIN
Y := X.Ex1;
negative := i < 0;
i := ABS(i);
LOOP
IF ODD(i) THEN X.ExMult(Y, Y, x) END;
i := i DIV 2;
IF i = 0 THEN EXIT END;
X.ExMult(x, x, x);
END;
IF negative THEN
X.ExDiv(Result, X.Ex1, Y);
ELSE
Result := Y;
END;
END xtoi;
PROCEDURE Root *(VAR Result : X.ExNumType;
x : X.ExNumType;
i : LONGINT);
(* Use iterative solution of a general root equation *)
VAR
y, yp, f, g, t : X.ExNumType;
iteration : INTEGER;
root : LONGREAL;
negate : BOOLEAN;
BEGIN
IF ((x.Sign = X.negative) & ~ODD(i)) OR (i < 2) THEN
X.ExStatus := X.IllegalNumber;
Result := X.Ex0;
ELSIF X.IsZero(x) THEN
Result := x;
ELSE
(* handle negative roots *)
IF x.Sign = X.negative THEN X.ExAbs(x); negate := TRUE
ELSE negate := FALSE
END;
(* estimate of the ith root *)
root := 1.0D / i;
LongRealToExNum(LM.Pow(root,ExNumToLongReal(x)), yp);
X.ExNumb(i, 0, 0, f); (* i *)
X.ExNumb(i-1, 0, 0, g); (* i - 1 *)
(* calculate the root *)
iteration := 4;
LOOP
(* y := 1/i * (yp * (i-1) + x / yp^(i-1)) *)
xtoi(t, yp, i-1); (* yp**(i-1) *)
X.ExMult(y, t, yp); (* yp**i *)
X.ExMult(y, y, g); (* yp**i * (i-1) *)
X.ExAdd(y, y, x); (* yp**i * (i-1) + x *)
X.ExMult(t, t, f); (* yp**(i-1) * i *)
X.ExDiv(y, y, t);
IF (X.ExCompare(y, yp) = X.ExEqual) OR (iteration = 0) THEN EXIT END;
DEC(iteration);
yp := y;
END;
(* adjust the number's sign *)
Result := y;
IF negate THEN X.ExChgSign(Result) END;
END;
END Root;
PROCEDURE powerof10(VAR Result : X.ExNumType; x : LONGINT);
BEGIN
X.ExNumb(1, 0, SHORT(x), Result);
END powerof10;
PROCEDURE RadToDegX*(VAR radianAngle : X.ExNumType);
(* Convert a radian measure into degrees *)
BEGIN
X.ExMult(radianAngle, ToDegrees, radianAngle);
END RadToDegX;
PROCEDURE DegToRadX*(VAR radianAngle : X.ExNumType);
(* Convert a degree measure into radians *)
BEGIN
X.ExMult(radianAngle, ToRadians, radianAngle);
END DegToRadX;
PROCEDURE sqrtX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
Root(Result, x, 2);
END sqrtX;
PROCEDURE lnX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Log(ExNumToLongReal(x)), Result);
END lnX;
PROCEDURE logX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Log10(ExNumToLongReal(x)), Result);
END logX;
PROCEDURE factorial(VAR prevn, currentn : LONGINT;
VAR PrevFact, Result : X.ExNumType);
(* Implements an incremental factorial using a previously calculated value. *)
VAR
i : LONGINT;
BEGIN
FOR i := prevn+1 TO currentn DO
(* PrevFact := PrevFact * i; *)
X.ExNumb(i, 0, 0, Result);
X.ExMult(PrevFact, PrevFact, Result);
END;
prevn := currentn;
Result := PrevFact;
END factorial;
PROCEDURE factorialX*(VAR Result : X.ExNumType; n : LONGINT);
CONST
MaxFactorial = 3249;
VAR
fact : LONGINT;
prev : X.ExNumType;
BEGIN
IF (n < 0) OR (n > MaxFactorial) THEN
X.ExStatus := X.IllegalNumber;
Result := X.Ex0;
RETURN;
END;
IF n < 500 THEN prev := X.Ex1; fact := 0
ELSIF n < 1000 THEN prev := Fact500; fact := 500
ELSIF n < 2000 THEN prev := Fact1000; fact := 1000
ELSIF n < 3000 THEN prev := Fact2000; fact := 2000
ELSE prev := Fact3000; fact := 3000
END;
factorial(fact, n, prev, Result);
END factorialX;
PROCEDURE expX*(VAR Result : X.ExNumType; x : X.ExNumType);
VAR
xPower : LONGREAL;
BEGIN
xPower := ExNumToLongReal(x);
X.ExFrac(x);
IF (ABS(xPower) < MAX(LONGINT)) & X.IsZero(x) THEN
xtoi(Result, X.e, ENTIER(xPower));
ELSE
LongRealToExNum(LM.Exp(xPower), Result);
END;
END expX;
PROCEDURE powerX*(VAR Result : X.ExNumType; x, y : X.ExNumType);
VAR
yPower : LONGREAL;
BEGIN
yPower := ExNumToLongReal(y);
X.ExFrac(y);
IF (ABS(yPower) < MAX(LONGINT)) & X.IsZero(y) THEN
xtoi(Result, x, ENTIER(yPower));
ELSE
LongRealToExNum(LM.Pow(yPower,ExNumToLongReal(x)),Result);
END;
END powerX;
PROCEDURE rootX*(VAR Result : X.ExNumType; x, y : X.ExNumType);
VAR
yRoot : LONGREAL;
BEGIN
yRoot := ExNumToLongReal(y);
X.ExFrac(y);
IF (ABS(yRoot) < MAX(LONGINT)) & X.IsZero(y) THEN
Root(Result, x, ENTIER(yRoot));
ELSE
yRoot := 1.0D / yRoot;
LongRealToExNum(LM.Pow(yRoot,ExNumToLongReal(x)),Result);
END;
END rootX;
PROCEDURE sinX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Sin(ExNumToLongReal(x)), Result);
END sinX;
PROCEDURE cosX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Cos(ExNumToLongReal(x)), Result);
END cosX;
PROCEDURE tanX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Tan(ExNumToLongReal(x)), Result);
END tanX;
PROCEDURE arctanX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Atan(ExNumToLongReal(x)), Result);
END arctanX;
PROCEDURE coshX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Cosh(ExNumToLongReal(x)), Result);
END coshX;
PROCEDURE sinhX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Sinh(ExNumToLongReal(x)), Result);
END sinhX;
PROCEDURE tanhX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Tanh(ExNumToLongReal(x)), Result);
END tanhX;
PROCEDURE arccoshX*(VAR Result : X.ExNumType; x : X.ExNumType);
VAR
Temp : X.ExNumType;
BEGIN
(* Result = ln(x + sqrt(x*x - 1)) *)
X.ExMult(Temp, x, x);
X.ExSub(Temp, Temp, X.Ex1);
sqrtX(Temp, Temp);
X.ExAdd(Temp, x, Temp);
lnX(Result, Temp);
END arccoshX;
PROCEDURE arcsinhX*(VAR Result : X.ExNumType; x : X.ExNumType);
VAR
Temp : X.ExNumType;
BEGIN
(* Result = ln(x + sqrt(x*x + 1)) *)
X.ExMult(Temp, x, x);
X.ExAdd(Temp, Temp, X.Ex1);
sqrtX(Temp, Temp);
X.ExAdd(Temp, x, Temp);
lnX(Result, Temp);
END arcsinhX;
PROCEDURE arctanhX*(VAR Result : X.ExNumType; x : X.ExNumType);
VAR
Temp, Temp2 : X.ExNumType;
BEGIN
(* Result = ln((1 + x) / (1 - x)) / 2 *)
X.ExAdd(Temp, X.Ex1, x);
X.ExSub(Temp2, X.Ex1, x);
X.ExDiv(Temp, Temp, Temp2);
lnX(Result, Temp);
X.ExNumb(0, 5, 0, Temp);
X.ExMult(Result, Result, Temp);
END arctanhX;
PROCEDURE arcsinX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
LongRealToExNum(LM.Asin(ExNumToLongReal(x)), Result);
END arcsinX;
PROCEDURE arccosX*(VAR Result : X.ExNumType; x : X.ExNumType);
BEGIN
(* Replacement algorithm *)
LongRealToExNum(LM.Acos(ExNumToLongReal(x)), Result);
END arccosX;
BEGIN
(* Initialize a few internal conversion constants *)
X.StrToExNum(
"5.729577951308232087679815481410517033240547246656420E+1",
ToDegrees);
X.StrToExNum(
"1.745329251994329576923690768488612713442871888541727E-2",
ToRadians);
(* Speed up very large factorials *)
X.StrToExNum(
"1.220136825991110068701238785423046926253574342803193E+1134",
Fact500);
X.StrToExNum(
"4.023872600770937735437024339230039857193748642107146E+2567",
Fact1000);
X.StrToExNum(
"3.316275092450633241175393380576324038281117208105780E+5735",
Fact2000);
X.StrToExNum(
"4.149359603437854085556867093086612170951119194931810E+9130",
Fact3000);
END ExMathLib0.