123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- MODULE Math;
- (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 System/Mod/Math.odc *)
- (* DO NOT EDIT *)
- IMPORT SYSTEM;
- VAR eps, e: REAL;
- (* code procedures for 80387 math coprocessor *)
- PROCEDURE [code] FLD (x: REAL);
- PROCEDURE [code] TOP (): REAL;
- PROCEDURE [code] FSW (): INTEGER 0DFH, 0E0H;
- PROCEDURE [code] FSWs (): SET 0DFH, 0E0H;
- PROCEDURE [code] ST0 (): REAL 0D9H, 0C0H;
- PROCEDURE [code] ST1 (): REAL 0D9H, 0C1H;
- PROCEDURE [code] FXCH 0D9H, 0C9H;
- PROCEDURE [code] FLDst0 0D9H, 0C0H; (* doublicate st[0] *)
- PROCEDURE [code] FSTPst0 0DDH, 0D8H; (* remove st[0] *)
- PROCEDURE [code] FSTPst1 0DDH, 0D9H; (* remove st[1] *)
- PROCEDURE [code] FSTPDe 0DBH, 05DH, 0F4H; (* FSTPD -12[FP] *) (* COMPILER DEPENDENT *)
- PROCEDURE [code] WAIT 09BH;
- PROCEDURE [code] FNOP 0D9H, 0D0H;
- PROCEDURE [code] FLD0 0D9H, 0EEH;
- PROCEDURE [code] FLD1 0D9H, 0E8H;
- PROCEDURE [code] FLDPI 0D9H, 0EBH;
- PROCEDURE [code] FLDLN2 0D9H, 0EDH;
- PROCEDURE [code] FLDLG2 0D9H, 0ECH;
- PROCEDURE [code] FLDL2E 0D9H, 0EAH;
- PROCEDURE [code] FADD 0DEH, 0C1H;
- PROCEDURE [code] FADDst0 0D8H, 0C0H;
- PROCEDURE [code] FSUB 0DEH, 0E9H;
- PROCEDURE [code] FSUBn 0DCH, 0E9H; (* no pop *)
- PROCEDURE [code] FSUBR 0DEH, 0E1H;
- PROCEDURE [code] FSUBst1 0D8H, 0E1H;
- PROCEDURE [code] FMUL 0DEH, 0C9H;
- PROCEDURE [code] FMULst0 0D8H, 0C8H;
- PROCEDURE [code] FMULst1st0 0DCH, 0C9H;
- PROCEDURE [code] FDIV 0DEH, 0F9H;
- PROCEDURE [code] FDIVR 0DEH, 0F1H;
- PROCEDURE [code] FDIVRst1 0D8H, 0F9H;
- PROCEDURE [code] FCHS 0D9H, 0E0H;
- PROCEDURE [code] FCOM 0D8H, 0D1H;
- PROCEDURE [code] FSWax 0DFH, 0E0H;
- PROCEDURE [code] SAHF 09EH;
- PROCEDURE [code] JBE4 076H, 004H;
- PROCEDURE [code] JAE4 073H, 004H;
- PROCEDURE [code] FRNDINT 0D9H, 0FCH;
- PROCEDURE [code] FSCALE 0D9H, 0FDH; (* st[0] * 2^FLOOR(st[1]) *)
- PROCEDURE [code] FXTRACT 0D9H, 0F4H; (* exp -> st[1]; mant -> st[0] *)
- PROCEDURE [code] FXAM 0D9H, 0E5H;
- PROCEDURE [code] FSQRT 0D9H, 0FAH; (* st[0] >= 0 *)
- PROCEDURE [code] FSIN 0D9H, 0FEH; (* |st[0]| < 2^63 *)
- PROCEDURE [code] FCOS 0D9H, 0FFH; (* |st[0]| < 2^63 *)
- PROCEDURE [code] FTAN 0D9H, 0F2H; (* |st[0]| < 2^63 *)
- PROCEDURE [code] FATAN 0D9H, 0F3H; (* atan2(st[1], st[0]) *)
- PROCEDURE [code] FYL2X 0D9H, 0F1H; (* st[1] * log2(st[0]), st[0] > 0 *)
- PROCEDURE [code] FYL2XP1 0D9H, 0F9H; (* st[1] * log2(1 + st[0]), |st[0]| < 1-sqrt(2)/2 *)
- PROCEDURE [code] F2XM1 0D9H, 0F0H; (* 2^st[0] - 1, |st[0]| <= 1 *)
- PROCEDURE IsNan (x: REAL): BOOLEAN;
- BEGIN
- FLD(x); FXAM; FSTPst0; WAIT; RETURN FSWs() * {8, 10} = {8}
- END IsNan;
- (* sin, cos, tan argument reduction *)
- PROCEDURE Reduce;
- BEGIN
- FXAM; WAIT;
- IF ~(8 IN FSWs()) & (ABS(ST0()) > 1.0E18) THEN
- (* to be completed *)
- FSTPst0; FLD0
- END;
- END Reduce;
- (** REAL precision **)
- PROCEDURE Pi* (): REAL;
- BEGIN
- FLDPI; RETURN TOP()
- END Pi;
- PROCEDURE Eps* (): REAL;
- BEGIN
- RETURN eps
- END Eps;
- PROCEDURE Sqrt* (x: REAL): REAL;
- BEGIN
- (* 20, argument of Sqrt must not be negative *)
- FLD(x); FSQRT; WAIT; RETURN TOP()
- END Sqrt;
- PROCEDURE Exp* (x: REAL): REAL;
- BEGIN
- (* 2 ^ (x * 1/ln(2)) *)
- FLD(x); FLDL2E; FMUL;
- IF ABS(ST0()) = INF THEN FLD1
- ELSE FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD
- END;
- FSCALE; FSTPst1; RETURN TOP()
- END Exp;
- PROCEDURE Ln* (x: REAL): REAL;
- BEGIN
- (* 20, argument of Ln must not be negative *)
- (* ln(2) * ld(x) *)
- FLDLN2; FLD(x); FYL2X; WAIT; RETURN TOP()
- END Ln;
- PROCEDURE Log* (x: REAL): REAL;
- BEGIN
- (* 20, argument of Log must not be negative *)
- (* log(2) * ld(x) *)
- FLDLG2; FLD(x); FYL2X; WAIT; RETURN TOP()
- END Log;
- PROCEDURE Power* (x, y: REAL): REAL;
- BEGIN
- ASSERT(x >= 0, 20);
- ASSERT((x # 0.0) OR (y # 0.0), 21);
- ASSERT((x # INF) OR (y # 0.0), 22);
- ASSERT((x # 1.0) OR (ABS(y) # INF), 23);
- (* 2 ^ (y * ld(x)) *)
- FLD(y); FLD(x); FYL2X;
- IF ABS(ST0()) = INF THEN FLD1
- ELSE FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD
- END;
- FSCALE; FSTPst1; WAIT; RETURN TOP()
- END Power;
- PROCEDURE IntPower* (x: REAL; n: INTEGER): REAL;
- BEGIN
- FLD1; FLD(x);
- IF n = MIN(INTEGER) THEN RETURN IntPower(x, n + 1) / x END;
- IF n <= 0 THEN FDIVRst1; (* 1 / x *) n := -n END;
- WHILE n > 0 DO
- IF ODD(n) THEN FMULst1st0; (* y := y * x *) DEC(n)
- ELSE FMULst0; (* x := x * x *) n := n DIV 2
- END
- END;
- FSTPst0; RETURN TOP()
- END IntPower;
- PROCEDURE Sin* (x: REAL): REAL;
- BEGIN
- (* 20, ABS(x) # INF *)
- FLD(x); Reduce; FSIN; WAIT; RETURN TOP()
- END Sin;
- PROCEDURE Cos* (x: REAL): REAL;
- BEGIN
- (* 20, ABS(x) # INF *)
- FLD(x); Reduce; FCOS; WAIT; RETURN TOP()
- END Cos;
- PROCEDURE Tan* (x: REAL): REAL;
- BEGIN
- (* 20, ABS(x) # INF *)
- FLD(x); Reduce; FTAN; FSTPst0; WAIT; RETURN TOP()
- END Tan;
- PROCEDURE ArcSin* (x: REAL): REAL;
- BEGIN
- (* 20, -1.0 <= x <= 1.0 *)
- (* atan2(x, sqrt(1 - x*x)) *)
- FLD(x); FLDst0; FMULst0; FLD1; FSUBR; FSQRT; FNOP; FATAN; WAIT; RETURN TOP()
- END ArcSin;
- PROCEDURE ArcCos* (x: REAL): REAL;
- BEGIN
- (* 20, -1.0 <= x <= 1.0 *)
- (* atan2(sqrt(1 - x*x), x) *)
- FLD(x); FMULst0; FLD1; FSUBR; FSQRT; FLD(x); FATAN; WAIT; RETURN TOP()
- END ArcCos;
- PROCEDURE ArcTan* (x: REAL): REAL;
- BEGIN
- (* atan2(x, 1) *)
- FLD(x); FLD1; FATAN; RETURN TOP()
- END ArcTan;
- PROCEDURE ArcTan2* (y, x: REAL): REAL;
- BEGIN
- ASSERT((y # 0) OR (x # 0), 20);
- ASSERT((ABS(y) # INF) OR (ABS(x) # INF), 21);
- FLD(y); FLD(x); FATAN; WAIT; RETURN TOP()
- END ArcTan2;
- PROCEDURE Sinh* (x: REAL): REAL;
- BEGIN
- (* IF IsNan(x) THEN RETURN x END; *)
- (* abs(x) * 1/ln(2) *)
- FLD(ABS(x)); FLDL2E; FMUL;
- IF ST0() < 0.5 THEN
- (* (2^z - 1) + (2^z - 1) / ((2^z - 1) + 1) *)
- F2XM1; FLDst0; FLDst0; FLD1; FADD; FDIV; FADD
- ELSIF ST0() # INF THEN
- (* 2^z - 1 / 2^z *)
- FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD; FSCALE;
- FSTPst1; FLDst0; FLD1; FDIVR; FSUB
- END;
- IF x < 0 THEN FCHS END;
- RETURN TOP() * 0.5
- END Sinh;
- PROCEDURE Cosh* (x: REAL): REAL;
- BEGIN
- (* IF IsNan(x) THEN RETURN x END; *)
- (* 2^(abs(x) * 1/ln(2)) *)
- FLD(ABS(x));
- IF ST0() # INF THEN
- FLDL2E; FMUL; FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD; FSCALE;
- FSTPst1;
- (* z + 1/z *)
- FLDst0; FLD1; FDIVR; FADD
- END;
- RETURN TOP() * 0.5
- END Cosh;
- PROCEDURE Tanh* (x: REAL): REAL;
- BEGIN
- (* IF IsNan(x) THEN RETURN x END; *)
- (* abs(x) * 1/ln(2) * 2 *)
- FLD(ABS(x)); FLDL2E; FMUL; FADDst0;
- IF ST0() < 0.5 THEN
- (* (2^z - 1) / (2^z + 1) *)
- F2XM1; FLDst0; FLD(2); FADD; FDIV
- ELSIF ST0() < 65 THEN
- (* 1 - 2 / (2^z + 1) *)
- FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD; FSCALE;
- FSTPst1; FLD1; FADD; FLD(2); FDIVR; FLD1; FSUBR
- ELSE
- FSTPst0; FLD1
- END;
- IF x < 0 THEN FCHS END;
- RETURN TOP()
- END Tanh;
- PROCEDURE ArcSinh* (x: REAL): REAL;
- BEGIN
- (* IF IsNan(x) THEN RETURN x END; *)
- (* x*x *)
- FLDLN2; FLD(ABS(x)); FLDst0; FMULst0;
- IF ST0() < 0.067 THEN
- (* ln(2) * ld(1 + x*x / (sqrt(x*x + 1) + 1) + x) *)
- FLDst0; FLD1; FADD; FSQRT; FLD1; FADD; FDIV; FADD; FYL2XP1
- ELSE
- (* ln(2) * ld(x + sqrt(x*x + 1)) *)
- FLD1; FADD; FSQRT; FADD; FYL2X
- END;
- IF x < 0 THEN FCHS END;
- RETURN TOP()
- END ArcSinh;
- PROCEDURE ArcCosh* (x: REAL): REAL;
- BEGIN
- (* 20, x >= 1.0 *)
- (* IF IsNan(x) THEN RETURN x END; *)
- (* ln(2) * ld(x + sqrt(x*x - 1)) *)
- FLDLN2; FLD(x); FLDst0; FMULst0; FLD1; FSUB; FSQRT; FADD; FYL2X; WAIT; RETURN TOP()
- END ArcCosh;
- PROCEDURE ArcTanh* (x: REAL): REAL;
- BEGIN
- (* 20, -1.0 <= x <= 1.0 *)
- (* IF IsNan(x) THEN RETURN x END; *)
- (* |x| *)
- FLDLN2; FLD(ABS(x));
- IF ST0() < 0.12 THEN
- (* ln(2) * ld(1 + 2*x / (1 - x)) *)
- FLDst0; FLD1; FSUBR; FDIV; FADDst0; FYL2XP1
- ELSE
- (* ln(2) * ld((1 + x) / (1 - x)) *)
- FLDst0; FLD1; FADD; FXCH; FLD1; FSUBR; FDIV; FNOP; FYL2X
- END;
- IF x < 0 THEN FCHS END;
- WAIT;
- RETURN TOP() * 0.5
- END ArcTanh;
- PROCEDURE Floor* (x: REAL): REAL;
- BEGIN
- FLD(x); FLDst0; FRNDINT; FCOM; FSWax; FSTPst1; SAHF; JBE4; FLD1; FSUB; RETURN TOP()
- END Floor;
- PROCEDURE Ceiling* (x: REAL): REAL;
- BEGIN
- FLD(x); FLDst0; FRNDINT; FCOM; FSWax; FSTPst1; SAHF; JAE4; FLD1; FADD; RETURN TOP()
- END Ceiling;
- PROCEDURE Round* (x: REAL): REAL;
- BEGIN
- FLD(x);
- IF ABS(ST0()) = INF THEN RETURN TOP() END;
- FLDst0; FRNDINT; FSUBn; FXCH;
- IF TOP() = 0.5 THEN FLD1; FADD END;
- RETURN TOP()
- END Round;
- PROCEDURE Trunc* (x: REAL): REAL;
- BEGIN
- FLD(x); FLDst0; FRNDINT;
- IF ST1() >= 0 THEN
- FCOM; FSWax; FSTPst1; SAHF; JBE4; FLD1; FSUB
- ELSE
- FCOM; FSWax; FSTPst1; SAHF; JAE4; FLD1; FADD
- END;
- RETURN TOP()
- END Trunc;
- PROCEDURE Frac* (x: REAL): REAL;
- BEGIN
- (* 20, x # INF & x # -INF *)
- FLD(x); FLDst0; FRNDINT;
- IF ST1() >= 0 THEN
- FCOM; FSWax; SAHF; JBE4; FLD1; FSUB
- ELSE
- FCOM; FSWax; SAHF; JAE4; FLD1; FADD
- END;
- FSUB; WAIT; RETURN TOP()
- END Frac;
- PROCEDURE Sign* (x: REAL): REAL;
- BEGIN
- FLD(x); FXAM; WAIT;
- CASE FSW() DIV 256 MOD 8 OF
- | 0, 2: FSTPst0; RETURN 0.0
- | 1, 4, 5: FSTPst0; RETURN 1.0
- | 3, 6, 7: FSTPst0; RETURN -1.0
- END
- END Sign;
- PROCEDURE Mantissa* (x: REAL): REAL;
- BEGIN
- FLD(x); FXAM; WAIT;
- CASE FSW() DIV 256 MOD 8 OF
- | 4, 6: FXTRACT; FSTPst1; RETURN TOP()
- | 0, 2: FSTPst0; RETURN 0.0 (* zero *)
- | 5: FSTPst0; RETURN 1.0 (* inf *)
- | 7: FSTPst0; RETURN -1.0 (* -inf *)
- | 1: FSTPst0; RETURN 1.5 (* nan *)
- | 3: FSTPst0; RETURN -1.5 (* -nan *)
- END
- END Mantissa;
- PROCEDURE Exponent* (x: REAL): INTEGER; (* COMPILER DEPENDENT *)
- VAR e: INTEGER; (* e is set by FSTPDe! *)
- BEGIN
- FLD(x); FXAM; WAIT;
- CASE FSW() DIV 256 MOD 8 OF
- | 4, 6: FXTRACT; FSTPst0; FSTPDe; WAIT; RETURN e
- | 0, 2: FSTPst0; RETURN 0 (* zero *)
- | 1, 3, 5, 7: FSTPst0; RETURN MAX(INTEGER) (* inf or nan*)
- END
- END Exponent;
- PROCEDURE Real* (m: REAL; e: INTEGER): REAL;
- VAR s: SET;
- BEGIN
- IF (m = 0) THEN RETURN 0.0 END;
- ASSERT(~IsNan(m) & (1 <= ABS(m)) & (ABS(m) < 2), 20);
- IF e = MAX(INTEGER) THEN
- SYSTEM.GET(SYSTEM.ADR(m) + 4, s);
- SYSTEM.PUT(SYSTEM.ADR(m) + 4, s + {20..30});
- RETURN m
- ELSE
- FLD(e); FLD(m); FSCALE; FSTPst1; RETURN TOP()
- END
- END Real;
- BEGIN
- eps := 1.0E+0; e := 2.0E+0;
- WHILE e > 1.0E+0 DO eps := eps/2.0E+0; e := 1.0E+0 + eps END; eps := 2.0E+0 * eps;
- END Math.
- PROCEDURE Log* (x: REAL): REAL;
- BEGIN
- RETURN Ln(x)/ln10
- END Log;
-
- PROCEDURE Power* (x, y: REAL): REAL;
- BEGIN
- RETURN Exp(y * Ln(x))
- END Power;
-
- PROCEDURE IntPower* (x: REAL; n: LONGINT): REAL;
- VAR y: REAL;
- BEGIN y := 1.0E+0;
- IF n < 0 THEN x := 1.0E+0/x; n := -n END;
- WHILE n > 0 DO
- IF ODD(n) THEN y := y*x; DEC(n)
- ELSE x := x * x; n := n DIV 2
- END
- END;
- RETURN y
- END IntPower;
- PROCEDURE Tan* (x: REAL): REAL;
- BEGIN
- RETURN Sin(x)/Cos(x)
- END Tan;
-
- PROCEDURE ArcSin* (x: REAL): REAL;
- BEGIN
- RETURN 2.0E+0 * ArcTan(x/(1.0E+0 + Sqrt(1.0E+0 - x*x)))
- END ArcSin;
-
- PROCEDURE ArcCos* (x: REAL): REAL;
- BEGIN (* pi/2 - arcsin(x) *)
- RETURN Pi()/2.0E+0 - 2.0E+0 * ArcTan(x/(1.0E+0 + Sqrt(1.0E+0 - x*x)))
- (*
- IF x = -1 THEN RETURN Pi()
- ELSE RETURN 2 * ArcTan(Sqrt((1 - x) / (1 + x)))
- END
- *) END ArcCos;
- PROCEDURE ArcTan2* (y, x: REAL): REAL;
- BEGIN
- IF x = 0.0 THEN
- RETURN Sign(y) * Pi() / 2.0
- ELSIF y = 0.0 THEN
- RETURN (1.0 - Sign(x)) * Pi() / 2.0
- ELSE
- RETURN ArcTan(y/x) + (1.0 - Sign(x)) * Sign(y) * Pi() / 2.0
- END
- END ArcTan2;
- PROCEDURE Sinh* (x: REAL): REAL;
- BEGIN
- IF ABS(x) < -lneps THEN RETURN (Exp(x)-Exp(-x))/2.0E+0
- ELSE RETURN Sign(x)*Exp(ABS(x))/2.0E+0
- END
- END Sinh;
-
- PROCEDURE Cosh* (x: REAL): REAL;
- BEGIN
- IF ABS(x) < -lneps THEN RETURN (Exp(x)+Exp(-x))/2.0E+0
- ELSE RETURN Exp(ABS(x))/2.0E+0
- END
- END Cosh;
-
- PROCEDURE Tanh* (x: REAL): REAL;
- VAR e1, e2: REAL;
- BEGIN
- IF ABS(x) < -lneps THEN
- e1 := Exp(x); e2 := 1.0E+0/e1;
- RETURN (e1-e2)/(e1+e2)
- ELSE
- RETURN Sign(x)
- END
- END Tanh;
-
- PROCEDURE ArcSinh* (x: REAL): REAL;
- BEGIN
- IF x >= 0.0E+0 THEN RETURN Ln(x + Sqrt(x*x + 1.0E+0))
- ELSE RETURN - Ln(-x + Sqrt(x*x + 1.0E+0))
- END
- END ArcSinh;
-
- PROCEDURE ArcCosh* (x: REAL): REAL;
- BEGIN
- RETURN Ln(x + Sqrt(x*x - 1.0E+0))
- END ArcCosh;
-
- PROCEDURE ArcTanh* (x: REAL): REAL;
- BEGIN
- RETURN Ln((1.0E+0 + x)/(1.0E+0 - x))/2.0E+0
- (* Variants:
- (Ln(1+x)-Ln(1-x))/2.0E+0
- -Ln((1-x)/Sqrt(1-x*x))
- arcsinh(x/sqrt(1-x*x))
- *)
- END ArcTanh;
-
- PROCEDURE Floor* (x: REAL): REAL;
- BEGIN
- IF ABS(x) >= 1.0E16 THEN RETURN x
- ELSE RETURN ENTIER(x)
- END
- END Floor;
-
- PROCEDURE Ceiling* (x: REAL): REAL;
- BEGIN
- IF ABS(x) >= 1.0E16 THEN RETURN x
- ELSE RETURN -ENTIER(-x)
- END
- END Ceiling;
-
- PROCEDURE Round* (x: REAL): REAL;
- BEGIN
- IF ABS(x) >= 1.0E16 THEN RETURN x
- ELSE RETURN ENTIER(x + 0.5)
- END
- END Round;
- PROCEDURE Trunc* (x: REAL): REAL;
- BEGIN
- IF ABS(x) >= 1.0E16 THEN RETURN x
- ELSIF x >= 0 THEN RETURN ENTIER(x)
- ELSE RETURN -ENTIER(-x)
- END
- END Trunc;
- PROCEDURE Frac* (x: REAL): REAL;
- BEGIN
- IF ABS(x) >= 1.0E16 THEN RETURN 0.0
- ELSIF x >= 0 THEN RETURN x - ENTIER(x)
- ELSE RETURN x + ENTIER(-x)
- END
- END Frac;
-
|