Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libsemigroups for openSUSE:Factory checked in at 2025-08-13 16:31:08 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libsemigroups (Old) and /work/SRC/openSUSE:Factory/.libsemigroups.new.1085 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libsemigroups" Wed Aug 13 16:31:08 2025 rev:35 rq:1299169 version:3.1.3 Changes: -------- --- /work/SRC/openSUSE:Factory/libsemigroups/libsemigroups.changes 2025-07-30 11:44:52.401470053 +0200 +++ /work/SRC/openSUSE:Factory/.libsemigroups.new.1085/libsemigroups.changes 2025-08-13 16:33:22.611575464 +0200 @@ -1,0 +2,11 @@ +Wed Aug 13 00:32:27 UTC 2025 - Jan Engelhardt <jeng...@inai.de> + +- Update to release 3.1.3 + * Add a `to_human_readable_repr` function for the `Action` class. + * Update the `to_human_readable_repr` of the `Congruence` class + to be more consistent with the `KnuthBendix` and `ToddCoxeter` + classes. + * Mark `IsBipartition`, `IsPBR`, `IsPresentation`, + `IsInversePresentation` and `IsWordGraph` as deprecated. + +------------------------------------------------------------------- Old: ---- v3.1.2.tar.gz New: ---- v3.1.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libsemigroups.spec ++++++ --- /var/tmp/diff_new_pack.9w3uSr/_old 2025-08-13 16:33:24.439652110 +0200 +++ /var/tmp/diff_new_pack.9w3uSr/_new 2025-08-13 16:33:24.439652110 +0200 @@ -18,7 +18,7 @@ Name: libsemigroups %define lname libsemigroups3 -Version: 3.1.2 +Version: 3.1.3 Release: 0 Summary: Library with algorithms for computing finite and finitely presented semigroups License: GPL-3.0-or-later ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.9w3uSr/_old 2025-08-13 16:33:24.475653619 +0200 +++ /var/tmp/diff_new_pack.9w3uSr/_new 2025-08-13 16:33:24.475653619 +0200 @@ -1,5 +1,5 @@ -mtime: 1753826701 -commit: 5be55ea33a3f05c2057445c049c04c7fc42d5905e7babaf2610fb679c7d44de6 +mtime: 1755045206 +commit: 96d5578d4b33904b454fb58b04d2e3819a6bc401ad89689571bbd4478b1d6a66 url: https://src.opensuse.org/jengelh/libsemigroups revision: master ++++++ build.specials.obscpio ++++++ ++++++ v3.1.2.tar.gz -> v3.1.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/CITATION.cff new/libsemigroups-3.1.3/CITATION.cff --- old/libsemigroups-3.1.2/CITATION.cff 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/CITATION.cff 2025-08-12 14:48:26.000000000 +0200 @@ -33,5 +33,5 @@ algorithms for computing finite, and finitely presented, semigroups and monoids. license: GPL-3.0 -version: 3.1.2 -date-released: "2025-07-29" +version: 3.1.3 +date-released: "2025-08-12" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/Makefile.am new/libsemigroups-3.1.3/Makefile.am --- old/libsemigroups-3.1.2/Makefile.am 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/Makefile.am 2025-08-12 14:48:26.000000000 +0200 @@ -72,6 +72,7 @@ pkginclude_HEADERS += include/libsemigroups/gabow.hpp pkginclude_HEADERS += include/libsemigroups/gabow.tpp pkginclude_HEADERS += include/libsemigroups/hpcombi.hpp +pkginclude_HEADERS += include/libsemigroups/is_specialization_of.hpp pkginclude_HEADERS += include/libsemigroups/kambites-class.hpp pkginclude_HEADERS += include/libsemigroups/kambites-class.tpp pkginclude_HEADERS += include/libsemigroups/kambites-helpers.hpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/docs/Doxyfile new/libsemigroups-3.1.3/docs/Doxyfile --- old/libsemigroups-3.1.2/docs/Doxyfile 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/docs/Doxyfile 2025-08-12 14:48:26.000000000 +0200 @@ -48,7 +48,7 @@ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = v3.1.2 +PROJECT_NUMBER = v3.1.3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewers a @@ -309,7 +309,9 @@ "ref_todd_coxeter=\ref todd_coxeter_class_group \"ToddCoxeter\"" \ "ref_knuth_bendix=\ref knuth_bendix_class_group \"KnuthBendix\"" \ "ref_kambites=\ref kambites_class_group \"Kambites\"" \ - "ref_congruence=\ref congruence_class_group \"Congruence\"" + "ref_congruence=\ref congruence_class_group \"Congruence\"" \ + "deprecated_alias_warning{1}=\warning This alias is deprecated and will be removed from `libsemigroups` in v4, please use `\1` instead." + # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For @@ -1014,6 +1016,7 @@ "../include/libsemigroups/detail" \ "../README.md" \ "authors.md" \ + "deprecate.md" \ "install.md" \ "changelog-v1.md" \ "changelog-v2.md" \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/docs/DoxygenLayout.xml new/libsemigroups-3.1.3/docs/DoxygenLayout.xml --- old/libsemigroups-3.1.2/docs/DoxygenLayout.xml 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/docs/DoxygenLayout.xml 2025-08-12 14:48:26.000000000 +0200 @@ -12,6 +12,7 @@ <tab type="user" visible="yes" url="@ref md_changelog-v3" title="Changelog - version 3" /> <tab type="user" visible="yes" url="@ref md_changelog-v2" title="Changelog - version 2" /> <tab type="user" visible="yes" url="@ref md_changelog-v1" title="Changelog - version 1" /> + <tab type="user" visible="yes" url="@ref md_deprecate" title="Deprecation" /> <tab type="user" visible="yes" url="@ref md_install" title="Installation" /> <tab type="user" visible="yes" url="_HEADING_" title="Data structures" /> <tab type="usergroup" visible="yes" url="@ref adapters_group" title="Adapters"> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/docs/changelog-v3.md new/libsemigroups-3.1.3/docs/changelog-v3.md --- old/libsemigroups-3.1.2/docs/changelog-v3.md 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/docs/changelog-v3.md 2025-08-12 14:48:26.000000000 +0200 @@ -1,5 +1,18 @@ # Changelog - version 3 +## v3.1.3 (released 12/08/2025) + +This is a minor release that does the following: + + * Add a `to_human_readable_repr` for the `Action` class by @james-d-mitchell in + https://github.com/libsemigroups/libsemigroups/pull/777 + * Update the `to_human_readable_repr` of the `Congruence` class to be more + consistent with the `KnuthBendix` and `ToddCoxeter` classes by + @james-d-mitchell in https://github.com/libsemigroups/libsemigroups/pull/778 + * Mark `IsBipartition`, `IsPBR`, `IsPresentation`, `IsInversePresentation` and + `IsWordGraph` as deprecated, to be favoured by `is_specialization_of` by + @james-d-mitchell in https://github.com/libsemigroups/libsemigroups/pull/771 + ## v3.1.2 (released 29/07/2025) This is a minor release fixing some more issues that were introduced in v3.1.0. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/docs/deprecate.md new/libsemigroups-3.1.3/docs/deprecate.md --- old/libsemigroups-3.1.2/docs/deprecate.md 1970-01-01 01:00:00.000000000 +0100 +++ new/libsemigroups-3.1.3/docs/deprecate.md 2025-08-12 14:48:26.000000000 +0200 @@ -0,0 +1,12 @@ +# Deprecation policy + +This page explains the deprecation policy for `libsemigroups`, it's not very +complicated. + +Any function, type, or alias with the attribute `[[deprecated]]` +will be removed in the next major release. So, the alias \ref +libsemigroups::IsBipartition "IsBipartition", for example, will be present in +every version of `libsemigroups` starting with the number `3`, but will be +removed in the first version starting with `4`. The documentation should +indicate an alternative for the deprecated entity, in the example of +`IsBipartition<Thing>` this is `std::is_same_v<Thing, Bipartition>`. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/docs/install.md new/libsemigroups-3.1.3/docs/install.md --- old/libsemigroups-3.1.2/docs/install.md 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/docs/install.md 2025-08-12 14:48:26.000000000 +0200 @@ -34,10 +34,10 @@ To build `libsemigroups` from a release archive: - curl -L -O https://github.com/libsemigroups/libsemigroups/releases/latest/download/libsemigroups-3.1.2.tar.gz - tar -xf libsemigroups-3.1.2.tar.gz - rm -f libsemigroups-3.1.2.tar.gz - cd libsemigroups-3.1.2 + curl -L -O https://github.com/libsemigroups/libsemigroups/releases/latest/download/libsemigroups-3.1.3.tar.gz + tar -xf libsemigroups-3.1.3.tar.gz + rm -f libsemigroups-3.1.3.tar.gz + cd libsemigroups-3.1.3 ./configure && make -j8 && sudo make install ## Configuration options diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/action.hpp new/libsemigroups-3.1.3/include/libsemigroups/action.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/action.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/action.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -258,6 +258,7 @@ typename Fnc, typename Trits, side LftOrRight> + // TODO make this a free function, and non-friend friend std::ostringstream& operator<<(std::ostringstream& os, Action<Elment, Pint, Fnc, Trits, LftOrRight> const& action); @@ -266,6 +267,7 @@ //! //! This member function allows Action objects to be inserted into a //! std::ostream. + // TODO make this a free function, and non-friend friend std::ostream& operator<<(std::ostream& os, Action const& action) { os << detail::to_string(action); return os; @@ -896,7 +898,7 @@ void throw_if_index_out_of_range(index_type i) const; void throw_if_no_generators() const; void throw_if_bad_degree(element_type const&) const; - }; + }; // class Action //! \ingroup action_group //! This is a traits class for use with Action, \ref LeftAction, @@ -941,6 +943,29 @@ typename Func = ImageLeftAction<Element, Point>, typename Traits = ActionTraits<Element, Point>> using LeftAction = Action<Element, Point, Func, Traits, side::left>; + + //! \ingroup action_group + //! + //! \brief Return a human readable representation of an Action object. + //! + //! Defined in `action.hpp`. + //! + //! This function returns a human readable representation of an Action + //! object. + //! + //! \param action the Action. + //! + //! \returns A std::string containing the representation. + //! + //! \exceptions + //! \no_libsemigroups_except + template <typename Element, + typename Point, + typename Func, + typename Traits, + side LeftOrRight> + std::string to_human_readable_repr( + Action<Element, Point, Func, Traits, LeftOrRight> const& action); } // namespace libsemigroups #include "action.tpp" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/action.tpp new/libsemigroups-3.1.3/include/libsemigroups/action.tpp --- old/libsemigroups-3.1.2/include/libsemigroups/action.tpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/action.tpp 2025-08-12 14:48:26.000000000 +0200 @@ -33,11 +33,7 @@ std::ostringstream& operator<<(std::ostringstream& os, Action<Element, Point, Func, Traits, LeftOrRight> const& action) { - os << fmt::format("<{} {} action with {} generators, {} points>", - action.finished() ? "complete" : "incomplete", - LeftOrRight, - action.number_of_generators(), - action.current_size()); + os << to_human_readable_repr(action); return os; } @@ -434,4 +430,20 @@ } } + template <typename Element, + typename Point, + typename Func, + typename Traits, + side LeftOrRight> + std::string to_human_readable_repr( + Action<Element, Point, Func, Traits, LeftOrRight> const& action) { + return fmt::format("<{} {} action with {} generator{}, {} point{}>", + action.finished() ? "complete" : "incomplete", + LeftOrRight, + action.number_of_generators(), + action.number_of_generators() == 1 ? "" : "s", + action.current_size(), + action.current_size() == 1 ? "" : "s"); + } + } // namespace libsemigroups diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/bipart.hpp new/libsemigroups-3.1.3/include/libsemigroups/bipart.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/bipart.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/bipart.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -166,39 +166,31 @@ } // namespace bipartition - namespace detail { - - template <typename T> - struct IsBipartitionHelper : std::false_type {}; - - template <> - struct IsBipartitionHelper<Bipartition> : std::true_type {}; - - } // namespace detail - //! \ingroup bipart_group //! \brief Helper variable template. //! - //! The value of this variable is \c true if the template parameter \p T + //! The value of this variable is \c true if the template parameter \p Thing //! decays to \ref Bipartition. //! - //! \tparam T a type. - template <typename T> - static constexpr bool IsBipartition - = detail::IsBipartitionHelper<std::decay_t<T>>::value; + //! \tparam Thing a type. + //! + //! \deprecated_alias_warning{std::is_same_v<Thing, Bipartition>} + template <typename Thing> + static constexpr bool IsBipartition [[deprecated]] + = std::is_same_v<std::decay_t<Thing>, Bipartition>; namespace detail { //! No doc - template <typename BipartitionOrBlocks, typename Scalar> + template <typename Thing, typename Scalar> static void throw_if_bad_args(std::vector<std::vector<Scalar>> const& blocks) { - static_assert(std::is_same_v<BipartitionOrBlocks, Bipartition> - || std::is_same_v<BipartitionOrBlocks, Blocks>); + static_assert(std::is_same_v<Thing, Bipartition> + || std::is_same_v<Thing, Blocks>); static_assert(std::is_signed<Scalar>::value, "the 2nd template parameter Scalar must be signed"); int32_t offset = 2; - if (!IsBipartition<BipartitionOrBlocks>) { + if (!std::is_same_v<Thing, Bipartition>) { offset = 1; } int32_t m = 0; @@ -223,7 +215,7 @@ "position {} of the block with index {}", j, i); - } else if (!IsBipartition<BipartitionOrBlocks> && positive && x < 0) { + } else if (!std::is_same_v<Thing, Bipartition> && positive && x < 0) { LIBSEMIGROUPS_EXCEPTION( "the argument (blocks) is invalid, expected every value in the " "block with index {} to be {}tive, but found {} in position {}", @@ -244,7 +236,7 @@ "too many points, expected at most {}, found {}", 0x40000000, m); } else if (deg != offset * m || vals.size() != size_t(deg)) { std::string range, prefix; - if (IsBipartition<BipartitionOrBlocks>) { + if (std::is_same_v<Thing, Bipartition>) { prefix = "the union of"; range = fmt::format("{{{}, ..., -1, 1, ..., {}}}", -m, m); } else { @@ -261,21 +253,21 @@ } //! No doc - template <typename BipartitionOrBlocks, typename Scalar> + template <typename Thing, typename Scalar> static void throw_if_bad_args( std::initializer_list<std::vector<Scalar>> const& blocks) { std::vector<std::vector<Scalar>> arg(blocks); - throw_if_bad_args<BipartitionOrBlocks>(arg); + throw_if_bad_args<Thing>(arg); } //! No doc - template <typename BipartitionOrBlocks, typename Scalar> + template <typename Thing, typename Scalar> static void throw_if_bad_args(std::vector<Scalar> const&) { // checks for this argument type are done in throw_if_invalid } //! No doc - template <typename BipartitionOrBlocks, typename Scalar> + template <typename Thing, typename Scalar> static void throw_if_bad_args(std::initializer_list<Scalar> const&) { // checks for this argument type are done in throw_if_invalid } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/cong-class.tpp new/libsemigroups-3.1.3/include/libsemigroups/cong-class.tpp --- old/libsemigroups-3.1.2/include/libsemigroups/cong-class.tpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/cong-class.tpp 2025-08-12 14:48:26.000000000 +0200 @@ -391,10 +391,14 @@ template <typename Word> std::string to_human_readable_repr(Congruence<Word> const& c) { - return fmt::format("<Congruence over {} with {} runner{}>", - to_human_readable_repr(c.presentation()), - c.number_of_runners(), - c.number_of_runners() > 1 ? "s" : ""); + return fmt::format( + "<{} Congruence over {} with {} gen. pair{}, {} runners>", + c.kind() == congruence_kind::twosided ? "2-sided" : "1-sided", + to_human_readable_repr(c.presentation()), + detail::group_digits(c.number_of_generating_pairs()), + c.number_of_generating_pairs() == 1 ? "" : "s", + c.number_of_runners(), + c.number_of_runners() > 1 ? "s" : ""); } // This function is declared in obv-inf.hpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/detail/containers.hpp new/libsemigroups-3.1.3/include/libsemigroups/detail/containers.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/detail/containers.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/detail/containers.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -1180,19 +1180,7 @@ private: std::array<std::array<T, N>, N> _arrays; }; - - template <typename T> - struct IsDynamicArray2Helper : std::false_type {}; - - template <typename T, typename A> - struct IsDynamicArray2Helper<DynamicArray2<T, A>> : std::true_type {}; - } // namespace detail - - template <typename T> - static constexpr bool IsDynamicArray2 - = detail::IsDynamicArray2Helper<std::decay_t<T>>::value; - } // namespace libsemigroups namespace std { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/detail/race.hpp new/libsemigroups-3.1.3/include/libsemigroups/detail/race.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/detail/race.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/detail/race.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -28,21 +28,25 @@ #ifndef LIBSEMIGROUPS_DETAIL_RACE_HPP_ #define LIBSEMIGROUPS_DETAIL_RACE_HPP_ +#include <algorithm> // for min, find_if #include <chrono> // for nanoseconds #include <cstddef> // for size_t -#include <memory> // for std::shared_ptr -#include <thread> // for mutex -#include <type_traits> // for invoke_result_t -#include <vector> // for vector +#include <exception> // for exception +#include <memory> // for shared_ptr, operator!=, opera... +#include <mutex> // for mutex, lock_guard +#include <string_view> // for basic_string_view +#include <thread> // for thread, get_id, __thread_id +#include <type_traits> // for invoke_result_t, is_same_v +#include <typeinfo> // for type_info +#include <utility> // for move, forward #include "libsemigroups/constants.hpp" // for UNDEFINED #include "libsemigroups/debug.hpp" // for LIBSEMIGROUPS_ASSERT #include "libsemigroups/exception.hpp" // for LIBSEMIGROUPS_EXCEPTION -#include "libsemigroups/runner.hpp" // for Runner +#include "libsemigroups/runner.hpp" // for Runner, delta, Reporter -#include "report.hpp" // for report_default, REPORT_TIME -#include "stl.hpp" // for IsCallable -#include "timer.hpp" // for Timer +#include "report.hpp" // for report_default, thread_id +#include "timer.hpp" // for Timer, string_time namespace libsemigroups { namespace detail { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/detail/stl.hpp new/libsemigroups-3.1.3/include/libsemigroups/detail/stl.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/detail/stl.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/detail/stl.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -27,7 +27,7 @@ #include <thread> // for std::thread #include <type_traits> // for enable_if, forward, hash, is_function, is_same #include <vector> // for vector - // + namespace libsemigroups { namespace detail { // Pass parameter p by value because this function modifies p. @@ -62,20 +62,6 @@ } } - // Since std::is_invocable is only introduced in C++17, we use this - // - // from: https://stackoverflow.com/q/15393938/ - // Only works if there are no overloads of operator() in type T. - template <typename T, typename = void> - struct IsCallable : std::is_function<T> {}; - - template <typename T> - struct IsCallable< - T, - std::enable_if_t< - std::is_same<decltype(void(&T::operator())), void>::value>> - : std::true_type {}; - // From p, 275, Section 8 of C++ concurrency in action, 2nd edition, by // Anthony Williams. class JoinThreads { @@ -94,21 +80,6 @@ } }; - // TODO ref - class ThreadGuard { - std::thread& _thread; - - public: - explicit ThreadGuard(std::thread& thread) : _thread(thread) {} - ~ThreadGuard() { - if (_thread.joinable()) { - _thread.join(); - } - } - ThreadGuard(ThreadGuard const&) = delete; - ThreadGuard& operator=(ThreadGuard const&) = delete; - }; - template <typename A, typename B, typename = decltype(std::declval<A>() <= std::declval<B>())> @@ -123,26 +94,6 @@ std::void_t<typename std::iterator_traits<T>::iterator_category>> : std::true_type {}; - template <typename T> - struct IsStdSharedPtrHelper : std::false_type {}; - - template <typename T> - struct IsStdSharedPtrHelper<std::shared_ptr<T>> : std::true_type {}; - - template <typename T> - static constexpr bool IsStdSharedPtr = IsStdSharedPtrHelper<T>::value; - - // From https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2098r0.pdf - template <typename Thing, template <typename...> typename Primary> - struct is_specialization_of : std::false_type {}; - - template <template <typename...> typename Primary, typename... Args> - struct is_specialization_of<Primary<Args...>, Primary> : std::true_type {}; - - template <typename Thing, template <typename...> typename Primary> - inline constexpr bool is_specialization_of_v - = is_specialization_of<Thing, Primary>::value; - template <typename... Args> struct is_array : std::false_type {}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/is_specialization_of.hpp new/libsemigroups-3.1.3/include/libsemigroups/is_specialization_of.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/is_specialization_of.hpp 1970-01-01 01:00:00.000000000 +0100 +++ new/libsemigroups-3.1.3/include/libsemigroups/is_specialization_of.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -0,0 +1,86 @@ +// +// libsemigroups - C++ library for semigroups and monoids +// Copyright (C) 2025 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 struct is_specialization_of and the alias +// is_specialization_of_v. + +#ifndef LIBSEMIGROUPS_IS_SPECIALIZATION_OF_HPP_ +#define LIBSEMIGROUPS_IS_SPECIALIZATION_OF_HPP_ + +#include <type_traits> // for true_type + +namespace libsemigroups { + //! \ingroup types_group + //! + //! \brief Struct for checking if a template parameter is a specialization of + //! another. + //! + //! This struct contains the unique member `value` which indicates whether or + //! not the template parameter \p Thing is a specialization of the template + //! template parameter \p Primary. + //! The implementation is based on + //! [this](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2098r0.pdf). + //! + //! \tparam Thing the type we are checking is a specialization of \p Primary. + //! \tparam Primary the type we are checking \p Thing against. + //! + //! \par Example + //! \code + //! is_specialization_of<std::vector<int>, std::vector>::value // true + //! is_specialization_of<std::vector<int>, std::unordered_map>::value + //! // false + //! \endcode + //! + //! \note The template parameters of \p Primary must be types, so, for + //! example, `is_specialization_of<std::array<int, 2>, std::array>` will not + //! compile. + //! + //! \sa is_specialization_of_v + // From https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2098r0.pdf + template <typename Thing, template <typename...> typename Primary> + struct is_specialization_of : std::false_type {}; + + //! \copydoc is_specialization_of + template <template <typename...> typename Primary, typename... Args> + struct is_specialization_of<Primary<Args...>, Primary> : std::true_type {}; + + //! \ingroup types_group + //! + //! \brief Helper variable template for \ref is_specialization_of. + //! + //! This helper is just a short version of + //! `is_specialization_of<Thing, Primary>::value`. + //! + //! \tparam Thing the type we are checking is a specialization of \p Primary. + //! \tparam Primary the type we are checking \p Thing against. + //! + //! \par Example + //! \code + //! is_specialization_of_v<std::vector<int>, std::vector> // true + //! is_specialization_of_v<std::vector<int>, std::unordered_map> // false + //! \endcode + //! + //! \note The template parameters of \p Primary must be types, so, for + //! example, `is_specialization_of<std::array<int, 2>, std::array>` will not + //! compile. + template <typename Thing, template <typename...> typename Primary> + inline constexpr bool is_specialization_of_v + = is_specialization_of<Thing, Primary>::value; +} // namespace libsemigroups + +#endif // LIBSEMIGROUPS_IS_SPECIALIZATION_OF_HPP_ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/libsemigroups.hpp new/libsemigroups-3.1.3/include/libsemigroups/libsemigroups.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/libsemigroups.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/libsemigroups.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -51,6 +51,7 @@ #include "froidure-pin.hpp" #include "gabow.hpp" #include "hpcombi.hpp" +#include "is_specialization_of.hpp" #include "kambites-class.hpp" #include "kambites-helpers.hpp" #include "kambites.hpp" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/pbr.hpp new/libsemigroups-3.1.3/include/libsemigroups/pbr.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/pbr.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/pbr.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -698,24 +698,16 @@ return y <= x; } - namespace detail { - - template <typename T> - struct IsPBRHelper : std::false_type {}; - - template <> - struct IsPBRHelper<PBR> : std::true_type {}; - - } // namespace detail - //! \brief Helper variable template. //! - //! The value of this variable is \c true if the template parameter \p T is - //! \ref PBR. + //! The value of this variable is \c true if the template parameter \p Thing + //! is \ref PBR. + //! + //! \tparam Thing a type. //! - //! \tparam T a type. - template <typename T> - static constexpr bool IsPBR = detail::IsPBRHelper<T>::value; + //! \deprecated_alias_warning{std::is_same_v<Thing, PBR>} + template <typename Thing> + static constexpr bool IsPBR [[deprecated]] = std::is_same_v<Thing, PBR>; //////////////////////////////////////////////////////////////////////// // Adapters diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/presentation.hpp new/libsemigroups-3.1.3/include/libsemigroups/presentation.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/presentation.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/presentation.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -41,9 +41,10 @@ #include <utility> // for move, pair #include <vector> // for vector, operator!= -#include "adapters.hpp" // for Hash, EqualTo -#include "constants.hpp" // for Max, UNDEFINED, operator== -#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT +#include "adapters.hpp" // for Hash, EqualTo +#include "constants.hpp" // for Max, UNDEFINED, operator== +#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT +#include "is_specialization_of.hpp" #include "order.hpp" // for ShortLexCompare #include "ranges.hpp" // for seq, operator|, rx, take, chain, is_sorted #include "types.hpp" // for word_type @@ -2580,21 +2581,6 @@ std::string to_human_readable_repr(InversePresentation<Word> const& p); namespace detail { - template <typename T> - struct IsPresentationHelper : std::false_type {}; - - template <typename T> - struct IsPresentationHelper<Presentation<T>> : std::true_type {}; - - template <typename T> - struct IsPresentationHelper<InversePresentation<T>> : std::true_type {}; - - template <typename T> - struct IsInversePresentationHelper : std::false_type {}; - - template <typename T> - struct IsInversePresentationHelper<InversePresentation<T>> - : std::true_type {}; class GreedyReduceHelper { private: @@ -2629,13 +2615,17 @@ //! //! Helper variable template. //! - //! The value of this variable is \c true if the template parameter \p T is - //! \ref InversePresentation. + //! The value of this variable is \c true if the template parameter \p Thing + //! is \ref InversePresentation. //! - //! \tparam T a type. - template <typename T> - static constexpr bool IsInversePresentation - = detail::IsInversePresentationHelper<T>::value; + //! \tparam Thing a type. + // clang-format off + // NOLINTNEXTLINE(whitespace/line_length) + //! \deprecated_alias_warning{is_specialization_of_v<Thing, InversePresentation>} + // clang-format on + template <typename Thing> + static constexpr bool IsInversePresentation [[deprecated]] + = is_specialization_of_v<Thing, InversePresentation>; //! \ingroup presentations_group //! @@ -2643,12 +2633,15 @@ //! //! Helper variable template. //! - //! The value of this variable is \c true if the template parameter \p T is - //! \ref InversePresentation. + //! The value of this variable is \c true if the template parameter \p Thing + //! is \ref InversePresentation. + //! + //! \tparam Thing a type. //! - //! \tparam T a type. - template <typename T> - static constexpr bool IsPresentation = detail::IsPresentationHelper<T>::value; + //! \deprecated_alias_warning{is_specialization_of_v<Thing, Presentation>} + template <typename Thing> + static constexpr bool IsPresentation [[deprecated]] + = is_specialization_of_v<Thing, Presentation>; } // namespace libsemigroups diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/stephen.tpp new/libsemigroups-3.1.3/include/libsemigroups/stephen.tpp --- old/libsemigroups-3.1.2/include/libsemigroups/stephen.tpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/stephen.tpp 2025-08-12 14:48:26.000000000 +0200 @@ -54,7 +54,8 @@ label_type letter, node_type to) { WordGraphWithSources_::target_no_checks(from, letter, to); - if constexpr (IsInversePresentation<presentation_type>) { + if constexpr (is_specialization_of_v<presentation_type, + InversePresentation>) { // convert l (which is an index) // -> actual letter // -> inverse of letter @@ -420,7 +421,8 @@ result.add_edge(s.accept_state(), "accept"); size_t max_letters = s.presentation().alphabet().size(); - if constexpr (IsInversePresentation<PresentationType>) { + if constexpr (is_specialization_of_v<PresentationType, + InversePresentation>) { max_letters /= 2; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/transf.hpp new/libsemigroups-3.1.3/include/libsemigroups/transf.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/transf.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/transf.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -46,13 +46,14 @@ #include "config.hpp" // for LIBSEMIGROUPS_HPCOMBI_ENABLED -#include "adapters.hpp" // for Hash etc -#include "bitset.hpp" // for BitSet -#include "constants.hpp" // for UNDEFINED, Undefined -#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT -#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION -#include "hpcombi.hpp" // for HPCombi::Transf16 -#include "types.hpp" // for SmallestInteger +#include "adapters.hpp" // for Hash etc +#include "bitset.hpp" // for BitSet +#include "constants.hpp" // for UNDEFINED, Undefined +#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT +#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION +#include "hpcombi.hpp" // for HPCombi::Transf16 +#include "is_specialization_of.hpp" // for is_specialization_of +#include "types.hpp" // for SmallestInteger #include "detail/stl.hpp" // for is_array_v @@ -128,7 +129,7 @@ class PTransfBase : public detail::PTransfPolymorphicBase { static_assert(std::is_integral_v<Scalar>, "template parameter Scalar must be an integral type"); - static_assert(!std::numeric_limits<Scalar>::is_signed, + static_assert(std::is_unsigned_v<Scalar>, "template parameter Scalar must be unsigned"); public: @@ -516,6 +517,7 @@ //! \warning This function does not check its arguments. In particular, if //! \c *this and \c that have different degrees, then bad things may happen. // TODO(later) other operators such as power + // TODO to tpp template <typename Subclass> [[nodiscard]] Subclass operator*(Subclass const& that) const { static_assert(IsDerivedFromPTransf<Subclass>, @@ -526,14 +528,14 @@ return xy; } - //! \brief Type of iterators point to image values. + //! \brief Type of iterators pointing to image values. //! - //! Type of iterators point to image values. + //! Type of iterators pointing to image values. using iterator = typename Container::iterator; - //! \brief Type of const iterators point to image values. + //! \brief Type of const iterators pointing to image values. //! - //! Type of const iterators point to image values. + //! Type of const iterators pointing to image values. using const_iterator = typename Container::const_iterator; //! \brief Returns a \ref const_iterator (random access iterator) pointing diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/word-graph.hpp new/libsemigroups-3.1.3/include/libsemigroups/word-graph.hpp --- old/libsemigroups-3.1.2/include/libsemigroups/word-graph.hpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/word-graph.hpp 2025-08-12 14:48:26.000000000 +0200 @@ -22,9 +22,9 @@ #ifndef LIBSEMIGROUPS_WORD_GRAPH_HPP_ #define LIBSEMIGROUPS_WORD_GRAPH_HPP_ -#include <algorithm> // for uniform_int_distribution -#include <cstddef> // for size_t -#include <cstdint> +#include <algorithm> // for uniform_int_distribution +#include <cstddef> // for size_t +#include <cstdint> // for uint32_t #include <ostream> // for operator<< #include <queue> // for queue #include <random> // for mt19937 @@ -36,15 +36,16 @@ #include <utility> // for pair #include <vector> // for vector -#include "config.hpp" // for LIBSEMIGROUPS_EIGEN_EN... -#include "constants.hpp" // for UNDEFINED -#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT -#include "dot.hpp" // for Dot -#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION -#include "forest.hpp" // for Forest -#include "order.hpp" // for Order -#include "ranges.hpp" // for ?? -#include "types.hpp" // for word_type, enable_if_is_same +#include "config.hpp" // for LIBSEMIGROUPS_EIGEN_EN... +#include "constants.hpp" // for UNDEFINED +#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT +#include "dot.hpp" // for Dot +#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION +#include "forest.hpp" // for Forest +#include "is_specialization_of.hpp" // for is_specialization_of_v +#include "order.hpp" // for Order +#include "ranges.hpp" // for ?? +#include "types.hpp" // for word_type, enable_if_is_same #include "detail/containers.hpp" // for DynamicArray2 #include "detail/int-range.hpp" // for IntRange @@ -2705,15 +2706,6 @@ } // namespace word_graph - namespace detail { - - template <typename T> - struct IsWordGraphHelper : std::false_type {}; - - template <typename Node> - struct IsWordGraphHelper<WordGraph<Node>> : std::true_type {}; - } // namespace detail - ////////////////////////////////////////////////////////////////////////// // WordGraph - non-member functions ////////////////////////////////////////////////////////////////////////// @@ -2721,12 +2713,15 @@ //! \ingroup word_graph_group //! \brief Helper variable template. //! - //! The value of this variable is \c true if the template parameter \p T is - //! \ref WordGraph for any template parameters. + //! The value of this variable is \c true if the template parameter \p Thing + //! is \ref WordGraph for any template parameters. + //! + //! \tparam Thing a type. //! - //! \tparam T a type. - template <typename T> - static constexpr bool IsWordGraph = detail::IsWordGraphHelper<T>::value; + //! \deprecated_alias_warning{is_specialization_of_v<Thing, WordGraph>} + template <typename Thing> + static constexpr bool IsWordGraph [[deprecated]] + = is_specialization_of_v<Thing, WordGraph>; //! \ingroup word_graph_group //! Output the edges of a wordGraph to a stream. @@ -2769,7 +2764,8 @@ //! out-degree is specified by the length of the first item //! in the second parameter, or 0 if the second parameter is empty. //! - //! \tparam Return the return type. Must satisfy \ref IsWordGraph<Return>. + //! \tparam Return the return type. Must satisfy + //! \ref is_specialization_of_v<Return, WordGraph>. //! //! \param num_nodes the number of nodes in the word graph. //! \param targets the targets of the word graph. @@ -2791,7 +2787,8 @@ // Passing the 2nd parameter "targets" by value disambiguates it from the // other make<WordGraph>. template <typename Return> - [[nodiscard]] std::enable_if_t<IsWordGraph<Return>, Return> + [[nodiscard]] std::enable_if_t<is_specialization_of_v<Return, WordGraph>, + Return> make(size_t num_nodes, std::initializer_list<std::vector<typename Return::node_type>> targets); @@ -2801,7 +2798,8 @@ //! \copydoc make(size_t, std::initializer_list<std::vector<typename Return::node_type>>) //NOLINT() // clang-format on template <typename Return> - [[nodiscard]] std::enable_if_t<IsWordGraph<Return>, Return> + [[nodiscard]] std::enable_if_t<is_specialization_of_v<Return, WordGraph>, + Return> make(size_t num_nodes, std::vector<std::vector<typename Return::node_type>> const& targets); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/include/libsemigroups/word-graph.tpp new/libsemigroups-3.1.3/include/libsemigroups/word-graph.tpp --- old/libsemigroups-3.1.2/include/libsemigroups/word-graph.tpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/include/libsemigroups/word-graph.tpp 2025-08-12 14:48:26.000000000 +0200 @@ -1483,7 +1483,7 @@ // TODO(1) refactor to use vectors api, not initializer_list template <typename Return> - std::enable_if_t<IsWordGraph<Return>, Return> + std::enable_if_t<is_specialization_of_v<Return, WordGraph>, Return> make(size_t num_nodes, std::vector<std::vector<typename Return::node_type>> const& edges) { Return result(num_nodes, std::empty(edges) ? 0 : edges.begin()->size()); @@ -1499,7 +1499,7 @@ } template <typename Return> - std::enable_if_t<IsWordGraph<Return>, Return> + std::enable_if_t<is_specialization_of_v<Return, WordGraph>, Return> make(size_t num_nodes, std::initializer_list<std::vector<typename Return::node_type>> il) { return make<Return>( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/tests/test-action.cpp new/libsemigroups-3.1.3/tests/test-action.cpp --- old/libsemigroups-3.1.2/tests/test-action.cpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/tests/test-action.cpp 2025-08-12 14:48:26.000000000 +0200 @@ -878,4 +878,16 @@ LibsemigroupsException); } + LIBSEMIGROUPS_TEST_CASE("Action", + "024", + "to_human_readable_repr", + "[quick]") { + RightAction<PPerm<>, PPerm<>> o; + o.add_seed(PPerm<>::one(8)); + o.add_generator( + make<PPerm<>>({0, 1, 2, 3, 4, 5, 6, 7}, {1, 2, 3, 4, 5, 6, 7, 0}, 8)); + REQUIRE(to_human_readable_repr(o) + == "<incomplete right action with 1 generator, 1 point>"); + } + } // namespace libsemigroups diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/tests/test-bipart.cpp new/libsemigroups-3.1.3/tests/test-bipart.cpp --- old/libsemigroups-3.1.2/tests/test-bipart.cpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/tests/test-bipart.cpp 2025-08-12 14:48:26.000000000 +0200 @@ -142,8 +142,6 @@ LIBSEMIGROUPS_TEST_CASE("Blocks", "004", "copy [empty blocks]", "[quick]") { Blocks b = construct_blocks({}, {}); Blocks c(b); - REQUIRE(!IsBipartition<Blocks>); - REQUIRE(IsBipartition<Bipartition>); REQUIRE(b.degree() == 0); REQUIRE(b.number_of_blocks() == 0); REQUIRE(b.rank() == 0); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/tests/test-cong.cpp new/libsemigroups-3.1.3/tests/test-cong.cpp --- old/libsemigroups-3.1.2/tests/test-cong.cpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/tests/test-cong.cpp 2025-08-12 14:48:26.000000000 +0200 @@ -1356,4 +1356,21 @@ REQUIRE(c.has<KnuthBendix<std::string>>()); REQUIRE(c.get<KnuthBendix<std::string>>() != nullptr); } + + LIBSEMIGROUPS_TEST_CASE("Congruence", + "039", + "to_human_readable_repr", + "[quick][cong]") { + auto rg = ReportGuard(false); + Presentation<std::string> p; + p.alphabet("abcdefg"); + presentation::add_rule(p, "abcd", "aaaeaa"); + Congruence cong(twosided, p); + congruence::add_generating_pair(cong, "ef", "dg"); + + REQUIRE(to_human_readable_repr(cong) + == "<2-sided Congruence over <semigroup presentation with 7 " + "letters, 1 rule, and length 10> with 1 gen. pair, 4 runners>"); + } + } // namespace libsemigroups diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsemigroups-3.1.2/tests/test-word-graph.cpp new/libsemigroups-3.1.3/tests/test-word-graph.cpp --- old/libsemigroups-3.1.2/tests/test-word-graph.cpp 2025-07-29 23:23:27.000000000 +0200 +++ new/libsemigroups-3.1.3/tests/test-word-graph.cpp 2025-08-12 14:48:26.000000000 +0200 @@ -282,8 +282,6 @@ wg.target(2, 0, 0); wg.induced_subgraph_no_checks(0, 2); - static_assert(!IsWordGraph<size_t>); - static_assert(IsWordGraph<WordGraph<size_t>>); REQUIRE(wg == make<WordGraph<size_t>>(2, {{1, UNDEFINED}, {0}})); }