p3_field/
array.rs

1use core::array;
2use core::iter::{Product, Sum};
3use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5use crate::{AbstractField, Field};
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct FieldArray<F: Field, const N: usize>(pub [F; N]);
9
10impl<F: Field, const N: usize> Default for FieldArray<F, N> {
11    fn default() -> Self {
12        Self::zero()
13    }
14}
15
16impl<F: Field, const N: usize> From<F> for FieldArray<F, N> {
17    fn from(val: F) -> Self {
18        [val; N].into()
19    }
20}
21
22impl<F: Field, const N: usize> From<[F; N]> for FieldArray<F, N> {
23    fn from(arr: [F; N]) -> Self {
24        Self(arr)
25    }
26}
27
28impl<F: Field, const N: usize> AbstractField for FieldArray<F, N> {
29    type F = F;
30
31    fn zero() -> Self {
32        FieldArray([F::zero(); N])
33    }
34    fn one() -> Self {
35        FieldArray([F::one(); N])
36    }
37    fn two() -> Self {
38        FieldArray([F::two(); N])
39    }
40    fn neg_one() -> Self {
41        FieldArray([F::neg_one(); N])
42    }
43
44    #[inline]
45    fn from_f(f: Self::F) -> Self {
46        f.into()
47    }
48
49    fn from_bool(b: bool) -> Self {
50        [F::from_bool(b); N].into()
51    }
52
53    fn from_canonical_u8(n: u8) -> Self {
54        [F::from_canonical_u8(n); N].into()
55    }
56
57    fn from_canonical_u16(n: u16) -> Self {
58        [F::from_canonical_u16(n); N].into()
59    }
60
61    fn from_canonical_u32(n: u32) -> Self {
62        [F::from_canonical_u32(n); N].into()
63    }
64
65    fn from_canonical_u64(n: u64) -> Self {
66        [F::from_canonical_u64(n); N].into()
67    }
68
69    fn from_canonical_usize(n: usize) -> Self {
70        [F::from_canonical_usize(n); N].into()
71    }
72
73    fn from_wrapped_u32(n: u32) -> Self {
74        [F::from_wrapped_u32(n); N].into()
75    }
76
77    fn from_wrapped_u64(n: u64) -> Self {
78        [F::from_wrapped_u64(n); N].into()
79    }
80
81    fn generator() -> Self {
82        [F::generator(); N].into()
83    }
84}
85
86impl<F: Field, const N: usize> Add for FieldArray<F, N> {
87    type Output = Self;
88
89    #[inline]
90    fn add(self, rhs: Self) -> Self::Output {
91        array::from_fn(|i| self.0[i] + rhs.0[i]).into()
92    }
93}
94
95impl<F: Field, const N: usize> Add<F> for FieldArray<F, N> {
96    type Output = Self;
97
98    #[inline]
99    fn add(self, rhs: F) -> Self::Output {
100        self.0.map(|x| x + rhs).into()
101    }
102}
103
104impl<F: Field, const N: usize> AddAssign for FieldArray<F, N> {
105    #[inline]
106    fn add_assign(&mut self, rhs: Self) {
107        self.0.iter_mut().zip(rhs.0).for_each(|(x, y)| *x += y);
108    }
109}
110
111impl<F: Field, const N: usize> AddAssign<F> for FieldArray<F, N> {
112    #[inline]
113    fn add_assign(&mut self, rhs: F) {
114        self.0.iter_mut().for_each(|x| *x += rhs);
115    }
116}
117
118impl<F: Field, const N: usize> Sub for FieldArray<F, N> {
119    type Output = Self;
120
121    #[inline]
122    fn sub(self, rhs: Self) -> Self::Output {
123        array::from_fn(|i| self.0[i] - rhs.0[i]).into()
124    }
125}
126
127impl<F: Field, const N: usize> Sub<F> for FieldArray<F, N> {
128    type Output = Self;
129
130    #[inline]
131    fn sub(self, rhs: F) -> Self::Output {
132        self.0.map(|x| x - rhs).into()
133    }
134}
135
136impl<F: Field, const N: usize> SubAssign for FieldArray<F, N> {
137    #[inline]
138    fn sub_assign(&mut self, rhs: Self) {
139        self.0.iter_mut().zip(rhs.0).for_each(|(x, y)| *x -= y);
140    }
141}
142
143impl<F: Field, const N: usize> SubAssign<F> for FieldArray<F, N> {
144    #[inline]
145    fn sub_assign(&mut self, rhs: F) {
146        self.0.iter_mut().for_each(|x| *x -= rhs);
147    }
148}
149
150impl<F: Field, const N: usize> Neg for FieldArray<F, N> {
151    type Output = Self;
152
153    #[inline]
154    fn neg(self) -> Self::Output {
155        self.0.map(|x| -x).into()
156    }
157}
158
159impl<F: Field, const N: usize> Mul for FieldArray<F, N> {
160    type Output = Self;
161
162    #[inline]
163    fn mul(self, rhs: Self) -> Self::Output {
164        array::from_fn(|i| self.0[i] * rhs.0[i]).into()
165    }
166}
167
168impl<F: Field, const N: usize> Mul<F> for FieldArray<F, N> {
169    type Output = Self;
170
171    #[inline]
172    fn mul(self, rhs: F) -> Self::Output {
173        self.0.map(|x| x * rhs).into()
174    }
175}
176
177impl<F: Field, const N: usize> MulAssign for FieldArray<F, N> {
178    #[inline]
179    fn mul_assign(&mut self, rhs: Self) {
180        self.0.iter_mut().zip(rhs.0).for_each(|(x, y)| *x *= y);
181    }
182}
183
184impl<F: Field, const N: usize> MulAssign<F> for FieldArray<F, N> {
185    #[inline]
186    fn mul_assign(&mut self, rhs: F) {
187        self.0.iter_mut().for_each(|x| *x *= rhs);
188    }
189}
190
191impl<F: Field, const N: usize> Sum for FieldArray<F, N> {
192    #[inline]
193    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
194        iter.reduce(|lhs, rhs| lhs + rhs).unwrap_or(Self::zero())
195    }
196}
197
198impl<F: Field, const N: usize> Product for FieldArray<F, N> {
199    #[inline]
200    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
201        iter.reduce(|lhs, rhs| lhs * rhs).unwrap_or(Self::one())
202    }
203}