halo2_ecc/bigint/
sub_no_carry.rs

1use super::{CRTInteger, OverflowInteger};
2use halo2_base::{gates::GateInstructions, utils::ScalarField, Context};
3use itertools::Itertools;
4use std::cmp::max;
5
6/// # Assumptions
7/// * `a, b` have same number of limbs
8pub fn assign<F: ScalarField>(
9    gate: &impl GateInstructions<F>,
10    ctx: &mut Context<F>,
11    a: OverflowInteger<F>,
12    b: OverflowInteger<F>,
13) -> OverflowInteger<F> {
14    let out_limbs = a
15        .limbs
16        .into_iter()
17        .zip_eq(b.limbs)
18        .map(|(a_limb, b_limb)| gate.sub(ctx, a_limb, b_limb))
19        .collect();
20
21    OverflowInteger::new(out_limbs, max(a.max_limb_bits, b.max_limb_bits) + 1)
22}
23
24pub fn crt<F: ScalarField>(
25    gate: &impl GateInstructions<F>,
26    ctx: &mut Context<F>,
27    a: CRTInteger<F>,
28    b: CRTInteger<F>,
29) -> CRTInteger<F> {
30    let out_trunc = assign(gate, ctx, a.truncation, b.truncation);
31    let out_native = gate.sub(ctx, a.native, b.native);
32    let out_val = a.value - b.value;
33    CRTInteger::new(out_trunc, out_native, out_val)
34}