GF2++
Loading...
Searching...
No Matches
BitPolynomial.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/BitVector.h>
10#include <sstream>
11
12namespace gf2 {
13
14// Forward declarations to avoid recursive inclusion issues when we define polynomial evaluation for bit-matrices.
15template<Unsigned Word>
16class BitMatrix;
17
29template<Unsigned Word = usize>
31private:
32 BitVector<Word> m_coeffs;
33
34public:
37
39 using word_type = Word;
40
43
53 constexpr BitPolynomial() : m_coeffs{} {}
54
64 template<BitStore Src>
65 constexpr BitPolynomial(Src const& coeffs) : m_coeffs{coeffs.size()} {
66 m_coeffs.copy(coeffs);
67 }
68
82 constexpr BitPolynomial(BitVector<Word>&& coeffs) : m_coeffs{std::move(coeffs)} {}
83
87
95 static constexpr BitPolynomial zero() { return BitPolynomial<Word>{}; }
96
104 static constexpr BitPolynomial one() { return BitPolynomial<Word>{std::move(coeffs_type::ones(1))}; }
105
113 static constexpr BitPolynomial constant(bool val) {
114 return BitPolynomial<Word>{std::move(coeffs_type::constant(val, 1))};
115 }
116
126 static constexpr BitPolynomial zeros(usize n) { return BitPolynomial<Word>{std::move(coeffs_type::zeros(n + 1))}; }
127
137 static constexpr BitPolynomial ones(usize n) { return BitPolynomial<Word>{std::move(coeffs_type::ones(n + 1))}; }
138
146 static constexpr BitPolynomial x_to_the(usize n) {
147 return BitPolynomial<Word>{std::move(coeffs_type::unit(n + 1, n))};
148 }
149
158 static constexpr BitPolynomial from(usize n, std::invocable<usize> auto f) {
159 return BitPolynomial<Word>{std::move(coeffs_type::from(n + 1, f))};
160 }
161
165
172 static constexpr BitPolynomial random(usize n) {
173 // BitPolynomial of degree `n` has `n + 1` coefficients.
174 auto coeffs = coeffs_type::random(n + 1);
175
176 // If `n > 0` we want the coefficient of `x^n` to be one for sure. If `n == 0` then a random 0/1 is fine.
177 if (n > 0) coeffs.set(n);
178 return BitPolynomial{std::move(coeffs)};
179 }
180
193 static constexpr BitPolynomial seeded_random(usize n, std::uint64_t seed) {
194 // BitPolynomial of degree `n` has `n + 1` coefficients.
195 auto coeffs = coeffs_type::seeded_random(n + 1, seed);
196
197 // If `n > 0` we want the coefficient of `x^n` to be one for sure. If `n == 0` then a random 0/1 is fine.
198 if (n > 0) coeffs.set(n);
199 return BitPolynomial{std::move(coeffs)};
200 }
201
205
219 constexpr usize degree() const { return m_coeffs.last_set().value_or(0); }
220
232 constexpr usize size() const { return m_coeffs.size(); }
233
235 constexpr bool is_zero() const { return m_coeffs.none(); }
236
238 constexpr bool is_non_zero() const { return m_coeffs.any(); }
239
241 constexpr bool is_one() const { return degree() == 0 && m_coeffs.size() >= 1 && m_coeffs.get(0); }
242
244 constexpr bool is_constant() const { return degree() == 0; }
245
247 constexpr bool is_monic() const { return m_coeffs.trailing_zeros() == 0; }
248
252 constexpr bool is_empty() const { return m_coeffs.is_empty(); }
253
257
265 constexpr auto operator[](usize i) const { return m_coeffs[i]; }
266
278 constexpr auto operator[](usize i) { return m_coeffs[i]; }
279
290 constexpr const coeffs_type& coefficients() const { return m_coeffs; }
291
304 constexpr coeffs_type& coefficients() { return m_coeffs; }
305
319 template<BitStore Src>
320 constexpr void copy_coefficients(Src const& coeffs) {
321 m_coeffs.resize(coeffs.size());
322 m_coeffs.copy(coeffs);
323 }
324
339 constexpr void move_coefficients(coeffs_type&& coeffs) { m_coeffs = std::move(coeffs); }
340
344
354 constexpr BitPolynomial& clear() {
355 m_coeffs.clear();
356 return *this;
357 }
358
377 constexpr BitPolynomial& resize(usize n) {
378 m_coeffs.resize(n);
379 return *this;
380 }
381
392 m_coeffs.shrink_to_fit();
393 return *this;
394 }
395
410 if (is_non_zero()) m_coeffs.resize(degree() + 1);
411 return *this;
412 }
413
417
427 constexpr BitPolynomial& operator+=(BitPolynomial const& rhs) {
428 // Edge case.
429 if (rhs.is_zero()) return *this;
430
431 // Another edge case.
432 if (is_zero()) {
433 *this = rhs;
434 return *this;
435 }
436
437 // Perhaps we need to get bigger to accommodate the rhs? Note that added coefficients are zeros.
438 auto rhs_degree = rhs.degree();
439 if (m_coeffs.size() < rhs_degree + 1) m_coeffs.resize(rhs_degree + 1);
440
441 // Add in the active rhs words.
442 for (auto i = 0uz; i < rhs.monic_word_count(); ++i) {
443 m_coeffs.set_word(i, m_coeffs.word(i) ^ rhs.m_coeffs.word(i));
444 }
445 return *this;
446 }
447
459 constexpr BitPolynomial& operator-=(BitPolynomial const& rhs) { return operator+=(rhs); }
460
474 constexpr BitPolynomial& operator*=(BitPolynomial const& rhs) {
475 // Edge cases: zero BitPolys.
476 if (rhs.is_zero()) return clear();
477 if (is_zero()) return *this;
478
479 // Edge cases: either BitPolynomial is one.
480 if (rhs.is_one()) return *this;
481 if (is_one()) {
482 *this = rhs;
483 return *this;
484 }
485
486 // Generally we pass the work to the convolution method for bit-vectors.
487 *this = BitPolynomial{std::move(convolve(m_coeffs, rhs.m_coeffs))};
488 return *this;
489 }
490
500 constexpr auto operator+(BitPolynomial<Word> const& rhs) const {
501 // Avoid unnecessary resizing by adding the smaller degree BitPolynomial to the larger one ...
502 if (degree() >= rhs.degree()) {
503 BitPolynomial<Word> result{*this};
504 result += rhs;
505 return result;
506 } else {
507 BitPolynomial<Word> result{rhs};
508 result += *this;
509 return result;
510 }
511 }
512
524 constexpr auto operator-(BitPolynomial<Word> const& rhs) const {
525 // Subtraction is identical to addition in GF(2).
526 return operator+(rhs);
527 }
528
538 constexpr auto operator*(BitPolynomial<Word> const& rhs) const {
539 BitPolynomial<Word> result{*this};
540 result *= rhs;
541 return result;
542 }
543
547
561 constexpr void squared(BitPolynomial& dst) const {
562 // Edge case: any constant BitPolynomial.
563 if (is_constant()) {
564 dst = *this;
565 return;
566 }
567
568 // In GF(2) if p(x) = a + bx + cx^2 + ... then p(x)^2 = a^2 + b^2x^2 + c^2x^4 + ...
569 // This identity means we can use the `riffle` method to square the BitPolynomial.
570 m_coeffs.riffled(dst.m_coeffs);
571 }
572
584 constexpr BitPolynomial squared() const {
585 BitPolynomial dst;
586 squared(dst);
587 return dst;
588 }
589
602 auto new_degree = degree() + n;
603 auto new_size = new_degree + 1;
604 if (m_coeffs.size() < new_size) { m_coeffs.resize(new_size); }
605 m_coeffs >>= n;
606 return *this;
607 }
608
612
630 constexpr void sub(usize d, BitPolynomial& dst) const {
631 if (d == 0) {
632 dst = BitPolynomial<Word>::constant(m_coeffs.get(0));
633 } else if (d + 1 >= m_coeffs.size()) {
634 dst = *this;
635 } else {
636 dst.copy_coefficients(m_coeffs.span(0, d + 1));
637 }
638 }
639
652 constexpr auto sub(usize d) const {
653 BitPolynomial dst;
654 sub(d, dst);
655 return std::move(dst);
656 }
657
676 constexpr void split(usize d, BitPolynomial& lo, BitPolynomial& hi) const {
677 if (d == 0) {
678 lo = BitPolynomial<Word>::constant(m_coeffs.get(0));
679 hi.copy_coefficients(m_coeffs.span(1, m_coeffs.size()));
680 } else if (d + 1 >= m_coeffs.size()) {
681 lo = *this;
682 hi.clear();
683 } else {
684 lo.copy_coefficients(m_coeffs.span(0, d + 1));
685 hi.copy_coefficients(m_coeffs.span(d + 1, m_coeffs.size()));
686 }
687 }
688
700 constexpr auto split(usize d) const {
701 BitPolynomial lo, hi;
702 split(d, lo, hi);
703 return std::make_pair(lo, hi);
704 }
705
709
718 constexpr bool operator()(bool x) const {
719 // Edge case: the zero BitPolynomial.
720 if (is_zero()) { return false; }
721
722 // Edge case: `x = false` which is the same as `x = 0` & we always have p(0) = p_0.
723 if (!x) { return m_coeffs.get(0); }
724
725 // We are evaluating the BitPolynomial at `x = true` which is the same as `x = 1`: p(1) = p_0 + p_1 + p_2 + ...
726 Word sum = 0;
727 for (auto i = 0uz; i < m_coeffs.words(); ++i) sum ^= m_coeffs.word(i);
728 return gf2::count_ones(sum) % 2 == 1;
729 }
730
746 constexpr auto operator()(BitMatrix<Word> const& M) const {
747 // The bit-matrix argument must be square.
748 gf2_assert(M.is_square(), "Matrix must be square -- not {} x {}!", M.rows(), M.cols());
749
750 // The returned bit-matrix will be n x n.
751 auto n = M.rows();
752
753 // Edge case: If the polynomial is zero then the return value is the n x n zero matrix.
754 if (is_zero()) return BitMatrix<Word>{n, n};
755
756 // Otherwise we start with the polynomial sum being the n x n identity matrix.
757 auto result = BitMatrix<Word>::identity(n);
758
759 // Work backwards a la Horner ...
760 auto d = degree();
761 while (d > 0) {
762
763 // Always multiply ...
764 result = dot(M, result);
765
766 // Add the identity to the sum if the corresponding polynomial coefficient is 1.
767 if (m_coeffs[d - 1]) result.add_identity();
768
769 // And count down ...
770 d--;
771 }
772
773 return result;
774 }
775
779
798 BitPolynomial reduce_x_to_the(usize n, bool n_is_log2 = false) const {
799 // Error check: anything mod 0 is not defined.
800 if (is_zero()) throw std::invalid_argument("... mod P(x) is not defined for P(x) := 0.");
801
802 // Edge case: anything mod 1 = 0.
803 if (is_one()) return BitPolynomial<Word>::zero();
804
805 // Edge case: x^0 = 1 and 1 mod P(x) = 1 for any P(x) != 1 (we already handled the case where P(x) := 1).
806 if (n == 0 && !n_is_log2) return BitPolynomial<Word>::one();
807
808 // The BitPolynomial P(x) is non-zero so can be written as P(x) = x^d + p(x) where degree(p) < d.
809 auto d = degree();
810
811 // Edge case: P(x) = x + c where c is a constant so x = P(x) + c (subtraction in GF(2) is the same as addition).
812 // Then x^e = (P(x) + c)^e = terms in powers of P(x) + c^e. Hence, x^e mod P(x) = c^e = c.
813 if (d == 1) return BitPolynomial<Word>::constant(m_coeffs.get(0));
814
815 // This polynomial is P(x) where P(x) = x^d + p(x) where p(x) = p_0 + p_1 x + ... + p_{d-1} x^{d-1}.
816 // All that matters are the `d` coefficients of p(x).
817 auto p = m_coeffs.sub(0, d);
818
819 // A lambda to perform: q(x) <- x*q(x) mod P(x) where degree(q) < d.
820 // The lambda works in-place on the coefficients of q(x) passed as a bit-vector q of size d.
821 auto times_x_step = [&](auto& q) {
822 bool add_p = q[d - 1];
823 q >>= 1;
824 if (add_p) q ^= p;
825 };
826
827 // Iteratively precompute x^{d+i} mod P(x) for i = 0, 1, ..., d-1 starting with x^d mod P(x) ~ p.
828 // We store all those bit-vectors in a standard `std::vector` of length d.
829 std::vector<coeffs_type> power_mod(d, coeffs_type{d});
830 power_mod[0] = p;
831 for (auto i = 1uz; i < d; ++i) {
832 power_mod[i] = power_mod[i - 1];
833 times_x_step(power_mod[i]);
834 }
835
836 // Some workspace we use/reuse below in order to minimize allocations/deallocations.
837 coeffs_type s{2 * d}, h{d};
838
839 // lambda to perform: q(x) <- q(x)^2 mod P(x) where degree(q) < d.
840 // The lambda works in-place on the coefficients of q(x) passed as a bit-vector q of size d.
841 auto square_step = [&](auto& q) {
842 // Square q(x) storing the result in workspace `s`.
843 q.riffled(s);
844
845 // Split s(x) = l(x) + x^d * h(x) where l(x) & h(x) are both of degree less than d.
846 // We reuse q(x) for l(x).
847 s.split_at(d, q, h);
848
849 // s(x) = q(x) + x^d h(x) so s(x) mod P(x) = q(x) + x^d h(x) mod P(x) which we handle term by term.
850 // If h(x) != 0 then at most every second term in h(x) is 1 (nature of bit-polynomial squares in GF(2)).
851 if (auto h_first = h.first_set()) {
852 auto h_last = h.last_set();
853 for (auto i = *h_first; i <= *h_last; i += 2)
854 if (h[i]) q ^= power_mod[i];
855 }
856 };
857
858 // Our return value r(x) := x^e mod P(x) has degree < d: r(x) = r_0 + r_1 x + ... + r_{d-1} x^{d-1}.
859 coeffs_type r{d};
860
861 // If `n_is_log2` is `true`, we are reducing x^(2^n) mod P(x) which is done iteratively by squaring.
862 if (n_is_log2) {
863 // Note that we already handled edge case where P(x) = x + c above.
864 // Start with r(x) = x mod P(x) -> x^2 mod P(x) -> x^4 mod P(x) ...
865 r[1] = true;
866 for (auto i = 0uz; i < n; ++i) square_step(r);
867 return BitPolynomial{std::move(r)};
868 }
869
870 // Small exponent case: n < d => x^n mod P(x) = x^n.
871 if (n < d) return BitPolynomial::x_to_the(n);
872
873 // Matching exponent case: n = d => x^n mod P(x) = x^d mod P(x) = p(x).
874 if (n == d) return BitPolynomial{std::move(p)};
875
876 // General case: n > d is handled by a square & multiply algorithm.
877 usize n_bit = std::bit_floor(n);
878
879 // Start with r(x) = x mod P(x) which takes care of the most significant binary digit in n.
880 // TODO: We could start a bit further along with a higher power r(x) := x^? mod P(x) where ? < n but > 1.
881 r[1] = 1;
882 n_bit >>= 1;
883
884 // And off we go ...
885 while (n_bit) {
886
887 // Always do a square step and then a times_x step if necessary (i.e. if current bit in N is set).
888 square_step(r);
889 if (n & n_bit) times_x_step(r);
890
891 // On to the next bit position in n.
892 n_bit >>= 1;
893 }
894
895 // Made it.
896 return BitPolynomial{std::move(r)};
897 }
898
902
915 std::string to_string(std::string_view var = "x") const {
916 // Edge case: the zero BitPolynomial.
917 if (is_zero()) return "0";
918
919 // Otherwise we construct the string ...
920 std::ostringstream ss;
921
922 // All terms other than the first one are preceded by a "+"
923 bool first_term = true;
924 for (auto i = 0uz; i <= degree(); ++i) {
925 if (m_coeffs.get(i)) {
926 if (i == 0) {
927 ss << "1";
928 } else {
929 if (!first_term) ss << " + ";
930 if (i == 1)
931 ss << var;
932 else
933 ss << var << "^" << i;
934 }
935 first_term = false;
936 }
937 }
938 return ss.str();
939 }
940
953 std::string to_full_string(std::string_view var = "x") const {
954 // Edge case: the zero BitPolynomial.
955 if (is_empty()) return "0";
956
957 // Otherwise we construct the string ...
958 std::ostringstream ss;
959
960 // Start with the first term ...
961 if (m_coeffs.get(0))
962 ss << "1";
963 else
964 ss << "0";
965
966 // Now all the other terms, each preceded by a "+"
967 for (auto i = 1uz; i < size(); ++i) {
968 ss << " + ";
969 if (m_coeffs.get(i) == false) ss << "0";
970 if (i == 1)
971 ss << var;
972 else
973 ss << var << "^" << i;
974 }
975 return ss.str();
976 }
977
979 std::ostream& operator<<(std::ostream& s) const { return s << to_string(); }
980
984
996 friend constexpr bool operator==(BitPolynomial const& lhs, BitPolynomial const& rhs) {
997 // Edge case.
998 if (&lhs == &rhs) return true;
999
1000 // Check the active words for equality.
1001 auto count = lhs.monic_word_count();
1002 if (rhs.monic_word_count() != count) return false;
1003 for (auto i = 0uz; i < count; ++i)
1004 if (lhs.m_coeffs.word(i) != rhs.m_coeffs.word(i)) return false;
1005
1006 // Made it
1007 return true;
1008 }
1009
1011
1012private:
1013 // Returns the number of "active" words underlying the coefficient bit-vector.
1014 // There may be high order trailing zero coefficients that have no real impact on most bit-polynomial calculations.
1015 // This method returns the number of "words" that matter in the coefficient bit-vector store of words.
1016 constexpr usize monic_word_count() const {
1017 if (auto deg = m_coeffs.last_set()) return word_index<Word>(*deg) + 1;
1018 return 0;
1019 }
1020};
1021
1022} // namespace gf2
1023
1024// --------------------------------------------------------------------------------------------------------------------
1025// Specialises `std::formatter` to handle bit-polynomials ...
1026// -------------------------------------------------------------------------------------------------------------------
1027
1041template<gf2::Unsigned Word>
1042struct std::formatter<gf2::BitPolynomial<Word>> {
1043
1045 constexpr auto parse(std::format_parse_context const& ctx) {
1046 auto it = ctx.begin();
1047 if (*it != '}') m_var.clear();
1048 while (it != ctx.end() && *it != '}') {
1049 m_var += *it;
1050 ++it;
1051 }
1052 return it;
1053 }
1054
1056 template<class FormatContext>
1057 auto format(gf2::BitPolynomial<Word> const& rhs, FormatContext& ctx) const {
1058 return std::format_to(ctx.out(), "{}", rhs.to_string(m_var));
1059 }
1060
1061 std::string m_var = "x";
1062};
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
A dynamically-sized matrix over GF(2) stored as a vector of bit-vectors representing the rows of the ...
Definition BitMatrix.h:33
constexpr usize rows() const
Returns the number of rows in the bit-matrix.
Definition BitMatrix.h:629
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
static constexpr BitMatrix identity(usize m)
Factory method to create the m x m identity bit-matrix.
Definition BitMatrix.h:383
A BitPolynomial represents a polynomial over GF(2) where we store the polynomial coefficients in a bi...
Definition BitPolynomial.h:30
constexpr BitPolynomial & shrink_to_fit()
Shrinks the BitPolynomial to have the minimum number of coefficients and returns self.
Definition BitPolynomial.h:391
constexpr auto split(usize d) const
Splits the bit-polynomial into a low and high part where the low part has degree at most d....
Definition BitPolynomial.h:700
constexpr const coeffs_type & coefficients() const
Read-only access to all the coefficients of the bit-polynomial.
Definition BitPolynomial.h:290
constexpr BitPolynomial & times_x_to_the(usize n)
Multiplies the BitPolynomial by x^n and returns self.
Definition BitPolynomial.h:601
constexpr void sub(usize d, BitPolynomial &dst) const
Makes the destination bit-polynomial a copy of the low d + 1 coefficients of this bit-polynomial....
Definition BitPolynomial.h:630
constexpr bool is_zero() const
Returns true if the bit-polynomial is some form of the zero BitPolynomial p(x) := 0.
Definition BitPolynomial.h:235
static constexpr BitPolynomial zeros(usize n)
Factory method to return a bit-polynomial with n + 1 coefficients, all initialized to zero.
Definition BitPolynomial.h:126
constexpr void squared(BitPolynomial &dst) const
Fills dst with the square of this bit-polynomial.
Definition BitPolynomial.h:561
constexpr BitPolynomial & make_monic()
Kills any trailing zero coefficients, so e.g. p(x) := 0*x^4 + x^2 + x becomes p(x) := x^2 + x.
Definition BitPolynomial.h:409
constexpr bool is_non_zero() const
Returns true if the bit-polynomial is non-zero.
Definition BitPolynomial.h:238
constexpr auto operator()(BitMatrix< Word > const &M) const
Evaluates the bit-polynomial for a square gf2::BitMatrix argument M.
Definition BitPolynomial.h:746
BitVector< Word > coeffs_type
The type used to store the bit-polynomial coefficients.
Definition BitPolynomial.h:36
static constexpr BitPolynomial one()
Factory method to return the "one" bit-polynomial p(x) := 1.
Definition BitPolynomial.h:104
std::string to_full_string(std::string_view var="x") const
Returns a readable full string representation of the bit-polynomial.
Definition BitPolynomial.h:953
constexpr BitPolynomial squared() const
Returns a new BitPolynomial that is the square of this BitPolynomial.
Definition BitPolynomial.h:584
static constexpr BitPolynomial ones(usize n)
Factory method to return a monic bit-polynomial of degree n with n + 1 coefficients,...
Definition BitPolynomial.h:137
static constexpr BitPolynomial from(usize n, std::invocable< usize > auto f)
Factory method to return a new bit-polynomial of degree n with coefficients set by calling the functi...
Definition BitPolynomial.h:158
constexpr void copy_coefficients(Src const &coeffs)
Set the bit-polynomial coefficients by copying them from a pre-filled bit-store.
Definition BitPolynomial.h:320
static constexpr BitPolynomial x_to_the(usize n)
Factory method to return the bit-polynomial p(x) := x^n.
Definition BitPolynomial.h:146
constexpr bool is_constant() const
Returns true if the bit-polynomial is either p(x) := 0 or 1.
Definition BitPolynomial.h:244
constexpr BitPolynomial(Src const &coeffs)
Constructs a bit-polynomial with the given coefficients by copying them from any bit-store.
Definition BitPolynomial.h:65
static constexpr BitPolynomial zero()
Factory method to return the "zero" bit-polynomial p(x) := 0.
Definition BitPolynomial.h:95
constexpr auto operator[](usize i) const
Returns the coefficient of in the bit-polynomial as a boolean.
Definition BitPolynomial.h:265
constexpr BitPolynomial & operator*=(BitPolynomial const &rhs)
In-place multiplication with another bit-polynomial, returning a reference to the result.
Definition BitPolynomial.h:474
static constexpr BitPolynomial random(usize n)
Factory method to return a new bit-polynomial of degree n with n + 1 coefficients picked uniformly at...
Definition BitPolynomial.h:172
constexpr coeffs_type & coefficients()
Read-write access to all the coefficients of the bit-polynomial.
Definition BitPolynomial.h:304
constexpr usize degree() const
Returns the degree of the bit-polynomial.
Definition BitPolynomial.h:219
constexpr bool is_empty() const
Returns true if the bit-polynomial is empty, i.e., has no coefficients.
Definition BitPolynomial.h:252
constexpr BitPolynomial()
The default constructor creates an empty bit-polynomial with no coefficients.
Definition BitPolynomial.h:53
constexpr auto operator-(BitPolynomial< Word > const &rhs) const
Returns the difference of two bit-polynomials.
Definition BitPolynomial.h:524
constexpr BitPolynomial(BitVector< Word > &&coeffs)
Constructs a bit-polynomial with the given coefficients by moving them.
Definition BitPolynomial.h:82
constexpr BitPolynomial & resize(usize n)
Resizes the BitPolynomial to have the n coefficients and returns self.
Definition BitPolynomial.h:377
static constexpr BitPolynomial constant(bool val)
Factory method to return the constant bit-polynomial p(x) := val where val is a boolean.
Definition BitPolynomial.h:113
constexpr auto operator+(BitPolynomial< Word > const &rhs) const
Returns the sum of two bit-polynomials.
Definition BitPolynomial.h:500
constexpr void move_coefficients(coeffs_type &&coeffs)
Set the BitPolynomial coefficients by moving a bit-vector of coefficients into place.
Definition BitPolynomial.h:339
constexpr void split(usize d, BitPolynomial &lo, BitPolynomial &hi) const
Splits the bit-polynomial into a low and high part where the low part has degree at most d....
Definition BitPolynomial.h:676
constexpr auto sub(usize d) const
Returns a new bit-polynomial that is a copy of the low d + 1 coefficients of this bit-polynomial....
Definition BitPolynomial.h:652
std::ostream & operator<<(std::ostream &s) const
The usual output stream operator for a bit-polynomial.
Definition BitPolynomial.h:979
constexpr bool operator()(bool x) const
Evaluates the BitPolynomial at the boolean scalar point x and returns the result.
Definition BitPolynomial.h:718
static constexpr BitPolynomial seeded_random(usize n, std::uint64_t seed)
Factory method to return a new bit-polynomial of degree n with n + 1 coefficients picked uniformly at...
Definition BitPolynomial.h:193
BitPolynomial reduce_x_to_the(usize n, bool n_is_log2=false) const
If this polynomial is P(x) we return x^e mod P(x) for e = n or e = 2^n depending on the n_is_log2 arg...
Definition BitPolynomial.h:798
constexpr auto operator[](usize i)
Returns the coefficient of in the bit-polynomial as a BitRef.
Definition BitPolynomial.h:278
constexpr BitPolynomial & clear()
Clears the BitPolynomial, i.e., sets it to the zero BitPolynomial & returns self.
Definition BitPolynomial.h:354
std::string to_string(std::string_view var="x") const
Returns a readable string representation of the bit-polynomial p(x) = p0 + p1x + ....
Definition BitPolynomial.h:915
constexpr usize size() const
Returns the "size" of the bit-polynomial which is its total number of coefficients.
Definition BitPolynomial.h:232
Word word_type
The underlying unsigned word type used to store the bits.
Definition BitPolynomial.h:39
constexpr auto operator*(BitPolynomial< Word > const &rhs) const
Returns the product of two bit-polynomials.
Definition BitPolynomial.h:538
constexpr bool is_one() const
Returns true if the bit-polynomial is p(x) := 1.
Definition BitPolynomial.h:241
friend constexpr bool operator==(BitPolynomial const &lhs, BitPolynomial const &rhs)
Equality operator checks that any pair of bit-polynomials are equal in content.
Definition BitPolynomial.h:996
constexpr bool is_monic() const
Returns true if the bit-polynomial is monic, i.e., no trailing zero coefficients.
Definition BitPolynomial.h:247
constexpr BitPolynomial & operator+=(BitPolynomial const &rhs)
In-place addition with another bit-polynomial, returning a reference to the result.
Definition BitPolynomial.h:427
constexpr BitPolynomial & operator-=(BitPolynomial const &rhs)
In-place subtraction with another bit-polynomial, returning a reference to the result.
Definition BitPolynomial.h:459
A dynamically-sized vector over GF(2) with bit elements compactly stored in a standard vector of prim...
Definition BitVector.h:23
constexpr std::optional< usize > last_set() const
Returns the index of the last set bit in the bit-vector or {} if no bits are set.
Definition BitVector.h:1426
static constexpr BitVector unit(usize n, usize i)
Definition BitVector.h:226
static constexpr BitVector from(Src src)
Definition BitVector.h:259
static BitVector random(usize size, double p=0.5, u64 seed=0)
Definition BitVector.h:373
static constexpr BitVector zeros(usize n)
Definition BitVector.h:196
static constexpr BitVector constant(usize n, bool value)
Definition BitVector.h:215
constexpr void split_at(usize at, BitVector< word_type > &left, BitVector< word_type > &right) const
Views the bit-vector as two parts containing the elements [0, at) and [at, size()) respectively.
Definition BitVector.h:1721
constexpr Word word(usize i) const
Returns word i from the bit-vector's underlying word store.
Definition BitVector.h:80
static constexpr BitVector ones(usize n)
Definition BitVector.h:204
static BitVector seeded_random(usize size, u64 seed)
Definition BitVector.h:396
The namespace for the gf2 library.
Definition assert.h:119
auto convolve(Lhs const &lhs, Rhs const &rhs)
Convolutions:
Definition BitStore.h:2223
constexpr auto dot(BitMatrix< Word > const &lhs, Rhs const &rhs)
Bit-matrix, bit-store multiplication, M * v, returning a new bit-vector.
Definition BitMatrix.h:2573
constexpr usize count_ones(Store const &store)
Returns the number of set bits in the store.
Definition BitStore.h:745
constexpr usize word_index(usize i)
Returns the index of the Unsigned word holding bit element i.
Definition Unsigned.h:547
std::size_t usize
Word type alias for the platform's "native"-sized unsigned integer.
Definition Unsigned.h:42
STL namespace.
constexpr auto parse(std::format_parse_context const &ctx)
Parse a bit-polynomial format specifier for a variable name (default is "x").
Definition BitPolynomial.h:1045
auto format(gf2::BitPolynomial< Word > const &rhs, FormatContext &ctx) const
Defer the work to the to_string(...) method in the class.
Definition BitPolynomial.h:1057