From 650244fd793e49c262a458f364ffdadb6c030dda Mon Sep 17 00:00:00 2001 From: Joseph Edwards Date: Mon, 8 Jul 2024 20:10:34 +0100 Subject: [PATCH] Add tpp --- Makefile.am | 1 + include/libsemigroups/to-presentation.hpp | 90 ++------------- include/libsemigroups/to-presentation.tpp | 130 ++++++++++++++++++++++ 3 files changed, 143 insertions(+), 78 deletions(-) create mode 100644 include/libsemigroups/to-presentation.tpp diff --git a/Makefile.am b/Makefile.am index 778e02ab0..ead118cd2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -98,6 +98,7 @@ pkginclude_HEADERS += include/libsemigroups/stephen.tpp pkginclude_HEADERS += include/libsemigroups/to-froidure-pin.hpp pkginclude_HEADERS += include/libsemigroups/to-knuth-bendix.hpp pkginclude_HEADERS += include/libsemigroups/to-presentation.hpp +pkginclude_HEADERS += include/libsemigroups/to-presentation.tpp pkginclude_HEADERS += include/libsemigroups/to-todd-coxeter.hpp pkginclude_HEADERS += include/libsemigroups/todd-coxeter.hpp pkginclude_HEADERS += include/libsemigroups/transf.hpp diff --git a/include/libsemigroups/to-presentation.hpp b/include/libsemigroups/to-presentation.hpp index ab33047f6..d4dbbddc2 100644 --- a/include/libsemigroups/to-presentation.hpp +++ b/include/libsemigroups/to-presentation.hpp @@ -16,8 +16,6 @@ // along with this program. If not, see . // -// TODO(later) tpp file - #ifndef LIBSEMIGROUPS_TO_PRESENTATION_HPP_ #define LIBSEMIGROUPS_TO_PRESENTATION_HPP_ @@ -60,29 +58,7 @@ namespace libsemigroups { //! \exceptions //! \no_libsemigroups_except template - // TODO(later) why not just to_presentation with no template WordOutput, - // always use word_type, and can be converted after if desirable - Presentation to_presentation(FroidurePinBase& fp) { - Presentation p; - p.alphabet(fp.number_of_generators()); - WordOutput lhs, rhs; - auto f = [](auto val) { - return presentation::human_readable_letter(val); - }; - - for (auto it = fp.cbegin_rules(); it != fp.cend_rules(); ++it) { - lhs.resize(it->first.size()); - rhs.resize(it->second.size()); - std::transform(it->first.cbegin(), it->first.cend(), lhs.begin(), f); - std::transform(it->second.cbegin(), it->second.cend(), rhs.begin(), f); - p.rules.push_back(std::move(lhs)); - p.rules.push_back(std::move(rhs)); - lhs.clear(); - rhs.clear(); - } - - return p; - } + Presentation to_presentation(FroidurePinBase& fp); #ifdef PARSED_BY_DOXYGEN //! \ingroup to_presentation_group @@ -122,28 +98,7 @@ namespace libsemigroups { typename Presentation::letter_type> && !std::is_same_v>> Presentation to_presentation(Presentation const& p, - Func&& f) { - p.validate(); - // Must call p.validate otherwise f(val) may segfault if val is not in the - // alphabet - - Presentation result; - result.contains_empty_word(p.contains_empty_word()); - WordOutput new_alphabet; - new_alphabet.resize(p.alphabet().size()); - std::transform( - p.alphabet().cbegin(), p.alphabet().cend(), new_alphabet.begin(), f); - // TODO(later) use alphabet_no_checks when it is implemented - result.alphabet(new_alphabet); - WordOutput rel; - for (auto it = p.rules.cbegin(); it != p.rules.cend(); ++it) { - rel.resize(it->size()); - std::transform(it->cbegin(), it->cend(), rel.begin(), f); - result.rules.push_back(std::move(rel)); - rel.clear(); - } - return result; - } + Func&& f); #endif #ifdef PARSED_BY_DOXYGEN @@ -178,11 +133,7 @@ namespace libsemigroups { template auto to_presentation(Presentation const& p) -> std::enable_if_t, - Presentation> { - return to_presentation(p, [&p](auto val) { - return presentation::human_readable_letter(p.index(val)); - }); - } + Presentation>; #endif #ifdef PARSED_BY_DOXYGEN @@ -226,18 +177,7 @@ namespace libsemigroups { typename Presentation::letter_type> && !std::is_same_v>> InversePresentation - to_inverse_presentation(InversePresentation const& ip, Func&& f) { - ip.validate_word(ip.inverses().begin(), ip.inverses().end()); - InversePresentation result( - std::move(to_presentation(ip, f))); - - WordOutput new_inverses; - new_inverses.resize(ip.inverses().size()); - std::transform( - ip.inverses().cbegin(), ip.inverses().cend(), new_inverses.begin(), f); - result.inverses_no_checks(new_inverses); - return result; - } + to_inverse_presentation(InversePresentation const& ip, Func&& f); #endif //! \ingroup to_presentation_group @@ -259,19 +199,14 @@ namespace libsemigroups { //! \throws LibsemigroupsException if `p.validate()` throws. template InversePresentation - to_inverse_presentation(Presentation const& p) { - InversePresentation result(p); - presentation::normalize_alphabet(result); - result.alphabet(2 * result.alphabet().size()); - auto invs = result.alphabet(); - std::rotate(invs.begin(), invs.begin() + invs.size() / 2, invs.end()); - result.inverses_no_checks(std::move(invs)); - return result; - } + to_inverse_presentation(Presentation const& p); //! No doc // TODO(now) is this the correct way to prevent the nonsensical conversion of // an inverse presentation to an inverse presentation of the same type? + // JDE wanted some way of preventing the user from calling + // to_inverse_presentation(Presentaion const& p) in the case where p is, + // in fact, already an inverse presentation. template InversePresentation to_inverse_presentation(InversePresentation const& ip) { @@ -314,12 +249,11 @@ namespace libsemigroups { template auto to_inverse_presentation(InversePresentation const& ip) -> std::enable_if_t, - InversePresentation> { - return to_inverse_presentation(ip, [&ip](auto val) { - return presentation::human_readable_letter(ip.index(val)); - }); - } + InversePresentation>; #endif } // namespace libsemigroups + +#include "to-presentation.tpp" + #endif // LIBSEMIGROUPS_TO_PRESENTATION_HPP_ diff --git a/include/libsemigroups/to-presentation.tpp b/include/libsemigroups/to-presentation.tpp new file mode 100644 index 000000000..0bb508410 --- /dev/null +++ b/include/libsemigroups/to-presentation.tpp @@ -0,0 +1,130 @@ +// +// libsemigroups - C++ library for semigroups and monoids +// Copyright (C) 2023 - 2024 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 . +// + +namespace libsemigroups { + + template + // TODO(later) why not just to_presentation with no template WordOutput, + // always use word_type, and can be converted after if desirable + Presentation to_presentation(FroidurePinBase& fp) { + Presentation p; + p.alphabet(fp.number_of_generators()); + WordOutput lhs, rhs; + auto f = [](auto val) { + return presentation::human_readable_letter(val); + }; + + for (auto it = fp.cbegin_rules(); it != fp.cend_rules(); ++it) { + lhs.resize(it->first.size()); + rhs.resize(it->second.size()); + std::transform(it->first.cbegin(), it->first.cend(), lhs.begin(), f); + std::transform(it->second.cbegin(), it->second.cend(), rhs.begin(), f); + p.rules.push_back(std::move(lhs)); + p.rules.push_back(std::move(rhs)); + lhs.clear(); + rhs.clear(); + } + + return p; + } + + template < + typename WordOutput, + typename WordInput, + typename Func, + typename = std::enable_if_t< + std::is_invocable_v, + typename Presentation::letter_type> + && !std::is_same_v>> + Presentation to_presentation(Presentation const& p, + Func&& f) { + p.validate(); + // Must call p.validate otherwise f(val) may segfault if val is not in the + // alphabet + + Presentation result; + result.contains_empty_word(p.contains_empty_word()); + WordOutput new_alphabet; + new_alphabet.resize(p.alphabet().size()); + std::transform( + p.alphabet().cbegin(), p.alphabet().cend(), new_alphabet.begin(), f); + // TODO(later) use alphabet_no_checks when it is implemented + result.alphabet(new_alphabet); + WordOutput rel; + for (auto it = p.rules.cbegin(); it != p.rules.cend(); ++it) { + rel.resize(it->size()); + std::transform(it->cbegin(), it->cend(), rel.begin(), f); + result.rules.push_back(std::move(rel)); + rel.clear(); + } + return result; + } + + template + auto to_presentation(Presentation const& p) + -> std::enable_if_t, + Presentation> { + return to_presentation(p, [&p](auto val) { + return presentation::human_readable_letter(p.index(val)); + }); + } + + template < + typename WordOutput, + typename WordInput, + typename Func, + typename = std::enable_if_t< + std::is_invocable_v, + typename Presentation::letter_type> + && !std::is_same_v>> + InversePresentation + to_inverse_presentation(InversePresentation const& ip, Func&& f) { + ip.validate_word(ip.inverses().begin(), ip.inverses().end()); + InversePresentation result( + std::move(to_presentation(ip, f))); + + WordOutput new_inverses; + new_inverses.resize(ip.inverses().size()); + std::transform( + ip.inverses().cbegin(), ip.inverses().cend(), new_inverses.begin(), f); + result.inverses_no_checks(new_inverses); + return result; + } + + template + InversePresentation + to_inverse_presentation(Presentation const& p) { + InversePresentation result(p); + presentation::normalize_alphabet(result); + result.alphabet(2 * result.alphabet().size()); + auto invs = result.alphabet(); + std::rotate(invs.begin(), invs.begin() + invs.size() / 2, invs.end()); + result.inverses_no_checks(std::move(invs)); + return result; + } + + template + auto to_inverse_presentation(InversePresentation const& ip) + -> std::enable_if_t, + InversePresentation> { + return to_inverse_presentation(ip, [&ip](auto val) { + return presentation::human_readable_letter(ip.index(val)); + }); + } + +} // namespace libsemigroups \ No newline at end of file