Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2019, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE Math;
  9.  
  10. IMPORT SYSTEM;
  11.  
  12.  
  13. CONST
  14.  
  15.     e   *= 2.71828182845904523;
  16.     pi  *= 3.14159265358979324;
  17.     ln2 *= 0.693147180559945309;
  18.  
  19.     eps = 1.0E-16;
  20.     MaxCosArg = 1000000.0 * pi;
  21.  
  22.  
  23. VAR
  24.  
  25.     Exp: ARRAY 710 OF REAL;
  26.  
  27.  
  28. PROCEDURE [stdcall64] sqrt* (x: REAL): REAL;
  29. BEGIN
  30.     ASSERT(x >= 0.0);
  31.     SYSTEM.CODE(
  32.     0F2H, 0FH, 51H, 45H, 10H,  (*  sqrtsd  xmm0, qword[rbp + 10h]  *)
  33.     05DH,                      (*  pop     rbp                     *)
  34.     0C2H, 08H, 00H             (*  ret     8                       *)
  35.     )
  36.  
  37.     RETURN 0.0
  38. END sqrt;
  39.  
  40.  
  41. PROCEDURE exp* (x: REAL): REAL;
  42. CONST
  43.     e25 = 1.284025416687741484; (* exp(0.25) *)
  44.  
  45. VAR
  46.     a, s, res: REAL;
  47.     neg: BOOLEAN;
  48.     n: INTEGER;
  49.  
  50. BEGIN
  51.     neg := x < 0.0;
  52.     IF neg THEN
  53.         x := -x
  54.     END;
  55.  
  56.     IF x < FLT(LEN(Exp)) THEN
  57.         res := Exp[FLOOR(x)];
  58.         x := x - FLT(FLOOR(x));
  59.         WHILE x >= 0.25 DO
  60.             res := res * e25;
  61.             x := x - 0.25
  62.         END
  63.     ELSE
  64.         res := SYSTEM.INF();
  65.         x := 0.0
  66.     END;
  67.  
  68.     n := 0;
  69.     a := 1.0;
  70.     s := 1.0;
  71.  
  72.     REPEAT
  73.         INC(n);
  74.         a := a * x / FLT(n);
  75.         s := s + a
  76.     UNTIL a < eps;
  77.  
  78.     IF neg THEN
  79.         res := 1.0 / (res * s)
  80.     ELSE
  81.         res := res * s
  82.     END
  83.  
  84.     RETURN res
  85. END exp;
  86.  
  87.  
  88. PROCEDURE ln* (x: REAL): REAL;
  89. VAR
  90.     a, x2, res: REAL;
  91.     n: INTEGER;
  92.  
  93. BEGIN
  94.     ASSERT(x > 0.0);
  95.     UNPK(x, n);
  96.  
  97.     x   := (x - 1.0) / (x + 1.0);
  98.     x2  := x * x;
  99.     res := x + FLT(n) * (ln2 * 0.5);
  100.     n   := 1;
  101.  
  102.     REPEAT
  103.         INC(n, 2);
  104.         x := x * x2;
  105.         a := x / FLT(n);
  106.         res := res + a
  107.     UNTIL a < eps
  108.  
  109.     RETURN res * 2.0
  110. END ln;
  111.  
  112.  
  113. PROCEDURE power* (base, exponent: REAL): REAL;
  114. BEGIN
  115.     ASSERT(base > 0.0)
  116.     RETURN exp(exponent * ln(base))
  117. END power;
  118.  
  119.  
  120. PROCEDURE log* (base, x: REAL): REAL;
  121. BEGIN
  122.     ASSERT(base > 0.0);
  123.     ASSERT(x > 0.0)
  124.     RETURN ln(x) / ln(base)
  125. END log;
  126.  
  127.  
  128. PROCEDURE cos* (x: REAL): REAL;
  129. VAR
  130.     a, res: REAL;
  131.     n: INTEGER;
  132.  
  133. BEGIN
  134.     x := ABS(x);
  135.     ASSERT(x <= MaxCosArg);
  136.  
  137.     x   := x - FLT( FLOOR(x / (2.0 * pi)) ) * (2.0 * pi);
  138.     x   := x * x;
  139.     res := 0.0;
  140.     a   := 1.0;
  141.     n   := -1;
  142.  
  143.     REPEAT
  144.         INC(n, 2);
  145.         res := res + a;
  146.         a := -a * x / FLT(n*n + n)
  147.     UNTIL ABS(a) < eps
  148.  
  149.     RETURN res
  150. END cos;
  151.  
  152.  
  153. PROCEDURE sin* (x: REAL): REAL;
  154. BEGIN
  155.     ASSERT(ABS(x) <= MaxCosArg);
  156.     x := cos(x)
  157.     RETURN sqrt(1.0 - x * x)
  158. END sin;
  159.  
  160.  
  161. PROCEDURE tan* (x: REAL): REAL;
  162. BEGIN
  163.     ASSERT(ABS(x) <= MaxCosArg);
  164.     x := cos(x)
  165.     RETURN sqrt(1.0 - x * x) / x
  166. END tan;
  167.  
  168.  
  169. PROCEDURE arcsin* (x: REAL): REAL;
  170.  
  171.  
  172.     PROCEDURE arctan (x: REAL): REAL;
  173.     VAR
  174.         z, p, k: REAL;
  175.  
  176.     BEGIN
  177.         p := x / (x * x + 1.0);
  178.         z := p * x;
  179.         x := 0.0;
  180.         k := 0.0;
  181.  
  182.         REPEAT
  183.             k := k + 2.0;
  184.             x := x + p;
  185.             p := p * k * z / (k + 1.0)
  186.         UNTIL p < eps
  187.  
  188.         RETURN x
  189.     END arctan;
  190.  
  191.  
  192. BEGIN
  193.     ASSERT(ABS(x) <= 1.0);
  194.  
  195.     IF ABS(x) >= 0.707 THEN
  196.         x := 0.5 * pi - arctan(sqrt(1.0 - x * x) / x)
  197.     ELSE
  198.         x := arctan(x / sqrt(1.0 - x * x))
  199.     END
  200.  
  201.     RETURN x
  202. END arcsin;
  203.  
  204.  
  205. PROCEDURE arccos* (x: REAL): REAL;
  206. BEGIN
  207.     ASSERT(ABS(x) <= 1.0)
  208.     RETURN 0.5 * pi - arcsin(x)
  209. END arccos;
  210.  
  211.  
  212. PROCEDURE arctan* (x: REAL): REAL;
  213.     RETURN arcsin(x / sqrt(1.0 + x * x))
  214. END arctan;
  215.  
  216.  
  217. PROCEDURE sinh* (x: REAL): REAL;
  218. BEGIN
  219.     x := exp(x)
  220.     RETURN (x - 1.0 / x) * 0.5
  221. END sinh;
  222.  
  223.  
  224. PROCEDURE cosh* (x: REAL): REAL;
  225. BEGIN
  226.     x := exp(x)
  227.     RETURN (x + 1.0 / x) * 0.5
  228. END cosh;
  229.  
  230.  
  231. PROCEDURE tanh* (x: REAL): REAL;
  232. BEGIN
  233.     IF x > 15.0 THEN
  234.         x := 1.0
  235.     ELSIF x < -15.0 THEN
  236.         x := -1.0
  237.     ELSE
  238.         x := exp(2.0 * x);
  239.         x := (x - 1.0) / (x + 1.0)
  240.     END
  241.  
  242.     RETURN x
  243. END tanh;
  244.  
  245.  
  246. PROCEDURE arsinh* (x: REAL): REAL;
  247.     RETURN ln(x + sqrt(x * x + 1.0))
  248. END arsinh;
  249.  
  250.  
  251. PROCEDURE arcosh* (x: REAL): REAL;
  252. BEGIN
  253.     ASSERT(x >= 1.0)
  254.     RETURN ln(x + sqrt(x * x - 1.0))
  255. END arcosh;
  256.  
  257.  
  258. PROCEDURE artanh* (x: REAL): REAL;
  259. BEGIN
  260.     ASSERT(ABS(x) < 1.0)
  261.     RETURN 0.5 * ln((1.0 + x) / (1.0 - x))
  262. END artanh;
  263.  
  264.  
  265. PROCEDURE sgn* (x: REAL): INTEGER;
  266. VAR
  267.     res: INTEGER;
  268.  
  269. BEGIN
  270.     IF x > 0.0 THEN
  271.         res := 1
  272.     ELSIF x < 0.0 THEN
  273.         res := -1
  274.     ELSE
  275.         res := 0
  276.     END
  277.  
  278.     RETURN res
  279. END sgn;
  280.  
  281.  
  282. PROCEDURE fact* (n: INTEGER): REAL;
  283. VAR
  284.     res: REAL;
  285.  
  286. BEGIN
  287.     res := 1.0;
  288.     WHILE n > 1 DO
  289.         res := res * FLT(n);
  290.         DEC(n)
  291.     END
  292.  
  293.     RETURN res
  294. END fact;
  295.  
  296.  
  297. PROCEDURE init;
  298. VAR
  299.     i: INTEGER;
  300.  
  301. BEGIN
  302.     Exp[0] := 1.0;
  303.     FOR i := 1 TO LEN(Exp) - 1 DO
  304.         Exp[i] := Exp[i - 1] * e
  305.     END
  306. END init;
  307.  
  308.  
  309. BEGIN
  310.     init
  311. END Math.