1# 2# Copyright (c) 2008-2012 Stefan Krah. All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions 6# are met: 7# 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26# 27 28 29# Generate test cases for deccheck.py. 30 31 32# 33# Grammar from http://speleotrove.com/decimal/daconvs.html 34# 35# sign ::= '+' | '-' 36# digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | 37# '8' | '9' 38# indicator ::= 'e' | 'E' 39# digits ::= digit [digit]... 40# decimal-part ::= digits '.' [digits] | ['.'] digits 41# exponent-part ::= indicator [sign] digits 42# infinity ::= 'Infinity' | 'Inf' 43# nan ::= 'NaN' [digits] | 'sNaN' [digits] 44# numeric-value ::= decimal-part [exponent-part] | infinity 45# numeric-string ::= [sign] numeric-value | [sign] nan 46# 47 48 49from random import randrange, sample 50from fractions import Fraction 51from randfloat import un_randfloat, bin_randfloat, tern_randfloat 52 53 54def sign(): 55 if randrange(2): 56 if randrange(2): return '+' 57 return '' 58 return '-' 59 60def indicator(): 61 return "eE"[randrange(2)] 62 63def digits(maxprec): 64 if maxprec == 0: return '' 65 return str(randrange(10**maxprec)) 66 67def dot(): 68 if randrange(2): return '.' 69 return '' 70 71def decimal_part(maxprec): 72 if randrange(100) > 60: # integers 73 return digits(maxprec) 74 if randrange(2): 75 intlen = randrange(1, maxprec+1) 76 fraclen = maxprec-intlen 77 intpart = digits(intlen) 78 fracpart = digits(fraclen) 79 return ''.join((intpart, '.', fracpart)) 80 else: 81 return ''.join((dot(), digits(maxprec))) 82 83def expdigits(maxexp): 84 return str(randrange(maxexp)) 85 86def exponent_part(maxexp): 87 return ''.join((indicator(), sign(), expdigits(maxexp))) 88 89def infinity(): 90 if randrange(2): return 'Infinity' 91 return 'Inf' 92 93def nan(): 94 d = '' 95 if randrange(2): 96 d = digits(randrange(99)) 97 if randrange(2): 98 return ''.join(('NaN', d)) 99 else: 100 return ''.join(('sNaN', d)) 101 102def numeric_value(maxprec, maxexp): 103 if randrange(100) > 90: 104 return infinity() 105 exp_part = '' 106 if randrange(100) > 60: 107 exp_part = exponent_part(maxexp) 108 return ''.join((decimal_part(maxprec), exp_part)) 109 110def numeric_string(maxprec, maxexp): 111 if randrange(100) > 95: 112 return ''.join((sign(), nan())) 113 else: 114 return ''.join((sign(), numeric_value(maxprec, maxexp))) 115 116def randdec(maxprec, maxexp): 117 return numeric_string(maxprec, maxexp) 118 119def rand_adjexp(maxprec, maxadjexp): 120 d = digits(maxprec) 121 maxexp = maxadjexp-len(d)+1 122 if maxexp == 0: maxexp = 1 123 exp = str(randrange(maxexp-2*(abs(maxexp)), maxexp)) 124 return ''.join((sign(), d, 'E', exp)) 125 126 127def ndigits(n): 128 if n < 1: return 0 129 return randrange(10**(n-1), 10**n) 130 131def randtuple(maxprec, maxexp): 132 n = randrange(100) 133 sign = randrange(2) 134 coeff = ndigits(maxprec) 135 if n >= 95: 136 coeff = () 137 exp = 'F' 138 elif n >= 85: 139 coeff = tuple(map(int, str(ndigits(maxprec)))) 140 exp = "nN"[randrange(2)] 141 else: 142 coeff = tuple(map(int, str(ndigits(maxprec)))) 143 exp = randrange(-maxexp, maxexp) 144 return (sign, coeff, exp) 145 146def from_triple(sign, coeff, exp): 147 return ''.join((str(sign*coeff), indicator(), str(exp))) 148 149 150# Close to 10**n 151def un_close_to_pow10(prec, maxexp, itr=None): 152 if itr is None: 153 lst = range(prec+30) 154 else: 155 lst = sample(range(prec+30), itr) 156 nines = [10**n - 1 for n in lst] 157 pow10 = [10**n for n in lst] 158 for coeff in nines: 159 yield coeff 160 yield -coeff 161 yield from_triple(1, coeff, randrange(2*maxexp)) 162 yield from_triple(-1, coeff, randrange(2*maxexp)) 163 for coeff in pow10: 164 yield coeff 165 yield -coeff 166 167# Close to 10**n 168def bin_close_to_pow10(prec, maxexp, itr=None): 169 if itr is None: 170 lst = range(prec+30) 171 else: 172 lst = sample(range(prec+30), itr) 173 nines = [10**n - 1 for n in lst] 174 pow10 = [10**n for n in lst] 175 for coeff in nines: 176 yield coeff, 1 177 yield -coeff, -1 178 yield 1, coeff 179 yield -1, -coeff 180 yield from_triple(1, coeff, randrange(2*maxexp)), 1 181 yield from_triple(-1, coeff, randrange(2*maxexp)), -1 182 yield 1, from_triple(1, coeff, -randrange(2*maxexp)) 183 yield -1, from_triple(-1, coeff, -randrange(2*maxexp)) 184 for coeff in pow10: 185 yield coeff, -1 186 yield -coeff, 1 187 yield 1, -coeff 188 yield -coeff, 1 189 190# Close to 1: 191def close_to_one_greater(prec, emax, emin): 192 rprec = 10**prec 193 return ''.join(("1.", '0'*randrange(prec), 194 str(randrange(rprec)))) 195 196def close_to_one_less(prec, emax, emin): 197 rprec = 10**prec 198 return ''.join(("0.9", '9'*randrange(prec), 199 str(randrange(rprec)))) 200 201# Close to 0: 202def close_to_zero_greater(prec, emax, emin): 203 rprec = 10**prec 204 return ''.join(("0.", '0'*randrange(prec), 205 str(randrange(rprec)))) 206 207def close_to_zero_less(prec, emax, emin): 208 rprec = 10**prec 209 return ''.join(("-0.", '0'*randrange(prec), 210 str(randrange(rprec)))) 211 212# Close to emax: 213def close_to_emax_less(prec, emax, emin): 214 rprec = 10**prec 215 return ''.join(("9.", '9'*randrange(prec), 216 str(randrange(rprec)), "E", str(emax))) 217 218def close_to_emax_greater(prec, emax, emin): 219 rprec = 10**prec 220 return ''.join(("1.", '0'*randrange(prec), 221 str(randrange(rprec)), "E", str(emax+1))) 222 223# Close to emin: 224def close_to_emin_greater(prec, emax, emin): 225 rprec = 10**prec 226 return ''.join(("1.", '0'*randrange(prec), 227 str(randrange(rprec)), "E", str(emin))) 228 229def close_to_emin_less(prec, emax, emin): 230 rprec = 10**prec 231 return ''.join(("9.", '9'*randrange(prec), 232 str(randrange(rprec)), "E", str(emin-1))) 233 234# Close to etiny: 235def close_to_etiny_greater(prec, emax, emin): 236 rprec = 10**prec 237 etiny = emin - (prec - 1) 238 return ''.join(("1.", '0'*randrange(prec), 239 str(randrange(rprec)), "E", str(etiny))) 240 241def close_to_etiny_less(prec, emax, emin): 242 rprec = 10**prec 243 etiny = emin - (prec - 1) 244 return ''.join(("9.", '9'*randrange(prec), 245 str(randrange(rprec)), "E", str(etiny-1))) 246 247 248def close_to_min_etiny_greater(prec, max_prec, min_emin): 249 rprec = 10**prec 250 etiny = min_emin - (max_prec - 1) 251 return ''.join(("1.", '0'*randrange(prec), 252 str(randrange(rprec)), "E", str(etiny))) 253 254def close_to_min_etiny_less(prec, max_prec, min_emin): 255 rprec = 10**prec 256 etiny = min_emin - (max_prec - 1) 257 return ''.join(("9.", '9'*randrange(prec), 258 str(randrange(rprec)), "E", str(etiny-1))) 259 260 261close_funcs = [ 262 close_to_one_greater, close_to_one_less, close_to_zero_greater, 263 close_to_zero_less, close_to_emax_less, close_to_emax_greater, 264 close_to_emin_greater, close_to_emin_less, close_to_etiny_greater, 265 close_to_etiny_less, close_to_min_etiny_greater, close_to_min_etiny_less 266] 267 268 269def un_close_numbers(prec, emax, emin, itr=None): 270 if itr is None: 271 itr = 1000 272 for _ in range(itr): 273 for func in close_funcs: 274 yield func(prec, emax, emin) 275 276def bin_close_numbers(prec, emax, emin, itr=None): 277 if itr is None: 278 itr = 1000 279 for _ in range(itr): 280 for func1 in close_funcs: 281 for func2 in close_funcs: 282 yield func1(prec, emax, emin), func2(prec, emax, emin) 283 for func in close_funcs: 284 yield randdec(prec, emax), func(prec, emax, emin) 285 yield func(prec, emax, emin), randdec(prec, emax) 286 287def tern_close_numbers(prec, emax, emin, itr): 288 if itr is None: 289 itr = 1000 290 for _ in range(itr): 291 for func1 in close_funcs: 292 for func2 in close_funcs: 293 for func3 in close_funcs: 294 yield (func1(prec, emax, emin), func2(prec, emax, emin), 295 func3(prec, emax, emin)) 296 for func in close_funcs: 297 yield (randdec(prec, emax), func(prec, emax, emin), 298 func(prec, emax, emin)) 299 yield (func(prec, emax, emin), randdec(prec, emax), 300 func(prec, emax, emin)) 301 yield (func(prec, emax, emin), func(prec, emax, emin), 302 randdec(prec, emax)) 303 for func in close_funcs: 304 yield (randdec(prec, emax), randdec(prec, emax), 305 func(prec, emax, emin)) 306 yield (randdec(prec, emax), func(prec, emax, emin), 307 randdec(prec, emax)) 308 yield (func(prec, emax, emin), randdec(prec, emax), 309 randdec(prec, emax)) 310 311 312# If itr == None, test all digit lengths up to prec + 30 313def un_incr_digits(prec, maxexp, itr): 314 if itr is None: 315 lst = range(prec+30) 316 else: 317 lst = sample(range(prec+30), itr) 318 for m in lst: 319 yield from_triple(1, ndigits(m), 0) 320 yield from_triple(-1, ndigits(m), 0) 321 yield from_triple(1, ndigits(m), randrange(maxexp)) 322 yield from_triple(-1, ndigits(m), randrange(maxexp)) 323 324# If itr == None, test all digit lengths up to prec + 30 325# Also output decimals im tuple form. 326def un_incr_digits_tuple(prec, maxexp, itr): 327 if itr is None: 328 lst = range(prec+30) 329 else: 330 lst = sample(range(prec+30), itr) 331 for m in lst: 332 yield from_triple(1, ndigits(m), 0) 333 yield from_triple(-1, ndigits(m), 0) 334 yield from_triple(1, ndigits(m), randrange(maxexp)) 335 yield from_triple(-1, ndigits(m), randrange(maxexp)) 336 # test from tuple 337 yield (0, tuple(map(int, str(ndigits(m)))), 0) 338 yield (1, tuple(map(int, str(ndigits(m)))), 0) 339 yield (0, tuple(map(int, str(ndigits(m)))), randrange(maxexp)) 340 yield (1, tuple(map(int, str(ndigits(m)))), randrange(maxexp)) 341 342# If itr == None, test all combinations of digit lengths up to prec + 30 343def bin_incr_digits(prec, maxexp, itr): 344 if itr is None: 345 lst1 = range(prec+30) 346 lst2 = range(prec+30) 347 else: 348 lst1 = sample(range(prec+30), itr) 349 lst2 = sample(range(prec+30), itr) 350 for m in lst1: 351 x = from_triple(1, ndigits(m), 0) 352 yield x, x 353 x = from_triple(-1, ndigits(m), 0) 354 yield x, x 355 x = from_triple(1, ndigits(m), randrange(maxexp)) 356 yield x, x 357 x = from_triple(-1, ndigits(m), randrange(maxexp)) 358 yield x, x 359 for m in lst1: 360 for n in lst2: 361 x = from_triple(1, ndigits(m), 0) 362 y = from_triple(1, ndigits(n), 0) 363 yield x, y 364 x = from_triple(-1, ndigits(m), 0) 365 y = from_triple(1, ndigits(n), 0) 366 yield x, y 367 x = from_triple(1, ndigits(m), 0) 368 y = from_triple(-1, ndigits(n), 0) 369 yield x, y 370 x = from_triple(-1, ndigits(m), 0) 371 y = from_triple(-1, ndigits(n), 0) 372 yield x, y 373 x = from_triple(1, ndigits(m), randrange(maxexp)) 374 y = from_triple(1, ndigits(n), randrange(maxexp)) 375 yield x, y 376 x = from_triple(-1, ndigits(m), randrange(maxexp)) 377 y = from_triple(1, ndigits(n), randrange(maxexp)) 378 yield x, y 379 x = from_triple(1, ndigits(m), randrange(maxexp)) 380 y = from_triple(-1, ndigits(n), randrange(maxexp)) 381 yield x, y 382 x = from_triple(-1, ndigits(m), randrange(maxexp)) 383 y = from_triple(-1, ndigits(n), randrange(maxexp)) 384 yield x, y 385 386 387def randsign(): 388 return (1, -1)[randrange(2)] 389 390# If itr == None, test all combinations of digit lengths up to prec + 30 391def tern_incr_digits(prec, maxexp, itr): 392 if itr is None: 393 lst1 = range(prec+30) 394 lst2 = range(prec+30) 395 lst3 = range(prec+30) 396 else: 397 lst1 = sample(range(prec+30), itr) 398 lst2 = sample(range(prec+30), itr) 399 lst3 = sample(range(prec+30), itr) 400 for m in lst1: 401 for n in lst2: 402 for p in lst3: 403 x = from_triple(randsign(), ndigits(m), 0) 404 y = from_triple(randsign(), ndigits(n), 0) 405 z = from_triple(randsign(), ndigits(p), 0) 406 yield x, y, z 407 408 409# Tests for the 'logical' functions 410def bindigits(prec): 411 z = 0 412 for i in range(prec): 413 z += randrange(2) * 10**i 414 return z 415 416def logical_un_incr_digits(prec, itr): 417 if itr is None: 418 lst = range(prec+30) 419 else: 420 lst = sample(range(prec+30), itr) 421 for m in lst: 422 yield from_triple(1, bindigits(m), 0) 423 424def logical_bin_incr_digits(prec, itr): 425 if itr is None: 426 lst1 = range(prec+30) 427 lst2 = range(prec+30) 428 else: 429 lst1 = sample(range(prec+30), itr) 430 lst2 = sample(range(prec+30), itr) 431 for m in lst1: 432 x = from_triple(1, bindigits(m), 0) 433 yield x, x 434 for m in lst1: 435 for n in lst2: 436 x = from_triple(1, bindigits(m), 0) 437 y = from_triple(1, bindigits(n), 0) 438 yield x, y 439 440 441def randint(): 442 p = randrange(1, 100) 443 return ndigits(p) * (1,-1)[randrange(2)] 444 445def randfloat(): 446 p = randrange(1, 100) 447 s = numeric_value(p, 383) 448 try: 449 f = float(numeric_value(p, 383)) 450 except ValueError: 451 f = 0.0 452 return f 453 454def randcomplex(): 455 real = randfloat() 456 if randrange(100) > 30: 457 imag = 0.0 458 else: 459 imag = randfloat() 460 return complex(real, imag) 461 462def randfraction(): 463 num = randint() 464 denom = randint() 465 if denom == 0: 466 denom = 1 467 return Fraction(num, denom) 468 469number_funcs = [randint, randfloat, randcomplex, randfraction] 470 471def un_random_mixed_op(itr=None): 472 if itr is None: 473 itr = 1000 474 for _ in range(itr): 475 for func in number_funcs: 476 yield func() 477 # Test garbage input 478 for x in (['x'], ('y',), {'z'}, {1:'z'}): 479 yield x 480 481def bin_random_mixed_op(prec, emax, emin, itr=None): 482 if itr is None: 483 itr = 1000 484 for _ in range(itr): 485 for func in number_funcs: 486 yield randdec(prec, emax), func() 487 yield func(), randdec(prec, emax) 488 for number in number_funcs: 489 for dec in close_funcs: 490 yield dec(prec, emax, emin), number() 491 # Test garbage input 492 for x in (['x'], ('y',), {'z'}, {1:'z'}): 493 for y in (['x'], ('y',), {'z'}, {1:'z'}): 494 yield x, y 495 496def tern_random_mixed_op(prec, emax, emin, itr): 497 if itr is None: 498 itr = 1000 499 for _ in range(itr): 500 for func in number_funcs: 501 yield randdec(prec, emax), randdec(prec, emax), func() 502 yield randdec(prec, emax), func(), func() 503 yield func(), func(), func() 504 # Test garbage input 505 for x in (['x'], ('y',), {'z'}, {1:'z'}): 506 for y in (['x'], ('y',), {'z'}, {1:'z'}): 507 for z in (['x'], ('y',), {'z'}, {1:'z'}): 508 yield x, y, z 509 510def all_unary(prec, exp_range, itr): 511 for a in un_close_to_pow10(prec, exp_range, itr): 512 yield (a,) 513 for a in un_close_numbers(prec, exp_range, -exp_range, itr): 514 yield (a,) 515 for a in un_incr_digits_tuple(prec, exp_range, itr): 516 yield (a,) 517 for a in un_randfloat(): 518 yield (a,) 519 for a in un_random_mixed_op(itr): 520 yield (a,) 521 for a in logical_un_incr_digits(prec, itr): 522 yield (a,) 523 for _ in range(100): 524 yield (randdec(prec, exp_range),) 525 for _ in range(100): 526 yield (randtuple(prec, exp_range),) 527 528def unary_optarg(prec, exp_range, itr): 529 for _ in range(100): 530 yield randdec(prec, exp_range), None 531 yield randdec(prec, exp_range), None, None 532 533def all_binary(prec, exp_range, itr): 534 for a, b in bin_close_to_pow10(prec, exp_range, itr): 535 yield a, b 536 for a, b in bin_close_numbers(prec, exp_range, -exp_range, itr): 537 yield a, b 538 for a, b in bin_incr_digits(prec, exp_range, itr): 539 yield a, b 540 for a, b in bin_randfloat(): 541 yield a, b 542 for a, b in bin_random_mixed_op(prec, exp_range, -exp_range, itr): 543 yield a, b 544 for a, b in logical_bin_incr_digits(prec, itr): 545 yield a, b 546 for _ in range(100): 547 yield randdec(prec, exp_range), randdec(prec, exp_range) 548 549def binary_optarg(prec, exp_range, itr): 550 for _ in range(100): 551 yield randdec(prec, exp_range), randdec(prec, exp_range), None 552 yield randdec(prec, exp_range), randdec(prec, exp_range), None, None 553 554def all_ternary(prec, exp_range, itr): 555 for a, b, c in tern_close_numbers(prec, exp_range, -exp_range, itr): 556 yield a, b, c 557 for a, b, c in tern_incr_digits(prec, exp_range, itr): 558 yield a, b, c 559 for a, b, c in tern_randfloat(): 560 yield a, b, c 561 for a, b, c in tern_random_mixed_op(prec, exp_range, -exp_range, itr): 562 yield a, b, c 563 for _ in range(100): 564 a = randdec(prec, 2*exp_range) 565 b = randdec(prec, 2*exp_range) 566 c = randdec(prec, 2*exp_range) 567 yield a, b, c 568 569def ternary_optarg(prec, exp_range, itr): 570 for _ in range(100): 571 a = randdec(prec, 2*exp_range) 572 b = randdec(prec, 2*exp_range) 573 c = randdec(prec, 2*exp_range) 574 yield a, b, c, None 575 yield a, b, c, None, None 576