struct QdrtPowPrec {
br_qdrt: BarrettReduction<u64>,
p0: Vec<u64>,
p1: Vec<u64>,
p2: Vec<u64>,
p3: Vec<u64>,
}Fields§
§br_qdrt: BarrettReduction<u64>§p0: Vec<u64>§p1: Vec<u64>§p2: Vec<u64>§p3: Vec<u64>Implementations§
Source§impl QdrtPowPrec
impl QdrtPowPrec
Sourcefn new(a: u64, ord: u64, br: &BarrettReduction<u128>) -> Self
fn new(a: u64, ord: u64, br: &BarrettReduction<u128>) -> Self
Examples found in repository?
crates/competitive/src/math/discrete_logarithm.rs (line 262)
258 fn new(p: u64, br_primes: &[BarrettReduction<u64>]) -> Self {
259 let ord = p - 1;
260 let g = primitive_root(p);
261 let br = BarrettReduction::<u128>::new(p as u128);
262 let prec = QdrtPowPrec::new(g, ord, &br);
263 let coeff = index_calculus_for_primitive_root(p, ord, br_primes, &prec);
264 Self {
265 p,
266 ord,
267 prec,
268 coeff,
269 }
270 }Sourcefn pow(&self, k: u64, br: &BarrettReduction<u128>) -> u64
fn pow(&self, k: u64, br: &BarrettReduction<u128>) -> u64
Examples found in repository?
crates/competitive/src/math/discrete_logarithm.rs (line 203)
182fn index_calculus_for_primitive_root(
183 p: u64,
184 ord: u64,
185 br_primes: &[BarrettReduction<u64>],
186 prec: &QdrtPowPrec,
187) -> Vec<u64> {
188 let br_ord = BarrettReduction::<u128>::new(ord as u128);
189 let mul = |x: u64, y: u64| br_ord.rem(x as u128 * y as u128) as u64;
190 let sub = |x: u64, y: u64| if x < y { x + ord - y } else { x - y };
191
192 let pc = br_primes.len();
193 let mut mat: Vec<Vec<u64>> = vec![];
194 let mut rows: Vec<Vec<u64>> = vec![];
195
196 let mut rng = Xorshift::default();
197 let br = BarrettReduction::<u128>::new(p as u128);
198
199 for i in 0..pc {
200 for ri in 0usize.. {
201 let mut row = vec![0u64; pc + 1];
202 let mut kk = rng.rand(ord - 1) + 1;
203 let mut gkk = prec.pow(kk, &br);
204 let mut k = kk;
205 let mut gk = gkk;
206 while ri >= rows.len() {
207 row[pc] = k;
208 if factorize_smooth(gk, &mut row, br_primes) {
209 rows.push(row);
210 break;
211 }
212 if k + kk < ord {
213 k += kk;
214 gk = br.rem(gk as u128 * gkk as u128) as u64;
215 } else {
216 kk = rng.rand(ord - 1) + 1;
217 gkk = prec.pow(kk, &br);
218 k = kk;
219 gk = gkk;
220 }
221 }
222 let row = &mut rows[ri];
223 for j in 0..i {
224 if row[j] != 0 {
225 let b = mul(modinv(mat[j][j], ord), row[j]);
226 for (r, a) in row[j..].iter_mut().zip(&mat[j][j..]) {
227 *r = sub(*r, mul(*a, b));
228 }
229 }
230 assert_eq!(row[j], 0);
231 }
232 if gcd(row[i], ord) == 1 {
233 let last = rows.len() - 1;
234 rows.swap(ri, last);
235 mat.push(rows.pop().unwrap());
236 break;
237 }
238 }
239 }
240 for i in (0..pc).rev() {
241 for j in i + 1..pc {
242 mat[i][pc] = sub(mat[i][pc], mul(mat[i][j], mat[j][pc]));
243 }
244 mat[i][pc] = mul(mat[i][pc], modinv(mat[i][i], ord));
245 }
246 (0..pc).map(|i| mat[i][pc]).collect()
247}
248
249#[derive(Debug)]
250struct IndexCalculusWithPrimitiveRoot {
251 p: u64,
252 ord: u64,
253 prec: QdrtPowPrec,
254 coeff: Vec<u64>,
255}
256
257impl IndexCalculusWithPrimitiveRoot {
258 fn new(p: u64, br_primes: &[BarrettReduction<u64>]) -> Self {
259 let ord = p - 1;
260 let g = primitive_root(p);
261 let br = BarrettReduction::<u128>::new(p as u128);
262 let prec = QdrtPowPrec::new(g, ord, &br);
263 let coeff = index_calculus_for_primitive_root(p, ord, br_primes, &prec);
264 Self {
265 p,
266 ord,
267 prec,
268 coeff,
269 }
270 }
271 fn index_calculus(&self, a: u64, br_primes: &[BarrettReduction<u64>]) -> Option<u64> {
272 let p = self.p;
273 let ord = self.ord;
274 let br = BarrettReduction::<u128>::new(p as u128);
275 let a = br.rem(a as _) as u64;
276 if a == 1 {
277 return Some(0);
278 }
279 if p == 2 {
280 return None;
281 }
282
283 let mut rng = Xorshift::new();
284 let mut row = vec![0u64; br_primes.len()];
285 let mut kk = rng.rand(ord - 1) + 1;
286 let mut gkk = self.prec.pow(kk, &br);
287 let mut k = kk;
288 let mut gk = br.rem(gkk as u128 * a as u128) as u64;
289 loop {
290 if factorize_smooth(gk, &mut row, br_primes) {
291 let mut res = ord - k;
292 for (&c, &r) in self.coeff.iter().zip(&row) {
293 for _ in 0..r {
294 res += c;
295 if res >= ord {
296 res -= ord;
297 }
298 }
299 }
300 return Some(res);
301 }
302 if k + kk < ord {
303 k += kk;
304 gk = br.rem(gk as u128 * gkk as u128) as u64;
305 } else {
306 kk = rng.rand(ord - 1) + 1;
307 gkk = self.prec.pow(kk, &br);
308 k = kk;
309 gk = br.rem(gkk as u128 * a as u128) as u64;
310 }
311 }
312 }Trait Implementations§
Auto Trait Implementations§
impl Freeze for QdrtPowPrec
impl RefUnwindSafe for QdrtPowPrec
impl Send for QdrtPowPrec
impl Sync for QdrtPowPrec
impl Unpin for QdrtPowPrec
impl UnsafeUnpin for QdrtPowPrec
impl UnwindSafe for QdrtPowPrec
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more