0

This has some relation to this question:

I am trying to get a slice/subarray of an N-dimensional array. The slices are, by construction, vectors of known length, but for the sake of generality let's supposed they are some arrays of lower rank M<N, whose dimensions are known a-priori. I want to operate on these slices (as arguments) for functions that takes Array of rank M or a Vec, rather than an Array with a bunch of singelton dimensions (so Vec and not Array{N} with dimensions (n,1,1,1,1...)).

For example I would like to have view(A,indx...) return a reference (SubArray?) with rank 1 and size (n,) and not rank M with (n,1,1,1,...). I understand that view naturally keeps the type of A to be type-stable, but I really do not want to make the functions work on arguments of size (n,1,1,1,...)... And of course, defining an array of the correct size and going through the setindex! path is almost certain slower.

Any suggestions / ideas / wisdom?

1 Answer 1

1

view already returns a SubArray with the right size, without extraneous dimensions:

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

[:, :, 2] =
 10  13  16
 11  14  17
 12  15  18

[:, :, 3] =
 19  22  25
 20  23  26
 21  24  27

julia> a = @view M[2:3, 2:3, 2]
2×2 view(::Array{Int64, 3}, 2:3, 2:3, 2) with eltype Int64:
 14  17
 15  18

julia> size(a)
(2, 2)

julia> a = @view M[2:3, 2, 2]
2-element view(::Array{Int64, 3}, 2:3, 2, 2) with eltype Int64:
 14
 15

julia> size(a)
(2,)

However, note that a SubArray is not an Array i.e. if you wrote a function to accept only Array{Int, 2} arguments, it won't accept SubArray{Int, 2 ...} as passed-in values.

Instead of being overly specific with argument types in this way, it's better to accept any AbstractArray, write your code in a generic way (eg. using eachindex, etc.), and explicitly check the dimensions or size with ndims or size within the function body if necessary.

Sign up to request clarification or add additional context in comments.

7 Comments

Maybe I have failed to explain myself properly: if I use A=rand(3,3,2) I get a 3×3×2 Array{Float64, 3}. Taking B=view(A,:,1,1) will indeed produce size(B) (3,), however it will be a SubArray of ::Array{Float64, 3} . While this is not a problem per-se, I need a mechanism that ensures that this will be dispatched to a function that operates on "1D" vectors and not an N-dimensional array.
What do you mean by "a function that operates on "1D" vectors"? How are you defining this function?
I'm using func(othervar::<irrelevant to our dicussion>, var::Base.AbstractVecOrTuple{<:Number}) = <operation> for when it only has 1 dimension of non-singelton indices. And it is important since if it were a 2 or more non-singelton indices, the operation in the function needs to be different (and therefore the dispatch)
That should work fine. B is a SubArray{Float64, 1} which is a subtype of AbstractVector, so that dispatch should work fine for this. The size of the parent array doesn't matter for the purpose of this dispatch.
the reason it didn't work is eventhough the view produced a "1-dimensional" size=(n,) entity, the type was still defined as ::SubArray{Float64, 3,...) which is not a subtype of Base.AbstractVecOrTuple (while ::SubArray{Float64, 1,...) is)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.