opis/integer/
addition.rs

1
2use crate::{Integer, Bit};
3use std::ops::{Add, AddAssign};
4
5impl Add for Integer {
6    type Output = Self;
7    fn add(self, b: Self) -> Self {
8        &self + &b
9    }
10}
11
12impl Add for &Integer {
13
14    type Output = Integer;
15
16    fn add(self, b: Self) -> Integer {
17
18        if self == &Integer::zero() {
19            b.clone()
20        } else if b == &Integer::zero() {
21            self.clone()
22        } else {
23            let sum_bits = adder(&self.0, &b.0);
24            let mut result = Integer(sum_bits);
25            result.truncate();
26            result
27        }
28
29    }
30}
31
32impl Add<&u8> for &Integer {
33    type Output = Integer;
34    fn add(self, b: &u8) -> Integer {
35        let b_int: Integer = b.into();
36        self + &b_int
37    }
38}
39
40impl Add<&u16> for &Integer {
41    type Output = Integer;
42    fn add(self, b: &u16) -> Integer {
43        let b_int: Integer = b.into();
44        self + &b_int
45    }
46}
47
48impl Add<&u32> for &Integer {
49    type Output = Integer;
50    fn add(self, b: &u32) -> Integer {
51        let b_int: Integer = b.into();
52        self + &b_int
53    }
54}
55
56impl Add<&u64> for &Integer {
57    type Output = Integer;
58    fn add(self, b: &u64) -> Integer {
59        let b_int: Integer = b.into();
60        self + &b_int
61    }
62}
63
64impl Add<&u128> for &Integer {
65    type Output = Integer;
66    fn add(self, b: &u128) -> Integer {
67        let b_int: Integer = b.into();
68        self + &b_int
69    }
70}
71
72impl Add<&usize> for &Integer {
73    type Output = Integer;
74    fn add(self, b: &usize) -> Integer {
75        let b_int: Integer = b.into();
76        self + &b_int
77    }
78}
79
80impl AddAssign for Integer {
81    fn add_assign(&mut self, b: Self) {
82        *self = &self.clone() + &b
83    }
84}
85
86impl AddAssign<&Integer> for Integer {
87    fn add_assign(&mut self, b: &Integer) {
88        *self = &self.clone() + b
89    }
90}
91
92impl AddAssign<&u8> for Integer {
93    fn add_assign(&mut self, b: &u8) {
94        let b_int: Integer = b.into();
95        *self = &self.clone() + &b_int
96    }
97}
98
99impl AddAssign<&u16> for Integer {
100    fn add_assign(&mut self, b: &u16) {
101        let b_int: Integer = b.into();
102        *self = &self.clone() + &b_int
103    }
104}
105
106impl AddAssign<&u32> for Integer {
107    fn add_assign(&mut self, b: &u32) {
108        let b_int: Integer = b.into();
109        *self = &self.clone() + &b_int
110    }
111}
112
113impl AddAssign<&u64> for Integer {
114    fn add_assign(&mut self, b: &u64) {
115        let b_int: Integer = b.into();
116        *self = &self.clone() + &b_int
117    }
118}
119
120impl AddAssign<&u128> for Integer {
121    fn add_assign(&mut self, b: &u128) {
122        let b_int: Integer = b.into();
123        *self = &self.clone() + &b_int
124    }
125}
126
127impl AddAssign<&usize> for Integer {
128    fn add_assign(&mut self, b: &usize) {
129        let b_int: Integer = b.into();
130        *self = &self.clone() + &b_int
131    }
132}
133
134pub fn adder(a: &[Bit], b: &[Bit]) -> Vec<Bit> {
135    
136    let precision = if a.len() > b.len() { a.len() } else { b.len() } + 1;
137
138    let mut a_pos = a.len() - 1;
139
140    let mut b_pos = b.len() - 1;
141
142    let mut carry = Bit::Zero;
143
144    (0..precision)
145        .into_iter()
146        .rev()
147        .fold(
148            vec![],
149            |sum, _|
150            {
151
152                let a_bit = if a_pos == 0 { a[0] } else { let r = a[a_pos]; a_pos -= 1; r };
153                
154                let b_bit = if b_pos == 0 { b[0] } else { let r = b[b_pos]; b_pos -= 1; r };
155
156                let (carry_1, sum_1) = carry + a_bit;
157
158                let (carry_2, sum_2) = sum_1 + b_bit;
159
160                carry = carry_1 ^ carry_2;
161
162                vec![sum_2].into_iter().chain(sum.into_iter()).collect()
163
164            }
165        
166        )
167
168}
169
170#[cfg(test)]
171mod tests {
172    
173    use super::*;
174
175    #[test]
176    fn test_int_plus_int() {
177        assert_eq!(Integer::one() + Integer::one(), Integer::two());
178    }
179
180    #[test]
181    fn test_int_plus_u8() {
182        assert_eq!(&Integer::one() + &1_u8, Integer::two());
183    }
184
185}