GF2++
Loading...
Searching...
No Matches
BitLU.h
Go to the documentation of this file.
1#pragma once
2// SPDX-FileCopyrightText: 2025 Nessan Fitzmaurice <nzznfitz+gh@icloud.com>
3// SPDX-License-Identifier: MIT
4
8
9#include <gf2/BitMatrix.h>
10
11namespace gf2 {
12
29template<Unsigned Word>
30class BitLU {
31private:
32 BitMatrix<Word> m_lu; // The LU decomposition stored in a single bit-matrix.
33 std::vector<usize> m_swaps; // The list of row swap instructions (a permutation in LAPACK format).
34 usize m_rank; // The rank of the underlying matrix.
35
36public:
62 BitLU(BitMatrix<Word> const& A) : m_lu(A), m_swaps(A.rows(), 0uz), m_rank(A.rows()) {
63 // Only handle square matrices
64 gf2_assert(A.is_square(), "Matrix is {} x {} but it should be square!", A.rows(), A.cols());
65
66 // Iterate through the bit-matrix.
67 auto nr = m_lu.rows();
68 auto nc = m_lu.cols();
69 for (auto j = 0uz; j < nr; ++j) {
70
71 // Initialize this element of the row swap instruction vector.
72 m_swaps[j] = j;
73
74 // Find a non-zero element on or below the diagonal in column -- a pivot.
75 auto p = j;
76 while (p < nr && !m_lu.get(p, j)) ++p;
77
78 // Perhaps no such element exists in this column? If so the matrix is singular!
79 if (p >= nr) {
80 m_rank--;
81 continue;
82 }
83
84 // If necessary, swap the pivot row  into place & record the rows swap instruction
85 if (p != j) {
86 m_lu.swap_rows(j, p);
87 m_swaps[j] = p;
88 }
89
90 // At this point m_lu(j,j) == 1
91 for (auto i = j + 1; i < nr; ++i) {
92 if (m_lu.get(i, j)) {
93 for (auto k = j + 1; k < nc; ++k) {
94 auto tmp = m_lu.get(i, k) ^ m_lu.get(j, k);
95 m_lu.set(i, k, tmp);
96 }
97 }
98 }
99 }
100 }
101
110 constexpr usize rank() const { return m_rank; }
111
113 constexpr bool is_singular() const { return m_rank < m_lu.rows(); }
114
116 constexpr bool determinant() const { return !is_singular(); }
117
119 constexpr const BitMatrix<Word>& LU() const { return m_lu; }
120
122 constexpr BitMatrix<Word> L() const { return m_lu.unit_lower(); }
123
125 constexpr BitMatrix<Word> U() const { return m_lu.upper(); }
126
147 constexpr const std::vector<usize>& swaps() const { return m_swaps; }
148
160 std::vector<usize> permutation_vector() const {
161 auto n = m_swaps.size();
162
163 std::vector<usize> result(n);
164 for (auto i = 0uz; i < n; ++i) result[i] = i;
165 for (auto i = 0uz; i < n; ++i) std::swap(result[m_swaps[i]], result[i]);
166 return result;
167 }
168
173 constexpr void permute(BitMatrix<Word>& B) const {
174 auto n = m_swaps.size();
175 gf2_assert(B.rows() == n, "Matrix has {} rows but the row-swap instruction vector has {}.", B.rows(), n);
176 for (auto i = 0uz; i < n; ++i)
177 if (m_swaps[i] != i) B.swap_rows(i, m_swaps[i]);
178 }
179
184 template<BitStore Store>
185 requires(std::same_as<typename Store::word_type, Word>)
186 constexpr void permute(Store& b) const {
187 auto n = m_swaps.size();
188 gf2_assert(b.size() == n, "Vector has {} elements but the row-swap instruction vector has {}.", b.size(), n);
189 for (auto i = 0uz; i < n; ++i)
190 if (m_swaps[i] != i) b.swap(i, m_swaps[i]);
191 }
192
210 template<BitStore Store>
211 requires(std::same_as<typename Store::word_type, Word>)
212 std::optional<BitVector<Word>> operator()(Store const& b) const {
213 auto n = m_lu.rows();
214 gf2_assert(b.size() == n, "RHS b has {} elements but the LHS matrix has {} rows.", b.size(), n);
215
216 // Can we solve this at all?
217 if (is_singular()) return std::nullopt;
218
219 // Make a permuted copy of the the right hand side
220 auto x = b;
221 permute(x);
222
223 // Forward substitution
224 for (auto i = 0uz; i < n; ++i) {
225 for (auto j = 0uz; j < i; ++j)
226 if (m_lu(i, j)) x[i] ^= x[j];
227 }
228
229 // Backward substitution
230 for (auto i = n; i--;) {
231 for (auto j = i + 1; j < n; ++j)
232 if (m_lu(i, j)) x[i] ^= x[j];
233 }
234
235 return x;
236 }
237
256 std::optional<BitMatrix<Word>> operator()(BitMatrix<Word> const& B) const {
257 auto n = m_lu.rows();
258 gf2_assert(B.rows() == n, "RHS B has {} rows but the LHS matrix has {} rows.", B.rows(), n);
259
260 // Can we solve this at all?
261 if (is_singular()) return std::nullopt;
262
263 // Make a permuted copy of the the right hand side
264 auto X = B;
265 permute(X);
266
267 // Solve for each column
268 for (auto j = 0uz; j < n; ++j) {
269
270 // Forward substitution
271 for (auto i = 0uz; i < n; ++i) {
272 for (auto k = 0uz; k < i; ++k)
273 if (m_lu(i, k)) X(i, j) ^= X(k, j);
274 }
275
276 // Backward substitution
277 for (auto i = n; i--;) {
278 for (auto k = i + 1; k < n; ++k)
279 if (m_lu(i, k)) X(i, j) ^= X(k, j);
280 }
281 }
282
283 return X;
284 }
285
296 std::optional<BitMatrix<Word>> inverse() const {
297 // We just solve the system A.A_inv = I for A_inv
298 return operator()(BitMatrix<Word>::identity(m_lu.rows()));
299 }
300};
301} // namespace gf2
Matrices over over GF(2) – bit-matrices. See the BitMatrix page for more details.
#define gf2_assert(cond,...)
A confirmation macro that checks a boolean condition cond. On failure, the confirmation prints an e...
Definition assert.h:98
std::optional< BitVector< Word > > operator()(Store const &b) const
Solves the linear system A.x_for = b for any b where A is the matrix used to construct the BitLU obje...
Definition BitLU.h:212
constexpr bool determinant() const
Returns the value of the determinant of the underlying matrix as true or false for 1 or 0.
Definition BitLU.h:116
std::vector< usize > permutation_vector() const
Returns the permutation matrix as a vector of showing the index positions of the non-zero entries.
Definition BitLU.h:160
constexpr const BitMatrix< Word > & LU() const
Read-only access to the LU form of the bit-matrix where A -> [L\U].
Definition BitLU.h:119
constexpr void permute(BitMatrix< Word > &B) const
Permutes the rows of the input matrix B in-place using our row-swap instruction vector.
Definition BitLU.h:173
constexpr void permute(Store &b) const
Permute the rows of the input vector b in-place using our row-swap instruction vector.
Definition BitLU.h:186
std::optional< BitMatrix< Word > > inverse() const
Returns the inverse of the matrix A as a full independent bit-matrix or std::nullopt if the matrix is...
Definition BitLU.h:296
constexpr usize rank() const
Returns the rank of the matrix.
Definition BitLU.h:110
BitLU(BitMatrix< Word > const &A)
Constructs the LU decomposition object for a square matrix A.
Definition BitLU.h:62
constexpr const std::vector< usize > & swaps() const
Returns a reference to the row swap instructions in LAPACK form.
Definition BitLU.h:147
constexpr BitMatrix< Word > U() const
Returns the upper triangular matrix U in the LU decomposition.
Definition BitLU.h:125
constexpr bool is_singular() const
Returns true if the underlying matrix is singular (i.e. rank deficient).
Definition BitLU.h:113
constexpr BitMatrix< Word > L() const
Returns the unit lower triangular matrix L in the LU decomposition.
Definition BitLU.h:122
std::optional< BitMatrix< Word > > operator()(BitMatrix< Word > const &B) const
Solves the linear system A.X_for = B for any B where A is the matrix used to construct the BitLU obje...
Definition BitLU.h:256
A dynamically-sized matrix over GF(2) stored as a vector of bit-vectors representing the rows of the ...
Definition BitMatrix.h:33
constexpr void swap_rows(usize i, usize j)
Swaps rows i and j of the bit-matrix.
Definition BitMatrix.h:1599
constexpr usize rows() const
Returns the number of rows in the bit-matrix.
Definition BitMatrix.h:629
constexpr BitMatrix upper() const
Returns an independent clone of the upper triangular part of the bit-matrix.
Definition BitMatrix.h:1504
constexpr usize cols() const
Returns the number of columns in the bit-matrix.
Definition BitMatrix.h:632
constexpr bool is_square() const
Returns true if this a square bit-matrix? Note that empty bit-matrices are NOT considered square.
Definition BitMatrix.h:655
constexpr BitMatrix unit_lower() const
Returns an independent clone of the unit lower triangular part of the bit-matrix.
Definition BitMatrix.h:1562
static constexpr BitMatrix identity(usize m)
Factory method to create the m x m identity bit-matrix.
Definition BitMatrix.h:383
A dynamically-sized vector over GF(2) with bit elements compactly stored in a standard vector of prim...
Definition BitVector.h:23
The namespace for the gf2 library.
Definition assert.h:119
std::size_t usize
Word type alias for the platform's "native"-sized unsigned integer.
Definition Unsigned.h:42