balancer_maths_rust/common/
log_exp_math.rs1use crate::common::constants::WAD;
4use crate::common::errors::PoolError;
5use lazy_static::lazy_static;
6use num_bigint::BigInt;
7use num_traits::{One, Signed, Zero};
8use std::str::FromStr;
9
10lazy_static! {
11 static ref MAX_NATURAL_EXPONENT: BigInt = BigInt::from(130000000000000000000i128);
13 static ref MIN_NATURAL_EXPONENT: BigInt = BigInt::from(-41000000000000000000i128);
14 static ref LN_36_LOWER_BOUND: BigInt = BigInt::from(900000000000000000i128);
15 static ref LN_36_UPPER_BOUND: BigInt = BigInt::from(1100000000000000000i128);
16 static ref MILD_EXPONENT_BOUND: BigInt = BigInt::from_str("289480223093290488558927462521719769633174961664101410098").unwrap();
18
19 static ref RAY: BigInt = BigInt::from_str("1000000000000000000000000000000000000").unwrap();
21
22 static ref X0: BigInt = BigInt::from(128000000000000000000i128); static ref A0: BigInt = BigInt::from_str("38877084059945950922200000000000000000000000000000000000").unwrap(); static ref X1: BigInt = BigInt::from(64000000000000000000i128); static ref A1: BigInt = BigInt::from(6235149080811616882910000000i128); static ref X2: BigInt = BigInt::from(3200000000000000000000i128); static ref A2: BigInt = BigInt::from_str("7896296018268069516100000000000000").unwrap(); static ref X3: BigInt = BigInt::from(1600000000000000000000i128); static ref A3: BigInt = BigInt::from_str("888611052050787263676000000").unwrap(); static ref X4: BigInt = BigInt::from(800000000000000000000i128); static ref A4: BigInt = BigInt::from_str("298095798704172827474000").unwrap(); static ref X5: BigInt = BigInt::from(400000000000000000000i128); static ref A5: BigInt = BigInt::from_str("5459815003314423907810").unwrap(); static ref X6: BigInt = BigInt::from(200000000000000000000i128); static ref A6: BigInt = BigInt::from_str("738905609893065022723").unwrap(); static ref X7: BigInt = BigInt::from(100000000000000000000i128); static ref A7: BigInt = BigInt::from_str("271828182845904523536").unwrap(); static ref X8: BigInt = BigInt::from(50000000000000000000i128); static ref A8: BigInt = BigInt::from_str("164872127070012814685").unwrap(); static ref X9: BigInt = BigInt::from(25000000000000000000i128); static ref A9: BigInt = BigInt::from_str("128402541668774148407").unwrap(); static ref X10: BigInt = BigInt::from(12500000000000000000i128); static ref A10: BigInt = BigInt::from_str("113314845306682631683").unwrap(); static ref X11: BigInt = BigInt::from(6250000000000000000i128); static ref A11: BigInt = BigInt::from_str("106449445891785942956").unwrap(); static ref HUNDRED_WAD: BigInt = BigInt::from(100000000000000000000i128);
51}
52
53pub fn pow(x: &BigInt, y: &BigInt) -> Result<BigInt, PoolError> {
55 if y.is_zero() {
56 return Ok(WAD.clone());
58 }
59
60 if x.is_zero() {
61 return Ok(BigInt::zero());
62 }
63
64 if x >= &BigInt::from_str(
66 "57896044618658097711785492504343953926634992332820282019728792003956564819968",
67 )
68 .unwrap()
69 {
70 return Err(PoolError::MathOverflow);
71 }
72 let x_int256 = x.clone();
73
74 if y >= &*MILD_EXPONENT_BOUND {
76 return Err(PoolError::MathOverflow);
77 }
78 let y_int256 = y.clone();
79
80 let logx_times_y = if x_int256 > *LN_36_LOWER_BOUND && x_int256 < *LN_36_UPPER_BOUND {
81 let ln_36_x = ln_36(&x_int256)?;
82 (ln_36_x.clone() / &*WAD) * &y_int256 + ((ln_36_x.clone() % &*WAD) * &y_int256) / &*WAD
87 } else {
88 ln(&x_int256)? * &y_int256
89 };
90
91 let logx_times_y = logx_times_y / &*WAD;
92
93 if logx_times_y < *MIN_NATURAL_EXPONENT || logx_times_y > *MAX_NATURAL_EXPONENT {
95 return Err(PoolError::MathOverflow);
96 }
97
98 exp(&logx_times_y)
99}
100
101fn exp(x: &BigInt) -> Result<BigInt, PoolError> {
103 if x < &MIN_NATURAL_EXPONENT || x > &MAX_NATURAL_EXPONENT {
104 return Err(PoolError::MathOverflow);
105 }
106
107 if x.is_negative() {
108 return Ok((&*WAD * &*WAD) / exp(&(-x))?);
112 }
113
114 let mut x = x.clone();
115 let first_an = if x >= *X0 {
116 x -= &*X0;
117 A0.clone()
118 } else if x >= *X1 {
119 x -= &*X1;
120 A1.clone()
121 } else {
122 BigInt::one()
123 };
124
125 x *= BigInt::from(100);
128
129 let mut product = HUNDRED_WAD.clone();
132
133 if x >= *X2 {
134 x -= &*X2;
135 product = (product * &*A2) / &*HUNDRED_WAD;
136 }
137 if x >= *X3 {
138 x -= &*X3;
139 product = (product * &*A3) / &*HUNDRED_WAD;
140 }
141 if x >= *X4 {
142 x -= &*X4;
143 product = (product * &*A4) / &*HUNDRED_WAD;
144 }
145 if x >= *X5 {
146 x -= &*X5;
147 product = (product * &*A5) / &*HUNDRED_WAD;
148 }
149 if x >= *X6 {
150 x -= &*X6;
151 product = (product * &*A6) / &*HUNDRED_WAD;
152 }
153 if x >= *X7 {
154 x -= &*X7;
155 product = (product * &*A7) / &*HUNDRED_WAD;
156 }
157 if x >= *X8 {
158 x -= &*X8;
159 product = (product * &*A8) / &*HUNDRED_WAD;
160 }
161 if x >= *X9 {
162 x -= &*X9;
163 product = (product * &*A9) / &*HUNDRED_WAD;
164 }
165
166 let mut series_sum = HUNDRED_WAD.clone(); let mut term = x.clone(); series_sum += &term;
176
177 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(2);
181 series_sum += &term;
182
183 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(3);
184 series_sum += &term;
185
186 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(4);
187 series_sum += &term;
188
189 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(5);
190 series_sum += &term;
191
192 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(6);
193 series_sum += &term;
194
195 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(7);
196 series_sum += &term;
197
198 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(8);
199 series_sum += &term;
200
201 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(9);
202 series_sum += &term;
203
204 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(10);
205 series_sum += &term;
206
207 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(11);
208 series_sum += &term;
209
210 term = (term * &x) / &*HUNDRED_WAD / &BigInt::from(12);
211 series_sum += &term;
212
213 let result = ((product * series_sum) / &*HUNDRED_WAD) * &first_an / BigInt::from(100);
218
219 Ok(result)
220}
221
222fn ln(x: &BigInt) -> Result<BigInt, PoolError> {
224 let mut a = x.clone();
225
226 if a < *WAD {
227 return Ok(-BigInt::one() * ln(&((&*WAD * &*WAD) / &a))?);
231 }
232
233 let mut sum = BigInt::zero();
249 if a >= (&*A0 * &*WAD) {
250 a /= &*A0; sum += &*X0;
252 }
253
254 if a >= (&*A1 * &*WAD) {
255 a /= &*A1; sum += &*X1;
257 }
258
259 sum *= BigInt::from(100);
261 a *= BigInt::from(100);
262
263 if a >= *A2 {
266 a = (&a * &*HUNDRED_WAD) / &*A2;
267 sum += &*X2;
268 }
269
270 if a >= *A3 {
271 a = (&a * &*HUNDRED_WAD) / &*A3;
272 sum += &*X3;
273 }
274
275 if a >= *A4 {
276 a = (&a * &*HUNDRED_WAD) / &*A4;
277 sum += &*X4;
278 }
279
280 if a >= *A5 {
281 a = (&a * &*HUNDRED_WAD) / &*A5;
282 sum += &*X5;
283 }
284
285 if a >= *A6 {
286 a = (&a * &*HUNDRED_WAD) / &*A6;
287 sum += &*X6;
288 }
289
290 if a >= *A7 {
291 a = (&a * &*HUNDRED_WAD) / &*A7;
292 sum += &*X7;
293 }
294
295 if a >= *A8 {
296 a = (&a * &*HUNDRED_WAD) / &*A8;
297 sum += &*X8;
298 }
299
300 if a >= *A9 {
301 a = (&a * &*HUNDRED_WAD) / &*A9;
302 sum += &*X9;
303 }
304
305 if a >= *A10 {
306 a = (&a * &*HUNDRED_WAD) / &*A10;
307 sum += &*X10;
308 }
309
310 if a >= *A11 {
311 a = (&a * &*HUNDRED_WAD) / &*A11;
312 sum += &*X11;
313 }
314
315 let z = ((&a - &*HUNDRED_WAD) * &*HUNDRED_WAD) / (&a + &*HUNDRED_WAD);
323 let z_squared = (&z * &z) / &*HUNDRED_WAD;
324
325 let mut num = z.clone();
327
328 let mut series_sum = num.clone();
330
331 num = (&num * &z_squared) / &*HUNDRED_WAD;
333 series_sum += &num / &BigInt::from(3);
334
335 num = (&num * &z_squared) / &*HUNDRED_WAD;
336 series_sum += &num / &BigInt::from(5);
337
338 num = (&num * &z_squared) / &*HUNDRED_WAD;
339 series_sum += &num / &BigInt::from(7);
340
341 num = (&num * &z_squared) / &*HUNDRED_WAD;
342 series_sum += &num / &BigInt::from(9);
343
344 num = (&num * &z_squared) / &*HUNDRED_WAD;
345 series_sum += &num / &BigInt::from(11);
346
347 series_sum *= BigInt::from(2);
351
352 Ok((sum + series_sum) / BigInt::from(100))
357}
358
359fn ln_36(x: &BigInt) -> Result<BigInt, PoolError> {
361 let mut x = x.clone();
362 x *= &*WAD;
367
368 let z = ((&x - &*RAY) * &*RAY) / (&x + &*RAY);
374 let z_squared = (&z * &z) / &*RAY;
375
376 let mut num = z.clone();
378
379 let mut series_sum = num.clone();
381
382 num = (&num * &z_squared) / &*RAY;
384 series_sum += &num / &BigInt::from(3);
385
386 num = (&num * &z_squared) / &*RAY;
387 series_sum += &num / &BigInt::from(5);
388
389 num = (&num * &z_squared) / &*RAY;
390 series_sum += &num / &BigInt::from(7);
391
392 num = (&num * &z_squared) / &*RAY;
393 series_sum += &num / &BigInt::from(9);
394
395 num = (&num * &z_squared) / &*RAY;
396 series_sum += &num / &BigInt::from(11);
397
398 num = (&num * &z_squared) / &*RAY;
399 series_sum += &num / &BigInt::from(13);
400
401 num = (&num * &z_squared) / &*RAY;
402 series_sum += &num / &BigInt::from(15);
403
404 Ok(series_sum * BigInt::from(2))
408}