miden_processor/fast/
field_ops.rs1use miden_core::{Felt, FieldElement, ONE, ZERO};
2
3use super::{ExecutionError, FastProcessor};
4use crate::{ErrorContext, operations::utils::assert_binary};
5
6const TWO: Felt = Felt::new(2);
7
8impl FastProcessor {
9 pub fn op_add(&mut self) -> Result<(), ExecutionError> {
11 self.pop2_applyfn_push(|a, b| Ok(a + b))
12 }
13
14 pub fn op_neg(&mut self) -> Result<(), ExecutionError> {
16 let element = self.stack_get(0);
17 self.stack_write(0, -element);
18 Ok(())
19 }
20
21 pub fn op_mul(&mut self) -> Result<(), ExecutionError> {
23 self.pop2_applyfn_push(|a, b| Ok(a * b))
24 }
25
26 #[inline(always)]
28 pub fn op_inv(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
29 let top = self.stack_get_mut(0);
30 if (*top) == ZERO {
31 return Err(ExecutionError::divide_by_zero(self.clk, err_ctx));
32 }
33 *top = top.inv();
34 Ok(())
35 }
36
37 pub fn op_incr(&mut self) -> Result<(), ExecutionError> {
39 *self.stack_get_mut(0) += ONE;
40 Ok(())
41 }
42
43 #[inline(always)]
45 pub fn op_and(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
46 self.pop2_applyfn_push(|a, b| {
47 assert_binary(b, err_ctx)?;
48 assert_binary(a, err_ctx)?;
49
50 if a == ONE && b == ONE { Ok(ONE) } else { Ok(ZERO) }
51 })
52 }
53
54 #[inline(always)]
56 pub fn op_or(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
57 self.pop2_applyfn_push(|a, b| {
58 assert_binary(b, err_ctx)?;
59 assert_binary(a, err_ctx)?;
60
61 if a == ONE || b == ONE { Ok(ONE) } else { Ok(ZERO) }
62 })
63 }
64
65 #[inline(always)]
67 pub fn op_not(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
68 let top = self.stack_get_mut(0);
69 if *top == ZERO {
70 *top = ONE;
71 } else if *top == ONE {
72 *top = ZERO;
73 } else {
74 return Err(ExecutionError::not_binary_value_op(*top, err_ctx));
75 }
76 Ok(())
77 }
78
79 pub fn op_eq(&mut self) -> Result<(), ExecutionError> {
81 self.pop2_applyfn_push(|a, b| if a == b { Ok(ONE) } else { Ok(ZERO) })
82 }
83
84 pub fn op_eqz(&mut self) -> Result<(), ExecutionError> {
86 let top = self.stack_get_mut(0);
87 if (*top) == ZERO {
88 *top = ONE;
89 } else {
90 *top = ZERO;
91 }
92 Ok(())
93 }
94
95 pub fn op_expacc(&mut self) {
97 let old_base = self.stack_get(1);
98 let old_acc = self.stack_get(2);
99 let old_exp_int = self.stack_get(3).as_int();
100
101 let new_exp = Felt::new(old_exp_int >> 1);
103
104 let exp_lsb = old_exp_int & 1;
107 let acc_update_val = if exp_lsb == 1 { old_base } else { ONE };
108 let new_acc = old_acc * acc_update_val;
109
110 let new_base = old_base * old_base;
112
113 self.stack_write(0, Felt::new(exp_lsb));
114 self.stack_write(1, new_base);
115 self.stack_write(2, new_acc);
116 self.stack_write(3, new_exp);
117 }
118
119 pub fn op_ext2mul(&mut self) {
127 let [a0, a1, b0, b1] = self.stack_get_word(0).into();
128
129 let b0_times_a0 = b0 * a0;
132 self.stack_write(2, (b0 + b1) * (a1 + a0) - b0_times_a0);
133 self.stack_write(3, b0_times_a0 - TWO * b1 * a1);
134 }
135
136 #[inline(always)]
144 fn pop2_applyfn_push(
145 &mut self,
146 f: impl FnOnce(Felt, Felt) -> Result<Felt, ExecutionError>,
147 ) -> Result<(), ExecutionError> {
148 let b = self.stack_get(0);
149 let a = self.stack_get(1);
150
151 self.decrement_stack_size();
152 self.stack_write(0, f(a, b)?);
153
154 Ok(())
155 }
156}