Submatrix replacement error in a matrix


#1

In this below code there is a weird error message:

joja = [1 2 3; 4 5 6; 7 8 9] 
joja[2:3,2:3] =  [1 2; 3 4 ] # ok
joja2 = reshape(1:9,3,3) 
joja2[2:3,2:3] =  [1 2; 3 4 ] # error (reshaped array)
joja3 = copy(joja2)
joja3[2:3,2:3] =  [1 2; 3 4 ] # ok

I know that reshaped array is a different animal, but why it happens?


#2

Please report the exact error by copying and pasting an actual Julia session.


#3

Thanks for your feedback

The two lines that generates an error (in the middle) was

Julia >joja2 = reshape(1:9,3,3)
3×3 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}:
 1  4  7
 2  5  8
 3  6  9

Julia>joja2[2:3,2:3] =  [1 2; 3 4 ]
ERROR: indexed assignment fails for a reshaped range; consider calling collect
Stacktrace:
 [1] macro expansion at .\multidimensional.jl:558 [inlined]
 [2] macro expansion at .\cartesian.jl:64 [inlined]
 [3] macro expansion at .\multidimensional.jl:556 [inlined]
 [4] _unsafe_setindex!(::IndexLinear, ::Base.ReshapedArray{Int64,2,UnitRange{Int
64},Tuple{}}, ::Array{Int64,2}, ::UnitRange{Int64}, ::UnitRange{Int64}) at .\mul
tidimensional.jl:549
 [5] macro expansion at .\multidimensional.jl:541 [inlined]
 [6] _setindex! at .\multidimensional.jl:537 [inlined]
 [7] setindex!(::Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}, ::Array{I
nt64,2}, ::UnitRange{Int64}, ::UnitRange{Int64}) at .\abstractarray.jl:968

A simular approach it’s ok, but uses pure array instead reshaped array

Julia>joja = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

Julia>joja[2:3,2:3] =  [1 2; 3 4 ]
2×2 Array{Int64,2}:
 1  2
 3  4

#4

There is no setindex! for ranges. The error suggests you to collect it as a regular array first then assign values.


#5

@tomaklutfu, in that case is not a range, is a real array, because reshape function get a range and convert it to an array in any shape.

However, it’s a little bit different from a declared array in the second piece of code. It’s a reshaped array (ReshapedArray in the error message) so it generates an error, but it lacks logic!

Notice that there is no 3D ranges, but reshape function produces 3D arrays:

vet = reshape(1:24,2,3,4)
println(vet[1,2,3])   # shows 15.

#6

A reshaped range is not the same as a reshaped Array. Ranges (even reshaped ones) are read-only. This is intentional language behavior. As the previous response suggests, you can first convert the range to a Vector via a call to theVector constructor or to collect.


#7

@Stephen_Vavasis, you are right! This reshaped range is read-only. I’ve got it. copy() or collect() do the job. Thanks for your explanation.

It’s pretty amazing so much power in a programming language.

The below code works!

Vals = [30 60; 45 30]
Dest = collect(reshape(1.:9.,3,3))
Dest[2:3,2:3] = sind.(Vals) .* cosd.(Vals)

Before submatrix assignment:

Julia> Dest
3×3 Array{Float64,2}:
1.0 4.0 7.0
2.0 5.0 8.0
3.0 6.0 9.0

After:

Julia> Dest
3×3 Array{Float64,2}:
1.0 4.0 7.0
2.0 0.433013 0.433013
3.0 0.5 0.433013