cosmwasm_std/math/
signed_decimal.rs

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