Blame mpn/generic/jacbase.c

Packit 5c3484
/* mpn_jacobi_base -- limb/limb Jacobi symbol with restricted arguments.
Packit 5c3484
Packit 5c3484
   THIS INTERFACE IS PRELIMINARY AND MIGHT DISAPPEAR OR BE SUBJECT TO
Packit 5c3484
   INCOMPATIBLE CHANGES IN A FUTURE RELEASE OF GMP.
Packit 5c3484
Packit 5c3484
Copyright 1999-2002, 2010 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 "gmp.h"
Packit 5c3484
#include "gmp-impl.h"
Packit 5c3484
#include "longlong.h"
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Use the simple loop by default.  The generic count_trailing_zeros is not
Packit 5c3484
   very fast, and the extra trickery of method 3 has proven to be less use
Packit 5c3484
   than might have been though.  */
Packit 5c3484
#ifndef JACOBI_BASE_METHOD
Packit 5c3484
#define JACOBI_BASE_METHOD  2
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Use count_trailing_zeros.  */
Packit 5c3484
#if JACOBI_BASE_METHOD == 1
Packit 5c3484
#define PROCESS_TWOS_ANY                                \
Packit 5c3484
  {                                                     \
Packit 5c3484
    mp_limb_t  twos;                                    \
Packit 5c3484
    count_trailing_zeros (twos, a);                     \
Packit 5c3484
    result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, b);        \
Packit 5c3484
    a >>= twos;                                         \
Packit 5c3484
  }
Packit 5c3484
#define PROCESS_TWOS_EVEN  PROCESS_TWOS_ANY
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
/* Use a simple loop.  A disadvantage of this is that there's a branch on a
Packit 5c3484
   50/50 chance of a 0 or 1 low bit.  */
Packit 5c3484
#if JACOBI_BASE_METHOD == 2
Packit 5c3484
#define PROCESS_TWOS_EVEN               \
Packit 5c3484
  {                                     \
Packit 5c3484
    int  two;                           \
Packit 5c3484
    two = JACOBI_TWO_U_BIT1 (b);        \
Packit 5c3484
    do                                  \
Packit 5c3484
      {                                 \
Packit 5c3484
	a >>= 1;                        \
Packit 5c3484
	result_bit1 ^= two;             \
Packit 5c3484
	ASSERT (a != 0);                \
Packit 5c3484
      }                                 \
Packit 5c3484
    while ((a & 1) == 0);               \
Packit 5c3484
  }
Packit 5c3484
#define PROCESS_TWOS_ANY        \
Packit 5c3484
  if ((a & 1) == 0)             \
Packit 5c3484
    PROCESS_TWOS_EVEN;
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
/* Process one bit arithmetically, then a simple loop.  This cuts the loop
Packit 5c3484
   condition down to a 25/75 chance, which should branch predict better.
Packit 5c3484
   The CPU will need a reasonable variable left shift.  */
Packit 5c3484
#if JACOBI_BASE_METHOD == 3
Packit 5c3484
#define PROCESS_TWOS_EVEN               \
Packit 5c3484
  {                                     \
Packit 5c3484
    int  two, mask, shift;              \
Packit 5c3484
					\
Packit 5c3484
    two = JACOBI_TWO_U_BIT1 (b);        \
Packit 5c3484
    mask = (~a & 2);                    \
Packit 5c3484
    a >>= 1;                            \
Packit 5c3484
					\
Packit 5c3484
    shift = (~a & 1);                   \
Packit 5c3484
    a >>= shift;                        \
Packit 5c3484
    result_bit1 ^= two ^ (two & mask);  \
Packit 5c3484
					\
Packit 5c3484
    while ((a & 1) == 0)                \
Packit 5c3484
      {                                 \
Packit 5c3484
	a >>= 1;                        \
Packit 5c3484
	result_bit1 ^= two;             \
Packit 5c3484
	ASSERT (a != 0);                \
Packit 5c3484
      }                                 \
Packit 5c3484
  }
Packit 5c3484
#define PROCESS_TWOS_ANY                \
Packit 5c3484
  {                                     \
Packit 5c3484
    int  two, mask, shift;              \
Packit 5c3484
					\
Packit 5c3484
    two = JACOBI_TWO_U_BIT1 (b);        \
Packit 5c3484
    shift = (~a & 1);                   \
Packit 5c3484
    a >>= shift;                        \
Packit 5c3484
					\
Packit 5c3484
    mask = shift << 1;                  \
Packit 5c3484
    result_bit1 ^= (two & mask);        \
Packit 5c3484
					\
Packit 5c3484
    while ((a & 1) == 0)                \
Packit 5c3484
      {                                 \
Packit 5c3484
	a >>= 1;                        \
Packit 5c3484
	result_bit1 ^= two;             \
Packit 5c3484
	ASSERT (a != 0);                \
Packit 5c3484
      }                                 \
Packit 5c3484
  }
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
#if JACOBI_BASE_METHOD < 4
Packit 5c3484
/* Calculate the value of the Jacobi symbol (a/b) of two mp_limb_t's, but
Packit 5c3484
   with a restricted range of inputs accepted, namely b>1, b odd.
Packit 5c3484
Packit 5c3484
   The initial result_bit1 is taken as a parameter for the convenience of
Packit 5c3484
   mpz_kronecker_ui() et al.  The sign changes both here and in those
Packit 5c3484
   routines accumulate nicely in bit 1, see the JACOBI macros.
Packit 5c3484
Packit 5c3484
   The return value here is the normal +1, 0, or -1.  Note that +1 and -1
Packit 5c3484
   have bit 1 in the "BIT1" sense, which could be useful if the caller is
Packit 5c3484
   accumulating it into some extended calculation.
Packit 5c3484
Packit 5c3484
   Duplicating the loop body to avoid the MP_LIMB_T_SWAP(a,b) would be
Packit 5c3484
   possible, but a couple of tests suggest it's not a significant speedup,
Packit 5c3484
   and may even be a slowdown, so what's here is good enough for now. */
