use alloc::{vec, vec::Vec};
use miden_core::{Felt, chiplets::hasher::Hasher};
use crate::transcript::poseidon2::math::STATE_WIDTH;
pub const PERIOD: usize = 16;
pub const NUM_PERIODIC_COLS: usize = 4 + STATE_WIDTH;
pub const PCOL_IS_INIT_EXT: usize = 0;
pub const PCOL_IS_EXT: usize = 1;
pub const PCOL_IS_PACKED_INT: usize = 2;
pub const PCOL_IS_INT_EXT: usize = 3;
pub const PCOL_ARK_BEGIN: usize = 4;
pub const PCOL_ARK_END: usize = PCOL_ARK_BEGIN + STATE_WIDTH;
pub const ROW_INIT_EXT: usize = 0;
pub const ROW_BOUNDARY: usize = PERIOD - 1;
pub const ROW_INT_EXT: usize = 11;
pub const PACKED_INT_BEGIN: usize = 4;
pub const PACKED_INT_END: usize = 11;
pub const NUM_PACKED_INT_ROWS: usize = PACKED_INT_END - PACKED_INT_BEGIN;
pub const NUM_PACKED_INT_RCS: usize = NUM_PACKED_INT_ROWS * 3;
pub const ARK_INT_LAST_IDX: usize = NUM_PACKED_INT_RCS;
pub fn poseidon2_program() -> [Vec<Felt>; NUM_PERIODIC_COLS] {
let mut cols: [Vec<Felt>; NUM_PERIODIC_COLS] =
core::array::from_fn(|_| vec![Felt::ZERO; PERIOD]);
cols[PCOL_IS_INIT_EXT][ROW_INIT_EXT] = Felt::ONE;
for r in [1, 2, 3, 12, 13, 14] {
cols[PCOL_IS_EXT][r] = Felt::ONE;
}
cols[PCOL_IS_PACKED_INT][PACKED_INT_BEGIN..PACKED_INT_END].fill(Felt::ONE);
cols[PCOL_IS_INT_EXT][ROW_INT_EXT] = Felt::ONE;
for (r, ark_row) in Hasher::ARK_EXT_INITIAL.iter().enumerate() {
for lane in 0..STATE_WIDTH {
cols[PCOL_ARK_BEGIN + lane][r] = ark_row[lane];
}
}
for triple in 0..NUM_PACKED_INT_ROWS {
let row = PACKED_INT_BEGIN + triple;
for k in 0..3 {
let ark_idx = triple * 3 + k;
cols[PCOL_ARK_BEGIN + k][row] = Hasher::ARK_INT[ark_idx];
}
}
for lane in 0..STATE_WIDTH {
cols[PCOL_ARK_BEGIN + lane][ROW_INT_EXT] = Hasher::ARK_EXT_TERMINAL[0][lane];
}
for (r, ark_row) in (12..=14).zip(Hasher::ARK_EXT_TERMINAL.iter().skip(1)) {
for lane in 0..STATE_WIDTH {
cols[PCOL_ARK_BEGIN + lane][r] = ark_row[lane];
}
}
cols
}