miden_stdlib/handlers/
u64_div.rs1use alloc::{vec, vec::Vec};
7
8use miden_core::EventName;
9use miden_processor::{AdviceMutation, EventError, ProcessState};
10
11use crate::handlers::u64_to_u32_elements;
12
13pub const U64_DIV_EVENT_NAME: EventName = EventName::new("stdlib::math::u64::u64_div");
15
16pub fn handle_u64_div(process: &ProcessState) -> Result<Vec<AdviceMutation>, EventError> {
36 let divisor = {
37 let divisor_hi = process.get_stack_item(1).as_int();
38 let divisor_lo = process.get_stack_item(2).as_int();
39
40 if divisor_hi > u32::MAX.into() {
42 return Err(U64DivError::NotU32Value {
43 value: divisor_hi,
44 position: "divisor_hi",
45 }
46 .into());
47 }
48 if divisor_lo > u32::MAX.into() {
49 return Err(U64DivError::NotU32Value {
50 value: divisor_lo,
51 position: "divisor_lo",
52 }
53 .into());
54 }
55
56 let divisor = (divisor_hi << 32) + divisor_lo;
57
58 if divisor == 0 {
59 return Err(U64DivError::DivideByZero.into());
60 }
61
62 divisor
63 };
64
65 let dividend = {
66 let dividend_hi = process.get_stack_item(3).as_int();
67 let dividend_lo = process.get_stack_item(4).as_int();
68
69 if dividend_hi > u32::MAX.into() {
71 return Err(U64DivError::NotU32Value {
72 value: dividend_hi,
73 position: "dividend_hi",
74 }
75 .into());
76 }
77 if dividend_lo > u32::MAX.into() {
78 return Err(U64DivError::NotU32Value {
79 value: dividend_lo,
80 position: "dividend_lo",
81 }
82 .into());
83 }
84
85 (dividend_hi << 32) + dividend_lo
86 };
87
88 let quotient = dividend / divisor;
89 let remainder = dividend - quotient * divisor;
90
91 let (q_hi, q_lo) = u64_to_u32_elements(quotient);
92 let (r_hi, r_lo) = u64_to_u32_elements(remainder);
93
94 let mutation = AdviceMutation::extend_stack([r_hi, r_lo, q_hi, q_lo]);
98 Ok(vec![mutation])
99}
100
101#[derive(Debug, thiserror::Error)]
106pub enum U64DivError {
107 #[error("division by zero")]
109 DivideByZero,
110
111 #[error("value {value} at {position} is not a valid u32")]
113 NotU32Value { value: u64, position: &'static str },
114}