{
"title": "cov",
"category": "stats/summary",
"keywords": [
"cov",
"covariance",
"statistics",
"weighted covariance",
"gpu"
],
"summary": "Compute covariance matrices for vectors, matrices, or paired data sets.",
"references": [
"https://www.mathworks.com/help/matlab/ref/cov.html"
],
"gpu_support": {
"elementwise": false,
"reduction": false,
"precisions": [
"f32",
"f64"
],
"broadcasting": "none",
"notes": "Runs on the GPU when rows='all' and no weight vector is supplied; other modes transparently fall back to the CPU reference path."
},
"fusion": {
"elementwise": false,
"reduction": false,
"max_inputs": 2,
"constants": "inline"
},
"requires_feature": null,
"tested": {
"unit": "builtins::stats::summary::cov::tests",
"integration": "builtins::stats::summary::cov::tests::cov_gpu_roundtrip"
},
"description": "`cov` returns covariance matrices for numeric data. Columns represent variables and rows are observations. You can pass in one matrix, two matching data sets, or supply observation weights and row-handling options that mirror MATLAB.",
"behaviors": [
"`cov(X)` treats each column of `X` as a variable and returns a square covariance matrix.",
"`cov(X, Y)` concatenates `X` and `Y` column-wise (they must have the same number of rows) before computing the covariance.",
"The second argument can be the normalization flag `0` (default) or `1`, matching MATLAB's unbiased and biased estimators.",
"You can pass a weight vector to obtain frequency-weighted covariance.",
"`'omitrows'` drops rows containing `NaN` or `Inf` before the covariance is computed.",
"`'partialrows'` performs pairwise deletion: each covariance entry uses only the rows that contain finite values for that column pair."
],
"examples": [
{
"description": "Computing covariance of columns in a matrix",
"input": "X = [4.0 2.0 0.60;\n 4.2 2.1 0.59;\n 3.9 2.0 0.58;\n 4.3 2.1 0.62;\n 4.1 2.2 0.63];\nC = cov(X)",
"output": "C =\n 0.0250 0.0075 0.0018\n 0.0075 0.0070 0.0014\n 0.0018 0.0014 0.0004"
},
{
"description": "Covariance between two vectors",
"input": "x = [1 2 3 4]';\ny = [10 11 9 12]';\nC = cov(x, y)",
"output": "C =\n 1.6667 0.6667\n 0.6667 1.6667"
},
{
"description": "Weighted covariance with observation weights",
"input": "X = [4.0 2.0;\n 4.2 2.1;\n 3.9 2.0;\n 4.3 2.1;\n 4.1 2.2];\nw = [1 1 1 2 2];\nCw = cov(X, w)",
"output": "Cw =\n 0.0224 0.0050\n 0.0050 0.0067"
},
{
"description": "Ignoring rows that contain missing values",
"input": "X = [1 NaN 2;\n 3 4 5;\n NaN 6 7;\n 8 9 10];\nC = cov(X, 'omitrows')",
"output": "C =\n 12.5000 12.5000 12.5000\n 12.5000 12.5000 12.5000\n 12.5000 12.5000 12.5000"
},
{
"description": "Pairwise covariance with staggered NaNs",
"input": "X = [ 1 2 NaN;\n 4 NaN 6;\n 7 8 9];\nC = cov(X, 'partialrows')",
"output": "C =\n 9.0000 18.0000 4.5000\n 18.0000 18.0000 NaN\n 4.5000 NaN 4.5000"
},
{
"description": "Running covariance on `gpuArray` inputs",
"input": "X = [4.0 2.0 0.60;\n 4.2 2.1 0.59;\n 3.9 2.0 0.58;\n 4.3 2.1 0.62;\n 4.1 2.2 0.63];\nG = gpuArray(X);\nCG = cov(G);\nCG_host = gather(CG)",
"output": "CG_host =\n 0.0250 0.0075 0.0018\n 0.0075 0.0070 0.0014\n 0.0018 0.0014 0.0004"
}
],
"faqs": [
{
"question": "Does `cov` support biased and unbiased estimators?",
"answer": "Yes. The default is the unbiased estimator (divide by *N - 1*). Passing `1` as the second argument switches to the biased estimator (divide by *N*), matching MATLAB."
},
{
"question": "How do I provide observation weights?",
"answer": "Supply a weight vector whose length equals the number of observations. The covariance is frequency-weighted using the MATLAB formula. Weighted covariance currently falls back to the CPU implementation when running on the GPU."
},
{
"question": "What happens when columns contain constant values?",
"answer": "The diagonal entries become zero, and off-diagonal entries involving the constant column are zero. Any slight negative values caused by floating-point noise are clamped to zero."
},
{
"question": "How are `NaN` and `Inf` handled?",
"answer": "By default (`'all'`), non-finite values propagate `NaN` into the affected covariance entries. `'omitrows'` drops rows containing non-finite values, while `'partialrows'` recomputes each covariance entry using only rows that are finite for the relevant column pair."
},
{
"question": "Can I call `cov` on logical inputs?",
"answer": "Yes. Logical arrays are converted to double precision (`true → 1.0`, `false → 0.0`) before the covariance is computed, matching MATLAB's behaviour."
}
],
"links": [
{
"label": "corrcoef",
"url": "./corrcoef"
},
{
"label": "mean",
"url": "./mean"
},
{
"label": "sum",
"url": "./sum"
},
{
"label": "gpuArray",
"url": "./gpuarray"
},
{
"label": "gather",
"url": "./gather"
}
],
"source": {
"label": "`crates/runmat-runtime/src/builtins/stats/summary/cov.rs`",
"url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/stats/summary/cov.rs"
},
"gpu_residency": "You usually do **not** need to call `gpuArray`. Expressions such as `cov(sin(X))` keep temporary results on the GPU as long as the active provider handles the operation. The builtin gathers to the CPU only when weights, `'omitrows'`, or `'partialrows'` are requested, or when the provider does not implement the covariance hook. Explicitly calling `gpuArray` remains supported for MATLAB compatibility and to seed GPU residency when you are unsure about planner decisions.",
"gpu_behavior": [
"RunMat invokes provider-specific GPU kernels when:\n\n1. All inputs already reside on the GPU; 2. No weight vector is supplied; 3. The rows option is `'all'`; and 4. The active provider exposes the custom `covariance` hook.\n\nIf any of these conditions is not met, RunMat gathers the data to the host, evaluates the reference implementation, and returns a dense host tensor. This guarantees MATLAB-compatible behaviour regardless of GPU support."
]
}