diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | arith.c | 11 | ||||
-rw-r--r-- | arith.h | 1 | ||||
-rw-r--r-- | lib.c | 17 |
4 files changed, 34 insertions, 6 deletions
@@ -12,6 +12,17 @@ * dep.mk: Regenerated. +2012-10-01 Kaz Kylheku <kaz@kylheku.com> + + * arith.c (bignum_from_long): New function. + + * arith.h (bignum_from_long): Declared. + + * lib.c (int_str): Streamlined. Only use mp_read_radix in the case when + wcstol fails, because now we have bignum_from_long to handle all values + of long. Ensure that the bignum is normalized, in case it falls in the + fixnum range (does not happen on our usual platforms). + 2012-09-25 Kaz Kylheku <kaz@kylheku.com> * eval.c: Allow the test form of a for loop to be omitted, @@ -68,6 +68,17 @@ val bignum(cnum cn) return n; } +val bignum_from_long(long l) +{ +#if SIZEOF_LONG <= SIZEOF_PTR + return bignum(l); +#else + val n = make_bignum(); + mp_set_int(mp(n), l); + return n; +#endif +} + #if HAVE_DOUBLE_INTPTR_T static val bignum_dbl_ipt(double_intptr_t di) @@ -26,6 +26,7 @@ val make_bignum(void); val bignum(cnum cn); +val bignum_from_long(long l); int highest_bit(int_ptr_t n); val normalize(val bignum); val in_int_ptr_range(val bignum); @@ -2103,11 +2103,11 @@ val int_str(val str, val base) /* TODO: detect if we have wcstoll */ long value = wcstol(wcs, &ptr, b ? b : 10); + if (value == 0 && ptr == wcs) return nil; - if (((value == LONG_MAX || value == LONG_MIN) && errno == ERANGE) || - (value < NUM_MIN || value > NUM_MAX)) - { + + if ((value == LONG_MAX || value == LONG_MIN) && errno == ERANGE) { val bignum = make_bignum(); unsigned char *ucs = utf8_dup_to_uc(wcs); mp_err err = mp_read_radix(mp(bignum), ucs, b); @@ -2117,10 +2117,15 @@ val int_str(val str, val base) if (err != MP_OKAY) return nil; - return bignum; - } + /* If wcstol overflowed, but the range of long is smaller than + that of fixnums, that means that the value might not + actually be a bignum, and so we must normalize. + We do not need this on our usual target platforms, where NUM_MAX is + never larger than LONG_MAX. */ + return (LONG_MAX < NUM_MAX) ? normalize(bignum) : bignum; + } - return num(value); + return bignum_from_long(value); } val flo_str(val str) |