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