<p dir="auto"><code class="notranslate">mul!</code> normally works for arbitary matrixs.<br>
The product of two triangular matrixs is itself triangular.<br>
But if i specify the storage destination as being a triangular matrix <code class="notranslate">mul!</code> errors.</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; using LinearAlgebra

julia&gt; X = LowerTriangular(rand(10,10));

julia&gt; Y = LowerTriangular(rand(10,10));

julia&gt; Z = LowerTriangular(rand(10,10));

julia&gt; mul!(Z, X, Y)
ERROR: MethodError: no method matching lmul!(::LowerTriangular{Float64, Matrix{Float64}}, ::LowerTriangular{Float64, Matrix{Float64}})
Closest candidates are:
  lmul!(::Tridiagonal, ::LinearAlgebra.AbstractTriangular) at /usr/local/src/julia/julia-master/usr/share/julia/stdlib/v1.6/LinearAlgeb
ra/src/triangular.jl:683
  lmul!(::Diagonal, ::AbstractVecOrMat{T} where T) at /usr/local/src/julia/julia-master/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/d
iagonal.jl:210
  lmul!(::UniformScaling, ::AbstractVecOrMat{T} where T) at /usr/local/src/julia/julia-master/usr/share/julia/stdlib/v1.6/LinearAlgebra
/src/uniformscaling.jl:286
  ...
Stacktrace:
 [1] mul!(C::LowerTriangular{Float64, Matrix{Float64}}, A::LowerTriangular{Float64, Matrix{Float64}}, B::LowerTriangular{Float64, Matri
x{Float64}})
   @ LinearAlgebra /usr/local/src/julia/julia-master/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/triangular.jl:700
 [2] top-level scope
   @ REPL[5]:1"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-k">using</span> LinearAlgebra

julia<span class="pl-k">&gt;</span> X <span class="pl-k">=</span> <span class="pl-c1">LowerTriangular</span>(<span class="pl-c1">rand</span>(<span class="pl-c1">10</span>,<span class="pl-c1">10</span>));

julia<span class="pl-k">&gt;</span> Y <span class="pl-k">=</span> <span class="pl-c1">LowerTriangular</span>(<span class="pl-c1">rand</span>(<span class="pl-c1">10</span>,<span class="pl-c1">10</span>));

julia<span class="pl-k">&gt;</span> Z <span class="pl-k">=</span> <span class="pl-c1">LowerTriangular</span>(<span class="pl-c1">rand</span>(<span class="pl-c1">10</span>,<span class="pl-c1">10</span>));

julia<span class="pl-k">&gt;</span> <span class="pl-c1">mul!</span>(Z, X, Y)
ERROR<span class="pl-k">:</span> MethodError<span class="pl-k">:</span> no method matching <span class="pl-c1">lmul!</span>(<span class="pl-k">::</span><span class="pl-c1">LowerTriangular{Float64, Matrix{Float64}}</span>, <span class="pl-k">::</span><span class="pl-c1">LowerTriangular{Float64, Matrix{Float64}}</span>)
Closest candidates are<span class="pl-k">:</span>
  <span class="pl-c1">lmul!</span>(<span class="pl-k">::</span><span class="pl-c1">Tridiagonal</span>, <span class="pl-k">::</span><span class="pl-c1">LinearAlgebra.AbstractTriangular</span>) at <span class="pl-k">/</span>usr<span class="pl-k">/</span><span class="pl-k">local</span><span class="pl-k">/</span>src<span class="pl-k">/</span>julia<span class="pl-k">/</span>julia<span class="pl-k">-</span>master<span class="pl-k">/</span>usr<span class="pl-k">/</span>share<span class="pl-k">/</span>julia<span class="pl-k">/</span>stdlib<span class="pl-k">/</span>v1.<span class="pl-c1">6</span><span class="pl-k">/</span>LinearAlgeb
ra<span class="pl-k">/</span>src<span class="pl-k">/</span>triangular<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">683</span>
  <span class="pl-c1">lmul!</span>(<span class="pl-k">::</span><span class="pl-c1">Diagonal</span>, <span class="pl-k">::</span><span class="pl-c1">AbstractVecOrMat{T}</span> <span class="pl-k">where</span> T) at <span class="pl-k">/</span>usr<span class="pl-k">/</span><span class="pl-k">local</span><span class="pl-k">/</span>src<span class="pl-k">/</span>julia<span class="pl-k">/</span>julia<span class="pl-k">-</span>master<span class="pl-k">/</span>usr<span class="pl-k">/</span>share<span class="pl-k">/</span>julia<span class="pl-k">/</span>stdlib<span class="pl-k">/</span>v1.<span class="pl-c1">6</span><span class="pl-k">/</span>LinearAlgebra<span class="pl-k">/</span>src<span class="pl-k">/</span>d
