miden_processor/fast/
field_ops.rs1use vm_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 pub fn op_inv(&mut self, op_idx: usize) -> Result<(), ExecutionError> {
28 let top = self.stack_get_mut(0);
29 if (*top) == ZERO {
30 return Err(ExecutionError::divide_by_zero(
31 self.clk + op_idx,
32 &ErrorContext::default(),
33 ));
34 }
35 *top = top.inv();
36 Ok(())
37 }
38
39 pub fn op_incr(&mut self) -> Result<(), ExecutionError> {
41 *self.stack_get_mut(0) += ONE;
42 Ok(())
43 }
44
45 pub fn op_and(&mut self) -> Result<(), ExecutionError> {
47 self.pop2_applyfn_push(|a, b| {
48 assert_binary(b)?;
49 assert_binary(a)?;
50
51 if a == ONE && b == ONE { Ok(ONE) } else { Ok(ZERO) }
52 })
53 }
54
55 pub fn op_or(&mut self) -> Result<(), ExecutionError> {
57 self.pop2_applyfn_push(|a, b| {
58 assert_binary(b)?;
59 assert_binary(a)?;
60
61 if a == ONE || b == ONE { Ok(ONE) } else { Ok(ZERO) }
62 })
63 }
64
65 pub fn op_not(&mut self) -> Result<(), ExecutionError> {
67 let top = self.stack_get_mut(0);
68 if *top == ZERO {
69 *top = ONE;
70 } else if *top == ONE {
71 *top = ZERO;
72 } else {
73 return Err(ExecutionError::not_binary_value_op(*top, &ErrorContext::default()));
74 }
75 Ok(())
76 }
77
78 pub fn op_eq(&mut self) -> Result<(), ExecutionError> {
80 self.pop2_applyfn_push(|a, b| if a == b { Ok(ONE) } else { Ok(ZERO) })
81 }
82
83 pub fn op_eqz(&mut self) -> Result<(), ExecutionError> {
85 let top = self.stack_get_mut(0);
86 if (*top) == ZERO {
87 *top = ONE;
88 } else {
89 *top = ZERO;
90 }
91 Ok(())
92 }
93
94 pub fn op_expacc(&mut self) {
96 let old_base = self.stack_get(1);
97 let old_acc = self.stack_get(2);
98 let old_exp_int = self.stack_get(3).as_int();
99
100 let new_exp = Felt::new(old_exp_int >> 1);
102
103 let exp_lsb = old_exp_int & 1;
106 let acc_update_val = if exp_lsb == 1 { old_base } else { ONE };
107 let new_acc = old_acc * acc_update_val;
108
109 let new_base = old_base * old_base;
111
112 self.stack_write(0, Felt::new(exp_lsb));
113 self.stack_write(1, new_base);
114 self.stack_write(2, new_acc);
115 self.stack_write(3, new_exp);
116 }
117
118 pub fn op_ext2mul(&mut self) {
126 let [a0, a1, b0, b1] = self.stack_get_word(0);
127
128 let b0_times_a0 = b0 * a0;
131 self.stack_write(2, (b0 + b1) * (a1 + a0) - b0_times_a0);
132 self.stack_write(3, b0_times_a0 - TWO * b1 * a1);
133 }
134
135 #[inline(always)]
143 fn pop2_applyfn_push(
144 &mut self,
145 f: impl FnOnce(Felt, Felt) -> Result<Felt, ExecutionError>,
146 ) -> Result<(), ExecutionError> {
147 let b = self.stack_get(0);
148 let a = self.stack_get(1);
149
150 self.decrement_stack_size();
151 self.stack_write(0, f(a, b)?);
152
153 Ok(())
154 }
155}