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
130
131
132
133
134
135
136
137
138
139
140
141
use crate::{
num::BigFloatNumber,
RoundingMode,
defs::{Error, WORD_SIGNIFICANT_BIT, WORD_BIT_SIZE},
common::consts::ONE, Sign,
};
use crate::ops::consts::Consts;
impl BigFloatNumber {
pub fn exp(&self, rm: RoundingMode, cc: &mut Consts) -> Result<Self, Error> {
if self.is_zero() {
return Self::from_word(1, self.get_mantissa_max_bit_len());
}
if self.e as isize > WORD_BIT_SIZE as isize {
return Err(Error::ExponentOverflow(self.get_sign()));
}
let int = self.get_int_as_usize()?;
let e_int = if int > 0 {
let e_const = cc.e(self.get_mantissa_max_bit_len() + 2 + 2*core::mem::size_of::<usize>(), RoundingMode::None)?;
e_const.powi(int, RoundingMode::None)
} else {
ONE.clone()
}?;
let mut fract = self.fract()?;
fract.set_precision(fract.get_mantissa_max_bit_len() + 4, RoundingMode::None)?;
fract.set_sign(Sign::Pos);
let e_fract = fract.expf(RoundingMode::None)?;
let mut ret = e_int.mul(&e_fract, RoundingMode::None)?;
if self.is_negative() {
ret = ret.reciprocal(RoundingMode::None)?;
};
ret.set_precision(self.get_mantissa_max_bit_len(), rm)?;
Ok(ret)
}
pub fn powi(&self, mut i: usize, rm: RoundingMode) -> Result<Self, Error> {
if self.is_zero() || i == 1 {
return self.clone();
}
if i == 0 {
return Self::from_word(1, self.get_mantissa_max_bit_len());
}
let mut bit_pos = WORD_BIT_SIZE;
while bit_pos > 0 {
bit_pos -= 1;
i <<= 1;
if i & WORD_SIGNIFICANT_BIT as usize != 0 {
bit_pos -= 1;
i <<= 1;
break;
}
}
let mut ret = self.clone()?;
while bit_pos > 0 {
bit_pos -= 1;
ret = ret.mul(&ret, rm)?;
if i & WORD_SIGNIFICANT_BIT as usize != 0 {
ret = ret.mul(self, rm)?;
}
i <<= 1;
}
Ok(ret)
}
fn expf(self, rm: RoundingMode) -> Result<Self, Error> {
let sh = self.sinh_series(rm)?; let sq = sh.mul(&sh, rm)?;
let sq2 = sq.add(&ONE, rm)?;
let sq3 = sq2.sqrt(rm)?;
sq3.add(&sh, rm)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_pow() {
let mut cc = Consts::new().unwrap();
let d1 = BigFloatNumber::parse("F.FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2DC85F7E77EC4872DC85F7E77EC487_e-1", crate::Radix::Hex, 320, RoundingMode::None).unwrap();
let d2 = d1.exp(RoundingMode::ToEven, &mut cc).unwrap();
let d3 = BigFloatNumber::parse("2.B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A5496AF9D95160A40F47A2ECF1C6AEA0", crate::Radix::Hex, 320, RoundingMode::None).unwrap();
assert!(d2.cmp(&d3) == 0);
let d1 = BigFloatNumber::parse("1.00000000000000000000000000000000000000000000000000000000000000002DC85F7E77EC487C", crate::Radix::Hex, 320, RoundingMode::None).unwrap();
let d2 = d1.exp(RoundingMode::ToEven, &mut cc).unwrap();
let d3 = BigFloatNumber::parse("2.B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEFAEC1BE22DDEADB48", crate::Radix::Hex, 320, RoundingMode::None).unwrap();
assert!(d2.cmp(&d3) == 0);
}
}