1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
pub mod nth_root;

pub use nth_root::{nth_inv_root, nth_root};

use cfx_types::U256;
use num::integer::Roots;

pub fn sqrt_u256(input: U256) -> U256 {
    let bits = input.bits();
    if bits <= 64 {
        return input.as_u64().sqrt().into();
    }

    /************************************************************
    * Step 1: pick the most significant 64 bits and estimate an
    * approximate root.
    ===========================================================*/
    let significant_bits = 64 - bits % 2;
    // The `rest_bits` must be even number.
    let rest_bits = bits - significant_bits;
    // The `input >> rest_bits` has `significant_bits`
    let significant_word = (input >> rest_bits).as_u64();
    // The `init_root` is slightly larger than the correct root.
    let init_root =
        U256::from(significant_word.sqrt() + 1u64) << (rest_bits / 2);

    /*=================================================================
    * Step 2: use the Newton's method to estimate the accurate value.
    =================================================================*/
    let mut root = init_root;
    // Will iterate for at most 4 rounds.
    while root * root > input {
        root = (input / root + root) / 2;
    }

    root
}

pub fn power_two_fractional(ratio: u64, increase: bool, precision: u8) -> U256 {
    assert!(precision <= 127);

    let mut base = U256::one();
    base <<= 254usize;

    for i in 0..64u64 {
        if ratio & (1 << i) != 0 {
            if increase {
                base <<= 1usize;
            } else {
                base >>= 1usize;
            }
        }
        base = sqrt_u256(base);
        base <<= 127usize;
    }

    base >>= (254 - precision) as usize;
    // Computing error < 5.2 * 2 ^ -127
    base
}