@@ -100,6 +100,49 @@ def check_strtod(self, s):
100100 "Incorrectly rounded str->float conversion for {}: "
101101 "expected {}, got {}" .format (s , expected , got ))
102102
103+ def test_short_halfway_cases (self ):
104+ # exact halfway cases with a small number of significant digits
105+ for k in 0 , 5 , 10 , 15 , 20 :
106+ # upper = smallest integer >= 2**54/5**k
107+ upper = - (- 2 ** 54 // 5 ** k )
108+ # lower = smallest odd number >= 2**53/5**k
109+ lower = - (- 2 ** 53 // 5 ** k )
110+ if lower % 2 == 0 :
111+ lower += 1
112+ for i in range (10 * TEST_SIZE ):
113+ # Select a random odd n in [2**53/5**k,
114+ # 2**54/5**k). Then n * 10**k gives a halfway case
115+ # with small number of significant digits.
116+ n , e = random .randrange (lower , upper , 2 ), k
117+
118+ # Remove any additional powers of 5.
119+ while n % 5 == 0 :
120+ n , e = n // 5 , e + 1
121+ assert n % 10 in (1 , 3 , 7 , 9 )
122+
123+ # Try numbers of the form n * 2**p2 * 10**e, p2 >= 0,
124+ # until n * 2**p2 has more than 20 significant digits.
125+ digits , exponent = n , e
126+ while digits < 10 ** 20 :
127+ s = '{}e{}' .format (digits , exponent )
128+ self .check_strtod (s )
129+ # Same again, but with extra trailing zeros.
130+ s = '{}e{}' .format (digits * 10 ** 40 , exponent - 40 )
131+ self .check_strtod (s )
132+ digits *= 2
133+
134+ # Try numbers of the form n * 5**p2 * 10**(e - p5), p5
135+ # >= 0, with n * 5**p5 < 10**20.
136+ digits , exponent = n , e
137+ while digits < 10 ** 20 :
138+ s = '{}e{}' .format (digits , exponent )
139+ self .check_strtod (s )
140+ # Same again, but with extra trailing zeros.
141+ s = '{}e{}' .format (digits * 10 ** 40 , exponent - 40 )
142+ self .check_strtod (s )
143+ digits *= 5
144+ exponent -= 1
145+
103146 def test_halfway_cases (self ):
104147 # test halfway cases for the round-half-to-even rule
105148 for i in range (1000 ):
@@ -164,10 +207,10 @@ def test_underflow_boundary(self):
164207 self .check_strtod (s )
165208
166209 def test_bigcomp (self ):
167- DIG10 = 10 ** 50
168- for i in range ( 1000 ):
169- for j in range (TEST_SIZE ):
170- digits = random .randrange (DIG10 )
210+ for ndigs in 5 , 10 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 40 , 41 , 50 :
211+ dig10 = 10 ** ndigs
212+ for i in range (100 * TEST_SIZE ):
213+ digits = random .randrange (dig10 )
171214 exponent = random .randrange (- 400 , 400 )
172215 s = '{}e{}' .format (digits , exponent )
173216 self .check_strtod (s )
@@ -254,11 +297,59 @@ def test_particular(self):
254297 # demonstration that original fix for issue 7632 bug 1 was
255298 # buggy; the exit condition was too strong
256299 '247032822920623295e-341' ,
300+ # demonstrate similar problem to issue 7632 bug1: crash
301+ # with 'oversized quotient in quorem' message.
302+ '99037485700245683102805043437346965248029601286431e-373' ,
303+ '99617639833743863161109961162881027406769510558457e-373' ,
304+ '98852915025769345295749278351563179840130565591462e-372' ,
305+ '99059944827693569659153042769690930905148015876788e-373' ,
306+ '98914979205069368270421829889078356254059760327101e-372' ,
257307 # issue 7632 bug 5: the following 2 strings convert differently
258308 '1000000000000000000000000000000000000000e-16' ,
259309 '10000000000000000000000000000000000000000e-17' ,
310+ # issue 7632 bug 7
311+ '991633793189150720000000000000000000000000000000000000000e-33' ,
312+ # And another, similar, failing halfway case
313+ '4106250198039490000000000000000000000000000000000000000e-38' ,
260314 # issue 7632 bug 8: the following produced 10.0
261315 '10.900000000000000012345678912345678912345' ,
316+ # exercise exit conditions in bigcomp comparison loop
317+ '2602129298404963083833853479113577253105939995688e2' ,
318+ '260212929840496308383385347911357725310593999568896e0' ,
319+ '26021292984049630838338534791135772531059399956889601e-2' ,
320+ '260212929840496308383385347911357725310593999568895e0' ,
321+ '260212929840496308383385347911357725310593999568897e0' ,
322+ '260212929840496308383385347911357725310593999568996e0' ,
323+ '260212929840496308383385347911357725310593999568866e0' ,
324+ # 2**53
325+ '9007199254740992.00' ,
326+ # 2**1024 - 2**970: exact overflow boundary. All values
327+ # smaller than this should round to something finite; any value
328+ # greater than or equal to this one overflows.
329+ '179769313486231580793728971405303415079934132710037' #...
330+ '826936173778980444968292764750946649017977587207096' #...
331+ '330286416692887910946555547851940402630657488671505' #...
332+ '820681908902000708383676273854845817711531764475730' #...
333+ '270069855571366959622842914819860834936475292719074' #...
334+ '168444365510704342711559699508093042880177904174497792' ,
335+ # 2**1024 - 2**970 - tiny
336+ '179769313486231580793728971405303415079934132710037' #...
337+ '826936173778980444968292764750946649017977587207096' #...
338+ '330286416692887910946555547851940402630657488671505' #...
339+ '820681908902000708383676273854845817711531764475730' #...
340+ '270069855571366959622842914819860834936475292719074' #...
341+ '168444365510704342711559699508093042880177904174497791.999' ,
342+ # 2**1024 - 2**970 + tiny
343+ '179769313486231580793728971405303415079934132710037' #...
344+ '826936173778980444968292764750946649017977587207096' #...
345+ '330286416692887910946555547851940402630657488671505' #...
346+ '820681908902000708383676273854845817711531764475730' #...
347+ '270069855571366959622842914819860834936475292719074' #...
348+ '168444365510704342711559699508093042880177904174497792.001' ,
349+ # 1 - 2**-54, +-tiny
350+ '999999999999999944488848768742172978818416595458984375e-54' ,
351+ '9999999999999999444888487687421729788184165954589843749999999e-54' ,
352+ '9999999999999999444888487687421729788184165954589843750000001e-54' ,
262353 ]
263354 for s in test_strings :
264355 self .check_strtod (s )
0 commit comments