Integer type promotion behavior

I just started learning Julia. I know a bit of Python and R.

I have a (probably) simple question about integer type promotion behavior of Julia.

julia> versioninfo()
Julia Version 1.10.1
Commit 7790d6f064 (2024-02-13 20:41 UTC)
Build Info:
Official release
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: 20 × 12th Gen Intel(R) Core™ i7-12700K
LIBM: libopenlibm
LLVM: libLLVM-15.0.7 (ORCJIT, alderlake)
Threads: 1 default, 0 interactive, 1 GC (on 20 virtual cores)

julia> 2^62 # This works

julia> 2^63 # But this results in an overflow

julia> Int128(2)^Int128(63) # This solves the problem

julia> 2^Int128(63) # But, this doesn’t

julia> 2^big(63) # But, this works, which is strange

Is this an expected behavior?
Could anyone give me a link to a related documentation?


Looking at the code, it looks deliberate.

The integer promotion in power_by_squaring() promotes the integer type using to_power_type(), but this only takes the base into account.

to_power_type() in turn promotes the type to the output of the base times itself.

I imagine the intent here was ensure the output type of, for example, Int32(2)^4 behaved as if it were written as Int32(2) * Int32(2) * Int32(2) * Int32(2), irrespective of the integer type of the power. However, I think a case could be made to first apply standard integer promotion rules to both the base and power, before passing anything to to_power_type().

1 Like

Note that for exponentiation where base and power aren’t bother integer types, standard type promotion rules apply.

e.g. 2^Float64(2)::Float64 and Float32(2)^2::Float32

1 Like

So, I guess the proper way of ensuring the integer type is big enough to hold the result is Int128(2)^63 instead of 2^Int128(63).

And, probably 2^big(63) works for the similar reason why 2^Float64(63) works
(i.e., BigInt is more than just another integer type)?

Thank you very much for your reply!


1 Like

I think the bigint case is possibly a bug, but I’m not 100% sure. the reason we have the behavior we do is because things like Int8(-1)^UInt32(3) seem like they should work

1 Like