use crate::{WideWord, Word};
#[inline(always)]
pub(crate) const fn addhilo(x_lo: Word, x_hi: Word, y_lo: Word, y_hi: Word) -> (Word, Word) {
let res = (((x_hi as WideWord) << Word::BITS) | (x_lo as WideWord))
+ (((y_hi as WideWord) << Word::BITS) | (y_lo as WideWord));
(res as Word, (res >> Word::BITS) as Word)
}
#[inline(always)]
pub(crate) const fn carrying_add(lhs: Word, rhs: Word, carry: Word) -> (Word, Word) {
let a = lhs as WideWord;
let b = rhs as WideWord;
let carry = carry as WideWord;
let ret = a + b + carry;
(ret as Word, (ret >> Word::BITS) as Word)
}
#[inline(always)]
pub(crate) const fn overflowing_add(lhs: Word, rhs: Word) -> (Word, Word) {
let (res, carry) = lhs.overflowing_add(rhs);
(res, carry as Word)
}
#[inline(always)]
pub(crate) const fn borrowing_sub(lhs: Word, rhs: Word, borrow: Word) -> (Word, Word) {
let a = lhs as WideWord;
let b = rhs as WideWord;
let borrow = (borrow >> (Word::BITS - 1)) as WideWord;
let ret = a.wrapping_sub(b + borrow);
(ret as Word, (ret >> Word::BITS) as Word)
}
#[inline(always)]
pub(crate) const fn widening_mul(lhs: Word, rhs: Word) -> (Word, Word) {
let a = lhs as WideWord;
let b = rhs as WideWord;
let ret = a * b;
(ret as Word, (ret >> Word::BITS) as Word)
}
#[inline(always)]
pub(crate) const fn carrying_mul_add(
lhs: Word,
rhs: Word,
addend: Word,
carry: Word,
) -> (Word, Word) {
let lhs = lhs as WideWord;
let rhs = rhs as WideWord;
let addend = addend as WideWord;
let carry = carry as WideWord;
let ret = ((lhs * rhs) + addend) + carry;
(ret as Word, (ret >> Word::BITS) as Word)
}
#[cfg(test)]
mod tests {
use crate::Word;
#[test]
fn carrying_mul_add_cannot_overflow() {
let lhs = Word::MAX;
let rhs = Word::MAX;
let addend = Word::MAX;
let carry_in = Word::MAX;
let (result, carry_out) = super::carrying_mul_add(lhs, rhs, addend, carry_in);
assert_eq!(result, Word::MAX);
assert_eq!(carry_out, Word::MAX);
}
}