summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-01-25 06:33:29 -0800
committerKaz Kylheku <kaz@kylheku.com>2019-01-25 06:33:29 -0800
commit4c71a77f2c39a8158c80b40af1a5cc2358251a00 (patch)
treef3c49877aed2a6898b89662f06a17cbc06c080ca
parent8195fbed4a8067362656d38e56fec3c4eb3deef1 (diff)
downloadtxr-4c71a77f2c39a8158c80b40af1a5cc2358251a00.tar.gz
txr-4c71a77f2c39a8158c80b40af1a5cc2358251a00.tar.bz2
txr-4c71a77f2c39a8158c80b40af1a5cc2358251a00.zip
Provide faster bignum-in-fixed-integer range tests in MPI.
* mpi/mpi.c (mp_in_range, mp_in_intptr_range, mp_in_uintptr_range): New functions. * mpi/mpi.h (mp_in_range, mp_in_intptr_range, mp_in_uintptr_range): Declared. * arith.c (NUM_MAX_MP, INT_PTR_MAX_MP, UINT_PTR_MAX_MP, INT_PTR_MAX_SUCC_MP): Static variables removed. Note that INT_PTR_MAX_MP was not used at all! (normalize): Use mp_in_range instead magnitude comparison to NUM_MAX_MP. (in_int_ptr_range, in_uint_ptr_range): Static functions removed. (c_unum): Use mp_in_uintptr_range instead of in_uint_ptr_range. (arith_init): Remove initializations of removed variables. (arith_free_all): Remove cleanup of removed variables, leaving function empty. * lib.c (c_num): Use mp_in_intptr_range instead of in_int_ptr_range.
-rw-r--r--arith.c41
-rw-r--r--lib.c2
-rw-r--r--mpi/mpi.c31
-rw-r--r--mpi/mpi.h3
4 files changed, 37 insertions, 40 deletions
diff --git a/arith.c b/arith.c
index 8bc459ca..f349b57a 100644
--- a/arith.c
+++ b/arith.c
@@ -54,9 +54,6 @@
#define CNUM_BIT ((int) sizeof (cnum) * CHAR_BIT)
#define ABS(A) ((A) < 0 ? -(A) : (A))
-static mp_int NUM_MAX_MP, INT_PTR_MAX_MP, UINT_PTR_MAX_MP;
-static mp_int INT_PTR_MAX_SUCC_MP;
-
val make_bignum(void)
{
val n = make_obj();
@@ -165,7 +162,7 @@ val bignum_dbl_ipt(double_intptr_t di)
val normalize(val bignum)
{
- if (mp_cmp_mag(mp(bignum), &NUM_MAX_MP) == MP_GT) {
+ if (!mp_in_range(mp(bignum), NUM_MAX, 0)) {
return bignum;
} else {
cnum fixnum;
@@ -174,27 +171,6 @@ val normalize(val bignum)
}
}
-val in_int_ptr_range(val bignum)
-{
- switch (mp_cmp_mag(mp(bignum), &INT_PTR_MAX_SUCC_MP)) {
- default:
- case MP_GT:
- return nil;
- case MP_EQ:
- if (mp_cmp_z(mp(bignum)) == MP_GT)
- return nil;
- /* fallthrough */
- case MP_LT:
- return t;
- }
-}
-
-static val in_uint_ptr_range(val bignum)
-{
- return (mp_cmp_z(mp(bignum)) == MP_LT ||
- mp_cmp_mag(mp(bignum), &UINT_PTR_MAX_MP) == MP_GT) ? nil : t;
-}
-
ucnum c_unum(val num)
{
switch (type(num)) {
@@ -206,7 +182,7 @@ ucnum c_unum(val num)
}
goto range;
case BGNUM:
- if (in_uint_ptr_range(num)) {
+ if (mp_in_uintptr_range(mp(num))) {
uint_ptr_t out;
mp_get_uintptr(mp(num), &out);
return out;
@@ -3348,15 +3324,6 @@ static val flo_set_round_mode(val mode)
void arith_init(void)
{
- mp_init(&NUM_MAX_MP);
- mp_set_intptr(&NUM_MAX_MP, NUM_MAX);
- mp_init(&INT_PTR_MAX_MP);
- mp_set_intptr(&INT_PTR_MAX_MP, INT_PTR_MAX);
- mp_init(&UINT_PTR_MAX_MP);
- mp_set_uintptr(&UINT_PTR_MAX_MP, -1);
- mp_init(&INT_PTR_MAX_SUCC_MP);
- mp_set_intptr(&INT_PTR_MAX_SUCC_MP, INT_PTR_MIN - 1);
- mp_neg(&INT_PTR_MAX_SUCC_MP, &INT_PTR_MAX_SUCC_MP);
log2_init();
if (opt_compat && opt_compat <= 199) {
@@ -3423,8 +3390,4 @@ void arith_init(void)
void arith_free_all(void)
{
- mp_clear(&NUM_MAX_MP);
- mp_clear(&INT_PTR_MAX_MP);
- mp_clear(&UINT_PTR_MAX_MP);
- mp_clear(&INT_PTR_MAX_SUCC_MP);
}
diff --git a/lib.c b/lib.c
index 26806b41..7e4edd9c 100644
--- a/lib.c
+++ b/lib.c
@@ -3105,7 +3105,7 @@ cnum c_num(val n)
case CHR: case NUM:
return coerce(cnum, n) >> TAG_SHIFT;
case BGNUM:
- if (in_int_ptr_range(n)) {
+ if (mp_in_intptr_range(mp(n))) {
int_ptr_t out;
mp_get_intptr(mp(n), &out);
return out;
diff --git a/mpi/mpi.c b/mpi/mpi.c
index ff11f2e2..2097b574 100644
--- a/mpi/mpi.c
+++ b/mpi/mpi.c
@@ -469,6 +469,37 @@ mp_err mp_get_intptr(mp_int *mp, int_ptr_t *z)
return MP_OKAY;
}
+int mp_in_range(mp_int *mp, uint_ptr_t lim, int unsig)
+{
+ const int ptrnd = (SIZEOF_PTR + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT;
+ mp_size nd = USED(mp);
+
+ if (unsig && ISNEG(mp))
+ return 0;
+
+ if (nd < ptrnd)
+ return 1;
+
+ if (nd > ptrnd)
+ return 0;
+
+ {
+ mp_digit top = DIGITS(mp)[ptrnd - 1];
+ lim >>= ((ptrnd - 1) * MP_DIGIT_BIT);
+ return top <= lim;
+ }
+}
+
+int mp_in_intptr_range(mp_int *mp)
+{
+ return mp_in_range(mp, INT_PTR_MAX, 0);
+}
+
+int mp_in_uintptr_range(mp_int *mp)
+{
+ return mp_in_range(mp, UINT_PTR_MAX, 1);
+}
+
#ifdef HAVE_DOUBLE_INTPTR_T
mp_err mp_set_double_intptr(mp_int *mp, double_intptr_t z)
{
diff --git a/mpi/mpi.h b/mpi/mpi.h
index 28fadb31..71e08055 100644
--- a/mpi/mpi.h
+++ b/mpi/mpi.h
@@ -85,6 +85,9 @@ mp_err mp_set_uintptr(mp_int *mp, uint_ptr_t z);
mp_err mp_set_intptr(mp_int *mp, int_ptr_t z);
mp_err mp_get_uintptr(mp_int *mp, uint_ptr_t *z);
mp_err mp_get_intptr(mp_int *mp, int_ptr_t *z);
+int mp_in_range(mp_int *mp, uint_ptr_t lim, int unsig);
+int mp_in_intptr_range(mp_int *mp);
+int mp_in_uintptr_range(mp_int *mp);
#ifdef HAVE_DOUBLE_INTPTR_T
mp_err mp_set_double_intptr(mp_int *mp, double_intptr_t z);
#endif