p3_field/extension/
complex.rs1use super::{
2 Binomial, BinomialExtensionField, BinomiallyExtendable, ExtensionAlgebra,
3 HasTwoAdicBinomialExtension, binomial_mul, binomial_square,
4};
5use crate::{Algebra, Field, PrimeCharacteristicRing};
6
7pub type Complex<F> = BinomialExtensionField<F, 2>;
8
9pub trait ComplexExtendable: Field {
12 const CIRCLE_TWO_ADICITY: usize;
14
15 const COMPLEX_GENERATOR: Complex<Self>;
16
17 fn circle_two_adic_generator(bits: usize) -> Complex<Self>;
18}
19
20impl<F: ComplexExtendable> ExtensionAlgebra<F, 2, Binomial<F>> for F {
21 #[inline]
22 fn ext_mul(a: &[Self; 2], b: &[Self; 2], res: &mut [Self; 2]) {
23 binomial_mul::<F, Self, Self, 2>(a, b, res, <F as BinomiallyExtendable<2>>::W);
24 }
25
26 #[inline]
27 fn ext_square(a: &[Self; 2], res: &mut [Self; 2]) {
28 binomial_square::<F, Self, 2>(a, res, <F as BinomiallyExtendable<2>>::W);
29 }
30}
31
32impl<F: ComplexExtendable> BinomiallyExtendable<2> for F {
33 fn binomial_algebra_id() -> alloc::vec::Vec<u8> {
34 b"p3-power-basis-v1:X^2+1".to_vec()
35 }
36
37 const W: Self = F::NEG_ONE;
38
39 const DTH_ROOT: Self = F::NEG_ONE;
42
43 const EXT_GENERATOR: [Self; 2] = F::COMPLEX_GENERATOR.value;
44}
45
46impl<R: PrimeCharacteristicRing> Complex<R> {
48 #[inline(always)]
49 pub const fn new_complex(real: R, imag: R) -> Self {
50 Self::new([real, imag])
51 }
52
53 #[inline(always)]
54 pub const fn new_real(real: R) -> Self {
55 Self::new_complex(real, R::ZERO)
56 }
57
58 #[inline(always)]
59 pub const fn new_imag(imag: R) -> Self {
60 Self::new_complex(R::ZERO, imag)
61 }
62
63 #[inline(always)]
64 #[must_use]
65 pub fn real(&self) -> R {
66 self.value[0].dup()
67 }
68
69 #[inline(always)]
70 #[must_use]
71 pub fn imag(&self) -> R {
72 self.value[1].dup()
73 }
74
75 #[inline(always)]
76 pub fn conjugate(&self) -> Self {
77 Self::new_complex(self.real(), self.imag().neg())
78 }
79
80 #[inline]
81 #[must_use]
82 pub fn norm(&self) -> R {
83 self.real().square() + self.imag().square()
84 }
85
86 #[inline(always)]
87 #[must_use]
88 pub fn to_array(&self) -> [R; 2] {
89 core::array::from_fn(|i| self.value[i].dup())
90 }
91
92 #[inline]
95 pub fn rotate<Ext: Algebra<R>>(&self, rhs: &Complex<Ext>) -> Complex<Ext> {
96 Complex::<Ext>::new_complex(
97 rhs.real() * self.real() - rhs.imag() * self.imag(),
98 rhs.imag() * self.real() + rhs.real() * self.imag(),
99 )
100 }
101}
102
103pub trait HasComplexBinomialExtension<const D: usize>: ComplexExtendable {
108 fn complex_binomial_algebra_id() -> alloc::vec::Vec<u8>;
110
111 const W: Complex<Self>;
112
113 const DTH_ROOT: Complex<Self>;
117
118 const EXT_GENERATOR: [Complex<Self>; D];
119
120 #[inline]
126 fn mul_by_w(z: Complex<Self>) -> Complex<Self> {
127 <Complex<Self> as BinomiallyExtendable<D>>::W * z
128 }
129}
130
131impl<F, const D: usize> ExtensionAlgebra<Self, D, Binomial<Self>> for Complex<F>
132where
133 F: HasComplexBinomialExtension<D>,
134{
135 #[inline]
136 fn ext_mul(a: &[Self; D], b: &[Self; D], res: &mut [Self; D]) {
137 binomial_mul::<Self, Self, Self, D>(a, b, res, <Self as BinomiallyExtendable<D>>::W);
138 }
139
140 #[inline]
141 fn ext_square(a: &[Self; D], res: &mut [Self; D]) {
142 match D {
143 2 => {
144 let a0 = a[0];
148 let a1 = a[1];
149 let a0_sq = a0.square();
150 let a1_sq = a1.square();
151 let w_a1_sq = F::mul_by_w(a1_sq);
152 res[0] = a0_sq + w_a1_sq;
153 res[1] = (a0 * a1).double();
154 }
155 _ => binomial_square::<Self, Self, D>(a, res, <Self as BinomiallyExtendable<D>>::W),
156 }
157 }
158}
159
160impl<F, const D: usize> BinomiallyExtendable<D> for Complex<F>
161where
162 F: HasComplexBinomialExtension<D>,
163{
164 fn binomial_algebra_id() -> alloc::vec::Vec<u8> {
165 F::complex_binomial_algebra_id()
166 }
167
168 const W: Self = <F as HasComplexBinomialExtension<D>>::W;
169
170 const DTH_ROOT: Self = <F as HasComplexBinomialExtension<D>>::DTH_ROOT;
171
172 const EXT_GENERATOR: [Self; D] = F::EXT_GENERATOR;
173}
174
175pub trait HasTwoAdicComplexBinomialExtension<const D: usize>:
177 HasComplexBinomialExtension<D>
178{
179 const COMPLEX_EXT_TWO_ADICITY: usize;
180
181 fn complex_ext_two_adic_generator(bits: usize) -> [Complex<Self>; D];
182}
183
184impl<F, const D: usize> HasTwoAdicBinomialExtension<D> for Complex<F>
185where
186 F: HasTwoAdicComplexBinomialExtension<D>,
187{
188 const EXT_TWO_ADICITY: usize = F::COMPLEX_EXT_TWO_ADICITY;
189
190 #[inline(always)]
191 fn ext_two_adic_generator(bits: usize) -> [Self; D] {
192 F::complex_ext_two_adic_generator(bits)
193 }
194}