1use core::cmp::Ordering;
2use core::fmt::{self, Write};
3use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
4use core::str::FromStr;
5use serde::{de, ser, Deserialize, Deserializer, Serialize};
6
7use crate::errors::{
8 CheckedFromRatioError, CheckedMultiplyRatioError, DivideByZeroError, ErrorKind, OverflowError,
9 OverflowOperation, RoundUpOverflowError, StdError,
10};
11use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
12use crate::{Decimal, SignedDecimal, SignedDecimal256, __internal::forward_ref_partial_eq};
13
14use super::Fraction;
15use super::Isqrt;
16use super::{Uint256, Uint512};
17
18#[derive(
22 Copy,
23 Clone,
24 Default,
25 PartialEq,
26 Eq,
27 PartialOrd,
28 Ord,
29 schemars::JsonSchema,
30 cw_schema::Schemaifier,
31)]
32#[schemaifier(type = cw_schema::NodeType::Decimal { precision: 256, signed: false })]
33pub struct Decimal256(#[schemars(with = "String")] Uint256);
34
35forward_ref_partial_eq!(Decimal256, Decimal256);
36
37#[derive(Debug, PartialEq, Eq, thiserror::Error)]
38#[error("Decimal256 range exceeded")]
39pub struct Decimal256RangeExceeded;
40
41impl Decimal256 {
42 const DECIMAL_FRACTIONAL: Uint256 = Uint256::new(1_000_000_000_000_000_000);
44 const DECIMAL_FRACTIONAL_SQUARED: Uint256 = Uint256::new(1_000_000_000_000_000_000_000_000_000_000_000_000);
46
47 pub const DECIMAL_PLACES: u32 = 18;
50 pub const MAX: Self = Self(Uint256::MAX);
52 pub const MIN: Self = Self(Uint256::MIN);
54
55 #[inline]
67 #[must_use]
68 pub const fn new(value: Uint256) -> Self {
69 Self(value)
70 }
71
72 #[deprecated(
75 since = "3.0.0",
76 note = "Use Decimal256::new(Uint256::new(value)) instead"
77 )]
78 pub const fn raw(value: u128) -> Self {
79 Self(Uint256::new(value))
80 }
81
82 #[inline]
84 pub const fn one() -> Self {
85 Self(Self::DECIMAL_FRACTIONAL)
86 }
87
88 #[inline]
90 pub const fn zero() -> Self {
91 Self(Uint256::zero())
92 }
93
94 pub const fn percent(x: u64) -> Self {
106 let atomics = (x as u128) * 10_000_000_000_000_000;
108 Self(Uint256::new(atomics))
109 }
110
111 pub const fn permille(x: u64) -> Self {
123 let atomics = (x as u128) * 1_000_000_000_000_000;
125 Self(Uint256::new(atomics))
126 }
127
128 pub const fn bps(x: u64) -> Self {
142 let atomics = (x as u128) * 100_000_000_000_000;
144 Self(Uint256::new(atomics))
145 }
146
147 pub fn from_atomics(
172 atomics: impl Into<Uint256>,
173 decimal_places: u32,
174 ) -> Result<Self, Decimal256RangeExceeded> {
175 let atomics = atomics.into();
176 const TEN: Uint256 = Uint256::from_be_bytes([
177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
178 0, 0, 10,
179 ]);
180 Ok(match decimal_places.cmp(&Self::DECIMAL_PLACES) {
181 Ordering::Less => {
182 let digits = (Self::DECIMAL_PLACES) - decimal_places; let factor = TEN.checked_pow(digits).unwrap(); Self(
185 atomics
186 .checked_mul(factor)
187 .map_err(|_| Decimal256RangeExceeded)?,
188 )
189 }
190 Ordering::Equal => Self(atomics),
191 Ordering::Greater => {
192 let digits = decimal_places - (Self::DECIMAL_PLACES); if atomics.is_zero() || digits > atomics.ilog10() {
194 Self(Uint256::zero())
196 } else {
197 let factor = TEN.checked_pow(digits).unwrap();
199 Self(atomics.checked_div(factor).unwrap()) }
201 }
202 })
203 }
204
205 pub fn from_ratio(numerator: impl Into<Uint256>, denominator: impl Into<Uint256>) -> Self {
207 match Decimal256::checked_from_ratio(numerator, denominator) {
208 Ok(value) => value,
209 Err(CheckedFromRatioError::DivideByZero) => {
210 panic!("Denominator must not be zero")
211 }
212 Err(CheckedFromRatioError::Overflow) => panic!("Multiplication overflow"),
213 }
214 }
215
216 pub fn checked_from_ratio(
218 numerator: impl Into<Uint256>,
219 denominator: impl Into<Uint256>,
220 ) -> Result<Self, CheckedFromRatioError> {
221 let numerator: Uint256 = numerator.into();
222 let denominator: Uint256 = denominator.into();
223 match numerator.checked_multiply_ratio(Self::DECIMAL_FRACTIONAL, denominator) {
224 Ok(ratio) => {
225 Ok(Self(ratio))
227 }
228 Err(CheckedMultiplyRatioError::Overflow) => Err(CheckedFromRatioError::Overflow),
229 Err(CheckedMultiplyRatioError::DivideByZero) => {
230 Err(CheckedFromRatioError::DivideByZero)
231 }
232 }
233 }
234
235 #[must_use]
236 pub const fn is_zero(&self) -> bool {
237 self.0.is_zero()
238 }
239
240 #[must_use]
259 #[inline]
260 pub const fn atomics(&self) -> Uint256 {
261 self.0
262 }
263
264 #[must_use]
269 #[inline]
270 pub const fn decimal_places(&self) -> u32 {
271 Self::DECIMAL_PLACES
272 }
273
274 #[must_use = "this returns the result of the operation, without modifying the original"]
276 pub fn floor(&self) -> Self {
277 Self((self.0 / Self::DECIMAL_FRACTIONAL) * Self::DECIMAL_FRACTIONAL)
278 }
279
280 #[must_use = "this returns the result of the operation, without modifying the original"]
282 pub fn ceil(&self) -> Self {
283 match self.checked_ceil() {
284 Ok(value) => value,
285 Err(_) => panic!("attempt to ceil with overflow"),
286 }
287 }
288
289 pub fn checked_ceil(&self) -> Result<Self, RoundUpOverflowError> {
291 let floor = self.floor();
292 if floor == self {
293 Ok(floor)
294 } else {
295 floor
296 .checked_add(Decimal256::one())
297 .map_err(|_| RoundUpOverflowError)
298 }
299 }
300
301 pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
302 self.0
303 .checked_add(other.0)
304 .map(Self)
305 .map_err(|_| OverflowError::new(OverflowOperation::Add))
306 }
307
308 pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
309 self.0
310 .checked_sub(other.0)
311 .map(Self)
312 .map_err(|_| OverflowError::new(OverflowOperation::Sub))
313 }
314
315 pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
317 let result_as_uint512 = self.numerator().full_mul(other.numerator())
318 / Uint512::from_uint256(Self::DECIMAL_FRACTIONAL); result_as_uint512
320 .try_into()
321 .map(Self)
322 .map_err(|_| OverflowError::new(OverflowOperation::Mul))
323 }
324
325 #[must_use = "this returns the result of the operation, without modifying the original"]
327 pub fn pow(self, exp: u32) -> Self {
328 match self.checked_pow(exp) {
329 Ok(value) => value,
330 Err(_) => panic!("Multiplication overflow"),
331 }
332 }
333
334 pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
336 fn inner(mut x: Decimal256, mut n: u32) -> Result<Decimal256, OverflowError> {
340 if n == 0 {
341 return Ok(Decimal256::one());
342 }
343
344 let mut y = Decimal256::one();
345
346 while n > 1 {
347 if n % 2 == 0 {
348 x = x.checked_mul(x)?;
349 n /= 2;
350 } else {
351 y = x.checked_mul(y)?;
352 x = x.checked_mul(x)?;
353 n = (n - 1) / 2;
354 }
355 }
356
357 Ok(x * y)
358 }
359
360 inner(self, exp).map_err(|_| OverflowError::new(OverflowOperation::Pow))
361 }
362
363 pub fn checked_div(self, other: Self) -> Result<Self, CheckedFromRatioError> {
364 Decimal256::checked_from_ratio(self.numerator(), other.numerator())
365 }
366
367 pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
368 self.0
369 .checked_rem(other.0)
370 .map(Self)
371 .map_err(|_| DivideByZeroError)
372 }
373
374 #[must_use = "this returns the result of the operation, without modifying the original"]
378 pub fn sqrt(&self) -> Self {
379 if self.0.is_zero() {
382 return self.sqrt_with_precision(Self::DECIMAL_PLACES / 2).unwrap();
384 }
385
386 let precision_guess = (77 - self.0.ilog10()) / 2;
389 let precision = core::cmp::min(precision_guess, Self::DECIMAL_PLACES / 2);
390
391 self.sqrt_with_precision(precision)
395 .or_else(|| self.sqrt_with_precision(precision - 1))
396 .unwrap()
397 }
398
399 #[must_use = "this returns the result of the operation, without modifying the original"]
404 fn sqrt_with_precision(&self, precision: u32) -> Option<Self> {
405 let inner_mul = Uint256::from(100u128).pow(precision);
406 self.0.checked_mul(inner_mul).ok().map(|inner| {
407 let outer_mul = Uint256::from(10u128).pow(Self::DECIMAL_PLACES / 2 - precision);
408 Self(inner.isqrt().checked_mul(outer_mul).unwrap())
409 })
410 }
411
412 #[must_use = "this returns the result of the operation, without modifying the original"]
413 pub fn abs_diff(self, other: Self) -> Self {
414 if self < other {
415 other - self
416 } else {
417 self - other
418 }
419 }
420
421 #[must_use = "this returns the result of the operation, without modifying the original"]
422 pub fn saturating_add(self, other: Self) -> Self {
423 self.checked_add(other).unwrap_or(Self::MAX)
424 }
425
426 #[must_use = "this returns the result of the operation, without modifying the original"]
427 pub fn saturating_sub(self, other: Self) -> Self {
428 self.checked_sub(other).unwrap_or_else(|_| Self::zero())
429 }
430
431 #[must_use = "this returns the result of the operation, without modifying the original"]
432 pub fn saturating_mul(self, other: Self) -> Self {
433 self.checked_mul(other).unwrap_or(Self::MAX)
434 }
435
436 #[must_use = "this returns the result of the operation, without modifying the original"]
437 pub fn saturating_pow(self, exp: u32) -> Self {
438 self.checked_pow(exp).unwrap_or(Self::MAX)
439 }
440
441 #[must_use = "this returns the result of the operation, without modifying the original"]
460 pub fn to_uint_floor(self) -> Uint256 {
461 self.0 / Self::DECIMAL_FRACTIONAL
462 }
463
464 #[must_use = "this returns the result of the operation, without modifying the original"]
483 pub fn to_uint_ceil(self) -> Uint256 {
484 let x = self.0;
487 let y = Self::DECIMAL_FRACTIONAL;
488 if x.is_zero() {
489 Uint256::zero()
490 } else {
491 Uint256::one() + ((x - Uint256::one()) / y)
492 }
493 }
494}
495
496impl Fraction<Uint256> for Decimal256 {
497 #[inline]
498 fn numerator(&self) -> Uint256 {
499 self.0
500 }
501
502 #[inline]
503 fn denominator(&self) -> Uint256 {
504 Self::DECIMAL_FRACTIONAL
505 }
506
507 fn inv(&self) -> Option<Self> {
511 if self.is_zero() {
512 None
513 } else {
514 Some(Self(Self::DECIMAL_FRACTIONAL_SQUARED / self.0))
518 }
519 }
520}
521
522impl From<Decimal> for Decimal256 {
523 fn from(input: Decimal) -> Self {
524 Decimal256::from_atomics(input.atomics(), input.decimal_places()).unwrap()
527 }
528}
529
530impl TryFrom<SignedDecimal> for Decimal256 {
531 type Error = Decimal256RangeExceeded;
532
533 fn try_from(value: SignedDecimal) -> Result<Self, Self::Error> {
534 value
535 .atomics()
536 .try_into()
537 .map(Decimal256)
538 .map_err(|_| Decimal256RangeExceeded)
539 }
540}
541
542impl TryFrom<SignedDecimal256> for Decimal256 {
543 type Error = Decimal256RangeExceeded;
544
545 fn try_from(value: SignedDecimal256) -> Result<Self, Self::Error> {
546 value
547 .atomics()
548 .try_into()
549 .map(Decimal256)
550 .map_err(|_| Decimal256RangeExceeded)
551 }
552}
553
554impl FromStr for Decimal256 {
555 type Err = StdError;
556
557 fn from_str(input: &str) -> Result<Self, Self::Err> {
564 let mut parts_iter = input.split('.');
565
566 let whole_part = parts_iter.next().unwrap(); let whole = whole_part.parse::<Uint256>()?;
568 let mut atomics = whole.checked_mul(Self::DECIMAL_FRACTIONAL)?;
569
570 if let Some(fractional_part) = parts_iter.next() {
571 let fractional = fractional_part.parse::<Uint256>()?;
572 let exp = Self::DECIMAL_PLACES
573 .checked_sub(fractional_part.len() as u32)
574 .ok_or_else(|| {
575 StdError::msg(format_args!(
576 "Cannot parse more than {} fractional digits",
577 Self::DECIMAL_PLACES
578 ))
579 })?;
580 debug_assert!(exp <= Self::DECIMAL_PLACES);
581 let fractional_factor = Uint256::from(10u128).pow(exp);
582 atomics = atomics.checked_add(
583 fractional.checked_mul(fractional_factor).unwrap(),
586 )?;
587 }
588
589 if parts_iter.next().is_some() {
590 return Err(StdError::msg("Unexpected number of dots").with_kind(ErrorKind::Parsing));
591 }
592
593 Ok(Self(atomics))
594 }
595}
596
597impl fmt::Display for Decimal256 {
598 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
599 let whole = (self.0) / Self::DECIMAL_FRACTIONAL;
600 let fractional = self.0.checked_rem(Self::DECIMAL_FRACTIONAL).unwrap();
601
602 if fractional.is_zero() {
603 write!(f, "{whole}")
604 } else {
605 let fractional_string = format!(
606 "{:0>padding$}",
607 fractional,
608 padding = Self::DECIMAL_PLACES as usize
609 );
610 f.write_str(&whole.to_string())?;
611 f.write_char('.')?;
612 f.write_str(fractional_string.trim_end_matches('0'))?;
613 Ok(())
614 }
615 }
616}
617
618impl fmt::Debug for Decimal256 {
619 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
620 write!(f, "Decimal256({self})")
621 }
622}
623
624impl Add for Decimal256 {
625 type Output = Self;
626
627 fn add(self, other: Self) -> Self {
628 Self(self.0 + other.0)
629 }
630}
631forward_ref_binop!(impl Add, add for Decimal256, Decimal256);
632
633impl AddAssign for Decimal256 {
634 fn add_assign(&mut self, rhs: Decimal256) {
635 *self = *self + rhs;
636 }
637}
638forward_ref_op_assign!(impl AddAssign, add_assign for Decimal256, Decimal256);
639
640impl Sub for Decimal256 {
641 type Output = Self;
642
643 fn sub(self, other: Self) -> Self {
644 Self(self.0 - other.0)
645 }
646}
647forward_ref_binop!(impl Sub, sub for Decimal256, Decimal256);
648
649impl SubAssign for Decimal256 {
650 fn sub_assign(&mut self, rhs: Decimal256) {
651 *self = *self - rhs;
652 }
653}
654forward_ref_op_assign!(impl SubAssign, sub_assign for Decimal256, Decimal256);
655
656impl Mul for Decimal256 {
657 type Output = Self;
658
659 #[allow(clippy::suspicious_arithmetic_impl)]
660 fn mul(self, other: Self) -> Self {
661 let result_as_uint512 = self.numerator().full_mul(other.numerator())
667 / Uint512::from_uint256(Self::DECIMAL_FRACTIONAL); match result_as_uint512.try_into() {
669 Ok(result) => Self(result),
670 Err(_) => panic!("attempt to multiply with overflow"),
671 }
672 }
673}
674forward_ref_binop!(impl Mul, mul for Decimal256, Decimal256);
675
676impl MulAssign for Decimal256 {
677 fn mul_assign(&mut self, rhs: Self) {
678 *self = *self * rhs;
679 }
680}
681forward_ref_op_assign!(impl MulAssign, mul_assign for Decimal256, Decimal256);
682
683impl Div for Decimal256 {
684 type Output = Self;
685
686 fn div(self, other: Self) -> Self {
687 match Decimal256::checked_from_ratio(self.numerator(), other.numerator()) {
688 Ok(ratio) => ratio,
689 Err(CheckedFromRatioError::DivideByZero) => {
690 panic!("Division failed - denominator must not be zero")
691 }
692 Err(CheckedFromRatioError::Overflow) => {
693 panic!("Division failed - multiplication overflow")
694 }
695 }
696 }
697}
698forward_ref_binop!(impl Div, div for Decimal256, Decimal256);
699
700impl DivAssign for Decimal256 {
701 fn div_assign(&mut self, rhs: Decimal256) {
702 *self = *self / rhs;
703 }
704}
705forward_ref_op_assign!(impl DivAssign, div_assign for Decimal256, Decimal256);
706
707impl Div<Uint256> for Decimal256 {
708 type Output = Self;
709
710 fn div(self, rhs: Uint256) -> Self::Output {
711 Self(self.0 / rhs)
712 }
713}
714
715impl DivAssign<Uint256> for Decimal256 {
716 fn div_assign(&mut self, rhs: Uint256) {
717 self.0 /= rhs;
718 }
719}
720
721impl Rem for Decimal256 {
722 type Output = Self;
723
724 #[inline]
728 fn rem(self, rhs: Self) -> Self {
729 Self(self.0.rem(rhs.0))
730 }
731}
732forward_ref_binop!(impl Rem, rem for Decimal256, Decimal256);
733
734impl RemAssign<Decimal256> for Decimal256 {
735 fn rem_assign(&mut self, rhs: Decimal256) {
736 *self = *self % rhs;
737 }
738}
739forward_ref_op_assign!(impl RemAssign, rem_assign for Decimal256, Decimal256);
740
741impl<A> core::iter::Sum<A> for Decimal256
742where
743 Self: Add<A, Output = Self>,
744{
745 fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
746 iter.fold(Self::zero(), Add::add)
747 }
748}
749
750impl Serialize for Decimal256 {
752 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
753 where
754 S: ser::Serializer,
755 {
756 serializer.serialize_str(&self.to_string())
757 }
758}
759
760impl<'de> Deserialize<'de> for Decimal256 {
762 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
763 where
764 D: Deserializer<'de>,
765 {
766 deserializer.deserialize_str(Decimal256Visitor)
767 }
768}
769
770struct Decimal256Visitor;
771
772impl de::Visitor<'_> for Decimal256Visitor {
773 type Value = Decimal256;
774
775 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
776 formatter.write_str("string-encoded decimal")
777 }
778
779 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
780 where
781 E: de::Error,
782 {
783 match Self::Value::from_str(v) {
784 Ok(d) => Ok(d),
785 Err(e) => Err(E::custom(format_args!("Error parsing decimal '{v}': {e}"))),
786 }
787 }
788}