Repository navigation
An interval scaled by a constant is an interval - #1118
Merged
Merged
Conversation
#322's arithmetic half. `Sumf` and `Minusf` had interval cases and `Mulf` and `Divf` had none, so `(0; 1) + 1` answered `(1; 2)` while `(0; 1) * 2` was handed back. Three rows of `Core/Sets/Arithmetics` recorded that asymmetry as the expected behaviour, directly beneath the two addition rows that answer. "3 * [2; 3]".ToEntity().Simplify() // was 3 * [2; 3], is [6; 9] "[2; 3] / 2".ToEntity().Simplify() // was [2; 3] / 2, is [1; 3/2] **A negative factor reflects the interval**, so its ends swap and their openness swaps with them, exactly as subtracting one does: `[2; 3) * (-1)` is `(-3; -2]`. That is the half a test on the printed form alone would not catch -- swapping the ends and leaving the flags where they were gives the right width and the wrong bracket at both ends -- so membership is asserted too. `0 - [0; 1)` is now `(-1; 0]`, and it is not a subtraction at all: `0 - x` is negated by an earlier arm, so it reaches `Mulf` as `-1 * [0; 1)`. It is the case #1117 had to leave out, and it comes back for free. **An unknown sign is answered by not answering.** `(0; 1) * k` for a symbolic `k` is one interval when `k` is positive and the reflected one when it is negative, so picking either would be choosing which. Two boundaries, asserted rather than left to be discovered. `(0; 1) * 0` still answers the number `0` rather than the set `{ 0 }` -- that arm is over every `Entity` and not only intervals, and moving it would change matrices and finite sets with it. And `2 / (0; 1)` is left alone: a constant over an interval straddling zero is two unbounded pieces rather than one interval, so there is no `Interval` to answer with. #322 says this "will be possible once we implement quantifiers". It needs none -- scaling is monotone in the factor's sign and in nothing else. Applying a *non-monotonic* function to an interval is the issue's other half and is still open. Recorded in BREAKING-CHANGES.md, both values measured on a build. Full suite: 9059 passed, 14 skipped, 0 failed. Part of #322.
Rafael-SOWNet
added a commit
that referenced
this pull request
Sep 18, 2026
…he images of its ends, and a product or quotient of two intervals is an interval (#1423) What #322 has left after #1117 and #1118: a function applied to an interval, and an interval times an interval. A function monotone on an interval maps it to the interval between the images of its ends -- in the same order when increasing, reversed when decreasing -- each end attained exactly when the end it comes from is, and an infinite image never attained: ln((0; 1)) is (-oo; 0), and so is ln([0; 1)), since ln(0) is not a value. Answered for the functions the library has nodes for on the intervals where they are monotone: ln and log for any positive base but 1 on the positives, b^I for such a base everywhere, I^n for a whole n (odd everywhere; even on either side of zero and folded across it; negative through the reciprocal where zero is outside), I^(1/n) from zero on, abs, arctan everywhere, arcsin and arccos on [-1; 1]. A product of two intervals with finite numeric ends is the interval between the least and the greatest of the four products of ends, an end attained where both its factors are; a quotient is the product by the reciprocal, which is an interval exactly when the divisor does not contain zero, and that also answers a constant over such an interval, which #1118 left. Symbolic ends and factors, a sine over an interval, a root of a negative interval and a divisor around zero are left as written. Recorded in BREAKING-CHANGES.md against a v2.5.0 build, where every one of these was left as written. Full suite green; benchmark gate PASSED. Closes #322. Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura 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.
#322's arithmetic half.
SumfandMinusfhad interval cases andMulfandDivfhad none, so(0; 1) + 1answered(1; 2)while(0; 1) * 2was handed back. Three rows ofCore/Sets/Arithmeticsrecorded that asymmetry as the expected behaviour, sitting directly beneath the two addition rows that answer:The sign is the whole of it
k > 0k < 0k = 03 * [2; 3]3 * [2; 3][6; 9][2; 3] / 2[2; 3] / 2[1; 3/2][2; 3) * (-1)(-3; -2](2; 3] / (-1)[-3; -2)0 - [0; 1)-[0; 1)(-1; 0]The reflection is the half a test on the printed form alone would not catch: swapping the ends and leaving the flags where they were gives the right width and the wrong bracket at both ends. Membership is asserted too, for that reason.
That last row is not a subtraction at all —
0 - xis negated by an earlier arm, so it reachesMulfas-1 * [0; 1). It is the case #1117 had to explicitly leave out, and it comes back for free.An unknown sign is answered by not answering
(0; 1) * kfor symbolickis one interval whenkis positive and the reflected one when it is negative. Picking either would be choosing which, so it is left unevaluated — which is what an unevaluated node means.Two boundaries, asserted rather than left to be discovered
(0; 1) * 0still answers the number0rather than the set{ 0 }. That arm is over everyEntity, not only intervals, and moving it would change matrices and finite sets with it.2 / (0; 1)is left alone. A constant over an interval straddling zero is two unbounded pieces rather than one interval, so there is noIntervalto answer with.On the issue's stated blocker
#322 says it "will be possible once we implement quantifiers". Scaling needs none — it is monotone in the factor's sign and in nothing else. Finite sets already map arbitrary functions (
ln({1,2,3})→{0, ln(2), ln(3)}), and this closes the interval-arithmetic gap.What remains of #322 is applying a non-monotonic function to an interval:
ln((0; 1))is(-oo; 0)becauselnincreases, butsin((0; 7))needs to know where the turning points are. That is a real piece of work and genuinely a proposal.Recorded in
BREAKING-CHANGES.md, both values measured on a build.Full suite: 9059 passed, 14 skipped, 0 failed.
Part of #322. The issue is labelled
Not now— this was implemented at @Rafael-SOWNet's direction after posting the measurement above; close it if the timing still stands.