# Question regarding Base.power\_by\_squaring

**URL:** <https://discourse.julialang.org/t/question-regarding-base-power-by-squaring/87416>\
**Category:** New to Julia\
**Created:** [September 17, 2022, 6:35pm UTC](https://discourse.julialang.org/t/question-regarding-base-power-by-squaring/87416 "2022-09-17T18:35:56Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielramos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielramos/32/38919_2.png) [@danielramos](https://discourse.julialang.org/u/danielramos)\
**Post date:** [September 17, 2022, 6:35pm UTC](https://discourse.julialang.org/t/question-regarding-base-power-by-squaring/87416/1 "2022-09-17T18:35:56Z")

</div>

I’ve been playing with the @code\_typed macro and checking how some pieces of code behave. I was trying to check the differences between ^(2,5) and ^(2,-5) but @code\_typed shows the same output for these two cases (I’m using Julia 1.6.1):

> julia\> @code\_typed ^(2,5)  
> CodeInfo(  
> 1 ─ %1 = invoke Base.power\_by\_squaring(\_2::Int64, \_3::Int64)::Int64  
> └── return %1  
> ) =\> Int64
> 
> julia\> @code\_typed ^(2,-5)  
> CodeInfo(  
> 1 ─ %1 = invoke Base.power\_by\_squaring(\_2::Int64, \_3::Int64)::Int64  
> └── return %1  
> ) =\> Int64

Using @which ^(2,5), I was able to find where the implementation of this function is:

> julia\> @which ^(2,5)  
> ^(x::T, p::T) where T\<:Integer in Base at intfuncs.jl:289

I found out that it calls power\_by\_squaring and that if the exponent is negative and the base is different from 1 or -1, it should throw an error:

> function power\_by\_squaring(x\_, p::Integer)  
> x = to\_power\_type(x\_)  
> if p == 1  
> return copy(x)  
> elseif p == 0  
> return one(x)  
> elseif p == 2  
> return x\*x  
> elseif p \< 0  
> isone(x) && return copy(x)  
> isone(-x) && return iseven(p) ? one(x) : copy(x)  
> throw\_domerr\_powbysq(x, p)  
> end  
> t = trailing\_zeros(p) + 1  
> p \>\>= t  
> while (t -= 1) \> 0  
> x \*= x  
> end  
> y = x  
> while p \> 0  
> t = trailing\_zeros(p) + 1  
> p \>\>= t  
> while (t -= 1) \>= 0  
> x \*= x  
> end  
> y \*= x  
> end  
> return y  
> end

> ^(x::T, p::T) where {T\<:Integer} = power\_by\_squaring(x,p)

So I’m left with two unanswered questions:

1. Why, in @code\_typed, the return type of ^(2,-5) is Int64 and not Float64?
2. Why ^(2,-5) does not throw an exception?

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [September 17, 2022, 7:07pm UTC](https://discourse.julialang.org/t/question-regarding-base-power-by-squaring/87416/2 "2022-09-17T19:07:34Z")

</div>

I think the `@code...` -macros are wrong here. `2^5` (and `2^-5`) actually lowers to `Base.literal_pow(^, 2, Val(5))`. If in the REPL you do a `@less 2^-5`, you see the comment:

```julia
# x^p for any literal integer p is lowered to Base.literal_pow(^, x, Val(p))
# to enable compile-time optimizations specialized to p.

```

This has a somewhat weird effect:

```julia
julia> 2^-5
0.03125

julia> p = -5
-5

julia> 2^p
ERROR: DomainError with -5:
Cannot raise an integer x to a negative power -5.
Make x or -5 a float by adding a zero decimal (e.g., 2.0^-5 or 2^-5.0 instead of 2^-5)or write 1/x^5, float(x)^-5, x^float(-5) or (x//1)^-5.
Stacktrace:
...

```

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [September 17, 2022, 7:11pm UTC](https://discourse.julialang.org/t/question-regarding-base-power-by-squaring/87416/3 "2022-09-17T19:11:41Z")

</div>

This seems to be a limitation of the @code\_… macros. If you look at the corresponding function e.g.:

```julia
help?> code_lowered
search: code_lowered @code_lowered

  code_lowered(f, types; generated=true, debuginfo=:default)
  ...

```

you see, that it is working only on the types, e.g.:

```julia
ulia> code_lowered( ^, (Int,Int) )
1-element Vector{Core.CodeInfo}:
 CodeInfo(
1 ─ %1 = Base.power_by_squaring(x, p)
└── return %1
)

```

therefor you get the the wrong implementation. You can overcome this by:

```julia
julia> function show_power()
       res=^(2,-5)
       end
show_power (generic function with 1 method)

julia> @code_lowered show_power()
CodeInfo(
1 ─ %1 = Core.apply_type(Base.Val, -5)
│ %2 = (%1)()
│ %3 = Base.literal_pow(Main.:^, 2, %2)
│ res = %3
└── return %3
)

```

You see now that `Base.literal_pow` is actually called.

(expanded on @sgaure answer)
