RunMat
GitHub

filter — Apply IIR/FIR digital filters in MATLAB and RunMat.

filter(b, a, X) applies a causal digital filter defined by numerator coefficients b and denominator coefficients a. By default, filtering runs along the first non-singleton dimension, and coefficients are normalized internally so a(1) is 1. Optional initial conditions and explicit dimension selection follow MATLAB semantics.

Syntax

y = filter(b, a, x)
y = filter(b, a, x, zi)
y = filter(b, a, x, zi, dim)
[y, zf] = filter(b, a, x)
[y, zf] = filter(b, a, x, zi)
[y, zf] = filter(b, a, x, zi, dim)

Inputs

NameTypeRequiredDefaultDescription
bAnyYesNumerator coefficient vector.
aAnyYesDenominator coefficient vector.
xAnyYesSignal values to filter.
ziAnyNo[]Initial filter state (use [] for default zero state).
dimNumericScalarNofirst non-singleton dimensionDimension to operate along.

Returns

NameTypeDescription
yNumericArrayFiltered signal output.
zfNumericArrayFinal filter state for warm-starting a subsequent call.

Returned values from filter depend on how many outputs the caller requests.

Errors

IdentifierWhenMessage
RunMat:filter:ArgCountMore than five input arguments are provided.filter: expected between three and five input arguments
RunMat:filter:InvalidDimensiondim is missing, non-numeric, non-integer, or less than one.filter: dimension must be numeric and >= 1
RunMat:filter:EmptyDenominatorDenominator coefficient vector is empty.filter: denominator coefficients cannot be empty

How filter works

  • filter(b, a, X) applies the filter along the first non-singleton dimension of X (column-wise for matrices).
  • The numerator b and denominator a must be non-empty vectors. a(1) must be non-zero; the runtime divides both coefficient vectors by a(1) automatically.
  • Optional initial conditions zi must have the same size as the output zf (the dimension being filtered is replaced by max(numel(b), numel(a)) - 1). Use [] to indicate zero initial state.
  • filter(b, a, X, zi, dim) processes X along dimension dim. Dimensions beyond ndims(X) are treated as length-one axes, exactly as in MATLAB.
  • Complex coefficients or inputs are supported; results follow MATLAB semantics for real/imaginary propagation.
  • The function returns a single output y by default. Request two outputs ([y, zf] = filter(...)) to obtain the final internal states zf.

Does RunMat run filter on the GPU?

The input signal already resides on the GPU (for example, via gpuArray) and all operands are real-valued.

The active provider implements iir_filter (both the in-process provider and the WGPU backend do).

Under those conditions the entire evaluation—including final-state propagation—stays on the device. If the hook is absent, or if any operand is complex, RunMat transparently gathers to the host, evaluates the filter with the scalar reference implementation, and returns MATLAB-compatible results. Auto-offload and fusion residency reuse the same hook, so high-level code does not need to differentiate between CPU and GPU execution.

Examples

Smoothing a signal with an FIR moving-average filter

b = ones(1, 3) / 3;
a = 1;
x = [1 5 2 0 3];
y = filter(b, a, x)

Expected output:

y =
    0.3333    2.0000    2.6667    2.3333    1.6667

Applying a first-order IIR low-pass filter

alpha = 0.8;
b = 1 - alpha;
a = [1 -alpha];
imp = [1 zeros(1, 4)];
y = filter(b, a, imp)

Expected output:

y =
    0.2000    0.1600    0.1280    0.1024    0.0819

Continuing a filtered stream with explicit initial conditions

b = ones(1, 3) / 3;
a = 1;
x1 = [1 5 2];
[y1, zf] = filter(b, a, x1);   % First chunk

x2 = [0 3];
[y2, zf2] = filter(b, a, x2, zf);  % Resume with stored state

Expected output:

y1 = [0.3333 2.0000 2.6667]
zf  = [2.3333 0.6667]

y2 = [2.3333 1.6667]
zf2 = [1.0000 1.0000]

Filtering along matrix rows (dimension 2)

X = [1  2  3  4;
     0  1  0  1];
b = [1 -1];   % simple differentiator
a = 1;
Y = filter(b, a, X, [], 2)

Expected output:

Y =
     1     1     1     1
     0     1    -1     1

Filtering complex-valued data

