p3_mersenne_31/
complex.rs1use p3_field::PrimeCharacteristicRing;
8use p3_field::extension::{Complex, ComplexExtendable, HasTwoAdicBinomialExtension};
9
10use crate::Mersenne31;
11
12impl ComplexExtendable for Mersenne31 {
13 const CIRCLE_TWO_ADICITY: usize = 31;
14
15 const COMPLEX_GENERATOR: Complex<Self> = Complex::new_complex(Self::new(12), Self::ONE);
22
23 fn circle_two_adic_generator(bits: usize) -> Complex<Self> {
24 assert!(bits <= Self::CIRCLE_TWO_ADICITY);
34 let base = Complex::new_complex(Self::new(311_014_874), Self::new(1_584_694_829));
35 base.exp_power_of_2(Self::CIRCLE_TWO_ADICITY - bits)
36 }
37}
38
39impl HasTwoAdicBinomialExtension<2> for Mersenne31 {
40 const EXT_TWO_ADICITY: usize = 32;
41
42 fn ext_two_adic_generator(bits: usize) -> [Self; 2] {
43 assert!(bits <= Self::EXT_TWO_ADICITY);
44 Self::EXT_TWO_ADIC_GENERATORS[bits]
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use num_bigint::BigUint;
51 use p3_field::{ExtensionField, PrimeField32};
52 use p3_field_testing::{
53 test_extension_field, test_field, test_packed_extension_field, test_two_adic_field,
54 };
55
56 use super::*;
57
58 type Fi = Complex<Mersenne31>;
59 type F = Mersenne31;
60
61 #[test]
62 fn add() {
63 assert_eq!(Fi::ONE + Fi::ONE, Fi::TWO);
65 assert_eq!(Fi::NEG_ONE + Fi::ONE, Fi::ZERO);
66 assert_eq!(Fi::NEG_ONE + Fi::TWO, Fi::ONE);
67 assert_eq!((Fi::NEG_ONE + Fi::NEG_ONE).real(), F::new(F::ORDER_U32 - 2));
68
69 assert_eq!(
71 Fi::new_imag(F::ONE) + Fi::new_imag(F::ONE),
72 Fi::new_imag(F::TWO)
73 );
74 assert_eq!(
75 Fi::new_imag(F::NEG_ONE) + Fi::new_imag(F::ONE),
76 Fi::new_imag(F::ZERO)
77 );
78 assert_eq!(
79 Fi::new_imag(F::NEG_ONE) + Fi::new_imag(F::TWO),
80 Fi::new_imag(F::ONE)
81 );
82 assert_eq!(
83 (Fi::new_imag(F::NEG_ONE) + Fi::new_imag(F::NEG_ONE)).imag(),
84 F::new(F::ORDER_U32 - 2)
85 );
86
87 assert_eq!(
89 Fi::new_complex(F::ONE, F::TWO) + Fi::new_complex(F::ONE, F::ONE),
90 Fi::new_complex(F::TWO, F::new(3))
91 );
92 assert_eq!(
93 Fi::new_complex(F::NEG_ONE, F::NEG_ONE) + Fi::new_complex(F::ONE, F::ONE),
94 Fi::ZERO
95 );
96 assert_eq!(
97 Fi::new_complex(F::NEG_ONE, F::ONE) + Fi::new_complex(F::TWO, F::new(F::ORDER_U32 - 2)),
98 Fi::new_complex(F::ONE, F::NEG_ONE)
99 );
100 }
101
102 #[test]
103 fn sub() {
104 assert_eq!(Fi::ONE - Fi::ONE, Fi::ZERO);
106 assert_eq!(Fi::TWO - Fi::TWO, Fi::ZERO);
107 assert_eq!(Fi::NEG_ONE - Fi::NEG_ONE, Fi::ZERO);
108 assert_eq!(Fi::TWO - Fi::ONE, Fi::ONE);
109 assert_eq!(Fi::NEG_ONE - Fi::ZERO, Fi::NEG_ONE);
110
111 assert_eq!(Fi::new_imag(F::ONE) - Fi::new_imag(F::ONE), Fi::ZERO);
113 assert_eq!(Fi::new_imag(F::TWO) - Fi::new_imag(F::TWO), Fi::ZERO);
114 assert_eq!(
115 Fi::new_imag(F::NEG_ONE) - Fi::new_imag(F::NEG_ONE),
116 Fi::ZERO
117 );
118 assert_eq!(
119 Fi::new_imag(F::TWO) - Fi::new_imag(F::ONE),
120 Fi::new_imag(F::ONE)
121 );
122 assert_eq!(
123 Fi::new_imag(F::NEG_ONE) - Fi::ZERO,
124 Fi::new_imag(F::NEG_ONE)
125 );
126 }
127
128 #[test]
129 fn mul() {
130 assert_eq!(
131 Fi::new_complex(F::TWO, F::TWO) * Fi::new_complex(F::new(4), F::new(5)),
132 Fi::new_complex(-F::TWO, F::new(18))
133 );
134 }
135
136 #[test]
137 fn mul_2exp_u64() {
138 assert_eq!(Fi::ONE.mul_2exp_u64(0), Fi::ONE);
141 assert_eq!(Fi::TWO.mul_2exp_u64(30), Fi::ONE);
143 assert_eq!(
145 Fi::new_real(F::new(5)).mul_2exp_u64(2),
146 Fi::new_real(F::new(20))
147 );
148
149 assert_eq!(Fi::new_imag(F::ONE).mul_2exp_u64(0), Fi::new_imag(F::ONE));
152 assert_eq!(Fi::new_imag(F::TWO).mul_2exp_u64(30), Fi::new_imag(F::ONE));
154 assert_eq!(
156 Fi::new_imag(F::new(5)).mul_2exp_u64(2),
157 Fi::new_imag(F::new(20))
158 );
159 }
160
161 const ZEROS: [Fi; 1] = [Fi::ZERO];
164 const ONES: [Fi; 1] = [Fi::ONE];
165
166 fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 7] {
169 [
170 (BigUint::from(2u8), 32),
171 (BigUint::from(3u8), 2),
172 (BigUint::from(7u8), 1),
173 (BigUint::from(11u8), 1),
174 (BigUint::from(31u8), 1),
175 (BigUint::from(151u8), 1),
176 (BigUint::from(331u16), 1),
177 ]
178 }
179
180 test_field!(
181 super::Fi,
182 &super::ZEROS,
183 &super::ONES,
184 &super::multiplicative_group_prime_factorization()
185 );
186
187 test_extension_field!(super::F, super::Fi);
188 test_two_adic_field!(super::Fi);
189
190 type Pef = <Fi as ExtensionField<F>>::ExtensionPacking;
191 const PACKED_ZEROS: [Pef; 1] = [Pef::ZERO];
192 const PACKED_ONES: [Pef; 1] = [Pef::ONE];
193 test_packed_extension_field!(super::Pef, &super::PACKED_ZEROS, &super::PACKED_ONES);
194}