miden_processor/fast/
horner_ops.rs1use core::array;
2
3use vm_core::Felt;
4
5use super::FastProcessor;
6use crate::{ExecutionError, QuadFelt};
7
8const ALPHA_ADDR_INDEX: usize = 13;
12const ACC_HIGH_INDEX: usize = 14;
13const ACC_LOW_INDEX: usize = 15;
14
15impl FastProcessor {
16 pub fn op_horner_eval_base(&mut self, op_idx: usize) -> Result<(), ExecutionError> {
18 let coeffs = self.get_coeffs_as_base_elements();
20
21 let alpha = self.get_evaluation_point(op_idx)?;
23
24 let (acc_new1, acc_new0) = {
26 let acc_old = self.get_accumulator();
27 let acc_new = coeffs
28 .iter()
29 .rev()
30 .fold(acc_old, |acc, coef| QuadFelt::from(*coef) + alpha * acc);
31
32 let acc_new_base_elements = acc_new.to_base_elements();
33
34 (acc_new_base_elements[1], acc_new_base_elements[0])
35 };
36
37 self.stack_write(ACC_HIGH_INDEX, acc_new1);
39 self.stack_write(ACC_LOW_INDEX, acc_new0);
40
41 Ok(())
42 }
43
44 pub fn op_horner_eval_ext(&mut self, op_idx: usize) -> Result<(), ExecutionError> {
46 let coef = self.get_coeffs_as_quad_ext_elements();
48
49 let alpha = self.get_evaluation_point(op_idx)?;
51
52 let (acc_new1, acc_new0) = {
54 let acc_old = self.get_accumulator();
55 let acc_new = coef.iter().rev().fold(acc_old, |acc, coef| *coef + alpha * acc);
56
57 let acc_new_base_elements = acc_new.to_base_elements();
58
59 (acc_new_base_elements[1], acc_new_base_elements[0])
60 };
61
62 self.stack_write(ACC_HIGH_INDEX, acc_new1);
64 self.stack_write(ACC_LOW_INDEX, acc_new0);
65
66 Ok(())
67 }
68
69 fn get_coeffs_as_base_elements(&self) -> [Felt; 8] {
75 array::from_fn(|i| self.stack_get(i))
76 }
77
78 fn get_coeffs_as_quad_ext_elements(&self) -> [QuadFelt; 4] {
80 let c0 = [self.stack_get(0), self.stack_get(1)];
81 let c1 = [self.stack_get(2), self.stack_get(3)];
82 let c2 = [self.stack_get(4), self.stack_get(5)];
83 let c3 = [self.stack_get(6), self.stack_get(7)];
84
85 [
86 QuadFelt::new(c0[1], c0[0]),
87 QuadFelt::new(c1[1], c1[0]),
88 QuadFelt::new(c2[1], c2[0]),
89 QuadFelt::new(c3[1], c3[0]),
90 ]
91 }
92
93 fn get_evaluation_point(&mut self, op_idx: usize) -> Result<QuadFelt, ExecutionError> {
95 let (alpha_0, alpha_1) = {
96 let addr = self.stack_get(ALPHA_ADDR_INDEX);
97 let word = self.memory.read_word(self.ctx, addr, self.clk + op_idx)?;
98
99 (word[0], word[1])
100 };
101
102 Ok(QuadFelt::new(alpha_0, alpha_1))
103 }
104
105 fn get_accumulator(&self) -> QuadFelt {
107 let acc1 = self.stack_get(ACC_HIGH_INDEX);
108 let acc0 = self.stack_get(ACC_LOW_INDEX);
109
110 QuadFelt::new(acc0, acc1)
111 }
112}