|
27 | 27 | -export([t_div/1, eq_28/1, eq_32/1, eq_big/1, eq_math/1, eq_big_mul_div/1, |
28 | 28 | eq_big_rem/1, |
29 | 29 | big_literals/1, borders/1, negative/1, karatsuba/1, |
30 | | - big_float_1/1, big_float_2/1, |
| 30 | + big_float_1/1, big_float_2/1, big_float_3/1, |
31 | 31 | bxor_2pow/1, band_2pow/1, |
32 | 32 | shift_limit_1/1, powmod/1, system_limit/1, toobig/1, otp_6692/1, |
33 | 33 | properties/1, reductions/1]). |
@@ -56,7 +56,7 @@ all() -> |
56 | 56 | properties, reductions]. |
57 | 57 |
|
58 | 58 | groups() -> |
59 | | - [{big_float, [], [big_float_1, big_float_2]}]. |
| 59 | + [{big_float, [], [big_float_1, big_float_2, big_float_3]}]. |
60 | 60 |
|
61 | 61 | %% |
62 | 62 | %% Syntax of data files: |
@@ -353,6 +353,68 @@ big_float_2(Config) when is_list(Config) -> |
353 | 353 | {'EXIT', _} = (catch 4/(2*I)), |
354 | 354 | ok. |
355 | 355 |
|
| 356 | +%% Converting a bignum to a float must give the nearest representable |
| 357 | +%% double, ties to even. Accumulating digit by digit rounds once per digit |
| 358 | +%% and compounds the error, which lands on the wrong side of the true value |
| 359 | +%% for some values wider than one digit. |
| 360 | +big_float_3(Config) when is_list(Config) -> |
| 361 | + rand_seed(), |
| 362 | + %% Each of these converted to the second-nearest double when the |
| 363 | + %% conversion rounded per digit. |
| 364 | + [begin |
| 365 | + Nearest = correctly_rounded(I), |
| 366 | + Nearest = float(I), |
| 367 | + Nearest = 1.0 * I, |
| 368 | + NegNearest = -Nearest, |
| 369 | + NegNearest = float(-I) |
| 370 | + end |
| 371 | + || I <- [428654966685883400000, |
| 372 | + 38409289721754710000, |
| 373 | + 34784104853086640000, |
| 374 | + 385269108828434300000, |
| 375 | + 96874578115970900000, |
| 376 | + 252558769001389900000, |
| 377 | + 26465126867694860000]], |
| 378 | + |
| 379 | + %% Widths on both sides of the single-digit boundary, where the |
| 380 | + %% per-digit accumulation starts to compound. |
| 381 | + for(50, 300, |
| 382 | + fun(Bits) -> |
| 383 | + for(1, 200, |
| 384 | + fun(_) -> |
| 385 | + I = rand:uniform(1 bsl Bits), |
| 386 | + Nearest = correctly_rounded(I), |
| 387 | + Nearest = float(I) |
| 388 | + end) |
| 389 | + end), |
| 390 | + |
| 391 | + %% 2-pows and neighbours |
| 392 | + [begin |
| 393 | + I = (1 bsl E) + Diff, |
| 394 | + Nearest = correctly_rounded(I), |
| 395 | + Nearest = float(I) |
| 396 | + end |
| 397 | + || E <- lists:seq(0, 1023), Diff <- lists:seq(-2,2)], |
| 398 | + |
| 399 | + %% Mantissa rounding edge cases |
| 400 | + [begin |
| 401 | + Mant = (1 bsl 52) + Odd, |
| 402 | + I = (Mant bsl Exp) + (Half bsl (Exp-1)) + (1 bsl Low), |
| 403 | + Nearest = correctly_rounded(I), |
| 404 | + Nearest = float(I) |
| 405 | + end |
| 406 | + || Exp <- lists:seq(1, 1023-53), |
| 407 | + Odd <- [0,1], |
| 408 | + Half <- [1], |
| 409 | + Low <- [-1 | lists:seq(0, Exp-2, 8)]], |
| 410 | + |
| 411 | + ok. |
| 412 | + |
| 413 | +%% The platform's decimal parser is correctly rounded, so it serves as the |
| 414 | +%% oracle for what float/1 must return. |
| 415 | +correctly_rounded(I) -> |
| 416 | + binary_to_float(iolist_to_binary([integer_to_list(I), ".0"])). |
| 417 | + |
356 | 418 | %% OTP-3256 |
357 | 419 | shift_limit_1(Config) when is_list(Config) -> |
358 | 420 | case catch (id(1) bsl 100000000) of |
|
0 commit comments