[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 51/69: Reimplement scm_{to,from}_{int32,uint32}
From: |
Andy Wingo |
Subject: |
[Guile-commits] 51/69: Reimplement scm_{to,from}_{int32,uint32} |
Date: |
Fri, 7 Jan 2022 08:27:16 -0500 (EST) |
wingo pushed a commit to branch wip-inline-digits
in repository guile.
commit 915f43ae30819aa05a558c8cd0ee41930a48c812
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Thu Jan 6 21:04:23 2022 +0100
Reimplement scm_{to,from}_{int32,uint32}
* libguile/numbers.c (scm_to_int32, scm_from_int32, scm_to_uint32):
(scm_from_uint32): Reimplement inline.
* libguile/integers.c (make_bignum_2):
(make_bignum_from_uint64):
(negative_uint32_to_int32):
(positive_uint32_to_int32):
(bignum_to_int32):
(bignum_to_uint32):
(scm_integer_from_int32):
(scm_integer_from_uint32):
(scm_integer_to_int32_z):
(scm_integer_to_uint32_z): Better int32 support for 32-bit machines.
---
libguile/integers.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++-----
libguile/integers.h | 8 +++-
libguile/numbers.c | 81 ++++++++++++++++++++++++++++++++-------
3 files changed, 171 insertions(+), 25 deletions(-)
diff --git a/libguile/integers.c b/libguile/integers.c
index 9ec42694f..f00885792 100644
--- a/libguile/integers.c
+++ b/libguile/integers.c
@@ -182,21 +182,25 @@ make_bignum_1 (int is_negative, mp_limb_t limb)
return is_negative ? negate_bignum(z) : z;
}
+#if SCM_SIZEOF_LONG == 4
+static struct scm_bignum *
+make_bignum_2 (int is_negative, mp_limb_t lo, mp_limb_t hi)
+{
+ struct scm_bignum *z = allocate_bignum (2);
+ z->limbs[0] = lo;
+ z->limbs[1] = hi;
+ return is_negative ? negate_bignum(z) : z;
+}
+#endif
+
static struct scm_bignum *
make_bignum_from_uint64 (uint64_t val)
{
#if SCM_SIZEOF_LONG == 4
- mp_limb_t lo = val, hi = val >> 32;
- struct scm_bignum *z = allocate_bignum (hi ? 2 : 1);
- z->limbs[0] = lo;
- if (hi)
- z->limbs[1] = hi;
- return z;
-#else
- struct scm_bignum *z = allocate_bignum (1);
- z->limbs[0] = val;
- return z;
+ if (val > UINT32_MAX)
+ return make_bignum_2 (0, val, val >> 32);
#endif
+ return make_bignum_1 (0, val);
}
static struct scm_bignum *
@@ -384,6 +388,59 @@ bignum_to_uint64 (struct scm_bignum *z, uint64_t *val)
}
}
+#if SCM_SIZEOF_LONG == 4
+static int
+negative_uint32_to_int32 (uint32_t magnitude, int32_t *val)
+{
+ if (magnitude > long_magnitude (INT32_MIN))
+ return 0;
+ *val = negative_long (magnitude);
+ return 1;
+}
+
+static int
+positive_uint32_to_int32 (uint32_t magnitude, int32_t *val)
+{
+ if (magnitude > INT32_MAX)
+ return 0;
+ *val = magnitude;
+ return 1;
+}
+
+static int
+bignum_to_int32 (struct scm_bignum *z, int32_t *val)
+{
+ switch (bignum_size (z))
+ {
+ case -1:
+ return negative_uint32_to_int32 (bignum_limbs (z)[0], val);
+ case 0:
+ *val = 0;
+ return 1;
+ case 1:
+ return positive_uint32_to_int32 (bignum_limbs (z)[0], val);
+ default:
+ return 0;
+ }
+}
+
+static int
+bignum_to_uint32 (struct scm_bignum *z, uint32_t *val)
+{
+ switch (bignum_size (z))
+ {
+ case 0:
+ *val = 0;
+ return 1;
+ case 1:
+ *val = bignum_limbs (z)[0];
+ return 1;
+ default:
+ return 0;
+ }
+}
+#endif
+
static int
bignum_cmp_long (struct scm_bignum *z, long l)
{
@@ -2921,6 +2978,36 @@ scm_integer_exact_quotient_zz (struct scm_bignum *n,
struct scm_bignum *d)
return take_mpz (q);
}
+#if SCM_SIZEOF_LONG == 4
+SCM
+scm_integer_from_int32 (int32_t n)
+{
+ if (SCM_FIXABLE (n))
+ return SCM_I_MAKINUM (n);
+ return scm_from_bignum (long_to_bignum (n));
+}
+
+SCM
+scm_integer_from_uint32 (uint32_t n)
+{
+ if (SCM_POSFIXABLE (n))
+ return SCM_I_MAKINUM (n);
+ return scm_from_bignum (ulong_to_bignum (n));
+}
+
+int
+scm_integer_to_int32_z (struct scm_bignum *z, int32_t *val)
+{
+ return bignum_to_int32 (z, val);
+}
+
+int
+scm_integer_to_uint32_z (struct scm_bignum *z, uint32_t *val)
+{
+ return bignum_to_uint32 (z, val);
+}
+#endif
+
SCM
scm_integer_from_int64 (int64_t n)
{
diff --git a/libguile/integers.h b/libguile/integers.h
index 8bf91f567..f8d150119 100644
--- a/libguile/integers.h
+++ b/libguile/integers.h
@@ -199,9 +199,15 @@ SCM_INTERNAL SCM scm_integer_exact_quotient_zi (struct
scm_bignum *n,
SCM_INTERNAL SCM scm_integer_exact_quotient_zz (struct scm_bignum *n,
struct scm_bignum *d);
+#if SCM_SIZEOF_LONG == 4
+SCM_INTERNAL SCM scm_integer_from_int32 (int32_t n);
+SCM_INTERNAL SCM scm_integer_from_uint32 (uint32_t n);
+SCM_INTERNAL int scm_integer_to_int32_z (struct scm_bignum *z, int32_t *val);
+SCM_INTERNAL int scm_integer_to_uint32_z (struct scm_bignum *z, uint32_t *val);
+#endif
+
SCM_INTERNAL int scm_integer_to_int64_z (struct scm_bignum *z, int64_t *val);
SCM_INTERNAL int scm_integer_to_uint64_z (struct scm_bignum *z, uint64_t *val);
-
SCM_INTERNAL SCM scm_integer_from_int64 (int64_t n);
SCM_INTERNAL SCM scm_integer_from_uint64 (uint64_t n);
diff --git a/libguile/numbers.c b/libguile/numbers.c
index b1ef37752..22321ebb2 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -6958,21 +6958,74 @@ scm_from_uint16 (uint16_t arg)
return SCM_I_MAKINUM (arg);
}
-#define TYPE int32_t
-#define TYPE_MIN INT32_MIN
-#define TYPE_MAX INT32_MAX
-#define SIZEOF_TYPE 4
-#define SCM_TO_TYPE_PROTO(arg) scm_to_int32 (arg)
-#define SCM_FROM_TYPE_PROTO(arg) scm_from_int32 (arg)
-#include "conv-integer.i.c"
+int32_t
+scm_to_int32 (SCM arg)
+{
+#if SCM_SIZEOF_LONG == 4
+ if (SCM_I_INUMP (arg))
+ return SCM_I_INUM (arg);
+ else if (!SCM_BIGP (arg))
+ scm_wrong_type_arg_msg (NULL, 0, arg, "exact integer");
+ int32_t ret;
+ if (scm_integer_to_int32_z (scm_bignum (arg), &ret))
+ return ret;
+ range_error (arg, scm_integer_from_int32 (INT32_MIN),
+ scm_integer_from_int32 (INT32_MAX));
+#elif SCM_SIZEOF_LONG == 8
+ return inum_in_range (arg, INT32_MIN, INT32_MAX);
+#else
+#error bad inum size
+#endif
+}
-#define TYPE uint32_t
-#define TYPE_MIN 0
-#define TYPE_MAX UINT32_MAX
-#define SIZEOF_TYPE 4
-#define SCM_TO_TYPE_PROTO(arg) scm_to_uint32 (arg)
-#define SCM_FROM_TYPE_PROTO(arg) scm_from_uint32 (arg)
-#include "conv-uinteger.i.c"
+SCM
+scm_from_int32 (int32_t arg)
+{
+#if SCM_SIZEOF_LONG == 4
+ return scm_integer_from_int32 (arg);
+#elif SCM_SIZEOF_LONG == 8
+ return SCM_I_MAKINUM (arg);
+#else
+#error bad inum size
+#endif
+}
+
+uint32_t
+scm_to_uint32 (SCM arg)
+{
+#if SCM_SIZEOF_LONG == 4
+ if (SCM_I_INUMP (arg))
+ {
+ if (SCM_I_INUM (arg) > 0)
+ return SCM_I_INUM (arg);
+ }
+ else if (SCM_BIGP (arg))
+ {
+ uint32_t ret;
+ if (scm_integer_to_uint32_z (scm_bignum (arg), &ret))
+ return ret;
+ }
+ else
+ scm_wrong_type_arg_msg (NULL, 0, arg, "exact integer");
+ range_error (arg, 0, scm_integer_from_uint32 (UINT32_MAX));
+#elif SCM_SIZEOF_LONG == 8
+ return inum_in_range (arg, 0, UINT32_MAX);
+#else
+#error bad inum size
+#endif
+}
+
+SCM
+scm_from_uint32 (uint32_t arg)
+{
+#if SCM_SIZEOF_LONG == 4
+ return scm_integer_from_uint32 (arg);
+#elif SCM_SIZEOF_LONG == 8
+ return SCM_I_MAKINUM (arg);
+#else
+#error bad inum size
+#endif
+}
#define TYPE scm_t_wchar
#define TYPE_MIN (int32_t)-1
- [Guile-commits] 43/69: Simplify scm_difference, use integer lib, (continued)
- [Guile-commits] 43/69: Simplify scm_difference, use integer lib, Andy Wingo, 2022/01/07
- [Guile-commits] 44/69: Simplify scm_product, use integer lib, Andy Wingo, 2022/01/07
- [Guile-commits] 52/69: Reimplement scm_{to,from}_{int64,uint64}, Andy Wingo, 2022/01/07
- [Guile-commits] 53/69: Implement scm_{to,from}_wchar inline, Andy Wingo, 2022/01/07
- [Guile-commits] 60/69: divide2double refactor, Andy Wingo, 2022/01/07
- [Guile-commits] 65/69: Avoid scm_i_mkbig outside numbers.c., Andy Wingo, 2022/01/07
- [Guile-commits] 57/69: Refactor scm_sqrt in terms of integers.[ch], Andy Wingo, 2022/01/07
- [Guile-commits] 59/69: Remove dead bignum frexp code from numbers.c, Andy Wingo, 2022/01/07
- [Guile-commits] 47/69: Fix deprecated bit-count* when counting 0 bits, Andy Wingo, 2022/01/07
- [Guile-commits] 49/69: Reimplement scm_is_{un, }signed_integer for bignums, Andy Wingo, 2022/01/07
- [Guile-commits] 51/69: Reimplement scm_{to,from}_{int32,uint32},
Andy Wingo <=
- [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, 2022/01/07