

# `⍉` — Transpose / Reorder axes

Function. Keys: `Alt-o Backslash`. Ranks: `∞` monadic, `1 ∞` dyadic

`⍉Y` reverses axis order.

``` bpl
⍉2 3⍴⍳6            ⍝ [0 3⋄1 4⋄2 5]
```

In `A⍉Y`, each item of `A` is a number that gives the result axis for
the corresponding leading axis of `Y`. The axes of `Y` that `A` doesn’t
reach fill the unused result axes in order, as in BQN. Together, the
selected and filled axes run from 0 with no gaps. A key on an item names
its result axis. A name in place of a number gives DOMAIN ERROR. To
select axes by name, use `⍉⁻¹`.

``` bpl
1 0⍉2 3⍴⍳6         ⍝ [0 3⋄1 4⋄2 5]
⍴1⍉2 3 4⍴⍳24       ⍝ [3 2 4]ₓ
["rows":1 "cols":0]⍉2 3⍴⍳6
⍝ ["cols":3 "rows":2]⍴[0 3⋄1 4⋄2 5]
```

Repeated destinations select diagonals, taking the smallest
participating dimension. A diagonal keeps the keys and name that its
axes agree on, as mix does.

``` bpl
0 0⍉3 3⍴⍳9         ⍝ 0 4 8
⍴["i":0 0]⍉3 3⍴⍳9  ⍝ ["i":3]ₓ
```

A left argument of higher rank transposes `Y` once for each row, and
stacks the results.

``` bpl
[0 1⋄1 0]⍉2 3⍴⍳6     ⍝ [[0 1 2⋄3 4 5]⋄[0 3⋄1 4⋄2 5]]
```

## Split and route

A nested list splits one input axis. Each of its items is a
`[destination size]` pair, optionally keyed by the new axis’s name. One
size can be `∞`, which `⍉` infers. The sizes must multiply to exactly
the input axis’s length. Unlike `⍴`, a split never cycles or truncates
data.

``` bpl
x←2 3 8⍴⍳48
⍴[0 2 [1 2;3 ∞]]⍉x   ⍝ [2 2 3 4]ₓ
```

The last axis splits into sizes `2 4`, which go to result axes `1 3`.
This turns `batch tokens packed` into `batch heads tokens features`. A
key on an unsplit item names its result axis. Keys within a group name
the factors. A key on a group names the axis that the inverse merges.

``` bpl
x←["b":2 "t":3 "d":8]⍴⍳48
f←["b":0 "t":2 "d":["h":1 2;"f":3 ∞]]⍉
⍴f x                      ⍝ ["b":2 "h":2 "t":3 "f":4]ₓ
(f⁻¹f x)≡x                ⍝ $t
```

Keys only name axes. Item `i` still describes input axis `i`, whatever
its key.

## Inverse

`⍉⁻¹Y` is `⍉Y`. In `X⍉⁻¹Y`, `X` lists the source axes in output order,
as einops does. A numeric `X` reverses `X⍉`. A name in `X` selects that
axis of `Y`.

``` bpl
2 0 1⍉⁻¹2 0 1⍉2 3 4⍴⍳24   ⍝ 2 3 4⍴⍳24
⍴2⍉⁻¹2 3 4⍴⍳24            ⍝ [4 2 3]ₓ
x←["b":2 "h":3 "w":4]⍴⍳24
⍴["w" "b" "h"]⍉⁻¹x       ⍝ ["w":4 "b":2 "h":3]ₓ
```

A nested list merges the axes it selects, in that order. Its items can
also be `[source size]` pairs, as a split’s are. Each size must match
its axis’s length. A size of `∞` matches any length. The inverse of a
bound split reads its pairs this way.

``` bpl
x←2 3 8⍴⍳48
f←[0 2 [1 2;3 ∞]]⍉
(f⁻¹f x)≡x                 ⍝ $t
[0 2 [1 3]]⍉⁻¹f x          ⍝ 2 3 8⍴⍳48
```

Names let `⍉⁻¹` reorder and merge the factors of a split. For 16 by 16
image patches, split height and width into patch and pixel axes, then
merge them into one patch axis and one pixel axis:

``` bpl
images←["b":8 "h":224 "w":224 "c":3]⍴0
patches←["b":0 "h":["i":1 ∞;"y":3 16] "w":["j":2 ∞;"x":4 16] "c":5]⍉images
⍴patches                  ⍝ ["b":8 "i":14 "j":14 "y":16 "x":16 "c":3]ₓ
⍴["b" "patch":["i" "j"] "pixel":["y" "x" "c"]]⍉⁻¹patches
⍝ ["b":8 "patch":196 "pixel":768]ₓ
```

Splitting or merging drops position keys on the changed axes. A changed
axis takes its name from a key in the left argument, and has none
without one. Untouched axes keep their keys and names, unless a key
renames them. A named `X⍉⁻¹` doesn’t record the original axis order.
Inverting it gives DOMAIN ERROR. A numeric left argument inverts in both
directions when each group is a list of pairs with sizes. Under writes
back through every form of `⍉` and `⍉⁻¹`.
