SciML/RecursiveArrayTools.jl

`reshape` with `Colon` fails on `VectorOfArray`

sethaxen opened this issue · 5 comments

reshape with any Colon dim appears to not work at all for VectorOfArray:

If the internal array is a vector, it appears to hit a dead branch:

julia> using RecursiveArrayTools

julia> x = VectorOfArray([randn(2) for _ in 1:4]);

julia> reshape(x, 2, :)
ERROR: UndefVarError: `_throw_dmrs` not defined
Stacktrace:
 [1] _reshape(parent::VectorOfArray{Float64, 2, Vector{Vector{Float64}}}, dims::Tuple{Int64, Int64})
   @ RecursiveArrayTools ~/.julia/packages/RecursiveArrayTools/w8ctF/src/vector_of_array.jl:397
 [2] reshape
   @ ./reshapedarray.jl:112 [inlined]
 [3] reshape
   @ ./reshapedarray.jl:119 [inlined]
 [4] reshape(::VectorOfArray{Float64, 2, Vector{Vector{Float64}}}, ::Int64, ::Colon)
   @ Base ./reshapedarray.jl:118
 [5] top-level scope
   @ REPL[5]:1

If the internal array is a matrix, then length of the array seems to incorrectly be given as the length of the vector of arrays, so the size corresponding to the colon dimension is incorrectly computed:

julia> x = VectorOfArray([randn(2, 3) for _ in 1:4]);

julia> reshape(x, 2, 3, :)
ERROR: DimensionMismatch: array size 4 must be divisible by the product of the new dimensions (2, 3, Colon())
Stacktrace:
 [1] (::Base.var"#throw2#320")(A::VectorOfArray{Float64, 3, Vector{Matrix{Float64}}}, dims::Tuple{Int64, Int64, Colon})
   @ Base ./reshapedarray.jl:123
 [2] _reshape_uncolon
   @ ./reshapedarray.jl:129 [inlined]
 [3] reshape(parent::VectorOfArray{Float64, 3, Vector{Matrix{Float64}}}, dims::Tuple{Int64, Int64, Colon})
   @ Base ./reshapedarray.jl:119
 [4] reshape(::VectorOfArray{Float64, 3, Vector{Matrix{Float64}}}, ::Int64, ::Int64, ::Vararg{Union{Colon, Int64}})
   @ Base ./reshapedarray.jl:118
 [5] top-level scope
   @ REPL[7]:1

Environment

julia> versioninfo()
Julia Version 1.9.2
Commit e4ee485e909 (2023-07-05 09:39 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, tigerlake)
  Threads: 8 on 8 virtual cores
Environment:
  JULIA_CMDSTAN_HOME = /home/sethaxen/software/cmdstan/2.30.1/
  JULIA_NUM_THREADS = auto
  JULIA_EDITOR = code

(jl_s8zJAU) pkg> st
Status `/tmp/jl_s8zJAU/Project.toml`
  [731186ca] RecursiveArrayTools v2.38.7
visr commented

The UndefVarError is fixed in #272, but that doesn't fix this issue, which I also ran into. Now your first example gives:

x = VectorOfArray([randn(2) for _ in 1:4]);
reshape(x, :)
# -> DimensionMismatch: parent has 8 elements, which is incompatible with size (4,)

This is related to the somewhat odd situation that length(x) == 4 and size(x) == (2,4), i.e. it seems to behave like both a vector and a matrix, but x isa AbstractMatrix.

The function vec according to the Base docs should return the same underlying data, but vec(x) creates a copy.

For my 1D example I could use reshape(x, prod(size(x))) as a workaround.

it seems to behave like both a vector and a matrix, but x isa AbstractMatrix.

For me this is a deal-breaker. I want one or the other. It's easy for me to create a vector of vectors, but I explicitly want to use this type to treat those as an AbstractMatrix.

yeah and that would be changed if someone has a good way to do it.

This works now. I think the issue can be closed?

Indeed, reshape(::VectorOfArray, ::Any...) was redefined in #290, and this now works.