forked from KolibriOS/kolibrios
311 lines
4.6 KiB
Plaintext
311 lines
4.6 KiB
Plaintext
|
(*
|
||
|
BSD 2-Clause License
|
||
|
|
||
|
Copyright (c) 2019, Anton Krotov
|
||
|
All rights reserved.
|
||
|
*)
|
||
|
|
||
|
MODULE Math;
|
||
|
|
||
|
IMPORT SYSTEM;
|
||
|
|
||
|
|
||
|
CONST
|
||
|
|
||
|
e *= 2.71828182845904523;
|
||
|
pi *= 3.14159265358979324;
|
||
|
ln2 *= 0.693147180559945309;
|
||
|
|
||
|
eps = 1.0E-16;
|
||
|
MaxCosArg = 1000000.0 * pi;
|
||
|
|
||
|
|
||
|
VAR
|
||
|
|
||
|
Exp: ARRAY 710 OF REAL;
|
||
|
|
||
|
|
||
|
PROCEDURE [stdcall64] sqrt* (x: REAL): REAL;
|
||
|
BEGIN
|
||
|
ASSERT(x >= 0.0);
|
||
|
SYSTEM.CODE(
|
||
|
0F2H, 0FH, 51H, 45H, 10H, (* sqrtsd xmm0, qword[rbp + 10h] *)
|
||
|
05DH, (* pop rbp *)
|
||
|
0C2H, 08H, 00H (* ret 8 *)
|
||
|
)
|
||
|
|
||
|
RETURN 0.0
|
||
|
END sqrt;
|
||
|
|
||
|
|
||
|
PROCEDURE exp* (x: REAL): REAL;
|
||
|
CONST
|
||
|
e25 = 1.284025416687741484; (* exp(0.25) *)
|
||
|
|
||
|
VAR
|
||
|
a, s, res: REAL;
|
||
|
neg: BOOLEAN;
|
||
|
n: INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
neg := x < 0.0;
|
||
|
IF neg THEN
|
||
|
x := -x
|
||
|
END;
|
||
|
|
||
|
IF x < FLT(LEN(Exp)) THEN
|
||
|
res := Exp[FLOOR(x)];
|
||
|
x := x - FLT(FLOOR(x));
|
||
|
WHILE x >= 0.25 DO
|
||
|
res := res * e25;
|
||
|
x := x - 0.25
|
||
|
END
|
||
|
ELSE
|
||
|
res := SYSTEM.INF();
|
||
|
x := 0.0
|
||
|
END;
|
||
|
|
||
|
n := 0;
|
||
|
a := 1.0;
|
||
|
s := 1.0;
|
||
|
|
||
|
REPEAT
|
||
|
INC(n);
|
||
|
a := a * x / FLT(n);
|
||
|
s := s + a
|
||
|
UNTIL a < eps;
|
||
|
|
||
|
IF neg THEN
|
||
|
res := 1.0 / (res * s)
|
||
|
ELSE
|
||
|
res := res * s
|
||
|
END
|
||
|
|
||
|
RETURN res
|
||
|
END exp;
|
||
|
|
||
|
|
||
|
PROCEDURE ln* (x: REAL): REAL;
|
||
|
VAR
|
||
|
a, x2, res: REAL;
|
||
|
n: INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
ASSERT(x > 0.0);
|
||
|
UNPK(x, n);
|
||
|
|
||
|
x := (x - 1.0) / (x + 1.0);
|
||
|
x2 := x * x;
|
||
|
res := x + FLT(n) * (ln2 * 0.5);
|
||
|
n := 1;
|
||
|
|
||
|
REPEAT
|
||
|
INC(n, 2);
|
||
|
x := x * x2;
|
||
|
a := x / FLT(n);
|
||
|
res := res + a
|
||
|
UNTIL a < eps
|
||
|
|
||
|
RETURN res * 2.0
|
||
|
END ln;
|
||
|
|
||
|
|
||
|
PROCEDURE power* (base, exponent: REAL): REAL;
|
||
|
BEGIN
|
||
|
ASSERT(base > 0.0)
|
||
|
RETURN exp(exponent * ln(base))
|
||
|
END power;
|
||
|
|
||
|
|
||
|
PROCEDURE log* (base, x: REAL): REAL;
|
||
|
BEGIN
|
||
|
ASSERT(base > 0.0);
|
||
|
ASSERT(x > 0.0)
|
||
|
RETURN ln(x) / ln(base)
|
||
|
END log;
|
||
|
|
||
|
|
||
|
PROCEDURE cos* (x: REAL): REAL;
|
||
|
VAR
|
||
|
a, res: REAL;
|
||
|
n: INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
x := ABS(x);
|
||
|
ASSERT(x <= MaxCosArg);
|
||
|
|
||
|
x := x - FLT( FLOOR(x / (2.0 * pi)) ) * (2.0 * pi);
|
||
|
x := x * x;
|
||
|
res := 0.0;
|
||
|
a := 1.0;
|
||
|
n := -1;
|
||
|
|
||
|
REPEAT
|
||
|
INC(n, 2);
|
||
|
res := res + a;
|
||
|
a := -a * x / FLT(n*n + n)
|
||
|
UNTIL ABS(a) < eps
|
||
|
|
||
|
RETURN res
|
||
|
END cos;
|
||
|
|
||
|
|
||
|
PROCEDURE sin* (x: REAL): REAL;
|
||
|
BEGIN
|
||
|
ASSERT(ABS(x) <= MaxCosArg);
|
||
|
x := cos(x)
|
||
|
RETURN sqrt(1.0 - x * x)
|
||
|
END sin;
|
||
|
|
||
|
|
||
|
PROCEDURE tan* (x: REAL): REAL;
|
||
|
BEGIN
|
||
|
ASSERT(ABS(x) <= MaxCosArg);
|
||
|
x := cos(x)
|
||
|
RETURN sqrt(1.0 - x * x) / x
|
||
|
END tan;
|
||
|
|
||
|
|
||
|
PROCEDURE arcsin* (x: REAL): REAL;
|
||
|
|
||
|
|
||
|
PROCEDURE arctan (x: REAL): REAL;
|
||
|
VAR
|
||
|
z, p, k: REAL;
|
||
|
|
||
|
BEGIN
|
||
|
p := x / (x * x + 1.0);
|
||
|
z := p * x;
|
||
|
x := 0.0;
|
||
|
k := 0.0;
|
||
|
|
||
|
REPEAT
|
||
|
k := k + 2.0;
|
||
|
x := x + p;
|
||
|
p := p * k * z / (k + 1.0)
|
||
|
UNTIL p < eps
|
||
|
|
||
|
RETURN x
|
||
|
END arctan;
|
||
|
|
||
|
|
||
|
BEGIN
|
||
|
ASSERT(ABS(x) <= 1.0);
|
||
|
|
||
|
IF ABS(x) >= 0.707 THEN
|
||
|
x := 0.5 * pi - arctan(sqrt(1.0 - x * x) / x)
|
||
|
ELSE
|
||
|
x := arctan(x / sqrt(1.0 - x * x))
|
||
|
END
|
||
|
|
||
|
RETURN x
|
||
|
END arcsin;
|
||
|
|
||
|
|
||
|
PROCEDURE arccos* (x: REAL): REAL;
|
||
|
BEGIN
|
||
|
ASSERT(ABS(x) <= 1.0)
|
||
|
RETURN 0.5 * pi - arcsin(x)
|
||
|
END arccos;
|
||
|
|
||
|
|
||
|
PROCEDURE arctan* (x: REAL): REAL;
|
||
|
RETURN arcsin(x / sqrt(1.0 + x * x))
|
||
|
END arctan;
|
||
|
|
||
|
|
||
|
PROCEDURE sinh* (x: REAL): REAL;
|
||
|
BEGIN
|
||
|
x := exp(x)
|
||
|
RETURN (x - 1.0 / x) * 0.5
|
||
|
END sinh;
|
||
|
|
||
|
|
||
|
PROCEDURE cosh* (x: REAL): REAL;
|
||
|
BEGIN
|
||
|
x := exp(x)
|
||
|
RETURN (x + 1.0 / x) * 0.5
|
||
|
END cosh;
|
||
|
|
||
|
|
||
|
PROCEDURE tanh* (x: REAL): REAL;
|
||
|
BEGIN
|
||
|
IF x > 15.0 THEN
|
||
|
x := 1.0
|
||
|
ELSIF x < -15.0 THEN
|
||
|
x := -1.0
|
||
|
ELSE
|
||
|
x := exp(2.0 * x);
|
||
|
x := (x - 1.0) / (x + 1.0)
|
||
|
END
|
||
|
|
||
|
RETURN x
|
||
|
END tanh;
|
||
|
|
||
|
|
||
|
PROCEDURE arsinh* (x: REAL): REAL;
|
||
|
RETURN ln(x + sqrt(x * x + 1.0))
|
||
|
END arsinh;
|
||
|
|
||
|
|
||
|
PROCEDURE arcosh* (x: REAL): REAL;
|
||
|
BEGIN
|
||
|
ASSERT(x >= 1.0)
|
||
|
RETURN ln(x + sqrt(x * x - 1.0))
|
||
|
END arcosh;
|
||
|
|
||
|
|
||
|
PROCEDURE artanh* (x: REAL): REAL;
|
||
|
BEGIN
|
||
|
ASSERT(ABS(x) < 1.0)
|
||
|
RETURN 0.5 * ln((1.0 + x) / (1.0 - x))
|
||
|
END artanh;
|
||
|
|
||
|
|
||
|
PROCEDURE sgn* (x: REAL): INTEGER;
|
||
|
VAR
|
||
|
res: INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
IF x > 0.0 THEN
|
||
|
res := 1
|
||
|
ELSIF x < 0.0 THEN
|
||
|
res := -1
|
||
|
ELSE
|
||
|
res := 0
|
||
|
END
|
||
|
|
||
|
RETURN res
|
||
|
END sgn;
|
||
|
|
||
|
|
||
|
PROCEDURE fact* (n: INTEGER): REAL;
|
||
|
VAR
|
||
|
res: REAL;
|
||
|
|
||
|
BEGIN
|
||
|
res := 1.0;
|
||
|
WHILE n > 1 DO
|
||
|
res := res * FLT(n);
|
||
|
DEC(n)
|
||
|
END
|
||
|
|
||
|
RETURN res
|
||
|
END fact;
|
||
|
|
||
|
|
||
|
PROCEDURE init;
|
||
|
VAR
|
||
|
i: INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
Exp[0] := 1.0;
|
||
|
FOR i := 1 TO LEN(Exp) - 1 DO
|
||
|
Exp[i] := Exp[i - 1] * e
|
||
|
END
|
||
|
END init;
|
||
|
|
||
|
|
||
|
BEGIN
|
||
|
init
|
||
|
END Math.
|