1use p3_field::exponentiation::exp_1725656503;
2use p3_field::{Algebra, PrimeCharacteristicRing, UniformSamplingField};
3use p3_monty_31::{
4 BarrettParameters, BinomialExtensionData, FieldParameters, MontyField31, MontyParameters,
5 PackedMontyParameters, RelativelyPrimePower, TwoAdicData,
6};
7
8pub type BabyBear = MontyField31<BabyBearParameters>;
10
11#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialEq)]
12pub struct BabyBearParameters;
13
14impl MontyParameters for BabyBearParameters {
15 const PRIME: u32 = 0x78000001;
18
19 const MONTY_BITS: u32 = 32;
20 const MONTY_MU: u32 = 0x88000001;
21}
22
23impl PackedMontyParameters for BabyBearParameters {}
24
25impl BarrettParameters for BabyBearParameters {}
26
27impl FieldParameters for BabyBearParameters {
28 const MONTY_GEN: BabyBear = BabyBear::new(31);
29
30 const BENEFITS_FROM_LOCKSTEP_EVALUATION: bool = true;
32}
33
34impl RelativelyPrimePower<7> for BabyBearParameters {
35 fn exp_root_d<R: PrimeCharacteristicRing>(val: R) -> R {
39 exp_1725656503(val)
40 }
41}
42
43impl TwoAdicData for BabyBearParameters {
44 const TWO_ADICITY: usize = 27;
45
46 type ArrayLike = &'static [BabyBear];
47
48 const TWO_ADIC_GENERATORS: Self::ArrayLike = &BabyBear::new_array([
49 0x1, 0x78000000, 0x67055c21, 0x5ee99486, 0xbb4c4e4, 0x2d4cc4da, 0x669d6090, 0x17b56c64,
50 0x67456167, 0x688442f9, 0x145e952d, 0x4fe61226, 0x4c734715, 0x11c33e2a, 0x62c3d2b1,
51 0x77cad399, 0x54c131f4, 0x4cabd6a6, 0x5cf5713f, 0x3e9430e8, 0xba067a3, 0x18adc27d,
52 0x21fd55bc, 0x4b859b3d, 0x3bd57996, 0x4483d85a, 0x3a26eef8, 0x1a427a41,
53 ]);
54
55 const ROOTS_8: Self::ArrayLike = &BabyBear::new_array([0x1, 0x5ee99486, 0x67055c21, 0xc9ea3ba]);
56 const INV_ROOTS_8: Self::ArrayLike =
57 &BabyBear::new_array([0x1, 0x6b615c47, 0x10faa3e0, 0x19166b7b]);
58
59 const ROOTS_16: Self::ArrayLike = &BabyBear::new_array([
60 0x1, 0xbb4c4e4, 0x5ee99486, 0x4b49e08, 0x67055c21, 0x5376917a, 0xc9ea3ba, 0x563112a7,
61 ]);
62 const INV_ROOTS_16: Self::ArrayLike = &BabyBear::new_array([
63 0x1, 0x21ceed5a, 0x6b615c47, 0x24896e87, 0x10faa3e0, 0x734b61f9, 0x19166b7b, 0x6c4b3b1d,
64 ]);
65}
66
67impl BinomialExtensionData<4> for BabyBearParameters {
68 const W: BabyBear = BabyBear::new(11);
69 const DTH_ROOT: BabyBear = BabyBear::new(1728404513);
70 const EXT_GENERATOR: [BabyBear; 4] = BabyBear::new_array([8, 1, 0, 0]);
71 const EXT_TWO_ADICITY: usize = 29;
72
73 type ArrayLike = [[BabyBear; 4]; 2];
74 const TWO_ADIC_EXTENSION_GENERATORS: Self::ArrayLike =
75 BabyBear::new_2d_array([[0, 0, 1996171314, 0], [0, 0, 0, 124907976]]);
76}
77
78impl BinomialExtensionData<5> for BabyBearParameters {
79 const W: BabyBear = BabyBear::new(2);
80
81 #[inline(always)]
82 fn mul_w<A: Algebra<MontyField31<Self>>>(a: A) -> A {
83 a.double()
84 }
85
86 const DTH_ROOT: BabyBear = BabyBear::new(815036133);
87 const EXT_GENERATOR: [BabyBear; 5] = BabyBear::new_array([8, 1, 0, 0, 0]);
88 const EXT_TWO_ADICITY: usize = 27;
89
90 type ArrayLike = [[BabyBear; 5]; 0];
91 const TWO_ADIC_EXTENSION_GENERATORS: Self::ArrayLike = [];
92}
93
94impl BinomialExtensionData<8> for BabyBearParameters {
95 const W: BabyBear = BabyBear::new(11);
96 const DTH_ROOT: BabyBear = BabyBear::new(420899707);
97 const EXT_GENERATOR: [BabyBear; 8] = BabyBear::new_array([5, 1, 0, 0, 0, 0, 0, 0]);
98 const EXT_TWO_ADICITY: usize = 30;
99
100 type ArrayLike = [[BabyBear; 8]; 3];
101 const TWO_ADIC_EXTENSION_GENERATORS: Self::ArrayLike = BabyBear::new_2d_array([
102 [0, 0, 0, 0, 1996171314, 0, 0, 0],
103 [0, 0, 0, 0, 0, 0, 124907976, 0],
104 [0, 0, 0, 518392818, 0, 0, 0, 0],
105 ]);
106}
107
108impl UniformSamplingField for BabyBearParameters {
109 const MAX_SINGLE_SAMPLE_BITS: usize = 27;
110 const SAMPLING_BITS_M: [u64; 64] = {
113 let prime: u64 = Self::PRIME as u64;
114 let mut a = [0u64; 64];
115 let mut k = 0;
116 while k < 64 {
117 if k == 0 {
118 a[k] = prime; } else {
120 let mask = !((1u64 << k) - 1);
122 a[k] = prime & mask;
123 }
124 k += 1;
125 }
126 a
127 };
128}
129
130#[cfg(test)]
131mod tests {
132 use core::array;
133
134 use num_bigint::BigUint;
135 use p3_field::extension::BinomialExtensionField;
136 use p3_field::{InjectiveMonomial, PermutationMonomial, PrimeField64, TwoAdicField};
137 use p3_field_testing::{
138 test_field, test_field_dft, test_field_dft_consistency, test_field_dft_large,
139 test_field_json_serialization, test_prime_field, test_prime_field_32, test_prime_field_64,
140 test_two_adic_field,
141 };
142 use proptest::prelude::*;
143
144 use super::*;
145
146 type F = BabyBear;
147 type EF = BinomialExtensionField<F, 4>;
148
149 #[test]
150 fn test_baby_bear_two_adicity_generators() {
151 let base = BabyBear::from_u32(0x1a427a41);
152 for bits in 0..=BabyBear::TWO_ADICITY {
153 assert_eq!(
154 BabyBear::two_adic_generator(bits),
155 base.exp_power_of_2(BabyBear::TWO_ADICITY - bits)
156 );
157 }
158 }
159
160 #[test]
161 fn test_to_babybear_array() {
162 let range_array: [u32; 32] = array::from_fn(|i| i as u32);
163 assert_eq!(
164 BabyBear::new_array(range_array),
165 range_array.map(F::from_u32)
166 );
167 }
168
169 #[test]
170 fn test_baby_bear() {
171 let f = F::from_u32(100);
172 assert_eq!(f.as_canonical_u64(), 100);
173
174 let f_1 = F::ONE;
175 let f_2 = F::TWO;
176 let f_p_minus_1 = F::NEG_ONE;
177 let f_p_minus_2 = F::NEG_ONE + F::NEG_ONE;
178 let m1 = F::from_u32(0x34167c58);
179 let m2 = F::from_u32(0x61f3207b);
180 let expected_prod = F::from_u32(0x1b5c8046);
181 assert_eq!(m1 * m2, expected_prod);
182
183 assert_eq!(m1.injective_exp_n().injective_exp_root_n(), m1);
184 assert_eq!(m2.injective_exp_n().injective_exp_root_n(), m2);
185 assert_eq!(F::TWO.injective_exp_n().injective_exp_root_n(), F::TWO);
186
187 test_field_json_serialization(&[f, f_1, f_2, f_p_minus_1, f_p_minus_2, m1, m2]);
188 }
189
190 proptest! {
191 #[test]
194 fn test_baby_bear_inherent_sqrt(x in prop::num::u32::ANY.prop_map(F::from_u32)) {
195 let square = x.square();
198 prop_assert_eq!(square.try_sqrt().map(|r| r.square()), Some(square));
199
200 if let Some(r) = x.try_sqrt() {
202 prop_assert_eq!(r.square(), x);
203 }
204 }
205 }
206
207 const ZEROS: [BabyBear; 1] = [BabyBear::ZERO];
209 const ONES: [BabyBear; 1] = [BabyBear::ONE];
210
211 fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 3] {
214 [
215 (BigUint::from(2u8), 27),
216 (BigUint::from(3u8), 1),
217 (BigUint::from(5u8), 1),
218 ]
219 }
220
221 test_field!(
222 crate::BabyBear,
223 &super::ZEROS,
224 &super::ONES,
225 &super::multiplicative_group_prime_factorization()
226 );
227 test_two_adic_field!(crate::BabyBear);
228
229 test_field_dft!(radix2dit, crate::BabyBear, super::EF, p3_dft::Radix2Dit<_>);
230 test_field_dft!(
231 radix2smallbatch,
232 crate::BabyBear,
233 super::EF,
234 p3_dft::Radix2DFTSmallBatch<_>
235 );
236 test_field_dft!(bowers, crate::BabyBear, super::EF, p3_dft::Radix2Bowers);
237 test_field_dft!(
238 parallel,
239 crate::BabyBear,
240 super::EF,
241 p3_dft::Radix2DitParallel::<_>
242 );
243 test_field_dft!(
244 recur_dft,
245 crate::BabyBear,
246 super::EF,
247 p3_monty_31::dft::RecursiveDft<_>
248 );
249 test_field_dft_consistency!(
250 radix2_smallbatch_and_ditparallel,
251 crate::BabyBear,
252 super::EF,
253 p3_dft::Radix2DFTSmallBatch<_>,
254 p3_dft::Radix2DitParallel<_>
255 );
256 test_field_dft_large!(
257 radix2smallbatch_large,
258 crate::BabyBear,
259 super::EF,
260 p3_dft::Radix2DFTSmallBatch<_>
261 );
262
263 test_field_dft_large!(
264 parallel_large,
265 crate::BabyBear,
266 super::EF,
267 p3_dft::Radix2DitParallel<_>
268 );
269
270 test_field_dft_large!(
271 recur_dft_large,
272 crate::BabyBear,
273 super::EF,
274 p3_monty_31::dft::RecursiveDft<_>
275 );
276 test_prime_field!(crate::BabyBear);
277 test_prime_field_64!(crate::BabyBear, &super::ZEROS, &super::ONES);
278 test_prime_field_32!(crate::BabyBear, &super::ZEROS, &super::ONES);
279}