-
Notifications
You must be signed in to change notification settings - Fork 34
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 isinteger #123
fix isinteger #123
Conversation
fixes JuliaMath#120 : `isinteger(1N0f8)` should be true
Codecov Report
@@ Coverage Diff @@
## master #123 +/- ##
========================================
+ Coverage 78.3% 78.4% +0.1%
========================================
Files 3 3
Lines 212 213 +1
========================================
+ Hits 166 167 +1
Misses 46 46
Continue to review full report at Codecov.
|
This helps improve test type coverage
After solving the conflicts, I failed to rebase the commits (not a git expert). You could either squash it or rebase it into two commits (if it's possible):
|
Wow, this patch fails in Windows x86. That's really out of my ability then. Can someone take it over to let the test pass? |
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.
@johnnychen94, please replace the 1<<f-1
with one(T)<<f-0x1
.
(Don't forget to restore the CI settings.:smile:)
Edit:
I'm sorry, but the suggestions were wrong. Now fixed.
""" return true if symbol `x` is a `ST` type""" | ||
function _is_type(x::Symbol, ST::Symbol) | ||
try | ||
@eval $(x) isa Type && $(x) <: $(ST) && return true | ||
catch | ||
return false | ||
end | ||
end | ||
|
||
""" | ||
generate_fixedpoint_types(ST::Symbol=:FixedPoint) | ||
|
||
generate a list of concrete `ST` types, where `ST ∈ (:FixedPoint, :Fixed, :Normed)` | ||
""" | ||
function generate_fixedpoint_types(ST::Symbol=:FixedPoint) | ||
fixed_types = setdiff(filter(x->_is_type(x, ST), names(FixedPointNumbers)), [:Fixed, :Normed, :FixedPoint]) | ||
fixed_types = [@eval $(x) for x in fixed_types] | ||
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.
What about using isconcretetype(T)
instead of setdiff
and renaming this function to something like concrete_subtypes
.
"""
concrete_subtypes(T::Type)
generate a list of concrete subtypes of `T` which are defined in `FixedPointNumbers`.
"""
function concrete_subtypes(T::Type)
is_concrete_subtype(x) = x isa Type && x <: T && isconcretetype(x)
filter(is_concrete_subtype, eval.(names(FixedPointNumbers)))
end
I believe that any exceptions do not occur in unbroken modules. If any exceptions should occur, they should not be caught.
# predicates | ||
isinteger(x::Normed{T,f}) where {T,f} = (x.i%(1<<f-1)) == 0 |
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.
See also comment for the Fixed
test.
isinteger(x::Normed{T,f}) where {T,f} = (x.i%(one(T)<<f-1)) == 0
Edit:
# predicates | |
isinteger(x::Normed{T,f}) where {T,f} = (x.i%(1<<f-1)) == 0 | |
isinteger(x::Normed{T,f}) where {T,f} = (x.i%(one(T)<<f-0x1)) == 0 |
FYI, (n%-1) == 0
is always true
.
Moreover, if you write this here (I think we should do so), we should remove the following:
FixedPointNumbers.jl/src/FixedPointNumbers.jl
Lines 56 to 57 in da39318
# predicates | |
isinteger(x::FixedPoint{T,f}) where {T,f} = (x.i&(1<<f-1)) == 0 |
And then, add
isinteger(x::Fixed{T,f}) where {T,f} = (x.i&(one(T)<<f-0x1)) == 0
into "src/fixed.jl"
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 above is analogous to isinteger(x::Fixed)
. Of course, you can use rawone(Normed{T,f})
.
@testset "isinteger" begin | ||
# issue #120 | ||
for T in generate_fixedpoint_types(:Fixed) | ||
T_ints = T.(clamp.(rand(rawtype(T), 500, 500), | ||
ceil(rawtype(T), floattype(T)(typemin(T))), | ||
floor(rawtype(T), floattype(T)(typemax(T))))) | ||
@test all(isinteger.(T_ints)) | ||
end | ||
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.
The reason for the failures on 32-bit systems is that the bit mask is only 32-bit length even for Fixed{Int64}
.
isinteger(x::FixedPoint{T,f}) where {T,f} = (x.i&(1<<f-1)) == 0 |
julia> typeof(1)
Int32
julia> typeof(1<<63)
Int32
julia> bitstring(1<<63-1)
"11111111111111111111111111111111"
julia> bitstring(one(Int64)<<63-1)
"0111111111111111111111111111111111111111111111111111111111111111"
Therefore, we should fix it up as follows:
isinteger(x::Fixed{T,f}) where {T,f} = (x.i&(one(T)<<f-0x1)) == 0
BTW, since this is a testset for Fixed
, not Image
, we do not have to store such a large matrix.
There are only 65,536(=256×256 < 500×500) different patterns for each Fixed{Int16}
type. So, for Fixed{Int16}
and Fixed{Int8}
types, @timholy's method is better. (There is no round()
for Fixed
, though.) I think it is important to check the non-integer cases.
In addition, the types with a large f
can represent only few integers (e.g. two integers: -1Q0f31
and 0Q0f31
). I think this is too inefficient.
@testset "isinteger" begin | ||
# issue #120 | ||
for T in generate_fixedpoint_types(:Normed) | ||
T_ints = T.(clamp.(rand(rawtype(T), 500, 500), | ||
ceil(rawtype(T), floattype(T)(typemin(T))), | ||
floor(rawtype(T), floattype(T)(typemax(T))))) | ||
@test all(isinteger.(T_ints)) | ||
end | ||
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.
See the comment for Fixed
version.
Thank you for putting your time investigating it! I'll find time to fix them accordingly. (I'm a little busy these days, and my night time is spent on ReferenceTests.jl, so if you can't wait, you can continue the work here :D) |
As I did not care about this issue until yesterday, please take your time. |
I am sorry for hindering the |
I'm ready to fix Since the master has left this branch, I'm going to submit a new PR. |
@kimikage Please feel free to do so 👍 , recently I just spent too much time here and I'm trying to catch up with my daily research projects in ECNU. |
fixes #120 :
isinteger(1N0f8)
should be trueP.S. I don't quite understand the magic behind bits operation, but the tests pass with this patch.
cc: @cjdoris