libsemigroups  v3.5.1
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
bmat8.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2019-2026 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 <memory> // for hash
33#include <string> // for string
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#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION
41
42#ifdef LIBSEMIGROUPS_HPCOMBI_ENABLED
43namespace HPCombi {
44 class BMat8;
45}
46#endif // LIBSEMIGROUPS_HPCOMBI_ENABLED
47
48namespace libsemigroups {
49
54
68
81 class BMat8 {
82 uint64_t _data;
83 // Proxy class for reference to bits in the matrix
84 class BitRef {
85 private:
86 uint64_t& _data;
87 uint64_t _mask;
88
89 public:
90 // Constructor: takes a reference to a byte and the index of the bit in
91 // that byte
92 constexpr BitRef(uint64_t& data, size_t index) noexcept
93 : _data(data), _mask(static_cast<uint64_t>(1) << (63 - index)) {}
94
95 // Assignment operator to allow setting the bit through the proxy
96 constexpr BitRef& operator=(bool val) noexcept {
97 _data ^= (-val ^ _data) & _mask;
98 return *this;
99 }
100
101 // Conversion operator to read the value of the bit as a boolean
102 [[nodiscard]] constexpr operator bool() const {
103 return _data & _mask;
104 }
105 };
106
107 public:
117 BMat8() noexcept = default;
118
131 constexpr explicit BMat8(uint64_t mat) noexcept : _data(mat) {}
132
148 explicit BMat8(std::vector<std::vector<bool>> const& mat);
149
157 constexpr BMat8(BMat8 const&) noexcept = default;
158
166 constexpr BMat8(BMat8&&) noexcept = default;
167
175 constexpr BMat8& operator=(BMat8 const&) noexcept = default;
176
184 constexpr BMat8& operator=(BMat8&&) noexcept = default;
185
186 ~BMat8() = default;
187
202 [[nodiscard]] constexpr bool operator==(BMat8 const& that) const noexcept {
203 return _data == that._data;
204 }
205
220 [[nodiscard]] constexpr bool operator!=(BMat8 const& that) const noexcept {
221 return _data != that._data;
222 }
223
238 [[nodiscard]] constexpr bool operator<(BMat8 const& that) const noexcept {
239 return _data < that._data;
240 }
241
256 [[nodiscard]] constexpr bool operator<=(BMat8 const& that) const noexcept {
257 return *this < that || *this == that;
258 }
259
274 [[nodiscard]] constexpr bool operator>(BMat8 const& that) const noexcept {
275 return _data > that._data;
276 }
277
292 [[nodiscard]] constexpr bool operator>=(BMat8 const& that) const noexcept {
293 return *this > that || *this == that;
294 }
295
322 [[nodiscard]] constexpr bool operator()(size_t r, size_t c) const noexcept {
323 LIBSEMIGROUPS_ASSERT(r < 8);
324 LIBSEMIGROUPS_ASSERT(c < 8);
325 return (_data << (8 * r + c)) >> 63;
326 }
327
353 [[nodiscard]] constexpr uint8_t operator()(size_t r) const noexcept {
354 LIBSEMIGROUPS_ASSERT(r < 8);
355 return static_cast<uint8_t>(to_int() << 8 * r >> 56);
356 }
357
381 [[nodiscard]] uint8_t at(size_t r) const;
382
410 [[nodiscard]] constexpr BitRef operator()(size_t r, size_t c) {
411 return BitRef(_data, 8 * r + c);
412 }
413
428 [[nodiscard]] bool at(size_t r, size_t c) const;
429
444 [[nodiscard]] BitRef at(size_t r, size_t c);
445
461 [[nodiscard]] constexpr inline uint64_t to_int() const noexcept {
462 return _data;
463 }
464
481 [[nodiscard]] BMat8 operator*(BMat8 const& that) const noexcept;
482
498 [[nodiscard]] constexpr BMat8 operator*(bool scalar) const noexcept {
499 if (scalar) {
500 return *this;
501 } else {
502 return BMat8(0);
503 }
504 }
505
521 constexpr BMat8& operator*=(bool scalar) noexcept {
522 if (!scalar) {
523 _data = 0;
524 }
525 return *this;
526 }
527
542 [[nodiscard]] constexpr BMat8 operator+(BMat8 const& that) const noexcept {
543 return BMat8(_data | that._data);
544 }
545
560 constexpr BMat8& operator+=(BMat8 const& that) noexcept {
561 _data |= that._data;
562 return *this;
563 }
564
580 BMat8& operator*=(BMat8 const& that) noexcept;
581
593 inline void swap(BMat8& that) noexcept {
594 std::swap(this->_data, that._data);
595 }
596 };
597
598 static_assert(std::is_trivial<BMat8>(), "BMat8 is not a trivial class!");
599
610 namespace bmat8 {
631 template <typename T>
632 [[nodiscard]] constexpr T one(size_t dim = 8) {
633#ifdef LIBSEMIGROUPS_HPCOMBI_ENABLED
634 static_assert(std::is_same_v<T, BMat8>
635 || std::is_same_v<T, HPCombi::BMat8>);
636#else
637 static_assert(std::is_same_v<T, BMat8>);
638#endif
639 if (dim > 8) {
641 "the argument (dimension) must be at most 8, found {}", dim);
642 }
643 constexpr std::array<uint64_t, 9> const ones = {0x0000000000000000,
644 0x8000000000000000,
645 0x8040000000000000,
646 0x8040200000000000,
647 0x8040201000000000,
648 0x8040201008000000,
649 0x8040201008040000,
650 0x8040201008040200,
651 0x8040201008040201};
652 return T(ones[dim]);
653 }
654
671 [[nodiscard]] constexpr BMat8 one(size_t dim = 8) {
672 return one<BMat8>(dim);
673 }
674
684 // Not noexcept since std::uniform_int_distribution::operator() is not
685 // noexcept.
686 [[nodiscard]] BMat8 random();
687
700 // Not noexcept since std::uniform_int_distribution::operator() is not
701 // noexcept.
702 [[nodiscard]] BMat8 random(size_t dim);
703
719 [[nodiscard]] constexpr BMat8 transpose(BMat8 const& x) noexcept {
720 uint64_t y = x.to_int();
721 uint64_t z = (y ^ (y >> 7)) & 0xAA00AA00AA00AA;
722 y = y ^ z ^ (z << 7);
723 z = (y ^ (y >> 14)) & 0xCCCC0000CCCC;
724 y = y ^ z ^ (z << 14);
725 z = (y ^ (y >> 28)) & 0xF0F0F0F0;
726 y = y ^ z ^ (z << 28);
727 return BMat8(y);
728 }
729
745 [[nodiscard]] BMat8 row_space_basis(BMat8 const& x) noexcept;
746
762 [[nodiscard]] inline BMat8 col_space_basis(BMat8 const& x) noexcept {
764 }
765
784 [[nodiscard]] constexpr size_t number_of_rows(BMat8 const& x) noexcept {
785 size_t count = 0;
786 for (size_t i = 0; i < 8; ++i) {
787 if (x.to_int() << (8 * i) >> 56 > 0) {
788 count++;
789 }
790 }
791 return count;
792 }
793
794 // TODO(2) these should be templated to allow using HPCombi::BMat8's
795 // here too.
814 // noexcept because transpose and number_of_rows are.
815 [[nodiscard]] constexpr size_t number_of_cols(BMat8 const& x) noexcept {
816 return number_of_rows(transpose(x));
817 }
818
833 [[nodiscard]] size_t row_space_size(BMat8 const& x);
834
849 // Not noexcept because row_space_size isn't.
850 [[nodiscard]] inline size_t col_space_size(BMat8 const& x) {
851 return row_space_size(transpose(x));
852 }
853
869 [[nodiscard]] size_t minimum_dim(BMat8 const& x) noexcept;
870
887 [[nodiscard]] std::vector<uint8_t> rows(BMat8 const& x);
888
905 template <typename Container>
906 void push_back_rows(Container& rows, BMat8 const& x) {
907 static_assert(std::is_same_v<typename Container::value_type, uint8_t>);
908 for (size_t i = 0; i < 8; ++i) {
909 rows.push_back(x(i));
910 }
911 }
912
930 [[nodiscard]] bool is_regular_element(BMat8 const& x) noexcept;
931
946
947 } // namespace bmat8
948
955
962
972 std::string const& braces = "{}");
973
983 [[nodiscard]] constexpr BMat8 operator*(bool scalar,
984 BMat8 const& x) noexcept {
985 if (scalar) {
986 return x;
987 } else {
988 return BMat8(0);
989 }
990 }
991} // namespace libsemigroups
992
993namespace std {
994 template <>
995 struct hash<libsemigroups::BMat8> {
996 size_t operator()(libsemigroups::BMat8 const& bm) const {
997 return hash<uint64_t>()(bm.to_int());
998 }
999 };
1000} // namespace std
1001
1002namespace libsemigroups {
1011
1016 template <>
1019 [[nodiscard]] constexpr inline size_t
1020 operator()(BMat8 const&) const noexcept {
1021 return 0;
1022 }
1023 };
1024
1030 template <>
1031 struct Degree<BMat8> {
1033 [[nodiscard]] constexpr inline size_t
1034 operator()(BMat8 const&) const noexcept {
1035 return 8;
1036 }
1037 };
1038
1045 template <>
1048 inline void operator()(BMat8 const&, size_t) const noexcept {}
1049 };
1050
1056 template <>
1057 struct One<BMat8> {
1059 [[nodiscard]] inline BMat8 operator()(BMat8 const&) const noexcept {
1060 return bmat8::one();
1061 }
1062
1063 [[nodiscard]] inline BMat8 operator()(size_t dim = 8) const {
1064 return bmat8::one(dim);
1065 }
1066 };
1067
1073 template <>
1074 struct Product<BMat8> {
1076 inline void operator()(BMat8& xy,
1077 BMat8 const& x,
1078 BMat8 const& y,
1079 size_t = 0) const noexcept {
1080 xy = x * y;
1081 }
1082 };
1083
1090 template <>
1095 BMat8 const& pt,
1096 BMat8 const& x) const noexcept {
1097 res = bmat8::row_space_basis(pt * x);
1098 }
1099 };
1100
1107 template <>
1112 BMat8 const& pt,
1113 BMat8 const& x) const noexcept {
1114 res = bmat8::col_space_basis(x * pt);
1115 }
1116 };
1117
1123 template <>
1124 struct Inverse<BMat8> {
1126 [[nodiscard]] inline BMat8 operator()(BMat8 const& x) const noexcept {
1127 LIBSEMIGROUPS_ASSERT(x * bmat8::transpose(x) == bmat8::one());
1128 return bmat8::transpose(x);
1129 }
1130 };
1131
1137 template <>
1141 using type = BMat8;
1142 };
1143
1149 template <>
1150 struct RhoValue<BMat8> {
1153 using type = BMat8;
1154 };
1155
1161 template <>
1162 struct Lambda<BMat8, BMat8> {
1165 // noexcept because bmat8::row_space_basis is noexcept
1166 inline void operator()(BMat8& res, BMat8 const& x) const noexcept {
1167 res = bmat8::row_space_basis(x);
1168 }
1169 };
1170
1175 template <>
1176 struct Rho<BMat8, BMat8> {
1179 // noexcept because bmat8::col_space_basis is noexcept
1180 inline void operator()(BMat8& res, BMat8 const& x) const noexcept {
1181 res = bmat8::col_space_basis(x);
1182 }
1183 };
1184
1190 template <>
1191 struct Rank<BMat8> {
1194 [[nodiscard]] inline size_t operator()(BMat8 const& x) const noexcept {
1195 return bmat8::row_space_size(x);
1196 }
1197 };
1198} // namespace libsemigroups
1199
1200#endif // LIBSEMIGROUPS_BMAT8_HPP_
Fast boolean matrices of dimension up to 8 x 8.
Definition bmat8.hpp:81
BMat8() noexcept=default
Default constructor.
constexpr bool operator>=(BMat8 const &that) const noexcept
Greater than or equal operator.
Definition bmat8.hpp:292
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:461
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:238
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:560
constexpr BMat8 operator+(BMat8 const &that) const noexcept
Sum BMat8 objects.
Definition bmat8.hpp:542
constexpr BMat8 & operator*=(bool scalar) noexcept
Multiply a BMat8 by a scalar (in-place).
Definition bmat8.hpp:521
constexpr uint8_t operator()(size_t r) const noexcept
Access a row of a BMat8 (no bound checks).
Definition bmat8.hpp:353
constexpr bool operator!=(BMat8 const &that) const noexcept
Inequality operator.
Definition bmat8.hpp:220
constexpr bool operator()(size_t r, size_t c) const noexcept
Access entries in a matrix (no bound checks).
Definition bmat8.hpp:322
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:256
constexpr BMat8 & operator=(BMat8 const &) noexcept=default
Default copy assignment operator.
void swap(BMat8 &that) noexcept
Swaps this with that.
Definition bmat8.hpp:593
constexpr BMat8 operator*(bool scalar) const noexcept
Multiply a BMat8 by a scalar.
Definition bmat8.hpp:498
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:410
constexpr BMat8(BMat8 const &) noexcept=default
Default copy constructor.
constexpr bool operator>(BMat8 const &that) const noexcept
Greater than operator.
Definition bmat8.hpp:274
std::string to_human_readable_repr(Action< Element, Point, Func, Traits, LeftOrRight > const &action)
Return a human readable representation of an Action object.
Bipartition operator*(Bipartition const &x, Bipartition const &y)
Multiply two bipartitions.
std::ostringstream & operator<<(std::ostringstream &os, BMat8 const &x)
Insertion operator.
#define LIBSEMIGROUPS_EXCEPTION(...)
Throw a LibsemigroupsException.
Definition exception.hpp:99
Namespace for BMat8 helper functions.
Definition bmat8.hpp:610
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.
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:906
constexpr T one(size_t dim=8)
Returns the identity boolean matrix of a given dimension.
Definition bmat8.hpp:632
BMat8 col_space_basis(BMat8 const &x) noexcept
Find a basis for the column space of a BMat8.
Definition bmat8.hpp:762
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:719
size_t col_space_size(BMat8 const &x)
Returns the size of the column space of a BMat8.
Definition bmat8.hpp:850
constexpr size_t number_of_cols(BMat8 const &x) noexcept
Returns the number of non-zero columns in a BMat8.
Definition bmat8.hpp:815
constexpr size_t number_of_rows(BMat8 const &x) noexcept
Returns the number of non-zero rows in a BMat8.
Definition bmat8.hpp:784
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:1020
Adapter for the complexity of multiplication.
Definition adapters.hpp:128
constexpr size_t operator()(BMat8 const &) const noexcept
Returns 8; all BMat8s have degree 8.
Definition bmat8.hpp:1034
Adapter for the degree of an element.
Definition adapters.hpp:166
void operator()(BMat8 &res, BMat8 const &pt, BMat8 const &x) const noexcept
Definition bmat8.hpp:1111
Adapter for the value of a left action.
Definition adapters.hpp:357
void operator()(BMat8 &res, BMat8 const &pt, BMat8 const &x) const noexcept
Definition bmat8.hpp:1094
Adapter for the value of a right action.
Definition adapters.hpp:399
void operator()(BMat8 const &, size_t) const noexcept
Does nothing.
Definition bmat8.hpp:1048
Adapter for increasing the degree of an element.
Definition adapters.hpp:206
BMat8 operator()(BMat8 const &x) const noexcept
Returns the group inverse of x.
Definition bmat8.hpp:1126
Adapter for the inverse of an element.
Definition adapters.hpp:326
void operator()(BMat8 &res, BMat8 const &x) const noexcept
Definition bmat8.hpp:1166
Adapter for the action on LambdaValue's.
Definition adapters.hpp:840
BMat8 type
Definition bmat8.hpp:1141
Adapter for lambda functions.
Definition adapters.hpp:800
BMat8 operator()(size_t dim=8) const
Returns bmat8::one(dim)
Definition bmat8.hpp:1063
BMat8 operator()(BMat8 const &) const noexcept
Returns x.one()
Definition bmat8.hpp:1059
Adapter for the identity element of the given type.
Definition adapters.hpp:253
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:1076
Adapter for the product of two elements.
Definition adapters.hpp:291
size_t operator()(BMat8 const &x) const noexcept
Definition bmat8.hpp:1194
Adapter for calculating ranks.
Definition adapters.hpp:937
void operator()(BMat8 &res, BMat8 const &x) const noexcept
Definition bmat8.hpp:1180
Adapter for the action on RhoValue's.
Definition adapters.hpp:861
BMat8 type
Definition bmat8.hpp:1153
Adapter for rho functions.
Definition adapters.hpp:819
T swap(T... args)