Repository navigation
Read an infinite or undefined real - #27
Merged
daniel-larraz merged 1 commit intoSep 22, 2026
Merged
Conversation
Not every rational Kind 2 reports is a number. Its decimal type is
type t = | InfPos | InfNeg | Undef | N of Num.num
and it writes the first three as a fraction over a zero denominator: 1/0 and
-1/0 for the infinities, 0/0 for a value it could not determine. That is how
a division by zero in the model reaches a counterexample, alongside the
warning Kind 2 prints about it, and the plain text and the XML render them
that way too.
RealValue divided the numerator by the denominator as it was constructed, so
one of these threw ArithmeticException out of the constructor. Values are
built while the Result is, so a single undefined value in a single stream
destroyed the whole result for a model Kind 2 had analysed and reported on.
A rational now says which of the four it is. `getKind` and `isFinite`
tell them apart, `getValue` returns the number for a finite one and
otherwise throws a Kind2Exception naming what it holds, and `getDoubleValue`
gives all four, since a double carries an infinity and a NaN where a
BigDecimal carries neither. `toString` renders the three as Kind 2 does,
so a counterexample reads the same through this API as through Kind 2's own
output. The numerator and the denominator, which had no accessors at all,
are readable too.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Not every rational Kind 2 reports is a number. Its decimal type is
and it writes the first three as a fraction over a zero denominator —
{"num": 1, "den": 0}and{"num": -1, "den": 0}for the infinities,{"num": 0, "den": 0}for a value it could not determine. That is how adivision by zero in the model reaches a counterexample, together with the
warning Kind 2 prints about it, and its plain text and XML render the three
as
1/0,-1/0and0/0.RealValuedivided the numerator by the denominator as it was constructed:which throws
ArithmeticException: / by zeroon any of them. Values arebuilt while the
Resultis, so one undefined value in one stream destroyedthe whole result for a model Kind 2 had analysed and reported on:
What changes
A rational now says which of the four kinds it is, rather than assuming it is
a number:
getKind()FINITE,POSITIVE_INFINITY,NEGATIVE_INFINITYorUNDEFINEDisFinite()getValue()will give a numbergetValue()BigDecimalfor a finite one; otherwise throws aKind2Exceptionnaming what it holdsgetDoubleValue()doublecarries an infinity and a NaN where aBigDecimalcarries neithergetNumerator(),getDenominator()toString()1/0,-1/0,0/0for the three, as Kind 2 itself prints themgetValue()throws rather than returning null on purpose: a nullBigDecimalsurfaces as aNullPointerExceptionsomewhere away from thecause, where the exception says what the value is and how to ask about it
first. Nothing can depend on the old behaviour, since the old behaviour was
to throw out of the constructor and lose the result.
toString()matching Kind 2 means a counterexample reads the same throughthis API as through Kind 2's own output, and the table in
SubNode, whichsizes its columns from
toString().length(), keeps working.The kind is a nested
RealValue.Kindrather than another top-level enum inresults: unlikePropertyTypeorLogLevelit has no meaning away fromthe class it describes.
Before and after, on the same counterexample
tests/regression/falsifiable/test-div-by-zero.lusin the Kind 2 treeproduces all three kinds. Reading its output:
and the counterexample it now yields, beside what Kind 2 prints for the same
run:
Tests
realValuesThatAreNotNumbersreads a counterexample holding a finite valueand all three of the others, and checks the kind,
isFinite,toString,getDoubleValue, the fraction, and thatgetValuethrows for an infinity.The existing 33 result tests and 10 pretty printer tests still pass,
javadoc -Xdoclint:allis clean over the main sources, and it compiles atthe Java 8 language level CI builds with.
Every model in the Kind 2 regression tree (639) now reads through
Result.analyzeJsonResult— the first time that has been true. This wasthe last one failing, and the one named as unrelated in #25 and #26.
🤖 Generated with Claude Code