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

DomainError in bigint_pow #9618

Closed
xyproto opened this issue Jan 5, 2015 · 7 comments
Closed

DomainError in bigint_pow #9618

xyproto opened this issue Jan 5, 2015 · 7 comments
Labels
error handling Handling of exceptions by Julia or the user

Comments

@xyproto
Copy link

xyproto commented Jan 5, 2015

big(3)^big(9)^big(9)^big(9)

gives

ERROR: DomainError in bigint_pow at gmp.jl:352 in ^ at gmp.jl:356

This is for Julia 0.3.4 on 64-bit Arch Linux.

@aviks
Copy link
Member

aviks commented Jan 5, 2015

Not sure if this is a bug.

From the source of biginit_pow it looks like the exponent has to be less than the largest unsigned integer (which is 18446744073709551615 on 64 bits).

^ is parsed as right associative, which means that the exponent in your expression above becomes larger that that value.

julia> Base.Meta.show_sexpr( :( big(3)^big(9)^big(9)^big(9)))
(:call, :^, (:call, :big, 3), (:call, :^, (:call, :big, 9), (:call, :^, (:call, :big, 9), (:call, :big, 9))))

If you really wanted right associative exponentiation, then I don't know if there is a way. GMP's exponentiation function is limited to an uint exponent: https://gmplib.org/manual/Integer-Exponentiation.html#Integer-Exponentiation

However, if you force the expression to be left associative, then you could do:

julia> ((big(3)^9)^9)^9
662818605424187176105172864214479748588986673875686419462793267420461248113287928124072014075084032555900857691049061274135779819474602180821485109388447092848836753879024702508785576075431392037236950553064188689954912598712398079759040464474717726449363185622056684690721420542800623411346656785162817900551337542270334990205437212700131838846883

@xyproto
Copy link
Author

xyproto commented Jan 5, 2015

Thank you for the great reply. I'm not sure if this is a bug either. If this is not a bug, I think this issue should be considered a feature request for a slightly more informative error message.

@jiahao
Copy link
Member

jiahao commented Jan 5, 2015

The answer to this computation has ~10^(3e8) digits...

@JeffBezanson
Copy link
Member

Yes, this is hitting a hard limit in GMP and, really, in the size of the universe.

@ihnorton ihnorton added the error handling Handling of exceptions by Julia or the user label Jan 6, 2015
jiahao added a commit that referenced this issue Jan 6, 2015
jiahao added a commit that referenced this issue Jan 6, 2015
If y in (x::BigInt)^y exceeds typemax of Uint and x>=2, the result will
overflow. In this case, return OverflowError. Otherwise retain the
current behavior of returning a DomainError.
@jiahao
Copy link
Member

jiahao commented Jan 6, 2015

Technically speaking the current DomainError is correct for the reasons above. However, an OverflowError may be more in line with what users expect since the result would certainly overflow for |x|>1 anyway.

jiahao added a commit that referenced this issue Jan 6, 2015
If y in (x::BigInt)^y exceeds typemax of Uint and |x|>1, the result will
overflow. In this case, return OverflowError. Otherwise retain the
current behavior of returning a DomainError.
@aviks
Copy link
Member

aviks commented Jan 6, 2015

I'm uncertain if an OverflowError is any better than a DomainError without any more context.

We cant catch exceptions by type, so this is really a message to the user. You are therefore assigning a lot of meaning to the words "DomainError" vs "OverflowError" . Which may be true in some domains (sic) but I'm not sure is universally understood. At least at first glance, I'll personally find these hard to disambiguate these from each other, or from "ArgumentError".

In my mind, the goal is, when the user gets this error, does he understand what is wrong without reading library code?

@jiahao
Copy link
Member

jiahao commented Jan 6, 2015

To me DomainError indicates a problem with the domain, i.e. the function is not defined for its inputs, whereas OverflowError indicates a problem with the range, specifically that the output is too large to be represented. I think the distinction is quite clear, although this case happens to trigger both.

However, the OverflowError seems more appropriate to me when just looking at the operation x^y purely as the mathematical exponentiation operation. The DomainError makes sense only if I know something about the implementation of x^y as you have explained above.

See also #8286, where doing very large arithmetic in GMP leads to nasty SIGABRTs when it overflows.

@jiahao jiahao changed the title DomainError DomainError in bigint_pow Jan 6, 2015
jiahao added a commit that referenced this issue Jan 7, 2015
If y in (x::BigInt)^y exceeds typemax of Uint and |x|>1, the result will
overflow. In this case, return OverflowError. Otherwise retain the
current behavior of returning a DomainError, unless if x==0, in which
case just return 0.
jiahao added a commit that referenced this issue Jan 7, 2015
If y in (x::BigInt)^y exceeds typemax of Uint and |x|>1, the result will
overflow. In this case, return OverflowError. Otherwise retain the
current behavior of returning a DomainError, unless if x==0, in which
case just return 0.
jiahao added a commit that referenced this issue Jan 18, 2015
If y in (x::BigInt)^y exceeds typemax of Uint and |x|>1, the result will
overflow. In this case, return OverflowError. Otherwise retain the
current behavior of returning a DomainError, unless if x==0, in which
case just return 0.
@jiahao jiahao closed this as completed in b41ff44 Jan 18, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error handling Handling of exceptions by Julia or the user
Projects
None yet
Development

No branches or pull requests

5 participants