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}