Search guides and the APICtrl K
  1. API reference
  2. DSP

matrix.h

A small dense matrix, and the linear solve that is usually why somebody wanted one.

#include <sonore/matrix.h>
On this page

Design notes

The places audio actually needs one are few and specific: an ambisonic decoder or a matrix mixer (a product per block), linear prediction (a Toeplitz system from an autocorrelation), a least-squares fit at prepare() -- an EQ curve matched to a measurement, a waveshaper fitted to a table -- and the state-space form of a circuit. All of them are small, dense and square or nearly so, which is what this is built for. It is not a BLAS.

Two decisions shape it:

ALLOCATION. The storage is a std::vector sized at construction, and every
operation that RETURNS a matrix allocates its result. That is the
convenient form for prepare() and for tests. For the audio thread there
is a second form of each operation that matters -- multiply() into an
existing result, solveInPlace(), the compound assignments -- and none of
those allocates. A matrix sized up front can be used per block; one built
per block is the mistake a general matrix type invites, and the test
counts allocations through the in-place forms to hold that line.

PIVOTING. The solve is Gaussian elimination with PARTIAL pivoting: at each
column the row with the largest magnitude is swapped up before it is
divided by. Without it, [[0 1][1 1]] cannot be solved at all (a zero on
the diagonal) and a matrix that is merely close to that loses every
digit. With it, the error is bounded by the matrix's conditioning rather
than by the order its rows happened to arrive in.

Storage is row-major: element (r, c) is data[r * columns + c], so a row is contiguous and getRow() is a pointer, not a copy.

Types 1

template <typename T> class Matrix

A small dense row-major matrix of float, double or long double, with Gaussian elimination (partial pivoting) behind solve(), inverse() and determinant(). It mirrors the reference's dsp::Matrix and keeps its accessor names.

Owns its storage, a std::vector sized at construction (see the file comment). Anything that returns a Matrix allocates, so build matrices in prepare() or on a message thread; on the audio thread use only the forms that write into existing storage -- multiply(a, b, out), solveInPlace(), the compound operators and element access. A shape mismatch is never a read past the end: it gives a 0 x 0 result, a false, or a target left as it was. Not synchronised: one thread at a time.

↑↓ to move↵ to openEvery public name in the headers, and every guide