//
// 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 KBE, which can be used as
// the element_type for a FroidurePin instance. This class just wraps a
// reduced word of a KnuthBendix instance.
// For technical reasons this is implemented in src/kbe-impl.hpp
#ifndef LIBSEMIGROUPS_KBE_HPP_
#define LIBSEMIGROUPS_KBE_HPP_
#include <cstddef>
// for size_t
#include <string>
// for string
#include <utility>
// for hash
#include "adapters.hpp" // for One
#include "froidure-pin.hpp" // for FroidurePin
#include "knuth-bendix.hpp" // for fpsemigroup::KnuthBendix
#include "types.hpp" // for word_type, letter_type
namespace libsemigroups {
namespace detail {
// This class is used to wrap libsemigroups::internal_string_type into an
// object that can be used as generators for a FroidurePin object.
class KBE final {
using KnuthBendix = fpsemigroup::KnuthBendix;
using internal_string_type = std::string;
KBE(internal_string_type
const&);
KBE(internal_string_type&&);
public:
KBE() =
default;
KBE(KBE
const&) =
default;
KBE(KBE&&) =
default;
KBE&
operator=(KBE
const&) =
default;
KBE&
operator=(KBE&&) =
default;
~KBE() =
default;
// Construct from internal string
KBE(KnuthBendix&, internal_string_type
const&);
KBE(KnuthBendix&, internal_string_type&&);
// Construct from external types
KBE(KnuthBendix&, letter_type
const&);
KBE(KnuthBendix&, word_type
const&);
bool operator==(KBE
const&)
const;
bool operator<(KBE
const&)
const;
void swap(KBE&);
internal_string_type
const& string()
const noexcept;
std::string string(KnuthBendix
const& kb)
const;
word_type word(KnuthBendix
const& kb)
const;
friend std::ostringstream&
operator<<(std::ostringstream& os,
KBE
const& kbe) {
os << kbe.string();
return os;
}
private:
internal_string_type _kb_word;
};
// 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<KBE>::value,
"KBE is trivial!!!");
static_assert(std::integral_constant<
bool, (
sizeof(KBE) <= 32)>::value,
"KBE's sizeof exceeds 32!!");
}
// namespace detail
////////////////////////////////////////////////////////////////////////
// Adapters for KBE class
////////////////////////////////////////////////////////////////////////
template <>
struct Complexity<detail::KBE> {
constexpr size_t
operator()(detail::KBE
const&)
const noexcept {
return LIMIT_MAX;
}
};
template <>
struct Degree<detail::KBE> {
constexpr size_t
operator()(detail::KBE
const&)
const noexcept {
return 0;
}
};
template <>
struct IncreaseDegree<detail::KBE> {
void operator()(detail::KBE
const&, size_t)
const noexcept {}
};
template <>
struct One<detail::KBE> {
detail::KBE
operator()(detail::KBE
const&)
const noexcept {
return detail::KBE();
}
detail::KBE
operator()(size_t = 0)
const noexcept {
return detail::KBE();
}
};
template <>
struct Product<detail::KBE> {
void operator()(detail::KBE& xy,
detail::KBE
const& x,
detail::KBE
const& y,
fpsemigroup::KnuthBendix* kb,
size_t) {
std::string w(x.string());
// internal_string_type
w += y.string();
xy = detail::KBE(*kb, w);
}
};
template <>
word_type
FroidurePin<detail::KBE,
FroidurePinTraits<detail::KBE, fpsemigroup::KnuthBendix>>::
factorisation(detail::KBE
const& x);
template <>
tril FroidurePin<detail::KBE,
FroidurePinTraits<detail::KBE, fpsemigroup::KnuthBendix>>::
is_finite()
const;
}
// namespace libsemigroups
////////////////////////////////////////////////////////////////////////
// Specializations of std::hash and std::equal_to
////////////////////////////////////////////////////////////////////////
namespace std {
template <>
struct hash<libsemigroups::detail::KBE> {
size_t
operator()(libsemigroups::detail::KBE
const& x)
const {
return hash<string>()(x.string());
}
};
template <>
struct equal_to<libsemigroups::detail::KBE> {
bool operator()(libsemigroups::detail::KBE
const& x,
libsemigroups::detail::KBE
const& y)
const {
return x == y;
}
};
}
// namespace std
#endif // LIBSEMIGROUPS_KBE_HPP_