Home | History | Annotate | Line # | Download | only in mpz
combit.c revision 1.1.1.2
      1      1.1  mrg /* mpz_combit -- complement a specified bit.
      2      1.1  mrg 
      3  1.1.1.2  mrg Copyright 2002, 2003, 2012 Free Software Foundation, Inc.
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU MP Library.
      6      1.1  mrg 
      7      1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
      8      1.1  mrg it under the terms of the GNU Lesser General Public License as published by
      9      1.1  mrg the Free Software Foundation; either version 3 of the License, or (at your
     10      1.1  mrg option) any later version.
     11      1.1  mrg 
     12      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     13      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14      1.1  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     15      1.1  mrg License for more details.
     16      1.1  mrg 
     17      1.1  mrg You should have received a copy of the GNU Lesser General Public License
     18      1.1  mrg along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
     19      1.1  mrg 
     20      1.1  mrg #include "gmp.h"
     21      1.1  mrg #include "gmp-impl.h"
     22      1.1  mrg 
     23      1.1  mrg void
     24      1.1  mrg mpz_combit (mpz_ptr d, mp_bitcnt_t bit_index)
     25      1.1  mrg {
     26  1.1.1.2  mrg   mp_size_t dsize = SIZ(d);
     27  1.1.1.2  mrg   mp_ptr dp = PTR(d);
     28      1.1  mrg 
     29      1.1  mrg   mp_size_t limb_index = bit_index / GMP_NUMB_BITS;
     30  1.1.1.2  mrg   mp_limb_t bit = (CNST_LIMB (1) << (bit_index % GMP_NUMB_BITS));
     31      1.1  mrg 
     32  1.1.1.2  mrg   /* Check for the most common case: Positive input, no realloc or
     33  1.1.1.2  mrg      normalization needed. */
     34  1.1.1.2  mrg   if (limb_index + 1 < dsize)
     35  1.1.1.2  mrg     dp[limb_index] ^= bit;
     36  1.1.1.2  mrg 
     37  1.1.1.2  mrg   /* Check for the hairy case. d < 0, and we have all zero bits to the
     38  1.1.1.2  mrg      right of the bit to toggle. */
     39  1.1.1.2  mrg   else if (limb_index < -dsize && mpn_zero_p (dp, limb_index)
     40  1.1.1.2  mrg 	   && (dp[limb_index] & (bit - 1)) == 0)
     41      1.1  mrg     {
     42  1.1.1.2  mrg       ASSERT (dsize < 0);
     43  1.1.1.2  mrg       dsize = -dsize;
     44      1.1  mrg 
     45  1.1.1.2  mrg       if (dp[limb_index] & bit)
     46  1.1.1.2  mrg 	{
     47  1.1.1.2  mrg 	  /* We toggle the least significant one bit. Corresponds to
     48  1.1.1.2  mrg 	     an add, with potential carry propagation, on the absolute
     49  1.1.1.2  mrg 	     value. */
     50  1.1.1.2  mrg 	  dp = MPZ_REALLOC (d, 1 + dsize);
     51  1.1.1.2  mrg 	  dp[dsize] = 0;
     52  1.1.1.2  mrg 	  MPN_INCR_U (dp + limb_index, 1 + dsize - limb_index, bit);
     53  1.1.1.2  mrg 	  SIZ(d) -= dp[dsize];
     54  1.1.1.2  mrg 	}
     55  1.1.1.2  mrg       else
     56  1.1.1.2  mrg 	{
     57  1.1.1.2  mrg 	  /* We toggle a zero bit, subtract from the absolute value. */
     58  1.1.1.2  mrg 	  MPN_DECR_U (dp + limb_index, dsize - limb_index, bit);
     59  1.1.1.2  mrg 	  MPN_NORMALIZE (dp, dsize);
     60  1.1.1.2  mrg 	  ASSERT (dsize > 0);
     61  1.1.1.2  mrg 	  SIZ(d) = -dsize;
     62  1.1.1.2  mrg 	}
     63      1.1  mrg     }
     64      1.1  mrg   else
     65      1.1  mrg     {
     66  1.1.1.2  mrg       /* Simple case: Toggle the bit in the absolute value. */
     67  1.1.1.2  mrg       dsize = ABS(dsize);
     68  1.1.1.2  mrg       if (limb_index < dsize)
     69      1.1  mrg 	{
     70  1.1.1.2  mrg 	  dp[limb_index] ^= bit;
     71      1.1  mrg 
     72  1.1.1.2  mrg 	  /* Can happen only when limb_index = dsize - 1. Avoid SIZ(d)
     73  1.1.1.2  mrg 	     bookkeeping in the common case. */
     74  1.1.1.2  mrg 	  if (dp[dsize-1] == 0)
     75  1.1.1.2  mrg 	    {
     76  1.1.1.2  mrg 	      dsize--;
     77  1.1.1.2  mrg 	      MPN_NORMALIZE (dp, dsize);
     78  1.1.1.2  mrg 	      SIZ (d) = SIZ (d) >= 0 ? dsize : -dsize;
     79  1.1.1.2  mrg 	    }
     80      1.1  mrg 	}
     81      1.1  mrg       else
     82  1.1.1.2  mrg 	{
     83  1.1.1.2  mrg 	  dp = MPZ_REALLOC (d, limb_index + 1);
     84  1.1.1.2  mrg 	  MPN_ZERO(dp + dsize, limb_index - dsize);
     85  1.1.1.2  mrg 	  dp[limb_index++] = bit;
     86  1.1.1.2  mrg 	  SIZ(d) = SIZ(d) >= 0 ? limb_index : -limb_index;
     87  1.1.1.2  mrg 	}
     88      1.1  mrg     }
     89      1.1  mrg }
     90