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 const W: Self = F::NEG_ONE;
34
35 const DTH_ROOT: Self = F::NEG_ONE;
38
39 const EXT_GENERATOR: [Self; 2] = F::COMPLEX_GENERATOR.value;
40}
41
42impl<R: PrimeCharacteristicRing> Complex<R> {
44 #[inline(always)]
45 pub const fn new_complex(real: R, imag: R) -> Self {
46 Self::new([real, imag])
47 }
48
49 #[inline(always)]
50 pub const fn new_real(real: R) -> Self {
51 Self::new_complex(real, R::ZERO)
52 }
53
54 #[inline(always)]
55 pub const fn new_imag(imag: R) -> Self {
56 Self::new_complex(R::ZERO, imag)
57 }
58
59 #[inline(always)]
60 #[must_use]
61 pub fn real(&self) -> R {
62 self.value[0].dup()
63 }
64
65 #[inline(always)]
66 #[must_use]
67 pub fn imag(&self) -> R {
68 self.value[1].dup()
69 }
70
71 #[inline(always)]
72 pub fn conjugate(&self) -> Self {
73 Self::new_complex(self.real(), self.imag().neg())
74 }
75
76 #[inline]
77 #[must_use]
78 pub fn norm(&self) -> R {
79 self.real().square() + self.imag().square()
80 }
81
82 #[inline(always)]
83 #[must_use]
84 pub fn to_array(&self) -> [R; 2] {
85 core::array::from_fn(|i| self.value[i].dup())
86 }
87
88 #[inline]
91 pub fn rotate<Ext: Algebra<R>>(&self, rhs: &Complex<Ext>) -> Complex<Ext> {
92 Complex::<Ext>::new_complex(
93 rhs.real() * self.real() - rhs.imag() * self.imag(),
94 rhs.imag() * self.real() + rhs.real() * self.imag(),
95 )
96 }
97}
98
99pub trait HasComplexBinomialExtension<const D: usize>: ComplexExtendable {
104 const W: Complex<Self>;
105
106 const DTH_ROOT: Complex<Self>;
110
111 const EXT_GENERATOR: [Complex<Self>; D];
112
113 #[inline]
119 fn mul_by_w(z: Complex<Self>) -> Complex<Self> {
120 <Complex<Self> as BinomiallyExtendable<D>>::W * z
121 }
122}
123
124impl<F, const D: usize> ExtensionAlgebra<Self, D, Binomial<Self>> for Complex<F>
125where
126 F: HasComplexBinomialExtension<D>,
127{
128 #[inline]
129 fn ext_mul(a: &[Self; D], b: &[Self; D], res: &mut [Self; D]) {
130 binomial_mul::<Self, Self, Self, D>(a, b, res, <Self as BinomiallyExtendable<D>>::W);
131 }
132
133 #[inline]
134 fn ext_square(a: &[Self; D], res: &mut [Self; D]) {
135 match D {
136 2 => {
137 let a0 = a[0];
141 let a1 = a[1];
142 let a0_sq = a0.square();
143 let a1_sq = a1.square();
144 let w_a1_sq = F::mul_by_w(a1_sq);
145 res[0] = a0_sq + w_a1_sq;
146 res[1] = (a0 * a1).double();
147 }
148 _ => binomial_square::<Self, Self, D>(a, res, <Self as BinomiallyExtendable<D>>::W),
149 }
150 }
151}
152
153impl<F, const D: usize> BinomiallyExtendable<D> for Complex<F>
154where
155 F: HasComplexBinomialExtension<D>,
156{
157 const W: Self = <F as HasComplexBinomialExtension<D>>::W;
158
159 const DTH_ROOT: Self = <F as HasComplexBinomialExtension<D>>::DTH_ROOT;
160
161 const EXT_GENERATOR: [Self; D] = F::EXT_GENERATOR;
162}
163
164pub trait HasTwoAdicComplexBinomialExtension<const D: usize>:
166 HasComplexBinomialExtension<D>
167{
168 const COMPLEX_EXT_TWO_ADICITY: usize;
169
170 fn complex_ext_two_adic_generator(bits: usize) -> [Complex<Self>; D];
171}
172
173impl<F, const D: usize> HasTwoAdicBinomialExtension<D> for Complex<F>
174where
175 F: HasTwoAdicComplexBinomialExtension<D>,
176{
177 const EXT_TWO_ADICITY: usize = F::COMPLEX_EXT_TWO_ADICITY;
178
179 #[inline(always)]
180 fn ext_two_adic_generator(bits: usize) -> [Self; D] {
181 F::complex_ext_two_adic_generator(bits)
182 }
183}