GF2++
Loading...
Searching...
No Matches
BitPoly.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 <sstream>
11
12namespace gf2 {
13
14// Forward declarations to avoid recursive inclusion issues
15// clang-format off
16template<unsigned_word Word> class BitMat;
17// clang-format on
18
30template<unsigned_word Word = usize>
31class BitPoly {
32private:
33 BitVec<Word> m_coeffs;
34
35public:
38
40 using word_type = Word;
41
44
54 constexpr BitPoly() : m_coeffs{} {}
55
63 constexpr BitPoly(const BitVec<Word>& coeffs) : m_coeffs{coeffs} {}
64
78 constexpr BitPoly(BitVec<Word>&& coeffs) : m_coeffs{std::move(coeffs)} {}
79
83
91 static constexpr BitPoly zero() { return BitPoly<Word>{}; }
92
100 static constexpr BitPoly one() { return BitPoly<Word>{std::move(coeffs_type::ones(1))}; }
101
109 static constexpr BitPoly constant(bool val) { return BitPoly<Word>{std::move(coeffs_type::constant(val, 1))}; }
110
120 static constexpr BitPoly zeros(usize n) { return BitPoly<Word>{std::move(coeffs_type::zeros(n + 1))}; }
121
131 static constexpr BitPoly ones(usize n) { return BitPoly<Word>{std::move(coeffs_type::ones(n + 1))}; }
132
140 static constexpr BitPoly x_to_the(usize n) { return BitPoly<Word>{std::move(coeffs_type::unit(n + 1, n))}; }
141
150 static constexpr BitPoly from(usize n, std::invocable<usize> auto f) {
151 return BitPoly<Word>{std::move(coeffs_type::from(n + 1, f))};
152 }
153
157
164 static constexpr BitPoly random(usize n) {
165 // BitPoly of degree `n` has `n + 1` coefficients.
166 auto coeffs = coeffs_type::random(n + 1);
167
168 // 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.
169 if (n > 0) coeffs.set(n);
170 return BitPoly{std::move(coeffs)};
171 }
172
185 static constexpr BitPoly seeded_random(usize n, std::uint64_t seed) {
186 // BitPoly of degree `n` has `n + 1` coefficients.
187 auto coeffs = coeffs_type::seeded_random(n + 1, seed);
188
189 // 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.
190 if (n > 0) coeffs.set(n);
191 return BitPoly{std::move(coeffs)};
192 }
193
197
211 constexpr usize degree() const { return m_coeffs.last_set().value_or(0); }
212
224 constexpr usize size() const { return m_coeffs.size(); }
225
227 constexpr bool is_zero() const { return m_coeffs.none(); }
228
230 constexpr bool is_non_zero() const { return m_coeffs.any(); }
231
233 constexpr bool is_one() const { return degree() == 0 && m_coeffs.size() >= 1 && m_coeffs.get(0); }
234
236 constexpr bool is_constant() const { return degree() == 0; }
237
239 constexpr bool is_monic() const { return m_coeffs.trailing_zeros() == 0; }
240
244 constexpr bool is_empty() const { return m_coeffs.is_empty(); }
245
249
257 constexpr bool operator[](usize i) const { return m_coeffs[i]; }
258
270 constexpr BitRef<coeffs_type> operator[](usize i) { return m_coeffs[i]; }
271
282 constexpr const coeffs_type& coefficients() const { return m_coeffs; }
283
296 constexpr coeffs_type& coefficients() { return m_coeffs; }
297
309 constexpr void copy_coefficients(const coeffs_type& coeffs) { m_coeffs = coeffs; }
310
325 constexpr void move_coefficients(coeffs_type&& coeffs) { m_coeffs = std::move(coeffs); }
326
330
340 constexpr BitPoly& clear() {
341 m_coeffs.clear();
342 return *this;
343 }
344
363 constexpr BitPoly& resize(usize n) {
364 m_coeffs.resize(n);
365 return *this;
366 }
367
377 constexpr BitPoly& shrink_to_fit() {
378 m_coeffs.shrink_to_fit();
379 return *this;
380 }
381
395 constexpr BitPoly& make_monic() {
396 if (is_non_zero()) m_coeffs.resize(degree() + 1);
397 return *this;
398 }
399
403
413 constexpr BitPoly& operator+=(const BitPoly& rhs) {
414 // Edge case.
415 if (rhs.is_zero()) return *this;
416
417 // Another edge case.
418 if (is_zero()) {
419 *this = rhs;
420 return *this;
421 }
422
423 // Perhaps we need to get bigger to accommodate the rhs? Note that added coefficients are zeros.
424 auto rhs_degree = rhs.degree();
425 if (m_coeffs.size() < rhs_degree + 1) m_coeffs.resize(rhs_degree + 1);
426
427 // Add in the active rhs words.
428 for (auto i = 0uz; i < rhs.monic_word_count(); ++i) {
429 m_coeffs.set_word(i, m_coeffs.word(i) ^ rhs.m_coeffs.word(i));
430 }
431 return *this;
432 }
433
445 constexpr BitPoly& operator-=(const BitPoly& rhs) { return operator+=(rhs); }
446
460 constexpr BitPoly& operator*=(const BitPoly& rhs) {
461 // Edge cases: zero BitPolys.
462 if (rhs.is_zero()) return clear();
463 if (is_zero()) return *this;
464
465 // Edge cases: one BitPolys.
466 if (rhs.is_one()) return *this;
467 if (is_one()) {
468 *this = rhs;
469 return *this;
470 }
471
472 // Generally we pass the work to the convolution method for bit-vectors.
473 *this = BitPoly{std::move(convolve(m_coeffs, rhs.m_coeffs))};
474 return *this;
475 }
476
486 constexpr BitPoly<Word> operator+(const BitPoly<Word>& rhs) const {
487 // Avoid unnecessary resizing by adding the smaller degree BitPoly to the larger one ...
488 if (degree() >= rhs.degree()) {
489 BitPoly<Word> result{*this};
490 result += rhs;
491 return result;
492 } else {
493 BitPoly<Word> result{rhs};
494 result += *this;
495 return result;
496 }
497 }
498
510 constexpr BitPoly<Word> operator-(const BitPoly<Word>& rhs) const {
511 // Subtraction is identical to addition in GF(2).
512 return operator+(rhs);
513 }
514
524 constexpr BitPoly<Word> operator*(const BitPoly<Word>& rhs) const {
525 BitPoly<Word> result{*this};
526 result *= rhs;
527 return result;
528 }
529
533
547 constexpr void square_into(BitPoly& dst) const {
548 // Edge case: any constant BitPoly.
549 if (is_constant()) {
550 dst = *this;
551 return;
552 }
553
554 // In GF(2) if p(x) = a + bx + cx^2 + ... then p(x)^2 = a^2 + b^2x^2 + c^2x^4 + ...
555 // This identity means we can use the `riffle` method to square the BitPoly.
556 m_coeffs.riffle_into(dst.m_coeffs);
557 }
558
570 constexpr BitPoly squared() const {
571 BitPoly dst;
572 square_into(dst);
573 return dst;
574 }
575
588 auto new_degree = degree() + n;
589 auto new_size = new_degree + 1;
590 if (m_coeffs.size() < new_size) { m_coeffs.resize(new_size); }
591 m_coeffs >>= n;
592 return *this;
593 }
594
598
607 constexpr bool operator()(bool x) const {
608 // Edge case: the zero BitPoly.
609 if (is_zero()) { return false; }
610
611 // Edge case: `x = false` which is the same as `x = 0` & we always have p(0) = p_0.
612 if (!x) { return m_coeffs.get(0); }
613
614 // We are evaluating the BitPoly at `x = true` which is the same as `x = 1`: p(1) = p_0 + p_1 + p_2 + ...
615 Word sum = 0;
616 for (auto i = 0uz; i < m_coeffs.words(); ++i) sum ^= m_coeffs.word(i);
617 return gf2::count_ones(sum) % 2 == 1;
618 }
619
634 constexpr BitMat<Word> operator()(const BitMat<Word>& M) const {
635 // The bit-matrix argument must be square.
636 gf2_assert(M.is_square(), "Matrix must be square -- not {} x {}!", M.rows(), M.cols());
637
638 // The returned bit-matrix will be n x n.
639 auto n = M.rows();
640
641 // Edge case: If the polynomial is zero then the return value is the n x n zero matrix.
642 if (is_zero()) return BitMat<Word>{n, n};
643
644 // Otherwise we start with the polynomial sum being the n x n identity matrix.
645 auto result = BitMat<Word>::identity(n);
646
647 // Work backwards a la Horner ...
648 auto d = degree();
649 while (d > 0) {
650
651 // Always multiply ...
652 result = M * result;
653
654 // Add the identity to the sum if the corresponding polynomial coefficient is 1.
655 if (m_coeffs[d - 1]) result.add_identity();
656
657 // And count down ...
658 d--;
659 }
660
661 return result;
662 }
663
667
685 BitPoly reduce_x_to_the(usize n, bool n_is_log2 = false) const {
686 // Error check: anything mod 0 is not defined.
687 if (is_zero()) throw std::invalid_argument("... mod P(x) is not defined for P(x) := 0.");
688
689 // Edge case: anything mod 1 = 0.
690 if (is_one()) return BitPoly<Word>::zero();
691
692 // 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).
693 if (n == 0 && !n_is_log2) return BitPoly<Word>::one();
694
695 // The BitPoly P(x) is non-zero so can be written as P(x) = x^d + p(x) where degree(p) < d.
696 auto d = degree();
697
698 // 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).
699 // Then x^e = (P(x) + c)^e = terms in powers of P(x) + c^e. Hence, x^e mod P(x) = c^e = c.
700 if (d == 1) return BitPoly<Word>::constant(m_coeffs.get(1));
701
702 // We can write p(x) = p_0 + p_1 x + ... + p_{d-1} x^{d-1}. All that matters are those coefficients.
703 auto p = m_coeffs.sub(0, d);
704
705 // A lambda to perform: q(x) <- x*q(x) mod P(x) where degree(q) < d.
706 // The lambda works on the coefficients of q(x) passed as a bit-vector q.
707 auto times_x_step = [&](auto& q) {
708 bool add_p = q[d - 1];
709 q >>= 1;
710 if (add_p) q ^= p;
711 };
712
713 // Iteratively precompute x^{d+i} mod P(x) for i = 0, 1, ..., d-1 starting with x^d mod P(x) ~ p.
714 // We store all the bit-vectors in a standard `std::vector` of length d.
715 std::vector<coeffs_type> power_mod(d, coeffs_type{d});
716 power_mod[0] = p;
717 for (auto i = 1uz; i < d; ++i) {
718 power_mod[i] = power_mod[i - 1];
719 times_x_step(power_mod[i]);
720 }
721
722 // Some workspace we use/reuse below in order to minimize allocations/deallocations.
723 coeffs_type s{2 * d}, h{d};
724
725 // lambda to perform: q(x) <- q(x)^2 mod P(x) where degree(q) < d.
726 // The lambda works on the coefficients of q(x) passed as a bit-vector q.
727 auto square_step = [&](auto& q) {
728 // Square q(x) storing the result in workspace `s`.
729 q.riffle_into(s);
730
731 // Split s(x) = l(x) + x^d * h(x) where l(x) & h(x) are both of degree less than d.
732 // We reuse q(x) for l(x).
733 s.split_at(d, q, h);
734
735 // s(x) = q(x) + h(x) so s(x) mod P(x) = q(x) + h(x) mod P(x) which we handle term by term.
736 // If h(x) != 0 then at most every second term in h(x) is 1 (nature of BitPoly squares in GF(2)).
737 if (auto h_first = h.first_set()) {
738 auto h_last = h.last_set();
739 for (auto i = *h_first; i <= *h_last; i += 2)
740 if (h[i]) q ^= power_mod[i];
741 }
742 };
743
744 // 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}.
745 coeffs_type r{d};
746
747 // If `n_is_log2` is `true`, we are reducing x^(2^n) mod P(x) which is done iteratively by squaring.
748 if (n_is_log2) {
749 // Note that we already handled edge case where P(x) = x + c above.
750 // Start with r(x) = x mod P(x) -> x^2 mod P(x) -> x^4 mod P(x) ...
751 r[1] = true;
752 for (auto i = 0uz; i < n; ++i) square_step(r);
753 return BitPoly{std::move(r)};
754 }
755
756 // Small exponent case: n < d => x^n mod P(x) = x^n.
757 if (n < d) return BitPoly::x_to_the(n);
758
759 // Matching exponent case: n = d => x^n mod P(x) = x^d mod P(x) = p(x).
760 if (n == d) return BitPoly{std::move(p)};
761
762 // General case: n > d is handled by a square & multiply algorithm.
763 usize n_bit = std::bit_floor(n);
764
765 // Start with r(x) = x mod P(x) which takes care of the most significant binary digit in n.
766 // TODO: We could start a bit further along with a higher power r(x) := x^? mod P(x) where ? < n but > 1.
767 r[1] = 1;
768 n_bit >>= 1;
769
770 // And off we go ...
771 while (n_bit) {
772
773 // Always do a square step and then a times_x step if necessary (i.e. if current bit in N is set).
774 square_step(r);
775 if (n & n_bit) times_x_step(r);
776
777 // On to the next bit position in n.
778 n_bit >>= 1;
779 }
780
781 // Made it.
782 return BitPoly{std::move(r)};
783 }
784
788
801 std::string to_string(std::string_view var = "x") const {
802 // Edge case: the zero BitPoly.
803 if (is_zero()) return "0";
804
805 // Otherwise we construct the string ...
806 std::ostringstream ss;
807
808 // All terms other than the first one are preceded by a "+"
809 bool first_term = true;
810 for (auto i = 0uz; i <= degree(); ++i) {
811 if (m_coeffs.get(i)) {
812 if (i == 0) {
813 ss << "1";
814 } else {
815 if (!first_term) ss << " + ";
816 if (i == 1)
817 ss << var;
818 else
819 ss << var << "^" << i;
820 }
821 first_term = false;
822 }
823 }
824 return ss.str();
825 }
826
839 std::string to_full_string(std::string_view var = "x") const {
840 // Edge case: the zero BitPoly.
841 if (is_empty()) return "0";
842
843 // Otherwise we construct the string ...
844 std::ostringstream ss;
845
846 // Start with the first term ...
847 if (m_coeffs.get(0))
848 ss << "1";
849 else
850 ss << "0";
851
852 // Now all the other terms, each preceded by a "+"
853 for (auto i = 1uz; i < size(); ++i) {
854 ss << " + ";
855 if (m_coeffs.get(i) == false) ss << "0";
856 if (i == 1)
857 ss << var;
858 else
859 ss << var << "^" << i;
860 }
861 return ss.str();
862 }
863
865 std::ostream& operator<<(std::ostream& s) const { return s << to_string(); }
866
870
882 friend constexpr bool operator==(const BitPoly& lhs, const BitPoly& rhs) {
883 // Edge case.
884 if (&lhs == &rhs) return true;
885
886 // Check the active words for equality.
887 auto count = lhs.monic_word_count();
888 if (rhs.monic_word_count() != count) return false;
889 for (auto i = 0uz; i < count; ++i)
890 if (lhs.m_coeffs.word(i) != rhs.m_coeffs.word(i)) return false;
891
892 // Made it
893 return true;
894 }
895
897
898private:
899 // Returns the number of "active" words underlying the coefficient bit-vector.
900 // There may be high order trailing zero coefficients that have no real impact on most bit-polynomial calculations.
901 // This method returns the number of "words" that matter in the coefficient bit-vector store of words.
902 constexpr usize monic_word_count() const {
903 if (auto deg = m_coeffs.last_set()) return word_index<Word>(*deg) + 1;
904 return 0;
905 }
906};
907
908} // namespace gf2
909
910// --------------------------------------------------------------------------------------------------------------------
911// Specialises `std::formatter` to handle bit-polynomials ...
912// -------------------------------------------------------------------------------------------------------------------
913
927template<gf2::unsigned_word Word>
928struct std::formatter<gf2::BitPoly<Word>> {
929
931 constexpr auto parse(const std::format_parse_context& ctx) {
932 auto it = ctx.begin();
933 if (*it != '}') m_var.clear();
934 while (it != ctx.end() && *it != '}') {
935 m_var += *it;
936 ++it;
937 }
938 return it;
939 }
940
942 template<class FormatContext>
943 auto format(const gf2::BitPoly<Word>& rhs, FormatContext& ctx) const {
944 return std::format_to(ctx.out(), "{}", rhs.to_string(m_var));
945 }
946
947 std::string m_var = "x";
948};
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 BitMat.h:32
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 usize cols() const
Returns the number of columns in the bit-matrix.
Definition BitMat.h:621
static constexpr BitMat identity(usize m)
Factory method to create the m x m identity bit-matrix.
Definition BitMat.h:376
constexpr void add_identity()
Adds the identity bit-matrix to the bit-matrix.
Definition BitMat.h:1590
constexpr usize rows() const
Returns the number of rows in the bit-matrix.
Definition BitMat.h:618
A BitPoly represents a polynomial over GF(2) where we store the polynomial coefficients in a bit-vect...
Definition BitPoly.h:31
constexpr BitRef< coeffs_type > operator[](usize i)
Returns the coefficient of in the bit-polynomial as a BitRef.
Definition BitPoly.h:270
constexpr bool is_empty() const
Returns true if the bit-polynomial is empty, i.e., has no coefficients.
Definition BitPoly.h:244
constexpr bool is_zero() const
Returns true if the bit-polynomial is some form of the zero BitPoly p(x) := 0.
Definition BitPoly.h:227
std::string to_string(std::string_view var="x") const
Returns a readable string representation of the bit-polynomial p(x) = p0 + p1x + ....
Definition BitPoly.h:801
static constexpr BitPoly constant(bool val)
Factory method to return the constant bit-polynomial p(x) := val where val is a boolean.
Definition BitPoly.h:109
constexpr BitPoly & 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 BitPoly.h:395
constexpr BitPoly< Word > operator-(const BitPoly< Word > &rhs) const
Returns the difference of two bit-polynomials.
Definition BitPoly.h:510
constexpr bool is_constant() const
Returns true if the bit-polynomial is either p(x) := 0 or 1.
Definition BitPoly.h:236
constexpr usize size() const
Returns the "size" of the bit-polynomial which is its total number of coefficients.
Definition BitPoly.h:224
constexpr BitPoly & shrink_to_fit()
Shrinks the BitPoly to have the minimum number of coefficients and returns self.
Definition BitPoly.h:377
constexpr BitPoly & operator+=(const BitPoly &rhs)
In-place addition with another bit-polynomial, returning a reference to the result.
Definition BitPoly.h:413
constexpr bool is_non_zero() const
Returns true if the bit-polynomial is non-zero.
Definition BitPoly.h:230
static constexpr BitPoly zero()
Factory method to return the "zero" bit-polynomial p(x) := 0.
Definition BitPoly.h:91
constexpr BitPoly & operator*=(const BitPoly &rhs)
In-place multiplication with another bit-polynomial, returning a reference to the result.
Definition BitPoly.h:460
constexpr bool operator[](usize i) const
Returns the coefficient of in the bit-polynomial as a boolean.
Definition BitPoly.h:257
static constexpr BitPoly 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 BitPoly.h:150
constexpr BitPoly & clear()
Clears the BitPoly, i.e., sets it to the zero BitPoly & returns self.
Definition BitPoly.h:340
constexpr void copy_coefficients(const coeffs_type &coeffs)
Set the bit-polynomial coefficients by copying them from a pre-filled bit-vector.
Definition BitPoly.h:309
constexpr BitPoly< Word > operator+(const BitPoly< Word > &rhs) const
Returns the sum of two bit-polynomials.
Definition BitPoly.h:486
constexpr BitPoly & resize(usize n)
Resizes the BitPoly to have the n coefficients and returns self.
Definition BitPoly.h:363
constexpr void move_coefficients(coeffs_type &&coeffs)
Set the BitPoly coefficients by moving a bit-vector of coefficients into place.
Definition BitPoly.h:325
constexpr BitPoly(const BitVec< Word > &coeffs)
Constructs a bit-polynomial with the given coefficients by copying them.
Definition BitPoly.h:63
friend constexpr bool operator==(const BitPoly &lhs, const BitPoly &rhs)
Equality operator checks that any pair of bit-polynomials are equal in content.
Definition BitPoly.h:882
constexpr BitPoly(BitVec< Word > &&coeffs)
Constructs a bit-polynomial with the given coefficients by moving them.
Definition BitPoly.h:78
std::ostream & operator<<(std::ostream &s) const
The usual output stream operator for a bit-polynomial.
Definition BitPoly.h:865
constexpr bool is_one() const
Returns true if the bit-polynomial is p(x) := 1.
Definition BitPoly.h:233
BitVec< Word > coeffs_type
The type used to store the bit-polynomial coefficients.
Definition BitPoly.h:37
static constexpr BitPoly one()
Factory method to return the "one" bit-polynomial p(x) := 1.
Definition BitPoly.h:100
constexpr BitPoly squared() const
Returns a new BitPoly that is the square of this BitPoly.
Definition BitPoly.h:570
std::string to_full_string(std::string_view var="x") const
Returns a readable full string representation of the bit-polynomial.
Definition BitPoly.h:839
constexpr usize degree() const
Returns the degree of the bit-polynomial.
Definition BitPoly.h:211
constexpr BitPoly()
The default constructor creates an empty bit-polynomial with no coefficients.
Definition BitPoly.h:54
Word word_type
The underlying unsigned word type used to store the bits.
Definition BitPoly.h:40
constexpr const coeffs_type & coefficients() const
Read-only access to all the coefficients of the bit-polynomial.
Definition BitPoly.h:282
constexpr bool is_monic() const
Returns true if the bit-polynomial is monic, i.e., no trailing zero coefficients.
Definition BitPoly.h:239
constexpr BitPoly & times_x_to_the(usize n)
Multiplies the BitPoly by x^n and returns self.
Definition BitPoly.h:587
constexpr coeffs_type & coefficients()
Read-write access to all the coefficients of the bit-polynomial.
Definition BitPoly.h:296
constexpr void square_into(BitPoly &dst) const
Fills dst with the square of this bit-polynomial.
Definition BitPoly.h:547
static constexpr BitPoly zeros(usize n)
Factory method to return a bit-polynomial with n + 1 coefficients, all initialized to zero.
Definition BitPoly.h:120
constexpr BitMat< Word > operator()(const BitMat< Word > &M) const
Evaluates the bit-polynomial for a square gf2::BitMat argument.
Definition BitPoly.h:634
constexpr bool operator()(bool x) const
Evaluates the BitPoly at the boolean scalar point x and returns the result.
Definition BitPoly.h:607
static constexpr BitPoly random(usize n)
Factory method to return a new bit-polynomial of degree n with n + 1 coefficients picked uniformly at...
Definition BitPoly.h:164
static constexpr BitPoly 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 BitPoly.h:185
constexpr BitPoly & operator-=(const BitPoly &rhs)
In-place subtraction with another bit-polynomial, returning a reference to the result.
Definition BitPoly.h:445
static constexpr BitPoly x_to_the(usize n)
Factory method to return the bit-polynomial p(x) := x^n.
Definition BitPoly.h:140
BitPoly 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 BitPoly.h:685
constexpr BitPoly< Word > operator*(const BitPoly< Word > &rhs) const
Returns the product of two bit-polynomials.
Definition BitPoly.h:524
static constexpr BitPoly ones(usize n)
Factory method to return a monic bit-polynomial of degree n with n + 1 coefficients,...
Definition BitPoly.h:131
A BitRef is a proxy class to reference a single bit in a bit-store.
Definition BitRef.h:38
std::optional< usize > last_set() const
Returns the index of the last set bit in the bit-store or {} if no bits are set.
Definition BitStore.h:706
constexpr void split_at(usize at, BitVec< word_type > &left, BitVec< word_type > &right) const
Definition BitStore.h:1132
A dynamically-sized vector over GF(2) with bit elements compactly stored in a standard vector of prim...
Definition BitVec.h:37
constexpr Word word(usize i) const
Returns word i from the bit-vector's underlying word store.
Definition BitVec.h:93
static constexpr BitVec constant(usize n, bool value)
Definition BitVec.h:231
static constexpr BitVec zeros(usize n)
Definition BitVec.h:212
static constexpr BitVec from(const BitStore< Src > &src)
Definition BitVec.h:277
static BitVec random(usize len, double p=0.5, u64 seed=0)
Definition BitVec.h:339
static constexpr BitVec ones(usize n)
Definition BitVec.h:220
static BitVec seeded_random(usize len, u64 seed)
Definition BitVec.h:362
static constexpr BitVec unit(usize n, usize i)
Definition BitVec.h:242
The namespace for the gf2 library.
Definition assert.h:119
auto convolve(const BitStore< Lhs > &lhs, const BitStore< Rhs > &rhs)
Returns the convolution of this store with the given rhs store as a new bit-vector.
Definition BitStore.h:1880
constexpr usize word_index(usize i)
Returns the index of the unsigned_word word holding bit element i.
Definition unsigned_word.h:539
constexpr u8 count_ones(Word word)
Returns the number of set bits in an unsigned_word.
Definition unsigned_word.h:327
std::size_t usize
Word type alias for the platform's "native"-sized unsigned integer.
Definition unsigned_word.h:41
constexpr auto parse(const std::format_parse_context &ctx)
Parse a bit-polynomial format specifier for a variable name (default is "x").
Definition BitPoly.h:931
auto format(const gf2::BitPoly< Word > &rhs, FormatContext &ctx) const
Defer the work to the to_string(...) method in the class.
Definition BitPoly.h:943