diff --git a/src/functions.jl b/src/functions.jl index 772d522..a1cbc11 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -578,30 +578,28 @@ end Converts the linear indices in `ind`, for a matrix/array with size `siz`, to the equivalent subscript indices. """ -function ind2sub(siz,ind) - - numDim = length(siz) - k = cumprod([siz[i] for i ∈ eachindex(siz)],dims=1) - m = prod(siz) - - if any(ind.>m) || any(ind.<1) - error("Encountered index value of out of valid range 1:$m") - end - - if length(ind)>1 - A = [ind2sub_(ind_i,numDim,k) for ind_i ∈ ind] - else - A = ind2sub_(ind,numDim,k) +function ind2sub(siz::Union{Tuple{Vararg{Int64, N}}, Vector{Int64}},ind::Union{Tuple{Vararg{Int64, M}}, Vector{Int64}}) where N where M + if !isempty(ind) # Not empty so subscript indices will be derived + numDim = length(siz) # Number of dimensions from length of size + k = cumprod(siz) # Cumulative product of size + m = prod(siz) # Number of elements + if any(ind.>m) || any(ind.<1) + error("Encountered index value of out of valid range 1:$m") + end + if length(ind)>1 # Multiple indices so loop over them + A = [ind2sub_(ind_i,numDim,k) for ind_i ∈ ind] + else # Just one so + A = ind2sub_(ind,numDim,k) + end + else # Empty so return an empty vector + A = Vector{Int64}[] end - return A end # ind2sub helper function to parse just a single linear index and produce a single subscript index set -function ind2sub_(ind,numDim,k) - +function ind2sub_(ind::Integer,numDim::Int64,k::Union{Int64,Vector{Int64},Tuple{Vararg{Int64, N}}}) where N a = Vector{Int64}(undef,numDim) # Initialise a - for q ∈ numDim:-1:1 # For all dimensions if isone(q) # First 1st dimension a[1] = rem(ind-1,k[1]) + 1 @@ -610,12 +608,10 @@ function ind2sub_(ind,numDim,k) a[q] = (ind - p)./k[q-1] + 1 # Current ind = p # Set indices as "previous" end - end - + end return a end - """ sub2ind(siz,A) diff --git a/test/runtests.jl b/test/runtests.jl index 2322171..4586b6f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -20,6 +20,37 @@ using Test, Comodo, Comodo.GeometryBasics IJK_C = ind2sub(size(C),ind) @test all([C[ind[i]] == C[IJK_C[i][1],IJK_C[i][2],IJK_C[i][3]] for i ∈ eachindex(ind)]) end + + @testset "Vector specifying size" begin + C = rand(3,5,2) + IJK_C = ind2sub(collect(size(C)),ind) + @test all([C[ind[i]] == C[IJK_C[i][1],IJK_C[i][2],IJK_C[i][3]] for i ∈ eachindex(ind)]) + end + + @testset "Tuple specifying indices" begin + C = rand(3,5,2) + ind_tuple = Tuple(ind[i] for i ∈ eachindex(ind)) + IJK_C = ind2sub(collect(size(C)),ind_tuple) + @test all([C[ind_tuple[i]] == C[IJK_C[i][1],IJK_C[i][2],IJK_C[i][3]] for i ∈ eachindex(ind_tuple)]) + end +end + +@testset "ind2sub_" verbose = true begin + ind = 6 + @testset "1D i.e. Vector" begin + A = rand(30) + @test Comodo.ind2sub_(6,length(size(A)),cumprod(size(A))) == [6] + end + + @testset "2D i.e. 2D Matrix" begin + B = rand(5,6) + @test Comodo.ind2sub_(6,length(size(B)),cumprod(size(B))) == [1,2] + end + + @testset "3D i.e. 3D matrix" begin + C = rand(3,5,2) + @test Comodo.ind2sub_(6,length(size(C)),cumprod(size(C))) == [3,2,1] + end end @testset "elements2indices" verbose = true begin