p3_field/extension/
complex.rs

1use super::{BinomialExtensionField, BinomiallyExtendable, HasTwoAdicBionmialExtension};
2use crate::{AbstractExtensionField, AbstractField, Field};
3
4pub type Complex<AF> = BinomialExtensionField<AF, 2>;
5
6/// A field for which `p = 3 (mod 4)`. Equivalently, `-1` is not a square,
7/// so the complex extension can be defined `F[X]/(X^2+1)`.
8pub trait ComplexExtendable: Field {
9    /// The two-adicity of `p+1`, the order of the circle group.
10    const CIRCLE_TWO_ADICITY: usize;
11
12    fn complex_generator() -> Complex<Self>;
13
14    fn circle_two_adic_generator(bits: usize) -> Complex<Self>;
15}
16
17impl<F: ComplexExtendable> BinomiallyExtendable<2> for F {
18    fn w() -> Self {
19        F::neg_one()
20    }
21    fn dth_root() -> Self {
22        // since `p = 3 (mod 4)`, `(p-1)/2` is always odd,
23        // so `(-1)^((p-1)/2) = -1`
24        F::neg_one()
25    }
26    fn ext_generator() -> [Self; 2] {
27        F::complex_generator().value
28    }
29}
30
31/// Convenience methods for complex extensions
32impl<AF: AbstractField> Complex<AF> {
33    pub const fn new(real: AF, imag: AF) -> Self {
34        Self {
35            value: [real, imag],
36        }
37    }
38    pub fn new_real(real: AF) -> Self {
39        Self::new(real, AF::zero())
40    }
41    pub fn new_imag(imag: AF) -> Self {
42        Self::new(AF::zero(), imag)
43    }
44    pub fn real(&self) -> AF {
45        self.value[0].clone()
46    }
47    pub fn imag(&self) -> AF {
48        self.value[1].clone()
49    }
50    pub fn conjugate(&self) -> Self {
51        Self::new(self.real(), self.imag().neg())
52    }
53    pub fn norm(&self) -> AF {
54        self.real().square() + self.imag().square()
55    }
56    pub fn to_array(&self) -> [AF; 2] {
57        self.value.clone()
58    }
59    // Sometimes we want to rotate over an extension that's not necessarily ComplexExtendable,
60    // but still on the circle.
61    pub fn rotate<Ext: AbstractExtensionField<AF>>(&self, rhs: Complex<Ext>) -> Complex<Ext> {
62        Complex::<Ext>::new(
63            rhs.real() * self.real() - rhs.imag() * self.imag(),
64            rhs.imag() * self.real() + rhs.real() * self.imag(),
65        )
66    }
67}
68
69/// The complex extension of this field has a binomial extension.
70pub trait HasComplexBinomialExtension<const D: usize>: ComplexExtendable {
71    fn w() -> Complex<Self>;
72    fn dth_root() -> Complex<Self>;
73    fn ext_generator() -> [Complex<Self>; D];
74}
75
76impl<F, const D: usize> BinomiallyExtendable<D> for Complex<F>
77where
78    F: HasComplexBinomialExtension<D>,
79{
80    fn w() -> Self {
81        <F as HasComplexBinomialExtension<D>>::w()
82    }
83    fn dth_root() -> Self {
84        <F as HasComplexBinomialExtension<D>>::dth_root()
85    }
86    fn ext_generator() -> [Self; D] {
87        <F as HasComplexBinomialExtension<D>>::ext_generator()
88    }
89}
90
91/// The complex extension of this field has a two-adic binomial extension.
92pub trait HasTwoAdicComplexBinomialExtension<const D: usize>:
93    HasComplexBinomialExtension<D>
94{
95    const COMPLEX_EXT_TWO_ADICITY: usize;
96    fn complex_ext_two_adic_generator(bits: usize) -> [Complex<Self>; D];
97}
98
99impl<F, const D: usize> HasTwoAdicBionmialExtension<D> for Complex<F>
100where
101    F: HasTwoAdicComplexBinomialExtension<D>,
102{
103    const EXT_TWO_ADICITY: usize = F::COMPLEX_EXT_TWO_ADICITY;
104
105    fn ext_two_adic_generator(bits: usize) -> [Self; D] {
106        F::complex_ext_two_adic_generator(bits)
107    }
108}