in src/integer_arith/scalar.rs [323:367]
fn _barret_reduce(a: (u64, u64), ratio: (u64, u64), q: u64) -> u64 {
// compute w = a*ratio >> 128.
// start with lw(a1r1)
let mut w = 0;
if a.1 != 0{
w = a.1.wrapping_mul(ratio.1);
}
let a0r0 = Scalar::_multiply_u64(a.0, ratio.0);
let a0r1 = Scalar::_multiply_u64(a.0, ratio.1);
// w += hw(a0r1)
w += a0r1.1;
// compute hw(a0r0) + lw(a0r1), add carry into w. put result into tmp.
let (tmp, carry) = Scalar::_add_u64(a0r0.1, a0r1.0);
w += carry as u64;
// Round2
if a.1 != 0{
let a1r0 = Scalar::_multiply_u64(a.1, ratio.0);
w += a1r0.1;
// final carry
let (_, carry2) = Scalar::_add_u64(a1r0.0, tmp);
w += carry2 as u64;
}
// low = w*q mod 2^64.
// let low = Scalar::multiply_u64(w, q).0;
let low = w.wrapping_mul(q);
let mut res;
if a.0 >= low {
res = a.0 - low;
} else {
// res = a.0 + 2^64 - low.
res = a.0 + (!low) + 1;
}
if res >= q {
res -= q;
}
res
}