use std::fmt::Debug;
use p3_air::AirBuilder;
use p3_field::{Field, PrimeCharacteristicRing};
use serde::{Deserialize, Serialize};
use crate::air_builders::symbolic::symbolic_expression::SymbolicExpression;
pub mod debug;
pub type BusIndex = u16;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Interaction<Expr> {
pub message: Vec<Expr>,
pub count: Expr,
pub bus_index: BusIndex,
pub count_weight: u32,
}
pub type SymbolicInteraction<F> = Interaction<SymbolicExpression<F>>;
pub trait InteractionBuilder: AirBuilder<F: Field, Var: Copy> {
fn push_interaction<E: Into<Self::Expr>>(
&mut self,
bus_index: BusIndex,
fields: impl IntoIterator<Item = E>,
count: impl Into<Self::Expr>,
count_weight: u32,
);
fn num_interactions(&self) -> usize;
fn all_interactions(&self) -> &[Interaction<Self::Expr>];
fn assert_tern(&mut self, x: impl Into<Self::Expr>) {
let x = x.into();
self.assert_zero(x.clone() * (x.clone() - Self::Expr::ONE) * (x - Self::Expr::TWO));
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct LookupBus {
pub index: BusIndex,
}
impl LookupBus {
pub const fn new(index: BusIndex) -> Self {
Self { index }
}
pub fn lookup_key<AB, E>(
&self,
builder: &mut AB,
query: impl IntoIterator<Item = E>,
enabled: impl Into<AB::Expr>,
) where
AB: InteractionBuilder,
E: Into<AB::Expr>,
{
builder.push_interaction(self.index, query, enabled, 1);
}
pub fn add_key_with_lookups<AB, E>(
&self,
builder: &mut AB,
key: impl IntoIterator<Item = E>,
num_lookups: impl Into<AB::Expr>,
) where
AB: InteractionBuilder,
E: Into<AB::Expr>,
{
builder.push_interaction(self.index, key, -num_lookups.into(), 0);
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct PermutationCheckBus {
pub index: BusIndex,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PermutationInteractionType {
Send,
Receive,
}
impl PermutationCheckBus {
pub const fn new(index: BusIndex) -> Self {
Self { index }
}
pub fn send<AB, E>(
&self,
builder: &mut AB,
message: impl IntoIterator<Item = E>,
enabled: impl Into<AB::Expr>,
) where
AB: InteractionBuilder,
E: Into<AB::Expr>,
{
builder.push_interaction(self.index, message, enabled, 1);
}
pub fn receive<AB, E>(
&self,
builder: &mut AB,
message: impl IntoIterator<Item = E>,
enabled: impl Into<AB::Expr>,
) where
AB: InteractionBuilder,
E: Into<AB::Expr>,
{
builder.push_interaction(self.index, message, -enabled.into(), 1);
}
pub fn send_or_receive<AB, E>(
&self,
builder: &mut AB,
interaction_type: PermutationInteractionType,
message: impl IntoIterator<Item = E>,
enabled: impl Into<AB::Expr>,
) where
AB: InteractionBuilder,
E: Into<AB::Expr>,
{
match interaction_type {
PermutationInteractionType::Send => self.send(builder, message, enabled),
PermutationInteractionType::Receive => self.receive(builder, message, enabled),
}
}
pub fn interact<AB, E>(
&self,
builder: &mut AB,
message: impl IntoIterator<Item = E>,
direction: impl Into<AB::Expr>,
) where
AB: InteractionBuilder,
E: Into<AB::Expr>,
{
builder.push_interaction(self.index, message, direction.into(), 1);
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[repr(C)]
pub struct LogUpSecurityParameters {
pub max_interaction_count: u32,
pub log_max_message_length: u32,
pub pow_bits: usize,
}
impl LogUpSecurityParameters {
pub fn max_message_length(&self) -> usize {
2usize
.checked_pow(self.log_max_message_length)
.expect("max_message_length overflowed usize")
}
}