use alloc::vec::Vec;
use miden_core::{
Felt,
field::{PrimeCharacteristicRing, QuadFelt},
utils::RowMajorMatrix,
};
use miden_lifted_air::{AirBuilder, BaseAir, LiftedAir, LiftedAirBuilder};
use crate::{
ec::EcGroupMsg,
logup::{
CyclicConstraintLookupBuilder, Deg, LookupAir, LookupBatch, LookupBuilder, LookupColumn,
LookupGroup, NUM_PUBLIC_VALUES, NUM_RANDOMNESS, NUM_SIGMA_VALUES,
},
relations::{MAX_MESSAGE_WIDTH, NUM_BUS_IDS},
utils::{current_main, next_main},
};
pub const COL_PTR: usize = 0;
pub const COL_A_PTR: usize = 1;
pub const COL_B_PTR: usize = 2;
pub const COL_BOUND_PTR: usize = 3;
pub const COL_SBOUND_PTR: usize = 4;
pub const COL_MULT: usize = 5;
pub const NUM_MAIN_COLS: usize = 6;
const NUM_LOGUP_COLS: usize = 1;
const AUX_WIDTH: usize = 1;
const COLUMN_SHAPE: [usize; NUM_LOGUP_COLS] = [1];
#[derive(Debug, Default, Clone, Copy)]
pub struct EcGroupsAir;
impl BaseAir<Felt> for EcGroupsAir {
fn width(&self) -> usize {
NUM_MAIN_COLS
}
fn num_public_values(&self) -> usize {
NUM_PUBLIC_VALUES
}
}
impl LiftedAir<Felt, QuadFelt> for EcGroupsAir {
fn num_randomness(&self) -> usize {
NUM_RANDOMNESS
}
fn aux_width(&self) -> usize {
AUX_WIDTH
}
fn num_aux_values(&self) -> usize {
NUM_SIGMA_VALUES
}
fn build_aux_trace(
&self,
main: &RowMajorMatrix<Felt>,
_air_inputs: &[Felt],
_aux_inputs: &[Felt],
challenges: &[QuadFelt],
) -> (RowMajorMatrix<QuadFelt>, Vec<QuadFelt>) {
crate::ec::trace::build_groups_aux(main, challenges)
}
fn eval<AB: LiftedAirBuilder<F = Felt>>(&self, builder: &mut AB) {
let local: [AB::Var; NUM_MAIN_COLS] = current_main(builder.main(), 0);
let next: [AB::Var; NUM_MAIN_COLS] = next_main(builder.main(), 0);
let ptr: AB::Expr = local[COL_PTR].into();
let ptr_next: AB::Expr = next[COL_PTR].into();
builder.when_transition().assert_zero(ptr_next - ptr.clone() - AB::Expr::ONE);
builder.when_first_row().assert_zero(ptr - AB::Expr::ONE);
let mut lb =
CyclicConstraintLookupBuilder::new(builder, self, self.preprocessed_width() > 0);
<Self as LookupAir<_>>::eval(self, &mut lb);
}
}
impl<LB> LookupAir<LB> for EcGroupsAir
where
LB: LookupBuilder<F = Felt>,
{
fn num_columns(&self) -> usize {
NUM_LOGUP_COLS
}
fn column_shape(&self) -> &[usize] {
&COLUMN_SHAPE
}
fn max_message_width(&self) -> usize {
MAX_MESSAGE_WIDTH
}
fn num_bus_ids(&self) -> usize {
NUM_BUS_IDS
}
fn eval(&self, builder: &mut LB) {
let local: [LB::Var; NUM_MAIN_COLS] = current_main(builder.main(), 0);
let neg_mult: LB::Expr = LB::Expr::ZERO - local[COL_MULT].into();
let provide_deg = Deg { v: 1, u: 1 };
let col_deg = Deg { v: 1, u: 1 };
builder.next_column(
|col| {
col.group(
"ec-groups",
|g| {
g.batch(
"ec-groups-fractions",
LB::Expr::ONE,
|b| {
b.insert(
"provide-ecgroup",
neg_mult,
EcGroupMsg {
group_ptr: local[COL_PTR].into(),
a_ptr: local[COL_A_PTR].into(),
b_ptr: local[COL_B_PTR].into(),
bound_ptr: local[COL_BOUND_PTR].into(),
scalar_bound_ptr: local[COL_SBOUND_PTR].into(),
},
provide_deg,
);
},
col_deg,
);
},
col_deg,
);
},
col_deg,
);
}
}