GF2::Matrix — Bit-Matrix Multiplication

Computes the dot product of a bit-vector with a bit-matrix, a bit-matrix with a bit-vector, and a bit-matrix with another.

template<std::unsigned_integral Block, typename Allocator>
constexpr const Vector<Block, Allocator>
dot(const Matrix<Block, Allocator> &M, const Vector<Block, Allocator> &v);  (1)

template<std::unsigned_integral Block, typename Allocator>
constexpr const Vector<Block, Allocator>
dot(const Vector<Block, Allocator> &v, const Matrix<Block, Allocator> &M);  (2)

template<std::unsigned_integral Block, typename Allocator>
constexpr const Matrix<Block, Allocator>
dot(const Matrix<Block, Allocator> &M, const Matrix<Block, Allocator> &N);  (3)
1 Computes \(M \cdot v\).
If M is r x c then v.size() must be c. The returned bit-vector will have size r.
2 Computes \(v \cdot M\).
If M is r x c then v.size() must be r. The returned bit-vector will have size c.
3 Computes \(M \cdot N\).
If M is a x b then N must be b x c for some c. The returned bit-matrix will be a x c.

These dot products are defined by:

\[\begin{aligned} \left(M \cdot v\right)_i &= \sum_j M_{ij} \times v_j \\ \left(v \cdot M\right)_j &= \sum_i v_i \times M_{ij} \\ \left(M \cdot N\right)_{ij} &= \sum_k M_{ik} \times N_{kj} \end{aligned}\]

In the case of GF(2), product is replaced by logical AND, and sum by the logical XOR operation.

The dot product is a key operation in linear algebra so it fortunate that AND’ing and XOR’ing for bit-matrices and bit-vectors can be done very efficiently over blocks of elements at a time.

The two arguments in each case must have compatible sizes. If the GF2_DEBUG flag is set at compile time this is checked and any violation will cause the program to abort with a helpful message.
Example
#include <GF2/GF2.h>
int main()
{
    GF2::Vector<> u(6, [](size_t k) { return k % 2; });
    GF2::Vector<> v(8, [](size_t k) { return (k + 1)% 2; });

    GF2::Matrix<> M(6, 8, [](size_t i, size_t j) { return i == j; });
    GF2::Matrix<> N(8, 4, [](size_t i, size_t j) { return (i + j)%2; });

    std::cout << "Matrix M:\n" << M << '\n';
    std::cout << "Matrix N:\n" << N << '\n';

    std::cout << "dot(" << u << ", M): " << dot(u, M) << '\n';
    std::cout << "dot(M, " << v << "): " << dot(M, v) << '\n';
    std::cout << "dot(M, N):\n" << dot(M, N) << '\n';
}
Output
Matrix M:
10000000
01000000
00100000
00010000
00001000
00000100
Matrix N:
0101
1010
0101
1010
0101
1010
0101
1010
dot(010101, M): 01010100
dot(M, 10101010): 101010
dot(M, N):
0101
1010
0101
1010
0101
1010
See Also

polynomial_sum