mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +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);
|
scm_remember_upto_here_1 (n);
|
||||||
return take_mpz (result);
|
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,
|
SCM_INTERNAL SCM scm_integer_bit_extract_z (SCM n, unsigned long start,
|
||||||
unsigned long bits);
|
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 */
|
#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. */
|
/* Clear the `mpz_t' embedded in bignum PTR. */
|
||||||
static void
|
static void
|
||||||
finalize_bignum (void *ptr, void *data)
|
finalize_bignum (void *ptr, void *data)
|
||||||
|
@ -3369,11 +3365,6 @@ SCM_DEFINE (scm_bit_extract, "bit-extract", 3, 0, 0,
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#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_DEFINE (scm_logcount, "logcount", 1, 0, 0,
|
||||||
(SCM n),
|
(SCM n),
|
||||||
"Return the number of bits in integer @var{n}. If integer is\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
|
#define FUNC_NAME s_scm_logcount
|
||||||
{
|
{
|
||||||
if (SCM_I_INUMP (n))
|
if (SCM_I_INUMP (n))
|
||||||
{
|
return scm_integer_logcount_i (SCM_I_INUM (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);
|
|
||||||
}
|
|
||||||
else if (SCM_BIGP (n))
|
else if (SCM_BIGP (n))
|
||||||
{
|
return scm_integer_logcount_z (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);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
|
SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
|
||||||
}
|
}
|
||||||
|
@ -8527,8 +8499,6 @@ scm_init_numbers ()
|
||||||
custom_gmp_realloc,
|
custom_gmp_realloc,
|
||||||
custom_gmp_free);
|
custom_gmp_free);
|
||||||
|
|
||||||
mpz_init_set_si (z_negative_one, -1);
|
|
||||||
|
|
||||||
/* It may be possible to tune the performance of some algorithms by using
|
/* It may be possible to tune the performance of some algorithms by using
|
||||||
* the following constants to avoid the creation of bignums. Please, before
|
* the following constants to avoid the creation of bignums. Please, before
|
||||||
* using these values, remember the two rules of program optimization:
|
* using these values, remember the two rules of program optimization:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue