1use std::fmt::Debug;
4
5use binius_field::PackedField;
6use either::Either;
7
8use crate::{Error, MultilinearExtension, MultilinearQueryRef};
9
10#[auto_impl::auto_impl(&, &mut, Box, Rc, Arc)]
14pub trait MultilinearPoly<P: PackedField>: Debug {
15 fn n_vars(&self) -> usize;
17
18 fn size(&self) -> usize {
20 1 << self.n_vars()
21 }
22
23 fn log_extension_degree(&self) -> usize;
25
26 fn evaluate_on_hypercube(&self, index: usize) -> Result<P::Scalar, Error>;
32
33 fn evaluate_on_hypercube_and_scale(
43 &self,
44 index: usize,
45 scalar: P::Scalar,
46 ) -> Result<P::Scalar, Error>;
47
48 fn evaluate(&self, query: MultilinearQueryRef<P>) -> Result<P::Scalar, Error>;
49
50 fn evaluate_partial_low(
51 &self,
52 query: MultilinearQueryRef<P>,
53 ) -> Result<MultilinearExtension<P>, Error>;
54
55 fn evaluate_partial_high(
56 &self,
57 query: MultilinearQueryRef<P>,
58 ) -> Result<MultilinearExtension<P>, Error>;
59
60 fn evaluate_partial(
61 &self,
62 query: MultilinearQueryRef<P>,
63 start_index: usize,
64 ) -> Result<MultilinearExtension<P>, Error>;
65
66 fn subcube_partial_low_evals(
71 &self,
72 query: MultilinearQueryRef<P>,
73 subcube_vars: usize,
74 subcube_index: usize,
75 partial_low_evals: &mut [P],
76 ) -> Result<(), Error>;
77
78 fn subcube_partial_high_evals(
83 &self,
84 query: MultilinearQueryRef<P>,
85 subcube_vars: usize,
86 subcube_index: usize,
87 partial_high_evals: &mut [P],
88 ) -> Result<(), Error>;
89
90 fn subcube_evals(
103 &self,
104 subcube_vars: usize,
105 subcube_index: usize,
106 log_embedding_degree: usize,
107 evals: &mut [P],
108 ) -> Result<(), Error>;
109
110 fn packed_evals(&self) -> Option<&[P]>;
127}
128
129impl<P, L, R> MultilinearPoly<P> for Either<L, R>
130where
131 P: PackedField,
132 L: MultilinearPoly<P>,
133 R: MultilinearPoly<P>,
134{
135 fn n_vars(&self) -> usize {
136 either::for_both!(self, inner => inner.n_vars())
137 }
138
139 fn size(&self) -> usize {
140 either::for_both!(self, inner => inner.size())
141 }
142
143 fn log_extension_degree(&self) -> usize {
144 either::for_both!(self, inner => inner.log_extension_degree())
145 }
146
147 fn evaluate_on_hypercube(&self, index: usize) -> Result<P::Scalar, Error> {
148 either::for_both!(self, inner => inner.evaluate_on_hypercube(index))
149 }
150
151 fn evaluate_on_hypercube_and_scale(
152 &self,
153 index: usize,
154 scalar: P::Scalar,
155 ) -> Result<P::Scalar, Error> {
156 either::for_both!(self, inner => inner.evaluate_on_hypercube_and_scale(index, scalar))
157 }
158
159 fn evaluate(&self, query: MultilinearQueryRef<P>) -> Result<P::Scalar, Error> {
160 either::for_both!(self, inner => inner.evaluate(query))
161 }
162
163 fn evaluate_partial(
164 &self,
165 query: MultilinearQueryRef<P>,
166 start_index: usize,
167 ) -> Result<MultilinearExtension<P>, Error> {
168 either::for_both!(self, inner => inner.evaluate_partial(query, start_index))
169 }
170
171 fn evaluate_partial_low(
172 &self,
173 query: MultilinearQueryRef<P>,
174 ) -> Result<MultilinearExtension<P>, Error> {
175 either::for_both!(self, inner => inner.evaluate_partial_low(query))
176 }
177
178 fn evaluate_partial_high(
179 &self,
180 query: MultilinearQueryRef<P>,
181 ) -> Result<MultilinearExtension<P>, Error> {
182 either::for_both!(self, inner => inner.evaluate_partial_high(query))
183 }
184
185 fn subcube_partial_low_evals(
186 &self,
187 query: MultilinearQueryRef<P>,
188 subcube_vars: usize,
189 subcube_index: usize,
190 partial_low_evals: &mut [P],
191 ) -> Result<(), Error> {
192 either::for_both!(
193 self,
194 inner => {
195 inner.subcube_partial_low_evals(query, subcube_vars, subcube_index, partial_low_evals)
196 }
197 )
198 }
199
200 fn subcube_partial_high_evals(
201 &self,
202 query: MultilinearQueryRef<P>,
203 subcube_vars: usize,
204 subcube_index: usize,
205 partial_high_evals: &mut [P],
206 ) -> Result<(), Error> {
207 either::for_both!(
208 self,
209 inner => {
210 inner.subcube_partial_high_evals(query, subcube_vars, subcube_index, partial_high_evals)
211 }
212 )
213 }
214
215 fn subcube_evals(
216 &self,
217 subcube_vars: usize,
218 subcube_index: usize,
219 log_embedding_degree: usize,
220 evals: &mut [P],
221 ) -> Result<(), Error> {
222 either::for_both!(
223 self,
224 inner => inner.subcube_evals(subcube_vars, subcube_index, log_embedding_degree, evals)
225 )
226 }
227
228 fn packed_evals(&self) -> Option<&[P]> {
229 either::for_both!(self, inner => inner.packed_evals())
230 }
231}