fastnum2/decimal/dec/math/
sqrt.rs

1use crate::decimal::{
2    dec::{
3        convert::to_f64,
4        intrinsics::Intrinsics,
5        math::{add::add, div::div, mul::mul},
6        parse::from_f64,
7    },
8    utils::types,
9    Decimal,
10};
11
12type D<const N: usize> = Decimal<N>;
13
14#[inline]
15pub(crate) const fn sqrt<const N: usize>(d: D<N>) -> D<N> {
16    if d.is_nan() {
17        return d.op_invalid();
18    }
19
20    if d.is_infinite() {
21        return d;
22    }
23
24    if d.is_zero() || d.is_one() {
25        return d;
26    }
27
28    if d.is_negative() {
29        return d.signaling_nan();
30    }
31
32    if d.eq(&D::TWO) {
33        return D::SQRT_2;
34    }
35
36    sqrt_heron(d)
37}
38
39#[inline]
40const fn sqrt_heron<const N: usize>(d: D<N>) -> D<N> {
41    let approx_f64 = to_f64(d);
42    let guess = types::f64::sqrt(approx_f64);
43
44    // TODO: from_f64 - optimization point
45    let mut result = from_f64(guess).compound(&d);
46
47    let mut result_next;
48    let mut i = 0;
49
50    while result.is_ok() && i < Intrinsics::<N>::SERIES_MAX_ITERATIONS {
51        result_next = mul(D::HALF, add(result, div(d, result)));
52
53        if result.eq(&result_next) {
54            break;
55        }
56
57        result = result_next;
58        i += 1;
59    }
60
61    result
62}