# Should \`reshape\` have an option for row-major order?

**URL:** <https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929>\
**Category:** Internals & Design\
**Tags:** proposal, column-major\
**Created:** [November 7, 2017, 7:17am UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929 "2017-11-07T07:17:08Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![tparker](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tparker](https://discourse.julialang.org/u/tparker)\
**Post date:** [November 7, 2017, 7:17am UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/1 "2017-11-07T07:17:08Z")

</div>

Currently `reshape` can only rearrange the raw linearly ordered data into Julia’s default column-major order (or colexicographical order, for higher-dimensional arrays). Would it be worth adding an optional keyword argument that reshapes the data in row major (or generally lexicographical) order? This would be convenient e.g. for interfacing with data generated by or for other programming languages that use the row-major convention (e.g. [here](https://discourse.julialang.org/t/converting-python-numpy-program-to-julia/4679)). It’s fairly easy to reshape an array into an n \times m row-major matrix by reshaping it into an m \times n column-major matrix and then taking the transpose, but this gets cumbersome for higher-dimensional arrays.

(Note that I’m only suggesting changing the visible behavior of `reshape`, not the way that the resulting array is stored internally.)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 7, 2017, 7:32am UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/2 "2017-11-07T07:32:55Z")

</div>

`permutedims`?

---

<div class="post-metadata">

**Author:** ![tparker](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tparker](https://discourse.julialang.org/u/tparker)\
**Post date:** [November 7, 2017, 7:43am UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/3 "2017-11-07T07:43:43Z")

</div>

Okay, fair, I guess `permutedims(reshape(A, p, o, n, m), [4, 3, 2, 1])` isn’t that much more cumbersome than `reshape(A, m, n, o, p, ordering = rowmajor)` would be. Maybe my suggestion isn’t necessary.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 7, 2017, 9:47am UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/4 "2017-11-07T09:47:53Z")

</div>

I think it is still a valid point. Although `permutedims(reshape(A, p, o, n, m), [4, 3, 2, 1])` is nice, it is conceptually different from the `order="row"` version in that one still has to “think” for a second.

I would, besides `order="row"` and `order="col"`, even suggest to follow [numpy’s example](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.reshape.html) and add something like `order="C"` and `order="F"` or `order="Fortran"` etc. for most common languages. I found those options really convenient.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 7, 2017, 10:17am UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/5 "2017-11-07T10:17:22Z")

</div>

> [@tparker](#):
>
> Currently `reshape` can only rearrange the raw linearly ordered data

The key about `reshape` is that it does not _rearrange_ the data, it just presents it differently. It even shares structure:

```julia
julia> A = ones(4)
4-element Array{Float64,1}:
 1.0
 1.0
 1.0
 1.0

julia> B = reshape(A, 2, :)
2×2 Array{Float64,2}:
 1.0 1.0
 1.0 1.0

julia> B[2,2] = 3.0
3.0

julia> A
4-element Array{Float64,1}:
 1.0
 1.0
 1.0
 3.0

```

What you are asking for is a useful operation (especially if interfacing with languages that use row-major), but it may be better to give it a different name.

---

<div class="post-metadata">

**Author:** ![tparker](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tparker](https://discourse.julialang.org/u/tparker)\
**Post date:** [November 7, 2017, 4:01pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/6 "2017-11-07T16:01:18Z")

</div>

I agree that “rearrange the data” was a poor choice of works in my OP. But couldn’t the current implementation of `reshape` and my proposed “row-major reshape” simply be two different ways to “present the data differently”? I don’t see why they are conceptually different enough to require two different names.

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [November 7, 2017, 4:18pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/7 "2017-11-07T16:18:20Z")

</div>

As @Tamas_Papp showed, currently `reshape` always returns a view on the same data. The behavior you request (changing to row-major order) requires allocating a new copy. This is a significant change which deserves a separate function IMHO.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 7, 2017, 4:21pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/8 "2017-11-07T16:21:29Z")

</div>

> [@tparker](#):
>
> my proposed “row-major reshape” simply be two different ways to “present the data differently”?

Not efficiently, no. In principle a “view” could be created for permuted dimensions, but it is vastly more complicated than a reshape.

---

<div class="post-metadata">

**Author:** ![tparker](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tparker](https://discourse.julialang.org/u/tparker)\
**Post date:** [November 7, 2017, 5:49pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/9 "2017-11-07T17:49:39Z")

</div>

You can’t change to row-major order just by changing the array strides? For example, if your raw data has six elements, then (schematically) setting `rowstride = 1, columnstride = 3` gives a column-major 3x2 matrix, `rowstride = 1, columnstride = 2` gives a column-major 2x3 matrix, `rowstride = 2, columnstride = 1` gives a row-major 3x2 matrix, and `rowstride = 1, columnstride = 3` gives a row-major 2x3 matrix.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 7, 2017, 6:25pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/10 "2017-11-07T18:25:54Z")

</div>

`reshape` also preserves linear indexing, ie

```julia
reshape(A, ...)[i] == A[i]

```

for all `i` in `1:length(A)`.

Again, what you are asking for is a perfectly reasonable feature, but you should call it something else.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 7, 2017, 6:34pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/11 "2017-11-07T18:34:03Z")

</div>

numpy:

> This will be a new view object if possible; otherwise, it will be a copy. Note there is no guarantee of the memory layout (C- or Fortran- contiguous) of the returned array.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [November 7, 2017, 6:42pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/12 "2017-11-07T18:42:10Z")

</div>

`PermutedDimsArray` does create a view; `permutedims` is the “eager” version which creates a copy.

@carstenbauer, Julia developers have tended to view “it might be A or it might be B depending on circumstance” as less than desirable; for example if you call those functions and then set elements in the resulting array, what will happen? Consequently among Julia devs there has been a drive to be 100% predictable, and it’s currently viewed as a bug when it’s not.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 7, 2017, 6:45pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/13 "2017-11-07T18:45:35Z")

</div>

@tim.holy Yes, I know and couldn’t agree more. I like this viewpoint very much. I was more citing this for completeness. I looked it up because I was curious how numpy handles this issue.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 8, 2017, 6:03pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/14 "2017-11-08T18:03:17Z")

