1use crate::{
2 ConstCoeffBitWidth, EvaluatablePolynomial, EvaluationError, Polynomial,
3 univariate::{binary_ref::BinaryRefPoly, binary_u64::BinaryU64Poly},
4};
5
6use core::slice;
7use crypto_primitives::{
8 FixedSemiring, FromWithConfig, IntoWithConfig, PrimeField, Ring, Semiring, boolean::Boolean,
9};
10use itertools::Itertools;
11use num_traits::{CheckedAdd, CheckedMul, CheckedNeg, CheckedSub, ConstOne, ConstZero, One, Zero};
12use rand::{distr::StandardUniform, prelude::*};
13use std::{
14 array,
15 fmt::Display,
16 hash::Hash,
17 iter::{Product, Sum},
18 marker::PhantomData,
19 ops::{Add, AddAssign, Deref, DerefMut, Mul, MulAssign, Neg, Sub, SubAssign},
20};
21use zinc_transcript::traits::{ConstTranscribable, GenTranscribable};
22use zinc_utils::{
23 from_ref::FromRef,
24 inner_product::{InnerProduct, InnerProductError},
25 mul_by_scalar::MulByScalar,
26 named::Named,
27 projectable_to_field::ProjectableToField,
28};
29
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct DensePolynomial<R, const DEGREE_PLUS_ONE: usize> {
32 pub coeffs: [R; DEGREE_PLUS_ONE],
34}
35
36impl<R: Semiring + Zero, const DEGREE_PLUS_ONE: usize> DensePolynomial<R, DEGREE_PLUS_ONE> {
37 #[allow(clippy::arithmetic_side_effects)]
42 pub fn new(coeffs: impl AsRef<[R]>) -> Self {
43 let coeffs = coeffs.as_ref();
44 assert!(
45 coeffs.len() <= DEGREE_PLUS_ONE,
46 "Too many coefficients provided: expected at most {}, got {}",
47 DEGREE_PLUS_ONE,
48 coeffs.len()
49 );
50
51 if coeffs.is_empty() {
52 return Self::zero();
53 }
54
55 let mut coeffs = coeffs.to_vec();
56 coeffs.resize(DEGREE_PLUS_ONE, R::zero());
57 let coeffs = coeffs.try_into().expect("unreachable");
58
59 DensePolynomial { coeffs }
60 }
61}
62
63impl<R: Semiring, const DEGREE_PLUS_ONE: usize> DensePolynomial<R, DEGREE_PLUS_ONE> {
64 #[allow(clippy::arithmetic_side_effects)]
69 pub fn new_with_zero(coeffs: impl AsRef<[R]>, zero: R) -> Self {
70 let coeffs = coeffs.as_ref();
71 assert!(
72 coeffs.len() <= DEGREE_PLUS_ONE,
73 "Too many coefficients provided: expected at most {}, got {}",
74 DEGREE_PLUS_ONE,
75 coeffs.len()
76 );
77
78 let mut coeffs = coeffs.to_vec();
79 coeffs.resize(DEGREE_PLUS_ONE, zero);
80 let coeffs = coeffs.try_into().expect("unreachable");
81
82 DensePolynomial { coeffs }
83 }
84}
85
86impl<R: Copy, const DEGREE_PLUS_ONE: usize> Copy for DensePolynomial<R, DEGREE_PLUS_ONE> {}
87
88impl<R: Default, const DEGREE_PLUS_ONE: usize> Default for DensePolynomial<R, DEGREE_PLUS_ONE> {
89 fn default() -> Self {
90 DensePolynomial {
91 coeffs: array::from_fn::<_, DEGREE_PLUS_ONE, _>(|_| R::default()),
92 }
93 }
94}
95
96impl<R: Display, const DEGREE_PLUS_ONE: usize> Display for DensePolynomial<R, DEGREE_PLUS_ONE> {
97 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98 write!(f, "[")?;
99 let mut first = true;
100 for coeff in self.coeffs.iter() {
101 if first {
102 first = false;
103 } else {
104 write!(f, ", ")?;
105 }
106 write!(f, "{}", coeff)?;
107 }
108 write!(f, "]")?;
109 Ok(())
110 }
111}
112
113impl<R: Hash, const DEGREE_PLUS_ONE: usize> Hash for DensePolynomial<R, DEGREE_PLUS_ONE> {
114 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
115 for coeff in self.coeffs.iter() {
116 coeff.hash(state);
117 }
118 }
119}
120
121impl<R: Semiring + Zero, const DEGREE_PLUS_ONE: usize> Zero
122 for DensePolynomial<R, DEGREE_PLUS_ONE>
123{
124 fn zero() -> Self {
125 Self {
126 coeffs: array::from_fn::<_, DEGREE_PLUS_ONE, _>(|_| R::zero()),
127 }
128 }
129
130 fn is_zero(&self) -> bool {
131 self.coeffs.iter().all(|c| c.is_zero())
132 }
133}
134
135impl<F: PrimeField, const DEGREE_PLUS_ONE: usize> DensePolynomial<F, DEGREE_PLUS_ONE> {
136 pub fn zero_with_cfg(cfg: &F::Config) -> Self {
137 let zero = F::zero_with_cfg(cfg);
138 Self {
139 coeffs: array::from_fn(|_| zero.clone()),
140 }
141 }
142
143 pub fn one_with_cfg(cfg: &F::Config) -> Self {
144 Self::new_with_zero([F::one_with_cfg(cfg)], F::zero_with_cfg(cfg))
145 }
146}
147
148impl<R: Semiring + Zero + One, const DEGREE_PLUS_ONE: usize> One
149 for DensePolynomial<R, DEGREE_PLUS_ONE>
150{
151 fn one() -> Self {
152 Self::from(R::one())
153 }
154}
155
156impl<R: Ring + Neg<Output = R>, const DEGREE_PLUS_ONE: usize> Neg
157 for DensePolynomial<R, DEGREE_PLUS_ONE>
158{
159 type Output = Self;
160
161 #[allow(clippy::arithmetic_side_effects)] fn neg(mut self) -> Self::Output {
163 self.coeffs.iter_mut().for_each(|c| *c = -c.clone());
164 self
165 }
166}
167
168impl<R: Semiring, const DEGREE_PLUS_ONE: usize> Add for DensePolynomial<R, DEGREE_PLUS_ONE> {
169 type Output = Self;
170
171 #[allow(clippy::arithmetic_side_effects, clippy::op_ref)]
172 #[inline(always)]
173 fn add(self, rhs: Self) -> Self::Output {
174 self + &rhs
175 }
176}
177
178impl<'a, R: Semiring, const DEGREE_PLUS_ONE: usize> Add<&'a Self>
179 for DensePolynomial<R, DEGREE_PLUS_ONE>
180{
181 type Output = Self;
182
183 #[allow(clippy::arithmetic_side_effects)]
184 #[inline(always)]
185 fn add(mut self, rhs: &'a Self) -> Self::Output {
186 self += rhs;
187 self
188 }
189}
190
191impl<R: Semiring, const DEGREE_PLUS_ONE: usize> Sub for DensePolynomial<R, DEGREE_PLUS_ONE> {
192 type Output = Self;
193
194 #[allow(clippy::arithmetic_side_effects, clippy::op_ref)]
195 #[inline(always)]
196 fn sub(self, rhs: Self) -> Self::Output {
197 self - &rhs
198 }
199}
200
201impl<'a, R: Semiring, const DEGREE_PLUS_ONE: usize> Sub<&'a Self>
202 for DensePolynomial<R, DEGREE_PLUS_ONE>
203{
204 type Output = Self;
205
206 #[allow(clippy::arithmetic_side_effects)]
207 #[inline(always)]
208 fn sub(mut self, rhs: &'a Self) -> Self::Output {
209 self -= rhs;
210 self
211 }
212}
213
214impl<R: Semiring, const DEGREE_PLUS_ONE: usize> Mul for DensePolynomial<R, DEGREE_PLUS_ONE> {
215 type Output = Self;
216
217 #[allow(clippy::arithmetic_side_effects, clippy::op_ref)]
218 #[inline(always)]
219 fn mul(self, rhs: Self) -> Self::Output {
220 self * &rhs
221 }
222}
223
224impl<'a, R: Semiring, const DEGREE_PLUS_ONE: usize> Mul<&'a Self>
225 for DensePolynomial<R, DEGREE_PLUS_ONE>
226{
227 type Output = Self;
228
229 fn mul(self, _rhs: &'a Self) -> Self::Output {
230 unimplemented!("Polynomial multiplication is not implemented")
231 }
232}
233
234impl<R: Semiring, const DEGREE_PLUS_ONE: usize> AddAssign for DensePolynomial<R, DEGREE_PLUS_ONE> {
235 #[allow(clippy::arithmetic_side_effects)]
236 #[inline(always)]
237 fn add_assign(&mut self, rhs: Self) {
238 *self += &rhs;
239 }
240}
241
242impl<'a, R: Semiring, const DEGREE_PLUS_ONE: usize> AddAssign<&'a Self>
243 for DensePolynomial<R, DEGREE_PLUS_ONE>
244{
245 #[allow(clippy::arithmetic_side_effects)]
246 #[inline(always)]
247 fn add_assign(&mut self, rhs: &'a Self) {
248 for i in 0..DEGREE_PLUS_ONE {
249 self.coeffs[i] += &rhs.coeffs[i];
250 }
251 }
252}
253
254impl<R: Semiring, const DEGREE_PLUS_ONE: usize> SubAssign for DensePolynomial<R, DEGREE_PLUS_ONE> {
255 #[allow(clippy::arithmetic_side_effects)]
256 #[inline(always)]
257 fn sub_assign(&mut self, rhs: Self) {
258 *self -= &rhs;
259 }
260}
261
262impl<'a, R: Semiring, const DEGREE_PLUS_ONE: usize> SubAssign<&'a Self>
263 for DensePolynomial<R, DEGREE_PLUS_ONE>
264{
265 #[allow(clippy::arithmetic_side_effects)]
266 #[inline(always)]
267 fn sub_assign(&mut self, rhs: &'a Self) {
268 for i in 0..DEGREE_PLUS_ONE {
269 self.coeffs[i] -= &rhs.coeffs[i];
270 }
271 }
272}
273
274impl<R: Semiring, const DEGREE_PLUS_ONE: usize> MulAssign for DensePolynomial<R, DEGREE_PLUS_ONE> {
275 #[allow(clippy::arithmetic_side_effects)]
276 #[inline(always)]
277 fn mul_assign(&mut self, rhs: Self) {
278 *self *= &rhs;
279 }
280}
281
282impl<'a, R: Semiring, const DEGREE_PLUS_ONE: usize> MulAssign<&'a Self>
283 for DensePolynomial<R, DEGREE_PLUS_ONE>
284{
285 fn mul_assign(&mut self, _rhs: &'a Self) {
286 unimplemented!("Polynomial multiplication is not implemented")
287 }
288}
289
290impl<R: Ring + Zero, const DEGREE_PLUS_ONE: usize> CheckedNeg
291 for DensePolynomial<R, DEGREE_PLUS_ONE>
292{
293 fn checked_neg(&self) -> Option<Self> {
294 let mut coeffs = self.coeffs.clone();
295
296 coeffs
297 .iter_mut()
298 .filter(|coeff| !coeff.is_zero())
299 .try_for_each(|x| {
300 *x = x.checked_neg()?;
301 Some(())
302 })?;
303
304 Some(Self { coeffs })
305 }
306}
307
308impl<R: Semiring, const DEGREE_PLUS_ONE: usize> CheckedAdd for DensePolynomial<R, DEGREE_PLUS_ONE> {
309 fn checked_add(&self, other: &Self) -> Option<Self> {
310 let mut coeffs = self.coeffs.clone();
311
312 coeffs.iter_mut().zip(other).try_for_each(|(a, b)| {
313 *a = a.checked_add(b)?;
314 Some(())
315 })?;
316
317 Some(Self { coeffs })
318 }
319}
320
321impl<R: Semiring, const DEGREE_PLUS_ONE: usize> CheckedSub for DensePolynomial<R, DEGREE_PLUS_ONE> {
322 fn checked_sub(&self, other: &Self) -> Option<Self> {
323 let mut coeffs = self.coeffs.clone();
324
325 coeffs.iter_mut().zip(other).try_for_each(|(a, b)| {
326 *a = a.checked_sub(b)?;
327 Some(())
328 })?;
329
330 Some(Self { coeffs })
331 }
332}
333
334impl<R: Semiring, const DEGREE_PLUS_ONE: usize> CheckedMul for DensePolynomial<R, DEGREE_PLUS_ONE> {
335 fn checked_mul(&self, _other: &Self) -> Option<Self> {
336 unimplemented!("Polynomial multiplication is not implemented")
337 }
338}
339
340impl<R: FixedSemiring, const DEGREE_PLUS_ONE: usize> Sum for DensePolynomial<R, DEGREE_PLUS_ONE> {
341 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
342 iter.fold(Self::zero(), |acc, x| {
343 acc.checked_add(&x).expect("overflow in sum")
344 })
345 }
346}
347
348impl<'a, R: FixedSemiring, const DEGREE_PLUS_ONE: usize> Sum<&'a Self>
349 for DensePolynomial<R, DEGREE_PLUS_ONE>
350{
351 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
352 iter.fold(Self::zero(), |acc, x| {
353 acc.checked_add(x).expect("overflow in sum")
354 })
355 }
356}
357
358impl<R: FixedSemiring, const DEGREE_PLUS_ONE: usize> Product
359 for DensePolynomial<R, DEGREE_PLUS_ONE>
360{
361 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
362 iter.fold(Self::one(), |acc, x| {
363 acc.checked_mul(&x).expect("overflow in product")
364 })
365 }
366}
367
368impl<'a, R: FixedSemiring, const DEGREE_PLUS_ONE: usize> Product<&'a Self>
369 for DensePolynomial<R, DEGREE_PLUS_ONE>
370{
371 fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
372 iter.fold(Self::one(), |acc, x| {
373 acc.checked_mul(x).expect("overflow in product")
374 })
375 }
376}
377
378impl<R: Semiring, const DEGREE_PLUS_ONE: usize> Semiring for DensePolynomial<R, DEGREE_PLUS_ONE> {}
379
380impl<R: Ring + FixedSemiring, const DEGREE_PLUS_ONE: usize> Ring
381 for DensePolynomial<R, DEGREE_PLUS_ONE>
382{
383}
384
385impl<R, const DEGREE_PLUS_ONE: usize> Distribution<DensePolynomial<R, DEGREE_PLUS_ONE>>
386 for StandardUniform
387where
388 StandardUniform: Distribution<R>,
389 StandardUniform: Distribution<[R; DEGREE_PLUS_ONE]>, {
391 fn sample<Gen: Rng + ?Sized>(&self, rng: &mut Gen) -> DensePolynomial<R, DEGREE_PLUS_ONE> {
392 let coeffs: [R; DEGREE_PLUS_ONE] = rng.random();
393 DensePolynomial { coeffs }
394 }
395}
396
397impl<R: Semiring, const DEGREE_PLUS_ONE: usize> Polynomial<R>
401 for DensePolynomial<R, DEGREE_PLUS_ONE>
402{
403 const DEGREE_BOUND: usize = DEGREE_PLUS_ONE - 1;
404}
405
406impl<R: Semiring, const DEGREE_PLUS_ONE: usize> EvaluatablePolynomial<R, R>
407 for DensePolynomial<R, DEGREE_PLUS_ONE>
408{
409 type EvaluationPoint = R;
410
411 fn evaluate_at_point(&self, point: &R) -> Result<R, EvaluationError> {
412 let mut result = self
414 .coeffs
415 .last()
416 .ok_or(EvaluationError::EmptyPolynomial)?
417 .clone();
418
419 for coeff in self.coeffs.iter().rev().skip(1) {
420 let term = result.checked_mul(point).ok_or(EvaluationError::Overflow)?;
421 result = term.checked_add(coeff).ok_or(EvaluationError::Overflow)?;
422 }
423
424 Ok(result)
425 }
426}
427
428impl<R: Semiring + ConstTranscribable, const DEGREE_PLUS_ONE: usize> ConstCoeffBitWidth
429 for DensePolynomial<R, DEGREE_PLUS_ONE>
430{
431 const COEFF_BIT_WIDTH: usize = R::NUM_BITS;
432}
433
434impl<R: Semiring + Named, const DEGREE_PLUS_ONE: usize> Named
435 for DensePolynomial<R, DEGREE_PLUS_ONE>
436{
437 fn type_name() -> String {
438 format!("Poly<{}, {}>", R::type_name(), Self::DEGREE_BOUND)
439 }
440}
441
442impl<R: ConstTranscribable + Default, const DEGREE_PLUS_ONE: usize> GenTranscribable
443 for DensePolynomial<R, DEGREE_PLUS_ONE>
444{
445 #[allow(clippy::arithmetic_side_effects)]
446 fn read_transcription_bytes_exact(bytes: &[u8]) -> Self {
447 assert_eq!(
448 bytes.len(),
449 R::NUM_BYTES * DEGREE_PLUS_ONE,
450 "Invalid byte length for DensePolynomial: expected {}, got {}",
451 R::NUM_BYTES * DEGREE_PLUS_ONE,
452 bytes.len()
453 );
454
455 let coeffs = bytes
458 .chunks_exact(R::NUM_BYTES)
459 .map(R::read_transcription_bytes_exact)
460 .collect_array()
461 .expect("Unreachable");
462 Self { coeffs }
463 }
464
465 fn write_transcription_bytes_exact(&self, buf: &mut [u8]) {
466 for (chunk, coeff) in buf.chunks_exact_mut(R::NUM_BYTES).zip(self.coeffs.iter()) {
467 coeff.write_transcription_bytes_exact(chunk);
468 }
469 }
470}
471
472impl<R: ConstTranscribable + Default, const DEGREE_PLUS_ONE: usize> ConstTranscribable
473 for DensePolynomial<R, DEGREE_PLUS_ONE>
474{
475 const NUM_BYTES: usize = R::NUM_BYTES * DEGREE_PLUS_ONE;
476}
477
478impl<R, S, const DEGREE_PLUS_ONE: usize> FromRef<DensePolynomial<S, DEGREE_PLUS_ONE>>
481 for DensePolynomial<R, DEGREE_PLUS_ONE>
482where
483 R: Semiring + FromRef<S> + Default,
484{
485 fn from_ref(value: &DensePolynomial<S, DEGREE_PLUS_ONE>) -> Self {
486 let mut coeffs = array::from_fn::<_, DEGREE_PLUS_ONE, _>(|_| R::default());
487 coeffs
488 .iter_mut()
489 .zip(value.coeffs.iter())
490 .for_each(|(coeff, other_coeff)| {
491 *coeff = R::from_ref(other_coeff);
492 });
493 DensePolynomial { coeffs }
494 }
495}
496
497impl<R, const DEGREE_PLUS_ONE: usize> FromRef<BinaryRefPoly<DEGREE_PLUS_ONE>>
498 for DensePolynomial<R, DEGREE_PLUS_ONE>
499where
500 R: Semiring + FromRef<Boolean> + Default,
501{
502 #[inline(always)]
503 fn from_ref(value: &BinaryRefPoly<DEGREE_PLUS_ONE>) -> Self {
504 Self::from_ref(value.inner())
505 }
506}
507
508impl<R, const DEGREE_PLUS_ONE: usize> FromRef<BinaryU64Poly<DEGREE_PLUS_ONE>>
509 for DensePolynomial<R, DEGREE_PLUS_ONE>
510where
511 R: Semiring + FromRef<Boolean> + Default,
512{
513 #[inline(always)]
514 fn from_ref(value: &BinaryU64Poly<DEGREE_PLUS_ONE>) -> Self {
515 let mut coeffs = array::from_fn::<_, DEGREE_PLUS_ONE, _>(|_| R::default());
516 coeffs.iter_mut().enumerate().for_each(|(i, coeff)| {
517 if value.inner() & (1 << i) != 0 {
518 *coeff = R::from_ref(&Boolean::ONE);
519 } else {
520 *coeff = R::from_ref(&Boolean::ZERO);
521 }
522 });
523 DensePolynomial { coeffs }
524 }
525}
526
527impl<R, S, const DEGREE_PLUS_ONE: usize> From<&DensePolynomial<S, DEGREE_PLUS_ONE>>
528 for DensePolynomial<R, DEGREE_PLUS_ONE>
529where
530 R: Semiring + FromRef<S> + Default,
531{
532 fn from(value: &DensePolynomial<S, DEGREE_PLUS_ONE>) -> Self {
533 Self::from_ref(value)
534 }
535}
536
537impl<R: Zero, const DEGREE_PLUS_ONE: usize> From<R> for DensePolynomial<R, DEGREE_PLUS_ONE> {
538 fn from(value: R) -> Self {
539 let mut coeffs = array::from_fn(|_| R::zero());
540 coeffs[0] = value;
541 Self { coeffs }
542 }
543}
544
545impl<const DEGREE_PLUS_ONE: usize> FromRef<i64> for DensePolynomial<i128, DEGREE_PLUS_ONE> {
546 fn from_ref(value: &i64) -> Self {
547 Self::from(i128::from(*value))
548 }
549}
550
551impl<'a, R, S, Out, const DEGREE_PLUS_ONE: usize>
552 MulByScalar<&'a S, DensePolynomial<Out, DEGREE_PLUS_ONE>>
553 for DensePolynomial<R, DEGREE_PLUS_ONE>
554where
555 R: FixedSemiring + MulByScalar<&'a S, Out>,
556 Out: FixedSemiring + Copy,
557{
558 fn mul_by_scalar<const CHECK: bool>(
559 &self,
560 rhs: &'a S,
561 ) -> Option<DensePolynomial<Out, DEGREE_PLUS_ONE>> {
562 let mut coeffs = [Out::default(); DEGREE_PLUS_ONE];
563
564 coeffs
565 .iter_mut()
566 .zip(self.coeffs.iter())
567 .filter(|(_, coeff)| !coeff.is_zero())
568 .try_for_each(|(out, x)| {
569 *out = x.mul_by_scalar::<CHECK>(rhs)?;
570 Some(())
571 })?;
572
573 Some(DensePolynomial { coeffs })
574 }
575}
576
577impl<R, F, const DEGREE_PLUS_ONE: usize> ProjectableToField<F>
578 for DensePolynomial<R, DEGREE_PLUS_ONE>
579where
580 R: Semiring,
581 F: PrimeField + for<'a> FromWithConfig<&'a R> + for<'a> MulByScalar<&'a F> + 'static,
582{
583 #![allow(clippy::arithmetic_side_effects)] fn prepare_projection(
585 sampled_value: &F,
586 ) -> impl Fn(&DensePolynomial<R, DEGREE_PLUS_ONE>) -> F + Send + Sync + 'static {
587 let sampled_value = sampled_value.clone();
588 let field_cfg = sampled_value.cfg().clone();
589
590 move |poly: &DensePolynomial<R, DEGREE_PLUS_ONE>| {
591 let coeffs: [F; DEGREE_PLUS_ONE] = poly
592 .coeffs
593 .iter()
594 .map(|v| v.into_with_cfg(&field_cfg))
595 .collect_array()
596 .expect("unreachable");
597
598 let poly2 = DensePolynomial { coeffs };
599 poly2
600 .evaluate_at_point(&sampled_value)
601 .expect("Failed to evaluate polynomial at point")
602 }
603 }
604}
605
606impl<R, const DEGREE_PLUS_ONE: usize> DensePolynomial<R, DEGREE_PLUS_ONE> {
607 #[inline(always)]
608 pub fn iter(&self) -> std::slice::Iter<'_, R> {
609 self.coeffs.iter()
610 }
611
612 #[inline(always)]
613 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, R> {
614 self.coeffs.iter_mut()
615 }
616}
617
618impl<R, const DEGREE_PLUS_ONE: usize> IntoIterator for DensePolynomial<R, DEGREE_PLUS_ONE> {
619 type Item = R;
620
621 type IntoIter = std::array::IntoIter<R, DEGREE_PLUS_ONE>;
622
623 #[inline(always)]
624 fn into_iter(self) -> Self::IntoIter {
625 self.coeffs.into_iter()
626 }
627}
628
629impl<'a, R, const DEGREE_PLUS_ONE: usize> IntoIterator for &'a DensePolynomial<R, DEGREE_PLUS_ONE> {
630 type Item = &'a R;
631
632 type IntoIter = slice::Iter<'a, R>;
633
634 fn into_iter(self) -> Self::IntoIter {
635 self.coeffs.iter()
636 }
637}
638
639impl<R, const DEGREE_PLUS_ONE: usize> AsRef<[R]> for DensePolynomial<R, DEGREE_PLUS_ONE> {
640 fn as_ref(&self) -> &[R] {
641 self.coeffs.as_slice()
642 }
643}
644
645impl<R, const DEGREE_PLUS_ONE: usize> Deref for DensePolynomial<R, DEGREE_PLUS_ONE> {
646 type Target = [R];
647
648 fn deref(&self) -> &Self::Target {
649 self.coeffs.as_slice()
650 }
651}
652
653impl<R, const DEGREE_PLUS_ONE: usize> DerefMut for DensePolynomial<R, DEGREE_PLUS_ONE> {
654 fn deref_mut(&mut self) -> &mut Self::Target {
655 &mut self.coeffs
656 }
657}
658
659#[derive(Clone, Debug)]
660pub struct DensePolyInnerProduct<
661 R,
662 Rhs,
663 Out,
664 I: InnerProduct<[R], Rhs, Out>,
665 const DEGREE_PLUS_ONE: usize,
666>(PhantomData<(I, R, Rhs, Out)>);
667
668impl<R, Rhs, Out, I, const DEGREE_PLUS_ONE: usize>
669 InnerProduct<DensePolynomial<R, DEGREE_PLUS_ONE>, Rhs, Out>
670 for DensePolyInnerProduct<R, Rhs, Out, I, DEGREE_PLUS_ONE>
671where
672 I: InnerProduct<[R], Rhs, Out>,
673{
674 #[inline(always)]
675 fn inner_product<const CHECK: bool>(
676 lhs: &DensePolynomial<R, DEGREE_PLUS_ONE>,
677 rhs: &[Rhs],
678 zero: Out,
679 ) -> Result<Out, InnerProductError> {
680 I::inner_product::<CHECK>(&lhs.coeffs, rhs, zero)
681 }
682}