1use std::ops::Shr;
2
3use ethers::types::{I256, U256};
4use eyre::{bail, Result};
5
6use crate::{int256, uint256};
7
8pub fn u256_from_str(s: &str) -> Result<U256> {
21 let mut found_dot = false;
24 let mut found_e = false;
25 let mut mantissa = ethers::types::U256::zero();
26 let mut exponent = ethers::types::U256::zero();
27 let mut decimals = 0;
28
29 for digit in s.chars() {
30 if digit.is_ascii_digit() {
31 let d = digit.to_digit(10).unwrap();
32 if !found_e {
33 mantissa = mantissa * 10 + d;
34 } else {
35 exponent = exponent * 10 + d;
36 }
37 if found_dot && !found_e {
38 decimals += 1;
39 }
40 } else if digit == 'e' && !found_e {
41 found_e = true;
42 } else if digit == '.' && !found_dot {
43 found_dot = true;
44 } else if digit != '_' {
45 bail!("Unexpected character in U256: {digit}");
46 }
47 }
48
49 let decimals = ethers::types::U256::from(decimals);
53 if exponent < decimals {
54 bail!("Exponent {exponent} is too small for U256: {s}");
55 }
56
57 Ok(mantissa * ethers::types::U256::from(10).pow(exponent - decimals))
58}
59
60pub fn i256_from_str(s: &str) -> Result<I256> {
73 let mut sign = ethers::types::I256::one();
76 let mut found_dot = false;
77 let mut found_e = false;
78 let mut mantissa = ethers::types::I256::zero();
79 let mut exponent = 0;
80 let mut decimals = 0;
81
82 for digit in s.chars() {
83 if digit.is_ascii_digit() {
84 let d = digit.to_digit(10).unwrap();
85 if !found_e {
86 mantissa = mantissa * 10 + d;
87 } else {
88 exponent = exponent * 10 + d;
89 }
90 if found_dot && !found_e {
91 decimals += 1;
92 }
93 } else if digit == '-' {
94 sign = -ethers::types::I256::one();
95 } else if digit == 'e' && !found_e {
96 found_e = true;
97 } else if digit == '.' && !found_dot {
98 found_dot = true;
99 } else if digit != '_' {
100 bail!("Unexpected character in I256: {digit}");
101 }
102 }
103
104 if exponent < decimals {
108 bail!("Exponent {exponent} is too small for I256: {s}");
109 }
110
111 Ok(sign * mantissa * ethers::types::I256::from(10).pow(exponent - decimals))
112}
113
114pub fn exp(mut x: I256) -> Result<I256> {
117 if x <= I256::from(-42139678854452767551_i128) {
120 return Ok(I256::zero());
121 }
122
123 if x >= int256!(135305999368893231589) {
126 bail!("invalid exponent {x}");
127 }
128
129 x = x.wrapping_shl(78) / int256!(5).pow(18);
133
134 let k = ((x.wrapping_shl(96) / int256!(54916777467707473351141471128))
138 .wrapping_add(int256!(2).pow(95)))
139 .asr(96);
140 x = x.wrapping_sub(k.wrapping_mul(54916777467707473351141471128_u128.into()));
141
142 let mut y = x.wrapping_add(1346386616545796478920950773328_u128.into());
147 y = y
148 .wrapping_mul(x)
149 .asr(96)
150 .wrapping_add(57155421227552351082224309758442_u128.into());
151 let mut p = y
152 .wrapping_add(x)
153 .wrapping_sub(94201549194550492254356042504812_u128.into());
154 p = p
155 .wrapping_mul(y)
156 .asr(96)
157 .wrapping_add(28719021644029726153956944680412240_u128.into());
158 p = p
159 .wrapping_mul(x)
160 .wrapping_add(int256!(4385272521454847904659076985693276).wrapping_shl(96));
161
162 let mut q = x.wrapping_sub(2855989394907223263936484059900_u128.into());
165 q = q
166 .wrapping_mul(x)
167 .asr(96)
168 .wrapping_add(50020603652535783019961831881945_u128.into());
169 q = q
170 .wrapping_mul(x)
171 .asr(96)
172 .wrapping_sub(533845033583426703283633433725380_u128.into());
173 q = q
174 .wrapping_mul(x)
175 .asr(96)
176 .wrapping_add(3604857256930695427073651918091429_u128.into());
177 q = q
178 .wrapping_mul(x)
179 .asr(96)
180 .wrapping_sub(14423608567350463180887372962807573_u128.into());
181 q = q
182 .wrapping_mul(x)
183 .asr(96)
184 .wrapping_add(26449188498355588339934803723976023_u128.into());
185
186 let mut r = p.wrapping_div(q);
187
188 r = I256::from_raw(
197 (r.into_raw()
198 .overflowing_mul(uint256!(3822833074963236453042738258902158003155416615667))
199 .0)
200 .shr(int256!(195).wrapping_sub(k).low_usize()),
201 );
202
203 Ok(r)
204}
205
206pub fn ln(mut x: I256) -> Result<I256> {
207 if x <= I256::zero() {
208 bail!("Cannot calculate ln of of negative number or zero.");
209 }
210
211 let mut r = I256::from((x > I256::from(0xffffffffffffffffffffffffffffffff_u128)) as u128)
217 .wrapping_shl(7);
218 r = r | I256::from((x.asr(r.as_usize()) > I256::from(0xffffffffffffffff_u128)) as u128)
219 .wrapping_shl(6);
220 r = r | I256::from((x.asr(r.as_usize()) > I256::from(0xffffffff_u128)) as u128).wrapping_shl(5);
221 r = r | I256::from((x.asr(r.as_usize()) > I256::from(0xffff_u128)) as u128).wrapping_shl(4);
222 r = r | I256::from((x.asr(r.as_usize()) > I256::from(0xff_u128)) as u128).wrapping_shl(3);
223 r = r | I256::from((x.asr(r.as_usize()) > I256::from(0xf_u128)) as u128).wrapping_shl(2);
224 r = r | I256::from((x.asr(r.as_usize()) > I256::from(0x3_u128)) as u128).wrapping_shl(1);
225 r = r | I256::from((x.asr(r.as_usize()) > I256::from(0x1_u128)) as u128);
226
227 let k = r.wrapping_sub(int256!(96));
229 x = x.wrapping_shl(int256!(159).wrapping_sub(k).as_usize());
230 x = I256::from_raw(x.into_raw().shr(159));
231
232 let mut p = x.wrapping_add(int256!(3273285459638523848632254066296));
235 p = ((p.wrapping_mul(x)).asr(96)).wrapping_add(int256!(24828157081833163892658089445524));
236 p = ((p.wrapping_mul(x)).asr(96)).wrapping_add(int256!(43456485725739037958740375743393));
237 p = ((p.wrapping_mul(x)).asr(96)).wrapping_sub(int256!(11111509109440967052023855526967));
238 p = ((p.wrapping_mul(x)).asr(96)).wrapping_sub(int256!(45023709667254063763336534515857));
239 p = ((p.wrapping_mul(x)).asr(96)).wrapping_sub(int256!(14706773417378608786704636184526));
240 p = p
241 .wrapping_mul(x)
242 .wrapping_sub(int256!(795164235651350426258249787498).wrapping_shl(96));
243
244 let mut q = x.wrapping_add(int256!(5573035233440673466300451813936));
247 q = (q.wrapping_mul(x).asr(96)).wrapping_add(int256!(71694874799317883764090561454958));
248 q = q
249 .wrapping_mul(x)
250 .asr(96)
251 .wrapping_add(int256!(283447036172924575727196451306956));
252 q = q
253 .wrapping_mul(x)
254 .asr(96)
255 .wrapping_add(int256!(401686690394027663651624208769553));
256 q = q
257 .wrapping_mul(x)
258 .asr(96)
259 .wrapping_add(int256!(204048457590392012362485061816622));
260 q = q
261 .wrapping_mul(x)
262 .asr(96)
263 .wrapping_add(int256!(31853899698501571402653359427138));
264 q = q
265 .wrapping_mul(x)
266 .asr(96)
267 .wrapping_add(int256!(909429971244387300277376558375));
268
269 r = p.wrapping_div(q);
270
271 r = r.wrapping_mul(int256!(1677202110996718588342820967067443963516166));
281 r = r.wrapping_add(
283 int256!(16597577552685614221487285958193947469193820559219878177908093499208371)
284 .wrapping_mul(k),
285 );
286 r = r.wrapping_add(int256!(
288 600920179829731861736702779321621459595472258049074101567377883020018308
289 ));
290 r = r.asr(174);
292
293 Ok(r)
294}
295
296#[cfg(test)]
297mod tests {
298 use ethers::signers::Signer;
299 use hyperdrive_wrappers::wrappers::mock_fixed_point_math::MockFixedPointMath;
300 use rand::{thread_rng, Rng};
301 use test_utils::{chain::Chain, constants::DEPLOYER};
302
303 use super::*;
304 use crate::{fixed, uint256, FixedPoint};
305
306 #[tokio::test]
307 async fn fuzz_exp_narrow() -> Result<()> {
308 let chain = Chain::connect(None, None).await?;
309 chain.deal(DEPLOYER.address(), uint256!(100_000e18)).await?;
310 let client = chain.client(DEPLOYER.clone()).await?;
311 let mock_fixed_point_math = MockFixedPointMath::deploy(client, ())?.send().await?;
312
313 let mut rng = thread_rng();
315 for _ in 0..10_000 {
316 let x: FixedPoint<I256> = rng.gen_range(fixed!(0)..=fixed!(1e18));
317 let actual = ln(x.raw());
318 match mock_fixed_point_math.ln(x.raw()).call().await {
319 Ok(expected) => assert_eq!(actual.unwrap(), expected),
320 Err(_) => assert!(actual.is_err()),
321 }
322 }
323
324 Ok(())
325 }
326
327 #[tokio::test]
328 async fn fuzz_exp() -> Result<()> {
329 let chain = Chain::connect(None, None).await?;
330 chain.deal(DEPLOYER.address(), uint256!(100_000e18)).await?;
331 let client = chain.client(DEPLOYER.clone()).await?;
332 let mock_fixed_point_math = MockFixedPointMath::deploy(client, ())?.send().await?;
333
334 let mut rng = thread_rng();
336 for _ in 0..10_000 {
337 let x: FixedPoint<I256> = rng.gen_range(fixed!(0)..FixedPoint::<I256>::MAX);
338 let actual = exp(x.raw());
339 match mock_fixed_point_math.exp(x.raw()).call().await {
340 Ok(expected) => assert_eq!(actual.unwrap(), expected),
341 Err(_) => assert!(actual.is_err()),
342 }
343 }
344
345 Ok(())
346 }
347
348 #[tokio::test]
349 async fn fuzz_ln_narrow() -> Result<()> {
350 let chain = Chain::connect(None, None).await?;
351 chain.deal(DEPLOYER.address(), uint256!(100_000e18)).await?;
352 let client = chain.client(DEPLOYER.clone()).await?;
353 let mock_fixed_point_math = MockFixedPointMath::deploy(client, ())?.send().await?;
354
355 let mut rng = thread_rng();
357 for _ in 0..10_000 {
358 let x: FixedPoint<I256> = rng.gen_range(fixed!(0)..=fixed!(1e18));
359 let actual = ln(x.raw());
360 match mock_fixed_point_math.ln(x.raw()).call().await {
361 Ok(expected) => assert_eq!(actual.unwrap(), expected),
362 Err(_) => assert!(actual.is_err()),
363 }
364 }
365
366 Ok(())
367 }
368
369 #[tokio::test]
370 async fn fuzz_ln() -> Result<()> {
371 let chain = Chain::connect(None, None).await?;
372 chain.deal(DEPLOYER.address(), uint256!(100_000e18)).await?;
373 let client = chain.client(DEPLOYER.clone()).await?;
374 let mock_fixed_point_math = MockFixedPointMath::deploy(client, ())?.send().await?;
375
376 let mut rng = thread_rng();
378 for _ in 0..10_000 {
379 let x: FixedPoint<I256> = rng.gen_range(fixed!(0)..FixedPoint::<I256>::MAX);
380 let actual = ln(x.raw());
381 match mock_fixed_point_math.ln(x.raw()).call().await {
382 Ok(expected) => assert_eq!(actual.unwrap(), expected),
383 Err(_) => assert!(actual.is_err()),
384 }
385 }
386
387 Ok(())
388 }
389}