@@ -9,8 +9,14 @@ impl Add<BigDecimal> for BigDecimal {
9
9
10
10
#[ inline]
11
11
fn add ( self , rhs : BigDecimal ) -> BigDecimal {
12
- let mut lhs = self ;
12
+ if rhs. is_zero ( ) {
13
+ return self ;
14
+ }
15
+ if self . is_zero ( ) {
16
+ return rhs;
17
+ }
13
18
19
+ let mut lhs = self ;
14
20
match lhs. scale . cmp ( & rhs. scale ) {
15
21
Ordering :: Equal => {
16
22
lhs. int_val += rhs. int_val ;
@@ -31,35 +37,41 @@ impl<'a, T: Into<BigDecimalRef<'a>>> Add<T> for BigDecimal {
31
37
}
32
38
}
33
39
34
- impl Add < BigDecimal > for & ' _ BigDecimal {
40
+ impl Add < BigInt > for BigDecimal {
35
41
type Output = BigDecimal ;
36
42
37
43
#[ inline]
38
- fn add ( self , rhs : BigDecimal ) -> BigDecimal {
39
- rhs + self
44
+ fn add ( self , rhs : BigInt ) -> BigDecimal {
45
+ self + BigDecimal :: from ( rhs )
40
46
}
41
47
}
42
48
43
- impl < ' a > Add < & ' a BigDecimal > for & ' _ BigDecimal {
49
+
50
+
51
+ impl Add < BigDecimal > for & ' _ BigDecimal {
44
52
type Output = BigDecimal ;
45
53
46
54
#[ inline]
47
- fn add ( self , rhs : & BigDecimal ) -> BigDecimal {
48
- let lhs = self ;
49
- match self . scale . cmp ( & rhs. scale ) {
50
- Ordering :: Less => lhs. with_scale ( rhs. scale ) + rhs,
51
- Ordering :: Greater => rhs. with_scale ( lhs. scale ) + lhs,
52
- Ordering :: Equal => BigDecimal :: new ( lhs. int_val . clone ( ) + & rhs. int_val , lhs. scale ) ,
53
- }
55
+ fn add ( self , rhs : BigDecimal ) -> BigDecimal {
56
+ rhs + self
54
57
}
55
58
}
56
59
57
- impl Add < BigInt > for BigDecimal {
60
+ impl < ' a , T : Into < BigDecimalRef < ' a > > > Add < T > for & ' _ BigDecimal {
58
61
type Output = BigDecimal ;
59
-
60
- #[ inline]
61
- fn add ( self , rhs : BigInt ) -> BigDecimal {
62
- self + BigDecimal :: from ( rhs)
62
+ fn add ( self , rhs : T ) -> BigDecimal {
63
+ let rhs = rhs. into ( ) ;
64
+ if rhs. is_zero ( ) {
65
+ return self . clone ( ) ;
66
+ }
67
+ if self . is_zero ( ) {
68
+ return rhs. to_owned ( ) ;
69
+ }
70
+ if self . scale >= rhs. scale {
71
+ self . to_owned ( ) + rhs
72
+ } else {
73
+ rhs. to_owned ( ) + self
74
+ }
63
75
}
64
76
}
65
77
@@ -72,12 +84,13 @@ impl Add<BigInt> for &'_ BigDecimal {
72
84
}
73
85
}
74
86
75
- impl < ' a > Add < & ' a BigInt > for & ' _ BigDecimal {
87
+
88
+ impl Add < BigDecimal > for BigDecimalRef < ' _ > {
76
89
type Output = BigDecimal ;
77
90
78
91
#[ inline]
79
- fn add ( self , rhs : & BigInt ) -> BigDecimal {
80
- self . to_ref ( ) + rhs
92
+ fn add ( self , rhs : BigDecimal ) -> BigDecimal {
93
+ rhs + self
81
94
}
82
95
}
83
96
@@ -102,7 +115,34 @@ impl Add<BigInt> for BigDecimalRef<'_> {
102
115
}
103
116
}
104
117
105
- impl Add < BigDecimal > for BigDecimalRef < ' _ > {
118
+
119
+ impl Add < BigDecimal > for BigInt {
120
+ type Output = BigDecimal ;
121
+
122
+ #[ inline]
123
+ fn add ( self , rhs : BigDecimal ) -> BigDecimal {
124
+ rhs + self
125
+ }
126
+ }
127
+
128
+ impl < ' a > Add < & ' a BigDecimal > for BigInt {
129
+ type Output = BigDecimal ;
130
+
131
+ fn add ( self , rhs : & BigDecimal ) -> BigDecimal {
132
+ rhs. to_ref ( ) . add ( self )
133
+ }
134
+ }
135
+
136
+ impl < ' a > Add < BigDecimalRef < ' a > > for BigInt {
137
+ type Output = BigDecimal ;
138
+
139
+ fn add ( self , rhs : BigDecimalRef < ' _ > ) -> BigDecimal {
140
+ rhs. add ( self )
141
+ }
142
+ }
143
+
144
+
145
+ impl Add < BigDecimal > for & BigInt {
106
146
type Output = BigDecimal ;
107
147
108
148
#[ inline]
@@ -111,7 +151,37 @@ impl Add<BigDecimal> for BigDecimalRef<'_> {
111
151
}
112
152
}
113
153
114
- forward_val_assignop ! ( impl AddAssign for BigDecimal , add_assign) ;
154
+ impl < ' a > Add < & ' a BigDecimal > for & BigInt {
155
+ type Output = BigDecimal ;
156
+
157
+ #[ inline]
158
+ fn add ( self , rhs : & BigDecimal ) -> BigDecimal {
159
+ rhs + self
160
+ }
161
+ }
162
+
163
+ impl < ' a > Add < BigDecimalRef < ' a > > for & BigInt {
164
+ type Output = BigDecimal ;
165
+
166
+ #[ inline]
167
+ fn add ( self , rhs : BigDecimalRef < ' _ > ) -> BigDecimal {
168
+ rhs + self
169
+ }
170
+ }
171
+
172
+
173
+ impl AddAssign < BigDecimal > for BigDecimal {
174
+ fn add_assign ( & mut self , rhs : BigDecimal ) {
175
+ if rhs. is_zero ( ) {
176
+ return ;
177
+ }
178
+ if self . is_zero ( ) {
179
+ * self = rhs;
180
+ return ;
181
+ }
182
+ self . add_assign ( rhs. to_ref ( ) ) ;
183
+ }
184
+ }
115
185
116
186
impl < ' a , N : Into < BigDecimalRef < ' a > > > AddAssign < N > for BigDecimal {
117
187
#[ inline]
@@ -157,21 +227,92 @@ mod test {
157
227
use paste:: paste;
158
228
159
229
macro_rules! impl_case {
160
- ( $name: ident: $a: literal + $b: literal => $c: literal ) => {
230
+ ( $name: ident: $a: literal + $b: literal => $c: literal ) => {
161
231
#[ test]
162
232
fn $name( ) {
163
- let mut a: BigDecimal = $a. parse( ) . unwrap( ) ;
233
+ let a: BigDecimal = $a. parse( ) . unwrap( ) ;
164
234
let b: BigDecimal = $b. parse( ) . unwrap( ) ;
165
235
let c: BigDecimal = $c. parse( ) . unwrap( ) ;
166
236
167
- assert_eq!( a. clone( ) + b. clone( ) , c) ;
237
+ assert_eq!( c, a. clone( ) + b. clone( ) ) ;
238
+ assert_eq!( c, a. clone( ) + b. to_ref( ) ) ;
239
+ assert_eq!( c, a. clone( ) + & b) ;
240
+
241
+ assert_eq!( c, & a + b. clone( ) ) ;
242
+ assert_eq!( c, & a + b. to_ref( ) ) ;
243
+ assert_eq!( c, & a + & b) ;
244
+
245
+ assert_eq!( c, a. to_ref( ) + b. clone( ) ) ;
246
+ assert_eq!( c, a. to_ref( ) + b. to_ref( ) ) ;
247
+ assert_eq!( c, a. to_ref( ) + & b) ;
248
+
249
+ // Reversed
250
+
251
+ assert_eq!( c, b. clone( ) + a. clone( ) ) ;
252
+ assert_eq!( c, b. clone( ) + a. to_ref( ) ) ;
253
+ assert_eq!( c, b. clone( ) + & a) ;
254
+
255
+ assert_eq!( c, & b + a. clone( ) ) ;
256
+ assert_eq!( c, & b + a. to_ref( ) ) ;
257
+ assert_eq!( c, & b + & a) ;
258
+
259
+ assert_eq!( c, b. to_ref( ) + a. clone( ) ) ;
260
+ assert_eq!( c, b. to_ref( ) + a. to_ref( ) ) ;
261
+ assert_eq!( c, b. to_ref( ) + & a) ;
262
+
263
+ let mut n = a. clone( ) ;
264
+ n += b. clone( ) ;
265
+ assert_eq!( c, n) ;
266
+
267
+ let mut n = a. clone( ) ;
268
+ n += & b;
269
+ assert_eq!( c, n) ;
270
+
271
+ let mut n = a. clone( ) ;
272
+ n += b. to_ref( ) ;
273
+ assert_eq!( c, n) ;
168
274
169
- assert_eq! ( a . clone ( ) + & b , c ) ;
170
- assert_eq! ( & a + b . clone( ) , c ) ;
171
- assert_eq!( & a + & b , c ) ;
275
+ let mut n = b . clone ( ) ;
276
+ n += a . clone( ) ;
277
+ assert_eq!( c , n ) ;
172
278
173
- a += b;
174
- assert_eq!( a, c) ;
279
+ let mut n = b. clone( ) ;
280
+ n += & a;
281
+ assert_eq!( c, n) ;
282
+
283
+ let mut n = b. clone( ) ;
284
+ n += a. to_ref( ) ;
285
+ assert_eq!( c, n) ;
286
+ }
287
+ } ;
288
+ ( $name: ident: $a: literal + ( int) $b: literal => $c: literal ) => {
289
+ #[ test]
290
+ fn $name( ) {
291
+ let a: BigDecimal = $a. parse( ) . unwrap( ) ;
292
+ let b: BigInt = $b. parse( ) . unwrap( ) ;
293
+ let c: BigDecimal = $c. parse( ) . unwrap( ) ;
294
+
295
+ assert_eq!( c, a. clone( ) + b. clone( ) ) ;
296
+ assert_eq!( c, a. clone( ) + & b) ;
297
+ assert_eq!( c, & a + & b) ;
298
+ assert_eq!( c, & a + b. clone( ) ) ;
299
+ assert_eq!( c, a. to_ref( ) + & b) ;
300
+
301
+ assert_eq!( c, b. clone( ) + a. clone( ) ) ;
302
+ assert_eq!( c, b. clone( ) + a. to_ref( ) ) ;
303
+ assert_eq!( c, b. clone( ) + & a) ;
304
+
305
+ assert_eq!( c, & b + a. clone( ) ) ;
306
+ assert_eq!( c, & b + a. to_ref( ) ) ;
307
+ assert_eq!( c, & b + & a) ;
308
+
309
+ let mut n = a. clone( ) ;
310
+ n += b. clone( ) ;
311
+ assert_eq!( c, n) ;
312
+
313
+ let mut n = a. clone( ) ;
314
+ n += & b;
315
+ assert_eq!( c, n) ;
175
316
}
176
317
} ;
177
318
}
@@ -182,7 +323,12 @@ mod test {
182
323
impl_case ! ( case_1234e6_1234en6: "1234e6" + "1234e-6" => "1234000000.001234" ) ;
183
324
impl_case ! ( case_1234en6_1234e6: "1234e6" + "1234e-6" => "1234000000.001234" ) ;
184
325
impl_case ! ( case_18446744073709551616_1: "18446744073709551616.0" + "1" => "18446744073709551617" ) ;
185
- impl_case ! ( case_184467440737e3380_1: "184467440737e3380" + "0" => "184467440737e3380" ) ;
326
+ impl_case ! ( case_184467440737e3380_0: "184467440737e3380" + "0" => "184467440737e3380" ) ;
327
+ impl_case ! ( case_0_776en1: "0" + "77.6" => "77.6" ) ;
328
+
329
+ impl_case ! ( case_80802295e5_int0: "80802295e5" + ( int) "0" => "80802295e5" ) ;
330
+ impl_case ! ( case_239200en4_intneg101: "23.9200" + ( int) "-101" => "-77.0800" ) ;
331
+ impl_case ! ( case_46636423395767125en15_int0: "46.636423395767125" + ( int) "123" => "169.636423395767125" ) ;
186
332
187
333
188
334
#[ cfg( property_tests) ]
0 commit comments