-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
fix float vs rational comparisons #8463
Conversation
a859ee8
to
d3a3d95
Compare
Okay, I've fixed the issues and rebased. Should be working now. |
d3a3d95
to
b73532c
Compare
@@ -206,6 +210,14 @@ end | |||
<=(x::Float32, y::Union(Int32,Uint32)) = float64(x)<=float64(y) | |||
<=(x::Union(Int32,Uint32), y::Float32) = float64(x)<=float64(y) | |||
|
|||
==(x::Float16,y::Integer) = float32(x) == y |
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 could be a serious problem that defining <
and promote_rule
for new types is no longer sufficient to get these kinds of cases to work. Maybe the new (Real,Real)
fallbacks should use Union(Rational,FloatingPoint)
instead? Or maybe we need a new Fractional
type between Real
and Rational
(and FloatingPoint
)?
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 reason for this are the calls to sign
, which require <(::NewType,::Integer)
. I might replace these with explicit x > zero(x)
checks, or define ispos
/isneg
methods (the advantage of the latter is that for BigFloat
and BigInt
it is possible to do the check without creating a zero(x)
). Then the Integer
comparisons would not be required for new types.
The problem with promote
is that in a lot of cases, there isn't going to be a single type which encompasses two distinct Real
types (e.g. BigFloat
can't exactly represent Rational
s). The decompose
-based approach seems like the most general construction, and would cover almost all cases (including <(::NewType,::Integer)
): the only exceptions I can think of are irrationals (like MathConst
or @jiahao's suggested Surd
type) and decimal floating point (which would require something like this).
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.
x > 0
should work for every type; zero(x)
should not be necessary there. Usually it will use promotion, but for example GMP has functions for comparing against small integers that we should use.
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 problem with relying on x > 0
is that <(::Integer,::NewType)
then also needs to be specifically defined for each NewType
.
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.
Ah, I see now.
|
2ef98c5
to
0388647
Compare
Yes, I'm rewriting this to use
I concede it's not fantastic, but
but the current structure wouldn't be very efficient, as rounding modes are values, not types (so we can't dispatch on them). Perhaps that's worth changing?
Hopefully nobody should ever have to call this directly. If they do, perhaps we should consider making it an immutable type? |
Okay, it should all be working now, bar |
@@ -360,6 +364,8 @@ typemax(::Type{Uint64}) = 0xffffffffffffffff | |||
@eval typemin(::Type{Int128} ) = $(convert(Int128,1)<<int32(127)) | |||
@eval typemax(::Type{Int128} ) = $(box(Int128,unbox(Uint128,typemax(Uint128)>>int32(1)))) | |||
|
|||
widen(::Type{Bool}) = Int | |||
widen(::Type{Char}) = Int |
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.
Int64?
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.
Good catch, thanks.
Instead of The reasons i don't like
|
This may not be a problem, but on this branch
|
I think overloading I'm working on a PR for FixedPointNumbers. |
I'm in the process of cleaning this up and rebasing, but something has occurred to me: this could be a bit simpler if we were to have Fewer internal comparisons would be required if the "denominator" from As far as I can tell, the only reason we need negative denominators is to distinguish between signed zeros. Is this useful? Also, one additional advantage of hashing them to be equal is that @StefanKarpinski thoughts? |
|
Yes, I suppose that would be ok. I have to think about it a bit and recall what my thinking was at the time, but I do think that allowing a negative denominator was the only reason – 0/-1 is the "decomposition" of -0.0 while 0/1 is the decomposition of 0.0. |
Closed in favour of #9198 |
This (should) fix
FloatingPoint
vsRational
comparisons (mentioned in #2960 and #8411), and should be easily extendable to other binaryReal
types such as FixedPointNumbers.jl.It does change the dispatch of comparison operators considerably, so there is a chance that this could break something, or cause a performance regression.