b = [1 1i];
a = 1;
t = 0:3;
x = exp(1i * pi/4 * t);
y = filter(b, a, x)

Expected output:

y =
   1.0000 + 0.0000i   0.7071 + 1.7071i  -0.7071 + 1.7071i  -1.7071 + 0.7071i

Executing a real filter on the GPU

g = gpuArray([1 5 2 0 3]);
b = ones(1, 3) / 3;
a = 1;
[y_gpu, zf_gpu] = filter(b, a, g);
y = gather(y_gpu)

Expected output:

y =
    0.3333    2.0000    2.6667    2.3333    1.6667

Using filter with coding agents

Open a RunMat example with live inputs, then ask the agent to explain how filter changes the result.

Run a small filter example, explain the result, then change one input and compare the output.

FAQ

What happens if a(1) is not 1.0?

RunMat (like MATLAB) divides every coefficient in a and b by a(1) internally so that a(1) becomes 1. You only need to ensure a(1) is non-zero.

How large should zi be?

zi must have the same size as zf (the returned final state). Replace the filtered dimension with max(numel(b), numel(a)) - 1; all other dimensions match X. Use [] for a zero state.

Can I filter along a dimension greater than ndims(X)?

Yes. Just like MATLAB, RunMat treats missing higher dimensions as length-one axes. filter(b, a, X, [], 5) is valid even if X is a vector.

Does filter support complex coefficients or signals?

Absolutely. The host implementation handles complex arithmetic exactly. GPU acceleration is currently limited to real-valued filters; complex inputs fall back to the CPU automatically.

Do I need to initialise the GPU path manually?

No. If the signal is a gpuArray value and the active provider supports iir_filter, RunMat keeps the entire computation on the device. Otherwise, the runtime gathers operands to the host, ensuring MATLAB-compatible results without extra user code.

What shape does zf have?

zf matches zi (or the default zero state). The filtered dimension is replaced by max(numel(b), numel(a)) - 1; other dimensions mirror the input.

How are empty signals handled?

When X is empty, y is empty and zf equals the supplied zi (or zeros). No arithmetic is performed, matching MATLAB.

Are logical and integer inputs supported?

Yes. They are promoted to double precision before filtering, exactly as in MATLAB.

How do I resume filtering a long stream chunk-by-chunk?

Call [y, zf] = filter(...) on each chunk and pass zf as the fourth argument for the next chunk. The example above shows the pattern.

Can I accelerate filtering with the planner’s auto-offload?

The planner leverages the same provider hook under the hood. As long as the operands are real and the provider implements iir_filter, auto-offload keeps the filter on the GPU.

Signal

blackman · conv · conv2 · deconv · hamming · hann · sawtooth · sinc · square

Elementwise

abs · angle · complex · conj · double · exp · expm1 · factorial · gamma · hypot · imag · ldivide · log · log10 · log1p · log2 · minus · nextpow2 · plus · pow2 · power · rdivide · real · sign · single · sqrt · times

Trigonometry

acos · acosh · asin · asinh · atan · atan2 · atanh · cos · cosd · cosh · deg2rad · rad2deg · sin · sind · sinh · tan · tand · tanh

Reduction

all · any · cummax · cummin · cumprod · cumsum · cumtrapz · diff · gradient · max · mean · median · min · nnz · prod · std · sum · trapz · var

Rounding

ceil · fix · floor · mod · rem · round

Factor

chol · eig · lu · qr · svd

Solve

cond · det · inv · linsolve · norm · pinv · rank · rcond

Fft

fft · fft2 · fftshift · ifft · ifft2 · ifftshift

Interpolation

interp1 · interp2 · pchip · ppval · spline

Ode

ode15s · ode23 · ode45

Open-source implementation

Unlike proprietary runtimes, every RunMat function is open-source. Read exactly how filter is executed, line by line, in Rust.

About RunMat

RunMat is an open-source runtime that executes MATLAB-syntax code blazing on any GPU. It is licensed under the Apache 2.0 license.

  • RunMat automatically optimizes your math for GPU execution on Apple, Nvidia, and AMD hardware. No code changes needed. Simulations that took hours now take minutes.
  • Start running code in seconds. RunMat runs in the browser, on the desktop, or from the CLI. No license server, no IT ticket.

Getting started · Benchmarks · Pricing

Download RunMat

Download RunMat for full performance, or use RunMat in your browser for zero setup.