libsemigroups  v3.0.0
C++ library for semigroups and monoids
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
Loading...
Searching...
No Matches
bmat8.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2019-2025 Finn Smith
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17//
18
19// This file contains a declaration of fast boolean matrices up to dimension 8.
20
21// TODO(1)
22// * is it better to pass BMat8 by value rather than by const&?
23
24#ifndef LIBSEMIGROUPS_BMAT8_HPP_
25#define LIBSEMIGROUPS_BMAT8_HPP_
26
27#include <array> // for array
28#include <cstddef> // for size_t
29#include <cstdint> // for uint64_t
30#include <functional> // for hash
31#include <iosfwd> // for ostream, ostringstream
32#include <string> // for string
33#include <string_view> // for hash
34#include <type_traits> // for is_trivial
35#include <utility> // for swap
36#include <vector> // for vector
37
38#include "adapters.hpp" // for Complexity, Degree, etc . . .
39#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT
40
41namespace libsemigroups {
42
47
61
74 class BMat8 {
75 uint64_t _data;
76 // Proxy class for reference to bits in the matrix
77 class BitRef {
78 private:
79 uint64_t& _data;
80 uint64_t _mask;
81
82 public:
83 // Constructor: takes a reference to a byte and the index of the bit in
84 // that byte
85 constexpr BitRef(uint64_t& data, size_t index) noexcept
86 : _data(data), _mask(static_cast<uint64_t>(1) << (63 - index)) {}
87
88 // Assignment operator to allow setting the bit through the proxy
89 constexpr BitRef& operator=(bool val) noexcept {
90 _data ^= (-val ^ _data) & _mask;
91 return *this;
92 }
93
94 // Conversion operator to read the value of the bit as a boolean
95 [[nodiscard]] constexpr operator bool() const {
96 return _data & _mask;
97 }
98 };
99
100 public:
110 BMat8() noexcept = default;
111
124 constexpr explicit BMat8(uint64_t mat) noexcept : _data(mat) {}
125
141 explicit BMat8(std::vector<std::vector<bool>> const& mat);
142
150 constexpr BMat8(BMat8 const&) noexcept = default;
151
159 constexpr BMat8(BMat8&&) noexcept = default;
160
168 constexpr BMat8& operator=(BMat8 const&) noexcept = default;
169
177 constexpr BMat8& operator=(BMat8&&) noexcept = default;
178
179 ~BMat8() = default;
180
195 [[nodiscard]] constexpr bool operator==(BMat8 const& that) const noexcept {
196 return _data == that._data;
197 }
198
213 [[nodiscard]] constexpr bool operator!=(BMat8 const& that) const noexcept {
214 return _data != that._data;
215 }
216
231 [[nodiscard]] constexpr bool operator<(BMat8 const& that) const noexcept {
232 return _data < that._data;
233 }
234
249 [[nodiscard]] constexpr bool operator<=(BMat8 const& that) const noexcept {
250 return *this < that || *this == that;
251 }
252
267 [[nodiscard]] constexpr bool operator>(BMat8 const& that) const noexcept {
268 return _data > that._data;
269 }
270
285 [[nodiscard]] constexpr bool operator>=(BMat8 const& that) const noexcept {
286 return *this > that || *this == that;
287 }
288
315 [[nodiscard]] constexpr bool operator()(size_t r, size_t c) const noexcept {
316 LIBSEMIGROUPS_ASSERT(r < 8);
317 LIBSEMIGROUPS_ASSERT(c < 8);
318 return (_data << (8 * r + c)) >> 63;
319 }
320
346 [[nodiscard]] constexpr uint8_t operator()(size_t r) const noexcept {
347 LIBSEMIGROUPS_ASSERT(r < 8);
348 return static_cast<uint8_t>(to_int() << 8 * r >> 56);
349 }
350
374 [[nodiscard]] uint8_t at(size_t r) const;
375
403 [[nodiscard]] constexpr BitRef operator()(size_t r, size_t c) {
404 return BitRef(_data, 8 * r + c);
405 }
406
421 [[nodiscard]] bool at(size_t r, size_t c) const;
422
437 [[nodiscard]] BitRef at(size_t r, size_t c);
438
454 [[nodiscard]] constexpr inline uint64_t to_int() const noexcept {
455 return _data;
456 }
457
474 [[nodiscard]] BMat8 operator*(BMat8 const& that) const noexcept;
475
491 [[nodiscard]] constexpr BMat8 operator*(bool scalar) const noexcept {
492 if (scalar) {
493 return *this;
494 } else {
495 return BMat8(0);
496 }
497 }
498
514 constexpr BMat8& operator*=(bool scalar) noexcept {
515 if (!scalar) {
516 _data = 0;
517 }
518 return *this;
519 }
520
535 [[nodiscard]] constexpr BMat8 operator+(BMat8 const& that) const noexcept {
536 return BMat8(_data | that._data);
537 }
538
553 constexpr BMat8& operator+=(BMat8 const& that) noexcept {
554 _data |= that._data;
555 return *this;
556 }
557
573 BMat8& operator*=(BMat8 const& that) noexcept;
574
586 inline void swap(BMat8& that) noexcept {
587 std::swap(this->_data, that._data);
588 }
589 };
590
591 static_assert(std::is_trivial<BMat8>(), "BMat8 is not a trivial class!");
592
603 namespace bmat8 {
624 // TODO(later) noexcept should depend on whether or not the constructor of
625 template <typename T>
626 [[nodiscard]] constexpr T one(size_t dim = 8) noexcept {
627 LIBSEMIGROUPS_ASSERT(dim <= 8);
628 constexpr std::array<uint64_t, 9> const ones = {0x0000000000000000,
629 0x8000000000000000,
630 0x8040000000000000,
631 0x8040200000000000,
632 0x8040201000000000,
633 0x8040201008000000,
634 0x8040201008040000,
635 0x8040201008040200,
636 0x8040201008040201};
637 return T(ones[dim]);
638 }
639
656 [[nodiscard]] constexpr BMat8 one(size_t dim = 8) noexcept {
657 return one<BMat8>(dim);
658 }
659
669 // Not noexcept since std::uniform_int_distribution::operator() is not
670 // noexcept.
671 [[nodiscard]] BMat8 random();
672
685 // Not noexcept since std::uniform_int_distribution::operator() is not
686 // noexcept.
687 [[nodiscard]] BMat8 random(size_t dim);
688
704 [[nodiscard]] constexpr BMat8 transpose(BMat8 const& x) noexcept {
705 uint64_t y = x.to_int();
706 uint64_t z = (y ^ (y >> 7)) & 0xAA00AA00AA00AA;
707 y = y ^ z ^ (z << 7);
708 z = (y ^ (y >> 14)) & 0xCCCC0000CCCC;
709 y = y ^ z ^ (z << 14);
710 z = (y ^ (y >> 28)) & 0xF0F0F0F0;
711 y = y ^ z ^ (z << 28);
712 return BMat8(y);
713 }
714
730 [[nodiscard]] BMat8 row_space_basis(BMat8 const& x) noexcept;
731
747 [[nodiscard]] inline BMat8 col_space_basis(BMat8 const& x) noexcept {
749 }
750
769 [[nodiscard]] constexpr size_t number_of_rows(BMat8 const& x) noexcept {
770 size_t count = 0;
771 for (size_t i = 0; i < 8; ++i) {
772 if (x.to_int() << (8 * i) >> 56 > 0) {
773 count++;
774 }
775 }
776 return count;
777 }
778
779 // TODO(2) these should be templated to allow using HPCombi::BMat8's
780 // here too.
799 // noexcept because transpose and number_of_rows are.
800 [[nodiscard]] constexpr size_t number_of_cols(BMat8 const& x) noexcept {
801 return number_of_rows(transpose(x));
802 }
803
818 [[nodiscard]] size_t row_space_size(BMat8 const& x);
819
834 // Not noexcept because row_space_size isn't.
835 [[nodiscard]] inline size_t col_space_size(BMat8 const& x) {
836 return row_space_size(transpose(x));
837 }
838
854 [[nodiscard]] size_t minimum_dim(BMat8 const& x) noexcept;
855
872 [[nodiscard]] std::vector<uint8_t> rows(BMat8 const& x);
873
890 template <typename Container>
891 void push_back_rows(Container& rows, BMat8 const& x) {
892 static_assert(std::is_same_v<typename Container::value_type, uint8_t>);
893 for (size_t i = 0; i < 8; ++i) {
894 rows.push_back(x(i));
895 }
896 }
897
915 [[nodiscard]] bool is_regular_element(BMat8 const& x) noexcept;
916
931
932 } // namespace bmat8
933
940
947
957 std::string const& braces = "{}");
958
968 [[nodiscard]] constexpr BMat8 operator*(bool scalar,
969 BMat8 const& x) noexcept {
970 if (scalar) {
971 return x;
972 } else {
973 return BMat8(0);
974 }
975 }
976} // namespace libsemigroups
977
978namespace std {
979 template <>
980 struct hash<libsemigroups::BMat8> {
981 size_t operator()(libsemigroups::BMat8 const& bm) const {
982 return hash<uint64_t>()(bm.to_int());
983 }
984 };
985} // namespace std
986
987namespace libsemigroups {
996
1001 template <>
1004 [[nodiscard]] constexpr inline size_t
1005 operator()(BMat8 const&) const noexcept {
1006 return 0;
1007 }
1008 };
1009
1015 template <>
1016 struct Degree<BMat8> {
1018 [[nodiscard]] constexpr inline size_t
1019 operator()(BMat8 const&) const noexcept {
1020 return 8;
1021 }
1022 };
1023
1030 template <>
1033 inline void operator()(BMat8 const&, size_t) const noexcept {}
1034 };
1035
1041 template <>
1042 struct One<BMat8> {
1044 [[nodiscard]] inline BMat8 operator()(BMat8 const&) const noexcept {
1045 return bmat8::one();
1046 }
1047
1048 [[nodiscard]] inline BMat8 operator()(size_t dim = 8) const noexcept {
1049 return bmat8::one(dim);
1050 }
1051 };
1052
1058 template <>
1059 struct Product<BMat8> {
1061 inline void operator()(BMat8& xy,
1062 BMat8 const& x,
1063 BMat8 const& y,
1064 size_t = 0) const noexcept {
1065 xy = x * y;
1066 }
1067 };
1068
1075 template <>
1080 BMat8 const& pt,
1081 BMat8 const& x) const noexcept {
1082 res = bmat8::row_space_basis(pt * x);
1083 }
1084 };
1085
1092 template <>
1097 BMat8 const& pt,
1098 BMat8 const& x) const noexcept {
1099 res = bmat8::col_space_basis(x * pt);
1100 }
1101 };
1102
1108 template <>
1109 struct Inverse<BMat8> {
1111 [[nodiscard]] inline BMat8 operator()(BMat8 const& x) const noexcept {
1112 LIBSEMIGROUPS_ASSERT(x * bmat8::transpose(x) == bmat8::one());
1113 return bmat8::transpose(x);
1114 }
1115 };
1116
1122 template <>
1126 using type = BMat8;
1127 };
1128
1134 template <>
1135 struct RhoValue<BMat8> {
1138 using type = BMat8;
1139 };
1140
1146 template <>
1147 struct Lambda<BMat8, BMat8> {
1150 // noexcept because bmat8::row_space_basis is noexcept
1151 inline void operator()(BMat8& res, BMat8 const& x) const noexcept {
1152 res = bmat8::row_space_basis(x);
1153 }
1154 };
1155
1160 template <>
1161 struct Rho<BMat8, BMat8> {
1164 // noexcept because bmat8::col_space_basis is noexcept
1165 inline void operator()(BMat8& res, BMat8 const& x) const noexcept {
1166 res = bmat8::col_space_basis(x);
1167 }
1168 };
1169
1175 template <>
1176 struct Rank<BMat8> {
1179 [[nodiscard]] inline size_t operator()(BMat8 const& x) const noexcept {
1180 return bmat8::row_space_size(x);
1181 }
1182 };
1183} // namespace libsemigroups
1184
1185#endif // LIBSEMIGROUPS_BMAT8_HPP_
Fast boolean matrices of dimension up to 8 x 8.
Definition bmat8.hpp:74
BMat8() noexcept=default
Default constructor.
constexpr bool operator>=(BMat8 const &that) const noexcept
Greater than or equal operator.
Definition bmat8.hpp:285
BitRef at(size_t r, size_t c)
Access entries in a matrix (with bound checks).
constexpr uint64_t to_int() const noexcept
Returns the integer representation of this.
Definition bmat8.hpp:454
constexpr BMat8(BMat8 &&) noexcept=default
Default move constructor.
BMat8 & operator*=(BMat8 const &that) noexcept
Multiply this by that in-place.
constexpr bool operator<(BMat8 const &that) const noexcept
Less than operator.
Definition bmat8.hpp:231
BMat8 operator*(BMat8 const &that) const noexcept
Returns the matrix product of this and that.
constexpr BMat8 & operator+=(BMat8 const &that) noexcept
Sum BMat8 objects (in-place).
Definition bmat8.hpp:553
constexpr BMat8 operator+(BMat8 const &that) const noexcept
Sum BMat8 objects.
Definition bmat8.hpp:535
constexpr BMat8 & operator*=(bool scalar) noexcept
Multiply a BMat8 by a scalar (in-place).
Definition bmat8.hpp:514
constexpr uint8_t operator()(size_t r) const noexcept
Access a row of a BMat8 (no bound checks).
Definition bmat8.hpp:346
constexpr bool operator!=(BMat8 const &that) const noexcept
Inequality operator.
Definition bmat8.hpp:213
constexpr bool operator()(size_t r, size_t c) const noexcept
Access entries in a matrix (no bound checks).
Definition bmat8.hpp:315
uint8_t at(size_t r) const
Access a row of a BMat8 (with bound checks).
BMat8(std::vector< std::vector< bool > > const &mat)
A constructor.
constexpr bool operator<=(BMat8 const &that) const noexcept
Less than or equal operator.
Definition bmat8.hpp:249
constexpr BMat8 & operator=(BMat8 const &) noexcept=default
Default copy assignment operator.
void swap(BMat8 &that) noexcept
Swaps this with that.
Definition bmat8.hpp:586
constexpr BMat8 operator*(bool scalar) const noexcept
Multiply a BMat8 by a scalar.
Definition bmat8.hpp:491
bool at(size_t r, size_t c) const
Access entries in a matrix (with bound checks).
constexpr BitRef operator()(size_t r, size_t c)
Access entries in a matrix (no bound checks).
Definition bmat8.hpp:403
constexpr BMat8(BMat8 const &) noexcept=default
Default copy constructor.
constexpr bool operator>(BMat8 const &that) const noexcept
Greater than operator.
Definition bmat8.hpp:267
std::string to_human_readable_repr(AhoCorasick const &ac)
Return a string representation.
Bipartition operator*(Bipartition const &x, Bipartition const &y)
Multiply two bipartitions.
std::ostringstream & operator<<(std::ostringstream &os, BMat8 const &x)
Insertion operator.
Namespace for BMat8 helper functions.
Definition bmat8.hpp:603
std::vector< bool > to_vector(uint8_t row)
Convert a uint8_t to a vector.
size_t minimum_dim(BMat8 const &x) noexcept
Returns the minimum dimension of a BMat8.
constexpr T one(size_t dim=8) noexcept
Returns the identity boolean matrix of a given dimension.
Definition bmat8.hpp:626
bool is_regular_element(BMat8 const &x) noexcept
Checks whether a BMat8 is regular in the monoid of all BMat8 objects.
BMat8 random()
Construct a random BMat8.
void push_back_rows(Container &rows, BMat8 const &x)
Push the rows of a BMat8 into the back of a container.
Definition bmat8.hpp:891
BMat8 col_space_basis(BMat8 const &x) noexcept
Find a basis for the column space of a BMat8.
Definition bmat8.hpp:747
size_t row_space_size(BMat8 const &x)
Returns the size of the row space of a BMat8.
std::vector< uint8_t > rows(BMat8 const &x)
Returns a vector of the rows of a BMat8.
constexpr BMat8 transpose(BMat8 const &x) noexcept
Returns the transpose of a BMat8.
Definition bmat8.hpp:704
size_t col_space_size(BMat8 const &x)
Returns the size of the column space of a BMat8.
Definition bmat8.hpp:835
constexpr size_t number_of_cols(BMat8 const &x) noexcept
Returns the number of non-zero columns in a BMat8.
Definition bmat8.hpp:800
constexpr size_t number_of_rows(BMat8 const &x) noexcept
Returns the number of non-zero rows in a BMat8.
Definition bmat8.hpp:769
BMat8 row_space_basis(BMat8 const &x) noexcept
Find a basis for the row space of a BMat8.
Namespace for everything in the libsemigroups library.
Definition action.hpp:44
T operator()(T... args)
constexpr size_t operator()(BMat8 const &) const noexcept
Returns 0; BMat8 multiplication is constant complexity.
Definition bmat8.hpp:1005
Adapter for the complexity of multiplication.
Definition adapters.hpp:121
constexpr size_t operator()(BMat8 const &) const noexcept
Returns 8; all BMat8s have degree 8.
Definition bmat8.hpp:1019
Adapter for the degree of an element.
Definition adapters.hpp:159
void operator()(BMat8 &res, BMat8 const &pt, BMat8 const &x) const noexcept
Definition bmat8.hpp:1096
Adapter for the value of a left action.
Definition adapters.hpp:350
void operator()(BMat8 &res, BMat8 const &pt, BMat8 const &x) const noexcept
Definition bmat8.hpp:1079
Adapter for the value of a right action.
Definition adapters.hpp:392
void operator()(BMat8 const &, size_t) const noexcept
Does nothing.
Definition bmat8.hpp:1033
Adapter for increasing the degree of an element.
Definition adapters.hpp:199
BMat8 operator()(BMat8 const &x) const noexcept
Returns the group inverse of x.
Definition bmat8.hpp:1111
Adapter for the inverse of an element.
Definition adapters.hpp:319
void operator()(BMat8 &res, BMat8 const &x) const noexcept
Definition bmat8.hpp:1151
Adapter for the action on LambdaValue's.
Definition adapters.hpp:833
BMat8 type
Definition bmat8.hpp:1126
Adapter for lambda functions.
Definition adapters.hpp:793
BMat8 operator()(size_t dim=8) const noexcept
Returns bmat8::one(dim)
Definition bmat8.hpp:1048
BMat8 operator()(BMat8 const &) const noexcept
Returns x.one()
Definition bmat8.hpp:1044
Adapter for the identity element of the given type.
Definition adapters.hpp:246
void operator()(BMat8 &xy, BMat8 const &x, BMat8 const &y, size_t=0) const noexcept
Changes xy in place to hold the product of x and y.
Definition bmat8.hpp:1061
Adapter for the product of two elements.
Definition adapters.hpp:284
size_t operator()(BMat8 const &x) const noexcept
Definition bmat8.hpp:1179
Adapter for calculating ranks.
Definition adapters.hpp:930
void operator()(BMat8 &res, BMat8 const &x) const noexcept
Definition bmat8.hpp:1165
Adapter for the action on RhoValue's.
Definition adapters.hpp:854
BMat8 type
Definition bmat8.hpp:1138
Adapter for rho functions.
Definition adapters.hpp:812
T swap(T... args)