-
Notifications
You must be signed in to change notification settings - Fork 10
Fix NaN arithmetic #81
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
Open
PatrickHaecker
wants to merge
4
commits into
JuliaMath:master
Choose a base branch
from
PatrickHaecker:nan_arithmetic
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hahaha this is exactly what I just suggested!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw For every
θthat is "natural" in base 2 (1, -1, 1/2, 1/4, 3/4, etc.) it turns outangle(exp(im*θ)) == θ. This seems like a a very lucky coincidence that rounding goes in the right direction!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but it only covers part of it, because we still have no defined interval the value is in and we still have a very strange format so store an angle when we have an integer. So this needs more thought.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are definitely onto something here. While it is true for all your numbers, it interestingly is not true, e.g., for 1/8:
So although 1/8 is exact in floating points, the calculation is not exact. That not only means that our tests are incomplete here (I already added some, but have not yet pushed). It also means that we need to check whether this loss of precision is a problem anywhere. And there are quite some locations where we do the exact comparison.
But I need to do this with a fresh mind tomorrow.
Especially as this lead me to
toinfand I currently think we have a bug intoinf:And I don't understand how we can have such a large bug here without the test suite detecting it. So I probably need to have a fresh look tomorrow to see why this is not a bug and only my current understanding is incomplete.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was indeed a bug and there is an explanation why the tests haven't caught it. Fix, details and off-axis tests in #85. So for all I know this conversation is resolved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The really important case is that for
r > 0whereris any real we always have_sb(r+0im) = zero(r),_sb(-r±0im) = one(r),_sb(r*im) = one(r)/2,_sb(-r*im) = -one(r)/2so we want this to be correct for
BigFloatand other types too. Actually, I'm not sure what the types should be (I guess for<: Realwe want them to beBool)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you mean
==as comparison. What do you mean with "types"? The storage type or the return type?I am currently trying a combination of
UInt64as a storage type and usingsignwith aFloat64as a possible user interface in addition to other methods forBasefunctions.This seems to work well up to now (unique values, some precision everywhere, wrapping for free, usage without rounding possible), but I can't yet see whether this will work in the whole package, which is the relevant question in the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit of a fringe question so I don't think any choice makes a big practical choice. But what I mean is if
_sb(x::Real) = signbit(x)then the return type is aBool, but for_sb(::Complex{<:Union{Int,Float64})it should probably be aFloat64. But then what about_sb(::Complex32)and_sb(::Complex{BigFloat})? ProbablyFloat32andBigFloat. (which I believe your implementation does)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the concern is: do we actually know that rounding works correctly for all
BigFloat? Eg, we haveThere is no obvious guarantee that when we divide this by
πwe get exactly1/2.Except.....in tests we do up to precision 10_000:
Which is to say: I think by luck we are fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you talking about #81 and not about the possible future solution.
I think in general we can't be exact with floats. The user can always have any arbitrary transformations between two points in time and when they compare then according to what should be identical with two mathematical reals it can be different in our implementation.
That being said, I think in this case it is probably more than luck. I am speculating, because I haven't followed into MPFR's implementation, but your example boils down to:
which is
and I strongly assume that this special cases such that
atanwill return the best rounding ofπ/2according to the current precision if the first argument is positive and the second is0. This triggers reliably because1and0are exact.πandπ/2will then have the same number in the significant and only differ in the mantissa by exactly1leading to0.5exactly in the division.So while it would be possible to implement that in a different way, I think an implementation which cares about precision will always return the exact value here, despite being a floating point operation. That's just a special case which is exact when using binary floating points. It wouldn't for some other base in general, but it is with base
2.