gen.float: a float generator with a range and edge values #3
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Missing
gen.float range(and a floatrange, orrange.*accepting floats), shrinking toward the origin likegen.int.Where it was needed
jsonschema2nix generates values for
type: "number"schemas withminimum/maximum/multipleOf. Without a float generator the test approximates:so only halves of integers are ever drawn, float bounds have to be integers, and edge cases (values just inside a bound, large magnitudes such as
1.0e100, negative zero, valuesbuiltins.floorcannot take) are never generated. The last one is a real class of bug in the code under test (an integral check that aborted on floats outside the Nix integer range) and the property could not have found it.Suggested shape
gen.float (range.linearFrom 0.0 lo hi); shrink toward the origin through halving, then toward integers.gen.floatEdgeor anedgeslist the generator mixes in (bounds themselves,±0.0,2^53,1.0e100).Plan
No new range constructor is needed:
range.linearFrom 0.0 (-1.5) 2.5already works (bounds 50={ lo = -1.5; hi = 0.5; }), because the arithmetic promotes to float. Onlygen.float rangeis missing.lo + rng.unit r * (hi - lo).towardsFloat(halve the distance to the origin until below an epsilon), with the origin itself as the first candidate andfloor xas one candidate so values pull toward integers.frequency [ [ 9 uniform ] [ 1 (elements edges) ] ],edges=[ lo hi origin 2^53 1.0e100 ~9.3e18 ]filtered to the range.builtins.floorerrors on1.0e100and on anything >= 2^63, which is exactly the bug class this issue targets, so both must be in the list.Nix 2.34 findings that shape the design:
-0.0evaluates to0; drop it from the edge list.1.0 / 0.0is an error;infonly arises from overflow (1.0e308 * 10.0),nanfrominf - inf,nan == nanis false,toJSONgivesnullfor both. Generate them only behind an opt-in (allowInfinite), as Hypothesis does.range.exponential(#10) is the natural companion for reaching large magnitudes by size instead of only via edge values. Depends on #6.Implemented in
465e0dd, pushed to main.