summaryrefslogtreecommitdiff
path: root/mpz/tstbit.c
diff options
context:
space:
mode:
authorKevin Ryde <user42@zip.com.au>2000-12-29 22:23:29 +0100
committerKevin Ryde <user42@zip.com.au>2000-12-29 22:23:29 +0100
commit96ba0f7f48d6f4f4e54d0749e420a0d9d0659ccb (patch)
treeafe96363713b10e68d1bd90b8f7587030f995b00 /mpz/tstbit.c
parent8d31258a9138f9eb1459dc61937eba54ec45eb9e (diff)
downloadgmp-96ba0f7f48d6f4f4e54d0749e420a0d9d0659ccb.tar.gz
* mpz/tstbit.c: Rewrite, slightly simplified.
Diffstat (limited to 'mpz/tstbit.c')
-rw-r--r--mpz/tstbit.c79
1 files changed, 39 insertions, 40 deletions
diff --git a/mpz/tstbit.c b/mpz/tstbit.c
index 1e2ca2755..5b4492f42 100644
--- a/mpz/tstbit.c
+++ b/mpz/tstbit.c
@@ -1,6 +1,6 @@
-/* mpz_tstbit -- test a specified bit. Simulate 2's complement representation.
+/* mpz_tstbit -- test a specified bit.
-Copyright 1997, 2000 Free Software Foundation, Inc.
+Copyright 2000 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
@@ -22,52 +22,51 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
+
+/* For negatives the effective twos complement is achieved by negating the
+ limb tested, either with a ones or twos complement. Twos complement
+ ("-") is used if there's only zero limbs below the one being tested.
+ Ones complement ("~") is used if there's a non-zero below. Note that "-"
+ is correct even if the limb examined is 0 (and the true beginning of twos
+ complement is further up).
+
+ Testing the limbs below p is unavoidable on negatives, but will usually
+ need to examine only *(p-1). The search is done from *(p-1) down to
+ *u_ptr, since that might give better cache locality, and because a
+ non-zero limb is perhaps a touch more likely in the middle of a number
+ than at the low end.
+
+ Bits past the end of available data simply follow sign of u. Notice that
+ the limb_index >= abs_size test covers u=0 too. */
+
int
-#if __STDC__
-mpz_tstbit (mpz_srcptr d, unsigned long int bit_index)
-#else
-mpz_tstbit (d, bit_index)
- mpz_srcptr d;
- unsigned long int bit_index;
-#endif
+mpz_tstbit (mpz_srcptr u, unsigned long bit_index)
{
- mp_size_t dn;
- mp_ptr dp;
- mp_size_t limb_index;
- mp_limb_t limb;
+ mp_srcptr u_ptr = PTR(u);
+ int size = SIZ(u);
+ unsigned abs_size = ABS(size);
+ unsigned long limb_index = bit_index / BITS_PER_MP_LIMB;
+ mp_srcptr p = u_ptr + limb_index;
+ mp_limb_t limb;
- dn = SIZ(d);
- dp = PTR(d);
+ if (limb_index >= abs_size)
+ return (size < 0);
- limb_index = bit_index / BITS_PER_MP_LIMB;
- if (dn >= 0)
- {
- limb = 0; /* Default if testing a bit outside of a positive number. */
- if (limb_index < dn)
- limb = dp[limb_index];
- }
- else
+ limb = *p;
+ if (size < 0)
{
- mp_size_t zero_bound;
+ limb = -limb; /* twos complement */
- dn = -dn;
-
- /* Locate the least significant non-zero limb. */
- for (zero_bound = 0; dp[zero_bound] == 0; zero_bound++)
- ;
-
- if (limb_index > zero_bound)
+ while (p != u_ptr)
{
- limb = ~(mp_limb_t) 0; /* Default if testing a bit outside of a negative number. */
- if (limb_index < dn)
- limb = ~dp[limb_index];
- }
- else
- {
- limb = 0;
- if (limb_index == zero_bound)
- limb = -dp[limb_index];
+ p--;
+ if (*p != 0)
+ {
+ limb--; /* make it a ones complement instead */
+ break;
+ }
}
}
+
return (limb >> (bit_index % BITS_PER_MP_LIMB)) & 1;
}