# Is matrix multiplication not associative?

**URL:** <https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231>\
**Category:** New to Julia\
**Tags:** question, error, matrix\
**Created:** [March 21, 2025, 4:09pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231 "2025-03-21T16:09:38Z")\
**Posts on this page:** 3\
**Page:** 2

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [March 23, 2025, 12:03am UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/21 "2025-03-23T00:03:25Z")

</div>

> [@stevengj](#):
>
> In linear algebra, the more fundamental operation is the adjoint ^\*

I agree.

> [@stevengj](#):
>
> the two are functionally and computationally equivalent for real vectors and matrices.

I’ve learned that.

The following is an example. Presumably `sm` is a more fundamental operation than `s_conj_m`.  
And `transpose` (rather than `'`) corresponds to `sm`. (That’s why in some sense I think `transpose` is more fundamental).

```julia
function sm(p, x) return sum(p .* x) end
function s_conj_m(p, x) return sum(conj(p) .* x) end
import LinearAlgebra.tr as tr
A = rand(ComplexF64, 3, 2)
B = rand(ComplexF64, 3, 2)
# ✅ The following LHS == RHS
LHS, RHS = sm(A, B), tr(transpose(A) * B)
@assert LHS == RHS "might due to tolerance";

# ✅ The following LHS == RHS
LHS, RHS = s_conj_m(A, B), tr(A' * B)
@assert LHS == RHS "might due to tolerance";

```

---

<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:** [March 23, 2025, 12:48am UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/22 "2025-03-23T00:48:14Z")

</div>

You seem to imply that, conceptually, `adjoint == conj ∘ transpose`, thus `transpose` is simpler and more fundamental when your arrays are real. I think @stevengj is arguing that you should reframe this as follows:

| Vector space | Linear algebra concept | Implementation for arrays |
| --- | --- | --- |
| Real | `adjoint` | `transpose` |
| Complex | `adjoint` | `conj ∘ transpose` |

In other words, you should let go of the idea that `adjoint` always implies conjugation. Rather, adjoint is the linear algebra concept that `transpose` accomplishes on a real-valued array, and `conj ∘ transpose` accomplishes on a complex-valued array.

The beauty of multiple dispatch is that function names can live on the conceptual level while compiling down to code that’s specific to the case at hand. You don’t have to worry about redundant `conj` calls under the hood when using `adjoint` on real vectors, the same way you don’t have to worry about hitting the complex code path applicable to `exp(2.0 + 2.0im)` when calling `exp(2.0)`.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [March 23, 2025, 2:11am UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/23 "2025-03-23T02:11:43Z")

</div>

> [@danielwe](#):
>
> You don’t have to worry about redundant `conj` calls under the hood when using `adjoint` on real vectors

This makes sense, which is reassuring.

[Previous page](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231.md?page=1)
