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 op_idx: usize,
21 err_ctx: &impl ErrorContext,
22 ) -> Result<(), ExecutionError> {
23 let coeffs = self.get_coeffs_as_base_elements();
25
26 let alpha = self.get_evaluation_point(op_idx, err_ctx)?;
28
29 let (acc_new1, acc_new0) = {
31 let acc_old = self.get_accumulator();
32 let acc_new = coeffs
33 .iter()
34 .rev()
35 .fold(acc_old, |acc, coef| QuadFelt::from(*coef) + alpha * acc);
36
37 let acc_new_base_elements = acc_new.to_base_elements();
38
39 (acc_new_base_elements[1], acc_new_base_elements[0])
40 };
41
42 self.stack_write(ACC_HIGH_INDEX, acc_new1);
44 self.stack_write(ACC_LOW_INDEX, acc_new0);
45
46 Ok(())
47 }
48
49 #[inline(always)]
51 pub fn op_horner_eval_ext(
52 &mut self,
53 op_idx: usize,
54 err_ctx: &impl ErrorContext,
55 ) -> Result<(), ExecutionError> {
56 let coef = self.get_coeffs_as_quad_ext_elements();
58
59 let alpha = self.get_evaluation_point(op_idx, err_ctx)?;
61
62 let (acc_new1, acc_new0) = {
64 let acc_old = self.get_accumulator();
65 let acc_new = coef.iter().rev().fold(acc_old, |acc, coef| *coef + alpha * acc);
66
67 let acc_new_base_elements = acc_new.to_base_elements();
68
69 (acc_new_base_elements[1], acc_new_base_elements[0])
70 };
71
72 self.stack_write(ACC_HIGH_INDEX, acc_new1);
74 self.stack_write(ACC_LOW_INDEX, acc_new0);
75
76 Ok(())
77 }
78
79 fn get_coeffs_as_base_elements(&self) -> [Felt; 8] {
85 array::from_fn(|i| self.stack_get(i))
86 }
87
88 fn get_coeffs_as_quad_ext_elements(&self) -> [QuadFelt; 4] {
90 let c0 = [self.stack_get(0), self.stack_get(1)];
91 let c1 = [self.stack_get(2), self.stack_get(3)];
92 let c2 = [self.stack_get(4), self.stack_get(5)];
93 let c3 = [self.stack_get(6), self.stack_get(7)];
94
95 [
96 QuadFelt::new(c0[1], c0[0]),
97 QuadFelt::new(c1[1], c1[0]),
98 QuadFelt::new(c2[1], c2[0]),
99 QuadFelt::new(c3[1], c3[0]),
100 ]
101 }
102
103 fn get_evaluation_point(
105 &mut self,
106 op_idx: usize,
107 err_ctx: &impl ErrorContext,
108 ) -> Result<QuadFelt, ExecutionError> {
109 let (alpha_0, alpha_1) = {
110 let addr = self.stack_get(ALPHA_ADDR_INDEX);
111 let word = self
112 .memory
113 .read_word(self.ctx, addr, self.clk + op_idx, err_ctx)
114 .map_err(ExecutionError::MemoryError)?;
115
116 (word[0], word[1])
117 };
118
119 Ok(QuadFelt::new(alpha_0, alpha_1))
120 }
121
122 fn get_accumulator(&self) -> QuadFelt {
124 let acc1 = self.stack_get(ACC_HIGH_INDEX);
125 let acc0 = self.stack_get(ACC_LOW_INDEX);
126
127 QuadFelt::new(acc0, acc1)
128 }
129}