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}}));
   }
 

Reply via email to