Home | History | Annotate | Line # | Download | only in mpz
combit.c revision 1.1
      1  1.1  mrg /* mpz_combit -- complement a specified bit.
      2  1.1  mrg 
      3  1.1  mrg Copyright 2002, 2003 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  mrg   mp_size_t dsize = ABSIZ(d);
     27  1.1  mrg   mp_ptr dp = LIMBS(d);
     28  1.1  mrg 
     29  1.1  mrg   mp_size_t limb_index = bit_index / GMP_NUMB_BITS;
     30  1.1  mrg   mp_limb_t bit = ((mp_limb_t) 1 << (bit_index % GMP_NUMB_BITS));
     31  1.1  mrg 
     32  1.1  mrg   if (limb_index >= dsize)
     33  1.1  mrg     {
     34  1.1  mrg       MPZ_REALLOC(d, limb_index + 1);
     35  1.1  mrg       dp = LIMBS(d);
     36  1.1  mrg 
     37  1.1  mrg       MPN_ZERO(dp + dsize, limb_index + 1 - dsize);
     38  1.1  mrg       dsize = limb_index + 1;
     39  1.1  mrg     }
     40  1.1  mrg 
     41  1.1  mrg   if (SIZ(d) >= 0)
     42  1.1  mrg     {
     43  1.1  mrg       dp[limb_index] ^= bit;
     44  1.1  mrg       MPN_NORMALIZE (dp, dsize);
     45  1.1  mrg       SIZ(d) = dsize;
     46  1.1  mrg     }
     47  1.1  mrg   else
     48  1.1  mrg     {
     49  1.1  mrg       mp_limb_t x = -dp[limb_index];
     50  1.1  mrg       mp_size_t i;
     51  1.1  mrg 
     52  1.1  mrg       /* non-zero limb below us means ones-complement */
     53  1.1  mrg       for (i = limb_index-1; i >= 0; i--)
     54  1.1  mrg 	if (dp[i] != 0)
     55  1.1  mrg 	  {
     56  1.1  mrg 	    x--;  /* change twos comp to ones comp */
     57  1.1  mrg 	    break;
     58  1.1  mrg 	  }
     59  1.1  mrg 
     60  1.1  mrg       if (x & bit)
     61  1.1  mrg 	{
     62  1.1  mrg 	  mp_limb_t  c;
     63  1.1  mrg 
     64  1.1  mrg 	  /* Clearing the bit increases the magitude. We might need a carry. */
     65  1.1  mrg 	  MPZ_REALLOC(d, dsize + 1);
     66  1.1  mrg 	  dp = LIMBS(d);
     67  1.1  mrg 
     68  1.1  mrg 	  __GMPN_ADD_1 (c, dp+limb_index, dp+limb_index,
     69  1.1  mrg 			dsize - limb_index, bit);
     70  1.1  mrg 	  dp[dsize] = c;
     71  1.1  mrg 	  dsize += c;
     72  1.1  mrg 	}
     73  1.1  mrg       else
     74  1.1  mrg 	/* Setting the bit decreases the magnitude */
     75  1.1  mrg 	mpn_sub_1(dp+limb_index, dp+limb_index, dsize + limb_index, bit);
     76  1.1  mrg 
     77  1.1  mrg       MPN_NORMALIZE (dp, dsize);
     78  1.1  mrg       SIZ(d) = -dsize;
     79  1.1  mrg     }
     80  1.1  mrg }
     81