Skip to content

Commit 62c2015

Browse files
committed
fix float shrinking issue
1 parent 7c32b09 commit 62c2015

2 files changed

Lines changed: 42 additions & 15 deletions

File tree

‎lib/experimental/property_testing.nim‎

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -977,27 +977,30 @@ proc genFloatScalar[T: SomeFloat](min, max: T,
977977
if choice > 90 and classes.len > 1:
978978
cls = classes[int((choice - 91) mod uint64(classes.len - 1)) + 1]
979979

980+
let
981+
fHigh = when T is float64: 1.7976931348623157e+308 else: 3.4028235e+38f
982+
actualMin = if classify(min) == fcNaN: (if allowInf: T(-Inf) else: T(-fHigh)) else: min
983+
actualMax = if classify(max) == fcNaN: (if allowInf: T(Inf) else: T(fHigh)) else: max
984+
minOrd = when T is float64: float64ToOrdinal(actualMin) else: int64(float32ToOrdinal(actualMin))
985+
maxOrd = when T is float64: float64ToOrdinal(actualMax) else: int64(float32ToOrdinal(actualMax))
986+
simplest = if actualMin > 0: actualMin elif actualMax < 0: actualMax else: T(0.0)
987+
simplestOrd = when T is float64: float64ToOrdinal(simplest) else: int64(float32ToOrdinal(simplest))
988+
989+
numBelow = cast[uint64](simplestOrd) - cast[uint64](minOrd)
990+
numAbove = cast[uint64](maxOrd) - cast[uint64](simplestOrd)
991+
rangeSize = numBelow + numAbove
992+
tgtKind = when T is float64: sk8Bytes else: sk4Bytes
993+
994+
# always pick a rank, so that the same number of bytes written/read
995+
# is the same every time
996+
let rank = s.chooseRange(0'u64, rangeSize, tgtKind)
997+
980998
case cls
981999
of 1: return T(-0.0)
9821000
of 2: return T(Inf)
9831001
of 3: return T(-Inf)
9841002
of 4: return T(NaN)
9851003
else:
986-
let
987-
fHigh = when T is float64: 1.7976931348623157e+308 else: 3.4028235e+38f
988-
actualMin = if classify(min) == fcNaN: (if allowInf: T(-Inf) else: T(-fHigh)) else: min
989-
actualMax = if classify(max) == fcNaN: (if allowInf: T(Inf) else: T(fHigh)) else: max
990-
minOrd = when T is float64: float64ToOrdinal(actualMin) else: int64(float32ToOrdinal(actualMin))
991-
maxOrd = when T is float64: float64ToOrdinal(actualMax) else: int64(float32ToOrdinal(actualMax))
992-
simplest = if actualMin > 0: actualMin elif actualMax < 0: actualMax else: T(0.0)
993-
simplestOrd = when T is float64: float64ToOrdinal(simplest) else: int64(float32ToOrdinal(simplest))
994-
995-
numBelow = cast[uint64](simplestOrd) - cast[uint64](minOrd)
996-
numAbove = cast[uint64](maxOrd) - cast[uint64](simplestOrd)
997-
rangeSize = numBelow + numAbove
998-
tgtKind = when T is float64: sk8Bytes else: sk4Bytes
999-
1000-
let rank = s.chooseRange(0'u64, rangeSize, tgtKind)
10011004
let uRes = rankToOrdinal(rank, renumerateInt64ToUint64(minOrd),
10021005
renumerateInt64ToUint64(maxOrd),
10031006
renumerateInt64ToUint64(simplestOrd))

‎tests/stdlib/experimental/tproperty_testing.nim‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,30 @@ suite "Mixed Data Type Generation & Shrinking":
13981398
check si < 76
13991399

14001400

1401+
test "Float stream alignment: (float64, int) shrinking":
1402+
let prop = forAll(
1403+
(f: genFloat64(allowInf = true),
1404+
i: genInt(100, 100)) # Always 100
1405+
):
1406+
# Fail if float is Infinity.
1407+
# This forces the shrinker to explore the 'Inf' branch of genFloatScalar.
1408+
# If the stream is corrupted, reading 'i' will fail or get a wrong value.
1409+
if f.classify == fcInf:
1410+
if i != 100:
1411+
return psError # Stream corruption
1412+
return psFail
1413+
return psPass
1414+
1415+
let res = runProperty(prop, trials=1000, seed=2)
1416+
# Depending on seed, we might hit Inf.
1417+
if res.status == psFail:
1418+
check res.shrunk
1419+
let (sf, si) = res.shrunkValue.get()
1420+
checkpoint "Shrunk float: " & $sf & " int: " & $si
1421+
if sf.classify == fcInf:
1422+
check si == 100
1423+
1424+
14011425
suite "Stress Testing & Final Validation":
14021426

14031427
test "Chaos Shrinking: Deeply nested structural minimization":

0 commit comments

Comments
 (0)