use super::{HeaplessBigInt, zero};
use crate::MachineWord;
use const_num_traits::{CarryingAdd, CarryingMul, ConstOne, Personality};
impl<T, const CAP: usize, P: Personality> modmath_cios::CiosRowOps for HeaplessBigInt<T, CAP, P>
where
T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
{
type Word = T;
fn word_count(&self) -> usize {
self.len as usize
}
fn cios_accumulator(&self) -> Self {
Self::new_zero_with_len(self.len)
}
fn word(&self, i: usize) -> T {
self.limbs[i]
}
fn mul_acc_row(scalar: T, multiplicand: &Self, acc: &mut Self, carry_in: T) -> T {
let n = multiplicand.len as usize;
let mut carry = carry_in;
let mut i = 0;
while i < n {
let (t_lo, t_hi) =
<T as CarryingMul>::carrying_mul(scalar, multiplicand.limbs[i], carry);
let (sum, c) = <T as CarryingAdd>::carrying_add(acc.limbs[i], t_lo, false);
acc.limbs[i] = sum;
let (new_carry, _) = <T as CarryingAdd>::carrying_add(t_hi, zero(), c);
carry = new_carry;
i += 1;
}
carry
}
fn mul_acc_shift_row(scalar: T, multiplicand: &Self, acc: &mut Self, acc_hi: T) -> T {
let n = multiplicand.len as usize;
let mut carry = zero::<T>();
let mut i = 0;
while i < n {
let (t_lo, t_hi) =
<T as CarryingMul>::carrying_mul(scalar, multiplicand.limbs[i], carry);
let (sum, c) = <T as CarryingAdd>::carrying_add(acc.limbs[i], t_lo, false);
acc.limbs[i] = sum;
let (new_carry, _) = <T as CarryingAdd>::carrying_add(t_hi, zero(), c);
carry = new_carry;
i += 1;
}
let (top_low, top_hi_bit) = <T as CarryingAdd>::carrying_add(carry, acc_hi, false);
let mut i = 0;
while i + 1 < n {
acc.limbs[i] = acc.limbs[i + 1];
i += 1;
}
if n > 0 {
acc.limbs[n - 1] = top_low;
}
if top_hi_bit {
<T as ConstOne>::ONE
} else {
zero()
}
}
}