From bc94bb205b91ab9f93879a7bd1339a641ffcbecd Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 25 Jan 2019 06:33:29 -0800 Subject: 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. --- arith.c | 41 ++--------------------------------------- lib.c | 2 +- mpi/mpi.c | 31 +++++++++++++++++++++++++++++++ mpi/mpi.h | 3 +++ 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 -- cgit v1.2.3