</div>

So, we could either do something similar to this

`change_major_order(X::AbstractArray, sizes...=size(X)...) = permutedims(reshape(X, sizes...), length(sizes):-1:1)`

which performs the multidimensional transpose (as proposed above), or go with functions like `row_major(X, sizes...)`, `col_major(X, sizes...)` which always brings X into row/column-major order.

In any case, we should certainly mention in the doc that none of this changes the actual structure in memory.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 8, 2017, 6:21pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/15 "2017-11-08T18:21:18Z")

</div>

> [@carstenbauer](#):
>
> `permutedims(reshape(X, sizes...), length(sizes):-1:1)` […] none of this changes the actual structure in memory.

I am not sure what you mean here. `permutedims` **does** rearrange the elements (of the copy). To see this, call `vec` on the result.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 8, 2017, 6:34pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/16 "2017-11-08T18:34:13Z")

</div>

Sorry, what I meant was that the final Array is always ~~row-major~~ column-major order in the sense that Julia always uses ~~row-major~~ column-order internally. If I switch to ~~column-major~~ row-major order by using `change_major_order` the Array will look/be like expected, what has been a row before is now a column, but internally I still have to iterate over ~~rows first~~ columns to be fast.

```julia
julia> A = rand(2,2)
2×2 Array{Float64,2}:
 0.48992 0.135993
 0.856454 0.625905

julia> A_row_order = change_major_order(A)
2×2 Array{Float64,2}:
 0.48992 0.856454
 0.135993 0.625905

julia> A_row_order[1] = 123
123

julia> A
2×2 Array{Float64,2}:
 0.48992 0.135993
 0.856454 0.625905

```

It does produce a copy but ~~A\_col\_order~~ A\_row\_order is still stored in column-major order. I am still fast if I iterate over ~~rows first~~ columns.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [November 8, 2017, 6:47pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/17 "2017-11-08T18:47:22Z")

</div>

> [@carstenbauer](#):
>
> Sorry, what I meant was that the final Array is always row-major order in the sense that Julia always uses row-major order internally

Actually, it’s the opposite, Julia is always column-major (Fortran) order internally.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 8, 2017, 6:51pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/18 "2017-11-08T18:51:39Z")

</div>

Argh, thanks, too much switching between orders. But my statement holds 🙂  
I update my post to not confuse anyone else.

---

<div class="post-metadata">

**Author:** ![tparker](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tparker](https://discourse.julialang.org/u/tparker)\
**Post date:** [November 8, 2017, 8:05pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/19 "2017-11-08T20:05:56Z")

</div>

@carstenbauer Sorry to nitpick, but for completeness you should edit post #16 to change both mentions of “iterate over rows” to “iterate over columns”. Also, note that your proposal in post #14 isn’t quite right; you need to reverse the desired sizes before the transpose so that they end up right after the transpose. So it would need to be something more like

```
change_major_order(X::AbstractArray, size...=size(X)...) = permutedims(reshape(X, reverse([size...])...), length(size):-1:1)

```

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 8, 2017, 8:20pm UTC](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929/20 "2017-11-08T20:20:42Z")

</div>

No need to be sorry, in fact, I should be sorry 🙂  
By “iterate over rows first” I was thinking of two for loops and the inner one should be the row index. But indeed, this is iterating columns. Changed it. Your second point is also right.

But, overlooking my incompetence, what about `change_major_order(X)` vs `row_major(X)` and `col_major(X)`?

[Next page](https://discourse.julialang.org/t/should-reshape-have-an-option-for-row-major-order/6929.md?page=2)
