fastnum/decimal/dec/math/
asin.rs1use 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; }
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}