mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 03:30:27 +02:00
Implement scm_logcount with new integer library
* libguile/integers.c (scm_integer_logcount_i) (scm_integer_logcount_z): New internal functions. * libguile/integers.h: Declare the new internal functions. * libguile/numbers.c (scm_logcount): Use new internal functions.
This commit is contained in:
parent
88f56e91aa
commit
7ec40fe5b0
3 changed files with 42 additions and 32 deletions
|
@ -2254,3 +2254,40 @@ scm_integer_bit_extract_z (SCM n, unsigned long start, unsigned long bits)
|
|||
scm_remember_upto_here_1 (n);
|
||||
return take_mpz (result);
|
||||
}
|
||||
|
||||
static const char scm_logtab[] = {
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
|
||||
};
|
||||
|
||||
SCM
|
||||
scm_integer_logcount_i (scm_t_inum n)
|
||||
{
|
||||
unsigned long c = 0;
|
||||
if (n < 0)
|
||||
n = -1 - n;
|
||||
while (n)
|
||||
{
|
||||
c += scm_logtab[15 & n];
|
||||
n >>= 4;
|
||||
}
|
||||
return SCM_I_MAKINUM (c);
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_integer_logcount_z (SCM n)
|
||||
{
|
||||
unsigned long count;
|
||||
mpz_t zn;
|
||||
alias_bignum_to_mpz (scm_bignum (n), zn);
|
||||
if (mpz_sgn (zn) >= 0)
|
||||
count = mpz_popcount (zn);
|
||||
else
|
||||
{
|
||||
mpz_t z_negative_one;
|
||||
mpz_init_set_si (z_negative_one, -1);
|
||||
count = mpz_hamdist (zn, z_negative_one);
|
||||
mpz_clear (z_negative_one);
|
||||
}
|
||||
scm_remember_upto_here_1 (n);
|
||||
return scm_from_ulong (count);
|
||||
}
|
||||
|
|
|
@ -168,6 +168,9 @@ SCM_INTERNAL SCM scm_integer_bit_extract_i (scm_t_inum n, unsigned long start,
|
|||
SCM_INTERNAL SCM scm_integer_bit_extract_z (SCM n, unsigned long start,
|
||||
unsigned long bits);
|
||||
|
||||
SCM_INTERNAL SCM scm_integer_logcount_i (scm_t_inum n);
|
||||
SCM_INTERNAL SCM scm_integer_logcount_z (SCM n);
|
||||
|
||||
|
||||
|
||||
#endif /* SCM_INTEGERS_H */
|
||||
|
|
|
@ -234,10 +234,6 @@ scm_from_complex_double (complex double z)
|
|||
|
||||
|
||||
|
||||
static mpz_t z_negative_one;
|
||||
|
||||
|
||||
|
||||
/* Clear the `mpz_t' embedded in bignum PTR. */
|
||||
static void
|
||||
finalize_bignum (void *ptr, void *data)
|
||||
|
@ -3369,11 +3365,6 @@ SCM_DEFINE (scm_bit_extract, "bit-extract", 3, 0, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
static const char scm_logtab[] = {
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
|
||||
};
|
||||
|
||||
SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
|
||||
(SCM n),
|
||||
"Return the number of bits in integer @var{n}. If integer is\n"
|
||||
|
@ -3392,28 +3383,9 @@ SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
|
|||
#define FUNC_NAME s_scm_logcount
|
||||
{
|
||||
if (SCM_I_INUMP (n))
|
||||
{
|
||||
unsigned long c = 0;
|
||||
scm_t_inum nn = SCM_I_INUM (n);
|
||||
if (nn < 0)
|
||||
nn = -1 - nn;
|
||||
while (nn)
|
||||
{
|
||||
c += scm_logtab[15 & nn];
|
||||
nn >>= 4;
|
||||
}
|
||||
return SCM_I_MAKINUM (c);
|
||||
}
|
||||
return scm_integer_logcount_i (SCM_I_INUM (n));
|
||||
else if (SCM_BIGP (n))
|
||||
{
|
||||
unsigned long count;
|
||||
if (mpz_sgn (SCM_I_BIG_MPZ (n)) >= 0)
|
||||
count = mpz_popcount (SCM_I_BIG_MPZ (n));
|
||||
else
|
||||
count = mpz_hamdist (SCM_I_BIG_MPZ (n), z_negative_one);
|
||||
scm_remember_upto_here_1 (n);
|
||||
return SCM_I_MAKINUM (count);
|
||||
}
|
||||
return scm_integer_logcount_z (n);
|
||||
else
|
||||
SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
|
||||
}
|
||||
|
@ -8527,8 +8499,6 @@ scm_init_numbers ()
|
|||
custom_gmp_realloc,
|
||||
custom_gmp_free);
|
||||
|
||||
mpz_init_set_si (z_negative_one, -1);
|
||||
|
||||
/* It may be possible to tune the performance of some algorithms by using
|
||||
* the following constants to avoid the creation of bignums. Please, before
|
||||
* using these values, remember the two rules of program optimization:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue