diff options
author | Kevin Ryde <user42@zip.com.au> | 2004-04-27 21:56:01 +0000 |
---|---|---|
committer | Kevin Ryde <user42@zip.com.au> | 2004-04-27 21:56:01 +0000 |
commit | e45fb186184ccedc7bd65f78f099e1a06875c818 (patch) | |
tree | a5f37610dd23903809684ac5489f9dae41492c29 /libguile/num2integral.i.c | |
parent | 36245b66c222110c84b04e14733614055dc36575 (diff) | |
download | guile-e45fb186184ccedc7bd65f78f099e1a06875c818.tar.gz |
(NUM2INTEGRAL): Under non-BIGMPZ_FITSP case,
corrections to range check for signed numbers. Remove
scm_remember_upto_here_1(num) from these checks, since num is used
subsequently anyway.
Diffstat (limited to 'libguile/num2integral.i.c')
-rw-r--r-- | libguile/num2integral.i.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/libguile/num2integral.i.c b/libguile/num2integral.i.c index 85cd4b10b..7d792ce55 100644 --- a/libguile/num2integral.i.c +++ b/libguile/num2integral.i.c @@ -88,19 +88,44 @@ NUM2INTEGRAL (SCM num, unsigned long int pos, const char *s_caller) } else { + size_t itype_bits = sizeof (ITYPE) * SCM_CHAR_BIT; + int sgn = mpz_sgn (SCM_I_BIG_MPZ (num)); size_t numbits; + if (UNSIGNED) { - int sgn = mpz_sgn (SCM_I_BIG_MPZ (num)); - scm_remember_upto_here_1 (num); if (sgn < 0) scm_out_of_range (s_caller, num); } - + numbits = mpz_sizeinbase (SCM_I_BIG_MPZ (num), 2); - scm_remember_upto_here_1 (num); - if (numbits > (sizeof (ITYPE) * SCM_CHAR_BIT)) - scm_out_of_range (s_caller, num); + + if (UNSIGNED) + { + if (numbits > itype_bits) + scm_out_of_range (s_caller, num); + } + else + { + if (sgn >= 0) + { + /* positive, require num < 2^(itype_bits-1) */ + if (numbits > itype_bits-1) + scm_out_of_range (s_caller, num); + } + else + { + /* negative, require abs(num) < 2^(itype_bits-1), but + also allow num == -2^(itype_bits-1), the latter + detected by numbits==itype_bits plus the lowest + (and only) 1 bit at position itype_bits-1 */ + if (numbits > itype_bits + || (numbits == itype_bits + && (mpz_scan1 (SCM_I_BIG_MPZ (num), 0) + != itype_bits - 1))) + scm_out_of_range (s_caller, num); + } + } } if (UNSIGNED && (SIZEOF_ITYPE <= SIZEOF_UNSIGNED_LONG)) |