1use anchor_lang::{AnchorDeserialize, AnchorSerialize};
2use spl_math::{
3 precise_number::{self, *},
4 uint::U256,
5};
6use std::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign};
7
8#[derive(Default, Clone, Debug, Copy, PartialEq, Eq, AnchorSerialize, AnchorDeserialize)]
10pub struct Number([u64; 4]);
11
12impl core::fmt::Display for Number {
13 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
14 let n = U256(self.0);
15 write!(f, "{}", n)
16 }
17}
18
19impl From<u64> for Number {
20 fn from(value: u64) -> Self {
21 let pn = PreciseNumber::new(value.into()).unwrap();
22 Number(pn.value.0)
23 }
24}
25
26impl From<u128> for Number {
27 fn from(value: u128) -> Self {
28 let pn = PreciseNumber::new(value).unwrap();
29 Number(pn.value.0)
30 }
31}
32
33impl Number {
35 pub const SIZEOF: usize = 32;
37
38 pub const ZERO: Self = Self(U256::zero().0);
39
40 pub const ONE: Self = Self([precise_number::ONE as u64, 0, 0, 0]);
42
43 pub const DENOM: u128 = precise_number::ONE;
44
45 pub fn from_bytes_le(slice: &[u8]) -> Self {
46 Self(U256::from_little_endian(slice).0)
47 }
48
49 pub fn from_natural_u64(value: u64) -> Self {
50 value.into()
51 }
52
53 pub fn from_ratio(num: u128, den: u128) -> Self {
54 let num = PreciseNumber::new(num).unwrap();
55 let den = PreciseNumber::new(den).unwrap();
56
57 PreciseNumber::checked_div(&num, &den)
58 .unwrap_or(PreciseNumber::new(0).unwrap())
59 .into()
60 }
61
62 pub fn from_bps(bps: u16) -> Self {
64 Self::from_natural_u64(bps as u64) / Self::from_natural_u64(10_000)
65 }
66
67 pub fn checked_add(&self, x: &Self) -> Option<Self> {
68 self.to_pn()
69 .checked_add(&x.to_pn())
70 .map(|pn| Self(pn.value.0))
71 }
72
73 pub fn checked_sub(&self, x: &Self) -> Option<Self> {
74 self.to_pn()
75 .checked_sub(&x.to_pn())
76 .map(|pn| Self(pn.value.0))
77 }
78
79 pub fn checked_mul(&self, x: &Self) -> Option<Self> {
80 self.to_pn()
81 .checked_mul(&x.to_pn())
82 .map(|pn| Self(pn.value.0))
83 }
84
85 pub fn checked_div(&self, x: &Self) -> Option<Self> {
86 self.to_pn()
87 .checked_div(&x.to_pn())
88 .map(|pn| Self(pn.value.0))
89 }
90
91 pub fn to_pn(&self) -> PreciseNumber {
92 PreciseNumber {
93 value: U256(self.0),
94 }
95 }
96
97 pub fn min(numbers: &[Self]) -> Self {
98 *numbers.iter().min().unwrap()
99 }
100
101 pub fn floor_u64(&self) -> u64 {
102 self.to_pn()
103 .floor()
104 .unwrap()
105 .to_imprecise()
106 .unwrap()
107 .try_into()
108 .unwrap()
109 }
110
111 pub fn ceil(&self) -> u128 {
112 self.to_pn().ceiling().unwrap().to_imprecise().unwrap()
113 }
114
115 pub fn ceil_u64(&self) -> u64 {
116 self.ceil().try_into().unwrap()
117 }
118
119 pub fn floor_u128(&self) -> u128 {
120 self.to_pn().floor().unwrap().to_imprecise().unwrap()
121 }
122
123 pub fn to_f64(&self) -> Option<f64> {
124 let n = self
126 .checked_mul(&Number::from(Self::DENOM))
127 .unwrap()
128 .to_pn()
129 .to_imprecise()
130 .unwrap();
131 let d = precise_number::ONE;
133 u128_to_f64_checked(n, d)
134 }
135}
136
137fn u128_to_f64_checked(numerator: u128, denominator: u128) -> Option<f64> {
139 const MAX_EXACT_U64: u128 = (1u128 << 53) - 1;
141
142 const U64_MAX_PLUS_ONE: f64 = 18446744073709551616.0;
144 if denominator == 0 {
145 return None; }
147
148 let num_high = (numerator >> 64) as u64;
150 let num_low = numerator as u64;
151
152 let denom_high = (denominator >> 64) as u64;
153 let denom_low = denominator as u64;
154
155 if numerator > MAX_EXACT_U64 || denominator > MAX_EXACT_U64 {
157 return None; }
159
160 let num_f64 = (num_high as f64) * U64_MAX_PLUS_ONE + num_low as f64;
162 let denom_f64 = (denom_high as f64) * U64_MAX_PLUS_ONE + denom_low as f64;
163
164 Some(num_f64 / denom_f64)
166}
167
168impl From<PreciseNumber> for Number {
169 fn from(pn: PreciseNumber) -> Self {
170 Self(pn.value.0)
171 }
172}
173
174impl Add<Number> for Number {
175 type Output = Self;
176
177 fn add(self, rhs: Number) -> Self::Output {
178 Self(self.to_pn().checked_add(&rhs.to_pn()).unwrap().value.0)
179 }
180}
181
182impl Mul<Number> for Number {
183 type Output = Self;
184
185 fn mul(self, x: Number) -> Self::Output {
186 Self(self.checked_mul(&x).unwrap().0)
187 }
188}
189
190impl Div<Number> for Number {
191 type Output = Self;
192
193 fn div(self, x: Number) -> Self {
194 Self(self.checked_div(&x).unwrap().0)
195 }
196}
197
198impl AddAssign<Number> for Number {
199 fn add_assign(&mut self, rhs: Number) {
200 self.0 = self.checked_add(&rhs).unwrap().0;
201 }
202}
203
204impl SubAssign<Number> for Number {
205 fn sub_assign(&mut self, rhs: Number) {
206 self.0 = self.checked_sub(&rhs).unwrap().0;
207 }
208}
209
210impl Sub<Number> for Number {
211 type Output = Self;
212
213 fn sub(self, x: Number) -> Self {
214 self.checked_sub(&x).unwrap()
215 }
216}
217
218impl PartialOrd for Number {
219 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
220 Some(self.cmp(other))
221 }
222}
223
224impl Ord for Number {
225 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
226 U256(self.0).cmp(&U256(other.0))
227 }
228}
229
230#[cfg(test)]
231mod test {
232 use super::*;
233
234 #[test]
235 fn test_to_f64() {
236 let n = Number::from_ratio(1, 2);
237 assert_eq!(n.to_f64(), Some(0.5));
238
239 let n = Number::from_ratio(123456789, 1_000_000_000);
240 assert_eq!(n.to_f64(), Some(0.123456789));
241
242 let n = Number::from_ratio(0, 1_000_000_000);
243 assert_eq!(n.to_f64(), Some(0.0));
244
245 let n = Number::from_ratio(1_000_000_000, 1_000_000_000);
246 assert_eq!(n.to_f64(), Some(1.0));
247
248 let n = Number::from_ratio(1_000_000_000_000, 1_000_000_000);
249 assert_eq!(n.to_f64(), Some(1000.0));
250
251 let n = Number::from_ratio(123456789123, 100_000_000_000);
252 assert_eq!(n.to_f64(), Some(1.23456789123));
253 }
254
255 #[test]
256 fn test_serialization() {
257 let n = Number([ONE as u64, 0, 0, 0]);
258 assert_eq!(n.floor_u64(), 1);
259
260 let n = Number::from_natural_u64(1_000_000_000);
261 let w0 = n.0[0] as u128;
262 let w1 = n.0[1] as u128;
263 let target: u128 = 1_000_000_000 * ONE;
264 assert_eq!(w0 + (w1 << 64), target);
265 }
266
267 #[test]
268 fn test_add() {
269 let num1 = Number::from(100u64);
270 let num2 = Number::from(200u64);
271 let ans = Number::from(300u64);
272 let num3 = num1 + num2;
273 assert_eq!(num3, ans);
274 }
275
276 #[test]
277 fn test_sub() {
278 let num1 = Number::from(100u64);
279 let num2 = Number::from(200u64);
280 let ans = Number::from(100u64);
281 let num3 = num2 - num1;
282 assert_eq!(num3, ans);
283 }
284
285 #[test]
286 fn test_mul() {
287 let num1 = Number::from(100u64);
288 let num2 = Number::from(200u64);
289 let ans = Number::from(20000u64);
290 let num3 = num1 * num2;
291 assert_eq!(num3, ans);
292 }
293
294 #[test]
295 fn test_div() {
296 let num1 = Number::from(100u64);
297 let num2 = Number::from(20u64);
298 let ans = Number::from(5u64);
299 let num3 = num1 / num2;
300 assert_eq!(num3, ans);
301 }
302
303 #[test]
304 fn test_add_assign() {
305 let mut num1 = Number::from(100u64);
306 let num2 = Number::from(200u64);
307 let ans = Number::from(300u64);
308 num1 += num2;
309 assert_eq!(num1, ans);
310 }
311
312 #[test]
313 fn test_sub_assign() {
314 let mut num1 = Number::from(300u64);
315 let num2 = Number::from(200u64);
316 let ans = Number::from(100u64);
317 num1 -= num2;
318 assert_eq!(num1, ans);
319 }
320
321 #[test]
322 fn test_min() {
323 let numbers = [
324 Number::from(300u64),
325 Number::from(100u64),
326 Number::from(200u64),
327 Number::from(400u64),
328 ];
329 let min_value = Number::min(&numbers);
330 assert_eq!(min_value, Number::from(100u64));
331 }
332
333 #[test]
334 fn test_from_ratio() {
335 let num1 = Number::from_ratio(1, 2);
336 assert!(num1 > Number::from(0u64));
337 assert!(num1 < Number::from(1u64));
338 }
339
340 #[test]
341 fn test_mul_div() {
342 let e = Number::from_ratio(22346643, 234216);
344
345 let a = Number::from_natural_u64(100);
346
347 let e_a = e * a;
348
349 let e_i = Number::ONE / e;
350
351 assert_eq!(a / e_a, e_i);
352 }
353
354 #[test]
355 fn test_floor_u64() {
356 let e = Number::from_ratio(10, 11);
357 assert_eq!(e.floor_u64(), 0);
358
359 let e = Number::from_ratio(11, 10);
360 assert_eq!(e.floor_u64(), 1);
361 }
362
363 #[test]
364 fn test_floor_u128() {
365 assert_eq!(Number::from_ratio(19, 10).floor_u128(), 1);
366 assert_eq!(Number::from_ratio(21, 10).floor_u128(), 2);
367 assert_eq!(Number::from_ratio(29, 10).floor_u128(), 2);
368 assert_eq!(Number::from_ratio(20, 10).floor_u128(), 2);
369 assert_eq!(Number::from_ratio(300, 100).floor_u128(), 3);
370 assert_eq!(Number::from_ratio(299, 10).floor_u128(), 29);
371 assert_eq!(Number::from_ratio(9, 10).floor_u128(), 0);
372 }
373}