@@ -30,65 +30,55 @@ use crate::big_digit::SignedDoubleBigDigit;
30
30
// Add with carry:
31
31
#[ cfg( all( use_addcarry, u64_digit) ) ]
32
32
#[ inline]
33
- fn adc ( a : BigDigit , b : BigDigit , acc : & mut u8 ) -> BigDigit {
34
- let mut out = 0 ;
33
+ fn adc ( carry : u8 , a : u64 , b : u64 , out : & mut u64 ) -> u8 {
35
34
// Safety: There are absolutely no safety concerns with calling `_addcarry_u64`.
36
35
// It's just unsafe for API consistency with other intrinsics.
37
- * acc = unsafe { arch:: _addcarry_u64 ( * acc, a, b, & mut out) } ;
38
- out
36
+ unsafe { arch:: _addcarry_u64 ( carry, a, b, out) }
39
37
}
40
38
41
39
#[ cfg( all( use_addcarry, not( u64_digit) ) ) ]
42
40
#[ inline]
43
- fn adc ( a : BigDigit , b : BigDigit , acc : & mut u8 ) -> BigDigit {
44
- let mut out = 0 ;
41
+ fn adc ( carry : u8 , a : u32 , b : u32 , out : & mut u32 ) -> u8 {
45
42
// Safety: There are absolutely no safety concerns with calling `_addcarry_u32`.
46
43
// It's just unsafe for API consistency with other intrinsics.
47
- * acc = unsafe { arch:: _addcarry_u32 ( * acc, a, b, & mut out) } ;
48
- out
44
+ unsafe { arch:: _addcarry_u32 ( carry, a, b, out) }
49
45
}
50
46
51
47
// fallback for environments where we don't have an addcarry intrinsic
52
48
#[ cfg( not( use_addcarry) ) ]
53
49
#[ inline]
54
- fn adc ( a : BigDigit , b : BigDigit , acc : & mut DoubleBigDigit ) -> BigDigit {
55
- * acc += DoubleBigDigit :: from ( a) ;
56
- * acc += DoubleBigDigit :: from ( b) ;
57
- let lo = * acc as BigDigit ;
58
- * acc >>= big_digit:: BITS ;
59
- lo
50
+ fn adc ( carry : u8 , a : BigDigit , b : BigDigit , out : & mut BigDigit ) -> u8 {
51
+ let sum = DoubleBigDigit :: from ( a) + DoubleBigDigit :: from ( b) + DoubleBigDigit :: from ( carry) ;
52
+ * out = sum as BigDigit ;
53
+ ( sum >> big_digit:: BITS ) as u8
60
54
}
61
55
62
56
// Subtract with borrow:
63
57
#[ cfg( all( use_addcarry, u64_digit) ) ]
64
58
#[ inline]
65
- fn sbb ( a : BigDigit , b : BigDigit , acc : & mut u8 ) -> BigDigit {
66
- let mut out = 0 ;
59
+ fn sbb ( borrow : u8 , a : u64 , b : u64 , out : & mut u64 ) -> u8 {
67
60
// Safety: There are absolutely no safety concerns with calling `_subborrow_u64`.
68
61
// It's just unsafe for API consistency with other intrinsics.
69
- * acc = unsafe { arch:: _subborrow_u64 ( * acc, a, b, & mut out) } ;
70
- out
62
+ unsafe { arch:: _subborrow_u64 ( borrow, a, b, out) }
71
63
}
72
64
73
65
#[ cfg( all( use_addcarry, not( u64_digit) ) ) ]
74
66
#[ inline]
75
- fn sbb ( a : BigDigit , b : BigDigit , acc : & mut u8 ) -> BigDigit {
76
- let mut out = 0 ;
67
+ fn sbb ( borrow : u8 , a : u32 , b : u32 , out : & mut u32 ) -> u8 {
77
68
// Safety: There are absolutely no safety concerns with calling `_subborrow_u32`.
78
69
// It's just unsafe for API consistency with other intrinsics.
79
- * acc = unsafe { arch:: _subborrow_u32 ( * acc, a, b, & mut out) } ;
80
- out
70
+ unsafe { arch:: _subborrow_u32 ( borrow, a, b, out) }
81
71
}
82
72
83
- // fallback for environments where we don't have an addcarry intrinsic
73
+ // fallback for environments where we don't have a subborrow intrinsic
84
74
#[ cfg( not( use_addcarry) ) ]
85
75
#[ inline]
86
- fn sbb ( a : BigDigit , b : BigDigit , acc : & mut SignedDoubleBigDigit ) -> BigDigit {
87
- * acc + = SignedDoubleBigDigit :: from ( a) ;
88
- * acc -= SignedDoubleBigDigit :: from ( b) ;
89
- let lo = * acc as BigDigit ;
90
- * acc >>= big_digit :: BITS ;
91
- lo
76
+ fn sbb ( borrow : u8 , a : BigDigit , b : BigDigit , out : & mut BigDigit ) -> u8 {
77
+ let difference = SignedDoubleBigDigit :: from ( a)
78
+ - SignedDoubleBigDigit :: from ( b)
79
+ - SignedDoubleBigDigit :: from ( borrow ) ;
80
+ * out = difference as BigDigit ;
81
+ u8 :: from ( difference < 0 )
92
82
}
93
83
94
84
#[ inline]
@@ -195,12 +185,12 @@ pub(crate) fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit {
195
185
let ( a_lo, a_hi) = a. split_at_mut ( b. len ( ) ) ;
196
186
197
187
for ( a, b) in a_lo. iter_mut ( ) . zip ( b) {
198
- * a = adc ( * a, * b, & mut carry ) ;
188
+ carry = adc ( carry , * a, * b, a ) ;
199
189
}
200
190
201
191
if carry != 0 {
202
192
for a in a_hi {
203
- * a = adc ( * a, 0 , & mut carry ) ;
193
+ carry = adc ( carry , * a, 0 , a ) ;
204
194
if carry == 0 {
205
195
break ;
206
196
}
@@ -229,12 +219,12 @@ pub(crate) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) {
229
219
let ( b_lo, b_hi) = b. split_at ( len) ;
230
220
231
221
for ( a, b) in a_lo. iter_mut ( ) . zip ( b_lo) {
232
- * a = sbb ( * a, * b, & mut borrow ) ;
222
+ borrow = sbb ( borrow , * a, * b, a ) ;
233
223
}
234
224
235
225
if borrow != 0 {
236
226
for a in a_hi {
237
- * a = sbb ( * a, 0 , & mut borrow ) ;
227
+ borrow = sbb ( borrow , * a, 0 , a ) ;
238
228
if borrow == 0 {
239
229
break ;
240
230
}
@@ -250,16 +240,16 @@ pub(crate) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) {
250
240
251
241
// Only for the Sub impl. `a` and `b` must have same length.
252
242
#[ inline]
253
- pub ( crate ) fn __sub2rev ( a : & [ BigDigit ] , b : & mut [ BigDigit ] ) -> BigDigit {
243
+ pub ( crate ) fn __sub2rev ( a : & [ BigDigit ] , b : & mut [ BigDigit ] ) -> u8 {
254
244
debug_assert ! ( b. len( ) == a. len( ) ) ;
255
245
256
246
let mut borrow = 0 ;
257
247
258
248
for ( ai, bi) in a. iter ( ) . zip ( b) {
259
- * bi = sbb ( * ai, * bi, & mut borrow ) ;
249
+ borrow = sbb ( borrow , * ai, * bi, bi ) ;
260
250
}
261
251
262
- borrow as BigDigit
252
+ borrow
263
253
}
264
254
265
255
pub ( crate ) fn sub2rev ( a : & [ BigDigit ] , b : & mut [ BigDigit ] ) {
0 commit comments