Skip to content

Commit e03bbc1

Browse files
committed
Restructure adc/sbb to match addcarry/subborrow
1 parent e3971e6 commit e03bbc1

File tree

1 file changed

+26
-36
lines changed

1 file changed

+26
-36
lines changed

src/algorithms.rs

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,65 +30,55 @@ use crate::big_digit::SignedDoubleBigDigit;
3030
// Add with carry:
3131
#[cfg(all(use_addcarry, u64_digit))]
3232
#[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 {
3534
// Safety: There are absolutely no safety concerns with calling `_addcarry_u64`.
3635
// 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) }
3937
}
4038

4139
#[cfg(all(use_addcarry, not(u64_digit)))]
4240
#[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 {
4542
// Safety: There are absolutely no safety concerns with calling `_addcarry_u32`.
4643
// 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) }
4945
}
5046

5147
// fallback for environments where we don't have an addcarry intrinsic
5248
#[cfg(not(use_addcarry))]
5349
#[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
6054
}
6155

6256
// Subtract with borrow:
6357
#[cfg(all(use_addcarry, u64_digit))]
6458
#[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 {
6760
// Safety: There are absolutely no safety concerns with calling `_subborrow_u64`.
6861
// 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) }
7163
}
7264

7365
#[cfg(all(use_addcarry, not(u64_digit)))]
7466
#[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 {
7768
// Safety: There are absolutely no safety concerns with calling `_subborrow_u32`.
7869
// 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) }
8171
}
8272

83-
// fallback for environments where we don't have an addcarry intrinsic
73+
// fallback for environments where we don't have a subborrow intrinsic
8474
#[cfg(not(use_addcarry))]
8575
#[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)
9282
}
9383

9484
#[inline]
@@ -195,12 +185,12 @@ pub(crate) fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit {
195185
let (a_lo, a_hi) = a.split_at_mut(b.len());
196186

197187
for (a, b) in a_lo.iter_mut().zip(b) {
198-
*a = adc(*a, *b, &mut carry);
188+
carry = adc(carry, *a, *b, a);
199189
}
200190

201191
if carry != 0 {
202192
for a in a_hi {
203-
*a = adc(*a, 0, &mut carry);
193+
carry = adc(carry, *a, 0, a);
204194
if carry == 0 {
205195
break;
206196
}
@@ -229,12 +219,12 @@ pub(crate) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) {
229219
let (b_lo, b_hi) = b.split_at(len);
230220

231221
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);
233223
}
234224

235225
if borrow != 0 {
236226
for a in a_hi {
237-
*a = sbb(*a, 0, &mut borrow);
227+
borrow = sbb(borrow, *a, 0, a);
238228
if borrow == 0 {
239229
break;
240230
}
@@ -250,16 +240,16 @@ pub(crate) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) {
250240

251241
// Only for the Sub impl. `a` and `b` must have same length.
252242
#[inline]
253-
pub(crate) fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> BigDigit {
243+
pub(crate) fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> u8 {
254244
debug_assert!(b.len() == a.len());
255245

256246
let mut borrow = 0;
257247

258248
for (ai, bi) in a.iter().zip(b) {
259-
*bi = sbb(*ai, *bi, &mut borrow);
249+
borrow = sbb(borrow, *ai, *bi, bi);
260250
}
261251

262-
borrow as BigDigit
252+
borrow
263253
}
264254

265255
pub(crate) fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) {

0 commit comments

Comments
 (0)