#[cfg(zisk_guest)]
use crate::alloc_extern::vec;
#[cfg(zisk_guest)]
use crate::alloc_extern::vec::Vec;
use crate::zisklib::fcall_bigint_div;
use super::{add_short, mul_short, U256};
pub fn rem_short_init(
a: &[U256],
b: &U256,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> U256 {
let len_a = a.len();
#[cfg(debug_assertions)]
{
assert_ne!(len_a, 0, "Input 'a' must have at least one limb");
assert!(!b.is_zero(), "Input 'b' must be greater than zero");
if len_a > 1 {
assert!(!a[len_a - 1].is_zero(), "Input 'a' must not have leading zeros");
}
}
if len_a == 1 {
let a = a[0];
if a.is_zero() || a.lt(b) {
return a;
} else if a.eq(b) {
return U256::ZERO;
}
}
let a_flat = U256::slice_to_flat(a);
let mut quo_flat = vec![0u64; len_a * 4];
let mut rem_flat = [0u64; 4];
let (limbs_quo, limbs_rem) = fcall_bigint_div(
a_flat,
b.as_limbs(),
&mut quo_flat,
&mut rem_flat,
#[cfg(feature = "hints")]
hints,
);
assert!(0 < limbs_quo && limbs_quo <= len_a * 4, "Quotient must fit in the allocated buffer");
assert!(limbs_quo % 4 == 0, "Quotient limbs must be a multiple of 4");
assert!(0 < limbs_rem && limbs_rem <= 4, "Remainder must fit in a single U256");
let quo = U256::flat_to_slice(&quo_flat[..limbs_quo]);
let rem = U256::from_u64s(&rem_flat);
let mut q_b = vec![U256::ZERO; len_a + 1]; let mut q_b_r = vec![U256::ZERO; len_a + 1];
verify_division(
a,
b,
quo,
&rem,
&mut q_b,
&mut q_b_r,
#[cfg(feature = "hints")]
hints,
);
rem
}
#[inline(always)]
fn verify_division(
a: &[U256],
b: &U256,
quo: &[U256],
rem: &U256,
q_b: &mut [U256],
q_b_r: &mut [U256],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) {
let len_a = a.len();
let len_quo = quo.len();
assert!(len_quo > 0, "Quotient must have at least one limb");
assert!(len_quo <= len_a, "Quotient length must be less than or equal to dividend length");
assert!(!quo[len_quo - 1].is_zero(), "Quotient must not have leading zeros");
let q_b_len = mul_short(
quo,
b,
q_b,
#[cfg(feature = "hints")]
hints,
);
if rem.is_zero() {
assert!(U256::eq_slices(a, &q_b[..q_b_len]), "Remainder is zero, but a != q·b");
} else {
assert!(rem.lt(b), "Remainder must be less than divisor");
let q_b_r_len = add_short(
&q_b[..q_b_len],
rem,
q_b_r,
#[cfg(feature = "hints")]
hints,
);
assert!(U256::eq_slices(a, &q_b_r[..q_b_r_len]), "a != q·b + r");
}
}