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

convert(Unsigned, ::BigInt) and convert(Signed, ::BigInt) throw confusing error #19182

Closed
jiahao opened this issue Nov 1, 2016 · 8 comments
Closed
Labels
domain:bignums BigInt and BigFloat

Comments

@jiahao
Copy link
Member

jiahao commented Nov 1, 2016

Migrated from #15601 (comment):

julia> Unsigned(big(100))
ERROR: argument is an abstract type; size is indeterminate
 in convert(::Type{Unsigned}, ::BigInt) at ./gmp.jl:181
 in Unsigned(::BigInt) at ./sysimg.jl:53

julia> Signed(big(100))
ERROR: argument is an abstract type; size is indeterminate
 in convert(::Type{Signed}, ::BigInt) at ./gmp.jl:191
 in Signed(::BigInt) at ./sysimg.jl:53

The methods here (defined for T<:Signed and T<:Unsigned) fail because sizeof(Signed) and sizeof(Unsigned) are not defined, which are called in the cases T==Signed and T==Unsigned.

It seems clear to me that we need specialized methods to handle convert(Unsigned, ::BigInt) and convert(Signed, ::BigInt) to fix the issue, but I'm not sure what the correct thing to do is here. Two obvious options:

  1. Try to convert to Int or UInt, else throw an InexactError if the BigInt is too big (or has the wrong sign in the case of Unsigned(big(-1))).

  2. Always throw an InexactError (a better error than "argument is an abstract type").

@yuyichao
Copy link
Contributor

yuyichao commented Nov 1, 2016

Is there a different use case where converting to Signed and Unsigned is useful (and just work on BigInt for generic code). I see convertions to Integer in generic code a lot but not as much for Unsigned / Signed . If not then maybe throw a better error would be the way to go.

@stevengj
Copy link
Member

stevengj commented Nov 1, 2016

It seems like we should define BigInt :< Signed and make Signed(x::BigInt) = x a no-op. Unsigned(::BigInt) seems like it should throw an error since we don't have an unsigned bignum type.

@stevengj
Copy link
Member

stevengj commented Nov 1, 2016

Seems wrong:

julia> BigInt <: Signed
false

(Note also that there is no docstring for Signed.)

@jiahao
Copy link
Member Author

jiahao commented Nov 2, 2016

Yeah, BigInts live outside of Signed and Unsigned, which seems strange.

@simonbyrne
Copy link
Contributor

I think a few places may use an implicit assumption that Signed integers are stored as two's complement, which BigInts are not.

@stevengj
Copy link
Member

stevengj commented Nov 2, 2016

@simonbyrne, can you give an example? I would think that any such methods would need (and maybe already have) specialized BigInt methods already.

@stevengj
Copy link
Member

stevengj commented Nov 2, 2016

One problem is that we'll get a bunch of method ambiguities that we'll need to resolve. e.g. <( x::Signed, y::Unsigned) will become ambiguous with <(x::BigInt, i::Integer).

@simonbyrne
Copy link
Contributor

simonbyrne commented Nov 2, 2016

I had a quick look in Base, and I didn't see any, so maybe it is okay (though packages may do this).

The other issue is the use of typemin/typemax: I think most uses in Base will be okay, but this one will need another method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:bignums BigInt and BigFloat
Projects
None yet
Development

No branches or pull requests

5 participants