[Gmp-commit] /var/hg/gmp: 2 new changesets

mercurial at gmplib.org mercurial at gmplib.org
Thu Nov 1 21:22:38 CET 2012


details:   /var/hg/gmp/rev/cb67ea40c57a
changeset: 15102:cb67ea40c57a
user:      Niels M?ller <nisse at lysator.liu.se>
date:      Thu Nov 01 21:18:45 2012 +0100
description:
mpz_combit rewrite.

details:   /var/hg/gmp/rev/e93da8a39685
changeset: 15103:e93da8a39685
user:      Niels M?ller <nisse at lysator.liu.se>
date:      Thu Nov 01 21:22:24 2012 +0100
description:
(mpn_hgcd2): Removed redundant loop exit tests in the single-precision loop.

diffstat:

 ChangeLog           |   8 ++++
 mpn/generic/hgcd2.c |   4 --
 mpz/combit.c        |  87 +++++++++++++++++++++++++++++-----------------------
 3 files changed, 57 insertions(+), 42 deletions(-)

diffs (145 lines):

diff -r 1e767ab37a8a -r e93da8a39685 ChangeLog
--- a/ChangeLog	Wed Oct 31 13:56:30 2012 +0100
+++ b/ChangeLog	Thu Nov 01 21:22:24 2012 +0100
@@ -1,3 +1,11 @@
+2012-11-01  Niels Möller  <nisse at lysator.liu.se>
+
+	* mpn/generic/hgcd2.c (mpn_hgcd2): Removed redundant loop exit
+	tests in the single-precision loop.
+
+	* mpz/combit.c (mpz_combit): Rewrite, optimizing for the common
+	case.
+
 2012-10-31  Niels Möller  <nisse at lysator.liu.se>
 
 	* tests/mpn/Makefile.am (check_PROGRAMS): Added t-brootinv.
diff -r 1e767ab37a8a -r e93da8a39685 mpn/generic/hgcd2.c
--- a/mpn/generic/hgcd2.c	Wed Oct 31 13:56:30 2012 +0100
+++ b/mpn/generic/hgcd2.c	Thu Nov 01 21:22:24 2012 +0100
@@ -338,8 +338,6 @@
   for (;;)
     {
       ASSERT (ah >= bh);
-      if (ah == bh)
-	break;
 
       ah -= bh;
       if (ah < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1)))
@@ -369,8 +367,6 @@
 	}
     subtract_a1:
       ASSERT (bh >= ah);
-      if (ah == bh)
-	break;
 
       bh -= ah;
       if (bh < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1)))
diff -r 1e767ab37a8a -r e93da8a39685 mpz/combit.c
--- a/mpz/combit.c	Wed Oct 31 13:56:30 2012 +0100
+++ b/mpz/combit.c	Thu Nov 01 21:22:24 2012 +0100
@@ -23,56 +23,67 @@
 void
 mpz_combit (mpz_ptr d, mp_bitcnt_t bit_index)
 {
-  mp_size_t dsize = ABSIZ(d);
+  mp_size_t dsize = SIZ(d);
   mp_ptr dp = PTR(d);
 
   mp_size_t limb_index = bit_index / GMP_NUMB_BITS;
   mp_limb_t bit = (CNST_LIMB (1) << (bit_index % GMP_NUMB_BITS));
 
-  if (limb_index >= dsize)
+  /* Check for the most common case: Positive input, no realloc or
+     normalization needed. */
+  if (limb_index + 1 < dsize)
+    dp[limb_index] ^= bit;
+
+  /* Check for the hairy case. d < 0, and we have all zero bits to the
+     right of the bit to toggle. */
+  else if (limb_index < -dsize && mpn_zero_p (dp, limb_index)
+	   && (dp[limb_index] & (bit - 1)) == 0)
     {
-      dp = MPZ_REALLOC(d, limb_index + 1);
+      ASSERT (dsize < 0);
+      dsize = -dsize;
 
-      MPN_ZERO(dp + dsize, limb_index + 1 - dsize);
-      dsize = limb_index + 1;
-    }
-
-  if (SIZ(d) >= 0)
-    {
-      dp[limb_index] ^= bit;
-      MPN_NORMALIZE (dp, dsize);
-      SIZ(d) = dsize;
+      if (dp[limb_index] & bit)
+	{
+	  /* We toggle the least significant one bit. Corresponds to
+	     an add, with potential carry propagation, on the absolute
+	     value. */
+	  dp = MPZ_REALLOC (d, 1 + dsize);
+	  dp[dsize] = 0;
+	  MPN_INCR_U (dp + limb_index, 1 + dsize - limb_index, bit);
+	  SIZ(d) -= dp[dsize];
+	}
+      else
+	{
+	  /* We toggle a zero bit, subtract from the absolute value. */
+	  MPN_DECR_U (dp + limb_index, dsize - limb_index, bit);
+	  MPN_NORMALIZE (dp, dsize);
+	  ASSERT (dsize > 0);
+	  SIZ(d) = -dsize;
+	}
     }
   else
     {
-      mp_limb_t x = -dp[limb_index];
-      mp_size_t i;
+      /* Simple case: Toggle the bit in the absolute value. */
+      dsize = ABS(dsize);
+      if (limb_index < dsize)
+	{
+	  dp[limb_index] ^= bit;
 
-      /* non-zero limb below us means ones-complement */
-      for (i = limb_index-1; i >= 0; i--)
-	if (dp[i] != 0)
-	  {
-	    x--;  /* change twos comp to ones comp */
-	    break;
-	  }
-
-      if (x & bit)
-	{
-	  mp_limb_t  c;
-
-	  /* Clearing the bit increases the magitude. We might need a carry. */
-	  dp = MPZ_REALLOC(d, dsize + 1);
-
-	  __GMPN_ADD_1 (c, dp+limb_index, dp+limb_index,
-			dsize - limb_index, bit);
-	  dp[dsize] = c;
-	  dsize += c;
+	  /* Can happen only when limb_index = dsize - 1. Avoid SIZ(d)
+	     bookkeeping in the common case. */
+	  if (dp[dsize-1] == 0)
+	    {
+	      dsize--;
+	      MPN_NORMALIZE (dp, dsize);
+	      SIZ (d) = SIZ (d) >= 0 ? dsize : -dsize;
+	    }
 	}
       else
-	/* Setting the bit decreases the magnitude */
-	mpn_sub_1(dp+limb_index, dp+limb_index, dsize + limb_index, bit);
-
-      MPN_NORMALIZE (dp, dsize);
-      SIZ(d) = -dsize;
+	{
+	  dp = MPZ_REALLOC (d, limb_index + 1);
+	  MPN_ZERO(dp + dsize, limb_index - dsize);
+	  dp[limb_index++] = bit;
+	  SIZ(d) = SIZ(d) >= 0 ? limb_index : -limb_index;
+	}
     }
 }


More information about the gmp-commit mailing list