View all functions

CategoryMath: Elementwise
GPUYes

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 to Inf, matching MATLAB’s overflow handling in double precision.
  • factorial(0) and factorial(-0.0) both return 1, in accordance with the definition 0! = 1.
  • Results are real doubles. Passing 'like', prototype lets 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_factorial hook. 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 factorial on 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

gamma, power, prod, permute

Source & Feedback