Week 5 · Lesson 2
Reshape and permute
Both ops rearrange a tensor without computing anything. reshape keeps every number in its place and changes how you count. permute keeps the numbers and changes which axis is which. They look alike, and the difference is the most common shape bug there is.
reshape reinterprets the same sequence
reshape %x shape=[d0 d1 ...] reads the elements of x in row-major order and lays them out again, row-major, in the new shape. The element counts must match: 12 can become [3 4], [2 2 3] or [12 1], never [5 3]. A shape of [] turns a one-element value into a scalar.
Nothing moves. If the buffer holds 0..11, the number 9 is the tenth element in every view, wherever the new shape puts its row and column.
permute reorders axes
permute %x order=[p0 p1 ...] makes a new tensor whose axis k is x's axis p_k. The new shape is shape[p_k] for each k, and the element at output index i is x at the index whose axis p_k holds i_k.
For a matrix there's one interesting order, [1 0]: the transpose. Element [i][j] of the result is x[j][i]. For rank 3 there are six orders. With order=[2 0 1], a (2, 3, 4) tensor becomes (4, 2, 3), and output [1][0][2] reads x[0][2][1]: output axis 0 carries its index to source axis 2, axis 1 to source axis 0, axis 2 to source axis 1.
The order must be a permutation of 0..r-1. order=[0 0] is invalid.
Transpose a 3x4 matrix
Slot 0 holds a 3x4 f32 matrix, row-major. Store its 4x3 transpose into slot 1, row-major. The starter reshapes to [4 3], which is not a transpose.
Permuted shape and source index
Write permute_shape shape order, the shape of permute x order=..., and src_index order idx, the index into x that output index idx reads.
Order of operations matters
Take [[0 1 2] [3 4 5]], shape (2, 3). Transpose it and flatten: the result reads down the columns, 0 3 1 4 2 5. Reshape it to [3 2] instead and flatten: 0 1 2 3 4 5, the original order, because reshape never moves anything. Both intermediate results have shape (3, 2), and only one of them is a transpose.
Reshaping a (3, 4) to (4, 3) gives the right shape with the wrong contents. They agree only when a dimension is 1, or for special data: constant values, symmetric square matrices, or values that differ only at the first and last positions (those stay put under both). That's why a transpose test with constant data passes for any wrong answer: test with distinct values everywhere.
Check yourself
A buffer holds 0..11. After reshape shape=[3 4], what is element [2][1]?
Rows of 4: row 2 starts at element 8.
4·2 + 1 = 9, and the buffer holds its own positions, so the value is 9.
Same buffer, reshaped to [3 4], then permute order=[1 0]. What is element [1][2] of the result?
The transpose's [i][j] is the original's [j][i].
It reads [2][1] of the 3x4, which is 9.
[[0 1 2] [3 4 5]] is transposed with permute order=[1 0] and flattened with reshape shape=[6]. What is the second element of the result?
The transpose's first row is the original's first column.
The transpose is [[0 3] [1 4] [2 5]], which flattens to 0 3 1 4 2 5. The second element is 3.
What shape is permute %t order=[2 0 1] for %t of shape (2, 3, 4)?
Output axis k has the size of input axis p_k.
(shape[2], shape[0], shape[1]) = (4, 2, 3).
Is permute %m order=[0 0] valid for a (2, 3) %m?
Where would axis 1 go?
Every axis must appear exactly once. [0 0] drops axis 1 and repeats axis 0, so the oracle rejects it.
0..5 is reshaped to [3 2] and then back to [6]. What do you get?
Does reshape ever change the order of the elements?
Never. Both reshapes keep row-major order, so the round trip is the identity.