cosmwasm_std/math/
signed_decimal.rs

1use alloc::string::ToString;
2use core::cmp::Ordering;
3use core::fmt::{self, Write};
4use core::ops::{
5    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
6};
7use core::str::FromStr;
8use serde::{de, ser, Deserialize, Deserializer, Serialize};
9
10use crate::errors::{
11    CheckedFromRatioError, CheckedMultiplyRatioError, DivideByZeroError, OverflowError,
12    OverflowOperation, RoundDownOverflowError, RoundUpOverflowError, StdError,
13};
14use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
15use crate::{Decimal, Decimal256, Int256, SignedDecimal256, __internal::forward_ref_partial_eq};
16
17use super::Fraction;
18use super::Int128;
19
20/// A signed fixed-point decimal value with 18 fractional digits, i.e. SignedDecimal(1_000_000_000_000_000_000) == 1.0
21///
22/// The greatest possible value that can be represented is 170141183460469231731.687303715884105727 (which is (2^127 - 1) / 10^18)
23/// and the smallest is -170141183460469231731.687303715884105728 (which is -2^127 / 10^18).
24#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
25pub struct SignedDecimal(#[schemars(with = "String")] Int128);
26
27forward_ref_partial_eq!(SignedDecimal, SignedDecimal);
28
29#[derive(Debug, PartialEq, Eq, thiserror::Error)]
30#[error("SignedDecimal range exceeded")]
31pub struct SignedDecimalRangeExceeded;
32
33impl SignedDecimal {
34    const DECIMAL_FRACTIONAL: Int128 = Int128::new(1_000_000_000_000_000_000i128); // 1*10**18
35    const DECIMAL_FRACTIONAL_SQUARED: Int128 =
36        Int128::new(1_000_000_000_000_000_000_000_000_000_000_000_000i128); // (1*10**18)**2 = 1*10**36
37
38    /// The number of decimal places. Since decimal types are fixed-point rather than
39    /// floating-point, this is a constant.
40    pub const DECIMAL_PLACES: u32 = 18; // This needs to be an even number.
41
42    /// The largest value that can be represented by this signed decimal type.
43    ///
44    /// # Examples
45    ///
46    /// ```
47    /// # use cosmwasm_std::SignedDecimal;
48    /// assert_eq!(SignedDecimal::MAX.to_string(), "170141183460469231731.687303715884105727");
49    /// ```
50    pub const MAX: Self = Self(Int128::MAX);
51
52    /// The smallest value that can be represented by this signed decimal type.
53    ///
54    /// # Examples
55    ///
56    /// ```
57    /// # use cosmwasm_std::SignedDecimal;
58    /// assert_eq!(SignedDecimal::MIN.to_string(), "-170141183460469231731.687303715884105728");
59    /// ```
60    pub const MIN: Self = Self(Int128::MIN);
61
62    /// Creates a SignedDecimal(value)
63    /// This is equivalent to `SignedDecimal::from_atomics(value, 18)` but usable in a const context.
64    ///
65    /// # Examples
66    ///
67    /// ```
68    /// # use cosmwasm_std::{SignedDecimal, Int128};
69    /// assert_eq!(SignedDecimal::new(Int128::one()).to_string(), "0.000000000000000001");
70    ///
71    /// let atoms = Int128::new(-141_183_460_469_231_731_687_303_715_884_105_727_125);
72    /// let value = SignedDecimal::new(atoms);
73    /// assert_eq!(value.to_string(), "-141183460469231731687.303715884105727125");
74    /// ```
75    #[inline]
76    #[must_use]
77    pub const fn new(value: Int128) -> Self {
78        Self(value)
79    }
80
81    /// Creates a SignedDecimal(Int128(value))
82    /// This is equivalent to `SignedDecimal::from_atomics(value, 18)` but usable in a const context.
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// # use cosmwasm_std::SignedDecimal;
88    /// assert_eq!(SignedDecimal::raw(1234i128).to_string(), "0.000000000000001234");
89    /// ```
90    #[deprecated(
91        since = "3.0.0",
92        note = "Use SignedDecimal::new(Int128::new(value)) instead"
93    )]
94    pub const fn raw(value: i128) -> Self {
95        Self(Int128::new(value))
96    }
97
98    /// Create a 1.0 SignedDecimal
99    #[inline]
100    pub const fn one() -> Self {
101        Self(Self::DECIMAL_FRACTIONAL)
102    }
103
104    /// Create a -1.0 SignedDecimal
105    #[inline]
106    pub const fn negative_one() -> Self {
107        Self(Int128::new(-Self::DECIMAL_FRACTIONAL.i128()))
108    }
109
110    /// Create a 0.0 SignedDecimal
111    #[inline]
112    pub const fn zero() -> Self {
113        Self(Int128::zero())
114    }
115
116    /// Convert x% into SignedDecimal
117    pub fn percent(x: i64) -> Self {
118        Self(((x as i128) * 10_000_000_000_000_000).into())
119    }
120
121    /// Convert permille (x/1000) into SignedDecimal
122    pub fn permille(x: i64) -> Self {
123        Self(((x as i128) * 1_000_000_000_000_000).into())
124    }
125
126    /// Convert basis points (x/10000) into SignedDecimal
127    pub fn bps(x: i64) -> Self {
128        Self(((x as i128) * 100_000_000_000_000).into())
129    }
130
131    /// Creates a signed decimal from a number of atomic units and the number
132    /// of decimal places. The inputs will be converted internally to form
133    /// a signed decimal with 18 decimal places. So the input 123 and 2 will create
134    /// the decimal 1.23.
135    ///
136    /// Using 18 decimal places is slightly more efficient than other values
137    /// as no internal conversion is necessary.
138    ///
139    /// ## Examples
140    ///
141    /// ```
142    /// # use cosmwasm_std::{SignedDecimal, Int128};
143    /// let a = SignedDecimal::from_atomics(Int128::new(1234), 3).unwrap();
144    /// assert_eq!(a.to_string(), "1.234");
145    ///
146    /// let a = SignedDecimal::from_atomics(1234i128, 0).unwrap();
147    /// assert_eq!(a.to_string(), "1234");
148    ///
149    /// let a = SignedDecimal::from_atomics(1i64, 18).unwrap();
150    /// assert_eq!(a.to_string(), "0.000000000000000001");
151    ///
152    /// let a = SignedDecimal::from_atomics(-1i64, 18).unwrap();
153    /// assert_eq!(a.to_string(), "-0.000000000000000001");
154    /// ```
155    pub fn from_atomics(
156        atomics: impl Into<Int128>,
157        decimal_places: u32,
158    ) -> Result<Self, SignedDecimalRangeExceeded> {
159        let atomics = atomics.into();
160        const TEN: Int128 = Int128::new(10);
161        Ok(match decimal_places.cmp(&(Self::DECIMAL_PLACES)) {
162            Ordering::Less => {
163                let digits = (Self::DECIMAL_PLACES) - decimal_places; // No overflow because decimal_places < DECIMAL_PLACES
164                let factor = TEN.checked_pow(digits).unwrap(); // Safe because digits <= 17
165                Self(
166                    atomics
167                        .checked_mul(factor)
168                        .map_err(|_| SignedDecimalRangeExceeded)?,
169                )
170            }
171            Ordering::Equal => Self(atomics),
172            Ordering::Greater => {
173                let digits = decimal_places - (Self::DECIMAL_PLACES); // No overflow because decimal_places > DECIMAL_PLACES
174                if let Ok(factor) = TEN.checked_pow(digits) {
175                    Self(atomics.checked_div(factor).unwrap()) // Safe because factor cannot be zero
176                } else {
177                    // In this case `factor` exceeds the Int128 range.
178                    // Any Int128 `x` divided by `factor` with `factor > Int128::MAX` is 0.
179                    // Try e.g. Python3: `(2**128-1) // 2**128`
180                    Self(Int128::zero())
181                }
182            }
183        })
184    }
185
186    /// Returns the ratio (numerator / denominator) as a SignedDecimal
187    ///
188    /// # Examples
189    ///
190    /// ```
191    /// # use cosmwasm_std::SignedDecimal;
192    /// assert_eq!(
193    ///     SignedDecimal::from_ratio(1, 3).to_string(),
194    ///     "0.333333333333333333"
195    /// );
196    /// ```
197    pub fn from_ratio(numerator: impl Into<Int128>, denominator: impl Into<Int128>) -> Self {
198        match SignedDecimal::checked_from_ratio(numerator, denominator) {
199            Ok(value) => value,
200            Err(CheckedFromRatioError::DivideByZero) => {
201                panic!("Denominator must not be zero")
202            }
203            Err(CheckedFromRatioError::Overflow) => panic!("Multiplication overflow"),
204        }
205    }
206
207    /// Returns the ratio (numerator / denominator) as a SignedDecimal
208    ///
209    /// # Examples
210    ///
211    /// ```
212    /// # use cosmwasm_std::{SignedDecimal, CheckedFromRatioError};
213    /// assert_eq!(
214    ///     SignedDecimal::checked_from_ratio(1, 3).unwrap().to_string(),
215    ///     "0.333333333333333333"
216    /// );
217    /// assert_eq!(
218    ///     SignedDecimal::checked_from_ratio(1, 0),
219    ///     Err(CheckedFromRatioError::DivideByZero)
220    /// );
221    /// ```
222    pub fn checked_from_ratio(
223        numerator: impl Into<Int128>,
224        denominator: impl Into<Int128>,
225    ) -> Result<Self, CheckedFromRatioError> {
226        let numerator: Int128 = numerator.into();
227        let denominator: Int128 = denominator.into();
228        match numerator.checked_multiply_ratio(Self::DECIMAL_FRACTIONAL, denominator) {
229            Ok(ratio) => {
230                // numerator * DECIMAL_FRACTIONAL / denominator
231                Ok(SignedDecimal(ratio))
232            }
233            Err(CheckedMultiplyRatioError::Overflow) => Err(CheckedFromRatioError::Overflow),
234            Err(CheckedMultiplyRatioError::DivideByZero) => {
235                Err(CheckedFromRatioError::DivideByZero)
236            }
237        }
238    }
239
240    /// Returns `true` if the number is 0
241    #[must_use]
242    pub const fn is_zero(&self) -> bool {
243        self.0.is_zero()
244    }
245
246    /// Returns `true` if the number is negative (< 0)
247    #[must_use]
248    pub const fn is_negative(&self) -> bool {
249        self.0.i128() < 0
250    }
251
252    /// A decimal is an integer of atomic units plus a number that specifies the
253    /// position of the decimal dot. So any decimal can be expressed as two numbers.
254    ///
255    /// ## Examples
256    ///
257    /// ```
258    /// # use cosmwasm_std::{SignedDecimal, Int128};
259    /// # use core::str::FromStr;
260    /// // Value with whole and fractional part
261    /// let a = SignedDecimal::from_str("1.234").unwrap();
262    /// assert_eq!(a.decimal_places(), 18);
263    /// assert_eq!(a.atomics(), Int128::new(1234000000000000000));
264    ///
265    /// // Smallest possible value
266    /// let b = SignedDecimal::from_str("0.000000000000000001").unwrap();
267    /// assert_eq!(b.decimal_places(), 18);
268    /// assert_eq!(b.atomics(), Int128::new(1));
269    /// ```
270    #[must_use]
271    #[inline]
272    pub const fn atomics(&self) -> Int128 {
273        self.0
274    }
275
276    /// The number of decimal places. This is a constant value for now
277    /// but this could potentially change as the type evolves.
278    ///
279    /// See also [`SignedDecimal::atomics()`].
280    #[must_use]
281    #[inline]
282    pub const fn decimal_places(&self) -> u32 {
283        Self::DECIMAL_PLACES
284    }
285
286    /// Rounds value by truncating the decimal places.
287    ///
288    /// # Examples
289    ///
290    /// ```
291    /// # use cosmwasm_std::SignedDecimal;
292    /// # use core::str::FromStr;
293    /// assert!(SignedDecimal::from_str("0.6").unwrap().trunc().is_zero());
294    /// assert_eq!(SignedDecimal::from_str("-5.8").unwrap().trunc().to_string(), "-5");
295    /// ```
296    #[must_use = "this returns the result of the operation, without modifying the original"]
297    pub fn trunc(&self) -> Self {
298        Self((self.0 / Self::DECIMAL_FRACTIONAL) * Self::DECIMAL_FRACTIONAL)
299    }
300
301    /// Rounds value down after decimal places. Panics on overflow.
302    ///
303    /// # Examples
304    ///
305    /// ```
306    /// # use cosmwasm_std::SignedDecimal;
307    /// # use core::str::FromStr;
308    /// assert!(SignedDecimal::from_str("0.6").unwrap().floor().is_zero());
309    /// assert_eq!(SignedDecimal::from_str("-5.2").unwrap().floor().to_string(), "-6");
310    /// ```
311    #[must_use = "this returns the result of the operation, without modifying the original"]
312    pub fn floor(&self) -> Self {
313        match self.checked_floor() {
314            Ok(value) => value,
315            Err(_) => panic!("attempt to floor with overflow"),
316        }
317    }
318
319    /// Rounds value down after decimal places.
320    pub fn checked_floor(&self) -> Result<Self, RoundDownOverflowError> {
321        if self.is_negative() {
322            let truncated = self.trunc();
323
324            if truncated != self {
325                truncated
326                    .checked_sub(SignedDecimal::one())
327                    .map_err(|_| RoundDownOverflowError)
328            } else {
329                Ok(truncated)
330            }
331        } else {
332            Ok(self.trunc())
333        }
334    }
335
336    /// Rounds value up after decimal places. Panics on overflow.
337    ///
338    /// # Examples
339    ///
340    /// ```
341    /// # use cosmwasm_std::SignedDecimal;
342    /// # use core::str::FromStr;
343    /// assert_eq!(SignedDecimal::from_str("0.2").unwrap().ceil(), SignedDecimal::one());
344    /// assert_eq!(SignedDecimal::from_str("-5.8").unwrap().ceil().to_string(), "-5");
345    /// ```
346    #[must_use = "this returns the result of the operation, without modifying the original"]
347    pub fn ceil(&self) -> Self {
348        match self.checked_ceil() {
349            Ok(value) => value,
350            Err(_) => panic!("attempt to ceil with overflow"),
351        }
352    }
353
354    /// Rounds value up after decimal places. Returns OverflowError on overflow.
355    pub fn checked_ceil(&self) -> Result<Self, RoundUpOverflowError> {
356        let floor = self.floor();
357        if floor == self {
358            Ok(floor)
359        } else {
360            floor
361                .checked_add(SignedDecimal::one())
362                .map_err(|_| RoundUpOverflowError)
363        }
364    }
365
366    /// Computes `self + other`, returning an `OverflowError` if an overflow occurred.
367    pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
368        self.0
369            .checked_add(other.0)
370            .map(Self)
371            .map_err(|_| OverflowError::new(OverflowOperation::Add))
372    }
373
374    /// Computes `self - other`, returning an `OverflowError` if an overflow occurred.
375    pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
376        self.0
377            .checked_sub(other.0)
378            .map(Self)
379            .map_err(|_| OverflowError::new(OverflowOperation::Sub))
380    }
381
382    /// Multiplies one `SignedDecimal` by another, returning an `OverflowError` if an overflow occurred.
383    pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
384        let result_as_int256 =
385            self.numerator().full_mul(other.numerator()) / Int256::from(Self::DECIMAL_FRACTIONAL);
386        result_as_int256
387            .try_into()
388            .map(Self)
389            .map_err(|_| OverflowError::new(OverflowOperation::Mul))
390    }
391
392    /// Raises a value to the power of `exp`, panics if an overflow occurred.
393    #[must_use = "this returns the result of the operation, without modifying the original"]
394    pub fn pow(self, exp: u32) -> Self {
395        match self.checked_pow(exp) {
396            Ok(value) => value,
397            Err(_) => panic!("Multiplication overflow"),
398        }
399    }
400
401    /// Raises a value to the power of `exp`, returning an `OverflowError` if an overflow occurred.
402    pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
403        // This uses the exponentiation by squaring algorithm:
404        // https://en.wikipedia.org/wiki/Exponentiation_by_squaring#Basic_method
405
406        fn inner(mut x: SignedDecimal, mut n: u32) -> Result<SignedDecimal, OverflowError> {
407            if n == 0 {
408                return Ok(SignedDecimal::one());
409            }
410
411            let mut y = SignedDecimal::one();
412
413            while n > 1 {
414                if n % 2 == 0 {
415                    x = x.checked_mul(x)?;
416                    n /= 2;
417                } else {
418                    y = x.checked_mul(y)?;
419                    x = x.checked_mul(x)?;
420                    n = (n - 1) / 2;
421                }
422            }
423
424            Ok(x * y)
425        }
426
427        inner(self, exp).map_err(|_| OverflowError::new(OverflowOperation::Pow))
428    }
429
430    pub fn checked_div(self, other: Self) -> Result<Self, CheckedFromRatioError> {
431        SignedDecimal::checked_from_ratio(self.numerator(), other.numerator())
432    }
433
434    /// Computes `self % other`, returning an `DivideByZeroError` if `other == 0`.
435    pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
436        self.0
437            .checked_rem(other.0)
438            .map(Self)
439            .map_err(|_| DivideByZeroError)
440    }
441
442    #[must_use = "this returns the result of the operation, without modifying the original"]
443    pub const fn abs_diff(self, other: Self) -> Decimal {
444        Decimal::new(self.0.abs_diff(other.0))
445    }
446
447    #[must_use = "this returns the result of the operation, without modifying the original"]
448    pub fn saturating_add(self, other: Self) -> Self {
449        Self(self.0.saturating_add(other.0))
450    }
451
452    #[must_use = "this returns the result of the operation, without modifying the original"]
453    pub fn saturating_sub(self, other: Self) -> Self {
454        Self(self.0.saturating_sub(other.0))
455    }
456
457    #[must_use = "this returns the result of the operation, without modifying the original"]
458    pub fn saturating_mul(self, other: Self) -> Self {
459        match self.checked_mul(other) {
460            Ok(value) => value,
461            Err(_) => {
462                // both negative or both positive results in positive number, otherwise negative
463                if self.is_negative() == other.is_negative() {
464                    Self::MAX
465                } else {
466                    Self::MIN
467                }
468            }
469        }
470    }
471
472    #[must_use = "this returns the result of the operation, without modifying the original"]
473    pub fn saturating_pow(self, exp: u32) -> Self {
474        match self.checked_pow(exp) {
475            Ok(value) => value,
476            Err(_) => {
477                // odd exponent of negative number results in negative number
478                // everything else results in positive number
479                if self.is_negative() && exp % 2 == 1 {
480                    Self::MIN
481                } else {
482                    Self::MAX
483                }
484            }
485        }
486    }
487
488    /// Converts this decimal to a signed integer by rounding down
489    /// to the next integer, e.g. 22.5 becomes 22 and -1.2 becomes -2.
490    ///
491    /// ## Examples
492    ///
493    /// ```
494    /// use core::str::FromStr;
495    /// use cosmwasm_std::{SignedDecimal, Int128};
496    ///
497    /// let d = SignedDecimal::from_str("12.345").unwrap();
498    /// assert_eq!(d.to_int_floor(), Int128::new(12));
499    ///
500    /// let d = SignedDecimal::from_str("-12.999").unwrap();
501    /// assert_eq!(d.to_int_floor(), Int128::new(-13));
502    ///
503    /// let d = SignedDecimal::from_str("-0.05").unwrap();
504    /// assert_eq!(d.to_int_floor(), Int128::new(-1));
505    /// ```
506    #[must_use = "this returns the result of the operation, without modifying the original"]
507    pub fn to_int_floor(self) -> Int128 {
508        if self.is_negative() {
509            // Using `x.to_int_floor() = -(-x).to_int_ceil()` for a negative `x`,
510            // but avoiding overflow by implementing the formula from `to_int_ceil` directly.
511            let x = self.0;
512            let y = Self::DECIMAL_FRACTIONAL;
513            // making sure not to negate `x`, as this would overflow
514            -Int128::one() - ((-Int128::one() - x) / y)
515        } else {
516            self.to_int_trunc()
517        }
518    }
519
520    /// Converts this decimal to a signed integer by truncating
521    /// the fractional part, e.g. 22.5 becomes 22.
522    ///
523    /// ## Examples
524    ///
525    /// ```
526    /// use core::str::FromStr;
527    /// use cosmwasm_std::{SignedDecimal, Int128};
528    ///
529    /// let d = SignedDecimal::from_str("12.345").unwrap();
530    /// assert_eq!(d.to_int_trunc(), Int128::new(12));
531    ///
532    /// let d = SignedDecimal::from_str("-12.999").unwrap();
533    /// assert_eq!(d.to_int_trunc(), Int128::new(-12));
534    ///
535    /// let d = SignedDecimal::from_str("75.0").unwrap();
536    /// assert_eq!(d.to_int_trunc(), Int128::new(75));
537    /// ```
538    #[must_use = "this returns the result of the operation, without modifying the original"]
539    pub fn to_int_trunc(self) -> Int128 {
540        self.0 / Self::DECIMAL_FRACTIONAL
541    }
542
543    /// Converts this decimal to a signed integer by rounding up
544    /// to the next integer, e.g. 22.3 becomes 23 and -1.2 becomes -1.
545    ///
546    /// ## Examples
547    ///
548    /// ```
549    /// use core::str::FromStr;
550    /// use cosmwasm_std::{SignedDecimal, Int128};
551    ///
552    /// let d = SignedDecimal::from_str("12.345").unwrap();
553    /// assert_eq!(d.to_int_ceil(), Int128::new(13));
554    ///
555    /// let d = SignedDecimal::from_str("-12.999").unwrap();
556    /// assert_eq!(d.to_int_ceil(), Int128::new(-12));
557    ///
558    /// let d = SignedDecimal::from_str("75.0").unwrap();
559    /// assert_eq!(d.to_int_ceil(), Int128::new(75));
560    /// ```
561    #[must_use = "this returns the result of the operation, without modifying the original"]
562    pub fn to_int_ceil(self) -> Int128 {
563        if self.is_negative() {
564            self.to_int_trunc()
565        } else {
566            // Using `q = 1 + ((x - 1) / y); // if x != 0` with unsigned integers x, y, q
567            // from https://stackoverflow.com/a/2745086/2013738. We know `x + y` CAN overflow.
568            let x = self.0;
569            let y = Self::DECIMAL_FRACTIONAL;
570            if x.is_zero() {
571                Int128::zero()
572            } else {
573                Int128::one() + ((x - Int128::one()) / y)
574            }
575        }
576    }
577}
578
579impl Fraction<Int128> for SignedDecimal {
580    #[inline]
581    fn numerator(&self) -> Int128 {
582        self.0
583    }
584
585    #[inline]
586    fn denominator(&self) -> Int128 {
587        Self::DECIMAL_FRACTIONAL
588    }
589
590    /// Returns the multiplicative inverse `1/d` for decimal `d`.
591    ///
592    /// If `d` is zero, none is returned.
593    fn inv(&self) -> Option<Self> {
594        if self.is_zero() {
595            None
596        } else {
597            // Let self be p/q with p = self.0 and q = DECIMAL_FRACTIONAL.
598            // Now we calculate the inverse a/b = q/p such that b = DECIMAL_FRACTIONAL. Then
599            // `a = DECIMAL_FRACTIONAL*DECIMAL_FRACTIONAL / self.0`.
600            Some(SignedDecimal(Self::DECIMAL_FRACTIONAL_SQUARED / self.0))
601        }
602    }
603}
604
605impl Neg for SignedDecimal {
606    type Output = Self;
607
608    fn neg(self) -> Self::Output {
609        Self(-self.0)
610    }
611}
612
613impl TryFrom<SignedDecimal256> for SignedDecimal {
614    type Error = SignedDecimalRangeExceeded;
615
616    fn try_from(value: SignedDecimal256) -> Result<Self, Self::Error> {
617        value
618            .atomics()
619            .try_into()
620            .map(SignedDecimal)
621            .map_err(|_| SignedDecimalRangeExceeded)
622    }
623}
624
625impl TryFrom<Decimal> for SignedDecimal {
626    type Error = SignedDecimalRangeExceeded;
627
628    fn try_from(value: Decimal) -> Result<Self, Self::Error> {
629        value
630            .atomics()
631            .try_into()
632            .map(SignedDecimal)
633            .map_err(|_| SignedDecimalRangeExceeded)
634    }
635}
636
637impl TryFrom<Decimal256> for SignedDecimal {
638    type Error = SignedDecimalRangeExceeded;
639
640    fn try_from(value: Decimal256) -> Result<Self, Self::Error> {
641        value
642            .atomics()
643            .try_into()
644            .map(SignedDecimal)
645            .map_err(|_| SignedDecimalRangeExceeded)
646    }
647}
648
649impl TryFrom<Int128> for SignedDecimal {
650    type Error = SignedDecimalRangeExceeded;
651
652    #[inline]
653    fn try_from(value: Int128) -> Result<Self, Self::Error> {
654        Self::from_atomics(value, 0)
655    }
656}
657
658impl FromStr for SignedDecimal {
659    type Err = StdError;
660
661    /// Converts the decimal string to a SignedDecimal
662    /// Possible inputs: "1.23", "1", "000012", "1.123000000", "-1.12300"
663    /// Disallowed: "", ".23"
664    ///
665    /// This never performs any kind of rounding.
666    /// More than DECIMAL_PLACES fractional digits, even zeros, result in an error.
667    fn from_str(input: &str) -> Result<Self, Self::Err> {
668        let mut parts_iter = input.split('.');
669
670        let whole_part = parts_iter.next().unwrap(); // split always returns at least one element
671        let is_neg = whole_part.starts_with('-');
672
673        let whole = whole_part
674            .parse::<Int128>()
675            .map_err(|_| StdError::generic_err("Error parsing whole"))?;
676        let mut atomics = whole
677            .checked_mul(Self::DECIMAL_FRACTIONAL)
678            .map_err(|_| StdError::generic_err("Value too big"))?;
679
680        if let Some(fractional_part) = parts_iter.next() {
681            let fractional = fractional_part
682                .parse::<u64>() // u64 is enough for 18 decimal places
683                .map_err(|_| StdError::generic_err("Error parsing fractional"))?;
684            let exp = (Self::DECIMAL_PLACES.checked_sub(fractional_part.len() as u32)).ok_or_else(
685                || {
686                    StdError::generic_err(format!(
687                        "Cannot parse more than {} fractional digits",
688                        Self::DECIMAL_PLACES
689                    ))
690                },
691            )?;
692            debug_assert!(exp <= Self::DECIMAL_PLACES);
693            let fractional_factor = Int128::from(10i128.pow(exp));
694
695            // This multiplication can't overflow because
696            // fractional < 10^DECIMAL_PLACES && fractional_factor <= 10^DECIMAL_PLACES
697            let fractional_part = Int128::from(fractional)
698                .checked_mul(fractional_factor)
699                .unwrap();
700
701            // for negative numbers, we need to subtract the fractional part
702            atomics = if is_neg {
703                atomics.checked_sub(fractional_part)
704            } else {
705                atomics.checked_add(fractional_part)
706            }
707            .map_err(|_| StdError::generic_err("Value too big"))?;
708        }
709
710        if parts_iter.next().is_some() {
711            return Err(StdError::generic_err("Unexpected number of dots"));
712        }
713
714        Ok(SignedDecimal(atomics))
715    }
716}
717
718impl fmt::Display for SignedDecimal {
719    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
720        let whole = (self.0) / Self::DECIMAL_FRACTIONAL;
721        let fractional = (self.0).checked_rem(Self::DECIMAL_FRACTIONAL).unwrap();
722
723        if fractional.is_zero() {
724            write!(f, "{whole}")
725        } else {
726            let fractional_string = format!(
727                "{:0>padding$}",
728                fractional.abs(), // fractional should always be printed as positive
729                padding = Self::DECIMAL_PLACES as usize
730            );
731            if self.is_negative() {
732                f.write_char('-')?;
733            }
734            write!(
735                f,
736                "{whole}.{fractional}",
737                whole = whole.abs(),
738                fractional = fractional_string.trim_end_matches('0')
739            )
740        }
741    }
742}
743
744impl fmt::Debug for SignedDecimal {
745    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
746        write!(f, "SignedDecimal({self})")
747    }
748}
749
750impl Add for SignedDecimal {
751    type Output = Self;
752
753    fn add(self, other: Self) -> Self {
754        SignedDecimal(self.0 + other.0)
755    }
756}
757forward_ref_binop!(impl Add, add for SignedDecimal, SignedDecimal);
758
759impl AddAssign for SignedDecimal {
760    fn add_assign(&mut self, rhs: SignedDecimal) {
761        *self = *self + rhs;
762    }
763}
764forward_ref_op_assign!(impl AddAssign, add_assign for SignedDecimal, SignedDecimal);
765
766impl Sub for SignedDecimal {
767    type Output = Self;
768
769    fn sub(self, other: Self) -> Self {
770        SignedDecimal(self.0 - other.0)
771    }
772}
773forward_ref_binop!(impl Sub, sub for SignedDecimal, SignedDecimal);
774
775impl SubAssign for SignedDecimal {
776    fn sub_assign(&mut self, rhs: SignedDecimal) {
777        *self = *self - rhs;
778    }
779}
780forward_ref_op_assign!(impl SubAssign, sub_assign for SignedDecimal, SignedDecimal);
781
782impl Mul for SignedDecimal {
783    type Output = Self;
784
785    #[allow(clippy::suspicious_arithmetic_impl)]
786    fn mul(self, other: Self) -> Self {
787        // SignedDecimals are fractions. We can multiply two decimals a and b
788        // via
789        //       (a.numerator() * b.numerator()) / (a.denominator() * b.denominator())
790        //     = (a.numerator() * b.numerator()) / a.denominator() / b.denominator()
791
792        let result_as_int256 =
793            self.numerator().full_mul(other.numerator()) / Int256::from(Self::DECIMAL_FRACTIONAL);
794        match result_as_int256.try_into() {
795            Ok(result) => Self(result),
796            Err(_) => panic!("attempt to multiply with overflow"),
797        }
798    }
799}
800forward_ref_binop!(impl Mul, mul for SignedDecimal, SignedDecimal);
801
802impl MulAssign for SignedDecimal {
803    fn mul_assign(&mut self, rhs: SignedDecimal) {
804        *self = *self * rhs;
805    }
806}
807forward_ref_op_assign!(impl MulAssign, mul_assign for SignedDecimal, SignedDecimal);
808
809impl Div for SignedDecimal {
810    type Output = Self;
811
812    fn div(self, other: Self) -> Self {
813        match SignedDecimal::checked_from_ratio(self.numerator(), other.numerator()) {
814            Ok(ratio) => ratio,
815            Err(CheckedFromRatioError::DivideByZero) => {
816                panic!("Division failed - denominator must not be zero")
817            }
818            Err(CheckedFromRatioError::Overflow) => {
819                panic!("Division failed - multiplication overflow")
820            }
821        }
822    }
823}
824forward_ref_binop!(impl Div, div for SignedDecimal, SignedDecimal);
825
826impl DivAssign for SignedDecimal {
827    fn div_assign(&mut self, rhs: SignedDecimal) {
828        *self = *self / rhs;
829    }
830}
831forward_ref_op_assign!(impl DivAssign, div_assign for SignedDecimal, SignedDecimal);
832
833impl Div<Int128> for SignedDecimal {
834    type Output = Self;
835
836    fn div(self, rhs: Int128) -> Self::Output {
837        SignedDecimal(self.0 / rhs)
838    }
839}
840
841impl DivAssign<Int128> for SignedDecimal {
842    fn div_assign(&mut self, rhs: Int128) {
843        self.0 /= rhs;
844    }
845}
846
847impl Rem for SignedDecimal {
848    type Output = Self;
849
850    /// # Panics
851    ///
852    /// This operation will panic if `rhs` is zero
853    #[inline]
854    fn rem(self, rhs: Self) -> Self {
855        Self(self.0.rem(rhs.0))
856    }
857}
858forward_ref_binop!(impl Rem, rem for SignedDecimal, SignedDecimal);
859
860impl RemAssign<SignedDecimal> for SignedDecimal {
861    fn rem_assign(&mut self, rhs: SignedDecimal) {
862        *self = *self % rhs;
863    }
864}
865forward_ref_op_assign!(impl RemAssign, rem_assign for SignedDecimal, SignedDecimal);
866
867impl<A> core::iter::Sum<A> for SignedDecimal
868where
869    Self: Add<A, Output = Self>,
870{
871    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
872        iter.fold(Self::zero(), Add::add)
873    }
874}
875
876/// Serializes as a decimal string
877impl Serialize for SignedDecimal {
878    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
879    where
880        S: ser::Serializer,
881    {
882        serializer.serialize_str(&self.to_string())
883    }
884}
885
886/// Deserializes as a base64 string
887impl<'de> Deserialize<'de> for SignedDecimal {
888    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
889    where
890        D: Deserializer<'de>,
891    {
892        deserializer.deserialize_str(SignedDecimalVisitor)
893    }
894}
895
896struct SignedDecimalVisitor;
897
898impl de::Visitor<'_> for SignedDecimalVisitor {
899    type Value = SignedDecimal;
900
901    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
902        formatter.write_str("string-encoded decimal")
903    }
904
905    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
906    where
907        E: de::Error,
908    {
909        match SignedDecimal::from_str(v) {
910            Ok(d) => Ok(d),
911            Err(e) => Err(E::custom(format_args!("Error parsing decimal '{v}': {e}"))),
912        }
913    }
914}
915
916#[cfg(test)]
917mod tests {
918    use crate::Uint128;
919
920    use super::*;
921
922    use alloc::vec::Vec;
923
924    fn dec(input: &str) -> SignedDecimal {
925        SignedDecimal::from_str(input).unwrap()
926    }
927
928    #[test]
929    fn signed_decimal_new() {
930        let expected = Int128::from(300i128);
931        assert_eq!(SignedDecimal::new(expected).0, expected);
932
933        let expected = Int128::from(-300i128);
934        assert_eq!(SignedDecimal::new(expected).0, expected);
935    }
936
937    #[test]
938    #[allow(deprecated)]
939    fn signed_decimal_raw() {
940        let value = 300i128;
941        assert_eq!(SignedDecimal::raw(value).0.i128(), value);
942
943        let value = -300i128;
944        assert_eq!(SignedDecimal::raw(value).0.i128(), value);
945    }
946
947    #[test]
948    fn signed_decimal_one() {
949        let value = SignedDecimal::one();
950        assert_eq!(value.0, SignedDecimal::DECIMAL_FRACTIONAL);
951    }
952
953    #[test]
954    fn signed_decimal_zero() {
955        let value = SignedDecimal::zero();
956        assert!(value.0.is_zero());
957    }
958
959    #[test]
960    fn signed_decimal_percent() {
961        let value = SignedDecimal::percent(50);
962        assert_eq!(
963            value.0,
964            SignedDecimal::DECIMAL_FRACTIONAL / Int128::from(2u8)
965        );
966
967        let value = SignedDecimal::percent(-50);
968        assert_eq!(
969            value.0,
970            SignedDecimal::DECIMAL_FRACTIONAL / Int128::from(-2i8)
971        );
972    }
973
974    #[test]
975    fn signed_decimal_permille() {
976        let value = SignedDecimal::permille(125);
977        assert_eq!(
978            value.0,
979            SignedDecimal::DECIMAL_FRACTIONAL / Int128::from(8u8)
980        );
981
982        let value = SignedDecimal::permille(-125);
983        assert_eq!(
984            value.0,
985            SignedDecimal::DECIMAL_FRACTIONAL / Int128::from(-8i8)
986        );
987    }
988
989    #[test]
990    fn signed_decimal_bps() {
991        let value = SignedDecimal::bps(125);
992        assert_eq!(
993            value.0,
994            SignedDecimal::DECIMAL_FRACTIONAL / Int128::from(80u8)
995        );
996
997        let value = SignedDecimal::bps(-125);
998        assert_eq!(
999            value.0,
1000            SignedDecimal::DECIMAL_FRACTIONAL / Int128::from(-80i8)
1001        );
1002    }
1003
1004    #[test]
1005    fn try_from_integer() {
1006        let int = Int128::new(0xDEADBEEF);
1007        let decimal = SignedDecimal::try_from(int).unwrap();
1008        assert_eq!(int.to_string(), decimal.to_string());
1009    }
1010
1011    #[test]
1012    fn signed_decimal_from_atomics_works() {
1013        let one = SignedDecimal::one();
1014        let two = one + one;
1015        let neg_one = SignedDecimal::negative_one();
1016
1017        assert_eq!(SignedDecimal::from_atomics(1i128, 0).unwrap(), one);
1018        assert_eq!(SignedDecimal::from_atomics(10i128, 1).unwrap(), one);
1019        assert_eq!(SignedDecimal::from_atomics(100i128, 2).unwrap(), one);
1020        assert_eq!(SignedDecimal::from_atomics(1000i128, 3).unwrap(), one);
1021        assert_eq!(
1022            SignedDecimal::from_atomics(1000000000000000000i128, 18).unwrap(),
1023            one
1024        );
1025        assert_eq!(
1026            SignedDecimal::from_atomics(10000000000000000000i128, 19).unwrap(),
1027            one
1028        );
1029        assert_eq!(
1030            SignedDecimal::from_atomics(100000000000000000000i128, 20).unwrap(),
1031            one
1032        );
1033
1034        assert_eq!(SignedDecimal::from_atomics(2i128, 0).unwrap(), two);
1035        assert_eq!(SignedDecimal::from_atomics(20i128, 1).unwrap(), two);
1036        assert_eq!(SignedDecimal::from_atomics(200i128, 2).unwrap(), two);
1037        assert_eq!(SignedDecimal::from_atomics(2000i128, 3).unwrap(), two);
1038        assert_eq!(
1039            SignedDecimal::from_atomics(2000000000000000000i128, 18).unwrap(),
1040            two
1041        );
1042        assert_eq!(
1043            SignedDecimal::from_atomics(20000000000000000000i128, 19).unwrap(),
1044            two
1045        );
1046        assert_eq!(
1047            SignedDecimal::from_atomics(200000000000000000000i128, 20).unwrap(),
1048            two
1049        );
1050
1051        assert_eq!(SignedDecimal::from_atomics(-1i128, 0).unwrap(), neg_one);
1052        assert_eq!(SignedDecimal::from_atomics(-10i128, 1).unwrap(), neg_one);
1053        assert_eq!(
1054            SignedDecimal::from_atomics(-100000000000000000000i128, 20).unwrap(),
1055            neg_one
1056        );
1057
1058        // Cuts decimal digits (20 provided but only 18 can be stored)
1059        assert_eq!(
1060            SignedDecimal::from_atomics(4321i128, 20).unwrap(),
1061            SignedDecimal::from_str("0.000000000000000043").unwrap()
1062        );
1063        assert_eq!(
1064            SignedDecimal::from_atomics(-4321i128, 20).unwrap(),
1065            SignedDecimal::from_str("-0.000000000000000043").unwrap()
1066        );
1067        assert_eq!(
1068            SignedDecimal::from_atomics(6789i128, 20).unwrap(),
1069            SignedDecimal::from_str("0.000000000000000067").unwrap()
1070        );
1071        assert_eq!(
1072            SignedDecimal::from_atomics(i128::MAX, 38).unwrap(),
1073            SignedDecimal::from_str("1.701411834604692317").unwrap()
1074        );
1075        assert_eq!(
1076            SignedDecimal::from_atomics(i128::MAX, 39).unwrap(),
1077            SignedDecimal::from_str("0.170141183460469231").unwrap()
1078        );
1079        assert_eq!(
1080            SignedDecimal::from_atomics(i128::MAX, 45).unwrap(),
1081            SignedDecimal::from_str("0.000000170141183460").unwrap()
1082        );
1083        assert_eq!(
1084            SignedDecimal::from_atomics(i128::MAX, 51).unwrap(),
1085            SignedDecimal::from_str("0.000000000000170141").unwrap()
1086        );
1087        assert_eq!(
1088            SignedDecimal::from_atomics(i128::MAX, 56).unwrap(),
1089            SignedDecimal::from_str("0.000000000000000001").unwrap()
1090        );
1091        assert_eq!(
1092            SignedDecimal::from_atomics(i128::MAX, 57).unwrap(),
1093            SignedDecimal::from_str("0.000000000000000000").unwrap()
1094        );
1095        assert_eq!(
1096            SignedDecimal::from_atomics(i128::MAX, u32::MAX).unwrap(),
1097            SignedDecimal::from_str("0.000000000000000000").unwrap()
1098        );
1099
1100        // Can be used with max value
1101        let max = SignedDecimal::MAX;
1102        assert_eq!(
1103            SignedDecimal::from_atomics(max.atomics(), max.decimal_places()).unwrap(),
1104            max
1105        );
1106
1107        // Can be used with min value
1108        let min = SignedDecimal::MIN;
1109        assert_eq!(
1110            SignedDecimal::from_atomics(min.atomics(), min.decimal_places()).unwrap(),
1111            min
1112        );
1113
1114        // Overflow is only possible with digits < 18
1115        let result = SignedDecimal::from_atomics(i128::MAX, 17);
1116        assert_eq!(result.unwrap_err(), SignedDecimalRangeExceeded);
1117    }
1118
1119    #[test]
1120    fn signed_decimal_from_ratio_works() {
1121        // 1.0
1122        assert_eq!(
1123            SignedDecimal::from_ratio(1i128, 1i128),
1124            SignedDecimal::one()
1125        );
1126        assert_eq!(
1127            SignedDecimal::from_ratio(53i128, 53i128),
1128            SignedDecimal::one()
1129        );
1130        assert_eq!(
1131            SignedDecimal::from_ratio(125i128, 125i128),
1132            SignedDecimal::one()
1133        );
1134
1135        // -1.0
1136        assert_eq!(
1137            SignedDecimal::from_ratio(-1i128, 1i128),
1138            SignedDecimal::negative_one()
1139        );
1140        assert_eq!(
1141            SignedDecimal::from_ratio(-53i128, 53i128),
1142            SignedDecimal::negative_one()
1143        );
1144        assert_eq!(
1145            SignedDecimal::from_ratio(125i128, -125i128),
1146            SignedDecimal::negative_one()
1147        );
1148
1149        // 1.5
1150        assert_eq!(
1151            SignedDecimal::from_ratio(3i128, 2i128),
1152            SignedDecimal::percent(150)
1153        );
1154        assert_eq!(
1155            SignedDecimal::from_ratio(150i128, 100i128),
1156            SignedDecimal::percent(150)
1157        );
1158        assert_eq!(
1159            SignedDecimal::from_ratio(333i128, 222i128),
1160            SignedDecimal::percent(150)
1161        );
1162
1163        // 0.125
1164        assert_eq!(
1165            SignedDecimal::from_ratio(1i64, 8i64),
1166            SignedDecimal::permille(125)
1167        );
1168        assert_eq!(
1169            SignedDecimal::from_ratio(125i64, 1000i64),
1170            SignedDecimal::permille(125)
1171        );
1172
1173        // -0.125
1174        assert_eq!(
1175            SignedDecimal::from_ratio(-1i64, 8i64),
1176            SignedDecimal::permille(-125)
1177        );
1178        assert_eq!(
1179            SignedDecimal::from_ratio(125i64, -1000i64),
1180            SignedDecimal::permille(-125)
1181        );
1182
1183        // 1/3 (result floored)
1184        assert_eq!(
1185            SignedDecimal::from_ratio(1i64, 3i64),
1186            SignedDecimal(Int128::from(333_333_333_333_333_333i128))
1187        );
1188
1189        // 2/3 (result floored)
1190        assert_eq!(
1191            SignedDecimal::from_ratio(2i64, 3i64),
1192            SignedDecimal(Int128::from(666_666_666_666_666_666i128))
1193        );
1194
1195        // large inputs
1196        assert_eq!(
1197            SignedDecimal::from_ratio(0i128, i128::MAX),
1198            SignedDecimal::zero()
1199        );
1200        assert_eq!(
1201            SignedDecimal::from_ratio(i128::MAX, i128::MAX),
1202            SignedDecimal::one()
1203        );
1204        // 170141183460469231731 is the largest integer <= SignedDecimal::MAX
1205        assert_eq!(
1206            SignedDecimal::from_ratio(170141183460469231731i128, 1i128),
1207            SignedDecimal::from_str("170141183460469231731").unwrap()
1208        );
1209    }
1210
1211    #[test]
1212    #[should_panic(expected = "Denominator must not be zero")]
1213    fn signed_decimal_from_ratio_panics_for_zero_denominator() {
1214        SignedDecimal::from_ratio(1i128, 0i128);
1215    }
1216
1217    #[test]
1218    #[should_panic(expected = "Multiplication overflow")]
1219    fn signed_decimal_from_ratio_panics_for_mul_overflow() {
1220        SignedDecimal::from_ratio(i128::MAX, 1i128);
1221    }
1222
1223    #[test]
1224    fn signed_decimal_checked_from_ratio_does_not_panic() {
1225        assert_eq!(
1226            SignedDecimal::checked_from_ratio(1i128, 0i128),
1227            Err(CheckedFromRatioError::DivideByZero)
1228        );
1229
1230        assert_eq!(
1231            SignedDecimal::checked_from_ratio(i128::MAX, 1i128),
1232            Err(CheckedFromRatioError::Overflow)
1233        );
1234    }
1235
1236    #[test]
1237    fn signed_decimal_implements_fraction() {
1238        let fraction = SignedDecimal::from_str("1234.567").unwrap();
1239        assert_eq!(
1240            fraction.numerator(),
1241            Int128::from(1_234_567_000_000_000_000_000i128)
1242        );
1243        assert_eq!(
1244            fraction.denominator(),
1245            Int128::from(1_000_000_000_000_000_000i128)
1246        );
1247
1248        let fraction = SignedDecimal::from_str("-1234.567").unwrap();
1249        assert_eq!(
1250            fraction.numerator(),
1251            Int128::from(-1_234_567_000_000_000_000_000i128)
1252        );
1253        assert_eq!(
1254            fraction.denominator(),
1255            Int128::from(1_000_000_000_000_000_000i128)
1256        );
1257    }
1258
1259    #[test]
1260    fn signed_decimal_from_str_works() {
1261        // Integers
1262        assert_eq!(
1263            SignedDecimal::from_str("0").unwrap(),
1264            SignedDecimal::percent(0)
1265        );
1266        assert_eq!(
1267            SignedDecimal::from_str("1").unwrap(),
1268            SignedDecimal::percent(100)
1269        );
1270        assert_eq!(
1271            SignedDecimal::from_str("5").unwrap(),
1272            SignedDecimal::percent(500)
1273        );
1274        assert_eq!(
1275            SignedDecimal::from_str("42").unwrap(),
1276            SignedDecimal::percent(4200)
1277        );
1278        assert_eq!(
1279            SignedDecimal::from_str("000").unwrap(),
1280            SignedDecimal::percent(0)
1281        );
1282        assert_eq!(
1283            SignedDecimal::from_str("001").unwrap(),
1284            SignedDecimal::percent(100)
1285        );
1286        assert_eq!(
1287            SignedDecimal::from_str("005").unwrap(),
1288            SignedDecimal::percent(500)
1289        );
1290        assert_eq!(
1291            SignedDecimal::from_str("0042").unwrap(),
1292            SignedDecimal::percent(4200)
1293        );
1294
1295        // Positive decimals
1296        assert_eq!(
1297            SignedDecimal::from_str("1.0").unwrap(),
1298            SignedDecimal::percent(100)
1299        );
1300        assert_eq!(
1301            SignedDecimal::from_str("1.5").unwrap(),
1302            SignedDecimal::percent(150)
1303        );
1304        assert_eq!(
1305            SignedDecimal::from_str("0.5").unwrap(),
1306            SignedDecimal::percent(50)
1307        );
1308        assert_eq!(
1309            SignedDecimal::from_str("0.123").unwrap(),
1310            SignedDecimal::permille(123)
1311        );
1312
1313        assert_eq!(
1314            SignedDecimal::from_str("40.00").unwrap(),
1315            SignedDecimal::percent(4000)
1316        );
1317        assert_eq!(
1318            SignedDecimal::from_str("04.00").unwrap(),
1319            SignedDecimal::percent(400)
1320        );
1321        assert_eq!(
1322            SignedDecimal::from_str("00.40").unwrap(),
1323            SignedDecimal::percent(40)
1324        );
1325        assert_eq!(
1326            SignedDecimal::from_str("00.04").unwrap(),
1327            SignedDecimal::percent(4)
1328        );
1329        // Negative decimals
1330        assert_eq!(
1331            SignedDecimal::from_str("-00.04").unwrap(),
1332            SignedDecimal::percent(-4)
1333        );
1334        assert_eq!(
1335            SignedDecimal::from_str("-00.40").unwrap(),
1336            SignedDecimal::percent(-40)
1337        );
1338        assert_eq!(
1339            SignedDecimal::from_str("-04.00").unwrap(),
1340            SignedDecimal::percent(-400)
1341        );
1342
1343        // Can handle DECIMAL_PLACES fractional digits
1344        assert_eq!(
1345            SignedDecimal::from_str("7.123456789012345678").unwrap(),
1346            SignedDecimal(Int128::from(7123456789012345678i128))
1347        );
1348        assert_eq!(
1349            SignedDecimal::from_str("7.999999999999999999").unwrap(),
1350            SignedDecimal(Int128::from(7999999999999999999i128))
1351        );
1352
1353        // Works for documented max value
1354        assert_eq!(
1355            SignedDecimal::from_str("170141183460469231731.687303715884105727").unwrap(),
1356            SignedDecimal::MAX
1357        );
1358        // Works for documented min value
1359        assert_eq!(
1360            SignedDecimal::from_str("-170141183460469231731.687303715884105728").unwrap(),
1361            SignedDecimal::MIN
1362        );
1363        assert_eq!(
1364            SignedDecimal::from_str("-1").unwrap(),
1365            SignedDecimal::negative_one()
1366        );
1367    }
1368
1369    #[test]
1370    fn signed_decimal_from_str_errors_for_broken_whole_part() {
1371        let expected_err = StdError::generic_err("Error parsing whole");
1372        assert_eq!(SignedDecimal::from_str("").unwrap_err(), expected_err);
1373        assert_eq!(SignedDecimal::from_str(" ").unwrap_err(), expected_err);
1374        assert_eq!(SignedDecimal::from_str("-").unwrap_err(), expected_err);
1375    }
1376
1377    #[test]
1378    fn signed_decimal_from_str_errors_for_broken_fractional_part() {
1379        let expected_err = StdError::generic_err("Error parsing fractional");
1380        assert_eq!(SignedDecimal::from_str("1.").unwrap_err(), expected_err);
1381        assert_eq!(SignedDecimal::from_str("1. ").unwrap_err(), expected_err);
1382        assert_eq!(SignedDecimal::from_str("1.e").unwrap_err(), expected_err);
1383        assert_eq!(SignedDecimal::from_str("1.2e3").unwrap_err(), expected_err);
1384        assert_eq!(SignedDecimal::from_str("1.-2").unwrap_err(), expected_err);
1385    }
1386
1387    #[test]
1388    fn signed_decimal_from_str_errors_for_more_than_18_fractional_digits() {
1389        let expected_err = StdError::generic_err("Cannot parse more than 18 fractional digits");
1390        assert_eq!(
1391            SignedDecimal::from_str("7.1234567890123456789").unwrap_err(),
1392            expected_err
1393        );
1394        // No special rules for trailing zeros. This could be changed but adds gas cost for the happy path.
1395        assert_eq!(
1396            SignedDecimal::from_str("7.1230000000000000000").unwrap_err(),
1397            expected_err
1398        );
1399    }
1400
1401    #[test]
1402    fn signed_decimal_from_str_errors_for_invalid_number_of_dots() {
1403        let expected_err = StdError::generic_err("Unexpected number of dots");
1404        assert_eq!(SignedDecimal::from_str("1.2.3").unwrap_err(), expected_err);
1405        assert_eq!(
1406            SignedDecimal::from_str("1.2.3.4").unwrap_err(),
1407            expected_err
1408        );
1409    }
1410
1411    #[test]
1412    fn signed_decimal_from_str_errors_for_more_than_max_value() {
1413        let expected_err = StdError::generic_err("Value too big");
1414        // Integer
1415        assert_eq!(
1416            SignedDecimal::from_str("170141183460469231732").unwrap_err(),
1417            expected_err
1418        );
1419        assert_eq!(
1420            SignedDecimal::from_str("-170141183460469231732").unwrap_err(),
1421            expected_err
1422        );
1423
1424        // SignedDecimal
1425        assert_eq!(
1426            SignedDecimal::from_str("170141183460469231732.0").unwrap_err(),
1427            expected_err
1428        );
1429        assert_eq!(
1430            SignedDecimal::from_str("170141183460469231731.687303715884105728").unwrap_err(),
1431            expected_err
1432        );
1433        assert_eq!(
1434            SignedDecimal::from_str("-170141183460469231731.687303715884105729").unwrap_err(),
1435            expected_err
1436        );
1437    }
1438
1439    #[test]
1440    fn signed_decimal_conversions_work() {
1441        // signed decimal to signed decimal
1442        assert_eq!(
1443            SignedDecimal::try_from(SignedDecimal256::MAX).unwrap_err(),
1444            SignedDecimalRangeExceeded
1445        );
1446        assert_eq!(
1447            SignedDecimal::try_from(SignedDecimal256::MIN).unwrap_err(),
1448            SignedDecimalRangeExceeded
1449        );
1450        assert_eq!(
1451            SignedDecimal::try_from(SignedDecimal256::zero()).unwrap(),
1452            SignedDecimal::zero()
1453        );
1454        assert_eq!(
1455            SignedDecimal::try_from(SignedDecimal256::one()).unwrap(),
1456            SignedDecimal::one()
1457        );
1458        assert_eq!(
1459            SignedDecimal::try_from(SignedDecimal256::percent(50)).unwrap(),
1460            SignedDecimal::percent(50)
1461        );
1462        assert_eq!(
1463            SignedDecimal::try_from(SignedDecimal256::percent(-200)).unwrap(),
1464            SignedDecimal::percent(-200)
1465        );
1466
1467        // unsigned to signed decimal
1468        assert_eq!(
1469            SignedDecimal::try_from(Decimal::MAX).unwrap_err(),
1470            SignedDecimalRangeExceeded
1471        );
1472        let max = Decimal::new(Uint128::new(SignedDecimal::MAX.atomics().i128() as u128));
1473        let too_big = max + Decimal::new(Uint128::one());
1474        assert_eq!(
1475            SignedDecimal::try_from(too_big).unwrap_err(),
1476            SignedDecimalRangeExceeded
1477        );
1478        assert_eq!(
1479            SignedDecimal::try_from(Decimal::zero()).unwrap(),
1480            SignedDecimal::zero()
1481        );
1482        assert_eq!(SignedDecimal::try_from(max).unwrap(), SignedDecimal::MAX);
1483    }
1484
1485    #[test]
1486    fn signed_decimal_atomics_works() {
1487        let zero = SignedDecimal::zero();
1488        let one = SignedDecimal::one();
1489        let half = SignedDecimal::percent(50);
1490        let two = SignedDecimal::percent(200);
1491        let max = SignedDecimal::MAX;
1492        let neg_half = SignedDecimal::percent(-50);
1493        let neg_two = SignedDecimal::percent(-200);
1494        let min = SignedDecimal::MIN;
1495
1496        assert_eq!(zero.atomics(), Int128::new(0));
1497        assert_eq!(one.atomics(), Int128::new(1000000000000000000));
1498        assert_eq!(half.atomics(), Int128::new(500000000000000000));
1499        assert_eq!(two.atomics(), Int128::new(2000000000000000000));
1500        assert_eq!(max.atomics(), Int128::MAX);
1501        assert_eq!(neg_half.atomics(), Int128::new(-500000000000000000));
1502        assert_eq!(neg_two.atomics(), Int128::new(-2000000000000000000));
1503        assert_eq!(min.atomics(), Int128::MIN);
1504    }
1505
1506    #[test]
1507    fn signed_decimal_decimal_places_works() {
1508        let zero = SignedDecimal::zero();
1509        let one = SignedDecimal::one();
1510        let half = SignedDecimal::percent(50);
1511        let two = SignedDecimal::percent(200);
1512        let max = SignedDecimal::MAX;
1513        let neg_one = SignedDecimal::negative_one();
1514
1515        assert_eq!(zero.decimal_places(), 18);
1516        assert_eq!(one.decimal_places(), 18);
1517        assert_eq!(half.decimal_places(), 18);
1518        assert_eq!(two.decimal_places(), 18);
1519        assert_eq!(max.decimal_places(), 18);
1520        assert_eq!(neg_one.decimal_places(), 18);
1521    }
1522
1523    #[test]
1524    fn signed_decimal_is_zero_works() {
1525        assert!(SignedDecimal::zero().is_zero());
1526        assert!(SignedDecimal::percent(0).is_zero());
1527        assert!(SignedDecimal::permille(0).is_zero());
1528
1529        assert!(!SignedDecimal::one().is_zero());
1530        assert!(!SignedDecimal::percent(123).is_zero());
1531        assert!(!SignedDecimal::permille(-1234).is_zero());
1532    }
1533
1534    #[test]
1535    fn signed_decimal_inv_works() {
1536        // d = 0
1537        assert_eq!(SignedDecimal::zero().inv(), None);
1538
1539        // d == 1
1540        assert_eq!(SignedDecimal::one().inv(), Some(SignedDecimal::one()));
1541
1542        // d == -1
1543        assert_eq!(
1544            SignedDecimal::negative_one().inv(),
1545            Some(SignedDecimal::negative_one())
1546        );
1547
1548        // d > 1 exact
1549        assert_eq!(
1550            SignedDecimal::from_str("2").unwrap().inv(),
1551            Some(SignedDecimal::from_str("0.5").unwrap())
1552        );
1553        assert_eq!(
1554            SignedDecimal::from_str("20").unwrap().inv(),
1555            Some(SignedDecimal::from_str("0.05").unwrap())
1556        );
1557        assert_eq!(
1558            SignedDecimal::from_str("200").unwrap().inv(),
1559            Some(SignedDecimal::from_str("0.005").unwrap())
1560        );
1561        assert_eq!(
1562            SignedDecimal::from_str("2000").unwrap().inv(),
1563            Some(SignedDecimal::from_str("0.0005").unwrap())
1564        );
1565
1566        // d > 1 rounded
1567        assert_eq!(
1568            SignedDecimal::from_str("3").unwrap().inv(),
1569            Some(SignedDecimal::from_str("0.333333333333333333").unwrap())
1570        );
1571        assert_eq!(
1572            SignedDecimal::from_str("6").unwrap().inv(),
1573            Some(SignedDecimal::from_str("0.166666666666666666").unwrap())
1574        );
1575
1576        // d < 1 exact
1577        assert_eq!(
1578            SignedDecimal::from_str("0.5").unwrap().inv(),
1579            Some(SignedDecimal::from_str("2").unwrap())
1580        );
1581        assert_eq!(
1582            SignedDecimal::from_str("0.05").unwrap().inv(),
1583            Some(SignedDecimal::from_str("20").unwrap())
1584        );
1585        assert_eq!(
1586            SignedDecimal::from_str("0.005").unwrap().inv(),
1587            Some(SignedDecimal::from_str("200").unwrap())
1588        );
1589        assert_eq!(
1590            SignedDecimal::from_str("0.0005").unwrap().inv(),
1591            Some(SignedDecimal::from_str("2000").unwrap())
1592        );
1593
1594        // d < 0
1595        assert_eq!(
1596            SignedDecimal::from_str("-0.5").unwrap().inv(),
1597            Some(SignedDecimal::from_str("-2").unwrap())
1598        );
1599        // d < 0 rounded
1600        assert_eq!(
1601            SignedDecimal::from_str("-3").unwrap().inv(),
1602            Some(SignedDecimal::from_str("-0.333333333333333333").unwrap())
1603        );
1604    }
1605
1606    #[test]
1607    #[allow(clippy::op_ref)]
1608    fn signed_decimal_add_works() {
1609        let value = SignedDecimal::one() + SignedDecimal::percent(50); // 1.5
1610        assert_eq!(
1611            value.0,
1612            SignedDecimal::DECIMAL_FRACTIONAL * Int128::from(3u8) / Int128::from(2u8)
1613        );
1614
1615        assert_eq!(
1616            SignedDecimal::percent(5) + SignedDecimal::percent(4),
1617            SignedDecimal::percent(9)
1618        );
1619        assert_eq!(
1620            SignedDecimal::percent(5) + SignedDecimal::zero(),
1621            SignedDecimal::percent(5)
1622        );
1623        assert_eq!(
1624            SignedDecimal::zero() + SignedDecimal::zero(),
1625            SignedDecimal::zero()
1626        );
1627        // negative numbers
1628        assert_eq!(
1629            SignedDecimal::percent(-5) + SignedDecimal::percent(-4),
1630            SignedDecimal::percent(-9)
1631        );
1632        assert_eq!(
1633            SignedDecimal::percent(-5) + SignedDecimal::percent(4),
1634            SignedDecimal::percent(-1)
1635        );
1636        assert_eq!(
1637            SignedDecimal::percent(5) + SignedDecimal::percent(-4),
1638            SignedDecimal::percent(1)
1639        );
1640
1641        // works for refs
1642        let a = SignedDecimal::percent(15);
1643        let b = SignedDecimal::percent(25);
1644        let expected = SignedDecimal::percent(40);
1645        assert_eq!(a + b, expected);
1646        assert_eq!(&a + b, expected);
1647        assert_eq!(a + &b, expected);
1648        assert_eq!(&a + &b, expected);
1649    }
1650
1651    #[test]
1652    #[should_panic]
1653    fn signed_decimal_add_overflow_panics() {
1654        let _value = SignedDecimal::MAX + SignedDecimal::percent(50);
1655    }
1656
1657    #[test]
1658    fn signed_decimal_add_assign_works() {
1659        let mut a = SignedDecimal::percent(30);
1660        a += SignedDecimal::percent(20);
1661        assert_eq!(a, SignedDecimal::percent(50));
1662
1663        // works for refs
1664        let mut a = SignedDecimal::percent(15);
1665        let b = SignedDecimal::percent(3);
1666        let expected = SignedDecimal::percent(18);
1667        a += &b;
1668        assert_eq!(a, expected);
1669    }
1670
1671    #[test]
1672    #[allow(clippy::op_ref)]
1673    fn signed_decimal_sub_works() {
1674        let value = SignedDecimal::one() - SignedDecimal::percent(50); // 0.5
1675        assert_eq!(
1676            value.0,
1677            SignedDecimal::DECIMAL_FRACTIONAL / Int128::from(2u8)
1678        );
1679
1680        assert_eq!(
1681            SignedDecimal::percent(9) - SignedDecimal::percent(4),
1682            SignedDecimal::percent(5)
1683        );
1684        assert_eq!(
1685            SignedDecimal::percent(16) - SignedDecimal::zero(),
1686            SignedDecimal::percent(16)
1687        );
1688        assert_eq!(
1689            SignedDecimal::percent(16) - SignedDecimal::percent(16),
1690            SignedDecimal::zero()
1691        );
1692        assert_eq!(
1693            SignedDecimal::zero() - SignedDecimal::zero(),
1694            SignedDecimal::zero()
1695        );
1696
1697        // negative numbers
1698        assert_eq!(
1699            SignedDecimal::percent(-5) - SignedDecimal::percent(-4),
1700            SignedDecimal::percent(-1)
1701        );
1702        assert_eq!(
1703            SignedDecimal::percent(-5) - SignedDecimal::percent(4),
1704            SignedDecimal::percent(-9)
1705        );
1706        assert_eq!(
1707            SignedDecimal::percent(500) - SignedDecimal::percent(-4),
1708            SignedDecimal::percent(504)
1709        );
1710
1711        // works for refs
1712        let a = SignedDecimal::percent(13);
1713        let b = SignedDecimal::percent(6);
1714        let expected = SignedDecimal::percent(7);
1715        assert_eq!(a - b, expected);
1716        assert_eq!(&a - b, expected);
1717        assert_eq!(a - &b, expected);
1718        assert_eq!(&a - &b, expected);
1719    }
1720
1721    #[test]
1722    #[should_panic]
1723    fn signed_decimal_sub_overflow_panics() {
1724        let _value = SignedDecimal::MIN - SignedDecimal::percent(50);
1725    }
1726
1727    #[test]
1728    fn signed_decimal_sub_assign_works() {
1729        let mut a = SignedDecimal::percent(20);
1730        a -= SignedDecimal::percent(2);
1731        assert_eq!(a, SignedDecimal::percent(18));
1732
1733        // works for refs
1734        let mut a = SignedDecimal::percent(33);
1735        let b = SignedDecimal::percent(13);
1736        let expected = SignedDecimal::percent(20);
1737        a -= &b;
1738        assert_eq!(a, expected);
1739    }
1740
1741    #[test]
1742    #[allow(clippy::op_ref)]
1743    fn signed_decimal_implements_mul() {
1744        let one = SignedDecimal::one();
1745        let two = one + one;
1746        let half = SignedDecimal::percent(50);
1747
1748        // 1*x and x*1
1749        assert_eq!(one * SignedDecimal::percent(0), SignedDecimal::percent(0));
1750        assert_eq!(one * SignedDecimal::percent(1), SignedDecimal::percent(1));
1751        assert_eq!(one * SignedDecimal::percent(10), SignedDecimal::percent(10));
1752        assert_eq!(
1753            one * SignedDecimal::percent(100),
1754            SignedDecimal::percent(100)
1755        );
1756        assert_eq!(
1757            one * SignedDecimal::percent(1000),
1758            SignedDecimal::percent(1000)
1759        );
1760        assert_eq!(one * SignedDecimal::MAX, SignedDecimal::MAX);
1761        assert_eq!(SignedDecimal::percent(0) * one, SignedDecimal::percent(0));
1762        assert_eq!(SignedDecimal::percent(1) * one, SignedDecimal::percent(1));
1763        assert_eq!(SignedDecimal::percent(10) * one, SignedDecimal::percent(10));
1764        assert_eq!(
1765            SignedDecimal::percent(100) * one,
1766            SignedDecimal::percent(100)
1767        );
1768        assert_eq!(
1769            SignedDecimal::percent(1000) * one,
1770            SignedDecimal::percent(1000)
1771        );
1772        assert_eq!(SignedDecimal::MAX * one, SignedDecimal::MAX);
1773        assert_eq!(SignedDecimal::percent(-1) * one, SignedDecimal::percent(-1));
1774        assert_eq!(
1775            one * SignedDecimal::percent(-10),
1776            SignedDecimal::percent(-10)
1777        );
1778
1779        // double
1780        assert_eq!(two * SignedDecimal::percent(0), SignedDecimal::percent(0));
1781        assert_eq!(two * SignedDecimal::percent(1), SignedDecimal::percent(2));
1782        assert_eq!(two * SignedDecimal::percent(10), SignedDecimal::percent(20));
1783        assert_eq!(
1784            two * SignedDecimal::percent(100),
1785            SignedDecimal::percent(200)
1786        );
1787        assert_eq!(
1788            two * SignedDecimal::percent(1000),
1789            SignedDecimal::percent(2000)
1790        );
1791        assert_eq!(SignedDecimal::percent(0) * two, SignedDecimal::percent(0));
1792        assert_eq!(SignedDecimal::percent(1) * two, SignedDecimal::percent(2));
1793        assert_eq!(SignedDecimal::percent(10) * two, SignedDecimal::percent(20));
1794        assert_eq!(
1795            SignedDecimal::percent(100) * two,
1796            SignedDecimal::percent(200)
1797        );
1798        assert_eq!(
1799            SignedDecimal::percent(1000) * two,
1800            SignedDecimal::percent(2000)
1801        );
1802        assert_eq!(SignedDecimal::percent(-1) * two, SignedDecimal::percent(-2));
1803        assert_eq!(
1804            two * SignedDecimal::new(Int128::MIN / Int128::new(2)),
1805            SignedDecimal::MIN
1806        );
1807
1808        // half
1809        assert_eq!(half * SignedDecimal::percent(0), SignedDecimal::percent(0));
1810        assert_eq!(half * SignedDecimal::percent(1), SignedDecimal::permille(5));
1811        assert_eq!(half * SignedDecimal::percent(10), SignedDecimal::percent(5));
1812        assert_eq!(
1813            half * SignedDecimal::percent(100),
1814            SignedDecimal::percent(50)
1815        );
1816        assert_eq!(
1817            half * SignedDecimal::percent(1000),
1818            SignedDecimal::percent(500)
1819        );
1820        assert_eq!(SignedDecimal::percent(0) * half, SignedDecimal::percent(0));
1821        assert_eq!(SignedDecimal::percent(1) * half, SignedDecimal::permille(5));
1822        assert_eq!(SignedDecimal::percent(10) * half, SignedDecimal::percent(5));
1823        assert_eq!(
1824            SignedDecimal::percent(100) * half,
1825            SignedDecimal::percent(50)
1826        );
1827        assert_eq!(
1828            SignedDecimal::percent(1000) * half,
1829            SignedDecimal::percent(500)
1830        );
1831
1832        // Move left
1833        let a = dec("123.127726548762582");
1834        assert_eq!(a * dec("1"), dec("123.127726548762582"));
1835        assert_eq!(a * dec("10"), dec("1231.27726548762582"));
1836        assert_eq!(a * dec("100"), dec("12312.7726548762582"));
1837        assert_eq!(a * dec("1000"), dec("123127.726548762582"));
1838        assert_eq!(a * dec("1000000"), dec("123127726.548762582"));
1839        assert_eq!(a * dec("1000000000"), dec("123127726548.762582"));
1840        assert_eq!(a * dec("1000000000000"), dec("123127726548762.582"));
1841        assert_eq!(a * dec("1000000000000000"), dec("123127726548762582"));
1842        assert_eq!(a * dec("1000000000000000000"), dec("123127726548762582000"));
1843        assert_eq!(dec("1") * a, dec("123.127726548762582"));
1844        assert_eq!(dec("10") * a, dec("1231.27726548762582"));
1845        assert_eq!(dec("100") * a, dec("12312.7726548762582"));
1846        assert_eq!(dec("1000") * a, dec("123127.726548762582"));
1847        assert_eq!(dec("1000000") * a, dec("123127726.548762582"));
1848        assert_eq!(dec("1000000000") * a, dec("123127726548.762582"));
1849        assert_eq!(dec("1000000000000") * a, dec("123127726548762.582"));
1850        assert_eq!(dec("1000000000000000") * a, dec("123127726548762582"));
1851        assert_eq!(dec("1000000000000000000") * a, dec("123127726548762582000"));
1852        assert_eq!(
1853            dec("-1000000000000000000") * a,
1854            dec("-123127726548762582000")
1855        );
1856
1857        // Move right
1858        let max = SignedDecimal::MAX;
1859        assert_eq!(
1860            max * dec("1.0"),
1861            dec("170141183460469231731.687303715884105727")
1862        );
1863        assert_eq!(
1864            max * dec("0.1"),
1865            dec("17014118346046923173.168730371588410572")
1866        );
1867        assert_eq!(
1868            max * dec("0.01"),
1869            dec("1701411834604692317.316873037158841057")
1870        );
1871        assert_eq!(
1872            max * dec("0.001"),
1873            dec("170141183460469231.731687303715884105")
1874        );
1875        assert_eq!(
1876            max * dec("0.000001"),
1877            dec("170141183460469.231731687303715884")
1878        );
1879        assert_eq!(
1880            max * dec("0.000000001"),
1881            dec("170141183460.469231731687303715")
1882        );
1883        assert_eq!(
1884            max * dec("0.000000000001"),
1885            dec("170141183.460469231731687303")
1886        );
1887        assert_eq!(
1888            max * dec("0.000000000000001"),
1889            dec("170141.183460469231731687")
1890        );
1891        assert_eq!(
1892            max * dec("0.000000000000000001"),
1893            dec("170.141183460469231731")
1894        );
1895
1896        // works for refs
1897        let a = SignedDecimal::percent(20);
1898        let b = SignedDecimal::percent(30);
1899        let expected = SignedDecimal::percent(6);
1900        assert_eq!(a * b, expected);
1901        assert_eq!(&a * b, expected);
1902        assert_eq!(a * &b, expected);
1903        assert_eq!(&a * &b, expected);
1904    }
1905
1906    #[test]
1907    fn signed_decimal_mul_assign_works() {
1908        let mut a = SignedDecimal::percent(15);
1909        a *= SignedDecimal::percent(60);
1910        assert_eq!(a, SignedDecimal::percent(9));
1911
1912        // works for refs
1913        let mut a = SignedDecimal::percent(50);
1914        let b = SignedDecimal::percent(20);
1915        a *= &b;
1916        assert_eq!(a, SignedDecimal::percent(10));
1917    }
1918
1919    #[test]
1920    #[should_panic(expected = "attempt to multiply with overflow")]
1921    fn signed_decimal_mul_overflow_panics() {
1922        let _value = SignedDecimal::MAX * SignedDecimal::percent(101);
1923    }
1924
1925    #[test]
1926    fn signed_decimal_checked_mul() {
1927        let test_data = [
1928            (SignedDecimal::zero(), SignedDecimal::zero()),
1929            (SignedDecimal::zero(), SignedDecimal::one()),
1930            (SignedDecimal::one(), SignedDecimal::zero()),
1931            (SignedDecimal::percent(10), SignedDecimal::zero()),
1932            (SignedDecimal::percent(10), SignedDecimal::percent(5)),
1933            (SignedDecimal::MAX, SignedDecimal::one()),
1934            (
1935                SignedDecimal::MAX / Int128::new(2),
1936                SignedDecimal::percent(200),
1937            ),
1938            (SignedDecimal::permille(6), SignedDecimal::permille(13)),
1939            (SignedDecimal::permille(-6), SignedDecimal::permille(0)),
1940            (SignedDecimal::MAX, SignedDecimal::negative_one()),
1941        ];
1942
1943        // The regular core::ops::Mul is our source of truth for these tests.
1944        for (x, y) in test_data.into_iter() {
1945            assert_eq!(x * y, x.checked_mul(y).unwrap());
1946        }
1947    }
1948
1949    #[test]
1950    fn signed_decimal_checked_mul_overflow() {
1951        assert_eq!(
1952            SignedDecimal::MAX.checked_mul(SignedDecimal::percent(200)),
1953            Err(OverflowError::new(OverflowOperation::Mul))
1954        );
1955    }
1956
1957    #[test]
1958    #[allow(clippy::op_ref)]
1959    fn signed_decimal_implements_div() {
1960        let one = SignedDecimal::one();
1961        let two = one + one;
1962        let half = SignedDecimal::percent(50);
1963
1964        // 1/x and x/1
1965        assert_eq!(
1966            one / SignedDecimal::percent(1),
1967            SignedDecimal::percent(10_000)
1968        );
1969        assert_eq!(
1970            one / SignedDecimal::percent(10),
1971            SignedDecimal::percent(1_000)
1972        );
1973        assert_eq!(
1974            one / SignedDecimal::percent(100),
1975            SignedDecimal::percent(100)
1976        );
1977        assert_eq!(
1978            one / SignedDecimal::percent(1000),
1979            SignedDecimal::percent(10)
1980        );
1981        assert_eq!(SignedDecimal::percent(0) / one, SignedDecimal::percent(0));
1982        assert_eq!(SignedDecimal::percent(1) / one, SignedDecimal::percent(1));
1983        assert_eq!(SignedDecimal::percent(10) / one, SignedDecimal::percent(10));
1984        assert_eq!(
1985            SignedDecimal::percent(100) / one,
1986            SignedDecimal::percent(100)
1987        );
1988        assert_eq!(
1989            SignedDecimal::percent(1000) / one,
1990            SignedDecimal::percent(1000)
1991        );
1992        assert_eq!(
1993            one / SignedDecimal::percent(-1),
1994            SignedDecimal::percent(-10_000)
1995        );
1996        assert_eq!(
1997            one / SignedDecimal::percent(-10),
1998            SignedDecimal::percent(-1_000)
1999        );
2000
2001        // double
2002        assert_eq!(
2003            two / SignedDecimal::percent(1),
2004            SignedDecimal::percent(20_000)
2005        );
2006        assert_eq!(
2007            two / SignedDecimal::percent(10),
2008            SignedDecimal::percent(2_000)
2009        );
2010        assert_eq!(
2011            two / SignedDecimal::percent(100),
2012            SignedDecimal::percent(200)
2013        );
2014        assert_eq!(
2015            two / SignedDecimal::percent(1000),
2016            SignedDecimal::percent(20)
2017        );
2018        assert_eq!(SignedDecimal::percent(0) / two, SignedDecimal::percent(0));
2019        assert_eq!(SignedDecimal::percent(1) / two, dec("0.005"));
2020        assert_eq!(SignedDecimal::percent(10) / two, SignedDecimal::percent(5));
2021        assert_eq!(
2022            SignedDecimal::percent(100) / two,
2023            SignedDecimal::percent(50)
2024        );
2025        assert_eq!(
2026            SignedDecimal::percent(1000) / two,
2027            SignedDecimal::percent(500)
2028        );
2029        assert_eq!(
2030            two / SignedDecimal::percent(-1),
2031            SignedDecimal::percent(-20_000)
2032        );
2033        assert_eq!(
2034            SignedDecimal::percent(-10000) / two,
2035            SignedDecimal::percent(-5000)
2036        );
2037
2038        // half
2039        assert_eq!(
2040            half / SignedDecimal::percent(1),
2041            SignedDecimal::percent(5_000)
2042        );
2043        assert_eq!(
2044            half / SignedDecimal::percent(10),
2045            SignedDecimal::percent(500)
2046        );
2047        assert_eq!(
2048            half / SignedDecimal::percent(100),
2049            SignedDecimal::percent(50)
2050        );
2051        assert_eq!(
2052            half / SignedDecimal::percent(1000),
2053            SignedDecimal::percent(5)
2054        );
2055        assert_eq!(SignedDecimal::percent(0) / half, SignedDecimal::percent(0));
2056        assert_eq!(SignedDecimal::percent(1) / half, SignedDecimal::percent(2));
2057        assert_eq!(
2058            SignedDecimal::percent(10) / half,
2059            SignedDecimal::percent(20)
2060        );
2061        assert_eq!(
2062            SignedDecimal::percent(100) / half,
2063            SignedDecimal::percent(200)
2064        );
2065        assert_eq!(
2066            SignedDecimal::percent(1000) / half,
2067            SignedDecimal::percent(2000)
2068        );
2069
2070        // Move right
2071        let a = dec("123127726548762582");
2072        assert_eq!(a / dec("1"), dec("123127726548762582"));
2073        assert_eq!(a / dec("10"), dec("12312772654876258.2"));
2074        assert_eq!(a / dec("100"), dec("1231277265487625.82"));
2075        assert_eq!(a / dec("1000"), dec("123127726548762.582"));
2076        assert_eq!(a / dec("1000000"), dec("123127726548.762582"));
2077        assert_eq!(a / dec("1000000000"), dec("123127726.548762582"));
2078        assert_eq!(a / dec("1000000000000"), dec("123127.726548762582"));
2079        assert_eq!(a / dec("1000000000000000"), dec("123.127726548762582"));
2080        assert_eq!(a / dec("1000000000000000000"), dec("0.123127726548762582"));
2081        assert_eq!(dec("1") / a, dec("0.000000000000000008"));
2082        assert_eq!(dec("10") / a, dec("0.000000000000000081"));
2083        assert_eq!(dec("100") / a, dec("0.000000000000000812"));
2084        assert_eq!(dec("1000") / a, dec("0.000000000000008121"));
2085        assert_eq!(dec("1000000") / a, dec("0.000000000008121647"));
2086        assert_eq!(dec("1000000000") / a, dec("0.000000008121647560"));
2087        assert_eq!(dec("1000000000000") / a, dec("0.000008121647560868"));
2088        assert_eq!(dec("1000000000000000") / a, dec("0.008121647560868164"));
2089        assert_eq!(dec("1000000000000000000") / a, dec("8.121647560868164773"));
2090        // negative
2091        let a = dec("-123127726548762582");
2092        assert_eq!(a / dec("1"), dec("-123127726548762582"));
2093        assert_eq!(a / dec("10"), dec("-12312772654876258.2"));
2094        assert_eq!(a / dec("100"), dec("-1231277265487625.82"));
2095        assert_eq!(a / dec("1000"), dec("-123127726548762.582"));
2096        assert_eq!(a / dec("1000000"), dec("-123127726548.762582"));
2097        assert_eq!(a / dec("1000000000"), dec("-123127726.548762582"));
2098        assert_eq!(a / dec("1000000000000"), dec("-123127.726548762582"));
2099        assert_eq!(a / dec("1000000000000000"), dec("-123.127726548762582"));
2100        assert_eq!(a / dec("1000000000000000000"), dec("-0.123127726548762582"));
2101        assert_eq!(dec("1") / a, dec("-0.000000000000000008"));
2102
2103        // Move left
2104        let a = dec("0.123127726548762582");
2105        assert_eq!(a / dec("1.0"), dec("0.123127726548762582"));
2106        assert_eq!(a / dec("0.1"), dec("1.23127726548762582"));
2107        assert_eq!(a / dec("0.01"), dec("12.3127726548762582"));
2108        assert_eq!(a / dec("0.001"), dec("123.127726548762582"));
2109        assert_eq!(a / dec("0.000001"), dec("123127.726548762582"));
2110        assert_eq!(a / dec("0.000000001"), dec("123127726.548762582"));
2111        assert_eq!(a / dec("0.000000000001"), dec("123127726548.762582"));
2112        assert_eq!(a / dec("0.000000000000001"), dec("123127726548762.582"));
2113        assert_eq!(a / dec("0.000000000000000001"), dec("123127726548762582"));
2114        // negative
2115        let a = dec("-0.123127726548762582");
2116        assert_eq!(a / dec("1.0"), dec("-0.123127726548762582"));
2117        assert_eq!(a / dec("0.1"), dec("-1.23127726548762582"));
2118        assert_eq!(a / dec("0.01"), dec("-12.3127726548762582"));
2119        assert_eq!(a / dec("0.001"), dec("-123.127726548762582"));
2120        assert_eq!(a / dec("0.000001"), dec("-123127.726548762582"));
2121        assert_eq!(a / dec("0.000000001"), dec("-123127726.548762582"));
2122
2123        assert_eq!(
2124            SignedDecimal::percent(15) / SignedDecimal::percent(60),
2125            SignedDecimal::percent(25)
2126        );
2127
2128        // works for refs
2129        let a = SignedDecimal::percent(100);
2130        let b = SignedDecimal::percent(20);
2131        let expected = SignedDecimal::percent(500);
2132        assert_eq!(a / b, expected);
2133        assert_eq!(&a / b, expected);
2134        assert_eq!(a / &b, expected);
2135        assert_eq!(&a / &b, expected);
2136    }
2137
2138    #[test]
2139    fn signed_decimal_div_assign_works() {
2140        let mut a = SignedDecimal::percent(15);
2141        a /= SignedDecimal::percent(20);
2142        assert_eq!(a, SignedDecimal::percent(75));
2143
2144        // works for refs
2145        let mut a = SignedDecimal::percent(50);
2146        let b = SignedDecimal::percent(20);
2147        a /= &b;
2148        assert_eq!(a, SignedDecimal::percent(250));
2149    }
2150
2151    #[test]
2152    #[should_panic(expected = "Division failed - multiplication overflow")]
2153    fn signed_decimal_div_overflow_panics() {
2154        let _value = SignedDecimal::MAX / SignedDecimal::percent(10);
2155    }
2156
2157    #[test]
2158    #[should_panic(expected = "Division failed - denominator must not be zero")]
2159    fn signed_decimal_div_by_zero_panics() {
2160        let _value = SignedDecimal::one() / SignedDecimal::zero();
2161    }
2162
2163    #[test]
2164    fn signed_decimal_int128_division() {
2165        // a/b
2166        let left = SignedDecimal::percent(150); // 1.5
2167        let right = Int128::new(3);
2168        assert_eq!(left / right, SignedDecimal::percent(50));
2169
2170        // negative
2171        let left = SignedDecimal::percent(-150); // -1.5
2172        let right = Int128::new(3);
2173        assert_eq!(left / right, SignedDecimal::percent(-50));
2174
2175        // 0/a
2176        let left = SignedDecimal::zero();
2177        let right = Int128::new(300);
2178        assert_eq!(left / right, SignedDecimal::zero());
2179    }
2180
2181    #[test]
2182    #[should_panic]
2183    fn signed_decimal_int128_divide_by_zero() {
2184        let left = SignedDecimal::percent(150); // 1.5
2185        let right = Int128::new(0);
2186        let _result = left / right;
2187    }
2188
2189    #[test]
2190    fn signed_decimal_int128_div_assign() {
2191        // a/b
2192        let mut dec = SignedDecimal::percent(150); // 1.5
2193        dec /= Int128::new(3);
2194        assert_eq!(dec, SignedDecimal::percent(50));
2195
2196        // 0/a
2197        let mut dec = SignedDecimal::zero();
2198        dec /= Int128::new(300);
2199        assert_eq!(dec, SignedDecimal::zero());
2200    }
2201
2202    #[test]
2203    #[should_panic]
2204    fn signed_decimal_int128_div_assign_by_zero() {
2205        // a/0
2206        let mut dec = SignedDecimal::percent(50);
2207        dec /= Int128::new(0);
2208    }
2209
2210    #[test]
2211    fn signed_decimal_checked_pow() {
2212        for exp in 0..10 {
2213            assert_eq!(
2214                SignedDecimal::one().checked_pow(exp).unwrap(),
2215                SignedDecimal::one()
2216            );
2217        }
2218
2219        // This case is mathematically undefined but we ensure consistency with Rust standard types
2220        // https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=20df6716048e77087acd40194b233494
2221        assert_eq!(
2222            SignedDecimal::zero().checked_pow(0).unwrap(),
2223            SignedDecimal::one()
2224        );
2225
2226        for exp in 1..10 {
2227            assert_eq!(
2228                SignedDecimal::zero().checked_pow(exp).unwrap(),
2229                SignedDecimal::zero()
2230            );
2231        }
2232
2233        for exp in 1..10 {
2234            assert_eq!(
2235                SignedDecimal::negative_one().checked_pow(exp).unwrap(),
2236                // alternates between 1 and -1
2237                if exp % 2 == 0 {
2238                    SignedDecimal::one()
2239                } else {
2240                    SignedDecimal::negative_one()
2241                }
2242            )
2243        }
2244
2245        for num in &[
2246            SignedDecimal::percent(50),
2247            SignedDecimal::percent(99),
2248            SignedDecimal::percent(200),
2249        ] {
2250            assert_eq!(num.checked_pow(0).unwrap(), SignedDecimal::one())
2251        }
2252
2253        assert_eq!(
2254            SignedDecimal::percent(20).checked_pow(2).unwrap(),
2255            SignedDecimal::percent(4)
2256        );
2257
2258        assert_eq!(
2259            SignedDecimal::percent(20).checked_pow(3).unwrap(),
2260            SignedDecimal::permille(8)
2261        );
2262
2263        assert_eq!(
2264            SignedDecimal::percent(200).checked_pow(4).unwrap(),
2265            SignedDecimal::percent(1600)
2266        );
2267
2268        assert_eq!(
2269            SignedDecimal::percent(200).checked_pow(4).unwrap(),
2270            SignedDecimal::percent(1600)
2271        );
2272
2273        assert_eq!(
2274            SignedDecimal::percent(700).checked_pow(5).unwrap(),
2275            SignedDecimal::percent(1680700)
2276        );
2277
2278        assert_eq!(
2279            SignedDecimal::percent(700).checked_pow(8).unwrap(),
2280            SignedDecimal::percent(576480100)
2281        );
2282
2283        assert_eq!(
2284            SignedDecimal::percent(700).checked_pow(10).unwrap(),
2285            SignedDecimal::percent(28247524900)
2286        );
2287
2288        assert_eq!(
2289            SignedDecimal::percent(120).checked_pow(123).unwrap(),
2290            SignedDecimal(5486473221892422150877397607i128.into())
2291        );
2292
2293        assert_eq!(
2294            SignedDecimal::percent(10).checked_pow(2).unwrap(),
2295            SignedDecimal(10000000000000000i128.into())
2296        );
2297
2298        assert_eq!(
2299            SignedDecimal::percent(10).checked_pow(18).unwrap(),
2300            SignedDecimal(1i128.into())
2301        );
2302
2303        let decimals = [
2304            SignedDecimal::percent(-50),
2305            SignedDecimal::percent(-99),
2306            SignedDecimal::percent(-200),
2307        ];
2308        let exponents = [1, 2, 3, 4, 5, 8, 10];
2309
2310        for d in decimals {
2311            for e in exponents {
2312                // use multiplication as source of truth
2313                let mut mul = Ok(d);
2314                for _ in 1..e {
2315                    mul = mul.and_then(|mul| mul.checked_mul(d));
2316                }
2317                assert_eq!(mul, d.checked_pow(e));
2318            }
2319        }
2320    }
2321
2322    #[test]
2323    fn signed_decimal_checked_pow_overflow() {
2324        assert_eq!(
2325            SignedDecimal::MAX.checked_pow(2),
2326            Err(OverflowError::new(OverflowOperation::Pow))
2327        );
2328    }
2329
2330    #[test]
2331    fn signed_decimal_to_string() {
2332        // Integers
2333        assert_eq!(SignedDecimal::zero().to_string(), "0");
2334        assert_eq!(SignedDecimal::one().to_string(), "1");
2335        assert_eq!(SignedDecimal::percent(500).to_string(), "5");
2336        assert_eq!(SignedDecimal::percent(-500).to_string(), "-5");
2337
2338        // SignedDecimals
2339        assert_eq!(SignedDecimal::percent(125).to_string(), "1.25");
2340        assert_eq!(SignedDecimal::percent(42638).to_string(), "426.38");
2341        assert_eq!(SignedDecimal::percent(3).to_string(), "0.03");
2342        assert_eq!(SignedDecimal::permille(987).to_string(), "0.987");
2343        assert_eq!(SignedDecimal::percent(-125).to_string(), "-1.25");
2344        assert_eq!(SignedDecimal::percent(-42638).to_string(), "-426.38");
2345        assert_eq!(SignedDecimal::percent(-3).to_string(), "-0.03");
2346        assert_eq!(SignedDecimal::permille(-987).to_string(), "-0.987");
2347
2348        assert_eq!(
2349            SignedDecimal(Int128::from(1i128)).to_string(),
2350            "0.000000000000000001"
2351        );
2352        assert_eq!(
2353            SignedDecimal(Int128::from(10i128)).to_string(),
2354            "0.00000000000000001"
2355        );
2356        assert_eq!(
2357            SignedDecimal(Int128::from(100i128)).to_string(),
2358            "0.0000000000000001"
2359        );
2360        assert_eq!(
2361            SignedDecimal(Int128::from(1000i128)).to_string(),
2362            "0.000000000000001"
2363        );
2364        assert_eq!(
2365            SignedDecimal(Int128::from(10000i128)).to_string(),
2366            "0.00000000000001"
2367        );
2368        assert_eq!(
2369            SignedDecimal(Int128::from(100000i128)).to_string(),
2370            "0.0000000000001"
2371        );
2372        assert_eq!(
2373            SignedDecimal(Int128::from(1000000i128)).to_string(),
2374            "0.000000000001"
2375        );
2376        assert_eq!(
2377            SignedDecimal(Int128::from(10000000i128)).to_string(),
2378            "0.00000000001"
2379        );
2380        assert_eq!(
2381            SignedDecimal(Int128::from(100000000i128)).to_string(),
2382            "0.0000000001"
2383        );
2384        assert_eq!(
2385            SignedDecimal(Int128::from(1000000000i128)).to_string(),
2386            "0.000000001"
2387        );
2388        assert_eq!(
2389            SignedDecimal(Int128::from(10000000000i128)).to_string(),
2390            "0.00000001"
2391        );
2392        assert_eq!(
2393            SignedDecimal(Int128::from(100000000000i128)).to_string(),
2394            "0.0000001"
2395        );
2396        assert_eq!(
2397            SignedDecimal(Int128::from(10000000000000i128)).to_string(),
2398            "0.00001"
2399        );
2400        assert_eq!(
2401            SignedDecimal(Int128::from(100000000000000i128)).to_string(),
2402            "0.0001"
2403        );
2404        assert_eq!(
2405            SignedDecimal(Int128::from(1000000000000000i128)).to_string(),
2406            "0.001"
2407        );
2408        assert_eq!(
2409            SignedDecimal(Int128::from(10000000000000000i128)).to_string(),
2410            "0.01"
2411        );
2412        assert_eq!(
2413            SignedDecimal(Int128::from(100000000000000000i128)).to_string(),
2414            "0.1"
2415        );
2416        assert_eq!(
2417            SignedDecimal(Int128::from(-1i128)).to_string(),
2418            "-0.000000000000000001"
2419        );
2420        assert_eq!(
2421            SignedDecimal(Int128::from(-100000000000000i128)).to_string(),
2422            "-0.0001"
2423        );
2424        assert_eq!(
2425            SignedDecimal(Int128::from(-100000000000000000i128)).to_string(),
2426            "-0.1"
2427        );
2428    }
2429
2430    #[test]
2431    fn signed_decimal_iter_sum() {
2432        let items = vec![
2433            SignedDecimal::zero(),
2434            SignedDecimal(Int128::from(2i128)),
2435            SignedDecimal(Int128::from(2i128)),
2436            SignedDecimal(Int128::from(-2i128)),
2437        ];
2438        assert_eq!(
2439            items.iter().sum::<SignedDecimal>(),
2440            SignedDecimal(Int128::from(2i128))
2441        );
2442        assert_eq!(
2443            items.into_iter().sum::<SignedDecimal>(),
2444            SignedDecimal(Int128::from(2i128))
2445        );
2446
2447        let empty: Vec<SignedDecimal> = vec![];
2448        assert_eq!(SignedDecimal::zero(), empty.iter().sum::<SignedDecimal>());
2449    }
2450
2451    #[test]
2452    fn signed_decimal_serialize() {
2453        assert_eq!(
2454            serde_json::to_vec(&SignedDecimal::zero()).unwrap(),
2455            br#""0""#
2456        );
2457        assert_eq!(
2458            serde_json::to_vec(&SignedDecimal::one()).unwrap(),
2459            br#""1""#
2460        );
2461        assert_eq!(
2462            serde_json::to_vec(&SignedDecimal::percent(8)).unwrap(),
2463            br#""0.08""#
2464        );
2465        assert_eq!(
2466            serde_json::to_vec(&SignedDecimal::percent(87)).unwrap(),
2467            br#""0.87""#
2468        );
2469        assert_eq!(
2470            serde_json::to_vec(&SignedDecimal::percent(876)).unwrap(),
2471            br#""8.76""#
2472        );
2473        assert_eq!(
2474            serde_json::to_vec(&SignedDecimal::percent(8765)).unwrap(),
2475            br#""87.65""#
2476        );
2477        assert_eq!(
2478            serde_json::to_vec(&SignedDecimal::percent(-87654)).unwrap(),
2479            br#""-876.54""#
2480        );
2481        assert_eq!(
2482            serde_json::to_vec(&SignedDecimal::negative_one()).unwrap(),
2483            br#""-1""#
2484        );
2485        assert_eq!(
2486            serde_json::to_vec(&-SignedDecimal::percent(8)).unwrap(),
2487            br#""-0.08""#
2488        );
2489    }
2490
2491    #[test]
2492    fn signed_decimal_deserialize() {
2493        assert_eq!(
2494            serde_json::from_slice::<SignedDecimal>(br#""0""#).unwrap(),
2495            SignedDecimal::zero()
2496        );
2497        assert_eq!(
2498            serde_json::from_slice::<SignedDecimal>(br#""1""#).unwrap(),
2499            SignedDecimal::one()
2500        );
2501        assert_eq!(
2502            serde_json::from_slice::<SignedDecimal>(br#""000""#).unwrap(),
2503            SignedDecimal::zero()
2504        );
2505        assert_eq!(
2506            serde_json::from_slice::<SignedDecimal>(br#""001""#).unwrap(),
2507            SignedDecimal::one()
2508        );
2509
2510        assert_eq!(
2511            serde_json::from_slice::<SignedDecimal>(br#""0.08""#).unwrap(),
2512            SignedDecimal::percent(8)
2513        );
2514        assert_eq!(
2515            serde_json::from_slice::<SignedDecimal>(br#""0.87""#).unwrap(),
2516            SignedDecimal::percent(87)
2517        );
2518        assert_eq!(
2519            serde_json::from_slice::<SignedDecimal>(br#""8.76""#).unwrap(),
2520            SignedDecimal::percent(876)
2521        );
2522        assert_eq!(
2523            serde_json::from_slice::<SignedDecimal>(br#""87.65""#).unwrap(),
2524            SignedDecimal::percent(8765)
2525        );
2526
2527        // negative numbers
2528        assert_eq!(
2529            serde_json::from_slice::<SignedDecimal>(br#""-0""#).unwrap(),
2530            SignedDecimal::zero()
2531        );
2532        assert_eq!(
2533            serde_json::from_slice::<SignedDecimal>(br#""-1""#).unwrap(),
2534            SignedDecimal::negative_one()
2535        );
2536        assert_eq!(
2537            serde_json::from_slice::<SignedDecimal>(br#""-001""#).unwrap(),
2538            SignedDecimal::negative_one()
2539        );
2540        assert_eq!(
2541            serde_json::from_slice::<SignedDecimal>(br#""-0.08""#).unwrap(),
2542            SignedDecimal::percent(-8)
2543        );
2544    }
2545
2546    #[test]
2547    fn signed_decimal_abs_diff_works() {
2548        let a = SignedDecimal::percent(285);
2549        let b = SignedDecimal::percent(200);
2550        let expected = Decimal::percent(85);
2551        assert_eq!(a.abs_diff(b), expected);
2552        assert_eq!(b.abs_diff(a), expected);
2553
2554        let a = SignedDecimal::percent(-200);
2555        let b = SignedDecimal::percent(200);
2556        let expected = Decimal::percent(400);
2557        assert_eq!(a.abs_diff(b), expected);
2558        assert_eq!(b.abs_diff(a), expected);
2559
2560        let a = SignedDecimal::percent(-200);
2561        let b = SignedDecimal::percent(-240);
2562        let expected = Decimal::percent(40);
2563        assert_eq!(a.abs_diff(b), expected);
2564        assert_eq!(b.abs_diff(a), expected);
2565    }
2566
2567    #[test]
2568    #[allow(clippy::op_ref)]
2569    fn signed_decimal_rem_works() {
2570        // 4.02 % 1.11 = 0.69
2571        assert_eq!(
2572            SignedDecimal::percent(402) % SignedDecimal::percent(111),
2573            SignedDecimal::percent(69)
2574        );
2575
2576        // 15.25 % 4 = 3.25
2577        assert_eq!(
2578            SignedDecimal::percent(1525) % SignedDecimal::percent(400),
2579            SignedDecimal::percent(325)
2580        );
2581
2582        // -20.25 % 5 = -25
2583        assert_eq!(
2584            SignedDecimal::percent(-2025) % SignedDecimal::percent(500),
2585            SignedDecimal::percent(-25)
2586        );
2587
2588        let a = SignedDecimal::percent(318);
2589        let b = SignedDecimal::percent(317);
2590        let expected = SignedDecimal::percent(1);
2591        assert_eq!(a % b, expected);
2592        assert_eq!(a % &b, expected);
2593        assert_eq!(&a % b, expected);
2594        assert_eq!(&a % &b, expected);
2595    }
2596
2597    #[test]
2598    fn signed_decimal_rem_assign_works() {
2599        let mut a = SignedDecimal::percent(17673);
2600        a %= SignedDecimal::percent(2362);
2601        assert_eq!(a, SignedDecimal::percent(1139)); // 176.73 % 23.62 = 11.39
2602
2603        let mut a = SignedDecimal::percent(4262);
2604        let b = SignedDecimal::percent(1270);
2605        a %= &b;
2606        assert_eq!(a, SignedDecimal::percent(452)); // 42.62 % 12.7 = 4.52
2607
2608        let mut a = SignedDecimal::percent(-4262);
2609        let b = SignedDecimal::percent(1270);
2610        a %= &b;
2611        assert_eq!(a, SignedDecimal::percent(-452)); // -42.62 % 12.7 = -4.52
2612    }
2613
2614    #[test]
2615    #[should_panic(expected = "divisor of zero")]
2616    fn signed_decimal_rem_panics_for_zero() {
2617        let _ = SignedDecimal::percent(777) % SignedDecimal::zero();
2618    }
2619
2620    #[test]
2621    fn signed_decimal_checked_methods() {
2622        // checked add
2623        assert_eq!(
2624            SignedDecimal::percent(402)
2625                .checked_add(SignedDecimal::percent(111))
2626                .unwrap(),
2627            SignedDecimal::percent(513)
2628        );
2629        assert!(matches!(
2630            SignedDecimal::MAX.checked_add(SignedDecimal::percent(1)),
2631            Err(OverflowError { .. })
2632        ));
2633        assert!(matches!(
2634            SignedDecimal::MIN.checked_add(SignedDecimal::percent(-1)),
2635            Err(OverflowError { .. })
2636        ));
2637
2638        // checked sub
2639        assert_eq!(
2640            SignedDecimal::percent(1111)
2641                .checked_sub(SignedDecimal::percent(111))
2642                .unwrap(),
2643            SignedDecimal::percent(1000)
2644        );
2645        assert_eq!(
2646            SignedDecimal::zero()
2647                .checked_sub(SignedDecimal::percent(1))
2648                .unwrap(),
2649            SignedDecimal::percent(-1)
2650        );
2651        assert!(matches!(
2652            SignedDecimal::MIN.checked_sub(SignedDecimal::percent(1)),
2653            Err(OverflowError { .. })
2654        ));
2655        assert!(matches!(
2656            SignedDecimal::MAX.checked_sub(SignedDecimal::percent(-1)),
2657            Err(OverflowError { .. })
2658        ));
2659
2660        // checked div
2661        assert_eq!(
2662            SignedDecimal::percent(30)
2663                .checked_div(SignedDecimal::percent(200))
2664                .unwrap(),
2665            SignedDecimal::percent(15)
2666        );
2667        assert_eq!(
2668            SignedDecimal::percent(88)
2669                .checked_div(SignedDecimal::percent(20))
2670                .unwrap(),
2671            SignedDecimal::percent(440)
2672        );
2673        assert!(matches!(
2674            SignedDecimal::MAX.checked_div(SignedDecimal::zero()),
2675            Err(CheckedFromRatioError::DivideByZero {})
2676        ));
2677        assert!(matches!(
2678            SignedDecimal::MAX.checked_div(SignedDecimal::percent(1)),
2679            Err(CheckedFromRatioError::Overflow {})
2680        ));
2681        assert_eq!(
2682            SignedDecimal::percent(-88)
2683                .checked_div(SignedDecimal::percent(20))
2684                .unwrap(),
2685            SignedDecimal::percent(-440)
2686        );
2687        assert_eq!(
2688            SignedDecimal::percent(-88)
2689                .checked_div(SignedDecimal::percent(-20))
2690                .unwrap(),
2691            SignedDecimal::percent(440)
2692        );
2693
2694        // checked rem
2695        assert_eq!(
2696            SignedDecimal::percent(402)
2697                .checked_rem(SignedDecimal::percent(111))
2698                .unwrap(),
2699            SignedDecimal::percent(69)
2700        );
2701        assert_eq!(
2702            SignedDecimal::percent(1525)
2703                .checked_rem(SignedDecimal::percent(400))
2704                .unwrap(),
2705            SignedDecimal::percent(325)
2706        );
2707        assert_eq!(
2708            SignedDecimal::percent(-1525)
2709                .checked_rem(SignedDecimal::percent(400))
2710                .unwrap(),
2711            SignedDecimal::percent(-325)
2712        );
2713        assert_eq!(
2714            SignedDecimal::percent(-1525)
2715                .checked_rem(SignedDecimal::percent(-400))
2716                .unwrap(),
2717            SignedDecimal::percent(-325)
2718        );
2719        assert!(matches!(
2720            SignedDecimal::MAX.checked_rem(SignedDecimal::zero()),
2721            Err(DivideByZeroError { .. })
2722        ));
2723    }
2724
2725    #[test]
2726    fn signed_decimal_pow_works() {
2727        assert_eq!(
2728            SignedDecimal::percent(200).pow(2),
2729            SignedDecimal::percent(400)
2730        );
2731        assert_eq!(
2732            SignedDecimal::percent(-200).pow(2),
2733            SignedDecimal::percent(400)
2734        );
2735        assert_eq!(
2736            SignedDecimal::percent(-200).pow(3),
2737            SignedDecimal::percent(-800)
2738        );
2739        assert_eq!(
2740            SignedDecimal::percent(200).pow(10),
2741            SignedDecimal::percent(102400)
2742        );
2743    }
2744
2745    #[test]
2746    #[should_panic]
2747    fn signed_decimal_pow_overflow_panics() {
2748        _ = SignedDecimal::MAX.pow(2u32);
2749    }
2750
2751    #[test]
2752    fn signed_decimal_saturating_works() {
2753        assert_eq!(
2754            SignedDecimal::percent(200).saturating_add(SignedDecimal::percent(200)),
2755            SignedDecimal::percent(400)
2756        );
2757        assert_eq!(
2758            SignedDecimal::percent(-200).saturating_add(SignedDecimal::percent(200)),
2759            SignedDecimal::zero()
2760        );
2761        assert_eq!(
2762            SignedDecimal::percent(-200).saturating_add(SignedDecimal::percent(-200)),
2763            SignedDecimal::percent(-400)
2764        );
2765        assert_eq!(
2766            SignedDecimal::MAX.saturating_add(SignedDecimal::percent(200)),
2767            SignedDecimal::MAX
2768        );
2769        assert_eq!(
2770            SignedDecimal::MIN.saturating_add(SignedDecimal::percent(-1)),
2771            SignedDecimal::MIN
2772        );
2773        assert_eq!(
2774            SignedDecimal::percent(200).saturating_sub(SignedDecimal::percent(100)),
2775            SignedDecimal::percent(100)
2776        );
2777        assert_eq!(
2778            SignedDecimal::percent(-200).saturating_sub(SignedDecimal::percent(100)),
2779            SignedDecimal::percent(-300)
2780        );
2781        assert_eq!(
2782            SignedDecimal::percent(-200).saturating_sub(SignedDecimal::percent(-100)),
2783            SignedDecimal::percent(-100)
2784        );
2785        assert_eq!(
2786            SignedDecimal::zero().saturating_sub(SignedDecimal::percent(200)),
2787            SignedDecimal::from_str("-2").unwrap()
2788        );
2789        assert_eq!(
2790            SignedDecimal::MIN.saturating_sub(SignedDecimal::percent(200)),
2791            SignedDecimal::MIN
2792        );
2793        assert_eq!(
2794            SignedDecimal::MAX.saturating_sub(SignedDecimal::percent(-200)),
2795            SignedDecimal::MAX
2796        );
2797        assert_eq!(
2798            SignedDecimal::percent(200).saturating_mul(SignedDecimal::percent(50)),
2799            SignedDecimal::percent(100)
2800        );
2801        assert_eq!(
2802            SignedDecimal::percent(-200).saturating_mul(SignedDecimal::percent(50)),
2803            SignedDecimal::percent(-100)
2804        );
2805        assert_eq!(
2806            SignedDecimal::percent(-200).saturating_mul(SignedDecimal::percent(-50)),
2807            SignedDecimal::percent(100)
2808        );
2809        assert_eq!(
2810            SignedDecimal::MAX.saturating_mul(SignedDecimal::percent(200)),
2811            SignedDecimal::MAX
2812        );
2813        assert_eq!(
2814            SignedDecimal::MIN.saturating_mul(SignedDecimal::percent(200)),
2815            SignedDecimal::MIN
2816        );
2817        assert_eq!(
2818            SignedDecimal::MIN.saturating_mul(SignedDecimal::percent(-200)),
2819            SignedDecimal::MAX
2820        );
2821        assert_eq!(
2822            SignedDecimal::percent(400).saturating_pow(2u32),
2823            SignedDecimal::percent(1600)
2824        );
2825        assert_eq!(SignedDecimal::MAX.saturating_pow(2u32), SignedDecimal::MAX);
2826        assert_eq!(SignedDecimal::MAX.saturating_pow(3u32), SignedDecimal::MAX);
2827        assert_eq!(SignedDecimal::MIN.saturating_pow(2u32), SignedDecimal::MAX);
2828        assert_eq!(SignedDecimal::MIN.saturating_pow(3u32), SignedDecimal::MIN);
2829    }
2830
2831    #[test]
2832    fn signed_decimal_rounding() {
2833        assert_eq!(SignedDecimal::one().floor(), SignedDecimal::one());
2834        assert_eq!(SignedDecimal::percent(150).floor(), SignedDecimal::one());
2835        assert_eq!(SignedDecimal::percent(199).floor(), SignedDecimal::one());
2836        assert_eq!(
2837            SignedDecimal::percent(200).floor(),
2838            SignedDecimal::percent(200)
2839        );
2840        assert_eq!(SignedDecimal::percent(99).floor(), SignedDecimal::zero());
2841        assert_eq!(
2842            SignedDecimal(Int128::from(1i128)).floor(),
2843            SignedDecimal::zero()
2844        );
2845        assert_eq!(
2846            SignedDecimal(Int128::from(-1i128)).floor(),
2847            SignedDecimal::negative_one()
2848        );
2849        assert_eq!(
2850            SignedDecimal::permille(-1234).floor(),
2851            SignedDecimal::percent(-200)
2852        );
2853
2854        assert_eq!(SignedDecimal::one().ceil(), SignedDecimal::one());
2855        assert_eq!(
2856            SignedDecimal::percent(150).ceil(),
2857            SignedDecimal::percent(200)
2858        );
2859        assert_eq!(
2860            SignedDecimal::percent(199).ceil(),
2861            SignedDecimal::percent(200)
2862        );
2863        assert_eq!(SignedDecimal::percent(99).ceil(), SignedDecimal::one());
2864        assert_eq!(
2865            SignedDecimal(Int128::from(1i128)).ceil(),
2866            SignedDecimal::one()
2867        );
2868        assert_eq!(
2869            SignedDecimal(Int128::from(-1i128)).ceil(),
2870            SignedDecimal::zero()
2871        );
2872        assert_eq!(
2873            SignedDecimal::permille(-1234).ceil(),
2874            SignedDecimal::negative_one()
2875        );
2876
2877        assert_eq!(SignedDecimal::one().trunc(), SignedDecimal::one());
2878        assert_eq!(SignedDecimal::percent(150).trunc(), SignedDecimal::one());
2879        assert_eq!(SignedDecimal::percent(199).trunc(), SignedDecimal::one());
2880        assert_eq!(
2881            SignedDecimal::percent(200).trunc(),
2882            SignedDecimal::percent(200)
2883        );
2884        assert_eq!(SignedDecimal::percent(99).trunc(), SignedDecimal::zero());
2885        assert_eq!(
2886            SignedDecimal(Int128::from(1i128)).trunc(),
2887            SignedDecimal::zero()
2888        );
2889        assert_eq!(
2890            SignedDecimal(Int128::from(-1i128)).trunc(),
2891            SignedDecimal::zero()
2892        );
2893        assert_eq!(
2894            SignedDecimal::permille(-1234).trunc(),
2895            SignedDecimal::negative_one()
2896        );
2897    }
2898
2899    #[test]
2900    #[should_panic(expected = "attempt to ceil with overflow")]
2901    fn signed_decimal_ceil_panics() {
2902        let _ = SignedDecimal::MAX.ceil();
2903    }
2904
2905    #[test]
2906    #[should_panic(expected = "attempt to floor with overflow")]
2907    fn signed_decimal_floor_panics() {
2908        let _ = SignedDecimal::MIN.floor();
2909    }
2910
2911    #[test]
2912    fn signed_decimal_checked_ceil() {
2913        assert_eq!(
2914            SignedDecimal::percent(199).checked_ceil(),
2915            Ok(SignedDecimal::percent(200))
2916        );
2917        assert_eq!(SignedDecimal::MAX.checked_ceil(), Err(RoundUpOverflowError));
2918    }
2919
2920    #[test]
2921    fn signed_decimal_checked_floor() {
2922        assert_eq!(
2923            SignedDecimal::percent(199).checked_floor(),
2924            Ok(SignedDecimal::one())
2925        );
2926        assert_eq!(
2927            SignedDecimal::percent(-199).checked_floor(),
2928            Ok(SignedDecimal::percent(-200))
2929        );
2930        assert_eq!(
2931            SignedDecimal::MIN.checked_floor(),
2932            Err(RoundDownOverflowError)
2933        );
2934        assert_eq!(
2935            SignedDecimal::negative_one().checked_floor(),
2936            Ok(SignedDecimal::negative_one())
2937        );
2938    }
2939
2940    #[test]
2941    fn signed_decimal_to_int_floor_works() {
2942        let d = SignedDecimal::from_str("12.000000000000000001").unwrap();
2943        assert_eq!(d.to_int_floor(), Int128::new(12));
2944        let d = SignedDecimal::from_str("12.345").unwrap();
2945        assert_eq!(d.to_int_floor(), Int128::new(12));
2946        let d = SignedDecimal::from_str("12.999").unwrap();
2947        assert_eq!(d.to_int_floor(), Int128::new(12));
2948        let d = SignedDecimal::from_str("0.98451384").unwrap();
2949        assert_eq!(d.to_int_floor(), Int128::new(0));
2950        let d = SignedDecimal::from_str("-12.000000000000000001").unwrap();
2951        assert_eq!(d.to_int_floor(), Int128::new(-13));
2952        let d = SignedDecimal::from_str("-12.345").unwrap();
2953        assert_eq!(d.to_int_floor(), Int128::new(-13));
2954        let d = SignedDecimal::from_str("75.0").unwrap();
2955        assert_eq!(d.to_int_floor(), Int128::new(75));
2956        let d = SignedDecimal::from_str("0.0001").unwrap();
2957        assert_eq!(d.to_int_floor(), Int128::new(0));
2958        let d = SignedDecimal::from_str("0.0").unwrap();
2959        assert_eq!(d.to_int_floor(), Int128::new(0));
2960        let d = SignedDecimal::from_str("-0.0").unwrap();
2961        assert_eq!(d.to_int_floor(), Int128::new(0));
2962        let d = SignedDecimal::from_str("-0.0001").unwrap();
2963        assert_eq!(d.to_int_floor(), Int128::new(-1));
2964        let d = SignedDecimal::from_str("-75.0").unwrap();
2965        assert_eq!(d.to_int_floor(), Int128::new(-75));
2966        let d = SignedDecimal::MAX;
2967        assert_eq!(d.to_int_floor(), Int128::new(170141183460469231731));
2968        let d = SignedDecimal::MIN;
2969        assert_eq!(d.to_int_floor(), Int128::new(-170141183460469231732));
2970    }
2971
2972    #[test]
2973    fn signed_decimal_to_int_ceil_works() {
2974        let d = SignedDecimal::from_str("12.000000000000000001").unwrap();
2975        assert_eq!(d.to_int_ceil(), Int128::new(13));
2976        let d = SignedDecimal::from_str("12.345").unwrap();
2977        assert_eq!(d.to_int_ceil(), Int128::new(13));
2978        let d = SignedDecimal::from_str("12.999").unwrap();
2979        assert_eq!(d.to_int_ceil(), Int128::new(13));
2980        let d = SignedDecimal::from_str("-12.000000000000000001").unwrap();
2981        assert_eq!(d.to_int_ceil(), Int128::new(-12));
2982        let d = SignedDecimal::from_str("-12.345").unwrap();
2983        assert_eq!(d.to_int_ceil(), Int128::new(-12));
2984
2985        let d = SignedDecimal::from_str("75.0").unwrap();
2986        assert_eq!(d.to_int_ceil(), Int128::new(75));
2987        let d = SignedDecimal::from_str("0.0").unwrap();
2988        assert_eq!(d.to_int_ceil(), Int128::new(0));
2989        let d = SignedDecimal::from_str("-75.0").unwrap();
2990        assert_eq!(d.to_int_ceil(), Int128::new(-75));
2991
2992        let d = SignedDecimal::MAX;
2993        assert_eq!(d.to_int_ceil(), Int128::new(170141183460469231732));
2994        let d = SignedDecimal::MIN;
2995        assert_eq!(d.to_int_ceil(), Int128::new(-170141183460469231731));
2996    }
2997
2998    #[test]
2999    fn signed_decimal_to_int_trunc_works() {
3000        let d = SignedDecimal::from_str("12.000000000000000001").unwrap();
3001        assert_eq!(d.to_int_trunc(), Int128::new(12));
3002        let d = SignedDecimal::from_str("12.345").unwrap();
3003        assert_eq!(d.to_int_trunc(), Int128::new(12));
3004        let d = SignedDecimal::from_str("12.999").unwrap();
3005        assert_eq!(d.to_int_trunc(), Int128::new(12));
3006        let d = SignedDecimal::from_str("-12.000000000000000001").unwrap();
3007        assert_eq!(d.to_int_trunc(), Int128::new(-12));
3008        let d = SignedDecimal::from_str("-12.345").unwrap();
3009        assert_eq!(d.to_int_trunc(), Int128::new(-12));
3010
3011        let d = SignedDecimal::from_str("75.0").unwrap();
3012        assert_eq!(d.to_int_trunc(), Int128::new(75));
3013        let d = SignedDecimal::from_str("0.0").unwrap();
3014        assert_eq!(d.to_int_trunc(), Int128::new(0));
3015        let d = SignedDecimal::from_str("-75.0").unwrap();
3016        assert_eq!(d.to_int_trunc(), Int128::new(-75));
3017
3018        let d = SignedDecimal::MAX;
3019        assert_eq!(d.to_int_trunc(), Int128::new(170141183460469231731));
3020        let d = SignedDecimal::MIN;
3021        assert_eq!(d.to_int_trunc(), Int128::new(-170141183460469231731));
3022    }
3023
3024    #[test]
3025    fn signed_decimal_neg_works() {
3026        assert_eq!(-SignedDecimal::percent(50), SignedDecimal::percent(-50));
3027        assert_eq!(-SignedDecimal::one(), SignedDecimal::negative_one());
3028    }
3029
3030    #[test]
3031    fn signed_decimal_partial_eq() {
3032        let test_cases = [
3033            ("1", "1", true),
3034            ("0.5", "0.5", true),
3035            ("0.5", "0.51", false),
3036            ("0", "0.00000", true),
3037            ("-1", "-1", true),
3038            ("-0.5", "-0.5", true),
3039            ("-0.5", "0.5", false),
3040            ("-0.5", "-0.51", false),
3041            ("-0", "-0.00000", true),
3042        ]
3043        .into_iter()
3044        .map(|(lhs, rhs, expected)| (dec(lhs), dec(rhs), expected));
3045
3046        #[allow(clippy::op_ref)]
3047        for (lhs, rhs, expected) in test_cases {
3048            assert_eq!(lhs == rhs, expected);
3049            assert_eq!(&lhs == rhs, expected);
3050            assert_eq!(lhs == &rhs, expected);
3051            assert_eq!(&lhs == &rhs, expected);
3052        }
3053    }
3054
3055    #[test]
3056    fn signed_decimal_implements_debug() {
3057        let decimal = SignedDecimal::from_str("123.45").unwrap();
3058        assert_eq!(format!("{decimal:?}"), "SignedDecimal(123.45)");
3059
3060        let test_cases = ["5", "5.01", "42", "0", "2", "-0.000001"];
3061        for s in test_cases {
3062            let decimal = SignedDecimal::from_str(s).unwrap();
3063            let expected = format!("SignedDecimal({s})");
3064            assert_eq!(format!("{decimal:?}"), expected);
3065        }
3066    }
3067
3068    #[test]
3069    fn signed_decimal_can_be_instantiated_from_decimal256() {
3070        let d: SignedDecimal = Decimal256::zero().try_into().unwrap();
3071        assert_eq!(d, SignedDecimal::zero());
3072    }
3073
3074    #[test]
3075    fn signed_decimal_may_fail_when_instantiated_from_decimal256() {
3076        let err = <Decimal256 as TryInto<SignedDecimal>>::try_into(Decimal256::MAX).unwrap_err();
3077        assert_eq!("SignedDecimalRangeExceeded", format!("{err:?}"));
3078        assert_eq!("SignedDecimal range exceeded", format!("{err}"));
3079    }
3080
3081    #[test]
3082    fn signed_decimal_can_be_serialized_and_deserialized() {
3083        // properly deserialized
3084        let value: SignedDecimal = serde_json::from_str(r#""123""#).unwrap();
3085        assert_eq!(SignedDecimal::from_str("123").unwrap(), value);
3086
3087        // properly serialized
3088        let value = SignedDecimal::from_str("456").unwrap();
3089        assert_eq!(r#""456""#, serde_json::to_string(&value).unwrap());
3090
3091        // invalid: not a string encoded decimal
3092        assert_eq!(
3093            "invalid type: integer `123`, expected string-encoded decimal at line 1 column 3",
3094            serde_json::from_str::<SignedDecimal>("123")
3095                .err()
3096                .unwrap()
3097                .to_string()
3098        );
3099
3100        // invalid: not properly defined signed decimal value
3101        assert_eq!(
3102            "Error parsing decimal '1.e': Generic error: Error parsing fractional at line 1 column 5",
3103            serde_json::from_str::<SignedDecimal>(r#""1.e""#)
3104                .err()
3105                .unwrap()
3106                .to_string()
3107        );
3108    }
3109
3110    #[test]
3111    fn signed_decimal_has_defined_json_schema() {
3112        let schema = schemars::schema_for!(SignedDecimal);
3113        assert_eq!(
3114            "SignedDecimal",
3115            schema.schema.metadata.unwrap().title.unwrap()
3116        );
3117    }
3118}