summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_float.py102
-rw-r--r--Lib/test/test_strtod.py6
2 files changed, 6 insertions, 102 deletions
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py
index cabeb16..5932b96 100644
--- a/Lib/test/test_float.py
+++ b/Lib/test/test_float.py
@@ -7,7 +7,6 @@ import math
from math import isinf, isnan, copysign, ldexp
import operator
import random, fractions
-import re
INF = float("inf")
NAN = float("nan")
@@ -21,74 +20,6 @@ requires_IEEE_754 = unittest.skipUnless(
test_dir = os.path.dirname(__file__) or os.curdir
format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
-finite_decimal_parser = re.compile(r""" # A numeric string consists of:
- (?P<sign>[-+])? # an optional sign, followed by
- (?=\d|\.\d) # a number with at least one digit
- (?P<int>\d*) # having a (possibly empty) integer part
- (?:\.(?P<frac>\d*))? # followed by an optional fractional part
- (?:E(?P<exp>[-+]?\d+))? # and an optional exponent
- \Z
-""", re.VERBOSE | re.IGNORECASE | re.UNICODE).match
-
-# Pure Python version of correctly rounded string->float conversion.
-# Avoids any use of floating-point by returning the result as a hex string.
-def strtod(s, mant_dig=53, min_exp = -1021, max_exp = 1024):
- """Convert a finite decimal string to a hex string representing an
- IEEE 754 binary64 float. Return 'inf' or '-inf' on overflow.
- This function makes no use of floating-point arithmetic at any
- stage."""
-
- # parse string into a pair of integers 'a' and 'b' such that
- # abs(decimal value) = a/b, and a boolean 'negative'.
- m = finite_decimal_parser(s)
- if m is None:
- raise ValueError('invalid numeric string')
- fraction = m.group('frac') or ''
- intpart = int(m.group('int') + fraction)
- exp = int(m.group('exp') or '0') - len(fraction)
- negative = m.group('sign') == '-'
- a, b = intpart*10**max(exp, 0), 10**max(0, -exp)
-
- # quick return for zeros
- if not a:
- return '-0x0.0p+0' if negative else '0x0.0p+0'
-
- # compute exponent e for result; may be one too small in the case
- # that the rounded value of a/b lies in a different binade from a/b
- d = a.bit_length() - b.bit_length()
- d += (a >> d if d >= 0 else a << -d) >= b
- e = max(d, min_exp) - mant_dig
-
- # approximate a/b by number of the form q * 2**e; adjust e if necessary
- a, b = a << max(-e, 0), b << max(e, 0)
- q, r = divmod(a, b)
- if 2*r > b or 2*r == b and q & 1:
- q += 1
- if q.bit_length() == mant_dig+1:
- q //= 2
- e += 1
-
- # double check that (q, e) has the right form
- assert q.bit_length() <= mant_dig and e >= min_exp - mant_dig
- assert q.bit_length() == mant_dig or e == min_exp - mant_dig
-
- # check for overflow and underflow
- if e + q.bit_length() > max_exp:
- return '-inf' if negative else 'inf'
- if not q:
- return '-0x0.0p+0' if negative else '0x0.0p+0'
-
- # for hex representation, shift so # bits after point is a multiple of 4
- hexdigs = 1 + (mant_dig-2)//4
- shift = 3 - (mant_dig-2)%4
- q, e = q << shift, e - shift
- return '{}0x{:x}.{:0{}x}p{:+d}'.format(
- '-' if negative else '',
- q // 16**hexdigs,
- q % 16**hexdigs,
- hexdigs,
- e + 4*hexdigs)
-
class GeneralFloatCases(unittest.TestCase):
def test_float(self):
@@ -1334,38 +1265,6 @@ class HexFloatTestCase(unittest.TestCase):
else:
self.identical(x, fromHex(toHex(x)))
-class StrtodTestCase(unittest.TestCase):
- def check_string(self, s):
- expected = strtod(s)
- try:
- fs = float(s)
- except OverflowError:
- got = '-inf' if s[0] == '-' else 'inf'
- else:
- got = fs.hex()
- self.assertEqual(expected, got,
- "Incorrectly rounded str->float conversion for "
- "{}: expected {}, got {}".format(s, expected, got))
-
- @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
- "applies only when using short float repr style")
- def test_bug7632(self):
- # check a few particular values that gave incorrectly rounded
- # results with previous versions of dtoa.c
- test_strings = [
- '94393431193180696942841837085033647913224148539854e-358',
- '12579816049008305546974391768996369464963024663104e-357',
- '17489628565202117263145367596028389348922981857013e-357',
- '18487398785991994634182916638542680759613590482273e-357',
- '32002864200581033134358724675198044527469366773928e-358',
- '73608278998966969345824653500136787876436005957953e-358',
- '64774478836417299491718435234611299336288082136054e-358',
- '13704940134126574534878641876947980878824688451169e-357',
- '46697445774047060960624497964425416610480524760471e-358',
- ]
- for s in test_strings:
- self.check_string(s)
-
def test_main():
support.run_unittest(
@@ -1378,7 +1277,6 @@ def test_main():
RoundTestCase,
InfNanTest,
HexFloatTestCase,
- StrtodTestCase,
)
if __name__ == '__main__':
diff --git a/Lib/test/test_strtod.py b/Lib/test/test_strtod.py
index e99693c..127e868 100644
--- a/Lib/test/test_strtod.py
+++ b/Lib/test/test_strtod.py
@@ -23,6 +23,8 @@ strtod_parser = re.compile(r""" # A numeric string consists of:
\Z
""", re.VERBOSE | re.IGNORECASE).match
+# Pure Python version of correctly rounded string->float conversion.
+# Avoids any use of floating-point by returning the result as a hex string.
def strtod(s, mant_dig=53, min_exp = -1021, max_exp = 1024):
"""Convert a finite decimal string to a hex string representing an
IEEE 754 binary64 float. Return 'inf' or '-inf' on overflow.
@@ -259,6 +261,10 @@ class StrtodTests(unittest.TestCase):
'18487398785991994634182916638542680759613590482273e-357',
'32002864200581033134358724675198044527469366773928e-358',
'94393431193180696942841837085033647913224148539854e-358',
+ '73608278998966969345824653500136787876436005957953e-358',
+ '64774478836417299491718435234611299336288082136054e-358',
+ '13704940134126574534878641876947980878824688451169e-357',
+ '46697445774047060960624497964425416610480524760471e-358',
# failing case for bug introduced by METD in r77451 (attempted
# fix for issue 7632, bug 2), and fixed in r77482.
'28639097178261763178489759107321392745108491825303e-311',