//
// libsemigroups - C++ library for semigroups and monoids
// Copyright (C) 2019 James D. Mitchell
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// This file contains the declaration of the class TCE, which is a
// wrapper around congruence::ToddCoxeter class indices, that can be used as
// the template parameter TElementType for the FroidurePin class template.
// This file also contains specializations of the adapters complexity, degree,
// less, one, product, and std::hash for TCE.
#ifndef LIBSEMIGROUPS_TCE_HPP_
#define LIBSEMIGROUPS_TCE_HPP_
#include <cstddef>
// for size_t
#include <sstream>
// for ostream, ostringstream
#include <type_traits>
// for integral_constant
#include <utility>
// for hash
#include "adapters.hpp" // for Complexity, Degree, Less, One, Product, ...
#include "constants.hpp" // for LIMIT_MAX
#include "string.hpp" // for to_string
#include "todd-coxeter.hpp" // for ToddCoxeter
namespace libsemigroups {
// Forward declarations
namespace congruence {
class ToddCoxeter;
}
// namespace congruence
namespace detail {
class TCE {
using ToddCoxeter = congruence::ToddCoxeter;
public:
using coset_type =
typename ToddCoxeter::coset_type;
using Table =
typename ToddCoxeter::table_type;
TCE() noexcept =
default;
TCE(TCE
const&) noexcept =
default;
TCE(TCE&&) noexcept =
default;
TCE&
operator=(TCE
const&) noexcept =
default;
TCE&
operator=(TCE&&) noexcept =
default;
~TCE() =
default;
explicit TCE(coset_type i) noexcept : _index(i) {}
bool operator==(TCE
const& that)
const noexcept {
return _index == that._index;
}
bool operator<(TCE
const& that)
const noexcept {
return _index < that._index;
}
TCE one()
const noexcept {
return TCE(0);
}
operator coset_type()
const {
return _index;
}
private:
// Note that the value of the class_index_type _value below is the actual
// class_index_type used in the ToddCoxeter class and not that number
// minus 1, which is what "class_index" means in the context of
// CongruenceInterface objects.
coset_type _index;
};
// The following are not really required but are here as a reminder that
// KBE are used in BruidhinnTraits which depends on the values in the
// static_asserts below.
static_assert(std::is_trivial<TCE>::value,
"TCE is not trivial!!!");
static_assert(std::integral_constant<
bool, (
sizeof(TCE) <= 8)>::value,
"TCE's sizeof exceeds 8!!");
}
// namespace detail
//! No doc
inline std::ostringstream&
operator<<(std::ostringstream& os,
detail::TCE
const& x) {
os <<
"TCE(" << detail::TCE::coset_type(x) <<
")";
return os;
}
//! No doc
inline std::ostream&
operator<<(std::ostream& os, detail::TCE
const& x) {
os << detail::to_string(x);
return os;
}
// Specialization of the adapter libsemigroups::Complexity for detail::TCE.
template <>
struct Complexity<detail::TCE> {
// Returns LIMIT_MAX, because it is not possible to multiply arbitrary TCE
// instances, only arbitrary TCE by a TCE representing a generator (see
// TCE::operator*). This adapter is used by the FroidurePin class to
// determine if it is better to trace paths in the Cayley graph or to
// directly multiply elements (using the \c * operator). Since LIMIT_MAX is
// returned, elements are not directly multiplied by the \c * operator
// (except if the right hand argument represents a TCE).
constexpr size_t
operator()(detail::TCE
const&)
const noexcept {
return LIMIT_MAX;
}
};
template <>
struct Degree<detail::TCE> {
constexpr size_t
operator()(detail::TCE
const&)
const noexcept {
return 0;
}
};
template <>
struct IncreaseDegree<detail::TCE> {
void operator()(detail::TCE
const&, size_t)
const noexcept {}
};
//! Specialization of the adapter libsemigroups::One for TCE.
template <>
struct One<detail::TCE> {
//! This directly uses the member function TCE::one.
detail::TCE
operator()(detail::TCE
const& x)
const noexcept {
return x.one();
}
};
template <>
struct Product<detail::TCE> {
void operator()(detail::TCE& xy,
detail::TCE
const& x,
detail::TCE
const& y,
detail::TCE::Table* t,
size_t = 0)
const {
xy = detail::TCE(t->get(x, y - 1));
}
};
}
// namespace libsemigroups
namespace std {
template <>
struct hash<libsemigroups::detail::TCE> {
using coset_type = libsemigroups::detail::TCE::coset_type;
size_t
operator()(libsemigroups::detail::TCE
const& x)
const noexcept {
return std::hash<coset_type>()(x);
}
};
}
// namespace std
#endif // LIBSEMIGROUPS_TCE_HPP_