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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::fp_decimal::{FPDecimal, U256};
impl FPDecimal {
#[allow(clippy::many_single_char_names)]
pub fn _ln(a: FPDecimal) -> FPDecimal {
assert!(a.sign != 0);
assert!(a != FPDecimal::zero());
let mut v = a.num;
let mut r = FPDecimal::zero();
while v <= FPDecimal::ONE.num / U256([10, 0, 0, 0]) {
v = v * U256([10, 0, 0, 0]);
r -= FPDecimal::LN_10;
}
while v >= U256([10, 0, 0, 0]) * FPDecimal::ONE.num {
v = v / U256([10, 0, 0, 0]);
r += FPDecimal::LN_10;
}
while v < FPDecimal::ONE.num {
v = FPDecimal::_mul(FPDecimal { num: v, sign: 1 }, FPDecimal::E).num;
r -= FPDecimal::ONE;
}
while v > FPDecimal::E.num {
v = FPDecimal::_div(FPDecimal { num: v, sign: 1 }, FPDecimal::E).num;
r += FPDecimal::ONE;
}
if v == FPDecimal::ONE.num {
return r;
}
if v == FPDecimal::E.num {
return r + FPDecimal::ONE;
}
let frac_1_5_fpdec = FPDecimal {
num: U256([3, 0, 0, 0]) * FPDecimal::ONE.num / U256([2, 0, 0, 0]),
sign: 1,
};
let v = FPDecimal { num: v, sign: 1 } - frac_1_5_fpdec;
r += FPDecimal::LN_1_5;
let mut m = FPDecimal::ONE * v
/ (v + FPDecimal {
num: U256([3, 0, 0, 0]) * FPDecimal::ONE.num,
sign: 1,
});
r += FPDecimal {
num: U256([2, 0, 0, 0]) * FPDecimal::ONE.num,
sign: 1,
} * m;
let m2 = m * m / FPDecimal::ONE;
let mut i: u64 = 3;
loop {
m = m * m2 / FPDecimal::ONE;
let fpdec_i = FPDecimal {
num: U256([i, 0, 0, 0]) * FPDecimal::ONE.num,
sign: 1,
};
r += FPDecimal {
num: U256([2, 0, 0, 0]) * FPDecimal::ONE.num,
sign: 1,
} * m
/ fpdec_i;
i += 2;
if i >= 3 + 2 * FPDecimal::DIGITS as u64 {
break;
}
}
r
}
pub fn ln(&self) -> FPDecimal {
FPDecimal::_ln(*self)
}
}
#[cfg(test)]
mod tests {
use crate::FPDecimal;
use bigint::U256;
#[test]
fn test_ln_sanity() {
let half = FPDecimal::one().div(2i128);
println!("{}", FPDecimal::_ln(half)); let num = FPDecimal::one().mul(5).div(4);
println!("{}", FPDecimal::_pow(num, half));
}
#[test]
fn test_ln() {
assert_eq!(FPDecimal::_ln(FPDecimal::E), FPDecimal::ONE);
}
#[test]
fn test_ln10() {
assert_eq!(
FPDecimal::_ln(FPDecimal {
num: U256([10, 0, 0, 0]) * FPDecimal::ONE.num,
sign: 1
}),
FPDecimal::LN_10
);
}
#[test]
fn test_ln1_5() {
let three = FPDecimal {
num: U256([3, 0, 0, 0]) * FPDecimal::ONE.num,
sign: 1,
};
let two = FPDecimal {
num: U256([2, 0, 0, 0]) * FPDecimal::ONE.num,
sign: 1,
};
let one_point_five = FPDecimal::_div(three, two);
assert_eq!(FPDecimal::_ln(one_point_five), FPDecimal::LN_1_5);
}
}