runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "randperm",
  "category": "array/creation",
  "keywords": [
    "randperm",
    "permutation",
    "random",
    "indices",
    "gpu",
    "like"
  ],
  "summary": "Random permutations of the integers 1:n with MATLAB-compatible semantics.",
  "references": [],
  "gpu_support": {
    "elementwise": false,
    "reduction": false,
    "precisions": [
      "f64"
    ],
    "broadcasting": "none",
    "notes": "Falls back to host-side generation followed by an upload when providers lack a dedicated permutation kernel."
  },
  "fusion": {
    "elementwise": false,
    "reduction": false,
    "max_inputs": 0,
    "constants": "none"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::array::creation::randperm::tests",
    "integration": "builtins::array::creation::randperm::tests::randperm_gpu_like_roundtrip"
  },
  "description": "`randperm(n)` returns a uniformly random permutation of the integers `1:n`. `randperm(n, k)` selects `k` unique integers from `1:n` without replacement. RunMat mirrors MATLAB's behaviour, including RNG seeding through `rng`, GPU-aware `'like'` prototypes, and deterministic results during testing.",
  "behaviors": [
    "`randperm(n)` produces a row vector whose length is `n` and whose entries are a random ordering of `1:n`.",
    "`randperm(n, k)` returns the first `k` entries of the permutation without replacement (`0 ≤ k ≤ n`). The result is a `1 × k` row vector.",
    "`randperm(n, ___, 'like', A)` matches the numeric class and residency of `A` when possible (e.g., GPU tensors).",
    "`randperm(n, ___, 'double')` keeps the default double-precision output.",
    "`randperm` errors when `n` or `k` are non-integers, negative, or exceed the IEEE `double` integer precision limit (`2^53`).",
    "Empty permutations (e.g., `randperm(0)` or `randperm(n, 0)`) return a `1×0` tensor."
  ],
  "examples": [
    {
      "description": "Getting a random permutation of integers 1 through N",
      "input": "rng(0);\np = randperm(6)",
      "output": "p = [1 6 2 4 3 5]"
    },
    {
      "description": "Selecting K unique indices without replacement",
      "input": "rng(0);\nidx = randperm(10, 3)",
      "output": "idx = [1 10 9]"
    },
    {
      "description": "Generating a reproducible permutation after seeding RNG",
      "input": "rng(42);\np1 = randperm(8);\nrng(42);\np2 = randperm(8)",
      "output": "isequal(p1, p2)\nans = logical\n     1"
    },
    {
      "description": "Creating a GPU-resident random permutation",
      "input": "G = gpuArray.zeros(4, 4);\np = randperm(12, 4, 'like', G);\npeek = gather(p)",
      "output": "isa(p, 'gpuArray')\nans = logical\n     1"
    },
    {
      "description": "Working with empty permutations",
      "input": "p = randperm(0);\nq = randperm(5, 0)",
      "output": "size(p)\nans =\n     1     0\n\nsize(q)\nans =\n     1     0"
    }
  ],
  "faqs": [
    {
      "question": "What ranges does `randperm` draw from?",
      "answer": "`randperm(n)` always returns integers in the inclusive range `1:n`. The optional second argument `k` picks the first `k` elements of that permutation."
    },
    {
      "question": "Can `k` be zero?",
      "answer": "Yes. `randperm(n, 0)` returns a `1×0` empty row vector without consuming any additional random numbers."
    },
    {
      "question": "Does `randperm` support `'single'` or integer output types?",
      "answer": "Not yet. The builtin currently emits double-precision arrays. Supplying `'single'` or integer class names raises a descriptive error."
    },
    {
      "question": "How does `randperm` interact with `rng`?",
      "answer": "`randperm` consumes the shared RunMat RNG stream. Use the MATLAB-compatible `rng` builtin to seed or restore the generator for reproducible permutations."
    },
    {
      "question": "Why is there a `2^53` limit?",
      "answer": "All outputs are stored in IEEE `double`. Values beyond `2^53` cannot be represented exactly, so RunMat rejects inputs larger than `2^53` to avoid duplicate entries."
    },
    {
      "question": "Does the GPU path stay device-resident?",
      "answer": "Yes—when a provider is active RunMat uploads the host permutation after it is generated. Providers that later add a dedicated permutation kernel can replace the fallback without changing user code."
    }
  ],
  "links": [
    {
      "label": "rand",
      "url": "./rand"
    },
    {
      "label": "randi",
      "url": "./randi"
    },
    {
      "label": "rng",
      "url": "./rng"
    },
    {
      "label": "gpuArray",
      "url": "./gpuarray"
    },
    {
      "label": "gather",
      "url": "./gather"
    },
    {
      "label": "colon",
      "url": "./colon"
    },
    {
      "label": "eye",
      "url": "./eye"
    },
    {
      "label": "false",
      "url": "./false"
    },
    {
      "label": "fill",
      "url": "./fill"
    },
    {
      "label": "linspace",
      "url": "./linspace"
    },
    {
      "label": "logspace",
      "url": "./logspace"
    },
    {
      "label": "magic",
      "url": "./magic"
    },
    {
      "label": "meshgrid",
      "url": "./meshgrid"
    },
    {
      "label": "ones",
      "url": "./ones"
    },
    {
      "label": "randn",
      "url": "./randn"
    },
    {
      "label": "range",
      "url": "./range"
    },
    {
      "label": "true",
      "url": "./true"
    },
    {
      "label": "zeros",
      "url": "./zeros"
    }
  ],
  "source": {
    "label": "`crates/runmat-runtime/src/builtins/array/creation/randperm.rs`",
    "url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/array/creation/randperm.rs"
  },
  "gpu_residency": "You usually do NOT need to call `gpuArray` yourself in RunMat (unlike MATLAB).\n\nIn RunMat, the fusion planner and acceleration layer keep residency on the GPU whenever downstream computation benefits from it. When you request a permutation `'like'` a GPU tensor, RunMat asks the active acceleration provider to generate and shuffle the permutation directly on the device. If the provider does not implement the permutation hook, RunMat falls back to host generation and performs a single upload so later GPU work still sees a device-resident array.\n\nTo preserve backwards compatibility with MathWorks MATLAB—and for situations where you want to be explicit—you can always wrap inputs in `gpuArray`.",
  "gpu_behavior": [
    "When the `'like'` prototype lives on the GPU, RunMat asks the active acceleration provider for a device-side permutation via the dedicated `random_permutation_like` hook. The bundled WGPU provider executes the entire selection and shuffle in a compute kernel, keeping the data resident on the device. Providers that do not advertise this hook fall back to the host implementation and upload the result once, preserving correctness while highlighting the extra transfer cost."
  ]
}