{
"title": "setdiff",
"category": "array/sorting_sets",
"keywords": [
"setdiff",
"difference",
"stable",
"rows",
"indices",
"gpu"
],
"summary": "Return values that appear in the first input but not the second, matching MATLAB ordering rules.",
"references": [
"https://www.mathworks.com/help/matlab/ref/setdiff.html"
],
"gpu_support": {
"elementwise": false,
"reduction": false,
"precisions": [
"f32",
"f64"
],
"broadcasting": "none",
"notes": "When providers lack a dedicated `setdiff` hook, RunMat gathers GPU tensors to host memory and reuses the CPU path."
},
"fusion": {
"elementwise": false,
"reduction": false,
"max_inputs": 2,
"constants": "inline"
},
"requires_feature": null,
"tested": {
"unit": "builtins::array::sorting_sets::setdiff::tests",
"integration": "builtins::array::sorting_sets::setdiff::tests::setdiff_gpu_roundtrip"
},
"description": "`setdiff(A, B)` returns the set of values (or rows) that appear in `A` but not in `B`. Results are unique, and the function can operate in sorted or stable order as well as row mode.",
"behaviors": [
"`setdiff(A, B)` flattens inputs column-major, removes duplicates, subtracts the values of `B` from `A`, and returns the remaining elements **sorted** ascending by default.",
"`[C, IA] = setdiff(A, B)` also returns indices so that `C = A(IA)`.",
"`setdiff(A, B, 'stable')` preserves the first appearance order from `A` instead of sorting.",
"`setdiff(A, B, 'rows')` treats each row as an element. Inputs must share the same number of columns.",
"Character arrays, string arrays, logical arrays, numeric types, and complex values are all supported.",
"Legacy flags (`'legacy'`, `'R2012a'`) are not supported; RunMat always follows modern MATLAB semantics."
],
"examples": [
{
"description": "Finding values exclusive to the first numeric vector",
"input": "A = [5 7 5 1];\nB = [7 1 3];\n[C, IA] = setdiff(A, B)",
"output": "C =\n 5\nIA =\n 1"
},
{
"description": "Preserving input order with `'stable'`",
"input": "A = [4 2 4 1 3];\nB = [3 4 5 1];\n[C, IA] = setdiff(A, B, 'stable')",
"output": "C =\n 2\nIA =\n 2"
},
{
"description": "Working with rows of numeric matrices",
"input": "A = [1 2; 3 4; 1 2];\nB = [3 4; 5 6];\n[C, IA] = setdiff(A, B, 'rows')",
"output": "C =\n 1 2\nIA =\n 1"
},
{
"description": "Computing set difference for character data",
"input": "A = ['m','z'; 'm','a'];\nB = ['a','x'; 'm','a'];\n[C, IA] = setdiff(A, B)",
"output": "C =\n m\nIA =\n 1"
},
{
"description": "Subtracting string arrays by row",
"input": "A = [\"alpha\" \"beta\"; \"gamma\" \"beta\"];\nB = [\"gamma\" \"beta\"; \"delta\" \"beta\"];\n[C, IA] = setdiff(A, B, 'rows', 'stable')",
"output": "C =\n 1x2 string array\n \"alpha\" \"beta\"\nIA =\n 1"
},
{
"description": "Using `setdiff` with GPU arrays",
"input": "G = gpuArray([10 4 6 4]);\nH = gpuArray([6 4 2]);\nC = setdiff(G, H)",
"output": "C =\n 10"
}
],
"faqs": [
{
"question": "What ordering does `setdiff` use by default?",
"answer": "Results are sorted ascending. Specify `'stable'` to preserve the first appearance order from the first input."
},
{
"question": "How are the index outputs defined?",
"answer": "`IA` points to the positions in `A` that correspond to each element (or row) returned in `C`, using MATLAB's one-based indexing."
},
{
"question": "Can I combine `'rows'` with `'stable'`?",
"answer": "Yes. `'rows'` can be paired with either `'sorted'` (default) or `'stable'`. Other option combinations that conflict (e.g. `'sorted'` with `'stable'`) are rejected."
},
{
"question": "Does `setdiff` remove `NaN` values from `A` when they exist in `B`?",
"answer": "Yes. `NaN` values are considered equal. If `B` contains `NaN`, all `NaN` entries from `A` are removed."
},
{
"question": "Are complex numbers supported?",
"answer": "Absolutely. Complex values use MATLAB's ordering rules (magnitude, then real part, then imaginary part) for the sorted output."
},
{
"question": "Does GPU execution change the results?",
"answer": "No. Until providers supply a device implementation, RunMat gathers GPU inputs and executes the CPU path to guarantee MATLAB-compatible behaviour."
},
{
"question": "What happens if the inputs have different classes?",
"answer": "RunMat follows MATLAB's rules: both inputs must share the same class (numeric/logical, complex, char, or string). Mixed-class inputs raise descriptive errors."
},
{
"question": "Can I request `'legacy'` behaviour?",
"answer": "No. RunMat implements the modern semantics only. Passing `'legacy'` or `'R2012a'` results in an error."
}
],
"links": [
{
"label": "unique",
"url": "./unique"
},
{
"label": "union",
"url": "./union"
},
{
"label": "intersect",
"url": "./intersect"
},
{
"label": "ismember",
"url": "./ismember"
},
{
"label": "gpuArray",
"url": "./gpuarray"
},
{
"label": "gather",
"url": "./gather"
},
{
"label": "argsort",
"url": "./argsort"
},
{
"label": "issorted",
"url": "./issorted"
},
{
"label": "sort",
"url": "./sort"
},
{
"label": "sortrows",
"url": "./sortrows"
}
],
"source": {
"label": "crates/runmat-runtime/src/builtins/array/sorting_sets/setdiff.rs",
"url": "crates/runmat-runtime/src/builtins/array/sorting_sets/setdiff.rs"
},
"gpu_behavior": [
"`setdiff` is registered as a residency sink. When tensors reside on the GPU and the active provider does not yet implement a `setdiff` hook, RunMat gathers them to host memory, performs the CPU implementation, and materialises host-resident results. Future providers can wire a custom hook to perform the set difference directly on-device without affecting existing callers."
]
}