runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "mean",
  "category": "math/reduction",
  "keywords": [
    "mean",
    "average",
    "reduction",
    "gpu",
    "omitnan",
    "like",
    "native"
  ],
  "summary": "Average elements of scalars, vectors, matrices, or N-D tensors with MATLAB-compatible options.",
  "references": [],
  "gpu_support": {
    "elementwise": false,
    "reduction": true,
    "precisions": [
      "f32",
      "f64"
    ],
    "broadcasting": "matlab",
    "notes": "Falls back to host whenever 'omitnan' is requested or the active provider lacks mean reductions."
  },
  "fusion": {
    "elementwise": false,
    "reduction": false,
    "max_inputs": 1,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::math::reduction::mean::tests",
    "integration": "builtins::math::reduction::mean::tests::mean_gpu_provider_roundtrip"
  },
  "description": "`mean(x)` computes the arithmetic mean of scalars, vectors, matrices, and higher-dimensional tensors. When no dimension is supplied, the reduction runs along the first non-singleton dimension.",
  "behaviors": [
    "`mean(X)` on an `m × n` matrix returns a row vector (`1 × n`) with column averages.",
    "`mean(X, 2)` returns a column vector (`m × 1`) containing row averages.",
    "`mean(X, 'all')` collapses every dimension and returns a scalar average of all elements.",
    "`mean(X, vecdim)` accepts a vector of dimensions (e.g., `[1 3]`) and reduces each listed axis in one call while preserving the others.",
    "Complex inputs are supported and follow MATLAB's rule `mean(a + bi) = mean(real(a + bi)) + i·mean(imag(a + bi))`, propagating `NaN` through either component.",
    "Logical inputs are promoted to double precision (`true → 1.0`, `false → 0.0`).",
    "`mean(..., 'omitnan')` ignores `NaN` values; if every element in the slice is `NaN`, the result is `NaN`.",
    "`mean(..., 'includenan')` (default) propagates `NaN` when any element in the slice is `NaN`.",
    "`mean(___, outtype)` accepts `'double'`, `'default'`, or `'native'` to control the output numeric class. Integer outputs round to the nearest integer, matching MATLAB.",
    "`mean(___, 'like', prototype)` matches the numeric class and residency of `prototype`, including GPU tensors and complex arrays.",
    "Empty slices produce `NaN` outputs that follow MATLAB's shape semantics.",
    "Dimensions larger than `ndims(X)` leave the input unchanged."
  ],
  "examples": [
    {
      "description": "Computing the mean of a matrix",
      "input": "A = [1 2 3; 4 5 6];\ncolMeans = mean(A);      % column averages\nrowMeans = mean(A, 2);   % row averages",
      "output": "colMeans = [2.5 3.5 4.5];\nrowMeans = [2; 5]"
    },
    {
      "description": "Computing the mean of a vector with NaN values",
      "input": "values = [1 NaN 3];\navg = mean(values, 'omitnan')",
      "output": "avg = 2"
    },
    {
      "description": "Computing the overall mean across all elements",
      "input": "B = reshape(1:12, [3 4]);\noverall = mean(B, 'all')",
      "output": "overall = 6.5"
    },
    {
      "description": "Reducing across multiple dimensions at once",
      "input": "C = cat(3, [1 2; 3 4], [5 6; 7 8]);\nslice_means = mean(C, [1 3]);   % reduce rows and pages, keep columns",
      "output": "slice_means = [4 5]"
    },
    {
      "description": "Matching a prototype with `'like'`",
      "input": "G = gpuArray(single([1 3; 5 7]));\nmu = mean(G, 'all', 'like', G);\nresult = gather(mu)",
      "output": "result = single(4)"
    },
    {
      "description": "Computing the mean of a matrix on a GPU",
      "input": "G = gpuArray([1 2 NaN; 3 4 5]);\nmeans = mean(G, 2, 'omitnan');\nresult = gather(means)",
      "output": "result = [1.5; 4]"
    }
  ],
  "faqs": [
    {
      "question": "When should I use the `mean` function?",
      "answer": "Use `mean` whenever you need to compute the arithmetic mean of a tensor. This is useful for calculating averages, central tendencies, or performing statistical analysis."
    },
    {
      "question": "What does `mean(A)` return?",
      "answer": "If you call `mean(A)`, where `A` is an array, the result is a new array of the same shape as `A` with the mean of each slice along the first non-singleton dimension. For example, if `A` is a 2x3 matrix, `mean(A)` will return a 1x3 matrix with the mean of each column."
    },
    {
      "question": "How do I compute the mean of a specific dimension?",
      "answer": "You can use the `dim` argument to specify the dimension along which to compute the mean. For example, `mean(A, 2)` will return a 2x1 matrix with the mean of each row."
    },
    {
      "question": "How do I average across multiple dimensions at once?",
      "answer": "Pass a vector of dimensions such as `mean(A, [1 3])`. RunMat reduces each listed axis in a single pass, leaving the remaining dimensions unchanged."
    },
    {
      "question": "What happens if the slice contains only NaN values?",
      "answer": "When you specify `'omitnan'`, slices that contain only `NaN` still return `NaN`, mirroring MATLAB. With `'includenan'` (the default), any `NaN` in the slice forces the result to `NaN`."
    },
    {
      "question": "Does `mean` support GPU arrays automatically?",
      "answer": "Yes. If a GPU provider is registered, device-resident tensors remain on the GPU and run through `reduce_mean_dim`/`reduce_mean`. Calls that the provider cannot satisfy—most notably `'omitnan'` and unsupported dimension combinations—are gathered to the CPU transparently."
    },
    {
      "question": "How are complex numbers handled?",
      "answer": "RunMat averages the real and imaginary components separately. If either component in a slice is `NaN`, the result for that slice becomes complex `NaN`, matching MATLAB's behaviour."
    },
    {
      "question": "How can I control the output type?",
      "answer": "By default, RunMat promotes inputs to double precision. Use the optional outtype argument to override this behaviour: pass `'native'` to round back to the input's integer class, or `'double'`/`'default'` to force double precision explicitly. `'like', prototype` matches the numeric flavour and residency of `prototype`, including complex outputs."
    },
    {
      "question": "Can I keep the result on the GPU or match an existing prototype?",
      "answer": "Yes. When you pass `'like', prototype`, RunMat mirrors both the class and residency of `prototype`. Providing a GPU tensor keeps the result on the device even when the reduction itself had to fall back to the host (for example with `'omitnan'`)."
    }
  ],
  "links": [
    {
      "label": "sum",
      "url": "./sum"
    },
    {
      "label": "median",
      "url": "./median"
    },
    {
      "label": "cumsum",
      "url": "./cumsum"
    },
    {
      "label": "gpuArray",
      "url": "./gpuarray"
    },
    {
      "label": "gather",
      "url": "./gather"
    },
    {
      "label": "all",
      "url": "./all"
    },
    {
      "label": "any",
      "url": "./any"
    },
    {
      "label": "cummax",
      "url": "./cummax"
    },
    {
      "label": "cummin",
      "url": "./cummin"
    },
    {
      "label": "cumprod",
      "url": "./cumprod"
    },
    {
      "label": "diff",
      "url": "./diff"
    },
    {
      "label": "max",
      "url": "./max"
    },
    {
      "label": "min",
      "url": "./min"
    },
    {
      "label": "nnz",
      "url": "./nnz"
    },
    {
      "label": "prod",
      "url": "./prod"
    },
    {
      "label": "std",
      "url": "./std"
    },
    {
      "label": "var",
      "url": "./var"
    }
  ],
  "source": {
    "label": "`crates/runmat-runtime/src/builtins/math/reduction/mean.rs`",
    "url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/math/reduction/mean.rs"
  },
  "gpu_residency": "You usually do NOT need to call `gpuArray` yourself in RunMat (unlike MATLAB).\n\nIn RunMat, the fusion planner keeps residency on GPU in branches of fused expressions. As such, in the above example, the result of the `mean` call will already be on the GPU when the fusion planner has detected a net benefit to operating the fused expression it is part of on the GPU.\n\nTo preserve backwards compatibility with MathWorks MATLAB, and for when you want to explicitly bootstrap GPU residency, you can call `gpuArray` explicitly to move data to the GPU if you want to be explicit about the residency.\n\nSince MathWorks MATLAB does not have a fusion planner, and they kept their parallel execution toolbox separate from the core language, as their toolbox is a separate commercial product, MathWorks MATLAB users need to call `gpuArray` to move data to the GPU manually whereas RunMat users can rely on the fusion planner to keep data on the GPU automatically.",
  "gpu_behavior": [
    "When the input tensor lives on the GPU, RunMat first asks the active acceleration provider for a device-side result via `reduce_mean_dim` or (when the entire tensor collapses) `reduce_mean`. If the provider lacks those hooks or the call specifies `'omitnan'`, RunMat gathers the data back to the host and evaluates the mean with the CPU reference implementation. Output templates are then applied: `'native'` restores integer classes, and `'like'` mirrors both the numeric class and residency—re-uploading to the GPU when the prototype is device-resident."
  ]
}