sp1_recursion_circuit_v2/
domain.rs

1use p3_commit::{LagrangeSelectors, PolynomialSpace, TwoAdicMultiplicativeCoset};
2use p3_field::{AbstractExtensionField, AbstractField, Field, TwoAdicField};
3use sp1_recursion_compiler::prelude::*;
4
5/// Reference: [p3_commit::PolynomialSpace]
6pub trait PolynomialSpaceVariable<C: Config>: Sized + PolynomialSpace<Val = C::F> {
7    fn selectors_at_point_variable(
8        &self,
9        builder: &mut Builder<C>,
10        point: Ext<C::F, C::EF>,
11    ) -> LagrangeSelectors<Ext<C::F, C::EF>>;
12
13    fn zp_at_point_variable(
14        &self,
15        builder: &mut Builder<C>,
16        point: Ext<C::F, C::EF>,
17    ) -> Ext<C::F, C::EF>;
18
19    fn next_point_variable(
20        &self,
21        builder: &mut Builder<C>,
22        point: Ext<<C as Config>::F, <C as Config>::EF>,
23    ) -> Ext<<C as Config>::F, <C as Config>::EF>;
24
25    fn zp_at_point_f(
26        &self,
27        builder: &mut Builder<C>,
28        point: Felt<<C as Config>::F>,
29    ) -> Felt<<C as Config>::F>;
30}
31
32impl<C: Config> PolynomialSpaceVariable<C> for TwoAdicMultiplicativeCoset<C::F>
33where
34    C::F: TwoAdicField,
35{
36    fn next_point_variable(
37        &self,
38        builder: &mut Builder<C>,
39        point: Ext<<C as Config>::F, <C as Config>::EF>,
40    ) -> Ext<<C as Config>::F, <C as Config>::EF> {
41        let g = C::F::two_adic_generator(self.log_n);
42        // let g: Felt<_> = builder.eval(g);
43        builder.eval(point * g)
44    }
45
46    fn selectors_at_point_variable(
47        &self,
48        builder: &mut Builder<C>,
49        point: Ext<<C as Config>::F, <C as Config>::EF>,
50    ) -> LagrangeSelectors<Ext<<C as Config>::F, <C as Config>::EF>> {
51        let unshifted_point: Ext<_, _> = builder.eval(point * self.shift.inverse());
52        let z_h_expr = builder
53            .exp_power_of_2_v::<Ext<_, _>>(unshifted_point, Usize::Const(self.log_n))
54            - C::EF::one();
55        let z_h: Ext<_, _> = builder.eval(z_h_expr);
56        let g = C::F::two_adic_generator(self.log_n);
57        let ginv = g.inverse();
58        LagrangeSelectors {
59            is_first_row: builder.eval(z_h / (unshifted_point - C::EF::one())),
60            is_last_row: builder.eval(z_h / (unshifted_point - ginv)),
61            is_transition: builder.eval(unshifted_point - ginv),
62            inv_zeroifier: builder.eval(z_h.inverse()),
63        }
64    }
65
66    fn zp_at_point_variable(
67        &self,
68        builder: &mut Builder<C>,
69        point: Ext<<C as Config>::F, <C as Config>::EF>,
70    ) -> Ext<<C as Config>::F, <C as Config>::EF> {
71        let unshifted_power = builder.exp_power_of_2_v::<Ext<_, _>>(
72            point
73                * C::EF::from_base_slice(&[self.shift, C::F::zero(), C::F::zero(), C::F::zero()])
74                    .inverse()
75                    .cons(),
76            Usize::Const(self.log_n),
77        );
78        builder.eval(unshifted_power - C::EF::one())
79    }
80    fn zp_at_point_f(
81        &self,
82        builder: &mut Builder<C>,
83        point: Felt<<C as Config>::F>,
84    ) -> Felt<<C as Config>::F> {
85        let unshifted_power = builder
86            .exp_power_of_2_v::<Felt<_>>(point * self.shift.inverse(), Usize::Const(self.log_n));
87        builder.eval(unshifted_power - C::F::one())
88    }
89}