{
"title": "argsort",
"category": "array/sorting_sets",
"keywords": [
"argsort",
"sort",
"indices",
"permutation",
"gpu"
],
"summary": "Return the permutation indices that would sort tensors along a dimension.",
"references": [
"https://www.mathworks.com/help/matlab/ref/sort.html"
],
"gpu_support": {
"elementwise": false,
"reduction": false,
"precisions": [
"f32",
"f64"
],
"broadcasting": "none",
"notes": "Uses the same sort kernels as `sort`; falls back to host evaluation when the provider lacks `sort_dim`."
},
"fusion": {
"elementwise": false,
"reduction": false,
"max_inputs": 1,
"constants": "inline"
},
"requires_feature": null,
"tested": {
"unit": "builtins::array::sorting_sets::argsort::tests",
"integration": "builtins::array::sorting_sets::argsort::tests::argsort_gpu_roundtrip"
},
"description": "`argsort(X)` returns the permutation indices that order `X` the same way `sort(X)` would. It matches the indices produced by `[~, I] = sort(X, ...)` in MathWorks MATLAB and honours the same argument forms for dimensions, directions, and comparison methods.",
"behaviors": [
"Operates along the first non-singleton dimension by default. Pass a dimension argument to override.",
"Accepts the same direction keywords as `sort`: `'ascend'` (default) or `'descend'`.",
"Supports `'ComparisonMethod'` values `'auto'`, `'real'`, and `'abs'` for real and complex inputs.",
"Returns indices as double-precision tensors using MATLAB's one-based indexing.",
"Treats NaN values as missing: they appear at the end for ascending permutations and at the beginning for descending permutations.",
"Acts as a residency sink. GPU tensors are gathered when the active provider does not expose a specialised sort kernel."
],
"examples": [
{
"description": "Getting indices that sort a vector",
"input": "A = [4; 1; 3];\nidx = argsort(A)",
"output": "idx =\n 2\n 3\n 1"
},
{
"description": "Reordering data with the permutation indices",
"input": "A = [3 9 1 5];\nidx = argsort(A);\nsorted = A(idx)",
"output": "sorted =\n 1 3 5 9"
},
{
"description": "Sorting along a specific dimension",
"input": "A = [1 6 4; 2 3 5];\nidx = argsort(A, 2)",
"output": "idx =\n 1 3 2\n 1 2 3"
},
{
"description": "Descending order permutations",
"input": "A = [10 4 7 9];\nidx = argsort(A, 'descend')",
"output": "idx =\n 1 4 3 2"
},
{
"description": "Using `ComparisonMethod` to sort by magnitude",
"input": "A = [-8 -1 3 -2];\nidx = argsort(A, 'ComparisonMethod', 'abs')",
"output": "idx =\n 2 4 3 1"
},
{
"description": "Handling NaN values during permutation",
"input": "A = [NaN 4 1 2];\nidx = argsort(A)",
"output": "idx =\n 3 4 2 1"
},
{
"description": "Argsort on GPU tensors falls back gracefully",
"input": "G = gpuArray(randn(5, 1));\nidx = argsort(G)"
}
],
"faqs": [
{
"question": "How is `argsort` different from `sort`?",
"answer": "`argsort` returns only the permutation indices. It behaves like calling `[~, I] = sort(X, ...)` without materialising the sorted values."
},
{
"question": "Are the indices one-based like MATLAB?",
"answer": "Yes. All indices follow MATLAB's one-based convention so they can be used directly with subsequent indexing operations."
},
{
"question": "Does `argsort` support the same arguments as `sort`?",
"answer": "Yes. Dimension arguments, direction keywords, and `'ComparisonMethod'` behave exactly like they do for `sort`."
},
{
"question": "How are NaN values ordered?",
"answer": "NaNs are treated as missing. They appear at the end for ascending permutations and at the beginning for descending permutations, matching MATLAB."
},
{
"question": "Can I call `argsort` on GPU arrays?",
"answer": "Yes. When the active provider implements the `sort_dim` hook, permutations stay on the device. Otherwise tensors are gathered automatically and sorted on the host."
},
{
"question": "Is the permutation stable?",
"answer": "Yes. Equal elements keep their relative order so that `argsort` remains consistent with MATLAB's stable sorting semantics."
},
{
"question": "What type is returned?",
"answer": "A double-precision tensor (or scalar) with the same shape as the input, containing permutation indices."
},
{
"question": "Does `argsort` mutate its input?",
"answer": "No. It only returns indices. Combine the result with indexing (`A(idx)`) to obtain reordered values when needed."
}
],
"links": [
{
"label": "sort",
"url": "./sort"
},
{
"label": "sortrows",
"url": "./sortrows"
},
{
"label": "randperm",
"url": "./randperm"
},
{
"label": "max",
"url": "./max"
},
{
"label": "min",
"url": "./min"
},
{
"label": "intersect",
"url": "./intersect"
},
{
"label": "ismember",
"url": "./ismember"
},
{
"label": "issorted",
"url": "./issorted"
},
{
"label": "setdiff",
"url": "./setdiff"
},
{
"label": "union",
"url": "./union"
},
{
"label": "unique",
"url": "./unique"
}
],
"source": {
"label": "`crates/runmat-runtime/src/builtins/array/sorting_sets/argsort.rs`",
"url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/array/sorting_sets/argsort.rs"
},
"gpu_behavior": [
"`argsort` shares the `sort_dim` provider hook with the `sort` builtin. When implemented, indices are computed without leaving the device.",
"If the provider lacks `sort_dim`, RunMat gathers tensors to host memory, evaluates the permutation, and returns host-resident indices.",
"Outputs are always host-resident double tensors because permutation indices are consumed immediately by host-side logic (e.g., indexing)."
]
}