Dense n × m matrices over R, backed by a flat row-major buffer of the
n * m entries: entry (i, j) is stored at flat index i * m + j. Opaque
one-field structure; consumers go through rows/getRow/ofRows/ofFn and
M[i] / M[(i,j)], never the data projection, so the representation can
change.
Implementation detail — the flat row-major backing buffer. Use
Matrix.rows/getRow, never this projection.
Instances For
Equations
- Hex.instBEqMatrix = { beq := Hex.instBEqMatrix.beq }
Dot product of two vectors.
This List.finRange form is the reference definition the entry lemmas reason
about; crucially it kernel-reduces, so #guard/decide checks over
dotProduct (e.g. memLattice membership) stay evaluable — core Fin.foldl
does not yet reduce in the kernel. Compiled code therefore uses the
allocation-free Vector.dotProductImpl, selected by
Vector.dotProduct_eq_impl, while logical evaluation retains the
list-based form.
Equations
- u.dotProduct v = List.foldl (fun (acc : R) (i : Fin n) => acc + u[i] * v[i]) 0 (List.finRange n)
Instances For
Allocation-free implementation of dotProduct: a Fin.foldl loop that never
materializes the List.finRange n index list. Swapped in for compiled code by the
@[csimp] lemma; dotProduct remains the reference form for proofs.
Instances For
The i-th row of a matrix, materialized from the flat buffer. This copies the
m contiguous entries of row i; it is the computable row accessor compiled code
uses (single entries go through M[(i, j)], which does not materialize a row).
Instances For
Row access M[i] for i : Fin n. Deliberately noncomputable: with the
flat (Vector R (n*m)) representation, materializing a whole row just to read it
— and especially M[i][j] to read one entry — is the wrong cost model. This
instance exists only so proofs may write M[i] / M[i][j]; executable code
must use the computable getRow for rows and M[(i, j)] (O(1)) for single
entries. Any compiled definition that reaches for M[i] will fail to compile,
which is the intended guard.
Equations
- Hex.Matrix.instGetElemFinVectorTrue = { getElem := fun (M : Hex.Matrix R n m) (i : Fin n) (x : True) => M.getRow i }
Row access by a Nat index. Also noncomputable; see the Fin n instance.
Equations
- Hex.Matrix.instGetElemNatVectorLt = { getElem := fun (M : Hex.Matrix R n m) (i : Nat) (h : i < n) => M.getRow ⟨i, h⟩ }
The rows of a matrix as a vector of row-vectors, materialized from the flat
buffer. The only sanctioned way to observe the full row data; O(n * m).
Equations
- M.rows = Vector.ofFn fun (i : Fin n) => M.getRow i
Instances For
Nat-pair entry access, normalized to the row lookup (concrete-index form).
The statement observes rows, not the backing buffer, so it is representation-
independent; the flat read behind it is getElem_pair_data below.
Modification of row i. The matrix is consumed; the row is read out once
(a borrowed read into a fresh m-vector, before the buffer is written), f is
applied, and the result is written back through writeRow, in place when the
runtime sees the buffer uniquely referenced at the write.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Map a function over every row. The row width may change, so this materializes the rows, maps, and reflattens.
Equations
- M.mapRows f = Hex.Matrix.ofRows (Vector.map f M.rows)
Instances For
A left fold of per-index sets at injectively-indexed positions over a
Nodup list writes val r at position idx r for every member r.
List.finRange k has no repeated indices (core-only proof; the Batteries
nodup_finRange is outside this Mathlib-free module's import closure).
In-place per-entry update of row i: entry t becomes g t applied to its
old value, written directly into the flat buffer with no row
materialization. This is the per-entry engine the elementary row operations
(rowScale, rowAdd) and the Bareiss row elimination build on: unlike
modifyRow, whose whole-row function forces a row copy-out and copy-back, each
entry here is a single in-place Vector.modify of the backing buffer when the
matrix is uniquely referenced.
Equations
Instances For
Entrywise read of modifyEntries: row i gets g applied entrywise, every
other row is unchanged.
The all-zero matrix.
Equations
- Hex.Matrix.zero n m = Hex.Matrix.ofFn fun (x : Fin n) (x_1 : Fin m) => 0
Instances For
Equations
- Hex.Matrix.instZeroOfOfNatOfNatNat = { zero := Hex.Matrix.zero n m }
Every row of the zero matrix is the zero vector.
Every column of the zero matrix is the zero vector.
The identity matrix.
Equations
- Hex.Matrix.identity n = Hex.Matrix.ofFn fun (i j : Fin n) => if i = j then 1 else 0
Instances For
Equations
- Hex.Matrix.instAdd = { add := Hex.Matrix.add }
Equations
- Hex.Matrix.instNeg = { neg := Hex.Matrix.neg }
Equations
- Hex.Matrix.instSub = { sub := Hex.Matrix.sub }
Multiply two matrices, using the naive algorithm.
This reads each column col N j and is the reference definition the entry
lemmas reason about. Compiled code uses the implementation below, which
transposes N once so each column is materialized a single time instead of
being rebuilt for every row of M; Hex.Matrix.mul_eq_impl selects
Hex.Matrix.mulImpl for compiled code.
Strassen-Winograd multiplication, with a customizable base kernel for small
sizes, is available as Hex.Matrix.mulStrassen, with equality proved by
Hex.Matrix.mulStrassen_eq_mul. It cannot replace this definition
through @[csimp]: the Winograd schedule subtracts blocks and therefore needs
[Sub R], while naive multiplication does not. Callers over a ring opt into
the Strassen-Winograd algorithm explicitly.
Equations
- M.mul N = Hex.Matrix.ofFn fun (i : Fin n) (j : Fin k) => (M.row i).dotProduct (N.col j)
Instances For
Cache-friendly implementation of Hex.Matrix.mul: transpose N once (turning its columns
into contiguous rows), materialize the transposed rows once, then take row-by-row
dot products, so each column is built a single time rather than once per row of
M. Swapped in for compiled code by the @[csimp] lemma; mul stays the
column-based reference form for proofs.
Equations
- M.mulImpl N = Hex.Matrix.ofRows (Vector.ofFn fun (i : Fin n) => have ri := M.getRow i; Vector.ofFn fun (j : Fin k) => ri.dotProduct N.transpose.rows[j])
Instances For
Homogeneous multiplication on square matrices, agreeing with the
heterogeneous HMul. This is the Mul instance Mathlib's Semiring/Ring
structures build on; see HexMatrixMathlib.
Equations
Multiply a row vector by a matrix, v * M. Equal to transpose M * v; the
j-th entry is ∑ i, M[i][j] * v[i], the combination of the rows of M with
coefficients v.
Equations
- Hex.Matrix.vecMul v M = M.transpose * v
Instances For
The identity matrix is its own transpose.
Indexed row map: replace row i by f i (row i) for every i, threading
M through a Fin.foldl of per-row modifyRows. No intermediate index list is
allocated. The whole-row function forces each visited row to be materialized and
written back (see modifyRow); per-entry updates should prefer the
copy-free modifyEntries / setCol / modifyCol.
Equations
- M.mapRowsIdx f = Fin.foldl n (fun (M : Hex.Matrix R n m) (i : Fin n) => M.modifyRow (↑i) (f i)) M
Instances For
The row data of mapRowsIdx is the corresponding Fin.foldl of Vector.modifys.
Row r of mapRowsIdx M f is f r applied to the original row r.
Replace column dst of M with the entry function v. In place: one
single-entry Vector.set of the flat buffer per row (O(n) writes total),
reusing the backing store when M is uniquely referenced, rather than
materializing any row or rebuilding the matrix.
Equations
Instances For
Transposing a row replacement is a column replacement on the transpose:
setRow on M corresponds to setCol on Mᵀ. This is the bridge the
determinant row laws route through to reuse the column laws.
In-place per-entry column modify: replace each entry M[i][dst] by
g i M[i][dst], every other column unchanged. In place: one single-entry
Vector.modify of the flat buffer per row, analogous to setCol.
Equations
Instances For
Scalar action on a matrix, delegated to the flat backing buffer. The single
sanctioned SMul instance for matrices: the Mathlib bridge layer reuses it rather
than declaring its own, so there is no overlapping instance.
Equations
- Hex.Matrix.instSMul = { smul := fun (c : S) (M : Hex.Matrix R n m) => { data := c • M.data } }