@@ -14,8 +14,7 @@ impl<const LIMBS: usize> Int<LIMBS> {
14
14
ConstCtOption :: new ( value, overflow. not ( ) )
15
15
}
16
16
17
- /// Perform `self + rhs`, returns the result, as well as a flag indicating whether the
18
- /// addition overflowed.
17
+ /// Perform addition, raising the `overflow` flag on overflow.
19
18
pub const fn overflowing_add ( & self , rhs : & Self ) -> ( Self , ConstChoice ) {
20
19
// Step 1. add operands
21
20
let res = Self ( self . 0 . wrapping_add ( & rhs. 0 ) ) ;
@@ -31,6 +30,7 @@ impl<const LIMBS: usize> Int<LIMBS> {
31
30
. eq ( rhs. is_negative ( ) )
32
31
. and ( self_msb. ne ( res. is_negative ( ) ) ) ;
33
32
33
+ // Step 3. Construct result
34
34
( res, overflow)
35
35
}
36
36
@@ -106,107 +106,220 @@ impl<const LIMBS: usize> WrappingAdd for Int<LIMBS> {
106
106
107
107
#[ cfg( test) ]
108
108
mod tests {
109
+ use crate :: { ConstChoice , I128 , U128 } ;
109
110
110
- #[ cfg( test) ]
111
- mod tests {
112
- use crate :: { I128 , U128 } ;
111
+ #[ test]
112
+ fn checked_add ( ) {
113
+ let min_plus_one = I128 {
114
+ 0 : I128 :: MIN . 0 . wrapping_add ( & I128 :: ONE . 0 ) ,
115
+ } ;
116
+ let max_minus_one = I128 {
117
+ 0 : I128 :: MAX . 0 . wrapping_sub ( & I128 :: ONE . 0 ) ,
118
+ } ;
119
+ let two = I128 {
120
+ 0 : U128 :: from ( 2u32 ) ,
121
+ } ;
113
122
114
- #[ test]
115
- fn checked_add ( ) {
116
- let min_plus_one = I128 {
117
- 0 : I128 :: MIN . 0 . wrapping_add ( & I128 :: ONE . 0 ) ,
118
- } ;
119
- let max_minus_one = I128 {
120
- 0 : I128 :: MAX . 0 . wrapping_sub ( & I128 :: ONE . 0 ) ,
121
- } ;
122
- let two = I128 {
123
- 0 : U128 :: from ( 2u32 ) ,
124
- } ;
123
+ // lhs = MIN
125
124
126
- // lhs = MIN
125
+ let result = I128 :: MIN . checked_add ( & I128 :: MIN ) ;
126
+ assert ! ( bool :: from( result. is_none( ) ) ) ;
127
127
128
- let result = I128 :: MIN . checked_add ( & I128 :: MIN ) ;
129
- assert ! ( bool :: from( result. is_none( ) ) ) ;
128
+ let result = I128 :: MIN . checked_add ( & I128 :: MINUS_ONE ) ;
129
+ assert ! ( bool :: from( result. is_none( ) ) ) ;
130
130
131
- let result = I128 :: MIN . checked_add ( & I128 :: MINUS_ONE ) ;
132
- assert ! ( bool :: from ( result. is_none ( ) ) ) ;
131
+ let result = I128 :: MIN . checked_add ( & I128 :: ZERO ) ;
132
+ assert_eq ! ( result. unwrap ( ) , I128 :: MIN ) ;
133
133
134
- let result = I128 :: MIN . checked_add ( & I128 :: ZERO ) ;
135
- assert_eq ! ( result. unwrap( ) , I128 :: MIN ) ;
134
+ let result = I128 :: MIN . checked_add ( & I128 :: ONE ) ;
135
+ assert_eq ! ( result. unwrap( ) , min_plus_one ) ;
136
136
137
- let result = I128 :: MIN . checked_add ( & I128 :: ONE ) ;
138
- assert_eq ! ( result. unwrap( ) , min_plus_one ) ;
137
+ let result = I128 :: MIN . checked_add ( & I128 :: MAX ) ;
138
+ assert_eq ! ( result. unwrap( ) , I128 :: MINUS_ONE ) ;
139
139
140
- let result = I128 :: MIN . checked_add ( & I128 :: MAX ) ;
141
- assert_eq ! ( result. unwrap( ) , I128 :: MINUS_ONE ) ;
140
+ // lhs = -1
142
141
143
- // lhs = -1
142
+ let result = I128 :: MINUS_ONE . checked_add ( & I128 :: MIN ) ;
143
+ assert ! ( bool :: from( result. is_none( ) ) ) ;
144
144
145
- let result = I128 :: MINUS_ONE . checked_add ( & I128 :: MIN ) ;
146
- assert ! ( bool :: from ( result. is_none ( ) ) ) ;
145
+ let result = I128 :: MINUS_ONE . checked_add ( & I128 :: MINUS_ONE ) ;
146
+ assert_eq ! ( result. unwrap ( ) , two . checked_neg ( ) . unwrap ( ) ) ;
147
147
148
- let result = I128 :: MINUS_ONE . checked_add ( & I128 :: MINUS_ONE ) ;
149
- assert_eq ! ( result. unwrap( ) , two . checked_neg ( ) . unwrap ( ) ) ;
148
+ let result = I128 :: MINUS_ONE . checked_add ( & I128 :: ZERO ) ;
149
+ assert_eq ! ( result. unwrap( ) , I128 :: MINUS_ONE ) ;
150
150
151
- let result = I128 :: MINUS_ONE . checked_add ( & I128 :: ZERO ) ;
152
- assert_eq ! ( result. unwrap( ) , I128 :: MINUS_ONE ) ;
151
+ let result = I128 :: MINUS_ONE . checked_add ( & I128 :: ONE ) ;
152
+ assert_eq ! ( result. unwrap( ) , I128 :: ZERO ) ;
153
153
154
- let result = I128 :: MINUS_ONE . checked_add ( & I128 :: ONE ) ;
155
- assert_eq ! ( result. unwrap( ) , I128 :: ZERO ) ;
154
+ let result = I128 :: MINUS_ONE . checked_add ( & I128 :: MAX ) ;
155
+ assert_eq ! ( result. unwrap( ) , max_minus_one ) ;
156
156
157
- let result = I128 :: MINUS_ONE . checked_add ( & I128 :: MAX ) ;
158
- assert_eq ! ( result. unwrap( ) , max_minus_one) ;
157
+ // lhs = 0
159
158
160
- // lhs = 0
159
+ let result = I128 :: ZERO . checked_add ( & I128 :: MIN ) ;
160
+ assert_eq ! ( result. unwrap( ) , I128 :: MIN ) ;
161
161
162
- let result = I128 :: ZERO . checked_add ( & I128 :: MIN ) ;
163
- assert_eq ! ( result. unwrap( ) , I128 :: MIN ) ;
162
+ let result = I128 :: ZERO . checked_add ( & I128 :: MINUS_ONE ) ;
163
+ assert_eq ! ( result. unwrap( ) , I128 :: MINUS_ONE ) ;
164
164
165
- let result = I128 :: ZERO . checked_add ( & I128 :: MINUS_ONE ) ;
166
- assert_eq ! ( result. unwrap( ) , I128 :: MINUS_ONE ) ;
165
+ let result = I128 :: ZERO . checked_add ( & I128 :: ZERO ) ;
166
+ assert_eq ! ( result. unwrap( ) , I128 :: ZERO ) ;
167
167
168
- let result = I128 :: ZERO . checked_add ( & I128 :: ZERO ) ;
169
- assert_eq ! ( result. unwrap( ) , I128 :: ZERO ) ;
168
+ let result = I128 :: ZERO . checked_add ( & I128 :: ONE ) ;
169
+ assert_eq ! ( result. unwrap( ) , I128 :: ONE ) ;
170
170
171
- let result = I128 :: ZERO . checked_add ( & I128 :: ONE ) ;
172
- assert_eq ! ( result. unwrap( ) , I128 :: ONE ) ;
171
+ let result = I128 :: ZERO . checked_add ( & I128 :: MAX ) ;
172
+ assert_eq ! ( result. unwrap( ) , I128 :: MAX ) ;
173
173
174
- let result = I128 :: ZERO . checked_add ( & I128 :: MAX ) ;
175
- assert_eq ! ( result. unwrap( ) , I128 :: MAX ) ;
174
+ // lhs = 1
176
175
177
- // lhs = 1
176
+ let result = I128 :: ONE . checked_add ( & I128 :: MIN ) ;
177
+ assert_eq ! ( result. unwrap( ) , min_plus_one) ;
178
178
179
- let result = I128 :: ONE . checked_add ( & I128 :: MIN ) ;
180
- assert_eq ! ( result. unwrap( ) , min_plus_one ) ;
179
+ let result = I128 :: ONE . checked_add ( & I128 :: MINUS_ONE ) ;
180
+ assert_eq ! ( result. unwrap( ) , I128 :: ZERO ) ;
181
181
182
- let result = I128 :: ONE . checked_add ( & I128 :: MINUS_ONE ) ;
183
- assert_eq ! ( result. unwrap( ) , I128 :: ZERO ) ;
182
+ let result = I128 :: ONE . checked_add ( & I128 :: ZERO ) ;
183
+ assert_eq ! ( result. unwrap( ) , I128 :: ONE ) ;
184
184
185
- let result = I128 :: ONE . checked_add ( & I128 :: ZERO ) ;
186
- assert_eq ! ( result. unwrap( ) , I128 :: ONE ) ;
185
+ let result = I128 :: ONE . checked_add ( & I128 :: ONE ) ;
186
+ assert_eq ! ( result. unwrap( ) , two ) ;
187
187
188
- let result = I128 :: ONE . checked_add ( & I128 :: ONE ) ;
189
- assert_eq ! ( result. unwrap ( ) , two ) ;
188
+ let result = I128 :: ONE . checked_add ( & I128 :: MAX ) ;
189
+ assert ! ( bool :: from ( result. is_none ( ) ) ) ;
190
190
191
- let result = I128 :: ONE . checked_add ( & I128 :: MAX ) ;
192
- assert ! ( bool :: from( result. is_none( ) ) ) ;
191
+ // lhs = MAX
193
192
194
- // lhs = MAX
193
+ let result = I128 :: MAX . checked_add ( & I128 :: MIN ) ;
194
+ assert_eq ! ( result. unwrap( ) , I128 :: MINUS_ONE ) ;
195
195
196
- let result = I128 :: MAX . checked_add ( & I128 :: MIN ) ;
197
- assert_eq ! ( result. unwrap( ) , I128 :: MINUS_ONE ) ;
196
+ let result = I128 :: MAX . checked_add ( & I128 :: MINUS_ONE ) ;
197
+ assert_eq ! ( result. unwrap( ) , max_minus_one ) ;
198
198
199
- let result = I128 :: MAX . checked_add ( & I128 :: MINUS_ONE ) ;
200
- assert_eq ! ( result. unwrap( ) , max_minus_one ) ;
199
+ let result = I128 :: MAX . checked_add ( & I128 :: ZERO ) ;
200
+ assert_eq ! ( result. unwrap( ) , I128 :: MAX ) ;
201
201
202
- let result = I128 :: MAX . checked_add ( & I128 :: ZERO ) ;
203
- assert_eq ! ( result. unwrap ( ) , I128 :: MAX ) ;
202
+ let result = I128 :: MAX . checked_add ( & I128 :: ONE ) ;
203
+ assert ! ( bool :: from ( result. is_none ( ) ) ) ;
204
204
205
- let result = I128 :: MAX . checked_add ( & I128 :: ONE ) ;
206
- assert ! ( bool :: from( result. is_none( ) ) ) ;
205
+ let result = I128 :: MAX . checked_add ( & I128 :: MAX ) ;
206
+ assert ! ( bool :: from( result. is_none( ) ) ) ;
207
+ }
208
+
209
+ #[ test]
210
+ fn overflowing_add ( ) {
211
+ let min_plus_one = I128 {
212
+ 0 : I128 :: MIN . 0 . wrapping_add ( & I128 :: ONE . 0 ) ,
213
+ } ;
214
+ let max_minus_one = I128 {
215
+ 0 : I128 :: MAX . 0 . wrapping_sub ( & I128 :: ONE . 0 ) ,
216
+ } ;
217
+ let two = I128 {
218
+ 0 : U128 :: from ( 2u32 ) ,
219
+ } ;
220
+
221
+ // lhs = MIN
222
+
223
+ let ( _val, overflow) = I128 :: MIN . overflowing_add ( & I128 :: MIN ) ;
224
+ assert_eq ! ( overflow, ConstChoice :: TRUE ) ;
225
+
226
+ let ( _val, overflow) = I128 :: MIN . overflowing_add ( & I128 :: MINUS_ONE ) ;
227
+ assert_eq ! ( overflow, ConstChoice :: TRUE ) ;
228
+
229
+ let ( val, overflow) = I128 :: MIN . overflowing_add ( & I128 :: ZERO ) ;
230
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
231
+ assert_eq ! ( val, I128 :: MIN ) ;
232
+
233
+ let ( val, overflow) = I128 :: MIN . overflowing_add ( & I128 :: ONE ) ;
234
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
235
+ assert_eq ! ( val, min_plus_one) ;
236
+
237
+ let ( val, overflow) = I128 :: MIN . overflowing_add ( & I128 :: MAX ) ;
238
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
239
+ assert_eq ! ( val, I128 :: MINUS_ONE ) ;
240
+
241
+ // lhs = -1
242
+
243
+ let ( _val, overflow) = I128 :: MINUS_ONE . overflowing_add ( & I128 :: MIN ) ;
244
+ assert_eq ! ( overflow, ConstChoice :: TRUE ) ;
245
+
246
+ let ( val, overflow) = I128 :: MINUS_ONE . overflowing_add ( & I128 :: MINUS_ONE ) ;
247
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
248
+ assert_eq ! ( val, two. wrapping_neg( ) ) ;
249
+
250
+ let ( val, overflow) = I128 :: MINUS_ONE . overflowing_add ( & I128 :: ZERO ) ;
251
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
252
+ assert_eq ! ( val, I128 :: MINUS_ONE ) ;
253
+
254
+ let ( val, overflow) = I128 :: MINUS_ONE . overflowing_add ( & I128 :: ONE ) ;
255
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
256
+ assert_eq ! ( val, I128 :: ZERO ) ;
257
+
258
+ let ( val, overflow) = I128 :: MINUS_ONE . overflowing_add ( & I128 :: MAX ) ;
259
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
260
+ assert_eq ! ( val, max_minus_one) ;
261
+
262
+ // lhs = 0
263
+
264
+ let ( val, overflow) = I128 :: ZERO . overflowing_add ( & I128 :: MIN ) ;
265
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
266
+ assert_eq ! ( val, I128 :: MIN ) ;
267
+
268
+ let ( val, overflow) = I128 :: ZERO . overflowing_add ( & I128 :: MINUS_ONE ) ;
269
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
270
+ assert_eq ! ( val, I128 :: MINUS_ONE ) ;
271
+
272
+ let ( val, overflow) = I128 :: ZERO . overflowing_add ( & I128 :: ZERO ) ;
273
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
274
+ assert_eq ! ( val, I128 :: ZERO ) ;
275
+
276
+ let ( val, overflow) = I128 :: ZERO . overflowing_add ( & I128 :: ONE ) ;
277
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
278
+ assert_eq ! ( val, I128 :: ONE ) ;
279
+
280
+ let ( val, overflow) = I128 :: ZERO . overflowing_add ( & I128 :: MAX ) ;
281
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
282
+ assert_eq ! ( val, I128 :: MAX ) ;
283
+
284
+ // lhs = 1
285
+
286
+ let ( val, overflow) = I128 :: ONE . overflowing_add ( & I128 :: MIN ) ;
287
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
288
+ assert_eq ! ( val, min_plus_one) ;
289
+
290
+ let ( val, overflow) = I128 :: ONE . overflowing_add ( & I128 :: MINUS_ONE ) ;
291
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
292
+ assert_eq ! ( val, I128 :: ZERO ) ;
293
+
294
+ let ( val, overflow) = I128 :: ONE . overflowing_add ( & I128 :: ZERO ) ;
295
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
296
+ assert_eq ! ( val, I128 :: ONE ) ;
297
+
298
+ let ( val, overflow) = I128 :: ONE . overflowing_add ( & I128 :: ONE ) ;
299
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
300
+ assert_eq ! ( val, two) ;
301
+
302
+ let ( _val, overflow) = I128 :: ONE . overflowing_add ( & I128 :: MAX ) ;
303
+ assert_eq ! ( overflow, ConstChoice :: TRUE ) ;
304
+
305
+ // lhs = MAX
306
+
307
+ let ( val, overflow) = I128 :: MAX . overflowing_add ( & I128 :: MIN ) ;
308
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
309
+ assert_eq ! ( val, I128 :: MINUS_ONE ) ;
310
+
311
+ let ( val, overflow) = I128 :: MAX . overflowing_add ( & I128 :: MINUS_ONE ) ;
312
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
313
+ assert_eq ! ( val, max_minus_one) ;
314
+
315
+ let ( val, overflow) = I128 :: MAX . overflowing_add ( & I128 :: ZERO ) ;
316
+ assert_eq ! ( overflow, ConstChoice :: FALSE ) ;
317
+ assert_eq ! ( val, I128 :: MAX ) ;
318
+
319
+ let ( _val, overflow) = I128 :: MAX . overflowing_add ( & I128 :: ONE ) ;
320
+ assert_eq ! ( overflow, ConstChoice :: TRUE ) ;
207
321
208
- let result = I128 :: MAX . checked_add ( & I128 :: MAX ) ;
209
- assert ! ( bool :: from( result. is_none( ) ) ) ;
210
- }
322
+ let ( _val, overflow) = I128 :: MAX . overflowing_add ( & I128 :: MAX ) ;
323
+ assert_eq ! ( overflow, ConstChoice :: TRUE ) ;
211
324
}
212
325
}
0 commit comments