balancer_maths_rust/common/
maths.rs1use crate::common::constants::{FOUR_WAD, MAX_POW_RELATIVE_ERROR, TWO_WAD, WAD};
4use crate::common::errors::PoolError;
5use crate::common::log_exp_math;
6use alloy_primitives::U256;
7
8pub fn mul_up_fixed(a: &U256, b: &U256) -> Result<U256, PoolError> {
10 let product = a * b;
11 if product.is_zero() {
12 return Ok(U256::ZERO);
13 }
14 let result = (product - U256::ONE) / WAD + U256::ONE;
15 Ok(result)
16}
17
18pub fn div_up_fixed(a: &U256, b: &U256) -> Result<U256, PoolError> {
20 if a.is_zero() {
21 return Ok(U256::ZERO);
22 }
23 if b.is_zero() {
24 return Err(PoolError::MathOverflow);
25 }
26
27 let a_inflated = a * WAD;
28 let result = (a_inflated - U256::ONE) / b + U256::ONE;
29 Ok(result)
30}
31
32pub fn mul_down_fixed(a: &U256, b: &U256) -> Result<U256, PoolError> {
34 let product = a * b;
35 let result = product / WAD;
36 Ok(result)
37}
38
39pub fn div_down_fixed(a: &U256, b: &U256) -> Result<U256, PoolError> {
41 if a.is_zero() {
42 return Ok(U256::ZERO);
43 }
44 if b.is_zero() {
45 return Err(PoolError::MathOverflow);
46 }
47
48 let a_inflated = a * WAD;
49 let result = a_inflated / b;
50 Ok(result)
51}
52
53pub fn div_up(a: &U256, b: &U256) -> Result<U256, PoolError> {
55 if b.is_zero() {
56 return Ok(U256::ZERO);
57 }
58 let result = U256::ONE + (a - U256::ONE) / b;
59 Ok(result)
60}
61
62pub fn mul_div_up_fixed(a: &U256, b: &U256, c: &U256) -> Result<U256, PoolError> {
64 let product = a * b;
65 let result = (product - U256::ONE) / c + U256::ONE;
66 Ok(result)
67}
68
69pub fn pow_down_fixed(base: &U256, exponent: &U256) -> Result<U256, PoolError> {
71 pow_down_fixed_with_version(base, exponent, 0)
72}
73
74pub fn pow_down_fixed_with_version(
76 base: &U256,
77 exponent: &U256,
78 version: u32,
79) -> Result<U256, PoolError> {
80 if *exponent == WAD && version != 1 {
81 return Ok(*base);
82 }
83 if *exponent == TWO_WAD && version != 1 {
84 return mul_up_fixed(base, base);
85 }
86 if *exponent == FOUR_WAD && version != 1 {
87 let square = mul_up_fixed(base, base)?;
88 return mul_up_fixed(&square, &square);
89 }
90
91 let raw = log_exp_math::pow(base, exponent)?;
92 let max_error = mul_up_fixed(&raw, &MAX_POW_RELATIVE_ERROR)? + U256::ONE;
93
94 if raw < max_error {
95 return Ok(U256::ZERO);
96 }
97
98 Ok(raw - max_error)
99}
100
101pub fn pow_up_fixed(base: &U256, exponent: &U256) -> Result<U256, PoolError> {
103 pow_up_fixed_with_version(base, exponent, 0)
104}
105
106pub fn pow_up_fixed_with_version(
108 base: &U256,
109 exponent: &U256,
110 version: u32,
111) -> Result<U256, PoolError> {
112 if *exponent == WAD && version != 1 {
113 return Ok(*base);
114 }
115 if *exponent == TWO_WAD && version != 1 {
116 return mul_up_fixed(base, base);
117 }
118 if *exponent == FOUR_WAD && version != 1 {
119 let square = mul_up_fixed(base, base)?;
120 return mul_up_fixed(&square, &square);
121 }
122
123 let raw = log_exp_math::pow(base, exponent)?;
124 let max_error = mul_up_fixed(&raw, &MAX_POW_RELATIVE_ERROR)? + U256::ONE;
125
126 Ok(raw + max_error)
127}
128
129pub fn complement_fixed(x: &U256) -> Result<U256, PoolError> {
131 if *x < WAD {
132 Ok(WAD - x)
133 } else {
134 Ok(U256::ZERO)
135 }
136}