malachite_nz/natural/arithmetic/kronecker_symbol.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MP Library.
4//
5// Copyright © 1991-2018 Free Software Foundation, Inc.
6//
7// This file is part of Malachite.
8//
9// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
10// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
11// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
12
13use crate::integer::arithmetic::kronecker_symbol::{
14 limbs_kronecker_symbol, limbs_kronecker_symbol_single,
15};
16use crate::natural::InnerNatural::{Large, Small};
17use crate::natural::Natural;
18use crate::natural::arithmetic::gcd::half_gcd::{
19 GCD_DC_THRESHOLD, GcdSubdivideStepContext, HGCD_THRESHOLD, HalfGcdMatrix, HalfGcdMatrix1,
20 extract_number, limbs_gcd_div, limbs_gcd_subdivide_step, limbs_gcd_subdivide_step_scratch_len,
21 limbs_half_gcd_matrix_1_mul_inverse_vector, limbs_half_gcd_matrix_adjust,
22 limbs_half_gcd_matrix_init_scratch_len, limbs_half_gcd_matrix_mul_matrix,
23 limbs_half_gcd_matrix_mul_matrix_1, limbs_half_gcd_matrix_update_q, limbs_half_gcd_scratch_len,
24};
25use crate::platform::{DoubleLimb, Limb};
26use core::cmp::max;
27use core::mem::swap;
28use malachite_base::fail_on_untested_path;
29use malachite_base::num::arithmetic::traits::{
30 DivMod, JacobiSymbol, KroneckerSymbol, LegendreSymbol, ModPowerOf2, Parity, XXSubYYToZZ,
31};
32use malachite_base::num::basic::integers::PrimitiveInt;
33use malachite_base::num::basic::traits::Zero;
34use malachite_base::num::conversion::traits::{JoinHalves, WrappingFrom};
35use malachite_base::num::logic::traits::LeadingZeros;
36use malachite_base::slices::slice_trailing_zeros;
37
38// This is equivalent to `jacobi_table` from `mpn/jacobi.c`, GMP 6.2.1.
39const JACOBI_TABLE: [u8; 208] = [
40 0, 0, 0, 0, 0, 12, 8, 4, 1, 1, 1, 1, 1, 13, 9, 5, 2, 2, 2, 2, 2, 6, 10, 14, 3, 3, 3, 3, 3, 7,
41 11, 15, 4, 16, 6, 18, 4, 0, 12, 8, 5, 17, 7, 19, 5, 1, 13, 9, 6, 18, 4, 16, 6, 10, 14, 2, 7,
42 19, 5, 17, 7, 11, 15, 3, 8, 10, 9, 11, 8, 4, 0, 12, 9, 11, 8, 10, 9, 5, 1, 13, 10, 9, 11, 8,
43 10, 14, 2, 6, 11, 8, 10, 9, 11, 15, 3, 7, 12, 22, 24, 20, 12, 8, 4, 0, 13, 23, 25, 21, 13, 9,
44 5, 1, 25, 21, 13, 23, 14, 2, 6, 10, 24, 20, 12, 22, 15, 3, 7, 11, 16, 6, 18, 4, 16, 16, 16, 16,
45 17, 7, 19, 5, 17, 17, 17, 17, 18, 4, 16, 6, 18, 22, 19, 23, 19, 5, 17, 7, 19, 23, 18, 22, 20,
46 12, 22, 24, 20, 20, 20, 20, 21, 13, 23, 25, 21, 21, 21, 21, 22, 24, 20, 12, 22, 19, 23, 18, 23,
47 25, 21, 13, 23, 18, 22, 19, 24, 20, 12, 22, 15, 3, 7, 11, 25, 21, 13, 23, 14, 2, 6, 10,
48];
49
50// This is equivalent to `mpn_jacobi_update` from `gmp-impl.h`, GMP 6.2.1.
51fn limbs_jacobi_update(bits: u8, denominator: u8, q: Limb) -> u8 {
52 assert!(bits < 26);
53 assert!(denominator < 2);
54 assert!(q < 4);
55 JACOBI_TABLE[usize::wrapping_from(((bits << 3) + (denominator << 2)) | u8::wrapping_from(q))]
56}
57
58// This is equivalent to `hgcd_jacobi_context` from `mpn/hgcd_jacobi.c`, GMP 6.2.1.
59struct HalfGcdJacobiContext<'a, 'b, 'c> {
60 m: &'a mut HalfGcdMatrix<'b>,
61 bits_mut: &'c mut u8,
62}
63
64impl GcdSubdivideStepContext for HalfGcdJacobiContext<'_, '_, '_> {
65 // This is equivalent to `hgcd_jacobi_hook` from `mpn/hgcd_jacobi.c`, GMP 6.2.1.
66 fn gcd_subdiv_step_hook(
67 &mut self,
68 gs: Option<&[Limb]>,
69 qs: Option<&mut [Limb]>,
70 mut qs_len: usize,
71 d: i8,
72 ) {
73 assert!(gs.is_none());
74 assert!(d >= 0);
75 let qs = qs.unwrap();
76 qs_len -= slice_trailing_zeros(&qs[..qs_len]);
77 if qs_len != 0 {
78 let (qs, scratch) = qs.split_at_mut(qs_len);
79 let d = u8::wrapping_from(d);
80 limbs_half_gcd_matrix_update_q(self.m, qs, d, scratch);
81 *self.bits_mut = limbs_jacobi_update(*self.bits_mut, d, qs[0].mod_power_of_2(2));
82 }
83 }
84}
85
86const HALF_WIDTH: u64 = Limb::WIDTH >> 1;
87const TWO_POW_HALF_WIDTH: Limb = 1 << HALF_WIDTH;
88const TWICE_TWO_POW_HALF_WIDTH: Limb = TWO_POW_HALF_WIDTH << 1;
89
90// This is equivalent to `mpn_hgcd2_jacobi` from `mpn/hgcd2_jacobi.c`, GMP 6.2.1, returning `bitsp`
91// along with a bool.
92fn limbs_half_gcd_2_jacobi(
93 mut x_1: Limb,
94 mut x_0: Limb,
95 mut y_1: Limb,
96 mut y_0: Limb,
97 m: &mut HalfGcdMatrix1,
98 mut bits: u8,
99) -> (u8, bool) {
100 if x_1 < 2 || y_1 < 2 {
101 return (bits, false);
102 }
103 let mut u00 = 1;
104 let mut u01;
105 let mut u10;
106 let mut u11 = 1;
107 (u01, u10, bits) = if x_1 > y_1 || x_1 == y_1 && x_0 > y_0 {
108 (x_1, x_0) = Limb::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0);
109 if x_1 < 2 {
110 return (bits, false);
111 }
112 (1, 0, limbs_jacobi_update(bits, 1, 1))
113 } else {
114 (y_1, y_0) = Limb::xx_sub_yy_to_zz(y_1, y_0, x_1, x_0);
115 if y_1 < 2 {
116 return (bits, false);
117 }
118 (0, 1, limbs_jacobi_update(bits, 0, 1))
119 };
120 let mut subtract_a = x_1 < y_1;
121 let mut subtract_a_1 = false;
122 loop {
123 if !subtract_a {
124 assert!(x_1 >= y_1);
125 if x_1 == y_1 {
126 m.data[0][0] = u00;
127 m.data[0][1] = u01;
128 m.data[1][0] = u10;
129 m.data[1][1] = u11;
130 return (bits, true);
131 }
132 if x_1 < TWO_POW_HALF_WIDTH {
133 x_1 = (x_1 << HALF_WIDTH) + (x_0 >> HALF_WIDTH);
134 y_1 = (y_1 << HALF_WIDTH) + (y_0 >> HALF_WIDTH);
135 break;
136 }
137 // Subtract x -= q * y, and multiply m from the right by (1 q ; 0 1), affecting the
138 // second column of m.
139 assert!(x_1 > y_1);
140 (x_1, x_0) = Limb::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0);
141 if x_1 < 2 {
142 m.data[0][0] = u00;
143 m.data[0][1] = u01;
144 m.data[1][0] = u10;
145 m.data[1][1] = u11;
146 return (bits, true);
147 }
148 let bits_copy = bits;
149 bits = limbs_jacobi_update(
150 bits_copy,
151 1,
152 if x_1 <= y_1 {
153 // Use q = 1
154 u01 += u00;
155 u11 += u10;
156 1
157 } else {
158 let mut q;
159 (q, x_1, x_0) = limbs_gcd_div(x_1, x_0, y_1, y_0);
160 if x_1 < 2 {
161 // X is too small, but q is correct.
162 u01 += q * u00;
163 u11 += q * u10;
164 bits = limbs_jacobi_update(bits, 1, q.mod_power_of_2(2));
165 m.data[0][0] = u00;
166 m.data[0][1] = u01;
167 m.data[1][0] = u10;
168 m.data[1][1] = u11;
169 return (bits, true);
170 }
171 q += 1;
172 u01 += q * u00;
173 u11 += q * u10;
174 q.mod_power_of_2(2)
175 },
176 );
177 }
178 subtract_a = false;
179 assert!(y_1 >= x_1);
180 if x_1 == y_1 {
181 m.data[0][0] = u00;
182 m.data[0][1] = u01;
183 m.data[1][0] = u10;
184 m.data[1][1] = u11;
185 return (bits, true);
186 }
187 if y_1 < TWO_POW_HALF_WIDTH {
188 x_1 = (x_1 << HALF_WIDTH) + (x_0 >> HALF_WIDTH);
189 y_1 = (y_1 << HALF_WIDTH) + (y_0 >> HALF_WIDTH);
190 subtract_a_1 = true;
191 break;
192 }
193 // Subtract b -= q a, and multiply M from the right by (1 0 ; q 1), affecting the first
194 // column of M.
195 (y_1, y_0) = Limb::xx_sub_yy_to_zz(y_1, y_0, x_1, x_0);
196 if y_1 < 2 {
197 m.data[0][0] = u00;
198 m.data[0][1] = u01;
199 m.data[1][0] = u10;
200 m.data[1][1] = u11;
201 return (bits, true);
202 }
203 let bits_copy = bits;
204 bits = limbs_jacobi_update(
205 bits_copy,
206 0,
207 if y_1 <= x_1 {
208 // Use q = 1
209 u00 += u01;
210 u10 += u11;
211 1
212 } else {
213 let mut q;
214 (q, y_1, y_0) = limbs_gcd_div(y_1, y_0, x_1, x_0);
215 if y_1 < 2 {
216 // Y is too small, but q is correct.
217 u00 += q * u01;
218 u10 += q * u11;
219 bits = limbs_jacobi_update(bits, 0, q.mod_power_of_2(2));
220 m.data[0][0] = u00;
221 m.data[0][1] = u01;
222 m.data[1][0] = u10;
223 m.data[1][1] = u11;
224 return (bits, true);
225 }
226 q += 1;
227 u00 += q * u01;
228 u10 += q * u11;
229 q.mod_power_of_2(2)
230 },
231 );
232 }
233 // Since we discard the least significant half limb, we don't get a truly maximal m
234 // (corresponding to |x - y| < 2^(W+1)).
235 //
236 // Single precision loop
237 loop {
238 if !subtract_a_1 {
239 assert!(x_1 >= y_1);
240 if x_1 == y_1 {
241 break;
242 }
243 x_1 -= y_1;
244 if x_1 < TWICE_TWO_POW_HALF_WIDTH {
245 break;
246 }
247 let bits_copy = bits;
248 bits = limbs_jacobi_update(
249 bits_copy,
250 1,
251 if x_1 <= y_1 {
252 // Use q = 1
253 u01 += u00;
254 u11 += u10;
255 1
256 } else {
257 let (mut q, r) = x_1.div_mod(y_1);
258 x_1 = r;
259 if x_1 < TWICE_TWO_POW_HALF_WIDTH {
260 // X is too small, but q is correct.
261 u01 += q * u00;
262 u11 += q * u10;
263 bits = limbs_jacobi_update(bits, 1, q.mod_power_of_2(2));
264 break;
265 }
266 q += 1;
267 u01 += q * u00;
268 u11 += q * u10;
269 q.mod_power_of_2(2)
270 },
271 );
272 }
273 subtract_a_1 = false;
274 assert!(y_1 >= x_1);
275 if x_1 == y_1 {
276 break;
277 }
278 y_1 -= x_1;
279 if y_1 < TWICE_TWO_POW_HALF_WIDTH {
280 break;
281 }
282 let bits_copy = bits;
283 bits = limbs_jacobi_update(
284 bits_copy,
285 0,
286 if y_1 <= x_1 {
287 // Use q = 1
288 u00 += u01;
289 u10 += u11;
290 1
291 } else {
292 let mut q;
293 (q, y_1) = y_1.div_mod(x_1);
294 if y_1 < TWICE_TWO_POW_HALF_WIDTH {
295 // Y is too small, but q is correct.
296 u00 += q * u01;
297 u10 += q * u11;
298 bits = limbs_jacobi_update(bits, 0, q.mod_power_of_2(2));
299 break;
300 }
301 q += 1;
302 u00 += q * u01;
303 u10 += q * u11;
304 q.mod_power_of_2(2)
305 },
306 );
307 }
308 m.data[0][0] = u00;
309 m.data[0][1] = u01;
310 m.data[1][0] = u10;
311 m.data[1][1] = u11;
312 (bits, true)
313}
314
315// Perform a few steps, using some of `limbs_half_gcd_2_jacobi`, subtraction and division. Reduces
316// the size by almost one limb or more, but never below the given size s. Return new size for x and
317// y, or 0 if no more steps are possible.
318//
319// If `limbs_half_gcd_2_jacobi` succeeds, needs temporary space for
320// `limbs_half_gcd_matrix_mul_matrix_1`, m.n limbs, and
321// `limbs_half_gcd_matrix_1_mul_inverse_vector`, n limbs. If `limbs_half_gcd_2_jacobi` fails, needs
322// space for the quotient, qs_len <= n - s + 1 limbs, for and `update_q`, qs_len + (size of the
323// appropriate column of M) <= resulting size of m.
324//
325// If n is the input size to the calling hgcd, then s = floor(N / 2) + 1, m.n < N, qs_len + matrix
326// size <= n - s + 1 + n - s = 2 (n - s) + 1 < N, so N is sufficient.
327//
328// This is equivalent to `hgcd_jacobi_step` from `mpn/hgcd_jacobi.c`, GMP 6.2.1, where `bitsp` is
329// returned along with the `usize`.
330fn limbs_half_gcd_jacobi_step(
331 xs: &mut [Limb],
332 ys: &mut [Limb],
333 s: usize,
334 m: &mut HalfGcdMatrix,
335 mut bits: u8,
336 scratch: &mut [Limb],
337) -> (u8, usize) {
338 let n = xs.len();
339 assert_eq!(ys.len(), n);
340 let scratch = &mut scratch[..n];
341 assert!(n > s);
342 let mask = xs[n - 1] | ys[n - 1];
343 assert_ne!(mask, 0);
344 let (x_hi, x_lo, y_hi, y_lo) = if n == s + 1 {
345 if mask < 4 {
346 let u = limbs_gcd_subdivide_step(
347 xs,
348 ys,
349 s,
350 &mut HalfGcdJacobiContext {
351 m,
352 bits_mut: &mut bits,
353 },
354 scratch,
355 );
356 return (bits, u);
357 }
358 (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2])
359 } else if mask.get_highest_bit() {
360 (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2])
361 } else {
362 let shift = LeadingZeros::leading_zeros(mask);
363 (
364 extract_number(shift, xs[n - 1], xs[n - 2]),
365 extract_number(shift, xs[n - 2], xs[n - 3]),
366 extract_number(shift, ys[n - 1], ys[n - 2]),
367 extract_number(shift, ys[n - 2], ys[n - 3]),
368 )
369 };
370 // Try a `limbs_half_gcd_2_jacobi` step
371 let mut m1 = HalfGcdMatrix1::default();
372 let b;
373 (bits, b) = limbs_half_gcd_2_jacobi(x_hi, x_lo, y_hi, y_lo, &mut m1, bits);
374 if b {
375 // Multiply m <- m * m1
376 limbs_half_gcd_matrix_mul_matrix_1(m, &m1, scratch);
377 // Can't swap inputs, so we need to copy
378 scratch.copy_from_slice(xs);
379 // Multiply m1^(-1) (x;y)
380 (
381 bits,
382 limbs_half_gcd_matrix_1_mul_inverse_vector(&m1, xs, scratch, ys),
383 )
384 } else {
385 let u = limbs_gcd_subdivide_step(
386 xs,
387 ys,
388 s,
389 &mut HalfGcdJacobiContext {
390 m,
391 bits_mut: &mut bits,
392 },
393 scratch,
394 );
395 (bits, u)
396 }
397}
398
399// Reduces x, y until |x - y| fits in n / 2 + 1 limbs. Constructs matrix m with elements of size at
400// most (n + 1) / 2 - 1. Returns new size of x, y, or zero if no reduction is possible.
401//
402// Same scratch requirements as for `limbs_half_gcd`.
403//
404// This is equivalent to `mpn_hgcd_jacobi` from `mpn/hgcd_jacobi.c`, GMP 6.2.1, where `bitsp` is
405// also returned.
406fn limbs_half_gcd_jacobi(
407 xs: &mut [Limb],
408 ys: &mut [Limb],
409 m: &mut HalfGcdMatrix<'_>,
410 mut bits: u8,
411 scratch: &mut [Limb],
412) -> (u8, usize) {
413 let mut n = xs.len();
414 assert_eq!(ys.len(), n);
415 let s = (n >> 1) + 1;
416 let mut success = false;
417 assert!(s < n);
418 assert!(xs[n - 1] != 0 || ys[n - 1] != 0);
419 assert!(((n + 1) >> 1) - 1 < s);
420 if n >= HGCD_THRESHOLD {
421 let n2 = ((3 * n) >> 2) + 1;
422 let p = n >> 1;
423 let mut nn;
424 (bits, nn) = limbs_half_gcd_jacobi(&mut xs[p..n], &mut ys[p..n], m, bits, scratch);
425 if nn != 0 {
426 // Needs 2 * (p + m.n) <= 2 * (floor(n / 2) + ceiling(n / 2) - 1) = 2 * (n - 1)
427 n = limbs_half_gcd_matrix_adjust(m, p + nn, xs, ys, p, scratch);
428 success = true;
429 }
430 while n > n2 {
431 // Needs n + 1 storage
432 (bits, nn) =
433 limbs_half_gcd_jacobi_step(&mut xs[..n], &mut ys[..n], s, m, bits, scratch);
434 if nn == 0 {
435 return (bits, if success { n } else { 0 });
436 }
437 n = nn;
438 success = true;
439 }
440 if n > s + 2 {
441 let p = 2 * s - n + 1;
442 let scratch_len = limbs_half_gcd_matrix_init_scratch_len(n - p);
443 let (scratch_lo, scratch_hi) = scratch.split_at_mut(scratch_len);
444 let mut m1 = HalfGcdMatrix::init(n - p, scratch_lo);
445 (bits, nn) =
446 limbs_half_gcd_jacobi(&mut xs[p..n], &mut ys[p..n], &mut m1, bits, scratch_hi);
447 if nn != 0 {
448 // We always have max(m) > 2^(-(W + 1)) * max(m1)
449 assert!(m.n + 2 >= m1.n);
450 // Furthermore, assume m ends with a quotient (1, q; 0, 1); then either q or q + 1
451 // is a correct quotient, and m1 will start with either (1, 0; 1, 1) or (2, 1; 1,
452 // 1). This rules out the case that the size of m * m1 is much smaller than the
453 // expected m.n + m1.n.
454 assert!(m.n + m1.n < m.s);
455 // Needs 2 * (p + m.n) <= 2 * (2 * s - nn + 1 + nn - s - 1) = 2 * s <= 2 * (floor(n
456 // / 2) + 1) <= n + 2.
457 n = limbs_half_gcd_matrix_adjust(&m1, p + nn, xs, ys, p, scratch_hi);
458 // We need a bound for of m.n + m1.n. Let n be the original input size. Then
459 //
460 // ceiling(n / 2) - 1 >= size of product >= m.n + m1.n - 2
461 //
462 // and it follows that
463 //
464 // m.n + m1.n <= ceiling(n / 2) + 1
465 //
466 // Then 3 * (m.n + m1.n) + 5 <= 3 * ceiling(n / 2) + 8 is the amount of needed
467 // scratch space.
468 limbs_half_gcd_matrix_mul_matrix(m, &m1, scratch_hi);
469 success = true;
470 }
471 }
472 }
473 loop {
474 // Needs s + 3 < n
475 let nn;
476 (bits, nn) = limbs_half_gcd_jacobi_step(&mut xs[..n], &mut ys[..n], s, m, bits, scratch);
477 if nn == 0 {
478 return (bits, if success { n } else { 0 });
479 }
480 n = nn;
481 success = true;
482 }
483}
484
485// This is equivalent to `CHOOSE_P` from `mpn/jacobi.c`, GMP 6.2.1.
486const fn choose_p(n: usize) -> usize {
487 (n << 1) / 3
488}
489
490const BITS_FAIL: u8 = 31;
491
492// This is equivalent to `mpn_jacobi_finish` from `gmp-impl.h`, GMP 6.2.1, which also handles the
493// `bits == BITS_FAIL` case.
494fn limbs_jacobi_finish(bits: u8) -> i8 {
495 // (a, b) = (1,0) or (0,1)
496 if bits == BITS_FAIL {
497 0
498 } else if bits.even() {
499 1
500 } else {
501 -1
502 }
503}
504
505// This is equivalent to `mpn_jacobi_init` from `gmp-impl.h`, GMP 6.2.1.
506pub_crate_test! {limbs_jacobi_symbol_init(a: Limb, b: Limb, s: u8) -> u8 {
507 assert!(b.odd());
508 assert!(s <= 1);
509 u8::wrapping_from((a.mod_power_of_2(2) << 2) + (b & 2)) + s
510}}
511
512struct JacobiContext<'a> {
513 bits_mut: &'a mut u8,
514}
515
516impl GcdSubdivideStepContext for JacobiContext<'_> {
517 // This is equivalent to `jacobi_hook` from `mpn/jacobi.c`, GMP 6.2.1.
518 fn gcd_subdiv_step_hook(
519 &mut self,
520 gs: Option<&[Limb]>,
521 qs: Option<&mut [Limb]>,
522 qs_len: usize,
523 d: i8,
524 ) {
525 if let Some(gs) = gs {
526 let gs_len = gs.len();
527 assert_ne!(gs_len, 0);
528 if gs_len != 1 || gs[0] != 1 {
529 *self.bits_mut = BITS_FAIL;
530 return;
531 }
532 }
533 if let Some(qs) = qs {
534 assert_ne!(qs_len, 0);
535 assert!(d >= 0);
536 *self.bits_mut = limbs_jacobi_update(
537 *self.bits_mut,
538 u8::wrapping_from(d),
539 qs[0].mod_power_of_2(2),
540 );
541 } else {
542 fail_on_untested_path("JacobiContext::gcd_subdiv_step_hook, qs == None");
543 }
544 }
545}
546
547const JACOBI_DC_THRESHOLD: usize = GCD_DC_THRESHOLD;
548
549// # Worst-case complexity
550// $T(n) = O(n (\log n)^2 \log\log n)$
551//
552// $M(n) = O(n \log n)$
553//
554// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
555//
556// This is equivalent to `mpn_jacobi_n` from `mpn/jacobi.c`, GMP 6.2.1.
557pub_crate_test! {
558 limbs_jacobi_symbol_same_length(xs: &mut [Limb], ys: &mut [Limb], mut bits: u8) -> i8 {
559 let mut n = xs.len();
560 assert_eq!(ys.len(), n);
561 assert_ne!(n, 0);
562 assert!(xs[n - 1] != 0 || ys[n - 1] != 0);
563 assert!((ys[0] | xs[0]).odd());
564 let mut scratch_len = limbs_gcd_subdivide_step_scratch_len(n);
565 if n >= JACOBI_DC_THRESHOLD {
566 let p = choose_p(n);
567 let matrix_scratch_len = limbs_half_gcd_matrix_init_scratch_len(n - p);
568 let hgcd_scratch_len = limbs_half_gcd_scratch_len(n - p);
569 let update_scratch_len = p + n - 1;
570 let dc_scratch_len = matrix_scratch_len + max(hgcd_scratch_len, update_scratch_len);
571 assert!(dc_scratch_len > scratch_len);
572 scratch_len = dc_scratch_len;
573 }
574 let mut scratch = vec![0; scratch_len];
575 let mut xs: &mut [Limb] = &mut xs[..];
576 let mut ys: &mut [Limb] = &mut ys[..];
577 let mut scratch: &mut [Limb] = &mut scratch;
578 while n >= JACOBI_DC_THRESHOLD {
579 let p = (n << 1) / 3;
580 let matrix_scratch_len = limbs_half_gcd_matrix_init_scratch_len(n - p);
581 let (scratch_lo, scratch_hi) = scratch.split_at_mut(matrix_scratch_len);
582 let mut m = HalfGcdMatrix::init(n - p, scratch_lo);
583 let nn;
584 (bits, nn) = limbs_half_gcd_jacobi(&mut xs[p..n], &mut ys[p..n], &mut m, bits, scratch_hi);
585 if nn != 0 {
586 assert!(m.n <= (n - p - 1) >> 1);
587 assert!(m.n + p <= (p + n - 1) >> 1);
588 // Temporary storage 2 (p + M->n) <= p + n - 1.
589 n = limbs_half_gcd_matrix_adjust(&m, p + nn, xs, ys, p, scratch_hi);
590 } else {
591 // Temporary storage n
592 n = limbs_gcd_subdivide_step(
593 &mut xs[..n],
594 &mut ys[..n],
595 0,
596 &mut JacobiContext {
597 bits_mut: &mut bits,
598 },
599 scratch,
600 );
601 if n == 0 {
602 return limbs_jacobi_finish(bits);
603 }
604 }
605 }
606 while n > 2 {
607 let mask = xs[n - 1] | ys[n - 1];
608 assert_ne!(mask, 0);
609 let (xs_hi, xs_lo, ys_hi, ys_lo) = if mask.get_highest_bit() {
610 (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2])
611 } else {
612 let shift = LeadingZeros::leading_zeros(mask);
613 (
614 extract_number(shift, xs[n - 1], xs[n - 2]),
615 extract_number(shift, xs[n - 2], xs[n - 3]),
616 extract_number(shift, ys[n - 1], ys[n - 2]),
617 extract_number(shift, ys[n - 2], ys[n - 3]),
618 )
619 };
620 let mut m = HalfGcdMatrix1::default();
621 // Try a `limbs_half_gcd_2_jacobi` step
622 let b;
623 (bits, b) = limbs_half_gcd_2_jacobi(xs_hi, xs_lo, ys_hi, ys_lo, &mut m, bits);
624 if b {
625 n = limbs_half_gcd_matrix_1_mul_inverse_vector(
626 &m,
627 &mut scratch[..n],
628 &xs[..n],
629 &mut ys[..n],
630 );
631 swap(&mut xs, &mut scratch);
632 } else {
633 // `limbs_half_gcd_2_jacobi` has failed. Then either one of x or y is very small, or the
634 // difference is very small. Perform one subtraction followed by one division.
635 n = limbs_gcd_subdivide_step(
636 &mut xs[..n],
637 &mut ys[..n],
638 0,
639 &mut JacobiContext {
640 bits_mut: &mut bits,
641 },
642 scratch,
643 );
644 if n == 0 {
645 return limbs_jacobi_finish(bits);
646 }
647 }
648 }
649 if bits >= 16 {
650 swap(&mut xs, &mut ys);
651 }
652 assert!(ys[0].odd());
653 let j = if n == 1 {
654 let x_lo = xs[0];
655 let y_lo = ys[0];
656 if y_lo == 1 {
657 1
658 } else {
659 x_lo.jacobi_symbol(y_lo)
660 }
661 } else {
662 DoubleLimb::join_halves(xs[1], xs[0]).jacobi_symbol(DoubleLimb::join_halves(ys[1], ys[0]))
663 };
664 if bits.even() {
665 j
666 } else {
667 -j
668 }
669}}
670
671impl LegendreSymbol<Self> for Natural {
672 /// Computes the Legendre symbol of two [`Natural`]s, taking both by value.
673 ///
674 /// This implementation is identical to that of [`JacobiSymbol`], since there is no
675 /// computational benefit to requiring that the denominator be prime.
676 ///
677 /// $$
678 /// f(x, y) = \left ( \frac{x}{y} \right ).
679 /// $$
680 ///
681 /// # Worst-case complexity
682 /// $T(n) = O(n (\log n)^2 \log\log n)$
683 ///
684 /// $M(n) = O(n \log n)$
685 ///
686 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
687 /// other.significant_bits())`.
688 ///
689 /// # Panics
690 /// Panics if `other` is even.
691 ///
692 /// # Examples
693 /// ```
694 /// use malachite_base::num::arithmetic::traits::LegendreSymbol;
695 /// use malachite_nz::natural::Natural;
696 ///
697 /// assert_eq!(Natural::from(10u32).legendre_symbol(Natural::from(5u32)), 0);
698 /// assert_eq!(Natural::from(7u32).legendre_symbol(Natural::from(5u32)), -1);
699 /// assert_eq!(Natural::from(11u32).legendre_symbol(Natural::from(5u32)), 1);
700 /// ```
701 #[inline]
702 fn legendre_symbol(self, other: Self) -> i8 {
703 assert_ne!(other, 0u32);
704 assert!(other.odd());
705 (&self).kronecker_symbol(&other)
706 }
707}
708
709impl<'a> LegendreSymbol<&'a Self> for Natural {
710 /// Computes the Legendre symbol of two [`Natural`]s, taking the first by value and the second
711 /// by reference.
712 ///
713 /// This implementation is identical to that of [`JacobiSymbol`], since there is no
714 /// computational benefit to requiring that the denominator be prime.
715 ///
716 /// $$
717 /// f(x, y) = \left ( \frac{x}{y} \right ).
718 /// $$
719 ///
720 /// # Worst-case complexity
721 /// $T(n) = O(n (\log n)^2 \log\log n)$
722 ///
723 /// $M(n) = O(n \log n)$
724 ///
725 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
726 /// other.significant_bits())`.
727 ///
728 /// # Panics
729 /// Panics if `other` is even.
730 ///
731 /// # Examples
732 /// ```
733 /// use malachite_base::num::arithmetic::traits::LegendreSymbol;
734 /// use malachite_nz::natural::Natural;
735 ///
736 /// assert_eq!(
737 /// Natural::from(10u32).legendre_symbol(&Natural::from(5u32)),
738 /// 0
739 /// );
740 /// assert_eq!(
741 /// Natural::from(7u32).legendre_symbol(&Natural::from(5u32)),
742 /// -1
743 /// );
744 /// assert_eq!(
745 /// Natural::from(11u32).legendre_symbol(&Natural::from(5u32)),
746 /// 1
747 /// );
748 /// ```
749 #[inline]
750 fn legendre_symbol(self, other: &'a Self) -> i8 {
751 assert_ne!(*other, 0u32);
752 assert!(other.odd());
753 (&self).kronecker_symbol(other)
754 }
755}
756
757impl LegendreSymbol<Natural> for &Natural {
758 /// Computes the Legendre symbol of two [`Natural`]s, taking both the first by reference and the
759 /// second by value.
760 ///
761 /// This implementation is identical to that of [`JacobiSymbol`], since there is no
762 /// computational benefit to requiring that the denominator be prime.
763 ///
764 /// $$
765 /// f(x, y) = \left ( \frac{x}{y} \right ).
766 /// $$
767 ///
768 /// # Worst-case complexity
769 /// $T(n) = O(n (\log n)^2 \log\log n)$
770 ///
771 /// $M(n) = O(n \log n)$
772 ///
773 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
774 /// other.significant_bits())`.
775 ///
776 /// # Panics
777 /// Panics if `other` is even.
778 ///
779 /// # Examples
780 /// ```
781 /// use malachite_base::num::arithmetic::traits::LegendreSymbol;
782 /// use malachite_nz::natural::Natural;
783 ///
784 /// assert_eq!(
785 /// (&Natural::from(10u32)).legendre_symbol(Natural::from(5u32)),
786 /// 0
787 /// );
788 /// assert_eq!(
789 /// (&Natural::from(7u32)).legendre_symbol(Natural::from(5u32)),
790 /// -1
791 /// );
792 /// assert_eq!(
793 /// (&Natural::from(11u32)).legendre_symbol(Natural::from(5u32)),
794 /// 1
795 /// );
796 /// ```
797 #[inline]
798 fn legendre_symbol(self, other: Natural) -> i8 {
799 assert_ne!(other, 0u32);
800 assert!(other.odd());
801 self.kronecker_symbol(&other)
802 }
803}
804
805impl LegendreSymbol<&Natural> for &Natural {
806 /// Computes the Legendre symbol of two [`Natural`]s, taking both by reference.
807 ///
808 /// This implementation is identical to that of [`JacobiSymbol`], since there is no
809 /// computational benefit to requiring that the denominator be prime.
810 ///
811 /// $$
812 /// f(x, y) = \left ( \frac{x}{y} \right ).
813 /// $$
814 ///
815 /// # Worst-case complexity
816 /// $T(n) = O(n (\log n)^2 \log\log n)$
817 ///
818 /// $M(n) = O(n \log n)$
819 ///
820 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
821 /// other.significant_bits())`.
822 ///
823 /// # Panics
824 /// Panics if `other` is even.
825 ///
826 /// # Examples
827 /// ```
828 /// use malachite_base::num::arithmetic::traits::LegendreSymbol;
829 /// use malachite_nz::natural::Natural;
830 ///
831 /// assert_eq!(
832 /// (&Natural::from(10u32)).legendre_symbol(&Natural::from(5u32)),
833 /// 0
834 /// );
835 /// assert_eq!(
836 /// (&Natural::from(7u32)).legendre_symbol(&Natural::from(5u32)),
837 /// -1
838 /// );
839 /// assert_eq!(
840 /// (&Natural::from(11u32)).legendre_symbol(&Natural::from(5u32)),
841 /// 1
842 /// );
843 /// ```
844 #[inline]
845 fn legendre_symbol(self, other: &Natural) -> i8 {
846 assert_ne!(*other, 0u32);
847 assert!(other.odd());
848 self.kronecker_symbol(other)
849 }
850}
851
852impl JacobiSymbol<Self> for Natural {
853 /// Computes the Jacobi symbol of two [`Natural`]s, taking both by value.
854 ///
855 /// $$
856 /// f(x, y) = \left ( \frac{x}{y} \right ).
857 /// $$
858 ///
859 /// # Worst-case complexity
860 /// $T(n) = O(n (\log n)^2 \log\log n)$
861 ///
862 /// $M(n) = O(n \log n)$
863 ///
864 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
865 /// other.significant_bits())`.
866 ///
867 /// # Panics
868 /// Panics if `other` is even.
869 ///
870 /// # Examples
871 /// ```
872 /// use malachite_base::num::arithmetic::traits::JacobiSymbol;
873 /// use malachite_nz::natural::Natural;
874 ///
875 /// assert_eq!(Natural::from(10u32).jacobi_symbol(Natural::from(5u32)), 0);
876 /// assert_eq!(Natural::from(7u32).jacobi_symbol(Natural::from(5u32)), -1);
877 /// assert_eq!(Natural::from(11u32).jacobi_symbol(Natural::from(5u32)), 1);
878 /// assert_eq!(Natural::from(11u32).jacobi_symbol(Natural::from(9u32)), 1);
879 /// ```
880 #[inline]
881 fn jacobi_symbol(self, other: Self) -> i8 {
882 assert_ne!(other, 0u32);
883 assert!(other.odd());
884 (&self).kronecker_symbol(&other)
885 }
886}
887
888impl<'a> JacobiSymbol<&'a Self> for Natural {
889 /// Computes the Jacobi symbol of two [`Natural`]s, taking the first by value and the second by
890 /// reference.
891 ///
892 /// $$
893 /// f(x, y) = \left ( \frac{x}{y} \right ).
894 /// $$
895 ///
896 /// # Worst-case complexity
897 /// $T(n) = O(n (\log n)^2 \log\log n)$
898 ///
899 /// $M(n) = O(n \log n)$
900 ///
901 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
902 /// other.significant_bits())`.
903 ///
904 /// # Panics
905 /// Panics if `other` is even.
906 ///
907 /// # Examples
908 /// ```
909 /// use malachite_base::num::arithmetic::traits::JacobiSymbol;
910 /// use malachite_nz::natural::Natural;
911 ///
912 /// assert_eq!(Natural::from(10u32).jacobi_symbol(&Natural::from(5u32)), 0);
913 /// assert_eq!(Natural::from(7u32).jacobi_symbol(&Natural::from(5u32)), -1);
914 /// assert_eq!(Natural::from(11u32).jacobi_symbol(&Natural::from(5u32)), 1);
915 /// assert_eq!(Natural::from(11u32).jacobi_symbol(&Natural::from(9u32)), 1);
916 /// ```
917 #[inline]
918 fn jacobi_symbol(self, other: &'a Self) -> i8 {
919 assert_ne!(*other, 0u32);
920 assert!(other.odd());
921 (&self).kronecker_symbol(other)
922 }
923}
924
925impl JacobiSymbol<Natural> for &Natural {
926 /// Computes the Jacobi symbol of two [`Natural`]s, taking the first by reference and the second
927 /// by value.
928 ///
929 /// $$
930 /// f(x, y) = \left ( \frac{x}{y} \right ).
931 /// $$
932 ///
933 /// # Worst-case complexity
934 /// $T(n) = O(n (\log n)^2 \log\log n)$
935 ///
936 /// $M(n) = O(n \log n)$
937 ///
938 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
939 /// other.significant_bits())`.
940 ///
941 /// # Panics
942 /// Panics if `other` is even.
943 ///
944 /// # Examples
945 /// ```
946 /// use malachite_base::num::arithmetic::traits::JacobiSymbol;
947 /// use malachite_nz::natural::Natural;
948 ///
949 /// assert_eq!(
950 /// (&Natural::from(10u32)).jacobi_symbol(Natural::from(5u32)),
951 /// 0
952 /// );
953 /// assert_eq!(
954 /// (&Natural::from(7u32)).jacobi_symbol(Natural::from(5u32)),
955 /// -1
956 /// );
957 /// assert_eq!(
958 /// (&Natural::from(11u32)).jacobi_symbol(Natural::from(5u32)),
959 /// 1
960 /// );
961 /// assert_eq!(
962 /// (&Natural::from(11u32)).jacobi_symbol(Natural::from(9u32)),
963 /// 1
964 /// );
965 /// ```
966 #[inline]
967 fn jacobi_symbol(self, other: Natural) -> i8 {
968 assert_ne!(other, 0u32);
969 assert!(other.odd());
970 self.kronecker_symbol(&other)
971 }
972}
973
974impl JacobiSymbol<&Natural> for &Natural {
975 /// Computes the Jacobi symbol of two [`Natural`]s, taking both by reference.
976 ///
977 /// $$
978 /// f(x, y) = \left ( \frac{x}{y} \right ).
979 /// $$
980 ///
981 /// # Worst-case complexity
982 /// $T(n) = O(n (\log n)^2 \log\log n)$
983 ///
984 /// $M(n) = O(n \log n)$
985 ///
986 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
987 /// other.significant_bits())`.
988 ///
989 /// # Panics
990 /// Panics if `other` is even.
991 ///
992 /// # Examples
993 /// ```
994 /// use malachite_base::num::arithmetic::traits::JacobiSymbol;
995 /// use malachite_nz::natural::Natural;
996 ///
997 /// assert_eq!(
998 /// (&Natural::from(10u32)).jacobi_symbol(&Natural::from(5u32)),
999 /// 0
1000 /// );
1001 /// assert_eq!(
1002 /// (&Natural::from(7u32)).jacobi_symbol(&Natural::from(5u32)),
1003 /// -1
1004 /// );
1005 /// assert_eq!(
1006 /// (&Natural::from(11u32)).jacobi_symbol(&Natural::from(5u32)),
1007 /// 1
1008 /// );
1009 /// assert_eq!(
1010 /// (&Natural::from(11u32)).jacobi_symbol(&Natural::from(9u32)),
1011 /// 1
1012 /// );
1013 /// ```
1014 #[inline]
1015 fn jacobi_symbol(self, other: &Natural) -> i8 {
1016 assert_ne!(*other, 0u32);
1017 assert!(other.odd());
1018 self.kronecker_symbol(other)
1019 }
1020}
1021
1022impl KroneckerSymbol<Self> for Natural {
1023 /// Computes the Kronecker symbol of two [`Natural`]s, taking both by value.
1024 ///
1025 /// $$
1026 /// f(x, y) = \left ( \frac{x}{y} \right ).
1027 /// $$
1028 ///
1029 /// # Worst-case complexity
1030 /// $T(n) = O(n (\log n)^2 \log\log n)$
1031 ///
1032 /// $M(n) = O(n \log n)$
1033 ///
1034 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1035 /// other.significant_bits())`.
1036 ///
1037 /// # Examples
1038 /// ```
1039 /// use malachite_base::num::arithmetic::traits::KroneckerSymbol;
1040 /// use malachite_nz::natural::Natural;
1041 ///
1042 /// assert_eq!(
1043 /// Natural::from(10u32).kronecker_symbol(Natural::from(5u32)),
1044 /// 0
1045 /// );
1046 /// assert_eq!(
1047 /// Natural::from(7u32).kronecker_symbol(Natural::from(5u32)),
1048 /// -1
1049 /// );
1050 /// assert_eq!(
1051 /// Natural::from(11u32).kronecker_symbol(Natural::from(5u32)),
1052 /// 1
1053 /// );
1054 /// assert_eq!(
1055 /// Natural::from(11u32).kronecker_symbol(Natural::from(9u32)),
1056 /// 1
1057 /// );
1058 /// assert_eq!(
1059 /// Natural::from(11u32).kronecker_symbol(Natural::from(8u32)),
1060 /// -1
1061 /// );
1062 /// ```
1063 #[inline]
1064 fn kronecker_symbol(self, other: Self) -> i8 {
1065 (&self).kronecker_symbol(&other)
1066 }
1067}
1068
1069impl<'a> KroneckerSymbol<&'a Self> for Natural {
1070 /// Computes the Kronecker symbol of two [`Natural`]s, taking the first by value and the second
1071 /// by reference.
1072 ///
1073 /// $$
1074 /// f(x, y) = \left ( \frac{x}{y} \right ).
1075 /// $$
1076 ///
1077 /// # Worst-case complexity
1078 /// $T(n) = O(n (\log n)^2 \log\log n)$
1079 ///
1080 /// $M(n) = O(n \log n)$
1081 ///
1082 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1083 /// other.significant_bits())`.
1084 ///
1085 /// # Examples
1086 /// ```
1087 /// use malachite_base::num::arithmetic::traits::KroneckerSymbol;
1088 /// use malachite_nz::natural::Natural;
1089 ///
1090 /// assert_eq!(
1091 /// Natural::from(10u32).kronecker_symbol(&Natural::from(5u32)),
1092 /// 0
1093 /// );
1094 /// assert_eq!(
1095 /// Natural::from(7u32).kronecker_symbol(&Natural::from(5u32)),
1096 /// -1
1097 /// );
1098 /// assert_eq!(
1099 /// Natural::from(11u32).kronecker_symbol(&Natural::from(5u32)),
1100 /// 1
1101 /// );
1102 /// assert_eq!(
1103 /// Natural::from(11u32).kronecker_symbol(&Natural::from(9u32)),
1104 /// 1
1105 /// );
1106 /// assert_eq!(
1107 /// Natural::from(11u32).kronecker_symbol(&Natural::from(8u32)),
1108 /// -1
1109 /// );
1110 /// ```
1111 #[inline]
1112 fn kronecker_symbol(self, other: &'a Self) -> i8 {
1113 (&self).kronecker_symbol(other)
1114 }
1115}
1116
1117impl KroneckerSymbol<Natural> for &Natural {
1118 /// Computes the Kronecker symbol of two [`Natural`]s, taking the first by reference and the
1119 /// second by value.
1120 ///
1121 /// $$
1122 /// f(x, y) = \left ( \frac{x}{y} \right ).
1123 /// $$
1124 ///
1125 /// # Worst-case complexity
1126 /// $T(n) = O(n (\log n)^2 \log\log n)$
1127 ///
1128 /// $M(n) = O(n \log n)$
1129 ///
1130 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1131 /// other.significant_bits())`.
1132 ///
1133 /// # Examples
1134 /// ```
1135 /// use malachite_base::num::arithmetic::traits::KroneckerSymbol;
1136 /// use malachite_nz::natural::Natural;
1137 ///
1138 /// assert_eq!(
1139 /// (&Natural::from(10u32)).kronecker_symbol(Natural::from(5u32)),
1140 /// 0
1141 /// );
1142 /// assert_eq!(
1143 /// (&Natural::from(7u32)).kronecker_symbol(Natural::from(5u32)),
1144 /// -1
1145 /// );
1146 /// assert_eq!(
1147 /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(5u32)),
1148 /// 1
1149 /// );
1150 /// assert_eq!(
1151 /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(9u32)),
1152 /// 1
1153 /// );
1154 /// assert_eq!(
1155 /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(8u32)),
1156 /// -1
1157 /// );
1158 /// ```
1159 #[inline]
1160 fn kronecker_symbol(self, other: Natural) -> i8 {
1161 self.kronecker_symbol(&other)
1162 }
1163}
1164
1165impl KroneckerSymbol<&Natural> for &Natural {
1166 /// Computes the Kronecker symbol of two [`Natural`]s, taking both by reference.
1167 ///
1168 /// $$
1169 /// f(x, y) = \left ( \frac{x}{y} \right ).
1170 /// $$
1171 ///
1172 /// # Worst-case complexity
1173 /// $T(n) = O(n (\log n)^2 \log\log n)$
1174 ///
1175 /// $M(n) = O(n \log n)$
1176 ///
1177 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1178 /// other.significant_bits())`.
1179 ///
1180 /// # Examples
1181 /// ```
1182 /// use malachite_base::num::arithmetic::traits::KroneckerSymbol;
1183 /// use malachite_nz::natural::Natural;
1184 ///
1185 /// assert_eq!(
1186 /// (&Natural::from(10u32)).kronecker_symbol(Natural::from(5u32)),
1187 /// 0
1188 /// );
1189 /// assert_eq!(
1190 /// (&Natural::from(7u32)).kronecker_symbol(Natural::from(5u32)),
1191 /// -1
1192 /// );
1193 /// assert_eq!(
1194 /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(5u32)),
1195 /// 1
1196 /// );
1197 /// assert_eq!(
1198 /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(9u32)),
1199 /// 1
1200 /// );
1201 /// assert_eq!(
1202 /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(8u32)),
1203 /// -1
1204 /// );
1205 /// ```
1206 fn kronecker_symbol(self, other: &Natural) -> i8 {
1207 match (self, other) {
1208 (x, &Natural::ZERO) => i8::from(*x == 1u32),
1209 (&Natural::ZERO, y) => i8::from(*y == 1u32),
1210 (Natural(Small(x)), Natural(Small(y))) => {
1211 limbs_kronecker_symbol_single(true, *x, true, *y)
1212 }
1213 (Natural(Small(x)), Natural(Large(ys))) => {
1214 limbs_kronecker_symbol(true, &[*x], true, ys)
1215 }
1216 (Natural(Large(xs)), Natural(Small(y))) => {
1217 limbs_kronecker_symbol(true, xs, true, &[*y])
1218 }
1219 (Natural(Large(xs)), Natural(Large(ys))) => limbs_kronecker_symbol(true, xs, true, ys),
1220 }
1221 }
1222}