1use crate::field::element::FieldElement;
2use crate::field::errors::FieldError;
3use crate::field::traits::{IsField, IsSubFieldOf};
4use crate::traits::ByteConversion;
5use core::fmt::Debug;
6use core::marker::PhantomData;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct CubicExtensionField<F, T> {
12 field: PhantomData<F>,
13 non_residue: PhantomData<T>,
14}
15
16pub type CubicExtensionFieldElement<F, T> = FieldElement<CubicExtensionField<F, T>>;
17
18pub trait HasCubicNonResidue<F: IsField> {
22 fn residue() -> FieldElement<F>;
25}
26
27impl<F> ByteConversion for [FieldElement<F>; 3]
28where
29 F: IsField,
30{
31 #[cfg(feature = "alloc")]
32 fn to_bytes_be(&self) -> alloc::vec::Vec<u8> {
33 unimplemented!()
34 }
35
36 #[cfg(feature = "alloc")]
37 fn to_bytes_le(&self) -> alloc::vec::Vec<u8> {
38 unimplemented!()
39 }
40
41 fn from_bytes_be(_bytes: &[u8]) -> Result<Self, crate::errors::ByteConversionError>
42 where
43 Self: Sized,
44 {
45 unimplemented!()
46 }
47
48 fn from_bytes_le(_bytes: &[u8]) -> Result<Self, crate::errors::ByteConversionError>
49 where
50 Self: Sized,
51 {
52 unimplemented!()
53 }
54}
55
56impl<F, Q> IsField for CubicExtensionField<F, Q>
57where
58 F: IsField,
59 Q: Clone + Debug + HasCubicNonResidue<F>,
60{
61 type BaseType = [FieldElement<F>; 3];
62
63 fn add(a: &[FieldElement<F>; 3], b: &[FieldElement<F>; 3]) -> [FieldElement<F>; 3] {
65 [&a[0] + &b[0], &a[1] + &b[1], &a[2] + &b[2]]
66 }
67
68 fn mul(a: &[FieldElement<F>; 3], b: &[FieldElement<F>; 3]) -> [FieldElement<F>; 3] {
73 let v0 = &a[0] * &b[0];
74 let v1 = &a[1] * &b[1];
75 let v2 = &a[2] * &b[2];
76
77 [
78 &v0 + Q::residue() * ((&a[1] + &a[2]) * (&b[1] + &b[2]) - &v1 - &v2),
79 (&a[0] + &a[1]) * (&b[0] + &b[1]) - &v0 - &v1 + Q::residue() * &v2,
80 (&a[0] + &a[2]) * (&b[0] + &b[2]) - v0 + v1 - v2,
81 ]
82 }
83
84 fn sub(a: &[FieldElement<F>; 3], b: &[FieldElement<F>; 3]) -> [FieldElement<F>; 3] {
86 [&a[0] - &b[0], &a[1] - &b[1], &a[2] - &b[2]]
87 }
88
89 fn neg(a: &[FieldElement<F>; 3]) -> [FieldElement<F>; 3] {
91 [-&a[0], -&a[1], -&a[2]]
92 }
93
94 fn inv(a: &[FieldElement<F>; 3]) -> Result<[FieldElement<F>; 3], FieldError> {
96 let three = FieldElement::<F>::from(3_u64);
97 let d = a[0].pow(3_u64)
98 + a[1].pow(3_u64) * Q::residue()
99 + a[2].pow(3_u64) * Q::residue().pow(2_u64)
100 - three * &a[0] * &a[1] * &a[2] * Q::residue();
101 let inv = d.inv()?;
102 Ok([
103 (a[0].pow(2_u64) - &a[1] * &a[2] * Q::residue()) * &inv,
104 (-&a[0] * &a[1] + a[2].pow(2_u64) * Q::residue()) * &inv,
105 (-&a[0] * &a[2] + a[1].pow(2_u64)) * &inv,
106 ])
107 }
108
109 fn div(
111 a: &[FieldElement<F>; 3],
112 b: &[FieldElement<F>; 3],
113 ) -> Result<[FieldElement<F>; 3], FieldError> {
114 let b_inv = &Self::inv(b).map_err(|_| FieldError::DivisionByZero)?;
115 Ok(<Self as IsField>::mul(a, b_inv))
116 }
117
118 fn eq(a: &[FieldElement<F>; 3], b: &[FieldElement<F>; 3]) -> bool {
120 a[0] == b[0] && a[1] == b[1] && a[2] == b[2]
121 }
122
123 fn zero() -> [FieldElement<F>; 3] {
125 [
126 FieldElement::zero(),
127 FieldElement::zero(),
128 FieldElement::zero(),
129 ]
130 }
131
132 fn one() -> [FieldElement<F>; 3] {
134 [
135 FieldElement::one(),
136 FieldElement::zero(),
137 FieldElement::zero(),
138 ]
139 }
140
141 fn from_u64(x: u64) -> Self::BaseType {
143 [
144 FieldElement::from(x),
145 FieldElement::zero(),
146 FieldElement::zero(),
147 ]
148 }
149
150 fn from_base_type(x: [FieldElement<F>; 3]) -> [FieldElement<F>; 3] {
155 x
156 }
157}
158
159impl<F, Q> IsSubFieldOf<CubicExtensionField<F, Q>> for F
160where
161 F: IsField,
162 Q: Clone + Debug + HasCubicNonResidue<F>,
163{
164 fn mul(
165 a: &Self::BaseType,
166 b: &<CubicExtensionField<F, Q> as IsField>::BaseType,
167 ) -> <CubicExtensionField<F, Q> as IsField>::BaseType {
168 let c0 = FieldElement::from_raw(F::mul(a, b[0].value()));
169 let c1 = FieldElement::from_raw(F::mul(a, b[1].value()));
170 let c2 = FieldElement::from_raw(F::mul(a, b[2].value()));
171 [c0, c1, c2]
172 }
173
174 fn add(
175 a: &Self::BaseType,
176 b: &<CubicExtensionField<F, Q> as IsField>::BaseType,
177 ) -> <CubicExtensionField<F, Q> as IsField>::BaseType {
178 let c0 = FieldElement::from_raw(F::add(a, b[0].value()));
179 [c0, b[1].clone(), b[2].clone()]
180 }
181
182 fn div(
183 a: &Self::BaseType,
184 b: &<CubicExtensionField<F, Q> as IsField>::BaseType,
185 ) -> Result<<CubicExtensionField<F, Q> as IsField>::BaseType, FieldError> {
186 let b_inv = <CubicExtensionField<F, Q> as IsField>::inv(b)?;
187 Ok(<Self as IsSubFieldOf<CubicExtensionField<F, Q>>>::mul(
188 a, &b_inv,
189 ))
190 }
191
192 fn sub(
193 a: &Self::BaseType,
194 b: &<CubicExtensionField<F, Q> as IsField>::BaseType,
195 ) -> <CubicExtensionField<F, Q> as IsField>::BaseType {
196 let c0 = FieldElement::from_raw(F::sub(a, b[0].value()));
197 let c1 = FieldElement::from_raw(F::neg(b[1].value()));
198 let c2 = FieldElement::from_raw(F::neg(b[2].value()));
199 [c0, c1, c2]
200 }
201
202 fn embed(a: Self::BaseType) -> <CubicExtensionField<F, Q> as IsField>::BaseType {
203 [
204 FieldElement::from_raw(a),
205 FieldElement::zero(),
206 FieldElement::zero(),
207 ]
208 }
209
210 #[cfg(feature = "alloc")]
211 fn to_subfield_vec(
212 b: <CubicExtensionField<F, Q> as IsField>::BaseType,
213 ) -> alloc::vec::Vec<Self::BaseType> {
214 b.into_iter().map(|x| x.to_raw()).collect()
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use crate::field::fields::u64_prime_field::{U64FieldElement, U64PrimeField};
221
222 const ORDER_P: u64 = 13;
223
224 use super::*;
225
226 #[derive(Debug, Clone)]
227 struct MyCubicNonResidue;
228 impl HasCubicNonResidue<U64PrimeField<ORDER_P>> for MyCubicNonResidue {
229 fn residue() -> FieldElement<U64PrimeField<ORDER_P>> {
230 -FieldElement::from(11)
231 }
232 }
233
234 type FE = U64FieldElement<ORDER_P>;
235 type MyFieldExtensionBackend = CubicExtensionField<U64PrimeField<ORDER_P>, MyCubicNonResidue>;
236 #[allow(clippy::upper_case_acronyms)]
237 type FEE = FieldElement<MyFieldExtensionBackend>;
238
239 #[test]
240 fn test_add_1() {
241 let a = FEE::new([FE::new(0), FE::new(3), FE::new(5)]);
242 let b = FEE::new([-FE::new(2), FE::new(8), FE::new(10)]);
243 let expected_result = FEE::new([FE::new(11), FE::new(11), FE::new(15)]);
244 assert_eq!(a + b, expected_result);
245 }
246
247 #[test]
248 fn test_add_2() {
249 let a = FEE::new([FE::new(12), FE::new(5), FE::new(3)]);
250 let b = FEE::new([-FE::new(4), FE::new(2), FE::new(8)]);
251 let expected_result = FEE::new([FE::new(8), FE::new(7), FE::new(11)]);
252 assert_eq!(a + b, expected_result);
253 }
254
255 #[test]
256 fn test_sub_1() {
257 let a = FEE::new([FE::new(0), FE::new(3), FE::new(3)]);
258 let b = FEE::new([-FE::new(2), FE::new(8), FE::new(2)]);
259 let expected_result = FEE::new([FE::new(2), FE::new(8), FE::new(1)]);
260 assert_eq!(a - b, expected_result);
261 }
262
263 #[test]
264 fn test_sub_2() {
265 let a = FEE::new([FE::new(12), FE::new(5), FE::new(3)]);
266 let b = FEE::new([-FE::new(4), FE::new(2), FE::new(8)]);
267 let expected_result = FEE::new([FE::new(16), FE::new(3), FE::new(8)]);
268 assert_eq!(a - b, expected_result);
269 }
270
271 #[test]
272 fn test_mul_1() {
273 let a = FEE::new([FE::new(0), FE::new(3), FE::new(5)]);
274 let b = FEE::new([-FE::new(2), FE::new(8), FE::new(6)]);
275 let expected_result = FEE::new([FE::new(12), FE::new(2), FE::new(1)]);
276 assert_eq!(a * b, expected_result);
277 }
278
279 #[test]
280 fn test_mul_2() {
281 let a = FEE::new([FE::new(12), FE::new(5), FE::new(11)]);
282 let b = FEE::new([-FE::new(4), FE::new(2), FE::new(15)]);
283 let expected_result = FEE::new([FE::new(3), FE::new(9), FE::new(3)]);
284 assert_eq!(a * b, expected_result);
285 }
286
287 #[test]
288 fn test_div_1() {
289 let a = FEE::new([FE::new(0), FE::new(3), FE::new(2)]);
290 let b = FEE::new([-FE::new(2), FE::new(8), FE::new(5)]);
291 let expected_result = FEE::new([FE::new(12), FE::new(6), FE::new(1)]);
292 assert_eq!((a / b).unwrap(), expected_result);
293 }
294
295 #[test]
296 fn test_div_2() {
297 let a = FEE::new([FE::new(12), FE::new(5), FE::new(4)]);
298 let b = FEE::new([-FE::new(4), FE::new(2), FE::new(2)]);
299 let expected_result = FEE::new([FE::new(3), FE::new(8), FE::new(11)]);
300 assert_eq!((a / b).unwrap(), expected_result);
301 }
302
303 #[test]
304 fn test_pow_1() {
305 let a = FEE::new([FE::new(0), FE::new(3), FE::new(3)]);
306 let b: u64 = 5;
307 let expected_result = FEE::new([FE::new(7), FE::new(3), FE::new(1)]);
308 assert_eq!(a.pow(b), expected_result);
309 }
310
311 #[test]
312 fn test_pow_2() {
313 let a = FEE::new([FE::new(12), FE::new(5), FE::new(3)]);
314 let b: u64 = 8;
315 let expected_result = FEE::new([FE::new(5), FE::new(5), FE::new(12)]);
316 assert_eq!(a.pow(b), expected_result);
317 }
318
319 #[test]
320 fn test_inv() {
321 let a = FEE::new([FE::new(12), FE::new(5), FE::new(3)]);
322 let expected_result = FEE::new([FE::new(2), FE::new(2), FE::new(3)]);
323 assert_eq!(a.inv().unwrap(), expected_result);
324 }
325
326 #[test]
327 fn test_inv_1() {
328 let a = FEE::new([FE::new(1), FE::new(0), FE::new(1)]);
329 let expected_result = FEE::new([FE::new(8), FE::new(3), FE::new(5)]);
330 assert_eq!(a.inv().unwrap(), expected_result);
331 }
332
333 #[test]
334 fn test_add_as_subfield_1() {
335 let a = FE::new(5);
336 let b = FEE::new([-FE::new(2), FE::new(8), FE::new(10)]);
337 let expected_result = FEE::new([FE::new(3), FE::new(8), FE::new(10)]);
338 assert_eq!(a + b, expected_result);
339 }
340
341 #[test]
342 fn test_add_as_subfield_2() {
343 let a = FE::new(12);
344 let b = FEE::new([-FE::new(4), FE::new(2), FE::new(8)]);
345 let expected_result = FEE::new([FE::new(8), FE::new(2), FE::new(8)]);
346 assert_eq!(a + b, expected_result);
347 }
348
349 #[test]
350 fn test_sub_as_subfield_1() {
351 let a = FE::new(3);
352 let b = FEE::new([-FE::new(2), FE::new(8), FE::new(2)]);
353 let expected_result = FEE::new([FE::new(5), FE::new(5), FE::new(11)]);
354 assert_eq!(a - b, expected_result);
355 }
356
357 #[test]
358 fn test_sub_as_subfield_2() {
359 let a = FE::new(12);
360 let b = FEE::new([-FE::new(4), FE::new(2), FE::new(3)]);
361 let expected_result = FEE::new([FE::new(3), FE::new(11), FE::new(10)]);
362 assert_eq!(a - b, expected_result);
363 }
364
365 #[test]
366 fn test_mul_as_subfield_1() {
367 let a = FE::new(5);
368 let b = FEE::new([-FE::new(2), FE::new(8), FE::new(6)]);
369 let expected_result = FEE::new([FE::new(3), FE::new(1), FE::new(4)]);
370 assert_eq!(a * b, expected_result);
371 }
372
373 #[test]
374 fn test_mul_as_subfield_2() {
375 let a = FE::new(11);
376 let b = FEE::new([-FE::new(4), FE::new(2), FE::new(15)]);
377 let expected_result = FEE::new([FE::new(8), FE::new(9), FE::new(9)]);
378 assert_eq!(a * b, expected_result);
379 }
380
381 #[test]
382 fn test_div_as_subfield_1() {
383 let a = FE::new(2);
384 let b = FEE::new([-FE::new(2), FE::new(8), FE::new(5)]);
385 let expected_result = FEE::new([FE::new(8), FE::new(4), FE::new(10)]);
386 assert_eq!((a / b).unwrap(), expected_result);
387 }
388
389 #[test]
390 fn test_div_as_subfield_2() {
391 let a = FE::new(4);
392 let b = FEE::new([-FE::new(4), FE::new(2), FE::new(2)]);
393 let expected_result = FEE::new([FE::new(3), FE::new(6), FE::new(11)]);
394 assert_eq!((a / b).unwrap(), expected_result);
395 }
396}