p3_field/extension/
complex.rs1use super::{
2 Binomial, BinomialExtensionField, BinomiallyExtendable, ExtensionAlgebra,
3 HasTwoAdicBinomialExtension, binomial_mul,
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
27impl<F: ComplexExtendable> BinomiallyExtendable<2> for F {
28 const W: Self = F::NEG_ONE;
29
30 const DTH_ROOT: Self = F::NEG_ONE;
33
34 const EXT_GENERATOR: [Self; 2] = F::COMPLEX_GENERATOR.value;
35}
36
37impl<R: PrimeCharacteristicRing> Complex<R> {
39 #[inline(always)]
40 pub const fn new_complex(real: R, imag: R) -> Self {
41 Self::new([real, imag])
42 }
43
44 #[inline(always)]
45 pub const fn new_real(real: R) -> Self {
46 Self::new_complex(real, R::ZERO)
47 }
48
49 #[inline(always)]
50 pub const fn new_imag(imag: R) -> Self {
51 Self::new_complex(R::ZERO, imag)
52 }
53
54 #[inline(always)]
55 #[must_use]
56 pub fn real(&self) -> R {
57 self.value[0].dup()
58 }
59
60 #[inline(always)]
61 #[must_use]
62 pub fn imag(&self) -> R {
63 self.value[1].dup()
64 }
65
66 #[inline(always)]
67 pub fn conjugate(&self) -> Self {
68 Self::new_complex(self.real(), self.imag().neg())
69 }
70
71 #[inline]
72 #[must_use]
73 pub fn norm(&self) -> R {
74 self.real().square() + self.imag().square()
75 }
76
77 #[inline(always)]
78 #[must_use]
79 pub fn to_array(&self) -> [R; 2] {
80 core::array::from_fn(|i| self.value[i].dup())
81 }
82
83 #[inline]
86 pub fn rotate<Ext: Algebra<R>>(&self, rhs: &Complex<Ext>) -> Complex<Ext> {
87 Complex::<Ext>::new_complex(
88 rhs.real() * self.real() - rhs.imag() * self.imag(),
89 rhs.imag() * self.real() + rhs.real() * self.imag(),
90 )
91 }
92}
93
94pub trait HasComplexBinomialExtension<const D: usize>: ComplexExtendable {
99 const W: Complex<Self>;
100
101 const DTH_ROOT: Complex<Self>;
105
106 const EXT_GENERATOR: [Complex<Self>; D];
107}
108
109impl<F, const D: usize> ExtensionAlgebra<Self, D, Binomial<Self>> for Complex<F>
110where
111 F: HasComplexBinomialExtension<D>,
112{
113 #[inline]
114 fn ext_mul(a: &[Self; D], b: &[Self; D], res: &mut [Self; D]) {
115 binomial_mul::<Self, Self, Self, D>(a, b, res, <Self as BinomiallyExtendable<D>>::W);
116 }
117}
118
119impl<F, const D: usize> BinomiallyExtendable<D> for Complex<F>
120where
121 F: HasComplexBinomialExtension<D>,
122{
123 const W: Self = <F as HasComplexBinomialExtension<D>>::W;
124
125 const DTH_ROOT: Self = <F as HasComplexBinomialExtension<D>>::DTH_ROOT;
126
127 const EXT_GENERATOR: [Self; D] = F::EXT_GENERATOR;
128}
129
130pub trait HasTwoAdicComplexBinomialExtension<const D: usize>:
132 HasComplexBinomialExtension<D>
133{
134 const COMPLEX_EXT_TWO_ADICITY: usize;
135
136 fn complex_ext_two_adic_generator(bits: usize) -> [Complex<Self>; D];
137}
138
139impl<F, const D: usize> HasTwoAdicBinomialExtension<D> for Complex<F>
140where
141 F: HasTwoAdicComplexBinomialExtension<D>,
142{
143 const EXT_TWO_ADICITY: usize = F::COMPLEX_EXT_TWO_ADICITY;
144
145 #[inline(always)]
146 fn ext_two_adic_generator(bits: usize) -> [Self; D] {
147 F::complex_ext_two_adic_generator(bits)
148 }
149}