diff options
author | Kevin Ryde <user42@zip.com.au> | 2000-12-29 22:23:29 +0100 |
---|---|---|
committer | Kevin Ryde <user42@zip.com.au> | 2000-12-29 22:23:29 +0100 |
commit | 96ba0f7f48d6f4f4e54d0749e420a0d9d0659ccb (patch) | |
tree | afe96363713b10e68d1bd90b8f7587030f995b00 /mpz/tstbit.c | |
parent | 8d31258a9138f9eb1459dc61937eba54ec45eb9e (diff) | |
download | gmp-96ba0f7f48d6f4f4e54d0749e420a0d9d0659ccb.tar.gz |
* mpz/tstbit.c: Rewrite, slightly simplified.
Diffstat (limited to 'mpz/tstbit.c')
-rw-r--r-- | mpz/tstbit.c | 79 |
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; } |