runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "mpower",
  "category": "math/linalg/ops",
  "keywords": [
    "mpower",
    "matrix power",
    "linear algebra",
    "gpu"
  ],
  "summary": "Raise scalars or square matrices to a scalar power (A^B) following MATLAB's matrix power semantics.",
  "references": [
    "https://www.mathworks.com/help/matlab/ref/mpower.html"
  ],
  "gpu_support": {
    "elementwise": false,
    "reduction": false,
    "precisions": [
      "f32",
      "f64"
    ],
    "broadcasting": "none",
    "notes": "Repeatedly invokes the provider matmul hook with binary exponentiation; falls back to the host when matmul or eye-like allocation is unavailable."
  },
  "fusion": {
    "elementwise": false,
    "reduction": false,
    "max_inputs": 2,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::math::linalg::ops::mpower::tests::matrix_square_power",
    "gpu": "builtins::math::linalg::ops::mpower::tests::gpu_matrix_power_roundtrip"
  },
  "description": "`C = mpower(A, B)` evaluates the matrix power `A^B`. For scalars it behaves like ordinary exponentiation, while square matrices use repeated matrix multiplication with MATLAB-compatible rules for identity, errors, and complex promotion.",
  "behaviors": [
    "`A` must be square when it is a matrix. If `A` is `m × n` with `m != n`, RunMat throws `Matrix must be square for matrix power: m×n`.",
    "The exponent `B` must be a scalar numeric value. Integer-valued doubles are accepted (`2.0` is treated as `2`); non-integer exponents raise `Matrix power requires integer exponent`.",
    "`A^0` returns the identity matrix of the same size as `A`. Scalar inputs follow the expected rule `x^0 = 1`.",
    "Positive integers are evaluated with binary exponentiation (`A^5` → `A * A * A * A * A`). Negative exponents are currently unsupported and produce the MATLAB-style message `Negative matrix powers not supported yet`.",
    "Complex scalars are handled exactly; complex matrices are supported so long as the exponent is an integer."
  ],
  "examples": [
    {
      "description": "Raising a matrix to an integer power",
      "input": "A = [1 3; 2 4];\nC = mpower(A, 2)",
      "output": "C =\n     7    15\n    10    22"
    },
    {
      "description": "Returning the identity matrix when exponent is zero",
      "input": "A = [5 2; 7 1];\nI = mpower(A, 0)",
      "output": "I =\n     1     0\n     0     1"
    },
    {
      "description": "Scalar bases behave like ordinary exponentiation",
      "input": "result = mpower(4, 0.5)",
      "output": "result = 2"
    },
    {
      "description": "Non-integer exponents raise an error for matrices",
      "input": "A = [1 2; 3 4];\nC = mpower(A, 1.5)",
      "output": "Error using  mpower\nMatrix power requires integer exponent."
    },
    {
      "description": "Computing matrix powers on the GPU",
      "input": "G = gpuArray([2 0; 0 2]);\nH = mpower(G, 3);\ngather(H)",
      "output": "ans =\n     8     0\n     0     8"
    }
  ],
  "faqs": [
    {
      "question": "Does `mpower` support non-square matrices?",
      "answer": "No. `mpower` requires `A` to be square. Use `A.^B` for element-wise powers on non-square arrays."
    },
    {
      "question": "Can I raise a matrix to a non-integer exponent?",
      "answer": "Not yet. RunMat matches MATLAB by requiring the exponent to be an integer-valued scalar for matrix powers. Non-integer exponents raise `Matrix power requires integer exponent`."
    },
    {
      "question": "Are negative exponents supported?",
      "answer": "Negative matrix exponents will return with `Negative matrix powers not supported yet`. Use `inv(A)` manually for now."
    },
    {
      "question": "How does `mpower` differ from the element-wise power operator?",
      "answer": "`mpower` performs matrix multiplication repeatedly. Element-wise power (`.^`) raises each entry independently and supports arbitrary array shapes."
    },
    {
      "question": "Will results stay on the GPU?",
      "answer": "Yes—provided the acceleration provider implements `matmul`. When it does not, RunMat computes on the host but attempts to re-upload the result so GPU pipelines continue smoothly."
    },
    {
      "question": "Is there a limit on the exponent magnitude?",
      "answer": "Integers up to ±(2³¹−1) are supported. Exponents outside this range trigger a descriptive error."
    }
  ],
  "links": [
    {
      "label": "mtimes",
      "url": "./mtimes"
    },
    {
      "label": "power",
      "url": "./power"
    },
    {
      "label": "eye",
      "url": "./eye"
    },
    {
      "label": "gpuArray",
      "url": "./gpuarray"
    },
    {
      "label": "gather",
      "url": "./gather"
    },
    {
      "label": "ctranspose",
      "url": "./ctranspose"
    },
    {
      "label": "dot",
      "url": "./dot"
    },
    {
      "label": "mldivide",
      "url": "./mldivide"
    },
    {
      "label": "mrdivide",
      "url": "./mrdivide"
    },
    {
      "label": "trace",
      "url": "./trace"
    },
    {
      "label": "transpose",
      "url": "./transpose"
    }
  ],
  "source": {
    "label": "`crates/runmat-runtime/src/builtins/math/linalg/ops/mpower.rs`",
    "url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/math/linalg/ops/mpower.rs"
  },
  "gpu_residency": "When a provider with matrix multiplication is active, RunMat keeps inputs and results on the GPU automatically—`gpuArray(A)^3` never leaves device memory. If the provider cannot service the request, the runtime gathers to the host, computes the reference result, and (when the outcome is real) uploads it back so the calling code still sees a `gpuArray`.",
  "gpu_behavior": [
    "1. When either operand already resides on the GPU, RunMat asks the active acceleration provider for repeated matrix multiplications using the provider’s `matmul` hook. 2. Identity results (`A^0`) are generated with `eye_like` when the provider exposes it; otherwise the runtime fabricates the identity on the host and uploads it. 3. If the provider declines any step (missing `matmul`, unsupported precision, unimplemented identity), RunMat gathers operands to the host, evaluates the CPU reference implementation, and uploads the result back to the device when possible so downstream code can stay on the GPU."
  ]
}