Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
7983 leency 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.