numera/number/integer/z/ops/
sub.rs

1// numera::number::integer::z::ops::sub
2//
3//! Implement the subtraction operations.
4//
5
6use crate::number::integer::*;
7use core::ops::{Sub, SubAssign};
8use devela::paste;
9
10macro_rules! impl_integer_sub {
11    // impl Sub ops for multiple integer types
12    //
13    // # Args
14    // $t: integer base name. e.g. Integer
15    // $p: inner primitive base name. e.g. i
16    // $b: integer and primitive bitsize. e.g. 8
17    ( $($t:ident + $p:ident + $b:literal, cast: $bcast:literal);+ ) => {
18        $(
19            impl_integer_sub![sub: $t + $p + $b];
20        )+
21    };
22
23    // subtraction operations
24    //
25    // impl variants:
26    // - sub
27    // - checked_
28    // - saturating_
29    // - wrapping_
30    // - overflowing_
31    // - modular_ TODO
32    // - modular_counting_ TODO
33    (sub: $t:ident + $p:ident + $b:literal) => { paste! {
34        impl Sub<[<$t$b>]> for [<$t$b>] {
35            type Output = [<$t$b>];
36            /// Performs the `-` operation.
37            ///
38            /// # Panics
39            /// Panics in debug, on overflow.
40            /// While in release, it performs two's complement wrapping.
41            #[inline]
42            #[must_use]
43            fn sub(self, rhs: [<$t$b>]) -> Self::Output {
44                self.sub(rhs)
45            }
46        }
47        impl SubAssign for [<$t$b>] {
48            /// Performs the `-=` operation.
49            ///
50            /// # Panics
51            /// Panics in debug, on overflow.
52            /// While in release, it performs two's complement wrapping.
53            #[inline]
54            fn sub_assign(&mut self, rhs: [<$t$b>]) {
55                *self = self.add(rhs);
56            }
57        }
58        /// # Subtraction
59        impl [<$t$b>] {
60            /// Integer subtraction.
61            ///
62            /// # Panics
63            /// Panics in debug, on overflow.
64            /// While in release, it performs two's complement wrapping.
65            #[inline]
66            #[must_use]
67            pub const fn sub(self, rhs: [<$t$b>]) -> [<$t$b>] {
68                Self(self.0 - rhs.0)
69            }
70
71            /// Checked subtraction.
72            #[inline]
73            #[must_use]
74            pub const fn checked_sub(self, rhs: [<$t$b>]) -> Option<[<$t$b>]> {
75                if let Some(result) = self.0.checked_sub(rhs.0) {
76                    Some(Self(result))
77                } else {
78                    None
79                }
80            }
81
82            /// Saturating subtraction.
83            /// Computes `self + rhs`, saturating at the numeric bounds instead of overflowing.
84            #[inline]
85            #[must_use]
86            pub const fn saturating_sub(self, rhs: [<$t$b>]) -> [<$t$b>] {
87                Self(self.0.saturating_sub(rhs.0))
88            }
89
90            /// Wrapping (modular) subtraction.
91            /// Computes `self + rhs`, wrapping around at the boundary of the type.
92            #[inline]
93            #[must_use]
94            pub const fn wrapping_sub(self, rhs: [<$t$b>]) -> [<$t$b>] {
95                Self(self.0.wrapping_sub(rhs.0))
96            }
97
98            /// Overflowing subtraction.
99            ///
100            /// Returns a tuple of the subtraction along with a boolean indicating
101            /// whether an arithmetic overflow would occur. If an overflow would
102            /// have occurred then the wrapped value is returned.
103            #[inline]
104            #[must_use]
105            pub const fn overflowing_sub(self, rhs: [<$t$b>]) -> ([<$t$b>], bool) {
106                let (result, overflown) = self.0.overflowing_sub(rhs.0);
107                (Self(result), overflown)
108            }
109
110            // /// Modular subtraction with a custom `modulo`.
111            // #[inline]
112            // #[must_use]
113            // pub const fn modular_sub(self, rhs: [<$t$b>], modulo: [<$t$b>]) -> [<$t$b>] {
114            //     self.sub(rhs).rem_euclid(modulo)
115            // }
116        }
117    }};
118}
119
120impl_integer_sub![
121    Integer+i+8, cast:16;
122    Integer+i+16, cast:32;
123    Integer+i+32, cast:64;
124    Integer+i+64, cast:128;
125    Integer+i+128, cast:128
126];
127
128#[cfg(feature = "dashu-int")]
129mod big {
130    use super::*;
131
132    impl Sub<IntegerBig> for IntegerBig {
133        type Output = IntegerBig;
134        /// Performs the `-` operation.
135        #[inline]
136        #[must_use]
137        fn sub(self, rhs: IntegerBig) -> Self::Output {
138            Self(self.0 - rhs.0)
139        }
140    }
141    impl SubAssign for IntegerBig {
142        /// Performs the `-=` operation.
143        #[inline]
144        fn sub_assign(&mut self, rhs: IntegerBig) {
145            self.0 -= rhs.0;
146        }
147    }
148}