You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Experimental script to show improvements in correctness:
```
using Random
accurate_div(x, y, r::RoundingMode) = div(BigFloat(x), BigFloat(y), r)
function count_wrong_floats(
div_fun::Fun,
r::RoundingMode,
::Type{F},
::Type{U},
n::Int,
m::Int,
) where {Fun <: Function, F, U}
count_wrong = 0
sample_size = 0
vec_x = zeros(U, m)
vec_y = zeros(U, m)
for i ∈ 1:n
Random.rand!(vec_x)
Random.rand!(vec_y)
for (x_raw, y_raw) ∈ zip(vec_x, vec_y)
x = reinterpret(F, x_raw)
y = reinterpret(F, y_raw)
# skip huge quotients, they're difficult to round correctly
(maxintfloat(F) < abs(x / y)) && continue
acc_big = accurate_div(x, y, r)
acc = F(acc_big)
# skip cases when the result isn't representable
(acc == acc_big) || continue
sample_size += true
d = div_fun(x, y, r)
is_ok = (d == acc) | (isnan(d) & isnan(acc))
count_wrong += !is_ok
end
end
(
bad_ratio = count_wrong / sample_size,
sample_size = sample_size,
)
end
const float_types = (Float16, Float32, Float64)
const bits_types = (UInt16, UInt32, UInt64)
const rounding_modes = (RoundUp, RoundDown, RoundFromZero, RoundToZero, RoundNearest)
function experiment(itcnt::Int, itcnt_inner::Int = 2^24)
for (F, U) ∈ zip(float_types, bits_types)
println("$F $U")
for rm ∈ rounding_modes
println(" $rm")
flush(stdout)
res = count_wrong_floats(div, rm, F, U, itcnt, itcnt_inner)
println(" sample size: $(res.sample_size)")
println(" ratio of bad results among all results: $(res.bad_ratio)")
flush(stdout)
end
println()
end
nothing
end
experiment(16)
```
The script checks only pairs of numbers whose quotient isn't huge with
respect to `maxintfloat(F)`, and also skips cases where the correct
answer isn't representable in the type (which, again, can only happen
for huge numbers).
Results for master:
```
Float16 UInt16
RoundingMode{:Up}()
sample size: 199242282
ratio of bad results among all results: 0.0046785199940643125
RoundingMode{:Down}()
sample size: 199236001
ratio of bad results among all results: 0.004678426566090332
RoundingMode{:FromZero}()
sample size: 199231891
ratio of bad results among all results: 0.005443671665998492
RoundingMode{:ToZero}()
sample size: 199220943
ratio of bad results among all results: 0.0039044690196050323
RoundingMode{:Nearest}()
sample size: 199243950
ratio of bad results among all results: 0.0017626532700240082
Float32 UInt32
RoundingMode{:Up}()
sample size: 157054574
ratio of bad results among all results: 0.00089996742151553
RoundingMode{:Down}()
sample size: 157035223
ratio of bad results among all results: 0.0009016130094583939
RoundingMode{:FromZero}()
sample size: 157037914
ratio of bad results among all results: 0.000918612558748074
RoundingMode{:ToZero}()
sample size: 157052945
ratio of bad results among all results: 0.0008894962141588621
RoundingMode{:Nearest}()
sample size: 157056698
ratio of bad results among all results: 0.00032412498574241
Float64 UInt64
RoundingMode{:Up}()
sample size: 140927221
ratio of bad results among all results: 0.00013208236044049998
RoundingMode{:Down}()
sample size: 140958292
ratio of bad results among all results: 0.00013300388174397005
RoundingMode{:FromZero}()
sample size: 140941597
ratio of bad results among all results: 0.000134701184065624
RoundingMode{:ToZero}()
sample size: 140939689
ratio of bad results among all results: 0.0001340360556634973
RoundingMode{:Nearest}()
sample size: 140928865
ratio of bad results among all results: 4.791069593869219e-5
```
Results after this commit:
```
Float16 UInt16
RoundingMode{:Up}()
sample size: 199235658
ratio of bad results among all results: 7.583983786677382e-6
RoundingMode{:Down}()
sample size: 199234976
ratio of bad results among all results: 7.257761809854109e-6
RoundingMode{:FromZero}()
sample size: 199239270
ratio of bad results among all results: 7.588865387832429e-6
RoundingMode{:ToZero}()
sample size: 199233698
ratio of bad results among all results: 7.584058395583261e-6
RoundingMode{:Nearest}()
sample size: 199231993
ratio of bad results among all results: 8.266744588556116e-6
Float32 UInt32
RoundingMode{:Up}()
sample size: 157061442
ratio of bad results among all results: 0.0
RoundingMode{:Down}()
sample size: 157048602
ratio of bad results among all results: 0.0
RoundingMode{:FromZero}()
sample size: 157056325
ratio of bad results among all results: 0.0
RoundingMode{:ToZero}()
sample size: 157061341
ratio of bad results among all results: 0.0
RoundingMode{:Nearest}()
sample size: 157053623
ratio of bad results among all results: 0.0
Float64 UInt64
RoundingMode{:Up}()
sample size: 140945983
ratio of bad results among all results: 0.0
RoundingMode{:Down}()
sample size: 140933327
ratio of bad results among all results: 0.0
RoundingMode{:FromZero}()
sample size: 140940387
ratio of bad results among all results: 0.0
RoundingMode{:ToZero}()
sample size: 140952881
ratio of bad results among all results: 0.0
RoundingMode{:Nearest}()
sample size: 140932846
ratio of bad results among all results: 0.0
```
The `RoundNearestTiesAway` and `RoundNearestTiesUp` rounding modes were
tested in a separate run, only for the state after this commit, because
they aren't supported on master at all:
```
Float16 UInt16
RoundingMode{:NearestTiesAway}()
sample size: 199247082
ratio of bad results among all results: 0.014750609998895743
RoundingMode{:NearestTiesUp}()
sample size: 199249202
ratio of bad results among all results: 0.014703050103056373
Float32 UInt32
RoundingMode{:NearestTiesAway}()
sample size: 157062272
ratio of bad results among all results: 0.0030406729376740455
RoundingMode{:NearestTiesUp}()
sample size: 157063551
ratio of bad results among all results: 0.003045557017872339
Float64 UInt64
RoundingMode{:NearestTiesAway}()
sample size: 140948580
ratio of bad results among all results: 0.000453839265354784
RoundingMode{:NearestTiesUp}()
sample size: 140936152
ratio of bad results among all results: 0.0004549790744960881
```
Experimental function for checking the status regarding #49450:
```
function count_wrong_floats()
wrong_fld_count = 0
wrong_cld_count = 0
for i in 0x0000:0xffff, j in 0x0000:0xffff
x = reinterpret(Float16, i)
y = reinterpret(Float16, j)
quotient = x / y
f = fld(x, y)
c = cld(x, y)
floor_is_wrong = (f > quotient) | (isnan(f) & !isnan(quotient))
ceil_is_wrong = (c < quotient) | (isnan(c) & !isnan(quotient))
wrong_fld_count += floor_is_wrong
wrong_cld_count += ceil_is_wrong
end
n = Int(0x10000)^2
(
fld_bad_ratio = wrong_fld_count / n,
cld_bad_ratio = wrong_cld_count / n,
)
end
```
Result of `count_wrong_floats()` on master:
```
(fld_bad_ratio = 0.0003659049980342388, cld_bad_ratio = 0.0003659049980342388)
```
Result of `count_wrong_floats()` after this commit:
```
(fld_bad_ratio = 7.445923984050751e-7, cld_bad_ratio = 7.445923984050751e-7)
```
Fixes#49450
0 commit comments