@@ -14,40 +14,67 @@ use crate::bigint::Sign::{Minus, NoSign, Plus};
14
14
15
15
use crate :: big_digit:: { self , BigDigit , DoubleBigDigit } ;
16
16
17
- #[ cfg( not( use_addcarry_u64) ) ] // only needed for the fallback implementation of `sbb`
17
+ // only needed for the fallback implementation of `sbb`
18
+ #[ cfg( not( any( use_addcarry_u64, use_addcarry_u32) ) ) ]
18
19
use crate :: big_digit:: SignedDoubleBigDigit ;
19
20
20
- // Generic functions for add/subtract/multiply with carry/borrow:
21
+ // Generic functions for add/subtract/multiply with carry/borrow. These are specialized for some platforms to take advantage of intrinsics etc
21
22
22
23
// Add with carry:
23
24
#[ cfg( use_addcarry_u64) ]
24
25
#[ inline]
25
- fn adc ( carry : u8 , a : BigDigit , b : BigDigit , out : & mut BigDigit ) -> u8 {
26
- unsafe { core:: arch:: x86_64:: _addcarry_u64 ( carry, a, b, out) }
26
+ fn adc ( a : BigDigit , b : BigDigit , acc : & mut u8 ) -> BigDigit {
27
+ let mut out = 0 ;
28
+ // Safety: There are absolutely no safety concerns with calling _addcarry_u64, it's just unsafe for API consistency with other intrinsics
29
+ * acc = unsafe { core:: arch:: x86_64:: _addcarry_u64 ( * acc, a, b, & mut out) } ;
30
+ out
27
31
}
28
32
29
- #[ cfg( not ( use_addcarry_u64 ) ) ] // fallback for environments where we don't have an addcarry intrinsic
33
+ #[ cfg( use_addcarry_u32 ) ]
30
34
#[ inline]
31
- fn adc ( mut carry : DoubleBigDigit , a : BigDigit , b : BigDigit , out : & mut BigDigit ) -> DoubleBigDigit {
32
- carry += DoubleBigDigit :: from ( a) ;
33
- carry += DoubleBigDigit :: from ( b) ;
34
- * out = carry as BigDigit ;
35
- carry >> big_digit:: BITS
35
+ fn adc ( a : BigDigit , b : BigDigit , acc : & mut u8 ) -> BigDigit {
36
+ let mut out = 0 ;
37
+ // Safety: There are absolutely no safety concerns with calling _addcarry_u64, it's just unsafe for API consistency with other intrinsics
38
+ * acc = unsafe { core:: arch:: x86_64:: _addcarry_u32 ( * acc, a, b, & mut out) } ;
39
+ out
40
+ }
41
+
42
+ #[ cfg( not( any( use_addcarry_u64, use_addcarry_u32) ) ) ] // fallback for environments where we don't have an addcarry intrinsic
43
+ #[ inline]
44
+ fn adc ( a : BigDigit , b : BigDigit , acc : & mut DoubleBigDigit ) -> BigDigit {
45
+ * acc += DoubleBigDigit :: from ( a) ;
46
+ * acc += DoubleBigDigit :: from ( b) ;
47
+ let lo = * acc as BigDigit ;
48
+ * acc >>= big_digit:: BITS ;
49
+ lo
36
50
}
37
51
38
52
// Subtract with borrow:
39
53
#[ cfg( use_addcarry_u64) ]
40
54
#[ inline]
41
- fn sbb ( carry : u8 , a : BigDigit , b : BigDigit , out : & mut BigDigit ) -> u8 {
42
- unsafe { core:: arch:: x86_64:: _subborrow_u64 ( carry, a, b, out) }
55
+ fn sbb ( a : BigDigit , b : BigDigit , acc : & mut u8 ) -> BigDigit {
56
+ let mut out = 0 ;
57
+ // Safety: There are absolutely no safety concerns with calling _addcarry_u64, it's just unsafe for API consistency with other intrinsics
58
+ * acc = unsafe { core:: arch:: x86_64:: _subborrow_u64 ( * acc, a, b, & mut out) } ;
59
+ out
43
60
}
44
- #[ cfg( not ( use_addcarry_u64 ) ) ] // fallback for environments where we don't have an addcarry intrinsic
61
+ #[ cfg( use_addcarry_u32 ) ]
45
62
#[ inline]
46
- fn sbb ( mut carry : SignedDoubleBigDigit , a : BigDigit , b : BigDigit , out : & mut BigDigit ) -> SignedDoubleBigDigit {
47
- carry += SignedDoubleBigDigit :: from ( a) ;
48
- carry -= SignedDoubleBigDigit :: from ( b) ;
49
- * out = carry as BigDigit ;
50
- carry >> big_digit:: BITS
63
+ fn sbb ( a : BigDigit , b : BigDigit , acc : & mut u8 ) -> BigDigit {
64
+ let mut out = 0 ;
65
+ // Safety: There are absolutely no safety concerns with calling _addcarry_u64, it's just unsafe for API consistency with other intrinsics
66
+ * acc = unsafe { core:: arch:: x86_64:: _subborrow_u32 ( * acc, a, b, & mut out) } ;
67
+ out
68
+ }
69
+
70
+ #[ cfg( not( any( use_addcarry_u64, use_addcarry_u32) ) ) ] // fallback for environments where we don't have an addcarry intrinsic
71
+ #[ inline]
72
+ fn sbb ( a : BigDigit , b : BigDigit , acc : & mut SignedDoubleBigDigit ) -> BigDigit {
73
+ * acc += SignedDoubleBigDigit :: from ( a) ;
74
+ * acc -= SignedDoubleBigDigit :: from ( b) ;
75
+ let lo = * acc as BigDigit ;
76
+ * acc >>= big_digit:: BITS ;
77
+ lo
51
78
}
52
79
53
80
#[ inline]
@@ -154,12 +181,12 @@ pub(crate) fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit {
154
181
let ( a_lo, a_hi) = a. split_at_mut ( b. len ( ) ) ;
155
182
156
183
for ( a, b) in a_lo. iter_mut ( ) . zip ( b) {
157
- carry = adc ( carry , * a, * b, a ) ;
184
+ * a = adc ( * a, * b, & mut carry ) ;
158
185
}
159
186
160
187
if carry != 0 {
161
188
for a in a_hi {
162
- carry = adc ( carry , * a, 0 , a ) ;
189
+ * a = adc ( * a, 0 , & mut carry ) ;
163
190
if carry == 0 {
164
191
break ;
165
192
}
@@ -188,12 +215,12 @@ pub(crate) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) {
188
215
let ( b_lo, b_hi) = b. split_at ( len) ;
189
216
190
217
for ( a, b) in a_lo. iter_mut ( ) . zip ( b_lo) {
191
- borrow = sbb ( borrow , * a, * b, a ) ;
218
+ * a = sbb ( * a, * b, & mut borrow ) ;
192
219
}
193
220
194
221
if borrow != 0 {
195
222
for a in a_hi {
196
- borrow = sbb ( borrow , * a, 0 , a ) ;
223
+ * a = sbb ( * a, 0 , & mut borrow ) ;
197
224
if borrow == 0 {
198
225
break ;
199
226
}
@@ -215,7 +242,7 @@ pub(crate) fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> BigDigit {
215
242
let mut borrow = 0 ;
216
243
217
244
for ( ai, bi) in a. iter ( ) . zip ( b) {
218
- borrow = sbb ( borrow , * ai, * bi, bi ) ;
245
+ * bi = sbb ( * ai, * bi, & mut borrow ) ;
219
246
}
220
247
221
248
borrow as BigDigit
0 commit comments