miden_processor/fast/
horner_ops.rs1use core::array;
2
3use miden_core::{Felt, QuadFelt};
4
5use super::FastProcessor;
6use crate::{ErrorContext, ExecutionError};
7
8const ALPHA_ADDR_INDEX: usize = 13;
12const ACC_HIGH_INDEX: usize = 14;
13const ACC_LOW_INDEX: usize = 15;
14
15impl FastProcessor {
16 #[inline(always)]
18 pub fn op_horner_eval_base(
19 &mut self,
20 err_ctx: &impl ErrorContext,
21 ) -> Result<(), ExecutionError> {
22 let coeffs = self.get_coeffs_as_base_elements();
24
25 let alpha = self.get_evaluation_point(err_ctx)?;
27
28 let (acc_new1, acc_new0) = {
30 let acc_old = self.get_accumulator();
31 let acc_new = coeffs
32 .iter()
33 .rev()
34 .fold(acc_old, |acc, coef| QuadFelt::from(*coef) + alpha * acc);
35
36 let acc_new_base_elements = acc_new.to_base_elements();
37
38 (acc_new_base_elements[1], acc_new_base_elements[0])
39 };
40
41 self.stack_write(ACC_HIGH_INDEX, acc_new1);
43 self.stack_write(ACC_LOW_INDEX, acc_new0);
44
45 Ok(())
46 }
47
48 #[inline(always)]
50 pub fn op_horner_eval_ext(
51 &mut self,
52 err_ctx: &impl ErrorContext,
53 ) -> Result<(), ExecutionError> {
54 let coef = self.get_coeffs_as_quad_ext_elements();
56
57 let alpha = self.get_evaluation_point(err_ctx)?;
59
60 let (acc_new1, acc_new0) = {
62 let acc_old = self.get_accumulator();
63 let acc_new = coef.iter().rev().fold(acc_old, |acc, coef| *coef + alpha * acc);
64
65 let acc_new_base_elements = acc_new.to_base_elements();
66
67 (acc_new_base_elements[1], acc_new_base_elements[0])
68 };
69
70 self.stack_write(ACC_HIGH_INDEX, acc_new1);
72 self.stack_write(ACC_LOW_INDEX, acc_new0);
73
74 Ok(())
75 }
76
77 fn get_coeffs_as_base_elements(&self) -> [Felt; 8] {
83 array::from_fn(|i| self.stack_get(i))
84 }
85
86 fn get_coeffs_as_quad_ext_elements(&self) -> [QuadFelt; 4] {
88 let c0 = [self.stack_get(0), self.stack_get(1)];
89 let c1 = [self.stack_get(2), self.stack_get(3)];
90 let c2 = [self.stack_get(4), self.stack_get(5)];
91 let c3 = [self.stack_get(6), self.stack_get(7)];
92
93 [
94 QuadFelt::new(c0[1], c0[0]),
95 QuadFelt::new(c1[1], c1[0]),
96 QuadFelt::new(c2[1], c2[0]),
97 QuadFelt::new(c3[1], c3[0]),
98 ]
99 }
100
101 fn get_evaluation_point(
103 &mut self,
104 err_ctx: &impl ErrorContext,
105 ) -> Result<QuadFelt, ExecutionError> {
106 let (alpha_0, alpha_1) = {
107 let addr = self.stack_get(ALPHA_ADDR_INDEX);
108 let word = self
109 .memory
110 .read_word(self.ctx, addr, self.clk, err_ctx)
111 .map_err(ExecutionError::MemoryError)?;
112
113 (word[0], word[1])
114 };
115
116 Ok(QuadFelt::new(alpha_0, alpha_1))
117 }
118
119 fn get_accumulator(&self) -> QuadFelt {
121 let acc1 = self.stack_get(ACC_HIGH_INDEX);
122 let acc0 = self.stack_get(ACC_LOW_INDEX);
123
124 QuadFelt::new(acc0, acc1)
125 }
126}