use alloc::{vec, vec::Vec};
use miden_core::{EventName, ZERO};
use miden_processor::{AdviceMutation, EventError, ProcessState};
use crate::handlers::u64_to_u32_elements;
const M: u64 = 12289;
pub const FALCON_DIV_EVENT_NAME: EventName =
EventName::new("stdlib::crypto::dsa::rpo_falcon512::falcon_div");
pub fn handle_falcon_div(process: &ProcessState) -> Result<Vec<AdviceMutation>, EventError> {
let dividend_hi = process.get_stack_item(1).as_int();
let dividend_lo = process.get_stack_item(2).as_int();
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 mutation = AdviceMutation::extend_stack([r_lo, q_lo, q_hi]);
Ok(vec![mutation])
}
#[derive(Debug, thiserror::Error)]
pub enum FalconDivError {
#[error("input value {value} at {position} is not a valid u32")]
InputNotU32 { value: u64, position: &'static str },
}