Skip to main content

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}