prov_cosmwasm_std/math/
decimal.rs

1use schemars::JsonSchema;
2use serde::{de, ser, Deserialize, Deserializer, Serialize};
3use std::cmp::Ordering;
4use std::convert::TryInto;
5use std::fmt::{self, Write};
6use std::ops;
7use std::str::FromStr;
8use thiserror::Error;
9
10use crate::errors::StdError;
11
12use super::Fraction;
13use super::Isqrt;
14use super::{Uint128, Uint256};
15
16/// A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0
17///
18/// The greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)
19#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
20pub struct Decimal(#[schemars(with = "String")] Uint128);
21
22#[derive(Error, Debug, PartialEq)]
23#[error("Decimal range exceeded")]
24pub struct DecimalRangeExceeded;
25
26impl Decimal {
27    const DECIMAL_FRACTIONAL: Uint128 = Uint128::new(1_000_000_000_000_000_000u128); // 1*10**18
28    const DECIMAL_FRACTIONAL_SQUARED: Uint128 =
29        Uint128::new(1_000_000_000_000_000_000_000_000_000_000_000_000u128); // (1*10**18)**2 = 1*10**36
30    const DECIMAL_PLACES: usize = 18; // This needs to be an even number.
31
32    pub const MAX: Self = Self(Uint128::MAX);
33
34    /// Create a 1.0 Decimal
35    pub const fn one() -> Self {
36        Decimal(Self::DECIMAL_FRACTIONAL)
37    }
38
39    /// Create a 0.0 Decimal
40    pub const fn zero() -> Self {
41        Decimal(Uint128::zero())
42    }
43
44    /// Convert x% into Decimal
45    pub fn percent(x: u64) -> Self {
46        Decimal(((x as u128) * 10_000_000_000_000_000).into())
47    }
48
49    /// Convert permille (x/1000) into Decimal
50    pub fn permille(x: u64) -> Self {
51        Decimal(((x as u128) * 1_000_000_000_000_000).into())
52    }
53
54    /// Creates a decimal from a number of atomic units and the number
55    /// of decimal places. The inputs will be converted internally to form
56    /// a decimal with 18 decimal places. So the input 123 and 2 will create
57    /// the decimal 1.23.
58    ///
59    /// Using 18 decimal places is slightly more efficient than other values
60    /// as no internal conversion is necessary.
61    ///
62    /// ## Examples
63    ///
64    /// ```
65    /// # use prov_cosmwasm_std::{Decimal, Uint128};
66    /// let a = Decimal::from_atomics(Uint128::new(1234), 3).unwrap();
67    /// assert_eq!(a.to_string(), "1.234");
68    ///
69    /// let a = Decimal::from_atomics(1234u128, 0).unwrap();
70    /// assert_eq!(a.to_string(), "1234");
71    ///
72    /// let a = Decimal::from_atomics(1u64, 18).unwrap();
73    /// assert_eq!(a.to_string(), "0.000000000000000001");
74    /// ```
75    pub fn from_atomics(
76        atomics: impl Into<Uint128>,
77        decimal_places: u32,
78    ) -> Result<Self, DecimalRangeExceeded> {
79        let atomics = atomics.into();
80        const TEN: Uint128 = Uint128::new(10);
81        Ok(match decimal_places.cmp(&(Self::DECIMAL_PLACES as u32)) {
82            Ordering::Less => {
83                let digits = (Self::DECIMAL_PLACES as u32) - decimal_places; // No overflow because decimal_places < DECIMAL_PLACES
84                let factor = TEN.checked_pow(digits).unwrap(); // Safe because digits <= 17
85                Self(
86                    atomics
87                        .checked_mul(factor)
88                        .map_err(|_| DecimalRangeExceeded)?,
89                )
90            }
91            Ordering::Equal => Self(atomics),
92            Ordering::Greater => {
93                let digits = decimal_places - (Self::DECIMAL_PLACES as u32); // No overflow because decimal_places > DECIMAL_PLACES
94                if let Ok(factor) = TEN.checked_pow(digits) {
95                    Self(atomics.checked_div(factor).unwrap()) // Safe because factor cannot be zero
96                } else {
97                    // In this case `factor` exceeds the Uint128 range.
98                    // Any Uint128 `x` divided by `factor` with `factor > Uint128::MAX` is 0.
99                    // Try e.g. Python3: `(2**128-1) // 2**128`
100                    Self(Uint128::zero())
101                }
102            }
103        })
104    }
105
106    /// Returns the ratio (numerator / denominator) as a Decimal
107    pub fn from_ratio(numerator: impl Into<Uint128>, denominator: impl Into<Uint128>) -> Self {
108        let numerator: Uint128 = numerator.into();
109        let denominator: Uint128 = denominator.into();
110        if denominator.is_zero() {
111            panic!("Denominator must not be zero");
112        }
113
114        Decimal(
115            // numerator * DECIMAL_FRACTIONAL / denominator
116            numerator.multiply_ratio(Self::DECIMAL_FRACTIONAL, denominator),
117        )
118    }
119
120    pub fn is_zero(&self) -> bool {
121        self.0.is_zero()
122    }
123
124    /// A decimal is an integer of atomic units plus a number that specifies the
125    /// position of the decimal dot. So any decimal can be expressed as two numbers.
126    ///
127    /// ## Examples
128    ///
129    /// ```
130    /// # use prov_cosmwasm_std::{Decimal, Uint128};
131    /// # use std::str::FromStr;
132    /// // Value with whole and fractional part
133    /// let a = Decimal::from_str("1.234").unwrap();
134    /// assert_eq!(a.decimal_places(), 18);
135    /// assert_eq!(a.atomics(), Uint128::new(1234000000000000000));
136    ///
137    /// // Smallest possible value
138    /// let b = Decimal::from_str("0.000000000000000001").unwrap();
139    /// assert_eq!(b.decimal_places(), 18);
140    /// assert_eq!(b.atomics(), Uint128::new(1));
141    /// ```
142    pub fn atomics(&self) -> Uint128 {
143        self.0
144    }
145
146    /// The number of decimal places. This is a constant value for now
147    /// but this could potentially change as the type evolves.
148    ///
149    /// See also [`Decimal::atomics()`].
150    pub fn decimal_places(&self) -> u32 {
151        Self::DECIMAL_PLACES as u32
152    }
153
154    /// Returns the approximate square root as a Decimal.
155    ///
156    /// This should not overflow or panic.
157    pub fn sqrt(&self) -> Self {
158        // Algorithm described in https://hackmd.io/@webmaster128/SJThlukj_
159        // We start with the highest precision possible and lower it until
160        // there's no overflow.
161        //
162        // TODO: This could be made more efficient once log10 is in:
163        // https://github.com/rust-lang/rust/issues/70887
164        // The max precision is something like `9 - log10(self.0) / 2`.
165        (0..=Self::DECIMAL_PLACES / 2)
166            .rev()
167            .find_map(|i| self.sqrt_with_precision(i))
168            // The last step (i = 0) is guaranteed to succeed because `isqrt(u128::MAX) * 10^9` does not overflow
169            .unwrap()
170    }
171
172    /// Lower precision means more aggressive rounding, but less risk of overflow.
173    /// Precision *must* be a number between 0 and 9 (inclusive).
174    ///
175    /// Returns `None` if the internal multiplication overflows.
176    fn sqrt_with_precision(&self, precision: usize) -> Option<Self> {
177        let precision = precision as u32;
178
179        let inner_mul = 100u128.pow(precision);
180        self.0.checked_mul(inner_mul.into()).ok().map(|inner| {
181            let outer_mul = 10u128.pow(Self::DECIMAL_PLACES as u32 / 2 - precision);
182            Decimal(inner.isqrt().checked_mul(Uint128::from(outer_mul)).unwrap())
183        })
184    }
185}
186
187impl Fraction<Uint128> for Decimal {
188    #[inline]
189    fn numerator(&self) -> Uint128 {
190        self.0
191    }
192
193    #[inline]
194    fn denominator(&self) -> Uint128 {
195        Self::DECIMAL_FRACTIONAL
196    }
197
198    /// Returns the multiplicative inverse `1/d` for decimal `d`.
199    ///
200    /// If `d` is zero, none is returned.
201    fn inv(&self) -> Option<Self> {
202        if self.is_zero() {
203            None
204        } else {
205            // Let self be p/q with p = self.0 and q = DECIMAL_FRACTIONAL.
206            // Now we calculate the inverse a/b = q/p such that b = DECIMAL_FRACTIONAL. Then
207            // `a = DECIMAL_FRACTIONAL*DECIMAL_FRACTIONAL / self.0`.
208            Some(Decimal(Self::DECIMAL_FRACTIONAL_SQUARED / self.0))
209        }
210    }
211}
212
213impl FromStr for Decimal {
214    type Err = StdError;
215
216    /// Converts the decimal string to a Decimal
217    /// Possible inputs: "1.23", "1", "000012", "1.123000000"
218    /// Disallowed: "", ".23"
219    ///
220    /// This never performs any kind of rounding.
221    /// More than DECIMAL_PLACES fractional digits, even zeros, result in an error.
222    fn from_str(input: &str) -> Result<Self, Self::Err> {
223        let mut parts_iter = input.split('.');
224
225        let whole_part = parts_iter.next().unwrap(); // split always returns at least one element
226        let whole = whole_part
227            .parse::<Uint128>()
228            .map_err(|_| StdError::generic_err("Error parsing whole"))?;
229        let mut atomics = whole
230            .checked_mul(Self::DECIMAL_FRACTIONAL)
231            .map_err(|_| StdError::generic_err("Value too big"))?;
232
233        if let Some(fractional_part) = parts_iter.next() {
234            let fractional = fractional_part
235                .parse::<Uint128>()
236                .map_err(|_| StdError::generic_err("Error parsing fractional"))?;
237            let exp =
238                (Self::DECIMAL_PLACES.checked_sub(fractional_part.len())).ok_or_else(|| {
239                    StdError::generic_err(format!(
240                        "Cannot parse more than {} fractional digits",
241                        Self::DECIMAL_PLACES
242                    ))
243                })?;
244            debug_assert!(exp <= Self::DECIMAL_PLACES);
245            let fractional_factor = Uint128::from(10u128.pow(exp as u32));
246            atomics = atomics
247                .checked_add(
248                    // The inner multiplication can't overflow because
249                    // fractional < 10^DECIMAL_PLACES && fractional_factor <= 10^DECIMAL_PLACES
250                    fractional.checked_mul(fractional_factor).unwrap(),
251                )
252                .map_err(|_| StdError::generic_err("Value too big"))?;
253        }
254
255        if parts_iter.next().is_some() {
256            return Err(StdError::generic_err("Unexpected number of dots"));
257        }
258
259        Ok(Decimal(atomics))
260    }
261}
262
263impl fmt::Display for Decimal {
264    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
265        let whole = (self.0) / Self::DECIMAL_FRACTIONAL;
266        let fractional = (self.0).checked_rem(Self::DECIMAL_FRACTIONAL).unwrap();
267
268        if fractional.is_zero() {
269            write!(f, "{}", whole)
270        } else {
271            let fractional_string =
272                format!("{:0>padding$}", fractional, padding = Self::DECIMAL_PLACES);
273            f.write_str(&whole.to_string())?;
274            f.write_char('.')?;
275            f.write_str(fractional_string.trim_end_matches('0'))?;
276            Ok(())
277        }
278    }
279}
280
281impl ops::Add for Decimal {
282    type Output = Self;
283
284    fn add(self, other: Self) -> Self {
285        Decimal(self.0 + other.0)
286    }
287}
288
289impl ops::Add<&Decimal> for Decimal {
290    type Output = Self;
291
292    fn add(self, other: &Decimal) -> Self {
293        Decimal(self.0 + other.0)
294    }
295}
296
297impl ops::Sub for Decimal {
298    type Output = Self;
299
300    fn sub(self, other: Self) -> Self {
301        Decimal(self.0 - other.0)
302    }
303}
304
305impl ops::Mul for Decimal {
306    type Output = Self;
307
308    #[allow(clippy::suspicious_arithmetic_impl)]
309    fn mul(self, other: Self) -> Self {
310        // Decimals are fractions. We can multiply two decimals a and b
311        // via
312        //       (a.numerator() * b.numerator()) / (a.denominator() * b.denominator())
313        //     = (a.numerator() * b.numerator()) / a.denominator() / b.denominator()
314
315        let result_as_uint256 = self.numerator().full_mul(other.numerator())
316            / Uint256::from_uint128(Self::DECIMAL_FRACTIONAL); // from_uint128 is a const method and should be "free"
317        match result_as_uint256.try_into() {
318            Ok(result) => Self(result),
319            Err(_) => panic!("attempt to multiply with overflow"),
320        }
321    }
322}
323
324/// Both d*u and u*d with d: Decimal and u: Uint128 returns an Uint128. There is no
325/// specific reason for this decision other than the initial use cases we have. If you
326/// need a Decimal result for the same calculation, use Decimal(d*u) or Decimal(u*d).
327impl ops::Mul<Decimal> for Uint128 {
328    type Output = Self;
329
330    #[allow(clippy::suspicious_arithmetic_impl)]
331    fn mul(self, rhs: Decimal) -> Self::Output {
332        // 0*a and b*0 is always 0
333        if self.is_zero() || rhs.is_zero() {
334            return Uint128::zero();
335        }
336        self.multiply_ratio(rhs.0, Decimal::DECIMAL_FRACTIONAL)
337    }
338}
339
340impl ops::Mul<Uint128> for Decimal {
341    type Output = Uint128;
342
343    fn mul(self, rhs: Uint128) -> Self::Output {
344        rhs * self
345    }
346}
347
348impl ops::Div<Uint128> for Decimal {
349    type Output = Self;
350
351    fn div(self, rhs: Uint128) -> Self::Output {
352        Decimal(self.0 / rhs)
353    }
354}
355
356impl ops::DivAssign<Uint128> for Decimal {
357    fn div_assign(&mut self, rhs: Uint128) {
358        self.0 /= rhs;
359    }
360}
361
362impl<A> std::iter::Sum<A> for Decimal
363where
364    Self: ops::Add<A, Output = Self>,
365{
366    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
367        iter.fold(Self::zero(), ops::Add::add)
368    }
369}
370
371/// Serializes as a decimal string
372impl Serialize for Decimal {
373    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
374    where
375        S: ser::Serializer,
376    {
377        serializer.serialize_str(&self.to_string())
378    }
379}
380
381/// Deserializes as a base64 string
382impl<'de> Deserialize<'de> for Decimal {
383    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
384    where
385        D: Deserializer<'de>,
386    {
387        deserializer.deserialize_str(DecimalVisitor)
388    }
389}
390
391struct DecimalVisitor;
392
393impl<'de> de::Visitor<'de> for DecimalVisitor {
394    type Value = Decimal;
395
396    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
397        formatter.write_str("string-encoded decimal")
398    }
399
400    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
401    where
402        E: de::Error,
403    {
404        match Decimal::from_str(v) {
405            Ok(d) => Ok(d),
406            Err(e) => Err(E::custom(format!("Error parsing decimal '{}': {}", v, e))),
407        }
408    }
409}
410
411#[cfg(test)]
412mod tests {
413    use super::*;
414    use crate::{from_slice, to_vec};
415
416    #[test]
417    fn decimal_one() {
418        let value = Decimal::one();
419        assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL);
420    }
421
422    #[test]
423    fn decimal_zero() {
424        let value = Decimal::zero();
425        assert!(value.0.is_zero());
426    }
427
428    #[test]
429    fn decimal_percent() {
430        let value = Decimal::percent(50);
431        assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(2u8));
432    }
433
434    #[test]
435    fn decimal_permille() {
436        let value = Decimal::permille(125);
437        assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(8u8));
438    }
439
440    #[test]
441    fn decimal_from_atomics_works() {
442        let one = Decimal::one();
443        let two = one + one;
444
445        assert_eq!(Decimal::from_atomics(1u128, 0).unwrap(), one);
446        assert_eq!(Decimal::from_atomics(10u128, 1).unwrap(), one);
447        assert_eq!(Decimal::from_atomics(100u128, 2).unwrap(), one);
448        assert_eq!(Decimal::from_atomics(1000u128, 3).unwrap(), one);
449        assert_eq!(
450            Decimal::from_atomics(1000000000000000000u128, 18).unwrap(),
451            one
452        );
453        assert_eq!(
454            Decimal::from_atomics(10000000000000000000u128, 19).unwrap(),
455            one
456        );
457        assert_eq!(
458            Decimal::from_atomics(100000000000000000000u128, 20).unwrap(),
459            one
460        );
461
462        assert_eq!(Decimal::from_atomics(2u128, 0).unwrap(), two);
463        assert_eq!(Decimal::from_atomics(20u128, 1).unwrap(), two);
464        assert_eq!(Decimal::from_atomics(200u128, 2).unwrap(), two);
465        assert_eq!(Decimal::from_atomics(2000u128, 3).unwrap(), two);
466        assert_eq!(
467            Decimal::from_atomics(2000000000000000000u128, 18).unwrap(),
468            two
469        );
470        assert_eq!(
471            Decimal::from_atomics(20000000000000000000u128, 19).unwrap(),
472            two
473        );
474        assert_eq!(
475            Decimal::from_atomics(200000000000000000000u128, 20).unwrap(),
476            two
477        );
478
479        // Cuts decimal digits (20 provided but only 18 can be stored)
480        assert_eq!(
481            Decimal::from_atomics(4321u128, 20).unwrap(),
482            Decimal::from_str("0.000000000000000043").unwrap()
483        );
484        assert_eq!(
485            Decimal::from_atomics(6789u128, 20).unwrap(),
486            Decimal::from_str("0.000000000000000067").unwrap()
487        );
488        assert_eq!(
489            Decimal::from_atomics(u128::MAX, 38).unwrap(),
490            Decimal::from_str("3.402823669209384634").unwrap()
491        );
492        assert_eq!(
493            Decimal::from_atomics(u128::MAX, 39).unwrap(),
494            Decimal::from_str("0.340282366920938463").unwrap()
495        );
496        assert_eq!(
497            Decimal::from_atomics(u128::MAX, 45).unwrap(),
498            Decimal::from_str("0.000000340282366920").unwrap()
499        );
500        assert_eq!(
501            Decimal::from_atomics(u128::MAX, 51).unwrap(),
502            Decimal::from_str("0.000000000000340282").unwrap()
503        );
504        assert_eq!(
505            Decimal::from_atomics(u128::MAX, 56).unwrap(),
506            Decimal::from_str("0.000000000000000003").unwrap()
507        );
508        assert_eq!(
509            Decimal::from_atomics(u128::MAX, 57).unwrap(),
510            Decimal::from_str("0.000000000000000000").unwrap()
511        );
512        assert_eq!(
513            Decimal::from_atomics(u128::MAX, u32::MAX).unwrap(),
514            Decimal::from_str("0.000000000000000000").unwrap()
515        );
516
517        // Can be used with max value
518        let max = Decimal::MAX;
519        assert_eq!(
520            Decimal::from_atomics(max.atomics(), max.decimal_places()).unwrap(),
521            max
522        );
523
524        // Overflow is only possible with digits < 18
525        let result = Decimal::from_atomics(u128::MAX, 17);
526        assert_eq!(result.unwrap_err(), DecimalRangeExceeded);
527    }
528
529    #[test]
530    fn decimal_from_ratio_works() {
531        // 1.0
532        assert_eq!(Decimal::from_ratio(1u128, 1u128), Decimal::one());
533        assert_eq!(Decimal::from_ratio(53u128, 53u128), Decimal::one());
534        assert_eq!(Decimal::from_ratio(125u128, 125u128), Decimal::one());
535
536        // 1.5
537        assert_eq!(Decimal::from_ratio(3u128, 2u128), Decimal::percent(150));
538        assert_eq!(Decimal::from_ratio(150u128, 100u128), Decimal::percent(150));
539        assert_eq!(Decimal::from_ratio(333u128, 222u128), Decimal::percent(150));
540
541        // 0.125
542        assert_eq!(Decimal::from_ratio(1u64, 8u64), Decimal::permille(125));
543        assert_eq!(Decimal::from_ratio(125u64, 1000u64), Decimal::permille(125));
544
545        // 1/3 (result floored)
546        assert_eq!(
547            Decimal::from_ratio(1u64, 3u64),
548            Decimal(Uint128::from(333_333_333_333_333_333u128))
549        );
550
551        // 2/3 (result floored)
552        assert_eq!(
553            Decimal::from_ratio(2u64, 3u64),
554            Decimal(Uint128::from(666_666_666_666_666_666u128))
555        );
556
557        // large inputs
558        assert_eq!(Decimal::from_ratio(0u128, u128::MAX), Decimal::zero());
559        assert_eq!(Decimal::from_ratio(u128::MAX, u128::MAX), Decimal::one());
560        // 340282366920938463463 is the largest integer <= Decimal::MAX
561        assert_eq!(
562            Decimal::from_ratio(340282366920938463463u128, 1u128),
563            Decimal::from_str("340282366920938463463").unwrap()
564        );
565    }
566
567    #[test]
568    #[should_panic(expected = "Denominator must not be zero")]
569    fn decimal_from_ratio_panics_for_zero_denominator() {
570        Decimal::from_ratio(1u128, 0u128);
571    }
572
573    #[test]
574    fn decimal_implements_fraction() {
575        let fraction = Decimal::from_str("1234.567").unwrap();
576        assert_eq!(
577            fraction.numerator(),
578            Uint128::from(1_234_567_000_000_000_000_000u128)
579        );
580        assert_eq!(
581            fraction.denominator(),
582            Uint128::from(1_000_000_000_000_000_000u128)
583        );
584    }
585
586    #[test]
587    fn decimal_from_str_works() {
588        // Integers
589        assert_eq!(Decimal::from_str("0").unwrap(), Decimal::percent(0));
590        assert_eq!(Decimal::from_str("1").unwrap(), Decimal::percent(100));
591        assert_eq!(Decimal::from_str("5").unwrap(), Decimal::percent(500));
592        assert_eq!(Decimal::from_str("42").unwrap(), Decimal::percent(4200));
593        assert_eq!(Decimal::from_str("000").unwrap(), Decimal::percent(0));
594        assert_eq!(Decimal::from_str("001").unwrap(), Decimal::percent(100));
595        assert_eq!(Decimal::from_str("005").unwrap(), Decimal::percent(500));
596        assert_eq!(Decimal::from_str("0042").unwrap(), Decimal::percent(4200));
597
598        // Decimals
599        assert_eq!(Decimal::from_str("1.0").unwrap(), Decimal::percent(100));
600        assert_eq!(Decimal::from_str("1.5").unwrap(), Decimal::percent(150));
601        assert_eq!(Decimal::from_str("0.5").unwrap(), Decimal::percent(50));
602        assert_eq!(Decimal::from_str("0.123").unwrap(), Decimal::permille(123));
603
604        assert_eq!(Decimal::from_str("40.00").unwrap(), Decimal::percent(4000));
605        assert_eq!(Decimal::from_str("04.00").unwrap(), Decimal::percent(400));
606        assert_eq!(Decimal::from_str("00.40").unwrap(), Decimal::percent(40));
607        assert_eq!(Decimal::from_str("00.04").unwrap(), Decimal::percent(4));
608
609        // Can handle DECIMAL_PLACES fractional digits
610        assert_eq!(
611            Decimal::from_str("7.123456789012345678").unwrap(),
612            Decimal(Uint128::from(7123456789012345678u128))
613        );
614        assert_eq!(
615            Decimal::from_str("7.999999999999999999").unwrap(),
616            Decimal(Uint128::from(7999999999999999999u128))
617        );
618
619        // Works for documented max value
620        assert_eq!(
621            Decimal::from_str("340282366920938463463.374607431768211455").unwrap(),
622            Decimal::MAX
623        );
624    }
625
626    #[test]
627    fn decimal_from_str_errors_for_broken_whole_part() {
628        match Decimal::from_str("").unwrap_err() {
629            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing whole"),
630            e => panic!("Unexpected error: {:?}", e),
631        }
632
633        match Decimal::from_str(" ").unwrap_err() {
634            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing whole"),
635            e => panic!("Unexpected error: {:?}", e),
636        }
637
638        match Decimal::from_str("-1").unwrap_err() {
639            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing whole"),
640            e => panic!("Unexpected error: {:?}", e),
641        }
642    }
643
644    #[test]
645    fn decimal_from_str_errors_for_broken_fractinal_part() {
646        match Decimal::from_str("1.").unwrap_err() {
647            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
648            e => panic!("Unexpected error: {:?}", e),
649        }
650
651        match Decimal::from_str("1. ").unwrap_err() {
652            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
653            e => panic!("Unexpected error: {:?}", e),
654        }
655
656        match Decimal::from_str("1.e").unwrap_err() {
657            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
658            e => panic!("Unexpected error: {:?}", e),
659        }
660
661        match Decimal::from_str("1.2e3").unwrap_err() {
662            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
663            e => panic!("Unexpected error: {:?}", e),
664        }
665    }
666
667    #[test]
668    fn decimal_from_str_errors_for_more_than_18_fractional_digits() {
669        match Decimal::from_str("7.1234567890123456789").unwrap_err() {
670            StdError::GenericErr { msg, .. } => {
671                assert_eq!(msg, "Cannot parse more than 18 fractional digits",)
672            }
673            e => panic!("Unexpected error: {:?}", e),
674        }
675
676        // No special rules for trailing zeros. This could be changed but adds gas cost for the happy path.
677        match Decimal::from_str("7.1230000000000000000").unwrap_err() {
678            StdError::GenericErr { msg, .. } => {
679                assert_eq!(msg, "Cannot parse more than 18 fractional digits")
680            }
681            e => panic!("Unexpected error: {:?}", e),
682        }
683    }
684
685    #[test]
686    fn decimal_from_str_errors_for_invalid_number_of_dots() {
687        match Decimal::from_str("1.2.3").unwrap_err() {
688            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Unexpected number of dots"),
689            e => panic!("Unexpected error: {:?}", e),
690        }
691
692        match Decimal::from_str("1.2.3.4").unwrap_err() {
693            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Unexpected number of dots"),
694            e => panic!("Unexpected error: {:?}", e),
695        }
696    }
697
698    #[test]
699    fn decimal_from_str_errors_for_more_than_max_value() {
700        // Integer
701        match Decimal::from_str("340282366920938463464").unwrap_err() {
702            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Value too big"),
703            e => panic!("Unexpected error: {:?}", e),
704        }
705
706        // Decimal
707        match Decimal::from_str("340282366920938463464.0").unwrap_err() {
708            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Value too big"),
709            e => panic!("Unexpected error: {:?}", e),
710        }
711        match Decimal::from_str("340282366920938463463.374607431768211456").unwrap_err() {
712            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Value too big"),
713            e => panic!("Unexpected error: {:?}", e),
714        }
715    }
716
717    #[test]
718    fn decimal_atomics_works() {
719        let zero = Decimal::zero();
720        let one = Decimal::one();
721        let half = Decimal::percent(50);
722        let two = Decimal::percent(200);
723        let max = Decimal::MAX;
724
725        assert_eq!(zero.atomics(), Uint128::new(0));
726        assert_eq!(one.atomics(), Uint128::new(1000000000000000000));
727        assert_eq!(half.atomics(), Uint128::new(500000000000000000));
728        assert_eq!(two.atomics(), Uint128::new(2000000000000000000));
729        assert_eq!(max.atomics(), Uint128::MAX);
730    }
731
732    #[test]
733    fn decimal_decimal_places_works() {
734        let zero = Decimal::zero();
735        let one = Decimal::one();
736        let half = Decimal::percent(50);
737        let two = Decimal::percent(200);
738        let max = Decimal::MAX;
739
740        assert_eq!(zero.decimal_places(), 18);
741        assert_eq!(one.decimal_places(), 18);
742        assert_eq!(half.decimal_places(), 18);
743        assert_eq!(two.decimal_places(), 18);
744        assert_eq!(max.decimal_places(), 18);
745    }
746
747    #[test]
748    fn decimal_is_zero_works() {
749        assert!(Decimal::zero().is_zero());
750        assert!(Decimal::percent(0).is_zero());
751        assert!(Decimal::permille(0).is_zero());
752
753        assert!(!Decimal::one().is_zero());
754        assert!(!Decimal::percent(123).is_zero());
755        assert!(!Decimal::permille(1234).is_zero());
756    }
757
758    #[test]
759    fn decimal_inv_works() {
760        // d = 0
761        assert_eq!(Decimal::zero().inv(), None);
762
763        // d == 1
764        assert_eq!(Decimal::one().inv(), Some(Decimal::one()));
765
766        // d > 1 exact
767        assert_eq!(
768            Decimal::from_str("2").unwrap().inv(),
769            Some(Decimal::from_str("0.5").unwrap())
770        );
771        assert_eq!(
772            Decimal::from_str("20").unwrap().inv(),
773            Some(Decimal::from_str("0.05").unwrap())
774        );
775        assert_eq!(
776            Decimal::from_str("200").unwrap().inv(),
777            Some(Decimal::from_str("0.005").unwrap())
778        );
779        assert_eq!(
780            Decimal::from_str("2000").unwrap().inv(),
781            Some(Decimal::from_str("0.0005").unwrap())
782        );
783
784        // d > 1 rounded
785        assert_eq!(
786            Decimal::from_str("3").unwrap().inv(),
787            Some(Decimal::from_str("0.333333333333333333").unwrap())
788        );
789        assert_eq!(
790            Decimal::from_str("6").unwrap().inv(),
791            Some(Decimal::from_str("0.166666666666666666").unwrap())
792        );
793
794        // d < 1 exact
795        assert_eq!(
796            Decimal::from_str("0.5").unwrap().inv(),
797            Some(Decimal::from_str("2").unwrap())
798        );
799        assert_eq!(
800            Decimal::from_str("0.05").unwrap().inv(),
801            Some(Decimal::from_str("20").unwrap())
802        );
803        assert_eq!(
804            Decimal::from_str("0.005").unwrap().inv(),
805            Some(Decimal::from_str("200").unwrap())
806        );
807        assert_eq!(
808            Decimal::from_str("0.0005").unwrap().inv(),
809            Some(Decimal::from_str("2000").unwrap())
810        );
811    }
812
813    #[test]
814    fn decimal_add() {
815        let value = Decimal::one() + Decimal::percent(50); // 1.5
816        assert_eq!(
817            value.0,
818            Decimal::DECIMAL_FRACTIONAL * Uint128::from(3u8) / Uint128::from(2u8)
819        );
820    }
821
822    #[test]
823    #[should_panic(expected = "attempt to add with overflow")]
824    fn decimal_add_overflow_panics() {
825        let _value = Decimal::MAX + Decimal::percent(50);
826    }
827
828    #[test]
829    fn decimal_sub() {
830        let value = Decimal::one() - Decimal::percent(50); // 0.5
831        assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(2u8));
832    }
833
834    #[test]
835    #[should_panic(expected = "attempt to subtract with overflow")]
836    fn decimal_sub_overflow_panics() {
837        let _value = Decimal::zero() - Decimal::percent(50);
838    }
839
840    #[test]
841    fn decimal_implements_mul() {
842        let one = Decimal::one();
843        let two = one + one;
844        let half = Decimal::percent(50);
845
846        // 1*x and x*1
847        assert_eq!(one * Decimal::percent(0), Decimal::percent(0));
848        assert_eq!(one * Decimal::percent(1), Decimal::percent(1));
849        assert_eq!(one * Decimal::percent(10), Decimal::percent(10));
850        assert_eq!(one * Decimal::percent(100), Decimal::percent(100));
851        assert_eq!(one * Decimal::percent(1000), Decimal::percent(1000));
852        assert_eq!(one * Decimal::MAX, Decimal::MAX);
853        assert_eq!(Decimal::percent(0) * one, Decimal::percent(0));
854        assert_eq!(Decimal::percent(1) * one, Decimal::percent(1));
855        assert_eq!(Decimal::percent(10) * one, Decimal::percent(10));
856        assert_eq!(Decimal::percent(100) * one, Decimal::percent(100));
857        assert_eq!(Decimal::percent(1000) * one, Decimal::percent(1000));
858        assert_eq!(Decimal::MAX * one, Decimal::MAX);
859
860        // double
861        assert_eq!(two * Decimal::percent(0), Decimal::percent(0));
862        assert_eq!(two * Decimal::percent(1), Decimal::percent(2));
863        assert_eq!(two * Decimal::percent(10), Decimal::percent(20));
864        assert_eq!(two * Decimal::percent(100), Decimal::percent(200));
865        assert_eq!(two * Decimal::percent(1000), Decimal::percent(2000));
866        assert_eq!(Decimal::percent(0) * two, Decimal::percent(0));
867        assert_eq!(Decimal::percent(1) * two, Decimal::percent(2));
868        assert_eq!(Decimal::percent(10) * two, Decimal::percent(20));
869        assert_eq!(Decimal::percent(100) * two, Decimal::percent(200));
870        assert_eq!(Decimal::percent(1000) * two, Decimal::percent(2000));
871
872        // half
873        assert_eq!(half * Decimal::percent(0), Decimal::percent(0));
874        assert_eq!(half * Decimal::percent(1), Decimal::permille(5));
875        assert_eq!(half * Decimal::percent(10), Decimal::percent(5));
876        assert_eq!(half * Decimal::percent(100), Decimal::percent(50));
877        assert_eq!(half * Decimal::percent(1000), Decimal::percent(500));
878        assert_eq!(Decimal::percent(0) * half, Decimal::percent(0));
879        assert_eq!(Decimal::percent(1) * half, Decimal::permille(5));
880        assert_eq!(Decimal::percent(10) * half, Decimal::percent(5));
881        assert_eq!(Decimal::percent(100) * half, Decimal::percent(50));
882        assert_eq!(Decimal::percent(1000) * half, Decimal::percent(500));
883
884        fn dec(input: &str) -> Decimal {
885            Decimal::from_str(input).unwrap()
886        }
887
888        // Move left
889        let a = dec("123.127726548762582");
890        assert_eq!(a * dec("1"), dec("123.127726548762582"));
891        assert_eq!(a * dec("10"), dec("1231.27726548762582"));
892        assert_eq!(a * dec("100"), dec("12312.7726548762582"));
893        assert_eq!(a * dec("1000"), dec("123127.726548762582"));
894        assert_eq!(a * dec("1000000"), dec("123127726.548762582"));
895        assert_eq!(a * dec("1000000000"), dec("123127726548.762582"));
896        assert_eq!(a * dec("1000000000000"), dec("123127726548762.582"));
897        assert_eq!(a * dec("1000000000000000"), dec("123127726548762582"));
898        assert_eq!(a * dec("1000000000000000000"), dec("123127726548762582000"));
899        assert_eq!(dec("1") * a, dec("123.127726548762582"));
900        assert_eq!(dec("10") * a, dec("1231.27726548762582"));
901        assert_eq!(dec("100") * a, dec("12312.7726548762582"));
902        assert_eq!(dec("1000") * a, dec("123127.726548762582"));
903        assert_eq!(dec("1000000") * a, dec("123127726.548762582"));
904        assert_eq!(dec("1000000000") * a, dec("123127726548.762582"));
905        assert_eq!(dec("1000000000000") * a, dec("123127726548762.582"));
906        assert_eq!(dec("1000000000000000") * a, dec("123127726548762582"));
907        assert_eq!(dec("1000000000000000000") * a, dec("123127726548762582000"));
908
909        // Move right
910        let max = Decimal::MAX;
911        assert_eq!(
912            max * dec("1.0"),
913            dec("340282366920938463463.374607431768211455")
914        );
915        assert_eq!(
916            max * dec("0.1"),
917            dec("34028236692093846346.337460743176821145")
918        );
919        assert_eq!(
920            max * dec("0.01"),
921            dec("3402823669209384634.633746074317682114")
922        );
923        assert_eq!(
924            max * dec("0.001"),
925            dec("340282366920938463.463374607431768211")
926        );
927        assert_eq!(
928            max * dec("0.000001"),
929            dec("340282366920938.463463374607431768")
930        );
931        assert_eq!(
932            max * dec("0.000000001"),
933            dec("340282366920.938463463374607431")
934        );
935        assert_eq!(
936            max * dec("0.000000000001"),
937            dec("340282366.920938463463374607")
938        );
939        assert_eq!(
940            max * dec("0.000000000000001"),
941            dec("340282.366920938463463374")
942        );
943        assert_eq!(
944            max * dec("0.000000000000000001"),
945            dec("340.282366920938463463")
946        );
947    }
948
949    #[test]
950    #[should_panic(expected = "attempt to multiply with overflow")]
951    fn decimal_mul_overflow_panics() {
952        let _value = Decimal::MAX * Decimal::percent(101);
953    }
954
955    #[test]
956    // in this test the Decimal is on the right
957    fn uint128_decimal_multiply() {
958        // a*b
959        let left = Uint128::new(300);
960        let right = Decimal::one() + Decimal::percent(50); // 1.5
961        assert_eq!(left * right, Uint128::new(450));
962
963        // a*0
964        let left = Uint128::new(300);
965        let right = Decimal::zero();
966        assert_eq!(left * right, Uint128::new(0));
967
968        // 0*a
969        let left = Uint128::new(0);
970        let right = Decimal::one() + Decimal::percent(50); // 1.5
971        assert_eq!(left * right, Uint128::new(0));
972    }
973
974    #[test]
975    // in this test the Decimal is on the left
976    fn decimal_uint128_multiply() {
977        // a*b
978        let left = Decimal::one() + Decimal::percent(50); // 1.5
979        let right = Uint128::new(300);
980        assert_eq!(left * right, Uint128::new(450));
981
982        // 0*a
983        let left = Decimal::zero();
984        let right = Uint128::new(300);
985        assert_eq!(left * right, Uint128::new(0));
986
987        // a*0
988        let left = Decimal::one() + Decimal::percent(50); // 1.5
989        let right = Uint128::new(0);
990        assert_eq!(left * right, Uint128::new(0));
991    }
992
993    #[test]
994    fn decimal_uint128_division() {
995        // a/b
996        let left = Decimal::percent(150); // 1.5
997        let right = Uint128::new(3);
998        assert_eq!(left / right, Decimal::percent(50));
999
1000        // 0/a
1001        let left = Decimal::zero();
1002        let right = Uint128::new(300);
1003        assert_eq!(left / right, Decimal::zero());
1004    }
1005
1006    #[test]
1007    #[should_panic(expected = "attempt to divide by zero")]
1008    fn decimal_uint128_divide_by_zero() {
1009        let left = Decimal::percent(150); // 1.5
1010        let right = Uint128::new(0);
1011        let _result = left / right;
1012    }
1013
1014    #[test]
1015    fn decimal_uint128_div_assign() {
1016        // a/b
1017        let mut dec = Decimal::percent(150); // 1.5
1018        dec /= Uint128::new(3);
1019        assert_eq!(dec, Decimal::percent(50));
1020
1021        // 0/a
1022        let mut dec = Decimal::zero();
1023        dec /= Uint128::new(300);
1024        assert_eq!(dec, Decimal::zero());
1025    }
1026
1027    #[test]
1028    #[should_panic(expected = "attempt to divide by zero")]
1029    fn decimal_uint128_div_assign_by_zero() {
1030        // a/0
1031        let mut dec = Decimal::percent(50);
1032        dec /= Uint128::new(0);
1033    }
1034
1035    #[test]
1036    fn decimal_uint128_sqrt() {
1037        assert_eq!(Decimal::percent(900).sqrt(), Decimal::percent(300));
1038
1039        assert!(Decimal::percent(316) < Decimal::percent(1000).sqrt());
1040        assert!(Decimal::percent(1000).sqrt() < Decimal::percent(317));
1041    }
1042
1043    /// sqrt(2) is an irrational number, i.e. all 18 decimal places should be used.
1044    #[test]
1045    fn decimal_uint128_sqrt_is_precise() {
1046        assert_eq!(
1047            Decimal::from_str("2").unwrap().sqrt(),
1048            Decimal::from_str("1.414213562373095048").unwrap() // https://www.wolframalpha.com/input/?i=sqrt%282%29
1049        );
1050    }
1051
1052    #[test]
1053    fn decimal_uint128_sqrt_does_not_overflow() {
1054        assert_eq!(
1055            Decimal::from_str("400").unwrap().sqrt(),
1056            Decimal::from_str("20").unwrap()
1057        );
1058    }
1059
1060    #[test]
1061    fn decimal_uint128_sqrt_intermediate_precision_used() {
1062        assert_eq!(
1063            Decimal::from_str("400001").unwrap().sqrt(),
1064            // The last two digits (27) are truncated below due to the algorithm
1065            // we use. Larger numbers will cause less precision.
1066            // https://www.wolframalpha.com/input/?i=sqrt%28400001%29
1067            Decimal::from_str("632.456322602596803200").unwrap()
1068        );
1069    }
1070
1071    #[test]
1072    fn decimal_to_string() {
1073        // Integers
1074        assert_eq!(Decimal::zero().to_string(), "0");
1075        assert_eq!(Decimal::one().to_string(), "1");
1076        assert_eq!(Decimal::percent(500).to_string(), "5");
1077
1078        // Decimals
1079        assert_eq!(Decimal::percent(125).to_string(), "1.25");
1080        assert_eq!(Decimal::percent(42638).to_string(), "426.38");
1081        assert_eq!(Decimal::percent(3).to_string(), "0.03");
1082        assert_eq!(Decimal::permille(987).to_string(), "0.987");
1083
1084        assert_eq!(
1085            Decimal(Uint128::from(1u128)).to_string(),
1086            "0.000000000000000001"
1087        );
1088        assert_eq!(
1089            Decimal(Uint128::from(10u128)).to_string(),
1090            "0.00000000000000001"
1091        );
1092        assert_eq!(
1093            Decimal(Uint128::from(100u128)).to_string(),
1094            "0.0000000000000001"
1095        );
1096        assert_eq!(
1097            Decimal(Uint128::from(1000u128)).to_string(),
1098            "0.000000000000001"
1099        );
1100        assert_eq!(
1101            Decimal(Uint128::from(10000u128)).to_string(),
1102            "0.00000000000001"
1103        );
1104        assert_eq!(
1105            Decimal(Uint128::from(100000u128)).to_string(),
1106            "0.0000000000001"
1107        );
1108        assert_eq!(
1109            Decimal(Uint128::from(1000000u128)).to_string(),
1110            "0.000000000001"
1111        );
1112        assert_eq!(
1113            Decimal(Uint128::from(10000000u128)).to_string(),
1114            "0.00000000001"
1115        );
1116        assert_eq!(
1117            Decimal(Uint128::from(100000000u128)).to_string(),
1118            "0.0000000001"
1119        );
1120        assert_eq!(
1121            Decimal(Uint128::from(1000000000u128)).to_string(),
1122            "0.000000001"
1123        );
1124        assert_eq!(
1125            Decimal(Uint128::from(10000000000u128)).to_string(),
1126            "0.00000001"
1127        );
1128        assert_eq!(
1129            Decimal(Uint128::from(100000000000u128)).to_string(),
1130            "0.0000001"
1131        );
1132        assert_eq!(
1133            Decimal(Uint128::from(10000000000000u128)).to_string(),
1134            "0.00001"
1135        );
1136        assert_eq!(
1137            Decimal(Uint128::from(100000000000000u128)).to_string(),
1138            "0.0001"
1139        );
1140        assert_eq!(
1141            Decimal(Uint128::from(1000000000000000u128)).to_string(),
1142            "0.001"
1143        );
1144        assert_eq!(
1145            Decimal(Uint128::from(10000000000000000u128)).to_string(),
1146            "0.01"
1147        );
1148        assert_eq!(
1149            Decimal(Uint128::from(100000000000000000u128)).to_string(),
1150            "0.1"
1151        );
1152    }
1153
1154    #[test]
1155    fn decimal_iter_sum() {
1156        let items = vec![
1157            Decimal::zero(),
1158            Decimal(Uint128::from(2u128)),
1159            Decimal(Uint128::from(2u128)),
1160        ];
1161        assert_eq!(items.iter().sum::<Decimal>(), Decimal(Uint128::from(4u128)));
1162        assert_eq!(
1163            items.into_iter().sum::<Decimal>(),
1164            Decimal(Uint128::from(4u128))
1165        );
1166
1167        let empty: Vec<Decimal> = vec![];
1168        assert_eq!(Decimal::zero(), empty.iter().sum());
1169    }
1170
1171    #[test]
1172    fn decimal_serialize() {
1173        assert_eq!(to_vec(&Decimal::zero()).unwrap(), br#""0""#);
1174        assert_eq!(to_vec(&Decimal::one()).unwrap(), br#""1""#);
1175        assert_eq!(to_vec(&Decimal::percent(8)).unwrap(), br#""0.08""#);
1176        assert_eq!(to_vec(&Decimal::percent(87)).unwrap(), br#""0.87""#);
1177        assert_eq!(to_vec(&Decimal::percent(876)).unwrap(), br#""8.76""#);
1178        assert_eq!(to_vec(&Decimal::percent(8765)).unwrap(), br#""87.65""#);
1179    }
1180
1181    #[test]
1182    fn decimal_deserialize() {
1183        assert_eq!(from_slice::<Decimal>(br#""0""#).unwrap(), Decimal::zero());
1184        assert_eq!(from_slice::<Decimal>(br#""1""#).unwrap(), Decimal::one());
1185        assert_eq!(from_slice::<Decimal>(br#""000""#).unwrap(), Decimal::zero());
1186        assert_eq!(from_slice::<Decimal>(br#""001""#).unwrap(), Decimal::one());
1187
1188        assert_eq!(
1189            from_slice::<Decimal>(br#""0.08""#).unwrap(),
1190            Decimal::percent(8)
1191        );
1192        assert_eq!(
1193            from_slice::<Decimal>(br#""0.87""#).unwrap(),
1194            Decimal::percent(87)
1195        );
1196        assert_eq!(
1197            from_slice::<Decimal>(br#""8.76""#).unwrap(),
1198            Decimal::percent(876)
1199        );
1200        assert_eq!(
1201            from_slice::<Decimal>(br#""87.65""#).unwrap(),
1202            Decimal::percent(8765)
1203        );
1204    }
1205}