bigdecimal/
impl_ops_add.rs

1//! Addition operator trait implementation
2//!
3
4use super::*;
5use stdlib::borrow::ToOwned;
6
7
8impl Add<BigDecimal> for BigDecimal {
9    type Output = BigDecimal;
10
11    #[inline]
12    fn add(self, rhs: BigDecimal) -> BigDecimal {
13        arithmetic::addition::add_bigdecimals(self, rhs)
14    }
15}
16
17impl<'a, T: Into<BigDecimalRef<'a>>> Add<T> for BigDecimal {
18    type Output = BigDecimal;
19
20    fn add(mut self, rhs: T) -> BigDecimal {
21        self.add_assign(rhs);
22        self
23    }
24}
25
26impl Add<BigInt> for BigDecimal {
27    type Output = BigDecimal;
28
29    #[inline]
30    fn add(self, rhs: BigInt) -> BigDecimal {
31        self + BigDecimal::from(rhs)
32    }
33}
34
35
36
37impl Add<BigDecimal> for &'_ BigDecimal {
38    type Output = BigDecimal;
39
40    #[inline]
41    fn add(self, rhs: BigDecimal) -> BigDecimal {
42        rhs + self
43    }
44}
45
46impl<'a, T: Into<BigDecimalRef<'a>>> Add<T> for &'_ BigDecimal {
47    type Output = BigDecimal;
48    fn add(self, rhs: T) -> BigDecimal {
49        arithmetic::addition::add_bigdecimal_refs(self, rhs, None)
50    }
51}
52
53impl Add<BigInt> for &'_ BigDecimal {
54    type Output = BigDecimal;
55
56    #[inline]
57    fn add(self, rhs: BigInt) -> BigDecimal {
58        self.to_ref() + rhs
59    }
60}
61
62
63impl Add<BigDecimal> for BigDecimalRef<'_> {
64    type Output = BigDecimal;
65
66    #[inline]
67    fn add(self, rhs: BigDecimal) -> BigDecimal {
68        rhs + self
69    }
70}
71
72impl<'a, T: Into<BigDecimalRef<'a>>> Add<T> for BigDecimalRef<'_> {
73    type Output = BigDecimal;
74    fn add(self, rhs: T) -> BigDecimal {
75        arithmetic::addition::add_bigdecimal_refs(self, rhs, None)
76    }
77}
78
79impl Add<BigInt> for BigDecimalRef<'_> {
80    type Output = BigDecimal;
81
82    #[inline]
83    fn add(self, rhs: BigInt) -> BigDecimal {
84        self + BigDecimal::from(rhs)
85    }
86}
87
88
89impl Add<BigDecimal> for BigInt {
90    type Output = BigDecimal;
91
92    #[inline]
93    fn add(self, rhs: BigDecimal) -> BigDecimal {
94        BigDecimal::from(self) + rhs
95    }
96}
97
98impl Add<&BigDecimal> for BigInt {
99    type Output = BigDecimal;
100
101    fn add(self, rhs: &BigDecimal) -> BigDecimal {
102        BigDecimal::from(self) + rhs
103    }
104}
105
106impl Add<BigDecimalRef<'_>> for BigInt {
107    type Output = BigDecimal;
108
109    fn add(self, rhs: BigDecimalRef<'_>) -> BigDecimal {
110        BigDecimal::from(self) + rhs
111    }
112}
113
114
115impl Add<BigDecimal> for &BigInt {
116    type Output = BigDecimal;
117
118    #[inline]
119    fn add(self, rhs: BigDecimal) -> BigDecimal {
120        rhs + self
121    }
122}
123
124impl Add<&BigDecimal> for &BigInt {
125    type Output = BigDecimal;
126
127    #[inline]
128    fn add(self, rhs: &BigDecimal) -> BigDecimal {
129        rhs + self
130    }
131}
132
133impl Add<BigDecimalRef<'_>> for &BigInt {
134    type Output = BigDecimal;
135
136    #[inline]
137    fn add(self, rhs: BigDecimalRef<'_>) -> BigDecimal {
138        rhs + self
139    }
140}
141
142
143impl AddAssign<BigDecimal> for BigDecimal {
144    fn add_assign(&mut self, rhs: BigDecimal) {
145        arithmetic::addition::addassign_bigdecimals(self, rhs)
146    }
147}
148
149impl<'a, N: Into<BigDecimalRef<'a>>> AddAssign<N> for BigDecimal {
150    #[inline]
151    fn add_assign(&mut self, rhs: N) {
152        arithmetic::addition::addassign_bigdecimal_ref(self, rhs)
153    }
154}
155
156impl AddAssign<BigInt> for BigDecimal {
157    #[inline]
158    fn add_assign(&mut self, rhs: BigInt) {
159        self.add_assign(BigDecimal::from(rhs));
160    }
161}
162
163
164#[cfg(test)]
165mod test {
166    use super::*;
167    use paste::paste;
168
169    macro_rules! impl_case {
170        ( $name:ident: $a:literal + $b:literal => $c:literal ) => {
171            #[test]
172            fn $name() {
173                let a: BigDecimal = $a.parse().unwrap();
174                let b: BigDecimal = $b.parse().unwrap();
175                let c: BigDecimal = $c.parse().unwrap();
176
177                assert_eq!(c, a.clone() + b.clone());
178                assert_eq!(c, a.clone() + b.to_ref());
179                assert_eq!(c, a.clone() + &b);
180
181                assert_eq!(c, &a + b.clone());
182                assert_eq!(c, &a + b.to_ref());
183                assert_eq!(c, &a + &b);
184
185                assert_eq!(c, a.to_ref() + b.clone());
186                assert_eq!(c, a.to_ref() + b.to_ref());
187                assert_eq!(c, a.to_ref() + &b);
188
189                // Reversed
190
191                assert_eq!(c, b.clone() + a.clone());
192                assert_eq!(c, b.clone() + a.to_ref());
193                assert_eq!(c, b.clone() + &a);
194
195                assert_eq!(c, &b + a.clone());
196                assert_eq!(c, &b + a.to_ref());
197                assert_eq!(c, &b + &a);
198
199                assert_eq!(c, b.to_ref() + a.clone());
200                assert_eq!(c, b.to_ref() + a.to_ref());
201                assert_eq!(c, b.to_ref() + &a);
202
203                let mut n = a.clone();
204                n += b.clone();
205                assert_eq!(c, n);
206
207                let mut n = a.clone();
208                n += &b;
209                assert_eq!(c, n);
210
211                let mut n = a.clone();
212                n += b.to_ref();
213                assert_eq!(c, n);
214
215                let mut n = b.clone();
216                n += a.clone();
217                assert_eq!(c, n);
218
219                let mut n = b.clone();
220                n += &a;
221                assert_eq!(c, n);
222
223                let mut n = b.clone();
224                n += a.to_ref();
225                assert_eq!(c, n);
226            }
227        };
228        ( $name:ident: $a:literal + (int) $b:literal => $c:literal ) => {
229            #[test]
230            fn $name() {
231                let a: BigDecimal = $a.parse().unwrap();
232                let b: BigInt = $b.parse().unwrap();
233                let c: BigDecimal = $c.parse().unwrap();
234
235                assert_eq!(c, a.clone() + b.clone());
236                assert_eq!(c, a.clone() + &b);
237                assert_eq!(c, &a + &b);
238                assert_eq!(c, &a + b.clone());
239                assert_eq!(c, a.to_ref() + &b);
240
241                assert_eq!(c, b.clone() + a.clone());
242                assert_eq!(c, b.clone() + a.to_ref());
243                assert_eq!(c, b.clone() + &a);
244
245                assert_eq!(c, &b + a.clone());
246                assert_eq!(c, &b + a.to_ref());
247                assert_eq!(c, &b + &a);
248
249                let mut n = a.clone();
250                n += b.clone();
251                assert_eq!(c, n);
252
253                let mut n = a.clone();
254                n += &b;
255                assert_eq!(c, n);
256            }
257        };
258    }
259
260    impl_case!(case_1234en2_1234en3: "12.34" + "1.234" => "13.574");
261    impl_case!(case_1234en2_n1234en3: "12.34" + "-1.234" => "11.106");
262    impl_case!(case_1234en2_n1234en2: "12.34" + "-12.34" => "0");
263    impl_case!(case_1234e6_1234en6: "1234e6" + "1234e-6" => "1234000000.001234");
264    impl_case!(case_1234en6_1234e6: "1234e6" + "1234e-6" => "1234000000.001234");
265    impl_case!(case_18446744073709551616_1: "18446744073709551616.0" + "1" => "18446744073709551617");
266    impl_case!(case_184467440737e3380_0: "184467440737e3380" + "0" => "184467440737e3380");
267    impl_case!(case_0_776en1: "0" + "77.6" => "77.6");
268
269    impl_case!(case_80802295e5_int0: "80802295e5" + (int)"0" => "80802295e5");
270    impl_case!(case_239200en4_intneg101: "23.9200" + (int)"-101" => "-77.0800");
271    impl_case!(case_46636423395767125en15_int0: "46.636423395767125" + (int)"123" => "169.636423395767125");
272
273
274    #[cfg(property_tests)]
275    mod prop {
276        use super::*;
277        use proptest::*;
278        use num_traits::FromPrimitive;
279
280        proptest! {
281            #[test]
282            fn add_refs_and_owners(f: f32, g: f32) {
283                // ignore non-normal numbers
284                prop_assume!(f.is_normal());
285                prop_assume!(g.is_normal());
286
287                let a = BigDecimal::from_f32(f).unwrap();
288                let b = BigDecimal::from_f32(g).unwrap();
289                let own_plus_ref = a.clone() + &b;
290                let ref_plus_own = &a + b.clone();
291
292                let mut c = a.clone();
293                c += &b;
294
295                let mut d = a.clone();
296                d += b;
297
298                prop_assert_eq!(&own_plus_ref, &ref_plus_own);
299                prop_assert_eq!(&c, &ref_plus_own);
300                prop_assert_eq!(&d, &ref_plus_own);
301            }
302
303            #[test]
304            fn addition_is_communative(f: f32, g: f32) {
305                // ignore non-normal numbers
306                prop_assume!(f.is_normal());
307                prop_assume!(g.is_normal());
308
309                let a = BigDecimal::from_f32(f).unwrap();
310                let b = BigDecimal::from_f32(g).unwrap();
311                let a_plus_b = &a + &b;
312                let b_plus_a = &b + &a;
313
314                prop_assert_eq!(a_plus_b, b_plus_a)
315            }
316
317            #[test]
318            fn addition_is_associative(f: f32, g: f32, h: f32) {
319                // ignore non-normal numbers
320                prop_assume!(f.is_normal());
321                prop_assume!(g.is_normal());
322                prop_assume!(h.is_normal());
323
324                let a = BigDecimal::from_f32(f).unwrap();
325                let b = BigDecimal::from_f32(g).unwrap();
326                let c = BigDecimal::from_f32(h).unwrap();
327
328                let ab = &a + &b;
329                let ab_c = ab + &c;
330
331                let bc = &b + &c;
332                let a_bc = a + bc;
333
334                prop_assert_eq!(ab_c, a_bc)
335            }
336        }
337    }
338}