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