Skip to main content

cosmwasm_std/math/
signed_decimal.rs

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