balancer_maths_rust/pools/gyro/
signed_fixed_point.rs

1use alloy_primitives::{uint, I256};
2
3pub const ONE: I256 = I256::from_raw(uint!(1000000000000000000_U256)); // 1e18
4pub const ONE_E_19: I256 = I256::from_raw(uint!(10000000000000000000_U256)); // 1e19
5pub const ONE_XP: I256 = I256::from_raw(uint!(100000000000000000000000000000000000000_U256)); // 1e38
6
7#[derive(Debug)]
8pub struct FixedPointError(pub &'static str);
9
10pub fn mul_down_mag(a: &I256, b: &I256) -> I256 {
11    (*a * *b) / ONE
12}
13
14pub fn mul_up_mag(a: &I256, b: &I256) -> I256 {
15    let product = *a * *b;
16    if product > I256::ZERO {
17        (product - I256::ONE) / ONE + I256::ONE
18    } else if product < I256::ZERO {
19        (product + I256::ONE) / ONE - I256::ONE
20    } else {
21        I256::ZERO
22    }
23}
24
25pub fn div_down_mag(a: &I256, b: &I256) -> I256 {
26    if b.is_zero() {
27        panic!("ZeroDivision");
28    }
29    if a.is_zero() {
30        return I256::ZERO;
31    }
32    let a_inflated = *a * ONE;
33    a_inflated / *b
34}
35
36pub fn div_up_mag(a: &I256, b: &I256) -> I256 {
37    if b.is_zero() {
38        panic!("ZeroDivision");
39    }
40    if a.is_zero() {
41        return I256::ZERO;
42    }
43    let mut local_a = *a;
44    let mut local_b = *b;
45    if b < &I256::ZERO {
46        local_b = -local_b;
47        local_a = -local_a;
48    }
49    let a_inflated = local_a * ONE;
50    if a_inflated > I256::ZERO {
51        (a_inflated - I256::ONE) / local_b + I256::ONE
52    } else {
53        (a_inflated + I256::ONE) / local_b - I256::ONE
54    }
55}
56
57// Signed versions of XP functions
58pub fn mul_xp_u(a: &I256, b: &I256) -> I256 {
59    (*a * *b) / ONE_XP
60}
61
62pub fn div_xp_u(a: &I256, b: &I256) -> I256 {
63    if b.is_zero() {
64        panic!("ZeroDivision");
65    }
66    (*a * ONE_XP) / *b
67}
68
69pub fn mul_down_xp_to_np(a: &I256, b: &I256) -> I256 {
70    let b1 = *b / ONE_E_19;
71    let b2 = *b % ONE_E_19;
72    let prod1 = *a * b1;
73    let prod2 = *a * b2;
74
75    if prod1 >= I256::ZERO && prod2 >= I256::ZERO {
76        let prod2_div_e19 = prod2 / ONE_E_19;
77        (prod1 + prod2_div_e19) / ONE_E_19
78    } else {
79        let prod2_div_e19 = prod2 / ONE_E_19;
80        (prod1 + prod2_div_e19 + I256::ONE) / ONE_E_19 - I256::ONE
81    }
82}
83
84pub fn mul_up_xp_to_np(a: &I256, b: &I256) -> I256 {
85    let b1 = *b / ONE_E_19;
86    let b2 = *b % ONE_E_19;
87    let prod1 = *a * b1;
88    let prod2 = *a * b2;
89
90    if prod1 <= I256::ZERO && prod2 <= I256::ZERO {
91        let prod2_div_e19 = prod2 / ONE_E_19;
92        (prod1 + prod2_div_e19) / ONE_E_19
93    } else {
94        let prod2_div_e19 = prod2 / ONE_E_19;
95        (prod1 + prod2_div_e19 - I256::ONE) / ONE_E_19 + I256::ONE
96    }
97}