I want to use a number to represent a multi-index. Consider i in 1:3 and j in 1:3. I want 3 to represent for (0,3), 4 for (1,1), 8 for (3,2) and so forth.
This can be done by i = (num-1)÷3 + 1 and j = (num-1)%3 + 1. This seems not quite elegant. Is there a better way to do this job? This is the first time I think 0-based indexing is superior…
Note that the i = (num-1)÷3 + 1 and j = (num-1)%3 + 1 formula you gave is row-major but Julia is column-major. If you really care about this you can just reverse the index order or transpose the array.
You can get both the (i,j) -> n and n -> (i,j) maps without allocation (as array-like objects that compute elements on the fly) using LinearIndices and CartesianIndices, respectively:
julia> C = CartesianIndices((3, 3)) # indices of a 3x3 array
CartesianIndices((3, 3))
julia> collect(C) # collect and display all the elements explicitly
3×3 Matrix{CartesianIndex{2}}:
CartesianIndex(1, 1) CartesianIndex(1, 2) CartesianIndex(1, 3)
CartesianIndex(2, 1) CartesianIndex(2, 2) CartesianIndex(2, 3)
CartesianIndex(3, 1) CartesianIndex(3, 2) CartesianIndex(3, 3)
julia> C[3], C[4], C[8]
(CartesianIndex(3, 1), CartesianIndex(1, 2), CartesianIndex(2, 3))
julia> L = LinearIndices(C) # alternatively: L = LinearIndices((3, 3))
3×3 LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}:
1 4 7
2 5 8
3 6 9
julia> L[3,1], L[1,2], L[2,3]
(3, 4, 8)
Thanks for your answer. I know julia has linear indexing for multidimensional arrays, but I’m working on a custom type.
The trick using an index matrix is interesting, but the size of my type is not fixed. That means I need to generate a new matrix when the sized is changed. I will think about how to deal with this.
CartesianIndices and LinearIndicesaren’t “index matrices” and they don’t need to be “generated” — creating them is essentially free, because they really just store the size of the array: