Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arithmetic operations with integers and intervals #594

Closed
wants to merge 1 commit into from

Conversation

lbenet
Copy link
Member

@lbenet lbenet commented Dec 6, 2023

Operations with integers should be promoted, since there are no issues with rounding,. I've hand-coded this operations to avoiding promotion.

@lbenet
Copy link
Member Author

lbenet commented Dec 6, 2023

More tests are perhaps needed...

@dpsanders
Copy link
Member

Aren't there issues with rounding if the integer is too big to represent exactly as a float, ie larger than 2^52 (?)

@lbenet
Copy link
Member Author

lbenet commented Dec 6, 2023

Aren't there issues with rounding if the integer is too big to represent exactly as a float, ie larger than 2^52 (?)

Good point! Indeed, that creates a problem with rounding....

@OlivierHnt
Copy link
Member

OlivierHnt commented Dec 6, 2023

A priori I am against this change; it is not a guaranteed operation. Integers can be produced in various ways which do not comply with interval arithmetic specifications. I believe this is the meaning of @Kolaru's comment #590 (comment).

The isguarantee field is not about correct rounding, but about the origin of the operands.

That being said, it is debatable for literal numbers (whether they are floats or integers or any other types). The problem is that it is not clear how to identify them. In fact, I am not even sure they can be distinguished from constant folded (from Julia's compiler) numbers...

@lbenet
Copy link
Member Author

lbenet commented Dec 6, 2023

I am very reluctant about this change; it is not a guaranteed operation. Integers can be produced in various ways which do not comply with interval arithmetic specifications.

I agree with you that the operation is not guaranteed in general, certainly not for for large integers (Ints) as David notes, but for small ones I think it should work. The following is a non-performant way to check that the "promotion" of Ints to intervals is guaranteed (at least for literal integers):

julia> setdisplay(:full);

julia> IntervalArithmetic.atomic(Float64,string(2.0^54)) # no need to round
BareInterval{Float64}(1.8014398509481984e16, 1.8014398509481984e16)

julia> isthin(ans)
true

julia> IntervalArithmetic.atomic(Float64,string(2.0^54+6)) # rounding is needed!
BareInterval{Float64}(1.8014398509481988e16, 1.801439850948199e16)

julia> isthin(ans)
false

(I think 2^54+6 is a the first Int that needs rounding when promoted to Float64, but that should be properly computed.)

Why do I care about this: essentially, many algorithms (in TaylorSeries) involve things like d = 2*c, which would lead to the "NG" tag, though it should definitely work. One could certainly write specialized methods with interval(2) instead, but that seems to involve repeating too much code for such a "tiny" change.

Again, the isguarantee field is not about correct rounding, but about the origin of the operands.

I agree, though I think that "origin of operands" at the end refers to the (finite) representation in some float format, which may involve rounding: interval(2,4)*0.5 is exacly interval(1,2), but replacing 0.5 by 0.1 requires rounding or the NG flag; dividing by interval(2) or interval(10) should yield a rigorous result. For these I do agree to have the NG flag when the "literals" are Float64. But for small enough integers, I think there should be no issue about rounding.

Hence, the only thing that is debatable are for literal numbers (whether they are floats or integers or any other types). The problem is that it is not clear how to identify them. In fact, I am not even sure they can be distinguished from constant folded (from Julia's compiler) numbers...

I think the code above shows the point of David: inspite of passing a literal Int, once the (Bare)Interval{Float64} is created, there may be issues with rounding.

The point to debate is whether we allow the user to write code like d = 2*c and expect no NG flag (due to the 2, but get it if the literal is too large), or we force him to write interval(2); in my opinion, we should opt for the second one.

@OlivierHnt
Copy link
Member

We have no choice but force the user to write interval(2). It is inconvenient but it is the only way we can preserve validated numerics and interoperability with Julia's ecosystem.

I agree, though I think that "origin of operands" at the end refers to the (finite) representation in some float format, which may involve rounding: interval(2,4)*0.5 is exacly interval(1,2), but replacing 0.5 by 0.1 requires rounding or the NG flag; dividing by interval(2) or interval(10) should yield a rigorous result. For these I do agree to have the NG flag when the "literals" are Float64. But for small enough integers, I think there should be no issue about rounding.

There are two separate problems. The one we care for is the parsing of numbers, not the correct rounding.

More concretely, in generic code we might want to use intervals as inputs and may end up with a computation x * interval(2, 4) where x is not an interval. Who can tell how x was obtained? We have lost validated numerics since we are mixing some untracked Real number with an interval.
So we must flag the interval with "NG" (instead of throwing an error), regardless if x is an integer or a float (or anything else).

Now, if one types π * interval(2, 4), well π cannot be the result of an unrigorous computation (since its internally defined as a constant) so this probably should not have the flag "NG". I agree; perhaps this PR can target this change?

The last scenario is if one types explicitly the number in their code, as in 2 * interval(2, 4), or 0.1 * interval(2, 4). Then, I also agree that this is safe (in both cases, but the integer case is easier to fix) because we trust that the user meant what they typed. So the question is how to hook into the parser to control this? Perhaps we should revive the @interval macro?
I do not see any other viable options.

@lbenet lbenet mentioned this pull request Dec 7, 2023
@lbenet
Copy link
Member Author

lbenet commented Dec 7, 2023

I agree; perhaps the way to overcome this, in a systematic way, is to revive @interval.

I will close this PR; we should continue the discussion in #595

@lbenet lbenet closed this Dec 7, 2023
@lbenet lbenet deleted the lb/arithm_with_ints branch March 8, 2024 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants