bigdecimal/
impl_ops_add.rs
1use 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 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 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 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 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}