1use std::str::FromStr;
2use std::{convert::TryFrom, ops::Neg};
3
4use cosmwasm_std::{Decimal256, StdError, Uint128, Uint256};
5use primitive_types::U256;
6use schemars::JsonSchema;
7
8#[allow(clippy::upper_case_acronyms)]
9#[derive(Copy, Clone, Default, Debug, Eq, JsonSchema)]
10pub struct FPDecimal {
11 #[schemars(with = "String")]
12 pub num: U256,
13 pub sign: i8,
14}
15
16impl From<u128> for FPDecimal {
17 fn from(x: u128) -> FPDecimal {
18 FPDecimal {
19 num: U256::from_little_endian(&x.to_le_bytes()) * FPDecimal::ONE.num,
20 sign: 1,
21 }
22 }
23}
24
25impl From<i128> for FPDecimal {
26 fn from(x: i128) -> FPDecimal {
27 let mut sign = 1;
28 if x < 0 {
29 sign = 0;
30 }
31
32 let abs_x: u128 = x.unsigned_abs();
33 FPDecimal {
34 num: U256::from_little_endian(&abs_x.to_le_bytes()) * FPDecimal::ONE.num,
35 sign,
36 }
37 }
38}
39
40impl From<FPDecimal> for u128 {
41 fn from(x: FPDecimal) -> u128 {
42 let num: U256 = x.int().num / FPDecimal::ONE.num;
43 if num.bits() > 128 {
44 panic!("overflow");
45 }
46
47 let mut array: [u8; 32] = [0; 32];
48 num.to_little_endian(&mut array);
49
50 let mut arr2: [u8; 16] = Default::default();
51 arr2.copy_from_slice(&array[0..16]);
52 u128::from_le_bytes(arr2)
53 }
54}
55
56impl From<U256> for FPDecimal {
57 fn from(x: U256) -> FPDecimal {
58 FPDecimal { num: x, sign: 1 }
59 }
60}
61
62impl From<FPDecimal> for Uint128 {
63 fn from(x: FPDecimal) -> Uint128 {
64 let number: u128 = x.into();
65 number.into()
66 }
67}
68
69impl From<Uint128> for FPDecimal {
70 fn from(x: Uint128) -> FPDecimal {
71 FPDecimal::from_str(&x.to_string()).unwrap()
72 }
73}
74
75impl From<Uint256> for FPDecimal {
76 fn from(x: Uint256) -> FPDecimal {
77 FPDecimal::from_str(&x.to_string()).unwrap()
78 }
79}
80
81impl From<Decimal256> for FPDecimal {
83 fn from(value: Decimal256) -> FPDecimal {
84 let atomics = value.atomics().to_be_bytes();
85 FPDecimal {
86 num: atomics.into(),
87 sign: 1,
88 }
89 }
90}
91
92impl TryFrom<FPDecimal> for Decimal256 {
94 type Error = StdError;
95
96 fn try_from(fp_decimal: FPDecimal) -> Result<Self, Self::Error> {
97 if fp_decimal.is_negative() {
98 return Err(StdError::generic_err(format!("Value {} must be >= {}", fp_decimal.num, 0)));
99 }
100
101 let fp_decimal_num_uint256 = fp_decimal.to_u256();
102
103 Ok(Decimal256::new(fp_decimal_num_uint256))
104 }
105}
106
107impl Neg for FPDecimal {
108 type Output = FPDecimal;
109 fn neg(mut self) -> Self::Output {
110 if self.is_zero() {
111 return self;
112 }
113 match self.sign {
114 0 => {
115 self.sign = 1;
116 }
117 _ => {
118 self.sign = 0;
119 }
120 }
121 self
122 }
123}
124
125impl FPDecimal {
127 pub const MAX: FPDecimal = FPDecimal { num: U256::MAX, sign: 1 };
128 pub const MIN: FPDecimal = FPDecimal { num: U256::MAX, sign: 0 };
129 pub const DIGITS: usize = 18;
130 pub const NEGATIVE_ONE: FPDecimal = FPDecimal {
131 num: U256([1_000_000_000_000_000_000, 0, 0, 0]),
132 sign: 0,
133 };
134 pub const ZERO: FPDecimal = FPDecimal {
135 num: U256([0, 0, 0, 0]),
136 sign: 1,
137 };
138
139 pub const LN2: FPDecimal = FPDecimal {
140 num: U256([693_147_180_559_945_309, 0, 0, 0]),
141 sign: 1,
142 };
143
144 pub const ONE: FPDecimal = FPDecimal {
145 num: U256([1_000_000_000_000_000_000, 0, 0, 0]),
146 sign: 1,
147 };
148
149 pub const TWO: FPDecimal = FPDecimal {
150 num: U256([2_000_000_000_000_000_000, 0, 0, 0]),
151 sign: 1,
152 };
153
154 pub const THREE: FPDecimal = FPDecimal {
155 num: U256([3_000_000_000_000_000_000, 0, 0, 0]),
156 sign: 1,
157 };
158
159 pub const FOUR: FPDecimal = FPDecimal {
160 num: U256([4_000_000_000_000_000_000, 0, 0, 0]),
161 sign: 1,
162 };
163
164 pub const FIVE: FPDecimal = FPDecimal {
165 num: U256([5_000_000_000_000_000_000, 0, 0, 0]),
166 sign: 1,
167 };
168 pub const SIX: FPDecimal = FPDecimal {
169 num: U256([6_000_000_000_000_000_000, 0, 0, 0]),
170 sign: 1,
171 };
172 pub const SEVEN: FPDecimal = FPDecimal {
173 num: U256([7_000_000_000_000_000_000, 0, 0, 0]),
174 sign: 1,
175 };
176 pub const EIGHT: FPDecimal = FPDecimal {
177 num: U256([8_000_000_000_000_000_000, 0, 0, 0]),
178 sign: 1,
179 };
180 pub const NINE: FPDecimal = FPDecimal {
181 num: U256([9_000_000_000_000_000_000, 0, 0, 0]),
182 sign: 1,
183 };
184 pub const TEN: FPDecimal = FPDecimal {
185 num: U256([10_000_000_000_000_000_000, 0, 0, 0]),
186 sign: 1,
187 };
188
189 pub const ELEVEN: FPDecimal = FPDecimal {
190 num: U256([11_000_000_000_000_000_000, 0, 0, 0]),
191 sign: 1,
192 };
193
194 pub const SMALLEST_PRECISION: FPDecimal = FPDecimal {
195 num: U256([1, 0, 0, 0]),
196 sign: 1,
197 };
198
199 pub const MUL_PRECISION: FPDecimal = FPDecimal {
200 num: U256([1_000_000_000, 0, 0, 0]),
201 sign: 1,
202 };
203
204 pub const E: FPDecimal = FPDecimal {
205 num: U256([2_718_281_828_459_045_235, 0, 0, 0]),
207 sign: 1,
208 };
209
210 pub const E_10: FPDecimal = FPDecimal {
211 num: U256([1_053_370_797_511_854_089u64, 1194u64, 0, 0]),
212 sign: 1,
213 }; pub const LN_1_5: FPDecimal = FPDecimal {
216 num: U256([405_465_108_108_164_382, 0, 0, 0]),
219 sign: 1,
220 }; pub const LN_2: FPDecimal = FPDecimal {
223 num: U256([693_147_180_559_945_309, 0, 0, 0]),
225 sign: 1,
226 }; pub const LN_10: FPDecimal = FPDecimal {
229 num: U256([2_302_585_092_994_045_684, 0, 0, 0]),
230 sign: 1,
231 }; pub const LOG2_10: FPDecimal = FPDecimal {
234 num: U256([3_321_928_094_887_362_347, 0, 0, 0]),
236 sign: 1,
237 }; pub const LOG2_E: FPDecimal = FPDecimal {
240 num: U256([1_442_695_040_888_963_330, 0, 0, 0]),
242 sign: 1,
243 }; pub const LOG10_2: FPDecimal = FPDecimal {
246 num: U256([301_029_995_663_981_195, 0, 0, 0]),
248 sign: 1,
249 };
250
251 pub const LOG10_E: FPDecimal = FPDecimal {
252 num: U256([301_029_995_663_981_195, 0, 0, 0]),
254 sign: 1,
255 };
256
257 pub const PI: FPDecimal = FPDecimal {
258 num: U256([3_141_592_653_589_793_115, 0, 0, 0]),
259 sign: 1,
260 };
261
262 pub const FRAC_1_PI: FPDecimal = FPDecimal {
263 num: U256([318_309_886_183_790_683, 0, 0, 0]),
265 sign: 1,
266 };
267
268 pub const FRAC_1_SQRT_2: FPDecimal = FPDecimal {
269 num: U256([707_106_781_186_547_524, 0, 0, 0]),
271 sign: 1,
272 };
273
274 pub const FRAC_2_PI: FPDecimal = FPDecimal {
275 num: U256([636_619_772_367_581_368, 0, 0, 0]),
277 sign: 1,
278 };
279
280 pub const FRAC_2_SQRT_PI: FPDecimal = FPDecimal {
281 num: U256([1_128_379_167_095_512_595, 0, 0, 0]),
283 sign: 1,
284 };
285
286 pub const FRAC_PI_2: FPDecimal = FPDecimal {
287 num: U256([1_570_796_326_794_896_558, 0, 0, 0]),
289 sign: 1,
290 };
291
292 pub const FRAC_PI_3: FPDecimal = FPDecimal {
293 num: U256([1_047_197_551_196_597_705, 0, 0, 0]),
295 sign: 1,
296 };
297
298 pub const FRAC_PI_4: FPDecimal = FPDecimal {
299 num: U256([785_398_163_397_448_279, 0, 0, 0]),
301 sign: 1,
302 };
303
304 pub const FRAC_PI_6: FPDecimal = FPDecimal {
305 num: U256([523_598_775_598_298_852, 0, 0, 0]),
307 sign: 1,
308 };
309
310 pub const FRAC_PI_8: FPDecimal = FPDecimal {
311 num: U256([392_699_081_698_724_139, 0, 0, 0]),
313 sign: 1,
314 };
315
316 pub const SQRT_2: FPDecimal = FPDecimal {
317 num: U256([1_414_213_562_373_095_048, 0, 0, 0]),
319 sign: 1,
320 };
321
322 pub const TAU: FPDecimal = FPDecimal {
323 num: U256([6_283_185_307_179_586_232, 0, 0, 0]),
326 sign: 1,
327 };
328
329 pub fn is_zero(&self) -> bool {
330 self.num.is_zero()
331 }
332
333 pub fn is_negative(&self) -> bool {
334 if self.num == FPDecimal::ZERO.num {
336 return false;
337 }
338
339 self.sign == 0
340 }
341
342 pub fn _int(x: FPDecimal) -> Self {
343 let x1 = x.num;
344 let x1_1 = x1 / FPDecimal::ONE.num;
345 let x_final = x1_1 * FPDecimal::ONE.num;
346 FPDecimal { num: x_final, sign: x.sign }
347 }
348
349 pub fn int(&self) -> Self {
350 FPDecimal::_int(*self)
351 }
352 pub fn is_int(&self) -> bool {
353 *self == self.int()
354 }
355
356 pub fn _fraction(x: FPDecimal) -> Self {
357 let x1 = x.num;
358 FPDecimal {
359 num: x1 - FPDecimal::_int(x).num,
360 sign: x.sign,
361 }
362 }
363
364 pub fn fraction(&self) -> Self {
365 FPDecimal::_fraction(*self)
366 }
367
368 pub fn into_uint256_ceil(self) -> Uint256 {
369 let uint256 = self.to_u256();
370 uint256.checked_add(1u64.into()).unwrap() }
372
373 pub fn into_uint256_floor(self) -> Uint256 {
374 self.to_u256()
375 }
376
377 pub fn to_u256(&self) -> Uint256 {
378 let mut bytes = [0u8; 32];
379 self.num.to_big_endian(&mut bytes);
380 Uint256::from_be_bytes(bytes)
381 }
382}
383
384mod arithmetic;
385mod comparison;
386pub mod display;
387pub mod error;
388mod exp;
389mod factorial;
390mod from_str;
391mod hyper;
392mod log;
393pub mod scale;
394mod serde;
395mod trigonometry;
396
397#[cfg(test)]
398mod tests {
399 use std::{convert::TryFrom, str::FromStr};
400
401 use crate::fp_decimal::U256;
402 use crate::FPDecimal;
403 use cosmwasm_std::{Decimal256, Uint256};
404
405 #[test]
406 fn test_const_pi() {
407 let pi = FPDecimal::PI;
408 let three_point_two = FPDecimal::must_from_str("3.2");
409 let three_point_one = FPDecimal::must_from_str("3.1");
410 let pi_precise = FPDecimal::must_from_str("3.141592653589793115");
411 assert!(three_point_one < pi);
412 assert!(pi < three_point_two);
413 assert_eq!(pi, pi_precise);
414 }
415
416 #[test]
417 fn test_const_ln2() {
418 let ln2 = FPDecimal::LN2;
419 let ln2_precise = FPDecimal::must_from_str("0.693147180559945309");
420 assert_eq!(ln2, ln2_precise);
421 }
422
423 #[test]
424 fn test_neg_sign() {
425 let lhs = FPDecimal::ZERO - FPDecimal::ONE;
426 let rhs = -FPDecimal::ONE;
427 assert_eq!(lhs, rhs);
428 }
429
430 #[test]
431 fn test_neg_zero() {
432 let lhs = FPDecimal::ZERO;
433 let rhs = -FPDecimal::ZERO;
434 assert_eq!(lhs, rhs);
435 }
436
437 #[test]
438 fn test_is_int() {
439 assert!(FPDecimal::TWO.is_int());
440 }
441
442 #[test]
443 fn test_is_not_int() {
444 assert!(!FPDecimal::must_from_str("2.1").is_int());
445 assert_eq!(FPDecimal::must_from_str("2.1") % FPDecimal::ONE, FPDecimal::must_from_str("0.1"));
446 }
447
448 #[test]
449 fn test_to_u256() {
450 let fp_decimal = FPDecimal {
451 num: U256::from(12345u64),
452 sign: 1, };
454
455 let uint256 = fp_decimal.to_u256();
456 assert_eq!(uint256, Uint256::from(12345u64));
457 }
458
459 #[test]
460 fn into_uint256_floor() {
461 let fp_decimal = FPDecimal {
462 num: U256::from_dec_str("12345").unwrap(),
463 sign: 1,
464 };
465
466 let uint256 = fp_decimal.into_uint256_floor();
467 assert_eq!(uint256, Uint256::from(12345u64));
468 }
469
470 #[test]
471 fn into_uint256_ceil() {
472 let fp_decimal = FPDecimal {
473 num: U256::from_dec_str("12345").unwrap(),
474 sign: 1,
475 };
476
477 let uint256 = fp_decimal.into_uint256_ceil();
478 assert_eq!(uint256, Uint256::from(12346u64));
479 }
480
481 #[test]
482 fn dec256_to_fpdecimal_conversion() {
483 let decimal_value = Decimal256::from_str("1.234").unwrap(); let fp_decimal: FPDecimal = decimal_value.into();
488
489 let expected_fp_decimal = FPDecimal::must_from_str("1.234");
492
493 assert_eq!(fp_decimal.num, expected_fp_decimal.num);
495 assert_eq!(fp_decimal.sign, expected_fp_decimal.sign);
496 }
497
498 #[test]
499 fn fpdecimal_to_dec256() {
500 let fp_decimal_valid = FPDecimal::must_from_str("1.2345");
502 let decimal_valid = Decimal256::try_from(fp_decimal_valid).unwrap();
503 assert_eq!(decimal_valid.to_string(), fp_decimal_valid.to_string());
504
505 let fp_decimal_zero = FPDecimal::ZERO;
507 let decimal_zero = Decimal256::try_from(fp_decimal_zero).unwrap();
508 assert_eq!(decimal_zero.to_string(), "0");
509
510 let fp_decimal_negative = FPDecimal::must_from_str("-1.2345");
512 assert!(Decimal256::try_from(fp_decimal_negative).is_err());
513 }
514}