1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
mod field;
mod group;
mod ring;

pub use field::*;
pub use group::*;
pub use ring::*;

/// extension field basic operation macro
#[macro_export]
macro_rules! extension_field_operation {
    ($extension_field:ident, $sub_field:ident, $limbs_length:ident) => {
        prime_extension_field_operation!($extension_field, $sub_field, $limbs_length);

        /// extension field of base field
        #[derive(Clone, Copy, Decode, Encode)]
        pub struct $extension_field(pub(crate) [$sub_field; $limbs_length]);

        impl ParityCmp for $extension_field {}
        impl Basic for $extension_field {}

        impl ExtensionField for $extension_field {
            fn mul_by_nonresidue(self) -> Self {
                self.mul_by_nonres()
            }
        }
    };
}

/// prime field operation for extension field macro
#[macro_export]
macro_rules! prime_extension_field_operation {
    ($extension_field:ident, $sub_field:ident, $limbs_length:ident) => {
        ext_field_operation!($extension_field, $sub_field, $limbs_length);

        impl From<u64> for $extension_field {
            fn from(val: u64) -> $extension_field {
                unimplemented!()
            }
        }

        impl RefOps for $extension_field {}

        impl PrimeField for $extension_field {
            // wrong if this is problem
            const MODULUS: $extension_field = $extension_field::one();

            const INV: u64 = $sub_field::INV;

            fn is_zero(self) -> bool {
                self.0.iter().all(|x| x.is_zero())
            }

            fn to_bits(self) -> Bits {
                unimplemented!()
            }

            fn to_nafs(self) -> Nafs {
                unimplemented!()
            }

            fn double(self) -> Self {
                let mut limbs: [$sub_field; $limbs_length] = [$sub_field::zero(); $limbs_length];
                for i in 0..$limbs_length {
                    limbs[i] = self.0[i].double();
                }
                $extension_field(limbs)
            }

            fn square(self) -> Self {
                self.square_ext_field()
            }

            fn double_assign(&mut self) {
                *self = self.double()
            }

            fn square_assign(&mut self) {
                *self = self.square()
            }
        }
    };
}

pub use {extension_field_operation, prime_extension_field_operation};