runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "permute",
  "category": "array/shape",
  "keywords": [
    "permute",
    "dimension reorder",
    "swap axes",
    "gpu"
  ],
  "summary": "Reorder the dimensions of arrays, tensors, logical masks, and gpuArray values.",
  "references": [],
  "gpu_support": {
    "elementwise": false,
    "reduction": false,
    "precisions": [
      "f32",
      "f64",
      "i32",
      "bool"
    ],
    "broadcasting": "none",
    "notes": "Providers may implement a dedicated permute hook; when unavailable the runtime gathers, permutes on the host, and re-uploads to keep results on the GPU."
  },
  "fusion": {
    "elementwise": false,
    "reduction": false,
    "max_inputs": 1,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::array::shape::permute::tests",
    "integration": "builtins::array::shape::permute::tests::permute_gpu_roundtrip"
  },
  "description": "`permute(A, order)` rearranges the dimensions of `A` to match the order specified by the integer vector `order`. It works for numeric arrays, logical masks, complex arrays, string arrays, and gpuArray values. Dimensions not explicitly mentioned in the original array become size-one axes.",
  "behaviors": [
    "`order` must be a permutation of `1:n`, where `n = numel(order)`. Each dimension index appears exactly once.",
    "The length of `order` must be at least `ndims(A)`. You can specify additional trailing dimensions; RunMat pads missing axes with size one.",
    "Duplicate or zero dimension indices throw an error.",
    "Works on empty arrays and arrays with zero-sized dimensions. The result preserves MATLAB's column-major ordering.",
    "Logical, complex, and string arrays keep their types. Character arrays support 2-D permutations (transpose or identity).",
    "gpuArray inputs stay on the GPU. If the provider lacks a native permute kernel, RunMat gathers once, permutes on the host, and uploads the result back to the device."
  ],
  "examples": [
    {
      "description": "Swapping the first two dimensions of a 3-D tensor",
      "input": "A = reshape(1:24, [2 3 4]);\nB = permute(A, [2 1 3]);\nsize(B)",
      "output": "ans = [3 2 4]"
    },
    {
      "description": "Moving the last dimension to the front",
      "input": "A = rand(4, 2, 5);\nC = permute(A, [3 1 2]);\nsize(C)",
      "output": "ans = [5 4 2]"
    },
    {
      "description": "Adding an explicit trailing singleton dimension",
      "input": "row = 1:5;\nT = permute(row, [2 1 3]);\nsize(T)",
      "output": "ans = [5 1 1]"
    },
    {
      "description": "Permuting logical masks without losing type information",
      "input": "mask = false(2, 1, 3);\nmask(1, 1, 2) = true;\nrotated = permute(mask, [3 1 2]);\nclass(rotated)",
      "output": "ans = 'logical'"
    },
    {
      "description": "Transposing character arrays",
      "input": "C = ['r','u','n'; 'm','a','t'];\nCt = permute(C, [2 1])",
      "output": "Ct =\n    'rm'\n    'ua'\n    'nt'"
    },
    {
      "description": "Permuting gpuArray data while staying on the device",
      "input": "G = gpuArray(rand(4, 2, 3));\nH = permute(G, [3 1 2]);\nisgpuarray(H)",
      "output": "ans = logical 1"
    }
  ],
  "faqs": [
    {
      "question": "Does `order` have to contain every dimension exactly once?",
      "answer": "Yes. `order` must be a true permutation of `1:n`. RunMat raises an error when dimensions repeat or are missing."
    },
    {
      "question": "Can I introduce new singleton dimensions?",
      "answer": "Yes. Set `order` to include additional trailing indices (e.g., `[1 2 3 4]` for a matrix) and RunMat will append size-one axes."
    },
    {
      "question": "What happens with empty arrays or zero-sized dimensions?",
      "answer": "They are preserved. The permutation still follows column-major ordering even when some dimensions are zero."
    },
    {
      "question": "Can I use `permute` on character arrays?",
      "answer": "Yes, but only for 2-D permutations (identity or transpose) because MATLAB character arrays are stored as 2-D matrices."
    },
    {
      "question": "How does `permute` interact with gpuArray values?",
      "answer": "RunMat keeps the result on the GPU. Providers that lack a native kernel trigger a gather-and-reupload fallback, which is documented above."
    },
    {
      "question": "Is the operation in-place?",
      "answer": "No. `permute` returns a new array; the original input remains unchanged."
    },
    {
      "question": "How do I invert a permutation?",
      "answer": "Use `ipermute` with the same `order` vector."
    },
    {
      "question": "Does `permute` change data layout or ordering?",
      "answer": "Only the dimension metadata changes. Column-major linearisation is preserved, so reshaping back with the inverse order recovers the original array."
    },
    {
      "question": "Can cell arrays be permuted?",
      "answer": "Cell arrays above two dimensions are not yet supported in RunMat; the builtin will report an error."
    },
    {
      "question": "What if I pass a gpuArray as the `order` argument?",
      "answer": "MATLAB requires numeric vectors on the host. RunMat mirrors this and reports an error if the order vector is gpu-resident."
    }
  ],
  "links": [
    {
      "label": "`ipermute`",
      "url": "./ipermute"
    },
    {
      "label": "`reshape`",
      "url": "./reshape"
    },
    {
      "label": "`squeeze`",
      "url": "./squeeze"
    },
    {
      "label": "`size`",
      "url": "./size"
    },
    {
      "label": "`ndims`",
      "url": "./ndims"
    },
    {
      "label": "`gpuArray`",
      "url": "./gpuarray"
    },
    {
      "label": "`gather`",
      "url": "./gather"
    },
    {
      "label": "cat",
      "url": "./cat"
    },
    {
      "label": "circshift",
      "url": "./circshift"
    },
    {
      "label": "diag",
      "url": "./diag"
    },
    {
      "label": "flip",
      "url": "./flip"
    },
    {
      "label": "fliplr",
      "url": "./fliplr"
    },
    {
      "label": "flipud",
      "url": "./flipud"
    },
    {
      "label": "horzcat",
      "url": "./horzcat"
    },
    {
      "label": "kron",
      "url": "./kron"
    },
    {
      "label": "repmat",
      "url": "./repmat"
    },
    {
      "label": "rot90",
      "url": "./rot90"
    },
    {
      "label": "tril",
      "url": "./tril"
    },
    {
      "label": "triu",
      "url": "./triu"
    },
    {
      "label": "vertcat",
      "url": "./vertcat"
    }
  ],
  "source": {
    "label": "`crates/runmat-runtime/src/builtins/array/shape/permute.rs`",
    "url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/array/shape/permute.rs"
  },
  "gpu_behavior": [
    "The runtime first asks the active acceleration provider for the `permute` hook. When implemented (e.g., a fused copy kernel), the permutation occurs entirely on the device. Otherwise RunMat falls back to a gather/permute/upload path. Either way, the result is returned as a gpuArray to match MATLAB behaviour."
  ]
}