use alloc::{vec, vec::Vec};
use miden_core::{Felt, utils::RowMajorMatrix};
pub use miden_precompiles_air::primitives::byte_pair_lut::*;
use crate::relations::ProvideMult;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct Multiplicities {
pub andnot: ProvideMult,
pub xor: ProvideMult,
pub range16: ProvideMult,
}
impl Multiplicities {
pub fn op(&self, op: BytePairOp) -> u32 {
match op {
BytePairOp::AndNot => self.andnot,
BytePairOp::Xor => self.xor,
}
}
pub fn is_nonzero(&self) -> bool {
self.andnot != 0 || self.xor != 0 || self.range16 != 0
}
}
const NUM_BYTE_PAIRS: usize = 1 << 16;
const fn pair_idx(a: u8, b: u8) -> usize {
((a as usize) << 8) | (b as usize)
}
#[derive(Debug, Clone)]
pub struct BytePairLutRequires {
counts: Vec<Multiplicities>,
}
impl Default for BytePairLutRequires {
fn default() -> Self {
Self {
counts: vec![Multiplicities::default(); NUM_BYTE_PAIRS],
}
}
}
impl BytePairLutRequires {
pub fn new() -> Self {
Self::default()
}
pub fn require(&mut self, op: BytePairOp, a: u8, b: u8) -> u8 {
let mults = &mut self.counts[pair_idx(a, b)];
match op {
BytePairOp::AndNot => mults.andnot += 1,
BytePairOp::Xor => mults.xor += 1,
}
op.apply(a, b)
}
pub fn require_range16(&mut self, w: u16) {
let a = (w & 0xff) as u8;
let b = (w >> 8) as u8;
self.counts[pair_idx(a, b)].range16 += 1;
}
pub fn multiplicity(&self, op: BytePairOp, a: u8, b: u8) -> ProvideMult {
self.counts[pair_idx(a, b)].op(op)
}
pub fn multiplicity_range16(&self, w: u16) -> ProvideMult {
let a = (w & 0xff) as u8;
let b = (w >> 8) as u8;
self.counts[pair_idx(a, b)].range16
}
}
pub fn require_logic64(bpl_req: &mut BytePairLutRequires, op: BytePairOp, a: u64, b: u64) -> u64 {
let a_bytes = a.to_le_bytes();
let b_bytes = b.to_le_bytes();
for i in 0..8 {
bpl_req.require(op, a_bytes[i], b_bytes[i]);
}
match op {
BytePairOp::AndNot => (!a) & b,
BytePairOp::Xor => a ^ b,
}
}
pub fn generate_trace(requires: BytePairLutRequires) -> RowMajorMatrix<Felt> {
let mut values = Vec::with_capacity(TRACE_HEIGHT * NUM_MAIN_COLS);
for mults in &requires.counts {
values.extend([Felt::from(mults.andnot), Felt::from(mults.xor), Felt::from(mults.range16)]);
}
RowMajorMatrix::new(values, NUM_MAIN_COLS)
}