2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 private unit private.math;
21 fn math_modulo(t : type, implicit cls : class_real_number(t), x y : t) : t;
22 fn math_power(t : type, implicit cls : class_real_number(t), x y : t) : t;
23 fn math_ldexp(t : type, implicit cls : class_real_number(t), x y : t) : t;
24 fn math_atan2(t : type, implicit cls : class_real_number(t), x y : t) : t;
25 fn math_pi(t : type, implicit cls : class_real_number(t)) : t;
26 fn math_sqrt(t : type, implicit cls : class_real_number(t), x : t) : t;
27 fn math_cbrt(t : type, implicit cls : class_real_number(t), x : t) : t;
28 fn math_sin(t : type, implicit cls : class_real_number(t), x : t) : t;
29 fn math_cos(t : type, implicit cls : class_real_number(t), x : t) : t;
30 fn math_tan(t : type, implicit cls : class_real_number(t), x : t) : t;
31 fn math_asin(t : type, implicit cls : class_real_number(t), x : t) : t;
32 fn math_acos(t : type, implicit cls : class_real_number(t), x : t) : t;
33 fn math_atan(t : type, implicit cls : class_real_number(t), x : t) : t;
34 fn math_sinh(t : type, implicit cls : class_real_number(t), x : t) : t;
35 fn math_cosh(t : type, implicit cls : class_real_number(t), x : t) : t;
36 fn math_tanh(t : type, implicit cls : class_real_number(t), x : t) : t;
37 fn math_asinh(t : type, implicit cls : class_real_number(t), x : t) : t;
38 fn math_acosh(t : type, implicit cls : class_real_number(t), x : t) : t;
39 fn math_atanh(t : type, implicit cls : class_real_number(t), x : t) : t;
40 fn math_exp2(t : type, implicit cls : class_real_number(t), x : t) : t;
41 fn math_exp(t : type, implicit cls : class_real_number(t), x : t) : t;
42 fn math_exp10(t : type, implicit cls : class_real_number(t), x : t) : t;
43 fn math_log2(t : type, implicit cls : class_real_number(t), x : t) : t;
44 fn math_log(t : type, implicit cls : class_real_number(t), x : t) : t;
45 fn math_log10(t : type, implicit cls : class_real_number(t), x : t) : t;
46 fn math_round(t : type, implicit cls : class_real_number(t), x : t) : t;
47 fn math_ceil(t : type, implicit cls : class_real_number(t), x : t) : t;
48 fn math_floor(t : type, implicit cls : class_real_number(t), x : t) : t;
49 fn math_trunc(t : type, implicit cls : class_real_number(t), x : t) : t;
50 fn math_fract(t : type, implicit cls : class_real_number(t), x : t) : t;
51 fn math_mantissa(t : type, implicit cls : class_real_number(t), x : t) : t;
52 fn math_exponent(t : type, implicit cls : class_real_number(t), x : t) : t;
58 fn math_modulo(t : type, implicit cls : class_real_number(t), x y : t) : t
60 if is_infinity x or y = 0 then
64 //var t := math_trunc(x / y);
81 if is_infinity yy then
89 fn math_power(t : type, implicit cls : class_real_number(t), x y : t) : t
98 if math_fract(y) <> 0 then [
100 return select(y < 0, 1.0/0.0, 0);
108 if is_exception yi then [
110 if is_infinity y then
113 m := math_modulo(y, 2);
117 return select(is_negative x, 0.0, -0.0);
119 return select(is_negative x, 1.0/0.0, -1.0/0.0);
130 return math_exp(math_log(x) * y);
133 // warning: this logic is duplicated in floating_ldexp
134 fn math_ldexp(t : type, implicit cls : class_real_number(t), x y : t) : t
138 if not is_exception yi, y = yi then [
139 if is_infinity x then
141 var q : t := 1 shl abs(yi);
142 if is_infinity q then [
145 x := math_ldexp(x, y1);
146 x := math_ldexp(x, y2);
155 return x * math_exp2(y);
158 fn math_atan2(t : type, implicit cls : class_real_number(t), x y : t) : t
160 if x = 0, y = 0 then [
161 y := select(is_negative y, 1, -1);
163 if is_infinity x, is_infinity y then [
168 if is_negative x = is_negative y then
169 return math_pi(t, cls) / 2;
171 return -math_pi(t, cls) / 2;
174 if not is_negative x then
175 return math_pi(t, cls) + math_atan(x / y);
177 return -math_pi(t, cls) + math_atan(x / y);
179 return math_atan(x / y);
182 fn math_pi(t : type, implicit cls : class_real_number(t)) : t
184 //return math_atan(cls.one) * 4;
189 var den0 := ipower(16, k);
190 var den1 := q + 2 * k;
191 var den2 := 2 + 4 * k;
192 var den3 := 5 + 8 * k;
193 var den4 := 6 + 8 * k;
195 var diff := ((cls.one / den1) - (cls.one / den2) - (cls.one / den3) - (cls.one / den4)) / den0;
196 //eval debug("k=" + ntos(k) + ",sum:" + ntos(sum) + ",diff=" + ntos(diff));
198 if sum = old_sum then
205 fn math_sqrt(t : type, implicit cls : class_real_number(t), x : t) : t
212 if is_infinity x then
217 guess -= (guess - x / guess) / 2;
224 fn math_cbrt(t : type, implicit cls : class_real_number(t), x : t) : t
228 if is_infinity x then
233 guess -= (guess - x / (guess * guess)) * (cls.one / 3);
240 fn math_sin(t : type, implicit cls : class_real_number(t), x : t) : t
249 var pi := math_pi(t, cls);
250 x := math_modulo(x, pi * 2);
255 if x >= pi / 2 then [
265 var diff := xp / fact;
267 fact *= (k + 1) * (k + 2);
270 if sum = old_sum then
278 fn math_cos(t : type, implicit cls : class_real_number(t), x : t) : t
280 return math_sin(x + math_pi(t, cls) / 2);
283 fn math_tan(t : type, implicit cls : class_real_number(t), x : t) : t
285 return math_sin(x) / math_cos(x);
288 fn math_asin(t : type, implicit cls : class_real_number(t), x : t) : t
290 if x = -1 or x = 1 then
291 return math_pi(t, cls) / 2 * x;
292 return math_atan(x / math_sqrt(cls.one - x * x));
295 fn math_acos(t : type, implicit cls : class_real_number(t), x : t) : t
297 return math_pi(t, cls) / 2 - math_asin(x);
300 fn math_atan(t : type, implicit cls : class_real_number(t), x : t) : t
309 if is_infinity x then
310 return math_pi(t, cls) / 2 * m;
313 var limit : t := 0.2;
315 a := math_atan(limit);
318 x := (x - limit) / (x * limit + 1);
331 if old_sum = sum then
336 return (a * f + sum) * m;
339 fn math_sinh(t : type, implicit cls : class_real_number(t), x : t) : t
341 return (math_exp(x) - math_exp(-x)) / 2;
344 fn math_cosh(t : type, implicit cls : class_real_number(t), x : t) : t
346 return (math_exp(x) + math_exp(-x)) / 2;
349 fn math_tanh(t : type, implicit cls : class_real_number(t), x : t) : t
351 var val1 := math_exp(x) - math_exp(-x);
352 var val2 := math_exp(x) + math_exp(-x);
353 if is_infinity val1, is_infinity val2 then
358 fn math_asinh(t : type, implicit cls : class_real_number(t), x : t) : t
360 if is_infinity x then
362 return math_log(x + math_sqrt(x * x + 1));
365 fn math_acosh(t : type, implicit cls : class_real_number(t), x : t) : t
367 return math_log(x + math_sqrt(x * x - 1));
370 fn math_atanh(t : type, implicit cls : class_real_number(t), x : t) : t
372 return math_log((cls.one + x) / (cls.one - x)) / 2;
375 fn math_exp2(t : type, implicit cls : class_real_number(t), x : t) : t
378 return math_exp(x * math_log(c2));
381 fn math_exp(t : type, implicit cls : class_real_number(t), x : t) : t
384 if is_infinity x then [
404 var diff := xp / fact;
409 if old_sum = sum then
420 return cls.recip(sum);
423 fn math_exp10(t : type, implicit cls : class_real_number(t), x : t) : t
426 return math_exp(x * math_log(c2));
429 fn math_log2(t : type, implicit cls : class_real_number(t), x : t) : t
432 return math_log(x) / math_log(c2);
435 fn math_log(t : type, implicit cls : class_real_number(t), x : t) : t
443 if is_infinity x then
447 while x <= 0.5 or x >= 2 do [
454 var a := (x - 1) / (x + 1);
462 if old_sum = sum then
469 fn math_log10(t : type, implicit cls : class_real_number(t), x : t) : t
472 return math_log(x) / math_log(c10);
475 fn math_round(t : type, implicit cls : class_real_number(t), x : t) : t
478 if is_exception i then
480 if abs(math_fract(x)) = 0.5 then [
481 if i bt 0 = is_negative x then
482 return i - (i and 1);
487 var fl := math_floor(xx);
488 if fl = 0, is_negative(x) then
493 fn math_ceil(t : type, implicit cls : class_real_number(t), x : t) : t
496 if is_exception i then
500 if i = 0, is_negative(x) then
505 fn math_floor(t : type, implicit cls : class_real_number(t), x : t) : t
508 if is_exception i then
512 if i = 0, is_negative(x) then
517 fn math_trunc(t : type, implicit cls : class_real_number(t), x : t) : t
520 if is_exception i then
522 if i = 0, is_negative(x) then
527 fn math_fract(t : type, implicit cls : class_real_number(t), x : t) : t
530 if is_exception i then
531 return select(is_negative x, 0.0, -0.0);
533 if r = 0, is_negative(x) then
538 fn math_mantissa(t : type, implicit cls : class_real_number(t), x : t) : t
540 if is_infinity x then
558 fn math_exponent(t : type, implicit cls : class_real_number(t), x : t) : t
560 if is_infinity x then