Blame mpz/jacobi.c

Packit 5c3484
/* mpz_jacobi, mpz_legendre, mpz_kronecker -- mpz/mpz Jacobi symbols.
Packit 5c3484
Packit 5c3484
Copyright 2000-2002, 2005, 2010-2012 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library.
Packit 5c3484
Packit 5c3484
The GNU MP Library is free software; you can redistribute it and/or modify
Packit 5c3484
it under the terms of either:
Packit 5c3484
Packit 5c3484
  * the GNU Lesser General Public License as published by the Free
Packit 5c3484
    Software Foundation; either version 3 of the License, or (at your
Packit 5c3484
    option) any later version.
Packit 5c3484
Packit 5c3484
or
Packit 5c3484
Packit 5c3484
  * the GNU General Public License as published by the Free Software
Packit 5c3484
    Foundation; either version 2 of the License, or (at your option) any
Packit 5c3484
    later version.
Packit 5c3484
Packit 5c3484
or both in parallel, as here.
Packit 5c3484
Packit 5c3484
The GNU MP Library is distributed in the hope that it will be useful, but
Packit 5c3484
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 5c3484
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 5c3484
for more details.
Packit 5c3484
Packit 5c3484
You should have received copies of the GNU General Public License and the
Packit 5c3484
GNU Lesser General Public License along with the GNU MP Library.  If not,
Packit 5c3484
see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
#include <stdio.h>
Packit 5c3484
#include "gmp.h"
Packit 5c3484
#include "gmp-impl.h"
Packit 5c3484
#include "longlong.h"
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* This code does triple duty as mpz_jacobi, mpz_legendre and
Packit 5c3484
   mpz_kronecker. For ABI compatibility, the link symbol is
Packit 5c3484
   __gmpz_jacobi, not __gmpz_kronecker, even though the latter would
Packit 5c3484
   be more logical.
Packit 5c3484
Packit 5c3484
   mpz_jacobi could assume b is odd, but the improvements from that seem
Packit 5c3484
   small compared to other operations, and anything significant should be
Packit 5c3484
   checked at run-time since we'd like odd b to go fast in mpz_kronecker
Packit 5c3484
   too.
Packit 5c3484
Packit 5c3484
   mpz_legendre could assume b is an odd prime, but knowing this doesn't
Packit 5c3484
   present any obvious benefits.  Result 0 wouldn't arise (unless "a" is a
Packit 5c3484
   multiple of b), but the checking for that takes little time compared to
Packit 5c3484
   other operations.
Packit 5c3484
Packit 5c3484
   Enhancements:
Packit 5c3484
Packit 5c3484
   mpn_bdiv_qr should be used instead of mpn_tdiv_qr.
Packit 5c3484
Packit 5c3484
*/
Packit 5c3484
Packit 5c3484
int
Packit 5c3484
mpz_jacobi (mpz_srcptr a, mpz_srcptr b)
Packit 5c3484
{
Packit 5c3484
  mp_srcptr  asrcp, bsrcp;
Packit 5c3484
  mp_size_t  asize, bsize;
Packit 5c3484
  mp_limb_t  alow, blow;
Packit 5c3484
  mp_ptr     ap, bp;
Packit 5c3484
  unsigned   btwos;
Packit 5c3484
  int        result_bit1;
Packit 5c3484
  int        res;
Packit 5c3484
  TMP_DECL;
Packit 5c3484
Packit 5c3484
  asize = SIZ(a);
Packit 5c3484
  asrcp = PTR(a);
Packit 5c3484
  alow = asrcp[0];
Packit 5c3484
Packit 5c3484
  bsize = SIZ(b);
Packit 5c3484
  bsrcp = PTR(b);
Packit 5c3484
  blow = bsrcp[0];
Packit 5c3484
Packit 5c3484
  /* The MPN jacobi functions require positive a and b, and b odd. So
Packit 5c3484
     we must to handle the cases of a or b zero, then signs, and then
Packit 5c3484
     the case of even b.
Packit 5c3484
  */
Packit 5c3484
Packit 5c3484
  if (bsize == 0)
Packit 5c3484
    /* (a/0) = [ a = 1 or a = -1 ] */
Packit 5c3484
    return JACOBI_LS0 (alow, asize);
Packit 5c3484
Packit 5c3484
  if (asize == 0)
Packit 5c3484
    /* (0/b) = [ b = 1 or b = - 1 ] */
Packit 5c3484
    return JACOBI_0LS (blow, bsize);
Packit 5c3484
Packit 5c3484
  if ( (((alow | blow) & 1) == 0))
Packit 5c3484
    /* Common factor of 2 ==> (a/b) = 0 */
Packit 5c3484
    return 0;
Packit 5c3484
Packit 5c3484
  if (bsize < 0)
Packit 5c3484
    {
Packit 5c3484
      /* (a/-1) = -1 if a < 0, +1 if a >= 0 */
Packit 5c3484
      result_bit1 = (asize < 0) << 1;
Packit 5c3484
      bsize = -bsize;
Packit 5c3484
    }
Packit 5c3484
  else
Packit 5c3484
    result_bit1 = 0;
Packit 5c3484
Packit 5c3484
  JACOBI_STRIP_LOW_ZEROS (result_bit1, alow, bsrcp, bsize, blow);
Packit 5c3484
Packit 5c3484
  count_trailing_zeros (btwos, blow);
Packit 5c3484
  blow >>= btwos;
Packit 5c3484
Packit 5c3484
  if (bsize > 1 && btwos > 0)
Packit 5c3484
    {
Packit 5c3484
      mp_limb_t b1 = bsrcp[1];
Packit 5c3484
      blow |= b1 << (GMP_NUMB_BITS - btwos);
Packit 5c3484
      if (bsize == 2 && (b1 >> btwos) == 0)
Packit 5c3484
	bsize = 1;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  if (asize < 0)
Packit 5c3484
    {
Packit 5c3484
      /* (-1/b) = -1 iff b = 3 (mod 4) */
Packit 5c3484
      result_bit1 ^= JACOBI_N1B_BIT1(blow);
Packit 5c3484
      asize = -asize;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  JACOBI_STRIP_LOW_ZEROS (result_bit1, blow, asrcp, asize, alow);
Packit 5c3484
Packit 5c3484
  /* Ensure asize >= bsize. Take advantage of the generalized
Packit 5c3484
     reciprocity law (a/b*2^n) = (b*2^n / a) * RECIP(a,b) */
Packit 5c3484
Packit 5c3484
  if (asize < bsize)
Packit 5c3484
    {
Packit 5c3484
      MPN_SRCPTR_SWAP (asrcp, asize, bsrcp, bsize);
Packit 5c3484
      MP_LIMB_T_SWAP (alow, blow);
Packit 5c3484
Packit 5c3484
      /* NOTE: The value of alow (old blow) is a bit subtle. For this code
Packit 5c3484
	 path, we get alow as the low, always odd, limb of shifted A. Which is
Packit 5c3484
	 what we need for the reciprocity update below.
Packit 5c3484
Packit 5c3484
	 However, all other uses of alow assumes that it is *not*
Packit 5c3484
	 shifted. Luckily, alow matters only when either
Packit 5c3484
Packit 5c3484
	 + btwos > 0, in which case A is always odd
Packit 5c3484
Packit 5c3484
	 + asize == bsize == 1, in which case this code path is never
Packit 5c3484
	   taken. */
Packit 5c3484
Packit 5c3484
      count_trailing_zeros (btwos, blow);
Packit 5c3484
      blow >>= btwos;
Packit 5c3484
Packit 5c3484
      if (bsize > 1 && btwos > 0)
Packit 5c3484
	{
Packit 5c3484
	  mp_limb_t b1 = bsrcp[1];
Packit 5c3484
	  blow |= b1 << (GMP_NUMB_BITS - btwos);
Packit 5c3484
	  if (bsize == 2 && (b1 >> btwos) == 0)
Packit 5c3484
	    bsize = 1;
Packit 5c3484
	}
Packit 5c3484
Packit 5c3484
      result_bit1 ^= JACOBI_RECIP_UU_BIT1 (alow, blow);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  if (bsize == 1)
Packit 5c3484
    {
Packit 5c3484
      result_bit1 ^= JACOBI_TWOS_U_BIT1(btwos, alow);
Packit 5c3484
Packit 5c3484
      if (blow == 1)
Packit 5c3484
	return JACOBI_BIT1_TO_PN (result_bit1);
Packit 5c3484
Packit 5c3484
      if (asize > 1)
Packit 5c3484
	JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, alow, asrcp, asize, blow);
Packit 5c3484
Packit 5c3484
      return mpn_jacobi_base (alow, blow, result_bit1);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  /* Allocation strategy: For A, we allocate a working copy only for A % B, but
Packit 5c3484
     when A is much larger than B, we have to allocate space for the large
Packit 5c3484
     quotient. We use the same area, pointed to by bp, for both the quotient
Packit 5c3484
     A/B and the working copy of B. */
Packit 5c3484
Packit 5c3484
  TMP_MARK;
Packit 5c3484
Packit 5c3484
  if (asize >= 2*bsize)
Packit 5c3484
    TMP_ALLOC_LIMBS_2 (ap, bsize, bp, asize - bsize + 1);
Packit 5c3484
  else
Packit 5c3484
    TMP_ALLOC_LIMBS_2 (ap, bsize, bp, bsize);
Packit 5c3484
Packit 5c3484
  /* In the case of even B, we conceptually shift out the powers of two first,
Packit 5c3484
     and then divide A mod B. Hence, when taking those powers of two into
Packit 5c3484
     account, we must use alow *before* the division. Doing the actual division
Packit 5c3484
     first is ok, because the point is to remove multiples of B from A, and
Packit 5c3484
     multiples of 2^k B are good enough. */
Packit 5c3484
  if (asize > bsize)
Packit 5c3484
    mpn_tdiv_qr (bp, ap, 0, asrcp, asize, bsrcp, bsize);
Packit 5c3484
  else
Packit 5c3484
    MPN_COPY (ap, asrcp, bsize);
Packit 5c3484
Packit 5c3484
  if (btwos > 0)
Packit 5c3484
    {
Packit 5c3484
      result_bit1 ^= JACOBI_TWOS_U_BIT1(btwos, alow);
Packit 5c3484
Packit 5c3484
      ASSERT_NOCARRY (mpn_rshift (bp, bsrcp, bsize, btwos));
Packit 5c3484
      bsize -= (ap[bsize-1] | bp[bsize-1]) == 0;
Packit 5c3484
    }
Packit 5c3484
  else
Packit 5c3484
    MPN_COPY (bp, bsrcp, bsize);
Packit 5c3484
Packit 5c3484
  ASSERT (blow == bp[0]);
Packit 5c3484
  res = mpn_jacobi_n (ap, bp, bsize,
Packit 5c3484
		      mpn_jacobi_init (ap[0], blow, (result_bit1>>1) & 1));
Packit 5c3484
Packit 5c3484
  TMP_FREE;
Packit 5c3484
  return res;
Packit 5c3484
}