# Checking strided array storage order

**URL:** <https://discourse.julialang.org/t/checking-strided-array-storage-order/128685>\
**Category:** General Usage\
**Tags:** array, column-major, row-major, strided-array, array-storage-order\
**Created:** [May 4, 2025, 11:17am UTC](https://discourse.julialang.org/t/checking-strided-array-storage-order/128685 "2025-05-04T11:17:05Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![stemann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stemann/32/4030_2.png) [@stemann](https://discourse.julialang.org/u/stemann)\
**Post date:** [May 4, 2025, 11:17am UTC](https://discourse.julialang.org/t/checking-strided-array-storage-order/128685/1 "2025-05-04T11:17:05Z")

</div>

Is

```julia
strides(array) == Base.size_to_strides(1, size(array)...)

```

a sane way to check if a strided array is in column-major (alias co-lexicographic, alias Fortran, alias Julia) order, storage-wise?

Cf. [julia/base/abstractarray.jl at v1.11.5 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/v1.11.5/base/abstractarray.jl#L606-L608)

If so, the following might be useful here and there (and perhaps in `Base`):

```julia
@enum ArrayStorageOrder begin
    ArrayStorageOrderColumn
    ArrayStorageOrderRow
end

size_to_strides_column(sz::Dims) = Base.size_to_strides(1, sz...)

size_to_strides_row(sz::Dims) = reverse(Base.size_to_strides(1, reverse(sz)...))

"""
    storage_order(a::AbstractArray; preferred_order::ArrayStorageOrder = ArrayStorageOrderColumn)

Returns the storage order of `a`, or `preferred_order` if `a` is a scalar or vector.
"""
function storage_order(
    a::AbstractArray{T, N}; preferred_order::ArrayStorageOrder = ArrayStorageOrderColumn
) where {T, N}
    if N < 2
        return preferred_order
    end

    if strides(a) == size_to_strides_column(size(a))
        return ArrayStorageOrderColumn
    elseif strides(a) == size_to_strides_row(size(a))
        return ArrayStorageOrderRow
    else
        throw(
            ArgumentError("Unexpected strides $(strides(a)) for array of size $(size(a))")
        )
    end
end

```

Related topic: [Should `reshape` have an option for row-major order?](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929)

---

<div class="post-metadata">

**Author:** ![stemann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stemann/32/4030_2.png) [@stemann](https://discourse.julialang.org/u/stemann)\
**Post date:** [May 4, 2025, 11:18am UTC](https://discourse.julialang.org/t/checking-strided-array-storage-order/128685/2 "2025-05-04T11:18:08Z")

</div>

For convenience, here’s a row-major strided array for testing purposes:

```julia
struct RowMajorArray{T, N} <: AbstractArray{T, N}
    array::Array{T, N}
    function RowMajorArray(array::Array{T, N}) where {T, N}
        a = permutedims(array, ndims(array):-1:1)
        return new{T, N}(a)
    end
end

RowMajorArray(array::AbstractArray{T, N}) where {T, N} = RowMajorArray{T, N}(array)

Base.size(array::RowMajorArray) = reverse(size(array.array))

Base.IndexStyle(::Type{<:RowMajorArray}) = IndexCartesian()

function Base.getindex(array::RowMajorArray, i::Vararg{Int, N}) where {N}
    return getindex(array.array, reverse(i)...)
end

Base.strides(array::RowMajorArray) = reverse(strides(array.array))

function Base.unsafe_convert(::Type{Ptr{T}}, array::RowMajorArray{T, N}) where {T, N}
    return unsafe_convert(Ptr{T}, array.array)
end

Base.elsize(array::RowMajorArray) = Base.elsize(array.array)

```

Where the `Base` functions has the following behaviour:

```julia-repl
julia> a_column = collect(reshape(1:24, (4,3,2)))
4×3×2 Array{Int64, 3}:
[:, :, 1] =
 1 5 9
 2 6 10
 3 7 11
 4 8 12

[:, :, 2] =
 13 17 21
 14 18 22
 15 19 23
 16 20 24

julia> a_row = RowMajorArray(a_column)
4×3×2 RowMajorArray{Int64, 3}:
[:, :, 1] =
 1 5 9
 2 6 10
 3 7 11
 4 8 12

[:, :, 2] =
 13 17 21
 14 18 22
 15 19 23
 16 20 24

julia> strides(a_column)
(1, 4, 12)

julia> strides(a_row)
(6, 2, 1)

julia> sz = size(a_column)
(4, 3, 2)

julia> Base.size_to_strides(1, sz...)
(1, 4, 12)

julia> reverse(Base.size_to_strides(1, reverse(sz)...))
(6, 2, 1)

```
