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;
26
27 fn evaluate_on_hypercube(&self, index: usize) -> Result<P::Scalar, Error>;
33
34 fn evaluate_on_hypercube_and_scale(
44 &self,
45 index: usize,
46 scalar: P::Scalar,
47 ) -> Result<P::Scalar, Error>;
48
49 fn evaluate(&self, query: MultilinearQueryRef<P>) -> Result<P::Scalar, Error>;
50
51 fn evaluate_partial_low(
52 &self,
53 query: MultilinearQueryRef<P>,
54 ) -> Result<MultilinearExtension<P>, Error>;
55
56 fn evaluate_partial_high(
57 &self,
58 query: MultilinearQueryRef<P>,
59 ) -> Result<MultilinearExtension<P>, Error>;
60
61 fn evaluate_partial(
62 &self,
63 query: MultilinearQueryRef<P>,
64 start_index: usize,
65 ) -> Result<MultilinearExtension<P>, Error>;
66
67 fn zero_pad(
68 &self,
69 n_pad_vars: usize,
70 start_index: usize,
71 nonzero_index: usize,
72 ) -> Result<MultilinearExtension<P>, Error>;
73
74 fn subcube_partial_low_evals(
79 &self,
80 query: MultilinearQueryRef<P>,
81 subcube_vars: usize,
82 subcube_index: usize,
83 partial_low_evals: &mut [P],
84 ) -> Result<(), Error>;
85
86 fn subcube_partial_high_evals(
91 &self,
92 query: MultilinearQueryRef<P>,
93 subcube_vars: usize,
94 subcube_index: usize,
95 partial_high_evals: &mut [P],
96 ) -> Result<(), Error>;
97
98 fn subcube_evals(
111 &self,
112 subcube_vars: usize,
113 subcube_index: usize,
114 log_embedding_degree: usize,
115 evals: &mut [P],
116 ) -> Result<(), Error>;
117
118 fn packed_evals(&self) -> Option<&[P]>;
135}
136
137impl<P, L, R> MultilinearPoly<P> for Either<L, R>
138where
139 P: PackedField,
140 L: MultilinearPoly<P>,
141 R: MultilinearPoly<P>,
142{
143 fn n_vars(&self) -> usize {
144 either::for_both!(self, inner => inner.n_vars())
145 }
146
147 fn size(&self) -> usize {
148 either::for_both!(self, inner => inner.size())
149 }
150
151 fn log_extension_degree(&self) -> usize {
152 either::for_both!(self, inner => inner.log_extension_degree())
153 }
154
155 fn evaluate_on_hypercube(&self, index: usize) -> Result<P::Scalar, Error> {
156 either::for_both!(self, inner => inner.evaluate_on_hypercube(index))
157 }
158
159 fn evaluate_on_hypercube_and_scale(
160 &self,
161 index: usize,
162 scalar: P::Scalar,
163 ) -> Result<P::Scalar, Error> {
164 either::for_both!(self, inner => inner.evaluate_on_hypercube_and_scale(index, scalar))
165 }
166
167 fn evaluate(&self, query: MultilinearQueryRef<P>) -> Result<P::Scalar, Error> {
168 either::for_both!(self, inner => inner.evaluate(query))
169 }
170
171 fn evaluate_partial(
172 &self,
173 query: MultilinearQueryRef<P>,
174 start_index: usize,
175 ) -> Result<MultilinearExtension<P>, Error> {
176 either::for_both!(self, inner => inner.evaluate_partial(query, start_index))
177 }
178
179 fn evaluate_partial_low(
180 &self,
181 query: MultilinearQueryRef<P>,
182 ) -> Result<MultilinearExtension<P>, Error> {
183 either::for_both!(self, inner => inner.evaluate_partial_low(query))
184 }
185
186 fn evaluate_partial_high(
187 &self,
188 query: MultilinearQueryRef<P>,
189 ) -> Result<MultilinearExtension<P>, Error> {
190 either::for_both!(self, inner => inner.evaluate_partial_high(query))
191 }
192
193 fn zero_pad(
194 &self,
195 n_pad_vars: usize,
196 start_index: usize,
197 nonzero_index: usize,
198 ) -> Result<MultilinearExtension<P>, Error> {
199 either::for_both!(self, inner => inner.zero_pad(n_pad_vars, start_index, nonzero_index))
200 }
201
202 fn subcube_partial_low_evals(
203 &self,
204 query: MultilinearQueryRef<P>,
205 subcube_vars: usize,
206 subcube_index: usize,
207 partial_low_evals: &mut [P],
208 ) -> Result<(), Error> {
209 either::for_both!(
210 self,
211 inner => {
212 inner.subcube_partial_low_evals(query, subcube_vars, subcube_index, partial_low_evals)
213 }
214 )
215 }
216
217 fn subcube_partial_high_evals(
218 &self,
219 query: MultilinearQueryRef<P>,
220 subcube_vars: usize,
221 subcube_index: usize,
222 partial_high_evals: &mut [P],
223 ) -> Result<(), Error> {
224 either::for_both!(
225 self,
226 inner => {
227 inner.subcube_partial_high_evals(query, subcube_vars, subcube_index, partial_high_evals)
228 }
229 )
230 }
231
232 fn subcube_evals(
233 &self,
234 subcube_vars: usize,
235 subcube_index: usize,
236 log_embedding_degree: usize,
237 evals: &mut [P],
238 ) -> Result<(), Error> {
239 either::for_both!(
240 self,
241 inner => inner.subcube_evals(subcube_vars, subcube_index, log_embedding_degree, evals)
242 )
243 }
244
245 fn packed_evals(&self) -> Option<&[P]> {
246 either::for_both!(self, inner => inner.packed_evals())
247 }
248}