defituna_client/math/
full_math.rs1use uint::construct_uint;
6
7construct_uint! {
8 pub struct U128(2);
9}
10
11construct_uint! {
12 pub struct U256(4);
13}
14
15construct_uint! {
16 pub struct U512(8);
17}
18
19pub trait MulDiv<RHS = Self> {
30 type Output;
32
33 fn mul_div_floor(self, num: RHS, denom: RHS) -> Option<Self::Output>;
34 fn mul_div_ceil(self, num: RHS, denom: RHS) -> Option<Self::Output>;
35
36 fn to_underflow_u64(self) -> u64;
38}
39
40pub trait Upcast256 {
41 fn as_u256(self) -> U256;
42}
43impl Upcast256 for U128 {
44 fn as_u256(self) -> U256 {
45 U256([self.0[0], self.0[1], 0, 0])
46 }
47}
48
49pub trait Downcast256 {
50 fn as_u128(self) -> U128;
53}
54impl Downcast256 for U256 {
55 fn as_u128(self) -> U128 {
56 U128([self.0[0], self.0[1]])
57 }
58}
59
60pub trait Upcast512 {
61 fn as_u512(self) -> U512;
62}
63impl Upcast512 for U256 {
64 fn as_u512(self) -> U512 {
65 U512([self.0[0], self.0[1], self.0[2], self.0[3], 0, 0, 0, 0])
66 }
67}
68
69pub trait Downcast512 {
70 fn as_u256(self) -> U256;
73}
74impl Downcast512 for U512 {
75 fn as_u256(self) -> U256 {
76 U256([self.0[0], self.0[1], self.0[2], self.0[3]])
77 }
78}
79
80impl MulDiv for u64 {
81 type Output = u64;
82
83 fn mul_div_floor(self, num: Self, denom: Self) -> Option<Self::Output> {
84 assert_ne!(denom, 0);
85 let r = (U128::from(self) * U128::from(num)) / U128::from(denom);
86 if r > U128::from(u64::MAX) {
87 None
88 } else {
89 Some(r.as_u64())
90 }
91 }
92
93 fn mul_div_ceil(self, num: Self, denom: Self) -> Option<Self::Output> {
94 assert_ne!(denom, 0);
95 let r = (U128::from(self) * U128::from(num) + U128::from(denom - 1)) / U128::from(denom);
96 if r > U128::from(u64::MAX) {
97 None
98 } else {
99 Some(r.as_u64())
100 }
101 }
102
103 fn to_underflow_u64(self) -> u64 {
104 self
105 }
106}
107
108impl MulDiv for U128 {
109 type Output = U128;
110
111 fn mul_div_floor(self, num: Self, denom: Self) -> Option<Self::Output> {
112 assert_ne!(denom, U128::default());
113 let r = ((self.as_u256()) * (num.as_u256())) / (denom.as_u256());
114 if r > U128::MAX.as_u256() {
115 None
116 } else {
117 Some(r.as_u128())
118 }
119 }
120
121 fn mul_div_ceil(self, num: Self, denom: Self) -> Option<Self::Output> {
122 assert_ne!(denom, U128::default());
123 let r = (self.as_u256() * num.as_u256() + (denom - 1).as_u256()) / denom.as_u256();
124 if r > U128::MAX.as_u256() {
125 None
126 } else {
127 Some(r.as_u128())
128 }
129 }
130
131 fn to_underflow_u64(self) -> u64 {
132 if self < U128::from(u64::MAX) {
133 self.as_u64()
134 } else {
135 0
136 }
137 }
138}
139
140impl MulDiv for U256 {
141 type Output = U256;
142
143 fn mul_div_floor(self, num: Self, denom: Self) -> Option<Self::Output> {
144 assert_ne!(denom, U256::default());
145 let r = (self.as_u512() * num.as_u512()) / denom.as_u512();
146 if r > U256::MAX.as_u512() {
147 None
148 } else {
149 Some(r.as_u256())
150 }
151 }
152
153 fn mul_div_ceil(self, num: Self, denom: Self) -> Option<Self::Output> {
154 assert_ne!(denom, U256::default());
155 let r = (self.as_u512() * num.as_u512() + (denom - 1).as_u512()) / denom.as_u512();
156 if r > U256::MAX.as_u512() {
157 None
158 } else {
159 Some(r.as_u256())
160 }
161 }
162
163 fn to_underflow_u64(self) -> u64 {
164 if self < U256::from(u64::MAX) {
165 self.as_u64()
166 } else {
167 0
168 }
169 }
170}