binius_field/
extension.rs1use std::{
4 iter,
5 ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
6};
7
8use super::{error::Error, Field};
9
10pub trait ExtensionField<F: Field>:
11 Field
12 + From<F>
13 + TryInto<F>
14 + Add<F, Output = Self>
15 + Sub<F, Output = Self>
16 + Mul<F, Output = Self>
17 + AddAssign<F>
18 + SubAssign<F>
19 + MulAssign<F>
20{
21 const LOG_DEGREE: usize;
23
24 const DEGREE: usize = 1 << Self::LOG_DEGREE;
28
29 fn basis(i: usize) -> Result<Self, Error>;
31
32 fn from_bases(base_elems: &[F]) -> Result<Self, Error> {
36 Self::from_bases_sparse(base_elems, 0)
37 }
38
39 fn from_bases_sparse(base_elems: &[F], log_stride: usize) -> Result<Self, Error>;
45
46 fn iter_bases(&self) -> impl Iterator<Item = F>;
48
49 fn into_iter_bases(self) -> impl Iterator<Item = F>;
51
52 #[inline]
54 fn get_base(&self, i: usize) -> F {
55 assert!(i < Self::DEGREE, "index out of bounds");
56 unsafe { self.get_base_unchecked(i) }
57 }
58
59 unsafe fn get_base_unchecked(&self, i: usize) -> F;
64}
65
66impl<F: Field> ExtensionField<F> for F {
67 const LOG_DEGREE: usize = 0;
68
69 #[inline(always)]
70 fn basis(i: usize) -> Result<Self, Error> {
71 if i != 0 {
72 return Err(Error::ExtensionDegreeMismatch);
73 }
74 Ok(Self::ONE)
75 }
76
77 #[inline(always)]
78 fn from_bases_sparse(base_elems: &[F], log_stride: usize) -> Result<Self, Error> {
79 if log_stride != 0 {
80 return Err(Error::ExtensionDegreeMismatch);
81 }
82
83 match base_elems.len() {
84 0 => Ok(F::ZERO),
85 1 => Ok(base_elems[0]),
86 _ => Err(Error::ExtensionDegreeMismatch),
87 }
88 }
89
90 #[inline(always)]
91 fn iter_bases(&self) -> impl Iterator<Item = F> {
92 iter::once(*self)
93 }
94
95 #[inline(always)]
96 fn into_iter_bases(self) -> impl Iterator<Item = F> {
97 iter::once(self)
98 }
99
100 #[inline(always)]
101 unsafe fn get_base_unchecked(&self, i: usize) -> F {
102 debug_assert_eq!(i, 0);
103 *self
104 }
105}