# Should power\_by\_squaring be defined for negative powers?

**URL:** https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831
**Category:** New to Julia
**Created:** [February 5, 2018, 2:46pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831 "2018-02-05T14:46:59Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [February 5, 2018, 2:46pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/1 "2018-02-05T14:46:59Z")

</div>

I write to tell of a disappointment I had. Perhaps people can explain to me  
the rationale or the right solution.

I implemented my permutation type (I am porting GAP code and none of the  
existing permutation packages quite filled my requirements). I was  
pleasantly surprised that, as soon as I defined the product of 2  
permutations, the power p^3 was automatically defined for a permutation p.  
But I was soon disappointed: p^-2 gives an error message, even though I  
defined inv( p )

I tracked this to the function power\_by\_squaring which raises an error  
automatically on negative exponents. I think that power\_by\_squaring should  
define p^-2 as power\_by\_squaring(inv( p ),2).

It would cause an incompatibility since inv is defined on integers,  
yielding floats, so this would define negative powers of integers. But I  
think defining inv on integers is a mistake since it makes inv  
type-unstable.

What do people think?

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [February 5, 2018, 3:07pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/2 "2018-02-05T15:07:35Z")

</div>

> [@Jean\_Michel](#):
>
> It would cause an incompatibility since inv is defined on integers,
> 
> yielding floats, so this would define negative powers of integers. But I
> 
> think defining inv on integers is a mistake since it makes inv
> 
> type-unstable.

No, `inv` is type-stable there. Type-stability doesn’t mean that the type returned by a function is the same as the input. It means that the type can be inferred at every step of the way. If `inv` of an integer is always a floating point number, then that’s type stable. The problem then is that `^` on integers wouldn’t be type-stable because it could output floats or integers, even though `inv` and `power_by_squaring` are type-stable, because of the switch where you’d check for negativity in order to apply `inv` which does a type change.

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [February 5, 2018, 3:21pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/3 "2018-02-05T15:21:12Z")

</div>

Ok, I see there would be a problem for Integers. It could of course be solved by a ^ method for them  
which would check that the exponent is positive before calling power\_by\_squaring. Still, it would be nice  
to have negative powers defined automatically for types which have inverses of the same type.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [February 5, 2018, 3:39pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/4 "2018-02-05T15:39:19Z")

</div>

Can’t you just implement it for your type if it is closed under `inv`? Eg

```julia
struct Foo{T <: AbstractFloat}
    x::T
end

Base.:*(a::Foo, b::Foo) = Foo(a.x * b.x)

Base.inv(a::Foo) = Foo(1/a.x) # assume this is returns the same type

Base.one(a::Foo) = Foo(one(a.x))

function Base.:^(a::Foo, p::Integer)
    if p ≥ 0
        Base.power_by_squaring(a, p)
    else
        Base.power_by_squaring(inv(a), -p)
    end
end

```

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [February 5, 2018, 4:06pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/5 "2018-02-05T16:06:35Z")

</div>

Of course I did implement it as you showed. The point is that it would be nice to have it being defined  
_automatically_. A slightly different design for Base would achieve that.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [February 5, 2018, 4:37pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/6 "2018-02-05T16:37:39Z")

</div>

> [@Jean\_Michel](#):
>
> A slightly different design for Base would achieve that.

Can you provide an example? I don’t see how you could automate it, besides relying on the return type. Eg

```julia
function Base.:^(a::T, p::Integer) where T
    if p ≥ 0
        Base.power_by_squaring(a, p)
    else
        b = inv(a)
        b isa T || error("won't calculate the inverse 'cause it is not type stable")
        Base.power_by_squaring(b, -p)
    end
end

```

then hope that it is optimized away.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [February 5, 2018, 4:40pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/7 "2018-02-05T16:40:11Z")

</div>

You can add a `Core.Inference` call (and make place `Base.@pure` on it if you want to assume that the inference result won’t change) and error based on the output of that.

---

<div class="post-metadata">

### Author: ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)
#### Post date: [February 5, 2018, 8:52pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/8 "2018-02-05T20:52:10Z")

</div>

@Tamas_Papp That definition looks reasonable to me (although I might abbreviate it as `b = inv(a)::T`). Maybe we should add this to the definition in Base?

> [@ChrisRackauckas](#):
>
> You can add a Core.Inference call (and make place Base.@pure on it if you want to assume that the inference result won’t change) and error based on the output of that.

`Core.Inference` is not `@pure`, and it makes no sense to suggest either here, since they don’t appear to have any connection to the original question (there is no use of inference necessary here, nor are any of the results known to be pure)

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [February 5, 2018, 9:10pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/9 "2018-02-05T21:10:49Z")

</div>

> [@jameson](#):
>
> Core.Inference is not @pure, and it makes no sense to suggest either here, since they don’t appear to have any connection to the original question (there is no use of inference necessary here, nor are any of the results known to be pure)

I was thinking a call to `Core.Inference` would get rid of calling `inv(a)`, but now I see that @tpapp’s way would probably just compile directly to an error in the else case so sure that works without calling Inference. And I did say that there are cases where pure is wrong there…

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [February 6, 2018, 2:16am UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/10 "2018-02-06T02:16:06Z")

</div>

> [@Jean\_Michel](#):
>
> But I was soon disappointed: `p^-2` gives an error message, even though I defined `inv( p )`

Note that in Julia 0.7, `p^-2` lowers to `inv(p)^2`, so this will work and be type-stable for literal integer exponents. ([make x^-n equivalent to inv(x)^n for literal n by stevengj · Pull Request #24240 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/24240)).

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [February 6, 2018, 7:00am UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/11 "2018-02-06T07:00:19Z")

</div>

> [@jameson](#):
>
> Maybe we should add this to the definition in Base?

I don’t see any harm in it.

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [February 6, 2018, 12:06pm UTC](https://discourse.julialang.org/t/should-power-by-squaring-be-defined-for-negative-powers/8831/12 "2018-02-06T12:06:35Z")

</div>

Thank everybody for the reactivity!  
If I understand, negative powers already work in 0.7 for literal exponents. That would be an argument to  
add for consistency Tamas Papp’s implementation (with Jameson’s improvement) ,so negative exponents  
work more generally.
