github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpz/kronsz.c (about)

     1  /* mpz_si_kronecker -- long+mpz Kronecker/Jacobi symbol.
     2  
     3  Copyright 1999-2002 Free Software Foundation, Inc.
     4  
     5  This file is part of the GNU MP Library.
     6  
     7  The GNU MP Library is free software; you can redistribute it and/or modify
     8  it under the terms of either:
     9  
    10    * the GNU Lesser General Public License as published by the Free
    11      Software Foundation; either version 3 of the License, or (at your
    12      option) any later version.
    13  
    14  or
    15  
    16    * the GNU General Public License as published by the Free Software
    17      Foundation; either version 2 of the License, or (at your option) any
    18      later version.
    19  
    20  or both in parallel, as here.
    21  
    22  The GNU MP Library is distributed in the hope that it will be useful, but
    23  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    24  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    25  for more details.
    26  
    27  You should have received copies of the GNU General Public License and the
    28  GNU Lesser General Public License along with the GNU MP Library.  If not,
    29  see https://www.gnu.org/licenses/.  */
    30  
    31  #include "gmp.h"
    32  #include "gmp-impl.h"
    33  #include "longlong.h"
    34  
    35  
    36  int
    37  mpz_si_kronecker (long a, mpz_srcptr b)
    38  {
    39    mp_srcptr  b_ptr;
    40    mp_limb_t  b_low;
    41    mp_size_t  b_size;
    42    mp_size_t  b_abs_size;
    43    mp_limb_t  a_limb, b_rem;
    44    unsigned   twos;
    45    int        result_bit1;
    46  
    47  #if GMP_NUMB_BITS < BITS_PER_ULONG
    48    if (a > GMP_NUMB_MAX || a < -GMP_NUMB_MAX)
    49      {
    50        mp_limb_t  alimbs[2];
    51        mpz_t      az;
    52        ALLOC(az) = numberof (alimbs);
    53        PTR(az) = alimbs;
    54        mpz_set_si (az, a);
    55        return mpz_kronecker (az, b);
    56      }
    57  #endif
    58  
    59    b_size = SIZ (b);
    60    if (b_size == 0)
    61      return JACOBI_S0 (a);  /* (a/0) */
    62  
    63    /* account for the effect of the sign of b, then ignore it */
    64    result_bit1 = JACOBI_BSGN_SS_BIT1 (a, b_size);
    65  
    66    b_ptr = PTR(b);
    67    b_low = b_ptr[0];
    68    b_abs_size = ABS (b_size);
    69  
    70    if ((b_low & 1) != 0)
    71      {
    72        /* b odd */
    73  
    74        result_bit1 ^= JACOBI_ASGN_SU_BIT1 (a, b_low);
    75        a_limb = ABS_CAST(mp_limb_t, a);
    76  
    77        if ((a_limb & 1) == 0)
    78  	{
    79  	  /* (0/b)=1 for b=+/-1, 0 otherwise */
    80  	  if (a_limb == 0)
    81  	    return (b_abs_size == 1 && b_low == 1);
    82  
    83  	  /* a even, b odd */
    84  	  count_trailing_zeros (twos, a_limb);
    85  	  a_limb >>= twos;
    86  	  /* (a*2^n/b) = (a/b) * twos(n,a) */
    87  	  result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, b_low);
    88  	}
    89      }
    90    else
    91      {
    92        /* (even/even)=0, and (0/b)=0 for b!=+/-1 */
    93        if ((a & 1) == 0)
    94  	return 0;
    95  
    96        /* a odd, b even
    97  
    98  	 Establish shifted b_low with valid bit1 for ASGN and RECIP below.
    99  	 Zero limbs stripped are accounted for, but zero bits on b_low are
   100  	 not because they remain in {b_ptr,b_abs_size} for the
   101  	 JACOBI_MOD_OR_MODEXACT_1_ODD. */
   102  
   103        JACOBI_STRIP_LOW_ZEROS (result_bit1, a, b_ptr, b_abs_size, b_low);
   104        if ((b_low & 1) == 0)
   105  	{
   106  	  if (UNLIKELY (b_low == GMP_NUMB_HIGHBIT))
   107  	    {
   108  	      /* need b_ptr[1] to get bit1 in b_low */
   109  	      if (b_abs_size == 1)
   110  		{
   111  		  /* (a/0x80000000) = (a/2)^(BPML-1) */
   112  		  if ((GMP_NUMB_BITS % 2) == 0)
   113  		    result_bit1 ^= JACOBI_TWO_U_BIT1 (a);
   114  		  return JACOBI_BIT1_TO_PN (result_bit1);
   115  		}
   116  
   117  	      /* b_abs_size > 1 */
   118  	      b_low = b_ptr[1] << 1;
   119  	    }
   120  	  else
   121  	    {
   122  	      count_trailing_zeros (twos, b_low);
   123  	      b_low >>= twos;
   124  	    }
   125  	}
   126  
   127        result_bit1 ^= JACOBI_ASGN_SU_BIT1 (a, b_low);
   128        a_limb = (unsigned long) ABS(a);
   129      }
   130  
   131    if (a_limb == 1)
   132      return JACOBI_BIT1_TO_PN (result_bit1);  /* (1/b)=1 */
   133  
   134    /* (a/b*2^n) = (b*2^n mod a / a) * recip(a,b) */
   135    JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, b_rem, b_ptr, b_abs_size, a_limb);
   136    result_bit1 ^= JACOBI_RECIP_UU_BIT1 (a_limb, b_low);
   137    return mpn_jacobi_base (b_rem, a_limb, result_bit1);
   138  }