Hey,
recently I wanted to reverse a multidimensional array. I didn’t find a built-in solution but only this post on StackOverflow.
I was wondering what’s a proper implementation. I came up with the following. reverse_2
is the the one from SO, but it’s horribly slow because it is copying everything for each reverse call again.
reverse_all
and reverse_all_view
are basically the same, except the @view
.
function reverse_all(arr::AbstractArray, dims=1:ndims(arr))
return arr[reverse_all_indices(arr, dims)...]
end
function reverse_all_view(arr::AbstractArray, dims=1:ndims(arr))
return @view arr[reverse_all_indices(arr, dims)...]
end
function reverse_all_indices(arr, dims=1:ndims(arr))
out = []
for i in 1:ndims(arr)
push!(out, 1:size(arr)[i])
end
for d in dims
out[d] = size(arr)[d]:-1:1
end
return out
end
function reverse_2(arr)
for d = 1:ndims(arr)
arr = reverse(arr, dims=d)
end
return arr
end
I often find myself writing code to construct the range expressions. Is there a better way? I’m aware of CartesianIndices
but often I don’t find them easier.
julia> x = randn((1000, 12, 122, 140));
julia> @time y = reverse_all(x);
0.988784 seconds (14 allocations: 1.527 GiB, 0.67% gc time)
julia> @time y_v = reverse_all_view(x);
0.000014 seconds (12 allocations: 528 bytes)
julia> @time y_2 = reverse_2(x);
32.074907 seconds (817.91 M allocations: 18.302 GiB, 7.29% gc time)
julia> y == y_2 == y_v
true
Thanks,
Felix