[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 49/85: Reimplement scm_from_int8 etc
From: |
Andy Wingo |
Subject: |
[Guile-commits] 49/85: Reimplement scm_from_int8 etc |
Date: |
Thu, 13 Jan 2022 03:40:21 -0500 (EST) |
wingo pushed a commit to branch main
in repository guile.
commit 27910181c53a7f836bfc8dc9c5619e2e3110eeaf
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Thu Jan 6 20:12:06 2022 +0100
Reimplement scm_from_int8 etc
* libguile/integers.c (make_bignum_from_uint64):
(make_bignum_from_int64): New helpers.
(scm_integer_from_int64):
(scm_integer_from_uint64): New internal functions.
* libguile/integers.h: Declare new internal functions.
* libguile/numbers.c (range_error): Declare as noreturn.xo
(inum_in_range): New helper.
(scm_from_signed_integer):
(scm_to_signed_integer):
(scm_from_unsigned_integer):
(scm_to_unsigned_integer):
(scm_to_int8):
(scm_from_int8):
(scm_to_uint8):
(scm_from_uint8):
(scm_to_int16):
(scm_from_int16):
(scm_to_uint16):
(scm_from_uint16): Implement manually.
---
libguile/integers.c | 41 ++++++++++++++
libguile/integers.h | 3 +
libguile/numbers.c | 157 ++++++++++++++++++++++++++++++++++++++--------------
3 files changed, 158 insertions(+), 43 deletions(-)
diff --git a/libguile/integers.c b/libguile/integers.c
index b8cb1a908..9ec42694f 100644
--- a/libguile/integers.c
+++ b/libguile/integers.c
@@ -182,6 +182,31 @@ make_bignum_1 (int is_negative, mp_limb_t limb)
return is_negative ? negate_bignum(z) : z;
}
+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;
+#endif
+}
+
+static struct scm_bignum *
+make_bignum_from_int64 (int64_t val)
+{
+ return val < 0
+ ? negate_bignum (make_bignum_from_uint64 (int64_magnitude (val)))
+ : make_bignum_from_uint64 (val);
+}
+
static struct scm_bignum *
ulong_to_bignum (unsigned long u)
{
@@ -2896,6 +2921,22 @@ scm_integer_exact_quotient_zz (struct scm_bignum *n,
struct scm_bignum *d)
return take_mpz (q);
}
+SCM
+scm_integer_from_int64 (int64_t n)
+{
+ if (SCM_FIXABLE (n))
+ return SCM_I_MAKINUM (n);
+ return scm_from_bignum (make_bignum_from_int64 (n));
+}
+
+SCM
+scm_integer_from_uint64 (uint64_t n)
+{
+ if (SCM_POSFIXABLE (n))
+ return SCM_I_MAKINUM (n);
+ return scm_from_bignum (make_bignum_from_uint64 (n));
+}
+
int
scm_integer_to_int64_z (struct scm_bignum *z, int64_t *val)
{
diff --git a/libguile/integers.h b/libguile/integers.h
index 60e3ea9bd..8bf91f567 100644
--- a/libguile/integers.h
+++ b/libguile/integers.h
@@ -202,6 +202,9 @@ SCM_INTERNAL SCM scm_integer_exact_quotient_zz (struct
scm_bignum *n,
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);
+
#endif /* SCM_INTEGERS_H */
diff --git a/libguile/numbers.c b/libguile/numbers.c
index 8657a6ebe..b1ef37752 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -6829,8 +6829,9 @@ scm_is_unsigned_integer (SCM val, uintmax_t min,
uintmax_t max)
return 0;
}
+static void range_error (SCM bad_val, SCM min, SCM max) SCM_NORETURN;
static void
-scm_i_range_error (SCM bad_val, SCM min, SCM max)
+range_error (SCM bad_val, SCM min, SCM max)
{
scm_error (scm_out_of_range_key,
NULL,
@@ -6838,54 +6839,124 @@ scm_i_range_error (SCM bad_val, SCM min, SCM max)
scm_list_3 (min, max, bad_val),
scm_list_1 (bad_val));
}
+#define scm_i_range_error range_error
-#define TYPE intmax_t
-#define TYPE_MIN min
-#define TYPE_MAX max
-#define SIZEOF_TYPE 0
-#define SCM_TO_TYPE_PROTO(arg) scm_to_signed_integer (arg, intmax_t min,
intmax_t max)
-#define SCM_FROM_TYPE_PROTO(arg) scm_from_signed_integer (arg)
-#include "conv-integer.i.c"
+static scm_t_inum
+inum_in_range (SCM x, scm_t_inum min, scm_t_inum max)
+{
+ if (SCM_LIKELY (SCM_I_INUMP (x)))
+ {
+ scm_t_inum val = SCM_I_INUM (x);
+ if (min <= val && val <= max)
+ return val;
+ }
+ else if (!SCM_BIGP (x))
+ scm_wrong_type_arg_msg (NULL, 0, x, "exact integer");
+ range_error (x, scm_from_long (min), scm_from_long (max));
+}
-#define TYPE uintmax_t
-#define TYPE_MIN min
-#define TYPE_MAX max
-#define SIZEOF_TYPE 0
-#define SCM_TO_TYPE_PROTO(arg) scm_to_unsigned_integer (arg, uintmax_t min,
uintmax_t max)
-#define SCM_FROM_TYPE_PROTO(arg) scm_from_unsigned_integer (arg)
-#include "conv-uinteger.i.c"
+SCM
+scm_from_signed_integer (intmax_t arg)
+{
+ return scm_integer_from_int64 (arg);
+}
-#define TYPE int8_t
-#define TYPE_MIN INT8_MIN
-#define TYPE_MAX INT8_MAX
-#define SIZEOF_TYPE 1
-#define SCM_TO_TYPE_PROTO(arg) scm_to_int8 (arg)
-#define SCM_FROM_TYPE_PROTO(arg) scm_from_int8 (arg)
-#include "conv-integer.i.c"
+intmax_t
+scm_to_signed_integer (SCM arg, intmax_t min, intmax_t max)
+{
+ int64_t ret;
+ if (SCM_I_INUMP (arg))
+ ret = SCM_I_INUM (arg);
+ else if (SCM_BIGP (arg))
+ {
+ if (!scm_integer_to_int64_z (scm_bignum (arg), &ret))
+ goto out_of_range;
+ }
+ else
+ scm_wrong_type_arg_msg (NULL, 0, arg, "exact integer");
+ if (min <= ret && ret <= max)
+ return ret;
+ out_of_range:
+ range_error (arg, scm_from_intmax (min), scm_from_intmax (max));
+}
-#define TYPE uint8_t
-#define TYPE_MIN 0
-#define TYPE_MAX UINT8_MAX
-#define SIZEOF_TYPE 1
-#define SCM_TO_TYPE_PROTO(arg) scm_to_uint8 (arg)
-#define SCM_FROM_TYPE_PROTO(arg) scm_from_uint8 (arg)
-#include "conv-uinteger.i.c"
+SCM
+scm_from_unsigned_integer (uintmax_t arg)
+{
+ return scm_integer_from_uint64 (arg);
+}
-#define TYPE int16_t
-#define TYPE_MIN INT16_MIN
-#define TYPE_MAX INT16_MAX
-#define SIZEOF_TYPE 2
-#define SCM_TO_TYPE_PROTO(arg) scm_to_int16 (arg)
-#define SCM_FROM_TYPE_PROTO(arg) scm_from_int16 (arg)
-#include "conv-integer.i.c"
+uintmax_t
+scm_to_unsigned_integer (SCM arg, uintmax_t min, uintmax_t max)
+{
+ uint64_t ret;
+ if (SCM_I_INUMP (arg))
+ {
+ scm_t_inum n = SCM_I_INUM (arg);
+ if (n < 0)
+ goto out_of_range;
+ ret = n;
+ }
+ else if (SCM_BIGP (arg))
+ {
+ if (!scm_integer_to_uint64_z (scm_bignum (arg), &ret))
+ goto out_of_range;
+ }
+ else
+ scm_wrong_type_arg_msg (NULL, 0, arg, "exact integer");
+ if (min <= ret && ret <= max)
+ return ret;
+ out_of_range:
+ range_error (arg, scm_from_uintmax (min), scm_from_uintmax (max));
+}
-#define TYPE uint16_t
-#define TYPE_MIN 0
-#define TYPE_MAX UINT16_MAX
-#define SIZEOF_TYPE 2
-#define SCM_TO_TYPE_PROTO(arg) scm_to_uint16 (arg)
-#define SCM_FROM_TYPE_PROTO(arg) scm_from_uint16 (arg)
-#include "conv-uinteger.i.c"
+int8_t
+scm_to_int8 (SCM arg)
+{
+ return inum_in_range (arg, INT8_MIN, INT8_MAX);
+}
+
+SCM
+scm_from_int8 (int8_t arg)
+{
+ return SCM_I_MAKINUM (arg);
+}
+
+uint8_t
+scm_to_uint8 (SCM arg)
+{
+ return inum_in_range (arg, 0, UINT8_MAX);
+}
+
+SCM
+scm_from_uint8 (uint8_t arg)
+{
+ return SCM_I_MAKINUM (arg);
+}
+
+int16_t
+scm_to_int16 (SCM arg)
+{
+ return inum_in_range (arg, INT16_MIN, INT16_MAX);
+}
+
+SCM
+scm_from_int16 (int16_t arg)
+{
+ return SCM_I_MAKINUM (arg);
+}
+
+uint16_t
+scm_to_uint16 (SCM arg)
+{
+ return inum_in_range (arg, 0, UINT16_MAX);
+}
+
+SCM
+scm_from_uint16 (uint16_t arg)
+{
+ return SCM_I_MAKINUM (arg);
+}
#define TYPE int32_t
#define TYPE_MIN INT32_MIN
- [Guile-commits] 66/85: Finish srfi-60 port off old scm mpz API, (continued)
- [Guile-commits] 66/85: Finish srfi-60 port off old scm mpz API, Andy Wingo, 2022/01/13
- [Guile-commits] 74/85: Less pessimal scm_integer_sub_zi, Andy Wingo, 2022/01/13
- [Guile-commits] 76/85: Avoid bignum clone in scm_integer_sub_zz, Andy Wingo, 2022/01/13
- [Guile-commits] 79/85: Optimize scm_integer_mul_ii, Andy Wingo, 2022/01/13
- [Guile-commits] 80/85: Optimize integer-expt for fixnums, Andy Wingo, 2022/01/13
- [Guile-commits] 81/85: Optimize logand against a positive inum, Andy Wingo, 2022/01/13
- [Guile-commits] 82/85: Simplify scm_abs for the real case, Andy Wingo, 2022/01/13
- [Guile-commits] 09/85: Implement ceiling-divide with new integer lib, Andy Wingo, 2022/01/13
- [Guile-commits] 08/85: Implement ceiling-remainder with new integer lib, Andy Wingo, 2022/01/13
- [Guile-commits] 11/85: Implement truncate-remainder with new integer lib, Andy Wingo, 2022/01/13
- [Guile-commits] 49/85: Reimplement scm_from_int8 etc,
Andy Wingo <=
- [Guile-commits] 55/85: Reimplement exact-integer-sqrt with integers.[ch], Andy Wingo, 2022/01/13
- [Guile-commits] 56/85: Refactor scm_sqrt in terms of integers.[ch], Andy Wingo, 2022/01/13
- [Guile-commits] 62/85: Simplify magnitude, angle, Andy Wingo, 2022/01/13
- [Guile-commits] 65/85: Start porting srfi-60 off the bad bignum interfaces, Andy Wingo, 2022/01/13
- [Guile-commits] 72/85: Optimize scm_integer_mul_zi, Andy Wingo, 2022/01/13
- [Guile-commits] 75/85: Start to optimize scm_integer_sub_iz, Andy Wingo, 2022/01/13
- [Guile-commits] 77/85: Optimize bignum add to avoid temporary allocations, Andy Wingo, 2022/01/13