use alloc::{vec, vec::Vec};
use miden_core::{ZERO, events::EventName};
use miden_processor::{ProcessorState, advice::AdviceMutation, event::EventError};
use crate::handlers::u64_to_u32_elements;
const M: u64 = 12289;
pub const FALCON_DIV_EVENT_NAME: EventName =
EventName::new("miden::core::crypto::dsa::falcon512_poseidon2::falcon_div");
pub fn handle_falcon_div(process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError> {
let dividend_hi = process.get_stack_item(1).as_canonical_u64();
let dividend_lo = process.get_stack_item(2).as_canonical_u64();
if dividend_lo > u32::MAX.into() {
return Err(FalconDivError::InputNotU32 {
value: dividend_lo,
position: "dividend_lo",
}
.into());
}
if dividend_hi > u32::MAX.into() {
return Err(FalconDivError::InputNotU32 {
value: dividend_hi,
position: "dividend_hi",
}
.into());
}
let dividend = (dividend_hi << 32) + dividend_lo;
let (quotient, remainder) = (dividend / M, dividend % M);
let (q_hi, q_lo) = u64_to_u32_elements(quotient);
let (r_hi, r_lo) = u64_to_u32_elements(remainder);
assert_eq!(r_hi, ZERO);
let remainder = AdviceMutation::extend_stack([r_lo]);
let quotient = AdviceMutation::extend_stack([q_hi, q_lo]);
Ok(vec![remainder, quotient])
}
#[derive(Debug, thiserror::Error)]
pub enum FalconDivError {
#[error("input value {value} at {position} is not a valid u32")]
InputNotU32 { value: u64, position: &'static str },
}