# Adjoint(A)\*A for MArray and Type Stability

**URL:** <https://discourse.julialang.org/t/adjoint-a-a-for-marray-and-type-stability/118201>\
**Category:** Specific Domains\
**Tags:** question\
**Created:** [August 14, 2024, 8:24pm UTC](https://discourse.julialang.org/t/adjoint-a-a-for-marray-and-type-stability/118201 "2024-08-14T20:24:07Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Domenico\_Lahaye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/domenico_lahaye/32/203728_2.png) [@Domenico\_Lahaye](https://discourse.julialang.org/u/Domenico_Lahaye)\
**Post date:** [August 14, 2024, 8:24pm UTC](https://discourse.julialang.org/t/adjoint-a-a-for-marray-and-type-stability/118201/1 "2024-08-14T20:24:07Z")

</div>

I wonder how to implement Adjoint(A)\*A in type stable way for MArrays. Below is a MWE and output of @code\_warntype()

```julia
struct SFoo
  SGnu::SMatrix{3,3}
end 

struct MFoo
  MGnu::MMatrix{3,3}
end 

sgnu = SMatrix{3,3}(0., 0., 0., 0., 0., 0., 0., 0., 0.)
sfoo = SFoo(sgnu)

mgnu = MMatrix{3,3}(0., 0., 0., 0., 0., 0., 0., 0., 0.)
mfoo = MFoo(mgnu)

function bar(sfoo)
    sgnu = sfoo.SGnu 
    return Adjoint(sgnu)*sgnu 
end 

function bar(mfoo)
    mgnu = mfoo.MGnu 
    return Adjoint(mgnu)*mgnu 
end 

```

Goes well for SArray

MethodInstance for bar(::SFoo)  
from bar(mfoo) in Main at In[65]:6  
Arguments  
#self#::Core.Const(bar)  
mfoo::SFoo  
Locals  
mgnu::Union{}  
Body::Union{}  
1 ─ (mgnu = Base.getproperty(mfoo, :MGnu))  
│ Core.Const(:(Main.Adjoint(mgnu)))  
│ Core.Const(:(%2 \* mgnu))  
└── Core.Const(:(return %3))

Results in Any for MArray

MethodInstance for bar(::MFoo)  
from bar(mfoo) in Main at In[65]:6  
Arguments  
#self#::Core.Const(bar)  
mfoo::MFoo  
Locals  
mgnu::MMatrix{3, 3}  
Body::Any  
1 ─ (mgnu = Base.getproperty(mfoo, :MGnu))  
│ %2 = Main.Adjoint(mgnu)::Adjoint  
│ %3 = (%2 \* mgnu)::Any  
└── return %3

---

<div class="post-metadata">

**Author:** ![JonasWickman](https://avatars.discourse-cdn.com/v4/letter/j/9de0a6/32.png) [@JonasWickman](https://discourse.julialang.org/u/JonasWickman)\
**Post date:** [August 14, 2024, 8:36pm UTC](https://discourse.julialang.org/t/adjoint-a-a-for-marray-and-type-stability/118201/2 "2024-08-14T20:36:12Z")

</div>

I’m not sure why this correctly infers for the SMatrix case, but you can fix it for the MMatrix case by fully specifying your MMatrix type like so:

```julia
struct MFoo{T}
    MGnu::MMatrix{3, 3, T, 9}
end 

```

With this, running

```julia
mgnu = MMatrix{3,3}(0., 0., 0., 0., 0., 0., 0., 0., 0.)
mfoo = MFoo(mgnu)
bar(mfoo)

```

will correctly infer the return type as an MMatrix. The final type parameter (the 9) is the number of elements stored for the MMatrix, and the `T` is the numeric type (here, a `Float64`)

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [August 14, 2024, 8:45pm UTC](https://discourse.julialang.org/t/adjoint-a-a-for-marray-and-type-stability/118201/3 "2024-08-14T20:45:59Z")

</div>

> [@Domenico\_Lahaye](#):
>
> ```julia
> function bar(sfoo)
> sgnu = sfoo.SGnu 
> return Adjoint(sgnu)*sgnu 
> end 
> 
> function bar(mfoo)
> mgnu = mfoo.MGnu 
> return Adjoint(mgnu)*mgnu 
> end
> 
> ```

The second method overwrites the first here, so you’re studying the `bar(mfoo)` version in both cases. It looks type stable when the argument is an `SFoo` because the compiler knows it will error and never return; instances of type `SFoo` have no field `MGnu`. Note that the inferred return type is `Union{}`, which is a type with no instances.

To implement different methods for different types, use type annotations as follows:

```julia
function bar(sfoo::SFoo)
    sgnu = sfoo.SGnu 
    return Adjoint(sgnu)*sgnu 
end 

function bar(mfoo::MFoo)
    mgnu = mfoo.MGnu 
    return Adjoint(mgnu)*mgnu 
end

```

To solve the type stability issue, make the fields concretely typed as shown by @JonasWickman, though I would personally prefer a solution that requires less knowledge about the implementation of `MMatrix`, like the following:

```julia
struct MFoo{M<:MMatrix{3,3}}
    MGnu::M
end

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [August 14, 2024, 8:52pm UTC](https://discourse.julialang.org/t/adjoint-a-a-for-marray-and-type-stability/118201/4 "2024-08-14T20:52:16Z")

</div>

One more thing, you should normally avoid using the constructor `Adjoint`. Instead, use the function `adjoint`, or, equivalently, the postfix operator `'`, as in `adjoint(mgnu) * mgnu` or `mgnu' * mgnu`.

The main difference is that `adjoint` knows that it is its own inverse, so `adjoint(adjoint(M)) === M`. Meanwhile, `Adjoint` is a dumb wrapper and will keep wrapping the wrapper if called multiple times.

---

<div class="post-metadata">

**Author:** ![Domenico\_Lahaye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/domenico_lahaye/32/203728_2.png) [@Domenico\_Lahaye](https://discourse.julialang.org/u/Domenico_Lahaye)\
**Post date:** [August 14, 2024, 9:02pm UTC](https://discourse.julialang.org/t/adjoint-a-a-for-marray-and-type-stability/118201/5 "2024-08-14T21:02:21Z")

</div>

Many thanks to both of you!

My limited understanding is that bar(sfoo) and bar(mfoo) are distinct by dispatch of the argument. Are they not?

Extending MMatrix{3,3} to MMatrix{3,3,Float64,9} does remove the type instability. I would like to beter understand why extending {3,3} to {3,3,Float64,9} is not required in the SMatrix case.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [August 14, 2024, 9:10pm UTC](https://discourse.julialang.org/t/adjoint-a-a-for-marray-and-type-stability/118201/6 "2024-08-14T21:10:41Z")

</div>

> [@Domenico\_Lahaye](#):
>
> My limited understanding is that bar(sfoo) and bar(mfoo) are distinct by dispatch of the argument. Are they not?

You need to add type annotations, as showed in my post above. Julia dispatches on _types_ of arguments, not _names_ of arguments.

> [@Domenico\_Lahaye](#):
>
> I would like to beter understand why extending {3,3} to {3,3,Float64,9} is not required in the SMatrix case.

As explained, if you actually tried to call `bar(sfoo)` the way you’ve written it, it would throw an error every time. This is why it looks “type stable”—it never returns and has no return type. Once you have a working implementation for both cases you will need a concrete field type in both cases, for example using parameters `{3,3,Float64,9}` (but see also the simpler and more generalizable solution at the bottom of my first post).

---

<div class="post-metadata">

**Author:** ![Domenico\_Lahaye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/domenico_lahaye/32/203728_2.png) [@Domenico\_Lahaye](https://discourse.julialang.org/u/Domenico_Lahaye)\
**Post date:** [August 14, 2024, 9:17pm UTC](https://discourse.julialang.org/t/adjoint-a-a-for-marray-and-type-stability/118201/7 "2024-08-14T21:17:53Z")

</div>

Thanks again.

Using

```julia
methods(bar)

```

I was able to gain a better understanding.
