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}