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

     1  /* mpz_congruent_2exp_p -- test congruence of mpz mod 2^n.
     2  
     3  Copyright 2001, 2002, 2013 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  
    34  
    35  int
    36  mpz_congruent_2exp_p (mpz_srcptr a, mpz_srcptr c, mp_bitcnt_t d) __GMP_NOTHROW
    37  {
    38    mp_size_t      i, dlimbs;
    39    unsigned       dbits;
    40    mp_ptr         ap, cp;
    41    mp_limb_t      dmask, alimb, climb, sum;
    42    mp_size_t      as, cs, asize, csize;
    43  
    44    as = SIZ(a);
    45    asize = ABS(as);
    46  
    47    cs = SIZ(c);
    48    csize = ABS(cs);
    49  
    50    if (asize < csize)
    51      {
    52        MPZ_SRCPTR_SWAP (a, c);
    53        MP_SIZE_T_SWAP (asize, csize);
    54      }
    55  
    56    dlimbs = d / GMP_NUMB_BITS;
    57    dbits = d % GMP_NUMB_BITS;
    58    dmask = (CNST_LIMB(1) << dbits) - 1;
    59  
    60    ap = PTR(a);
    61    cp = PTR(c);
    62  
    63    if (csize == 0)
    64      goto a_zeros;
    65  
    66    if ((cs ^ as) >= 0)
    67      {
    68        /* same signs, direct comparison */
    69  
    70        /* a==c for limbs in common */
    71        if (mpn_cmp (ap, cp, MIN (csize, dlimbs)) != 0)
    72  	return 0;
    73  
    74        /* if that's all of dlimbs, then a==c for remaining bits */
    75        if (csize > dlimbs)
    76  	return ((ap[dlimbs]-cp[dlimbs]) & dmask) == 0;
    77  
    78      a_zeros:
    79        /* a remains, need all zero bits */
    80  
    81        /* if d covers all of a and c, then must be exactly equal */
    82        if (asize <= dlimbs)
    83  	return asize == csize;
    84  
    85        /* whole limbs zero */
    86        for (i = csize; i < dlimbs; i++)
    87  	if (ap[i] != 0)
    88  	  return 0;
    89  
    90        /* partial limb zero */
    91        return (ap[dlimbs] & dmask) == 0;
    92      }
    93    else
    94      {
    95        /* different signs, negated comparison */
    96  
    97        /* common low zero limbs, stopping at first non-zeros, which must
    98  	 match twos complement */
    99        i = 0;
   100        do
   101  	{
   102  	  ASSERT (i < csize);  /* always have a non-zero limb on c */
   103  	  alimb = ap[i];
   104  	  climb = cp[i];
   105  	  sum = (alimb + climb) & GMP_NUMB_MASK;
   106  
   107  	  if (i >= dlimbs)
   108  	    return (sum & dmask) == 0;
   109  	  ++i;
   110  
   111  	  /* require both zero, or first non-zeros as twos-complements */
   112  	  if (sum != 0)
   113  	    return 0;
   114  	} while (alimb == 0);
   115  
   116        /* further limbs matching as ones-complement */
   117        for (; i < csize; ++i)
   118  	{
   119  	  alimb = ap[i];
   120  	  climb = cp[i];
   121  	  sum = alimb ^ climb ^ GMP_NUMB_MASK;
   122  
   123  	  if (i >= dlimbs)
   124  	    return (sum & dmask) == 0;
   125  
   126  	  if (sum != 0)
   127  	    return 0;
   128  	}
   129  
   130        /* no more c, so require all 1 bits in a */
   131  
   132        if (asize < dlimbs)
   133  	return 0;   /* not enough a */
   134  
   135        /* whole limbs */
   136        for ( ; i < dlimbs; i++)
   137  	if (ap[i] != GMP_NUMB_MAX)
   138  	  return 0;
   139  
   140        /* if only whole limbs, no further fetches from a */
   141        if (dbits == 0)
   142  	return 1;
   143  
   144        /* need enough a */
   145        if (asize == dlimbs)
   146  	return 0;
   147  
   148        return ((ap[dlimbs]+1) & dmask) == 0;
   149      }
   150  }