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

promote(Int64(-1), Uint64(1)) yields an InexactError on v0.4 but not v0.3 #11303

Closed
yurivish opened this issue May 17, 2015 · 8 comments
Closed

Comments

@yurivish
Copy link
Contributor

A test for a package of mine that passes on 0.3 fails on 0.4. I've narrowed it down to the following problem:

julia> promote(Int64(-1), Uint64(1))
ERROR: InexactError()
 in promote at promotion.jl:132

The problem occurs in the context of a branch-free saturating arithmetic function for subtraction that uses some bitwise tricks for speed:

function satsub{T <: Unsigned}(x::T, y::Unsigned)
    res::T = x - y
    convert(T, res & -(res <= x))
end

The & call internally uses promote, which throws the InexactError. You can call satsub(Uint64(6), Uint64(5)) to produce the error in context.

On v0.3.7, here's the result of the equivalent call to promote:

julia> promote(int64(-1), uint64(1))
(0xffffffffffffffff,0x0000000000000001)

I am not sure what the expected behavior is and the current release notes for v0.4 don't mention anything regarding this change to promote. Is this a desired undocumented change or a bug?

If is a desired change, what should I be doing instead?

I'm running on OS X Yosemite with julia-0.4.0-c260ea92f4-osx.

@yurivish yurivish changed the title promote(Int64(-1), Uint64(1)) yields an InexactError [v0.4] promote(Int64(-1), Uint64(1)) yields an InexactError on v0.4 but not v0.3 May 17, 2015
@yurivish
Copy link
Contributor Author

Also, on 0.3:

julia> uint32(-1)
0xffffffff

julia> uint64(-1)
0xffffffffffffffff

julia> convert(Uint32, -1)
0xffffffff

julia> convert(Uint64, -1)
0xffffffffffffffff

On 0.4:

julia> Uint32(-1)
ERROR: InexactError()
 in call at /Applications/Julia-0.4.0-dev.app/Contents/Resources/julia/lib/julia/sys.dylib

julia> Uint64(-1)
ERROR: InexactError()
 in call at /Applications/Julia-0.4.0-dev.app/Contents/Resources/julia/lib/julia/sys.dylib

julia> convert(Uint32, -1)
ERROR: InexactError()
 in convert at /Applications/Julia-0.4.0-dev.app/Contents/Resources/julia/lib/julia/sys.dylib

julia> convert(Uint64, -1)
ERROR: InexactError()
 in convert at int.jl:180

@tkelman
Copy link
Contributor

tkelman commented May 17, 2015

At least the latter parts are intended, see #8420 - kinda buried in NEWS but it's there. You might want to try reinterpret(UInt64, -1)

@yurivish
Copy link
Contributor Author

Oh, right – I'd forgotten about those. Thanks! I'm now working on fixing up the saturating multiplication functions, which relied on conversions to extract the high 64 and low 64 bits from a Uint128. Reinterpret won't work here, since they're not the same size. Do you know what can be done instead?

@tkelman
Copy link
Contributor

tkelman commented May 17, 2015

shift and convert for high bits, mask and convert for low bits maybe?

@yurivish
Copy link
Contributor Author

Oh yeah! It's still valid to convert a higher-precision type into a lower-precision type if the value is within range...

@yurivish
Copy link
Contributor Author

So reinterpret(UInt64, -1) works, but reinterpret(UInt32, -1) fails with "ERROR: box: argument is of incorrect size". This is understandable, since reinterpret is about changing the type-interpretation while leaving the actual bits unchanged.

I wonder if there's a built-in function for saying something like "the signed integer type of the same size as the unsigned integer type T".

@simonbyrne
Copy link
Contributor

So reinterpret(UInt64, -1) works, but reinterpret(UInt32, -1) fails with "ERROR: box: argument is of incorrect size". This is understandable, since reinterpret is about changing the type-interpretation while leaving the actual bits unchanged.

You can also use mod (or %), for "modulo reinterpret"

julia> mod(-1,UInt32)
0xffffffff

I wonder if there's a built-in function for saying something like "the signed integer type of the same size as the unsigned integer type T".

Try signed/unsigned:

julia> unsigned(-1)
0xffffffffffffffff

julia> signed(typemax(UInt64))
-1

@tkelman
Copy link
Contributor

tkelman commented May 17, 2015

Good suggestions. Is there any action item on docs or a real bug here, or should we close this out?

@tkelman tkelman closed this as completed May 19, 2015
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

No branches or pull requests

3 participants