[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 66/69: Start porting srfi-60 off the bad bignum interfac
From: |
Andy Wingo |
Subject: |
[Guile-commits] 66/69: Start porting srfi-60 off the bad bignum interfaces |
Date: |
Fri, 7 Jan 2022 08:27:29 -0500 (EST) |
wingo pushed a commit to branch wip-inline-digits
in repository guile.
commit 76e6a4a0e9890bbc061c41840e95e5c08d8b4b03
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Fri Jan 7 12:07:44 2022 +0100
Start porting srfi-60 off the bad bignum interfaces
* libguile/integers.h:
* libguile/integers.c (scm_integer_scan1_i):
(scm_integer_scan1_z): New internal functions.
* libguile/srfi-60.c (scm_srfi60_log2_binary_factors): Use scan1
functions.
(scm_srfi60_copy_bit): Use integers lib.
---
libguile/integers.c | 19 ++++++++++++++++++
libguile/integers.h | 3 +++
libguile/srfi-60.c | 57 +++++++++--------------------------------------------
3 files changed, 31 insertions(+), 48 deletions(-)
diff --git a/libguile/integers.c b/libguile/integers.c
index f6d33a21c..520cc6dbb 100644
--- a/libguile/integers.c
+++ b/libguile/integers.c
@@ -3168,3 +3168,22 @@ scm_integer_inexact_sqrt_z (struct scm_bignum *k)
double result = ldexp (sqrt (signif), expon / 2);
return negative ? -result : result;
}
+
+SCM
+scm_integer_scan1_i (scm_t_inum n)
+{
+ if (n == 0)
+ return SCM_I_MAKINUM (-1);
+ n = n ^ (n-1); /* 1 bits for each low 0 and lowest 1 */
+ return scm_integer_logcount_i (n >> 1);
+}
+
+SCM
+scm_integer_scan1_z (struct scm_bignum *n)
+{
+ mpz_t zn;
+ alias_bignum_to_mpz (n, zn);
+ unsigned long pos = mpz_scan1 (zn, 0L);
+ scm_remember_upto_here_1 (n);
+ return ulong_to_scm (pos);
+}
diff --git a/libguile/integers.h b/libguile/integers.h
index 470d3ea54..a232eb8cc 100644
--- a/libguile/integers.h
+++ b/libguile/integers.h
@@ -227,6 +227,9 @@ SCM_INTERNAL SCM scm_integer_floor_sqrt_z (struct
scm_bignum *k);
SCM_INTERNAL double scm_integer_inexact_sqrt_i (scm_t_inum k);
SCM_INTERNAL double scm_integer_inexact_sqrt_z (struct scm_bignum *k);
+SCM_INTERNAL SCM scm_integer_scan1_i (scm_t_inum n);
+SCM_INTERNAL SCM scm_integer_scan1_z (struct scm_bignum *n);
+
#endif /* SCM_INTEGERS_H */
diff --git a/libguile/srfi-60.c b/libguile/srfi-60.c
index 578106e8e..9ee0fed53 100644
--- a/libguile/srfi-60.c
+++ b/libguile/srfi-60.c
@@ -1,6 +1,6 @@
/* srfi-60.c --- Integers as Bits
- Copyright 2005-2006,2008,2010,2014,2018
+ Copyright 2005-2006,2008,2010,2014,2018,2022
Free Software Foundation, Inc.
This file is part of Guile.
@@ -29,6 +29,7 @@
#include "eq.h"
#include "extensions.h"
#include "gsubr.h"
+#include "integers.h"
#include "list.h"
#include "numbers.h"
#include "pairs.h"
@@ -52,19 +53,9 @@ SCM_DEFINE (scm_srfi60_log2_binary_factors,
"log2-binary-factors", 1, 0, 0,
SCM ret = SCM_EOL;
if (SCM_I_INUMP (n))
- {
- long nn = SCM_I_INUM (n);
- if (nn == 0)
- return SCM_I_MAKINUM (-1);
- nn = nn ^ (nn-1); /* 1 bits for each low 0 and lowest 1 */
- return scm_logcount (SCM_I_MAKINUM (nn >> 1));
- }
+ return scm_integer_scan1_i (SCM_I_INUM (n));
else if (SCM_BIGP (n))
- {
- /* no need for scm_remember_upto_here_1 here, mpz_scan1 doesn't do
- anything that could result in a gc */
- return SCM_I_MAKINUM (mpz_scan1 (SCM_I_BIG_MPZ (n), 0L));
- }
+ return scm_integer_scan1_z (scm_bignum (n));
else
SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
@@ -85,7 +76,6 @@ SCM_DEFINE (scm_srfi60_copy_bit, "copy-bit", 3, 0, 0,
"@end example")
#define FUNC_NAME s_scm_srfi60_copy_bit
{
- SCM r;
unsigned long ii;
int bb;
@@ -94,47 +84,18 @@ SCM_DEFINE (scm_srfi60_copy_bit, "copy-bit", 3, 0, 0,
if (SCM_I_INUMP (n))
{
- long nn = SCM_I_INUM (n);
-
- /* can't set high bit ii==SCM_LONG_BIT-1, that would change the sign,
- which is not what's wanted */
- if (ii < SCM_LONG_BIT-1)
- {
- nn &= ~(1L << ii); /* zap bit at index */
- nn |= ((long) bb << ii); /* insert desired bit */
- return scm_from_long (nn);
- }
- else
- {
- /* bits at ii==SCM_LONG_BIT-1 and above are all copies of the sign
- bit, if this is already the desired "bit" value then no need to
- make a new bignum value */
- if (bb == (nn < 0))
- return n;
-
- r = scm_i_long2big (nn);
- goto big;
- }
+ if (scm_integer_logbit_ui (ii, SCM_I_INUM (n)) == bb)
+ return n;
}
else if (SCM_BIGP (n))
{
- /* if the bit is already what's wanted then no need to make a new
- bignum */
- if (bb == mpz_tstbit (SCM_I_BIG_MPZ (n), ii))
+ if (scm_integer_logbit_uz (ii, scm_bignum (n)) == bb)
return n;
-
- r = scm_i_clonebig (n, 1);
- big:
- if (bb)
- mpz_setbit (SCM_I_BIG_MPZ (r), ii);
- else
- mpz_clrbit (SCM_I_BIG_MPZ (r), ii);
-
- /* changing a high bit might put the result into range of a fixnum */
- return scm_i_normbig (r);
}
else
SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
+
+ return scm_logxor (n, ii == 0 ? SCM_INUM1 : scm_integer_lsh_iu (1, ii));
}
#undef FUNC_NAME
- [Guile-commits] 51/69: Reimplement scm_{to,from}_{int32,uint32}, (continued)
- [Guile-commits] 51/69: Reimplement scm_{to,from}_{int32,uint32}, Andy Wingo, 2022/01/07
- [Guile-commits] 45/69: Remove support for allowing exact numbers to be divided by zero, Andy Wingo, 2022/01/07
- [Guile-commits] 50/69: Reimplement scm_from_int8 etc, Andy Wingo, 2022/01/07
- [Guile-commits] 56/69: Reimplement exact-integer-sqrt with integers.[ch], Andy Wingo, 2022/01/07
- [Guile-commits] 55/69: scm_to_mpz uses integer lib, Andy Wingo, 2022/01/07
- [Guile-commits] 62/69: Remove last non-admin SCM_I_BIG_MPZ uses in numbers.c, Andy Wingo, 2022/01/07
- [Guile-commits] 61/69: Simplify scm_exact_integer_quotient, Andy Wingo, 2022/01/07
- [Guile-commits] 63/69: Simplify magnitude, angle, Andy Wingo, 2022/01/07
- [Guile-commits] 64/69: Use scm_integer_to_double_z in numbers.c instead of big2dbl, Andy Wingo, 2022/01/07
- [Guile-commits] 67/69: Finish srfi-60 port off old scm mpz API, Andy Wingo, 2022/01/07
- [Guile-commits] 66/69: Start porting srfi-60 off the bad bignum interfaces,
Andy Wingo <=
- [Guile-commits] 69/69: Bignums avoid both custom GMP allocator and finalizers, Andy Wingo, 2022/01/07
- [Guile-commits] 68/69: scm_to_ipv6 uses scm_to_mpz, Andy Wingo, 2022/01/07