matrix.h
A small dense matrix, and the linear solve that is usually why somebody wanted one.
#include <sonore/matrix.h>- 1type
- Guides: Getting started, MIDI and MPE
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.