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/BitVec.h>
10#include <gf2/BitMat.h>
11
12namespace gf2 {
13
29template<unsigned_word Word>
30class BitLU {
31private:
32 BitMat<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:
61 BitLU(const BitMat<Word>& A) : m_lu(A), m_swaps(A.rows(), 0uz), m_rank(A.rows()) {
62 // Only handle square matrices
63 gf2_assert(A.is_square(), "Matrix is {} x {} but it should be square!", A.rows(), A.cols());
64
65 // Iterate through the bit-matrix.
66 auto nr = m_lu.rows();
67 auto nc = m_lu.cols();
68 for (auto j = 0uz; j < nr; ++j) {
69
70 // Initialize this element of the row swap instruction vector.
71 m_swaps[j] = j;
72
73 // Find a non-zero element on or below the diagonal in column -- a pivot.
74 auto p = j;
75 while (p < nr && !m_lu.get(p, j)) ++p;
76
77 // Perhaps no such element exists in this column? If so the matrix is singular!
78 if (p >= nr) {
79 m_rank--;
80 continue;
81 }
82
83 // If necessary, swap the pivot row  into place & record the rows swap instruction
84 if (p != j) {
85 m_lu.swap_rows(j, p);
86 m_swaps[j] = p;
87 }
88
89 // At this point m_lu(j,j) == 1
90 for (auto i = j + 1; i < nr; ++i) {
91 if (m_lu.get(i, j)) {
92 for (auto k = j + 1; k < nc; ++k) {
93 auto tmp = m_lu.get(i, k) ^ m_lu.get(j, k);
94 m_lu.set(i, k, tmp);
95 }
96 }
97 }
98 }
99 }
100
109 constexpr usize rank() const { return m_rank; }
110
112 constexpr bool is_singular() const { return m_rank < m_lu.rows(); }
113
115 constexpr bool determinant() const { return !is_singular(); }
116
118 constexpr const BitMat<Word>& LU() const { return m_lu; }
119
121 constexpr BitMat<Word> L() const { return m_lu.unit_lower(); }
122
124 constexpr BitMat<Word> U() const { return m_lu.upper(); }
125
146 constexpr const std::vector<usize>& swaps() const { return m_swaps; }
147
159 std::vector<usize> permutation_vector() const {
160 auto n = m_swaps.size();
161
162 std::vector<usize> result(n);
163 for (auto i = 0uz; i < n; ++i) result[i] = i;
164 for (auto i = 0uz; i < n; ++i) std::swap(result[m_swaps[i]], result[i]);
165 return result;
166 }
167
171 constexpr void permute(BitMat<Word>& B) const {
172 auto n = m_swaps.size();
173 gf2_assert(B.rows() == n, "Matrix has {} rows but the row-swap instruction vector has {}.", B.rows(), n);
174 for (auto i = 0uz; i < n; ++i)
175 if (m_swaps[i] != i) B.swap_rows(i, m_swaps[i]);
176 }
177
181 constexpr void permute(BitVec<Word>& b) const {
182 auto n = m_swaps.size();
183 gf2_assert(b.size() == n, "Vector has {} elements but the row-swap instruction vector has {}.", b.size(), n);
184 for (auto i = 0uz; i < n; ++i)
185 if (m_swaps[i] != i) b.swap(i, m_swaps[i]);
186 }
187
204 std::optional<BitVec<Word>> operator()(const BitVec<Word>& b) const {
205 auto n = m_lu.rows();
206 gf2_assert(b.size() == n, "RHS b has {} elements but the LHS matrix has {} rows.", b.size(), n);
207
208 // Can we solve this at all?
209 if (is_singular()) return std::nullopt;
210
211 // Make a permuted copy of the the right hand side
212 auto x = b;
213 permute(x);
214
215 // Forward substitution
216 for (auto i = 0uz; i < n; ++i) {
217 for (auto j = 0uz; j < i; ++j)
218 if (m_lu(i, j)) x[i] ^= x[j];
219 }
220
221 // Backward substitution
222 for (auto i = n; i--;) {
223 for (auto j = i + 1; j < n; ++j)
224 if (m_lu(i, j)) x[i] ^= x[j];
225 }
226
227 return x;
228 }
229
248 std::optional<BitMat<Word>> operator()(const BitMat<Word>& B) const {
249 auto n = m_lu.rows();
250 gf2_assert(B.rows() == n, "RHS B has {} rows but the LHS matrix has {} rows.", B.rows(), n);
251
252 // Can we solve this at all?
253 if (is_singular()) return std::nullopt;
254
255 // Make a permuted copy of the the right hand side
256 auto X = B;
257 permute(X);
258
259 // Solve for each column
260 for (auto j = 0uz; j < n; ++j) {
261
262 // Forward substitution
263 for (auto i = 0uz; i < n; ++i) {
264 for (auto k = 0uz; k < i; ++k)
265 if (m_lu(i, k)) X(i, j) ^= X(k, j);
266 }
267
268 // Backward substitution
269 for (auto i = n; i--;) {
270 for (auto k = i + 1; k < n; ++k)
271 if (m_lu(i, k)) X(i, j) ^= X(k, j);
272 }
273 }
274
275 return X;
276 }
277
288 std::optional<BitMat<Word>> inverse() const {
289 // We just solve the system A.A_inv = I for A_inv
290 return operator()(BitMat<Word>::identity(m_lu.rows()));
291 }
292};
293} // namespace gf2
Matrices over over GF(2) – bit-matrices. See the BitMat page for more details.
Vectors over GF(2) with compactly stored bit-elements in a standard vector of primitive unsigned word...
#define gf2_assert(cond,...)
A confirmation macro that checks a boolean condition cond. On failure, the confirmation prints an e...
Definition assert.h:98
constexpr void permute(BitVec< Word > &b) const
Permute the rows of the input vector b in-place using our row-swap instruction vector.
Definition BitLU.h:181
std::optional< BitVec< Word > > operator()(const BitVec< Word > &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:204
constexpr void permute(BitMat< Word > &B) const
Permutes the rows of the input matrix B in-place using our row-swap instruction vector.
Definition BitLU.h:171
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:115
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:159
BitLU(const BitMat< Word > &A)
Constructs the LU decomposition object for a square matrix A.
Definition BitLU.h:61
constexpr usize rank() const
Returns the rank of the matrix.
Definition BitLU.h:109
std::optional< BitMat< Word > > operator()(const BitMat< Word > &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:248
constexpr const BitMat< Word > & LU() const
Read-only access to the LU form of the bit-matrix where A -> [L\U].
Definition BitLU.h:118
constexpr BitMat< Word > U() const
Returns the upper triangular matrix U in the LU decomposition.
Definition BitLU.h:124
constexpr const std::vector< usize > & swaps() const
Returns a reference to the row swap instructions in LAPACK form.
Definition BitLU.h:146
constexpr bool is_singular() const
Returns true if the underlying matrix is singular (i.e. rank deficient).
Definition BitLU.h:112
std::optional< BitMat< 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:288
constexpr BitMat< Word > L() const
Returns the unit lower triangular matrix L in the LU decomposition.
Definition BitLU.h:121
A dynamically-sized matrix over GF(2) stored as a vector of bit-vectors representing the rows of the ...
Definition BitMat.h:32
constexpr BitMat upper() const
Returns an independent clone of the upper triangular part of the bit-matrix.
Definition BitMat.h:1464
constexpr bool is_square() const
Returns true if this a square bit-matrix? Note that empty bit-matrices are NOT considered square.
Definition BitMat.h:644
constexpr BitMat unit_lower() const
Returns an independent clone of the unit lower triangular part of the bit-matrix.
Definition BitMat.h:1522
constexpr usize cols() const
Returns the number of columns in the bit-matrix.
Definition BitMat.h:621
constexpr void swap_rows(usize i, usize j)
Swaps rows i and j of the bit-matrix.
Definition BitMat.h:1558
static constexpr BitMat identity(usize m)
Factory method to create the m x m identity bit-matrix.
Definition BitMat.h:376
constexpr usize rows() const
Returns the number of rows in the bit-matrix.
Definition BitMat.h:618
constexpr auto swap(usize i0, usize i1)
Swaps the bits in the bit-store at indices i0 and i1 and returns this for chaining.
Definition BitStore.h:258
A dynamically-sized vector over GF(2) with bit elements compactly stored in a standard vector of prim...
Definition BitVec.h:37
constexpr usize size() const
Returns the number of bit-elements in the bit-vector.
Definition BitVec.h:64
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_word.h:41