iagonal<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">210</span>
  <span class="pl-c1">lmul!</span>(<span class="pl-k">::</span><span class="pl-c1">UniformScaling</span>, <span class="pl-k">::</span><span class="pl-c1">AbstractVecOrMat{T}</span> <span class="pl-k">where</span> T) at <span class="pl-k">/</span>usr<span class="pl-k">/</span><span class="pl-k">local</span><span class="pl-k">/</span>src<span class="pl-k">/</span>julia<span class="pl-k">/</span>julia<span class="pl-k">-</span>master<span class="pl-k">/</span>usr<span class="pl-k">/</span>share<span class="pl-k">/</span>julia<span class="pl-k">/</span>stdlib<span class="pl-k">/</span>v1.<span class="pl-c1">6</span><span class="pl-k">/</span>LinearAlgebra
<span class="pl-k">/</span>src<span class="pl-k">/</span>uniformscaling<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">286</span>
  <span class="pl-k">...</span>
Stacktrace<span class="pl-k">:</span>
 [<span class="pl-c1">1</span>] <span class="pl-c1">mul!</span>(C<span class="pl-k">::</span><span class="pl-c1">LowerTriangular{Float64, Matrix{Float64}}</span>, A<span class="pl-k">::</span><span class="pl-c1">LowerTriangular{Float64, Matrix{Float64}}</span>, B<span class="pl-k">::</span><span class="pl-c1">LowerTriangular</span>{Float64, Matri
x{Float64}})
   @ LinearAlgebra <span class="pl-k">/</span>usr<span class="pl-k">/</span><span class="pl-k">local</span><span class="pl-k">/</span>src<span class="pl-k">/</span>julia<span class="pl-k">/</span>julia<span class="pl-k">-</span>master<span class="pl-k">/</span>usr<span class="pl-k">/</span>share<span class="pl-k">/</span>julia<span class="pl-k">/</span>stdlib<span class="pl-k">/</span>v1.<span class="pl-c1">6</span><span class="pl-k">/</span>LinearAlgebra<span class="pl-k">/</span>src<span class="pl-k">/</span>triangular<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">700</span>
 [<span class="pl-c1">2</span>] top<span class="pl-k">-</span>level scope
   @ REPL[<span class="pl-c1">5</span>]<span class="pl-k">:</span><span class="pl-c1">1</span></pre></div>
<p dir="auto">If i make it store in a normal matrix it is fine</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; mul!(collect(Z), X,  Y)
10×10 Matrix{Float64}:
 0.476498  0.0       0.0        0.0       0.0       0.0       0.0       0.0       0.0       0.0
 0.480309  0.159117  0.0        0.0       0.0       0.0       0.0       0.0       0.0       0.0
 1.38858   0.480959  0.0549959  0.0       0.0       0.0       0.0       0.0       0.0       0.0
..."><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">mul!</span>(<span class="pl-c1">collect</span>(Z), X,  Y)
<span class="pl-c1">10</span><span class="pl-k">×</span><span class="pl-c1">10</span> Matrix{Float64}<span class="pl-k">:</span>
 <span class="pl-c1">0.476498</span>  <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>        <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>
 <span class="pl-c1">0.480309</span>  <span class="pl-c1">0.159117</span>  <span class="pl-c1">0.0</span>        <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>
 <span class="pl-c1">1.38858</span>   <span class="pl-c1">0.480959</span>  <span class="pl-c1">0.0549959</span>  <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>       <span class="pl-c1">0.0</span>
<span class="pl-k">...</span></pre></div>
<p dir="auto">I guess the reasonable thing to do is to define it to operate on the parent of the destination then rewrap it?</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="using LinearAlgebra
M1 = UpperTriangular(rand(100,100))
Mr = similar(M1)
mul!(Mr,M1,M1) # Doesn't work

Mr2 = zeros(100,100)
mul!(Mr2,M1,M1) #Does work"><pre class="notranslate"><code class="notranslate">using LinearAlgebra
M1 = UpperTriangular(rand(100,100))
Mr = similar(M1)
mul!(Mr,M1,M1) # Doesn't work

Mr2 = zeros(100,100)
mul!(Mr2,M1,M1) #Does work
</code></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Julia Version 1.4.2
Commit 44fa15b150* (2020-05-23 18:35 UTC)
Platform Info:
  OS: Linux (x86_64-redhat-linux)
  CPU: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-8.0.1 (ORCJIT, skylake)
Environment:
  JULIA_NUM_THREADS = 4"><pre class="notranslate"><code class="notranslate">Julia Version 1.4.2
Commit 44fa15b150* (2020-05-23 18:35 UTC)
Platform Info:
  OS: Linux (x86_64-redhat-linux)
  CPU: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-8.0.1 (ORCJIT, skylake)
Environment:
  JULIA_NUM_THREADS = 4
</code></pre></div>