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(
29 &mut self,
30 op_idx: usize,
31 err_ctx: &impl ErrorContext,
32 ) -> Result<(), ExecutionError> {
33 let top = self.stack_get_mut(0);
34 if (*top) == ZERO {
35 return Err(ExecutionError::divide_by_zero(self.clk + op_idx, err_ctx));
36 }
37 *top = top.inv();
38 Ok(())
39 }
40
41 pub fn op_incr(&mut self) -> Result<(), ExecutionError> {
43 *self.stack_get_mut(0) += ONE;
44 Ok(())
45 }
46
47 #[inline(always)]
49 pub fn op_and(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
50 self.pop2_applyfn_push(|a, b| {
51 assert_binary(b, err_ctx)?;
52 assert_binary(a, err_ctx)?;
53
54 if a == ONE && b == ONE { Ok(ONE) } else { Ok(ZERO) }
55 })
56 }
57
58 #[inline(always)]
60 pub fn op_or(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
61 self.pop2_applyfn_push(|a, b| {
62 assert_binary(b, err_ctx)?;
63 assert_binary(a, err_ctx)?;
64
65 if a == ONE || b == ONE { Ok(ONE) } else { Ok(ZERO) }
66 })
67 }
68
69 #[inline(always)]
71 pub fn op_not(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
72 let top = self.stack_get_mut(0);
73 if *top == ZERO {
74 *top = ONE;
75 } else if *top == ONE {
76 *top = ZERO;
77 } else {
78 return Err(ExecutionError::not_binary_value_op(*top, err_ctx));
79 }
80 Ok(())
81 }
82
83 pub fn op_eq(&mut self) -> Result<(), ExecutionError> {
85 self.pop2_applyfn_push(|a, b| if a == b { Ok(ONE) } else { Ok(ZERO) })
86 }
87
88 pub fn op_eqz(&mut self) -> Result<(), ExecutionError> {
90 let top = self.stack_get_mut(0);
91 if (*top) == ZERO {
92 *top = ONE;
93 } else {
94 *top = ZERO;
95 }
96 Ok(())
97 }
98
99 pub fn op_expacc(&mut self) {
101 let old_base = self.stack_get(1);
102 let old_acc = self.stack_get(2);
103 let old_exp_int = self.stack_get(3).as_int();
104
105 let new_exp = Felt::new(old_exp_int >> 1);
107
108 let exp_lsb = old_exp_int & 1;
111 let acc_update_val = if exp_lsb == 1 { old_base } else { ONE };
112 let new_acc = old_acc * acc_update_val;
113
114 let new_base = old_base * old_base;
116
117 self.stack_write(0, Felt::new(exp_lsb));
118 self.stack_write(1, new_base);
119 self.stack_write(2, new_acc);
120 self.stack_write(3, new_exp);
121 }
122
123 pub fn op_ext2mul(&mut self) {
131 let [a0, a1, b0, b1] = self.stack_get_word(0).into();
132
133 let b0_times_a0 = b0 * a0;
136 self.stack_write(2, (b0 + b1) * (a1 + a0) - b0_times_a0);
137 self.stack_write(3, b0_times_a0 - TWO * b1 * a1);
138 }
139
140 #[inline(always)]
148 fn pop2_applyfn_push(
149 &mut self,
150 f: impl FnOnce(Felt, Felt) -> Result<Felt, ExecutionError>,
151 ) -> Result<(), ExecutionError> {
152 let b = self.stack_get(0);
153 let a = self.stack_get(1);
154
155 self.decrement_stack_size();
156 self.stack_write(0, f(a, b)?);
157
158 Ok(())
159 }
160}