1use std::ops::Add;
2use std::ops::AddAssign;
3
4use crate::bits::Bits;
5use crate::signed_bits::SignedBits;
6
7impl<const N: usize> Add<u128> for Bits<N> {
8 type Output = Self;
9 fn add(self, rhs: u128) -> Self::Output {
10 self + Bits::<N>::from(rhs)
11 }
12}
13
14impl<const N: usize> Add<Bits<N>> for u128 {
15 type Output = Bits<N>;
16 fn add(self, rhs: Bits<N>) -> Self::Output {
17 Bits::<N>::from(self) + rhs
18 }
19}
20
21impl<const N: usize> Add<Bits<N>> for Bits<N> {
22 type Output = Self;
23 #[allow(clippy::suspicious_arithmetic_impl)]
24 fn add(self, rhs: Self) -> Self::Output {
25 Self(u128::wrapping_add(self.0, rhs.0) & Self::mask().0)
26 }
27}
28
29impl<const N: usize> AddAssign<Bits<N>> for Bits<N> {
30 fn add_assign(&mut self, rhs: Bits<N>) {
31 *self = *self + rhs;
32 }
33}
34
35impl<const N: usize> AddAssign<u128> for Bits<N> {
36 fn add_assign(&mut self, rhs: u128) {
37 *self = *self + rhs;
38 }
39}
40
41impl<const N: usize> Add<i128> for SignedBits<N> {
42 type Output = Self;
43 fn add(self, rhs: i128) -> Self::Output {
44 self + SignedBits::<N>::from(rhs)
45 }
46}
47
48impl<const N: usize> Add<SignedBits<N>> for i128 {
49 type Output = SignedBits<N>;
50 fn add(self, rhs: SignedBits<N>) -> Self::Output {
51 SignedBits::<N>::from(self) + rhs
52 }
53}
54
55impl<const N: usize> Add<SignedBits<N>> for SignedBits<N> {
56 type Output = Self;
57 fn add(self, rhs: Self) -> Self::Output {
58 (self.as_unsigned() + rhs.as_unsigned()).as_signed()
61 }
62}
63
64impl<const N: usize> AddAssign<i128> for SignedBits<N> {
65 fn add_assign(&mut self, rhs: i128) {
66 *self = *self + rhs;
67 }
68}
69
70impl<const N: usize> AddAssign<SignedBits<N>> for SignedBits<N> {
71 fn add_assign(&mut self, rhs: SignedBits<N>) {
72 *self = *self + rhs;
73 }
74}
75
76#[cfg(test)]
77mod test {
78 use super::*;
79
80 #[test]
81 fn test_add_bits() {
82 let bits: Bits<8> = 0b1101_1010.into();
83 let result = bits + bits;
84 assert_eq!(result.0, 180_u128);
85 let bits: Bits<8> = 0b1101_1010.into();
86 let result = bits + bits + bits;
87 assert_eq!(result.0, 142_u128);
88 let mut bits: Bits<128> = 0.into();
89 bits.set_bit(127, true);
90 let result = bits + bits;
91 assert_eq!(result.0, 0_u128);
92 let bits: Bits<54> = 0b1101_1010.into();
93 let result = bits + 1;
94 assert_eq!(result.0, 219_u128);
95 let result = 1 + bits;
96 assert_eq!(result.0, 219_u128);
97 }
98
99 #[test]
100 fn test_add_assign_bits() {
101 let mut bits: Bits<8> = 0b1101_1010.into();
102 bits += bits;
103 assert_eq!(bits.0, 180_u128);
104 let mut bits: Bits<8> = 0b1101_1010.into();
105 bits += bits;
106 bits += bits;
107 assert_eq!(bits.0, ((218 * 4) as u128) & 0xff);
108 let mut bits: Bits<128> = 0.into();
109 bits.set_bit(127, true);
110 bits += bits;
111 assert_eq!(bits.0, 0_u128);
112 let mut bits: Bits<54> = 0b1101_1010.into();
113 bits += 1;
114 assert_eq!(bits.0, 219_u128);
115 }
116
117 #[test]
118 fn test_signed_addition_matches_built_in_behavior_for_i8() {
119 for i in i8::MIN..i8::MAX {
120 for j in i8::MIN..i8::MAX {
121 let i_as_signed = SignedBits::<8>::from(i as i128);
122 let j_as_signed = SignedBits::<8>::from(j as i128);
123 let k_as_signed = i_as_signed + j_as_signed;
124 let k = i8::wrapping_add(i, j);
125 assert_eq!(k_as_signed.0, k as i128);
126 }
127 }
128 }
129
130 #[test]
131 fn test_signed_addition_matches_built_in_behavior_for_i64() {
132 for i in [i64::MIN, -1, 0, 1, i64::MAX] {
133 for j in [i64::MIN, -1, 0, 1, i64::MAX] {
134 let i_as_signed = SignedBits::<64>::from(i as i128);
135 let j_as_signed = SignedBits::<64>::from(j as i128);
136 let k_as_signed = i_as_signed + j_as_signed;
137 let k = i64::wrapping_add(i, j);
138 assert_eq!(k_as_signed.0, k as i128);
139 }
140 }
141 }
142
143 #[test]
144 fn test_signed_addition_matches_built_in_behavior_for_i128() {
145 for i in [i128::MIN, -1, 0, 1, i128::MAX] {
146 for j in [i128::MIN, -1, 0, 1, i128::MAX] {
147 let i_as_signed = SignedBits::<128>::from(i);
148 let j_as_signed = SignedBits::<128>::from(j);
149 let k_as_signed = i_as_signed + j_as_signed;
150 let k = i128::wrapping_add(i, j);
151 assert_eq!(k_as_signed.0, k);
152 }
153 }
154 }
155
156 #[test]
157 fn test_add_assign_signed() {
158 let mut x = SignedBits::<8>::from(1);
159 x += SignedBits::<8>::from(-2);
160 assert_eq!(x.0, -1);
161 x += 7;
162 assert_eq!(x.0, 6);
163 }
164}