Strange behaviour when copying into an element of a vector of matrices

The following is a statement within a for loop of a function, where I have an array of matrices Zd with three 1x1 matrix elements all equal to [1.0] and I would like to modify Zd[2] using the following command (exact copy as used in the code)

Zd[k+1] .= view(qz, m+1:2m, 1:m)

where k = 1, m = 1 and qz = [-0.707; 0.707;;] . I expected to obtain
Zd = [[1.],[0.707],[1.]], but I obtained Zd = [[0.707],[0.707],[0.707]].

However, if I change the above statement to
Zd[k+1] = view(qz, m+1:2m, 1:m)
the result is correct. I was not able to reproduce this behaviour in REPL.

I hope somebody has an idea what is the issue here. If necessary, I can indicate exacly which is the function in question.

Sounds like your entries of Zd all refer to the same Matrix. When you use Zd[2] .= ... you are altering this Matrix, affecting also Zd[1] (as this is the same Matrix as Zd[2]). When you use Zd[2] = ... you are assigning a new, separate Matrix to this position.

E.g.

julia> Zd = fill([1.;;], 3)
3-element Vector{Matrix{Float64}}:
 [1.0;;]
 [1.0;;]
 [1.0;;]

julia> Zd[1] === Zd[2]  # (Not just ==)
true

julia> Zd[2] .= [5.;;]
1×1 Matrix{Float64}:
 5.0

julia> Zd
3-element Vector{Matrix{Float64}}:
 [5.0;;]
 [5.0;;]
 [5.0;;]

julia>  Zd[2] = [-1;;]
1×1 Matrix{Int64}:
 -1

julia> Zd
3-element Vector{Matrix{Float64}}:
 [5.0;;]
 [-1.0;;]
 [5.0;;]
2 Likes

Thanks for the nice simple example. The question still remains for me: why are all elements (i.e., matrices) affected ? Is this possibly a compilation error ?

Because it is only one single matrix, referred to in three different places, not three distinct matrices.

And, BTW, this is expected behavior.

1 Like

Perhaps it would be clearer as follows:

julia> matrix = [1.;;]
1×1 Matrix{Float64}:
 1.0

julia> Zd = [matrix, matrix, matrix]
3-element Vector{Matrix{Float64}}:
 [1.0;;]
 [1.0;;]
 [1.0;;]

julia> matrix .= 2
1×1 Matrix{Float64}:
 2.0

julia> Zd  # Still Zd[i] === matrix for all i
3-element Vector{Matrix{Float64}}:
 [2.0;;]
 [2.0;;]
 [2.0;;]

In the example in my previous post, if I wanted the entries of Zd to be equal but not identical, I could have used Zd = [[1.;;] for _ = 1:3] (see also the documentation of fill).

3 Likes