fastnum/decimal/dec/math/
asin.rs

1use core::cmp::Ordering;
2
3use crate::decimal::{
4    dec::{
5        intrinsics::Intrinsics,
6        math::{add::add, consts::Consts, div::div, mul::mul, sqrt::sqrt, sub::sub},
7        parse::from_u32,
8    },
9    Decimal,
10};
11
12type D<const N: usize> = Decimal<N>;
13
14#[inline]
15pub(crate) const fn asin<const N: usize>(x: D<N>) -> D<N> {
16    if x.is_nan() {
17        return x.op_invalid();
18    }
19
20    if x.is_zero() {
21        return D::ZERO.set_ctx(x.context());
22    }
23
24    if x.is_infinite() {
25        return x.signaling_nan();
26    }
27
28    match x.cmp(&D::ONE.neg()) {
29        Ordering::Less => {
30            return x.signaling_nan();
31        }
32        Ordering::Equal => return Consts::FRAC_PI_2.neg(),
33        Ordering::Greater => {}
34    }
35
36    match x.cmp(&D::ONE) {
37        Ordering::Less => {}
38        Ordering::Equal => {
39            return Consts::FRAC_PI_2;
40        }
41        Ordering::Greater => {
42            return x.signaling_nan();
43        }
44    }
45
46    asin_reduction(x).set_ctx(x.context())
47}
48
49struct Reduction<const N: usize>;
50
51impl<const N: usize> Reduction<N> {
52    const K: D<N> = D::HALF; // TODO
53}
54
55#[inline]
56const fn asin_reduction<const N: usize>(x: D<N>) -> D<N> {
57    debug_assert!(x.ge(&D::ONE.neg()));
58    debug_assert!(x.le(&D::ONE));
59
60    if x.abs().gt(&Reduction::K) {
61        let x2 = mul(x, x);
62        let y = div(
63            x,
64            mul(Consts::SQRT_2, sqrt(add(D::ONE, sqrt(sub(D::ONE, x2))))),
65        );
66        mul(D::TWO, asin_reduction(y))
67    } else {
68        taylor_series(x)
69    }
70}
71
72#[inline]
73const fn taylor_series<const N: usize>(x: D<N>) -> D<N> {
74    debug_assert!(x.ge(&D::ONE.neg()));
75    debug_assert!(x.le(&D::ONE));
76
77    let mut result = D::ZERO;
78    let mut result_next;
79    let mut item = x;
80
81    let x2 = mul(x, x);
82
83    let mut i = 2;
84
85    while i < Intrinsics::<N>::SERIES_MAX_ITERATIONS + 2 {
86        result_next = add(result, item);
87
88        if result.eq(&result_next) {
89            break;
90        }
91
92        item = div(
93            mul(mul(item, x2), from_u32((2 * i - 3) * (2 * i - 3))),
94            from_u32((2 * i - 1) * (2 * i - 2)),
95        );
96
97        result = result_next;
98        i += 1;
99    }
100
101    result
102}