-
Notifications
You must be signed in to change notification settings - Fork 33
Implement promotion among UFixed, make convert errors more informative #53
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
Conversation
Closing and reopening to see if AppVeyor triggers. |
9d2bdf3
to
59331a8
Compare
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.
LGTM
U(_unsafe_trunc(T, y), 0) | ||
end | ||
function _convert{U<:UFixed}(::Type{U}, ::Type{UInt128}, x) | ||
y = round(rawone(U)*x) # for UInt128, we can't widen |
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.
If we definedwiden1(::Type{UInt128}) = UInt128
we wouldn't need to duplicate the code path and we would be forward compatible for the glorious day when we have UInt256
.
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 thought about that. The flip side is that if one is counting on widen1
to actually protect you, then you'll be mistaken.
But perhaps that's at too low of a level to matter, and that the only issue that matters is whether convert
successfully catches the problem. Which refusing to defining widen1
doesn't actually help with. I will change it.
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.
OK, we had a number of problems with high-precision UFixed types.
ef03354
to
a399254
Compare
convert{T1<:UFixed}(::Type{T1}, x::UFixed) = reinterpret(T1, round(rawtype(T1), (rawone(T1)/rawone(x))*reinterpret(x))) | ||
function convert{T<:UFixed}(::Type{T}, x::UFixed) | ||
y = round((rawone(T)/rawone(x))*reinterpret(x)) | ||
(0 <= y) & (y <= typemax(rawtype(T))) || throw_converterror(T, x) |
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.
why not just say (0 <= y <= typemax(rawtype(T))) || ...
?
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.
Performance. Currently a <= x <= b
gets lowered to (a <= x) && (x <= b)
rather than (a <= x) & (x <= b)
, which means there are two branches rather than one.
This is something that should probably be changed in Julia, but neither I nor anyone else has gotten to it yet.
39ef3f5
to
18615f8
Compare
a0628e5
to
526a7b9
Compare
f = 2^nbitsfrac(T)-1 | ||
:( T($f,0) ) | ||
function one{T<:UFixed}(::Type{T}) | ||
T(typemax(rawtype(T)) >> (8*sizeof(T)-nbitsfrac(T)), 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.
the generated version might be faster. see #44 (comment). or does the use of >>
instead of ^
close the gap?
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.
LLVM inlines this new version to a constant:
julia> @code_llvm one(UFixed{UInt64, 51})
define %UFixed @julia_one_70810(%jl_value_t*) #0 {
top:
ret %UFixed { i64 2251799813685247 }
}
The bigger issue was that for UInt128
(or even for UInt64
on 32-bit machines), 2^f
was returning 0 for f
bigger than the WORD_SIZE
. This version is guaranteed to be safe no matter what kind of machine or what kind of precision we're using.
On the master branch, we have the following bug:
We also have this uninformative message:
This PR fixes the bug by implementing
promote_type
amongUFixed
types. It also produces the more verbose error message:Assuming people like this, I think it should be merged before #51, and we can tag a new version before making a more incompatible change.