# Need a rarely used binary operator for matrices

**URL:** <https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263>\
**Category:** General Usage\
**Created:** [October 25, 2022, 11:15pm UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263 "2022-10-25T23:15:44Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![prittjam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/prittjam/32/21267_2.png) [@prittjam](https://discourse.julialang.org/u/prittjam)\
**Post date:** [October 25, 2022, 11:15pm UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/1 "2022-10-25T23:15:44Z")

</div>

Could you suggest a good binary operator that is not commonly used for matrices in Julia Base or packages? I need to use it for some common matrix operations in my code. I don’t want to step on something else.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [October 26, 2022, 12:10am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/2 "2022-10-26T00:10:58Z")

</div>

what’s the operation?

---

<div class="post-metadata">

**Author:** ![Tbl](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbl/32/5984_2.png) [@Tbl](https://discourse.julialang.org/u/Tbl)\
**Post date:** [October 26, 2022, 7:03am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/3 "2022-10-26T07:03:57Z")

</div>

I don’t think there’s much problem with conflicts for everything beyond standard arithmetic. I personally like `⊕` (`\oplus`) or '⊗` (`\otimes`).

If there is a conflict Julia just informs and asks to make the statement precise, e.g `MyLibrary.:⊕`

---

<div class="post-metadata">

**Author:** ![prittjam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/prittjam/32/21267_2.png) [@prittjam](https://discourse.julialang.org/u/prittjam)\
**Post date:** [October 26, 2022, 10:26am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/4 "2022-10-26T10:26:52Z")

</div>

multiplication of a homogeneous matrix with an inhomogeneous vector, e.g.,

hmul(A,x) = A[1:end,1:end-1]\*x.+A[:,end]

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [October 26, 2022, 10:41am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/5 "2022-10-26T10:41:17Z")

</div>

This is somewhat like a affine (translation) operation.  
Some possibilities  
`\otimesrhrim` : `⨵`  
`\oplusrhrim` : `⨮`

since they have a sense of directionality to them…

---

<div class="post-metadata">

**Author:** ![prittjam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/prittjam/32/21267_2.png) [@prittjam](https://discourse.julialang.org/u/prittjam)\
**Post date:** [October 26, 2022, 10:46am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/6 "2022-10-26T10:46:13Z")

</div>

Yes, homogeneous translation would be one application of it. Thanks for the tip!

---

<div class="post-metadata">

**Author:** ![prittjam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/prittjam/32/21267_2.png) [@prittjam](https://discourse.julialang.org/u/prittjam)\
**Post date:** [October 26, 2022, 10:46am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/7 "2022-10-26T10:46:46Z")

</div>

is the precedence the same as \* for those operators?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 26, 2022, 10:58am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/8 "2022-10-26T10:58:15Z")

</div>

> [@prittjam](#):
>
> ```julia
> hmul(A,x) = A[1:end,1:end-1]*x.+A[:,end]
> 
> ```

Seems to be faster to do

```julia
hmul2(A,x) = A * [x; 1]

```

Also, check out StaticArrays for this, it will be _much_ faster, if you are working on e.g. 3-4D vectors.

```julia
julia> using StaticArrays

julia> A = @SArray rand(4,4);

julia> x = @SArray rand(3);

julia> @btime hmul($A, $x)
  110.808 ns (3 allocations: 352 bytes)
4-element SizedVector{4, Float64, Vector{Float64}} with indices SOneTo(4):
 1.281701572863999
 1.45284156801398
 0.8569634443644434
 1.3118854951752263

julia> @btime hmul2($A, $x)
  2.900 ns (0 allocations: 0 bytes)
4-element SVector{4, Float64} with indices SOneTo(4):
 1.281701572863999
 1.45284156801398
 0.8569634443644434
 1.3118854951752263

```

---

<div class="post-metadata">

**Author:** ![prittjam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/prittjam/32/21267_2.png) [@prittjam](https://discourse.julialang.org/u/prittjam)\
**Post date:** [October 26, 2022, 11:10am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/9 "2022-10-26T11:10:41Z")

</div>

Wow, thanks for the tip. Yes, I am using 3-4D vectors and StaticArrays. I’m impressed that the augmentation does not cost an allocation. I see that it is constructed on the stack as an SVector. Very cool!

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 26, 2022, 11:13am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/10 "2022-10-26T11:13:26Z")

</div>

You don’t normally get any allocations as long as the sizes are statically known. It is easy for the compiler to see that `[x; 1]` will have type `SVector{4, Float64}`, though you could also use `StaticArrays.push` with no difference.

If you want to get rid of the last element of the output vector (which is common), you can use `StaticArrays.pop`. This can be quite useful, since

```julia
julia> typeof(x[1:end-1])
Vector{Float64} (alias for Array{Float64, 1})

julia> typeof(pop(x))
SVector{2, Float64} (alias for SArray{Tuple{2}, Float64, 1, 2})

```

---

<div class="post-metadata">

**Author:** ![prittjam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/prittjam/32/21267_2.png) [@prittjam](https://discourse.julialang.org/u/prittjam)\
**Post date:** [October 26, 2022, 11:53am UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/11 "2022-10-26T11:53:26Z")

</div>

Yes, type stability for these operations is tricky. Thanks for the tip. I have a more general question.

Suppose I have a vector of static vectors, e.g., something like,

```julia
 100-element reinterpret(SVector{2, Float64}, ::Vector{Float64}

```

but I’d like to be able to do

```julia
y = A*x

```

What is the Julian and most performant way to accomplish this? E.g., this works, but seems a bit awkward,

```julia
y = Ref(A).*x

100-element Vector{SVector{2, Float64}}

```

Now suppose I want the output y to be a matrix. Tullio is an option, e.g.,

```julia
@tullio y[i,k] := A[i,j]*x[k][j] 

2×100 Matrix{Float64}

```

Is there a solution using reinterpret?

---

<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:** [October 26, 2022, 12:27pm UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/12 "2022-10-26T12:27:15Z")

</div>

> [@prittjam](#):
>
> `y = Ref(A).*x`

This is the usual way.

That being said, if you are worried about the performance of this operation then you may be making a more fundamental mistake — the Matlab/Python style of “vectorized” programming [leaves a lot of performance on the table](https://julialang.org/blog/2017/01/moredots/#why_vectorized_code_is_not_as_fast_as_it_could_be) by doing a bunch of separate “vectorized” loops that each perform one small operation (producing a bunch of temporary arrays) rather than combining the calculations into a single pass over the data whenever possible. Presumably, in your real application, you aren’t _just_ doing `Ref(A) .* x`, and you should try to exploit that by writing a _single_ loop that does all of the operations you need on each `x[k]` at once.

---

<div class="post-metadata">

**Author:** ![prittjam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/prittjam/32/21267_2.png) [@prittjam](https://discourse.julialang.org/u/prittjam)\
**Post date:** [October 26, 2022, 12:37pm UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/13 "2022-10-26T12:37:10Z")

</div>

I suppose that loop fusion should eliminate temporaries for element-wise matrix operations. (matrix multiplication clearly cant be fused). Thanks for the response. I find some tension going between vector of vectors representations and matrices (or more generally tensors).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 26, 2022, 1:17pm UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/14 "2022-10-26T13:17:56Z")

</div>

Just using a loop should be a good solution here, but you could also have a look at [GitHub - JuliaArrays/HybridArrays.jl: Arrays with both statically and dynamically sized axes in Julia](https://github.com/JuliaArrays/HybridArrays.jl) which lets you mix static and dynamic dimensions, e.g. the number of rows is static, while the number of columns is dynamic. I believe it builds on top of StaticArrays.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 26, 2022, 1:21pm UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/15 "2022-10-26T13:21:42Z")

</div>

> [@prittjam](#):
>
> Is there a solution using reinterpret?

```julia
julia> As = @SMatrix rand(4,4);

julia> Xs = [@SVector rand(3) for _ in 1:10];

julia> reinterpret(reshape, Float64, hmul2.(Ref(As), Xs))
4×10 reinterpret(reshape, Float64, ::Vector{SVector{4, Float64}}) with eltype Float64:
 1.68023 1.41434 1.33775 1.3449 2.34028 0.655653 2.2069 2.09013 1.45916 1.42397
 2.12982 1.87084 1.80543 1.79198 2.79192 1.03538 2.60938 2.55969 1.67285 1.79207
 1.11249 1.06255 1.02429 1.0432 1.2869 0.845418 1.24341 1.22446 1.01764 1.02749
 1.09398 0.907248 0.901433 0.866234 1.47011 0.479292 1.39198 1.32744 0.951519 0.951254

```

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [November 1, 2022, 12:52pm UTC](https://discourse.julialang.org/t/need-a-rarely-used-binary-operator-for-matrices/89263/16 "2022-11-01T12:52:08Z")

</div>

The reference operator precedence table is here:

> <https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm>
