There is something strange that I do not understand:
julia> 2^-3
0.125
works ok. But the following minor generalization does not.
julia> g() = -3; 2^g()
ERROR: DomainError with -3:
Cannot raise an integer x to a negative power -3.
Make x or -3 a float by adding a zero decimal (e.g., 2.0^-3 or 2^-3.0 instead of 2^-3)or write 1/x^3, float(x)^-3, x^float(-3) or (x//1)^-3.
Stacktrace:
[1] throw_domerr_powbysq(::Int64, p::Int64)
@ Base ./intfuncs.jl:265
[2] power_by_squaring(x_::Int64, p::Int64)
@ Base ./intfuncs.jl:286
[3] ^(x::Int64, p::Int64)
@ Base ./intfuncs.jl:310
[4] top-level scope
@ REPL[2]:1
of course
julia> 2.0^g()
0.125
works. I tried to descend
into the call but did not find where 2^g()
misses the promotion to 2.0^g()
. I do not think it is a bug, but I do not see the rationale behind this behavior.
Thanks
From documentation on ^
:
If y is an Int literal (e.g. 2 in x^2 or -3 in x^-3), the Julia code x^y is transformed by the compiler to Base.literal_pow(^, x, Val(y)), to enable compile-time specialization on the value of the exponent. (As a default fallback we have Base.literal_pow(^, x, Val(y)) = ^(x,y), where usually ^ == Base.^ unless ^ has been defined in the calling namespace.) If y is a negative integer literal, then Base.literal_pow transforms the operation to inv(x)^-y by default, where -y
is positive.
julia> Base.literal_pow(^, 3, Val(-3))
0.037037037037037035
g()
in 2^g()
is not a literal, so this transformation does not happen.
1 Like
Thanks @barucden … I overlooked the docs. Marking your reply as a solution.
Yet, it is not completely clear why 2^g()
where g() is inferred to be an Int
should behave differently. g() is not a literal true, but there should be a code path where literal_pow and pow should behave the same for provably integer exponents.
This is not just about the exponent being an integer, but being a specific integer. Cf. Confusing difference: ^literal vs ^variable - #6 by StefanKarpinski for some rationale.