1use super::{maybe_panic, FixedUInt, MachineWord, PanicReason};
2
3use num_traits::ops::overflowing::{OverflowingAdd, OverflowingSub};
4
5impl<T: MachineWord, const N: usize> num_traits::ops::overflowing::OverflowingAdd
6 for FixedUInt<T, N>
7{
8 fn overflowing_add(&self, other: &Self) -> (Self, bool) {
9 let mut ret = *self;
10 let overflow = Self::add_impl(&mut ret, other);
11 (ret, overflow)
12 }
13}
14
15impl<T: MachineWord, const N: usize> core::ops::Add for FixedUInt<T, N> {
16 type Output = Self;
17 fn add(self, other: Self) -> Self {
18 let (res, overflow) = self.overflowing_add(&other);
19 if overflow {
20 maybe_panic(PanicReason::Add);
21 }
22 res
23 }
24}
25
26impl<T: MachineWord, const N: usize> core::ops::Add<&'_ Self> for FixedUInt<T, N> {
27 type Output = Self;
28 fn add(self, other: &Self) -> Self {
29 let (res, overflow) = self.overflowing_add(other);
30 if overflow {
31 maybe_panic(PanicReason::Add);
32 }
33 res
34 }
35}
36
37impl<T: MachineWord, const N: usize> core::ops::Add<FixedUInt<T, N>> for &FixedUInt<T, N> {
38 type Output = FixedUInt<T, N>;
39 fn add(self, other: FixedUInt<T, N>) -> Self::Output {
40 let (res, overflow) = self.overflowing_add(&other);
41 if overflow {
42 maybe_panic(PanicReason::Add);
43 }
44 res
45 }
46}
47
48impl<T: MachineWord, const N: usize> core::ops::Add<Self> for &FixedUInt<T, N> {
49 type Output = FixedUInt<T, N>;
50 fn add(self, other: Self) -> Self::Output {
51 let (res, overflow) = self.overflowing_add(other);
52 if overflow {
53 maybe_panic(PanicReason::Add);
54 }
55 res
56 }
57}
58
59impl<T: MachineWord, const N: usize> num_traits::WrappingAdd for FixedUInt<T, N> {
60 fn wrapping_add(&self, other: &Self) -> Self {
61 self.overflowing_add(other).0
62 }
63}
64
65impl<T: MachineWord, const N: usize> num_traits::CheckedAdd for FixedUInt<T, N> {
66 fn checked_add(&self, other: &Self) -> Option<Self> {
67 let res = self.overflowing_add(other);
68 if res.1 {
69 None
70 } else {
71 Some(res.0)
72 }
73 }
74}
75
76impl<T: MachineWord, const N: usize> num_traits::ops::saturating::SaturatingAdd
77 for FixedUInt<T, N>
78{
79 fn saturating_add(&self, other: &Self) -> Self {
81 self.saturating_add_impl(other)
82 }
83}
84
85impl<T: MachineWord, const N: usize> core::ops::AddAssign<Self> for FixedUInt<T, N> {
86 fn add_assign(&mut self, other: Self) {
87 if Self::add_impl(self, &other) {
88 maybe_panic(PanicReason::Add);
89 }
90 }
91}
92
93impl<T: MachineWord, const N: usize> core::ops::AddAssign<&'_ Self> for FixedUInt<T, N> {
94 fn add_assign(&mut self, other: &Self) {
95 if Self::add_impl(self, other) {
96 maybe_panic(PanicReason::Add);
97 }
98 }
99}
100
101impl<T: MachineWord, const N: usize> num_traits::ops::overflowing::OverflowingSub
102 for FixedUInt<T, N>
103{
104 fn overflowing_sub(&self, other: &Self) -> (Self, bool) {
105 let mut ret = *self;
106 let overflow = Self::sub_impl(&mut ret, other);
107 (ret, overflow)
108 }
109}
110
111impl<T: MachineWord, const N: usize> core::ops::Sub for FixedUInt<T, N> {
112 type Output = Self;
113 fn sub(self, other: Self) -> <Self as core::ops::Sub<Self>>::Output {
114 let (res, overflow) = self.overflowing_sub(&other);
115 if overflow {
116 maybe_panic(PanicReason::Sub);
117 }
118 res
119 }
120}
121
122impl<T: MachineWord, const N: usize> core::ops::Sub<&'_ Self> for FixedUInt<T, N> {
123 type Output = Self;
124 fn sub(self, other: &Self) -> Self {
125 let (res, overflow) = self.overflowing_sub(other);
126 if overflow {
127 maybe_panic(PanicReason::Sub);
128 }
129 res
130 }
131}
132
133impl<T: MachineWord, const N: usize> core::ops::Sub<FixedUInt<T, N>> for &FixedUInt<T, N> {
134 type Output = FixedUInt<T, N>;
135 fn sub(self, other: FixedUInt<T, N>) -> Self::Output {
136 let (res, overflow) = self.overflowing_sub(&other);
137 if overflow {
138 maybe_panic(PanicReason::Sub);
139 }
140 res
141 }
142}
143
144impl<T: MachineWord, const N: usize> core::ops::Sub<Self> for &FixedUInt<T, N> {
145 type Output = FixedUInt<T, N>;
146 fn sub(self, other: Self) -> Self::Output {
147 let (res, overflow) = self.overflowing_sub(other);
148 if overflow {
149 maybe_panic(PanicReason::Sub);
150 }
151 res
152 }
153}
154
155impl<T: MachineWord, const N: usize> num_traits::WrappingSub for FixedUInt<T, N> {
156 fn wrapping_sub(&self, other: &Self) -> Self {
157 self.overflowing_sub(other).0
158 }
159}
160
161impl<T: MachineWord, const N: usize> num_traits::CheckedSub for FixedUInt<T, N> {
162 fn checked_sub(&self, other: &Self) -> Option<Self> {
163 let res = self.overflowing_sub(other);
164 if res.1 {
165 None
166 } else {
167 Some(res.0)
168 }
169 }
170}
171
172impl<T: MachineWord, const N: usize> num_traits::ops::saturating::SaturatingSub
173 for FixedUInt<T, N>
174{
175 fn saturating_sub(&self, other: &Self) -> Self {
177 self.saturating_sub_impl(other)
178 }
179}
180
181impl<T: MachineWord, const N: usize> core::ops::SubAssign<Self> for FixedUInt<T, N> {
182 fn sub_assign(&mut self, other: Self) {
183 if Self::sub_impl(self, &other) {
184 maybe_panic(PanicReason::Sub);
185 }
186 }
187}
188
189impl<T: MachineWord, const N: usize> core::ops::SubAssign<&'_ Self> for FixedUInt<T, N> {
190 fn sub_assign(&mut self, other: &Self) {
191 if Self::sub_impl(self, other) {
192 maybe_panic(PanicReason::Sub);
193 }
194 }
195}
196
197impl<T: MachineWord, const N: usize> num_traits::Saturating for FixedUInt<T, N> {
199 fn saturating_add(self, other: Self) -> Self {
201 self.saturating_add_impl(&other)
202 }
203
204 fn saturating_sub(self, other: Self) -> Self {
206 self.saturating_sub_impl(&other)
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213
214 #[test]
215 fn test_add_combinations() {
216 let a = FixedUInt::<u8, 2>::from(12u8);
217 let b = FixedUInt::<u8, 2>::from(3u8);
218 let expected = FixedUInt::<u8, 2>::from(15u8);
219
220 assert_eq!(a + b, expected);
222 assert_eq!(a + &b, expected);
224 assert_eq!(&a + b, expected);
226 assert_eq!(&a + &b, expected);
228 }
229
230 #[test]
231 fn test_sub_combinations() {
232 let a = FixedUInt::<u8, 2>::from(15u8);
233 let b = FixedUInt::<u8, 2>::from(3u8);
234 let expected = FixedUInt::<u8, 2>::from(12u8);
235
236 assert_eq!(a - b, expected);
238 assert_eq!(a - &b, expected);
240 assert_eq!(&a - b, expected);
242 assert_eq!(&a - &b, expected);
244 }
245}