Packit 5c3484
Packit 5c3484
int
Packit 5c3484
mpn_jacobi_base (mp_limb_t a, mp_limb_t b, int result_bit1)
Packit 5c3484
{
Packit 5c3484
  ASSERT (b & 1);  /* b odd */
Packit 5c3484
  ASSERT (b != 1);
Packit 5c3484
Packit 5c3484
  if (a == 0)
Packit 5c3484
    return 0;
Packit 5c3484
Packit 5c3484
  PROCESS_TWOS_ANY;
Packit 5c3484
  if (a == 1)
Packit 5c3484
    goto done;
Packit 5c3484
Packit 5c3484
  if (a >= b)
Packit 5c3484
    goto a_gt_b;
Packit 5c3484
Packit 5c3484
  for (;;)
Packit 5c3484
    {
Packit 5c3484
      result_bit1 ^= JACOBI_RECIP_UU_BIT1 (a, b);
Packit 5c3484
      MP_LIMB_T_SWAP (a, b);
Packit 5c3484
Packit 5c3484
    a_gt_b:
Packit 5c3484
      do
Packit 5c3484
	{
Packit 5c3484
	  /* working on (a/b), a,b odd, a>=b */
Packit 5c3484
	  ASSERT (a & 1);
Packit 5c3484
	  ASSERT (b & 1);
Packit 5c3484
	  ASSERT (a >= b);
Packit 5c3484
Packit 5c3484
	  if ((a -= b) == 0)
Packit 5c3484
	    return 0;
Packit 5c3484
Packit 5c3484
	  PROCESS_TWOS_EVEN;
Packit 5c3484
	  if (a == 1)
Packit 5c3484
	    goto done;
Packit 5c3484
	}
Packit 5c3484
      while (a >= b);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
 done:
Packit 5c3484
  return JACOBI_BIT1_TO_PN (result_bit1);
Packit 5c3484
}
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
#if JACOBI_BASE_METHOD == 4
Packit 5c3484
/* Computes (a/b) for odd b > 1 and any a. The initial bit is taken as a
Packit 5c3484
 * parameter. We have no need for the convention that the sign is in
Packit 5c3484
 * bit 1, internally we use bit 0. */
Packit 5c3484
Packit 5c3484
/* FIXME: Could try table-based count_trailing_zeros. */
Packit 5c3484
int
Packit 5c3484
mpn_jacobi_base (mp_limb_t a, mp_limb_t b, int bit)
Packit 5c3484
{
Packit 5c3484
  int c;
Packit 5c3484
Packit 5c3484
  ASSERT (b & 1);
Packit 5c3484
  ASSERT (b > 1);
Packit 5c3484
Packit 5c3484
  if (a == 0)
Packit 5c3484
    /* This is the only line which depends on b > 1 */
Packit 5c3484
    return 0;
Packit 5c3484
Packit 5c3484
  bit >>= 1;
Packit 5c3484
Packit 5c3484
  /* Below, we represent a and b shifted right so that the least
Packit 5c3484
     significant one bit is implicit. */
Packit 5c3484
Packit 5c3484
  b >>= 1;
Packit 5c3484
Packit 5c3484
  count_trailing_zeros (c, a);
Packit 5c3484
  bit ^= c & (b ^ (b >> 1));
Packit 5c3484
Packit 5c3484
  /* We may have c==GMP_LIMB_BITS-1, so we can't use a>>c+1. */
Packit 5c3484
  a >>= c;
Packit 5c3484
  a >>= 1;
Packit 5c3484
Packit 5c3484
  do
Packit 5c3484
    {
Packit 5c3484
      mp_limb_t t = a - b;
Packit 5c3484
      mp_limb_t bgta = LIMB_HIGHBIT_TO_MASK (t);
Packit 5c3484
Packit 5c3484
      if (t == 0)
Packit 5c3484
	return 0;
Packit 5c3484
Packit 5c3484
      /* If b > a, invoke reciprocity */
Packit 5c3484
      bit ^= (bgta & a & b);
Packit 5c3484
Packit 5c3484
      /* b <-- min (a, b) */
Packit 5c3484
      b += (bgta & t);
Packit 5c3484
Packit 5c3484
      /* a <-- |a - b| */
Packit 5c3484
      a = (t ^ bgta) - bgta;
Packit 5c3484
Packit 5c3484
      /* Number of trailing zeros is the same no matter if we look at
Packit 5c3484
       * t or a, but using t gives more parallelism. */
Packit 5c3484
      count_trailing_zeros (c, t);
Packit 5c3484
      c ++;
Packit 5c3484
      /* (2/b) = -1 if b = 3 or 5 mod 8 */
Packit 5c3484
      bit ^= c & (b ^ (b >> 1));
Packit 5c3484
      a >>= c;
Packit 5c3484
    }
Packit 5c3484
  while (b > 0);
Packit 5c3484
Packit 5c3484
  return 1-2*(bit & 1);
Packit 5c3484
}
Packit 5c3484
#endif /* JACOBI_BASE_METHOD == 4 */