8 | %language ElabReflection
10 | ||| We often deal with the 'logical' representation of tensors, but for
11 | ||| performance characteristics we need to be cognisant of how these tensors
12 | ||| are stored in the physical memory, which is in 1D linear order.
13 | ||| There are two options: row-major and column-major format
14 | ||| NumPy, PyTorch, TensorFlow and JAX use row-major indexing
15 | ||| The idea is that once linearised, with:
16 | ||| - row-major the last index of the array varies fastest
17 | ||| - column-major the first index of the array varies fastest
26 | ||| Following most popular conventions, we use row-major ordering by default
31 | ||| Layout-aware version of splitProd from Data.Fin.Split.
32 | |||
33 | ||| Row-major: index k in a m×n matrix maps to (k/n, k%n)
34 | ||| - goes through all columns before moving to next row
35 | ||| Column-major: index k maps to (k%m, k/m)
36 | ||| - goes through all rows before moving to next column
37 | |||
38 | ||| For a 2×3 matrix:
39 | ||| Row-major order: (0,0), (0,1), (0,2), (1,0), (1,1), (1,2)
40 | ||| Column-major order: (0,0), (1,0), (0,1), (1,1), (0,2), (1,2)
50 | ||| Layout-aware version of indexProd from Data.Fin.Split.
51 | ||| Inverse of splitFinProd: given (row, col) indices, compute linear index.
52 | |||
53 | ||| Row-major: linear index = row * n + col
54 | ||| Column-major: linear index = col * m + row
55 | |||
56 | ||| For a 2×3 matrix with (row=1, col=2):
57 | ||| Row-major: 1 * 3 + 2 = 5
58 | ||| Column-major: 2 * 2 + 1 = 5
69 | ||| Like `splitFinProd`, but here the order is fixed for us by dependency