|
|
|
#!/usr/bin/env python2
|
|
|
|
#
|
|
|
|
# Generate a table indicating how many digits should be considered
|
|
|
|
# significant for each radix (2 to 36) when doing string-to-number
|
|
|
|
# conversion.
|
|
|
|
#
|
|
|
|
# For decimal, the E5/E5.1 specification indicates that anything
|
|
|
|
# after the 20th digit can be ignored (treated as zero) and the
|
|
|
|
# 20th digit can be rounded upwards. We estimate the significant
|
|
|
|
# bits of precision from this and compute similar values for other
|
|
|
|
# radix values.
|
|
|
|
#
|
|
|
|
# Also generate a table of minimum and maximum radix-specific
|
|
|
|
# exponent values above and below which a number is guaranteed
|
|
|
|
# to overflow to Infinity or underflow to zero. This allows the
|
|
|
|
# C code to quick reject such exponent values, and to keep bigint
|
|
|
|
# values bounded. The exponent limit is relative to an integer
|
|
|
|
# significand padded to the precision-related digit count (e.g.
|
|
|
|
# 20 for decimal).
|
|
|
|
#
|
|
|
|
|
|
|
|
import math
|
|
|
|
|
|
|
|
digits_table = []
|
|
|
|
limits_table = []
|
|
|
|
|
|
|
|
for radix in xrange(2, 36+1):
|
|
|
|
bits_per_digit = math.log(radix, 2)
|
|
|
|
|
|
|
|
if radix == 10:
|
|
|
|
prec_digits = 20
|
|
|
|
else:
|
|
|
|
target_bits = math.ceil(math.log(10, 2) * 20) + 2 # +2 is extra, just in case
|
|
|
|
prec_digits = int(math.ceil(target_bits / bits_per_digit))
|
|
|
|
digits_table.append(prec_digits)
|
|
|
|
|
|
|
|
# these are conservative (details are off by one etc); +/- 2 is the extra
|
|
|
|
overflow_limit = int(math.ceil(1024.0 / bits_per_digit)) + 2 - prec_digits
|
|
|
|
underflow_limit = int(math.floor((-1024.0 - 52.0) / bits_per_digit)) - 2 - prec_digits
|
|
|
|
|
|
|
|
limits_table.append(overflow_limit)
|
|
|
|
limits_table.append(underflow_limit)
|
|
|
|
|
|
|
|
print repr(digits_table)
|
|
|
|
print repr(limits_table)
|