What does the factorial function do in MATLAB / RunMat?
factorial(X) computes X! (the product of the integers from 1 to X) for every element of X.
Inputs must be non-negative integers; MATLAB semantics dictate that non-integers return NaN,
and integers larger than 170 overflow to Inf in double precision.
How does the factorial function behave in MATLAB / RunMat?
- Scalars, vectors, matrices, and N-D tensors are processed element-by-element with MATLAB’s implicit expansion rules.
- Logical inputs promote to double precision (
true → 1,false → 0) before evaluation; integer classes are cast to double. - Non-integer or negative inputs yield
NaN; large integers (n ≥ 171) overflow toInf, matching MATLAB’s overflow handling in double precision. factorial(0)andfactorial(-0.0)both return1, in accordance with the definition0! = 1.- Results are real doubles. Passing
'like', prototypelets you retain host or GPU residency to integrate with existing pipelines. - GPU tensors remain on device when the active provider implements
unary_factorial; otherwise RunMat gathers to the host, computes the result, and re-uploads only when you explicitly request GPU residency via'like'.
factorial Function GPU Execution Behaviour
- RunMat Accelerate first tries the provider’s
unary_factorialhook. Simple in-process providers can satisfy this by mirroring the CPU calculation. - When the hook is unavailable (currently the WGPU backend), RunMat transparently gathers the tensor, evaluates
factorialon the CPU, and returns the host result. - Provide
'like', gpuArray(...)to force the fallback path to re-upload the result so downstream GPU code keeps working. - Fusion currently bypasses factorial because the operation is not polynomial; element-wise kernels fall back to the scalar implementation.
Examples of using the factorial function in MATLAB / RunMat
Factorial of a single integer value
y = factorial(5)
Expected output:
y = 120
Factorial of zero returns one
factorial(0)
Expected output:
ans = 1
Factorial across a vector of non-negative integers
vals = factorial([0 1 3 5]);
Expected output:
vals = [1 1 6 120]
Detecting invalid non-integer inputs
result = factorial([2.5 -1 4]);
Expected output:
result = [NaN NaN 24]
Handling large inputs that overflow to infinity
big = factorial(171);
Expected output:
big = Inf
Using factorial with gpuArray inputs
G = gpuArray(uint16([3 4 5]));
R = factorial(G);
host = gather(R);
Expected output:
host = [6 24 120]
Keeping results on the GPU with 'like'
proto = gpuArray.zeros(1, 1, 'single');
deviceResult = factorial([3 4], 'like', proto);
gathered = gather(deviceResult);
Expected output:
gathered =
1x2 single
6 24
GPU residency in RunMat (Do I need gpuArray?)
You do not need to call gpuArray manually to get correct results. When the provider supports
unary_factorial, tensors stay on the GPU automatically. If the provider does not, RunMat gathers to
the host and computes the answer there. Provide 'like', gpuArray(...) if you want the fallback path
to re-upload the result automatically.
FAQ
What inputs are valid for factorial?
Any non-negative integer (including zero). Logical and integer arrays are accepted; doubles must be
exact integers within floating-point tolerance. Non-integer or negative values return NaN.
Why do large integers return Inf?
Double precision overflows at 171!. MATLAB returns Inf for those values, and RunMat mirrors that
behaviour.
Does factorial support complex numbers?
No. Use gamma(z + 1) if you need the analytic continuation for complex arguments.
How does factorial behave with NaN or Inf inputs?
factorial(NaN) returns NaN. factorial(Inf) returns Inf. Negative infinity propagates to NaN.
Can I keep the output on the GPU?
Yes, either when the provider implements unary_factorial or by passing 'like', gpuArray(...),
which uploads the host-computed result back to the GPU after the fallback path.
Why does factorial return double precision even for integer inputs?
MATLAB defines factorial to return doubles so the result matches downstream functions that expect
floating-point inputs, and RunMat follows the same convention.
How does factorial interact with fusion?
Factorial currently bypasses the fusion planner because it is not built from primitive arithmetic ops. Surrounding element-wise expressions still fuse; factorial runs as an isolated scalar op inside those kernels.
What error message should I expect for unsupported types?
Passing strings, structs, or complex numbers raises factorial: unsupported input type ... so you
can correct the call site quickly.
See Also
Source & Feedback
- The full source code for the implementation of the
factorialfunction is available at:crates/runmat-runtime/src/builtins/math/elementwise/factorial.rs - Found a bug or behavioral difference? Please open an issue with details and a minimal repro.