rhdl_bits/
sub.rs

1use std::ops::Sub;
2use std::ops::SubAssign;
3
4use crate::bits::Bits;
5use crate::signed_bits::SignedBits;
6
7impl<const N: usize> Sub<Bits<N>> for Bits<N> {
8    type Output = Self;
9    #[allow(clippy::suspicious_arithmetic_impl)]
10    fn sub(self, rhs: Self) -> Self::Output {
11        Self(u128::wrapping_sub(self.0, rhs.0) & Self::mask().0)
12    }
13}
14
15impl<const N: usize> Sub<Bits<N>> for u128 {
16    type Output = Bits<N>;
17    fn sub(self, rhs: Bits<N>) -> Self::Output {
18        Bits::<N>::from(self) - rhs
19    }
20}
21
22impl<const N: usize> Sub<u128> for Bits<N> {
23    type Output = Self;
24    fn sub(self, rhs: u128) -> Self::Output {
25        self - Bits::<N>::from(rhs)
26    }
27}
28
29impl<const N: usize> SubAssign<u128> for Bits<N> {
30    fn sub_assign(&mut self, rhs: u128) {
31        *self = *self - rhs;
32    }
33}
34
35impl<const N: usize> SubAssign<Bits<N>> for Bits<N> {
36    fn sub_assign(&mut self, rhs: Bits<N>) {
37        *self = *self - rhs;
38    }
39}
40
41impl<const N: usize> Sub<SignedBits<N>> for SignedBits<N> {
42    type Output = Self;
43    fn sub(self, rhs: Self) -> Self::Output {
44        (self.as_unsigned() - rhs.as_unsigned()).as_signed()
45    }
46}
47
48impl<const N: usize> Sub<i128> for SignedBits<N> {
49    type Output = Self;
50    fn sub(self, rhs: i128) -> Self::Output {
51        self - SignedBits::<N>::from(rhs)
52    }
53}
54
55impl<const N: usize> SubAssign<i128> for SignedBits<N> {
56    fn sub_assign(&mut self, rhs: i128) {
57        *self = *self - rhs;
58    }
59}
60
61impl<const N: usize> SubAssign<SignedBits<N>> for SignedBits<N> {
62    fn sub_assign(&mut self, rhs: SignedBits<N>) {
63        *self = *self - rhs;
64    }
65}
66
67#[cfg(test)]
68mod test {
69    use super::*;
70    use std::num::Wrapping;
71
72    #[test]
73    fn test_sub_bits() {
74        let bits: Bits<8> = 0b1101_1010.into();
75        let result = bits - bits;
76        assert_eq!(result.0, 0_u128);
77        let x: std::num::Wrapping<u8> = Wrapping(0b1101_1010);
78        let bits: Bits<8> = 0b1101_1010.into();
79        let result = bits - bits - bits;
80        assert_eq!(Wrapping(result.0 as u8), x - x - x);
81        let mut bits: Bits<128> = 0.into();
82        bits.set_bit(127, true);
83        let result = bits - bits;
84        assert_eq!(result.0, 0_u128);
85        let bits: Bits<54> = 0b1101_1010.into();
86        let result = bits - 1;
87        let bits_m_1: Bits<54> = 0b1101_1001.into();
88        assert_eq!(result, bits_m_1);
89        let result = 1 - bits;
90        // The 2s complement equivalent of 1 - x is 1 + (x::mask() - x) + 1
91        // which is 2 + (x::mask() - x)
92        assert_eq!(result.0, 2 + (Bits::<54>::mask().0 - bits.0));
93    }
94
95    #[test]
96    fn test_subassign_bits() {
97        let mut bits: Bits<8> = 0b1101_1010.into();
98        let bits_m_1: Bits<8> = 0b1101_1001.into();
99        bits -= bits_m_1;
100        assert_eq!(bits.0, 1_u128);
101        let mut bits: Bits<8> = 0b1101_1010.into();
102        bits -= 1;
103        assert_eq!(bits.0, 0b1101_1001_u128);
104    }
105
106    #[test]
107    fn test_subtraction_i8() {
108        for i in i8::MIN..i8::MAX {
109            for j in i8::MIN..i8::MAX {
110                let signed_i: SignedBits<8> = (i as i128).into();
111                let signed_j: SignedBits<8> = (j as i128).into();
112                let signed_k = signed_i - signed_j;
113                let built_in_k = i8::wrapping_sub(i, j) as i128;
114                assert_eq!(signed_k.0, built_in_k);
115            }
116        }
117    }
118
119    #[test]
120    fn test_subtraction_i128() {
121        for i in [i128::MIN, -1, 0, 1, i128::MAX] {
122            for j in [i128::MIN, -1, 0, 1, i128::MAX] {
123                let signed_i: SignedBits<128> = i.into();
124                let signed_j: SignedBits<128> = j.into();
125                let signed_k = signed_i - signed_j;
126                let built_in_k = i.wrapping_sub(j);
127                assert_eq!(signed_k.0, built_in_k);
128            }
129        }
130    }
131
132    #[test]
133    fn test_subassign() {
134        let mut x = SignedBits::<8>::from(1);
135        x -= SignedBits::<8>::from(-2);
136        assert_eq!(x.0, 3);
137    }
138}