use crate::math::numbers::gcd::limbs::{Matrix1, gcd_11};
#[inline]
pub(in crate::math::numbers) unsafe fn reduce_pair(a: *mut u64, b: *mut u64, n: usize, m: Matrix1) {
let (mut ca, mut cb) = (0i128, 0i128);
unsafe {
for i in 0..n {
let (x, y) = (u128::from(*a.add(i)), u128::from(*b.add(i)));
let p = (u128::from(m.u11) * x) as i128 - (u128::from(m.u01) * y) as i128 + ca;
let q = (u128::from(m.u00) * y) as i128 - (u128::from(m.u10) * x) as i128 + cb;
*a.add(i) = p as u64;
*b.add(i) = q as u64;
ca = p >> 64;
cb = q >> 64;
}
}
debug_assert!(ca == 0 && cb == 0, "a reduced pair is negative or too long");
}
#[inline]
pub(in crate::math::numbers) unsafe fn extend_row(
x: *mut u64,
y: *mut u64,
n: usize,
m: Matrix1,
) -> (u64, u64) {
let (mut cx, mut cy) = (0u64, 0u64);
unsafe {
for i in 0..n {
let (u, v) = (u128::from(*x.add(i)), u128::from(*y.add(i)));
let p = u128::from(m.u00) * u + u128::from(m.u10) * v + u128::from(cx);
let q = u128::from(m.u01) * u + u128::from(m.u11) * v + u128::from(cy);
*x.add(i) = p as u64;
*y.add(i) = q as u64;
cx = (p >> 64) as u64;
cy = (q >> 64) as u64;
}
}
(cx, cy)
}
#[inline]
pub(in crate::math::numbers) unsafe fn addmul_1(
r: *mut u64,
x: *const u64,
n: usize,
y: u64,
) -> u64 {
let mut carry = 0;
unsafe {
for i in 0..n {
let p =
u128::from(*x.add(i)) * u128::from(y) + u128::from(*r.add(i)) + u128::from(carry);
*r.add(i) = p as u64;
carry = (p >> 64) as u64;
}
}
carry
}
#[inline(always)]
pub(in crate::math::numbers) fn small_q1(n: u64, d: u64) -> (u64, u64) {
let mut r = n;
let mut q = 0;
for k in [2, 1, 0] {
let (t, borrow) = r.overflowing_sub(d << k);
r = core::hint::select_unpredictable(borrow, r, t);
q = (q << 1) | u64::from(!borrow);
}
(q, r)
}
#[inline(always)]
pub(in crate::math::numbers) fn small_q2(n: u128, d: u128) -> (u64, u128) {
let mut r = n;
let mut q = 0;
for k in [2, 1, 0] {
let (t, borrow) = r.overflowing_sub(d << k);
r = core::hint::select_unpredictable(borrow, r, t);
q = (q << 1) | u64::from(!borrow);
}
(q, r)
}
#[inline]
pub(in crate::math::numbers) fn gcd_22(mut u: u128, mut v: u128) -> u128 {
debug_assert!(u & v & 1 == 1);
while (u | v) >> 64 != 0 {
let (d, below) = u.overflowing_sub(v);
if d == 0 {
return u;
}
let zeros = d.trailing_zeros();
if below {
v = u;
}
u = if below { d.wrapping_neg() } else { d } >> zeros;
}
u128::from(gcd_11(u as u64, v as u64))
}