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/BitMat.h>
10
11namespace gf2 {
12
28template<Unsigned Word>
29class BitLU {
30private:
31 BitMat<Word> m_lu; // The LU decomposition stored in a single bit-matrix.
32 std::vector<usize> m_swaps; // The list of row swap instructions (a permutation in LAPACK format).
33 usize m_rank; // The rank of the underlying matrix.
34
35public:
60 BitLU(BitMat<Word> const& A) : m_lu(A), m_swaps(A.rows(), 0uz), m_rank(A.rows()) {
61 // Only handle square matrices
62 gf2_assert(A.is_square(), "Matrix is {} x {} but it should be square!", A.rows(), A.cols());
63
64 // Iterate through the bit-matrix.
65 auto nr = m_lu.rows();
66 auto nc = m_lu.cols();
67 for (auto j = 0uz; j < nr; ++j) {
68
69 // Initialize this element of the row swap instruction vector.
70 m_swaps[j] = j;
71
72 // Find a non-zero element on or below the diagonal in column -- a pivot.
73 auto p = j;
74 while (p < nr && !m_lu.get(p, j)) ++p;
75
76 // Perhaps no such element exists in this column? If so the matrix is singular!
77 if (p >= nr) {
78 m_rank--;
79 continue;
80 }
81
82 // If necessary, swap the pivot row  into place & record the rows swap instruction
83 if (p != j) {
84 m_lu.swap_rows(j, p);
85 m_swaps[j] = p;
86 }
87
88 // At this point m_lu(j,j) == 1
89 for (auto i = j + 1; i < nr; ++i) {
90 if (m_lu.get(i, j)) {
91 for (auto k = j + 1; k < nc; ++k) {
92 auto tmp = m_lu.get(i, k) ^ m_lu.get(j, k);
93 m_lu.set(i, k, tmp);
94 }
95 }
96 }
97 }
98 }
99
108 constexpr usize rank() const { return m_rank; }
109
111 constexpr bool is_singular() const { return m_rank < m_lu.rows(); }
112
114 constexpr bool determinant() const { return !is_singular(); }
115
117 constexpr const BitMat<Word>& LU() const { return m_lu; }
118
120 constexpr BitMat<Word> L() const { return m_lu.unit_lower(); }
121
123 constexpr BitMat<Word> U() const { return m_lu.upper(); }
124
145 constexpr const std::vector<usize>& swaps() const { return m_swaps; }
146
158 std::vector<usize> permutation_vector() const {
159 auto n = m_swaps.size();
160
161 std::vector<usize> result(n);
162 for (auto i = 0uz; i < n; ++i) result[i] = i;
163 for (auto i = 0uz; i < n; ++i) std::swap(result[m_swaps[i]], result[i]);
164 return result;
165 }
166
170 constexpr void permute(BitMat<Word>& B) const {
171 auto n = m_swaps.size();
172 gf2_assert(B.rows() == n, "Matrix has {} rows but the row-swap instruction vector has {}.", B.rows(), n);
173 for (auto i = 0uz; i < n; ++i)
174 if (m_swaps[i] != i) B.swap_rows(i, m_swaps[i]);
175 }
176
180 template<BitStore Store>
181 requires(std::same_as<typename Store::word_type, Word>)
182 constexpr void permute(Store& b) const {
183 auto n = m_swaps.size();
184 gf2_assert(b.size() == n, "Vector has {} elements but the row-swap instruction vector has {}.", b.size(), n);
185 for (auto i = 0uz; i < n; ++i)
186 if (m_swaps[i] != i) b.swap(i, m_swaps[i]);
187 }
188
205 template<BitStore Store>
206 requires(std::same_as<typename Store::word_type, Word>)
207 std::optional<BitVec<Word>> operator()(Store const& b) const {
208 auto n = m_lu.rows();
209 gf2_assert(b.size() == n, "RHS b has {} elements but the LHS matrix has {} rows.", b.size(), n);
210
211 // Can we solve this at all?
212 if (is_singular()) return std::nullopt;
213
214 // Make a permuted copy of the the right hand side
215 auto x = b;
216 permute(x);
217
218 // Forward substitution
219 for (auto i = 0uz; i < n; ++i) {
220 for (auto j = 0uz; j < i; ++j)
221 if (m_lu(i, j)) x[i] ^= x[j];
222 }
223
224 // Backward substitution
225 for (auto i = n; i--;) {
226 for (auto j = i + 1; j < n; ++j)
227 if (m_lu(i, j)) x[i] ^= x[j];
228 }
229
230 return x;
231 }
232
251 std::optional<BitMat<Word>> operator()(BitMat<Word> const& B) const {
252 auto n = m_lu.rows();
253 gf2_assert(B.rows() == n, "RHS B has {} rows but the LHS matrix has {} rows.", B.rows(), n);
254
255 // Can we solve this at all?
256 if (is_singular()) return std::nullopt;
257
258 // Make a permuted copy of the the right hand side
259 auto X = B;
260 permute(X);
261
262 // Solve for each column
263 for (auto j = 0uz; j < n; ++j) {
264
265 // Forward substitution
266 for (auto i = 0uz; i < n; ++i) {
267 for (auto k = 0uz; k < i; ++k)
268 if (m_lu(i, k)) X(i, j) ^= X(k, j);
269 }
270
271 // Backward substitution
272 for (auto i = n; i--;) {
273 for (auto k = i + 1; k < n; ++k)
274 if (m_lu(i, k)) X(i, j) ^= X(k, j);
275 }
276 }
277
278 return X;
279 }
280
291 std::optional<BitMat<Word>> inverse() const {
292 // We just solve the system A.A_inv = I for A_inv
293 return operator()(BitMat<Word>::identity(m_lu.rows()));
294 }
295};
296} // namespace gf2
Matrices over over GF(2) – bit-matrices. See the BitMat 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
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:170
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:114
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:158
std::optional< BitMat< Word > > operator()(BitMat< 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:251
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:182
constexpr usize rank() const
Returns the rank of the matrix.
Definition BitLU.h:108
constexpr const BitMat< Word > & LU() const
Read-only access to the LU form of the bit-matrix where A -> [L\U].
Definition BitLU.h:117
constexpr BitMat< Word > U() const
Returns the upper triangular matrix U in the LU decomposition.
Definition BitLU.h:123
constexpr const std::vector< usize > & swaps() const
Returns a reference to the row swap instructions in LAPACK form.
Definition BitLU.h:145
std::optional< BitVec< 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:207
constexpr bool is_singular() const
Returns true if the underlying matrix is singular (i.e. rank deficient).
Definition BitLU.h:111
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:291
constexpr BitMat< Word > L() const
Returns the unit lower triangular matrix L in the LU decomposition.
Definition BitLU.h:120
BitLU(BitMat< Word > const &A)
Constructs the LU decomposition object for a square matrix A.
Definition BitLU.h:60
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:1475
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:652
constexpr BitMat unit_lower() const
Returns an independent clone of the unit lower triangular part of the bit-matrix.
Definition BitMat.h:1533
constexpr usize cols() const
Returns the number of columns in the bit-matrix.
Definition BitMat.h:629
constexpr void swap_rows(usize i, usize j)
Swaps rows i and j of the bit-matrix.
Definition BitMat.h:1569
static constexpr BitMat identity(usize m)
Factory method to create the m x m identity bit-matrix.
Definition BitMat.h:380
constexpr usize rows() const
Returns the number of rows in the bit-matrix.
Definition BitMat.h:626
A dynamically-sized vector over GF(2) with bit elements compactly stored in a standard vector of prim...
Definition BitVec.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