use ark_ff::PrimeField;
use num_bigint::BigUint;
use num_integer::Integer;
use o1_utils::{field_helpers::BigUintFieldHelpers, FieldHelpers, ForeignElement};
use std::array;
use crate::{
circuits::{
polynomial::COLUMNS,
polynomials::foreign_field_common::{BigUintForeignFieldHelpers, LIMB_BITS},
witness::{init_row, CopyBitsCell, CopyCell, VariableCell, Variables, WitnessCell},
},
variable_map, variables,
};
fn layout<F: PrimeField>() -> [Vec<Box<dyn WitnessCell<F>>>; 4] {
[
range_check_0_row("v0", 0),
range_check_0_row("v1", 1),
vec![
VariableCell::create("v2"),
VariableCell::create("v12"), CopyBitsCell::create(2, 0, 86, 88),
CopyBitsCell::create(2, 0, 74, 86),
CopyBitsCell::create(2, 0, 62, 74),
CopyBitsCell::create(2, 0, 50, 62),
CopyBitsCell::create(2, 0, 38, 50),
CopyBitsCell::create(2, 0, 36, 38),
CopyBitsCell::create(2, 0, 34, 36),
CopyBitsCell::create(2, 0, 32, 34),
CopyBitsCell::create(2, 0, 30, 32),
CopyBitsCell::create(2, 0, 28, 30),
CopyBitsCell::create(2, 0, 26, 28),
CopyBitsCell::create(2, 0, 24, 26),
CopyBitsCell::create(2, 0, 22, 24),
],
vec![
CopyBitsCell::create(2, 0, 20, 22),
CopyBitsCell::create(2, 0, 18, 20),
CopyBitsCell::create(2, 0, 16, 18),
CopyCell::create(0, 1),
CopyCell::create(0, 2),
CopyCell::create(1, 1),
CopyCell::create(1, 2),
CopyBitsCell::create(2, 0, 14, 16),
CopyBitsCell::create(2, 0, 12, 14),
CopyBitsCell::create(2, 0, 10, 12),
CopyBitsCell::create(2, 0, 8, 10),
CopyBitsCell::create(2, 0, 6, 8),
CopyBitsCell::create(2, 0, 4, 6),
CopyBitsCell::create(2, 0, 2, 4),
CopyBitsCell::create(2, 0, 0, 2),
],
]
}
pub fn range_check_0_row<F: PrimeField>(
limb_name: &'static str,
row: usize,
) -> Vec<Box<dyn WitnessCell<F>>> {
vec![
VariableCell::create(limb_name),
CopyBitsCell::create(row, 0, 76, 88),
CopyBitsCell::create(row, 0, 64, 76),
CopyBitsCell::create(row, 0, 52, 64),
CopyBitsCell::create(row, 0, 40, 52),
CopyBitsCell::create(row, 0, 28, 40),
CopyBitsCell::create(row, 0, 16, 28),
CopyBitsCell::create(row, 0, 14, 16),
CopyBitsCell::create(row, 0, 12, 14),
CopyBitsCell::create(row, 0, 10, 12),
CopyBitsCell::create(row, 0, 8, 10),
CopyBitsCell::create(row, 0, 6, 8),
CopyBitsCell::create(row, 0, 4, 6),
CopyBitsCell::create(row, 0, 2, 4),
CopyBitsCell::create(row, 0, 0, 2),
]
}
pub fn create_multi<F: PrimeField>(v0: F, v1: F, v2: F) -> [Vec<F>; COLUMNS] {
let layout = layout();
let mut witness: [Vec<F>; COLUMNS] = array::from_fn(|_| vec![F::zero(); 4]);
init_row(&mut witness, 0, 0, &layout, &variables!(v0));
init_row(&mut witness, 0, 1, &layout, &variables!(v1));
init_row(
&mut witness,
0,
2,
&layout,
&variable_map!("v2" => v2, "v12" => F::zero()),
);
init_row(&mut witness, 0, 3, &layout, &variables!());
witness
}
pub fn create_multi_compact<F: PrimeField>(v01: F, v2: F) -> [Vec<F>; COLUMNS] {
let layout = layout();
let mut witness: [Vec<F>; COLUMNS] = array::from_fn(|_| vec![F::zero(); 4]);
let (v1, v0) = v01.to_biguint().div_rem(&BigUint::two_to_limb());
let v0: F = v0.to_field().expect("failed to convert to field element");
let v1: F = v1.to_field().expect("failed to convert to field element");
init_row(&mut witness, 0, 0, &layout, &variable_map!("v0" => v2));
init_row(&mut witness, 0, 1, &layout, &variable_map!("v1" => v0));
init_row(
&mut witness,
0,
2,
&layout,
&variable_map!("v2" => v1, "v12" => v01),
);
init_row(&mut witness, 0, 3, &layout, &variables!());
witness
}
pub fn create_multi_limbs<F: PrimeField>(limbs: &[F; 3]) -> [Vec<F>; COLUMNS] {
create_multi(limbs[0], limbs[1], limbs[2])
}
pub fn create_multi_compact_limbs<F: PrimeField>(limbs: &[F; 2]) -> [Vec<F>; COLUMNS] {
create_multi_compact(limbs[0], limbs[1])
}
pub fn create<F: PrimeField>(v0: F) -> [Vec<F>; COLUMNS] {
let layout = vec![range_check_0_row("v0", 0)];
let mut witness: [Vec<F>; COLUMNS] = array::from_fn(|_| vec![F::zero()]);
init_row(&mut witness, 0, 0, &layout, &variables!(v0));
witness
}
pub fn extend_multi<F: PrimeField>(witness: &mut [Vec<F>; COLUMNS], v0: F, v1: F, v2: F) {
let limbs_witness = create_multi(v0, v1, v2);
for col in 0..COLUMNS {
witness[col].extend(limbs_witness[col].iter())
}
}
pub fn extend_multi_compact<F: PrimeField>(witness: &mut [Vec<F>; COLUMNS], v01: F, v2: F) {
let limbs_witness = create_multi_compact(v01, v2);
for col in 0..COLUMNS {
witness[col].extend(limbs_witness[col].iter())
}
}
pub fn extend_multi_limbs<F: PrimeField>(witness: &mut [Vec<F>; COLUMNS], limbs: &[F; 3]) {
let limbs_witness = create_multi_limbs(limbs);
for col in 0..COLUMNS {
witness[col].extend(limbs_witness[col].iter())
}
}
pub fn extend_multi_compact_limbs<F: PrimeField>(witness: &mut [Vec<F>; COLUMNS], limbs: &[F; 2]) {
let limbs_witness = create_multi_compact_limbs(limbs);
for col in 0..COLUMNS {
witness[col].extend(limbs_witness[col].iter())
}
}
pub fn extend_multi_from_fe<F: PrimeField>(
witness: &mut [Vec<F>; COLUMNS],
fe: &ForeignElement<F, LIMB_BITS, 3>,
) {
extend_multi(witness, fe.limbs[0], fe.limbs[1], fe.limbs[2]);
}
pub fn extend<F: PrimeField>(witness: &mut [Vec<F>; COLUMNS], fe: F) {
let limbs_witness = create(fe);
for col in 0..COLUMNS {
witness[col].extend(limbs_witness[col].iter())
}
}
pub fn extend_single<F: PrimeField>(witness: &mut [Vec<F>; COLUMNS], elem: F) {
let single_wit = create(elem);
for col in 0..COLUMNS {
witness[col].extend(single_wit[col].iter())
}
}