From c12286a6b08623698985a8d2f0d3b15e70399d1e Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Mon, 22 Jan 2024 16:38:39 +0000 Subject: [PATCH 1/3] ci: add job with hpcombi enabled --- .github/workflows/config-options.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/config-options.yml b/.github/workflows/config-options.yml index ba7ad3c97..62606311c 100644 --- a/.github/workflows/config-options.yml +++ b/.github/workflows/config-options.yml @@ -35,6 +35,30 @@ jobs: - name: "Run Semigroups package's tst/teststandard.g" uses: gap-actions/run-pkg-tests@v2 + enable-hpcombi: + runs-on: "ubuntu-latest" + steps: + - uses: actions/checkout@v3 + # Don't use ccache, since sometimes this fails when using -mavx + - name: "Install GAP and clone/compile necessary packages" + uses: gap-actions/setup-gap@v2 + with: + GAP_PKGS_TO_BUILD: "digraphs io orb datastructures profiling" + GAPBRANCH: stable-4.12 + ABI: 64 + - name: "Build Semigroups" + uses: gap-actions/build-pkg@v1 + with: + ABI: 64 + - name: "Run Semigroups package's tst/teststandard.g" + uses: gap-actions/run-pkg-tests@v2 + - uses: gap-actions/process-coverage@v2 + - uses: codecov/codecov-action@v2 + - name: "Run GAP's tst/testinstall.g" + uses: gap-actions/run-pkg-tests@v2 + with: + GAP_TESTFILE: "ci/run-gap-testinstall.g" + with-external-libsemigroups: runs-on: "ubuntu-latest" env: From dfb17354a96cef3b1400a0750254644013927882 Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Mon, 22 Jan 2024 16:52:46 +0000 Subject: [PATCH 2/3] build: fix AX_CHECK_HPCOMBI Previously the paths were incorrect, probably copied from libsemigroups directly, and so HPCombi was never found. This commit also ensures that HPCOMBI_CXXFLAGS are added to CXX_FLAGS, which they previously weren't. --- GNUmakefile.in | 2 +- m4/ax_check_hpcombi.m4 | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/GNUmakefile.in b/GNUmakefile.in index ca33508df..aa197f383 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -39,7 +39,7 @@ KEXT_CPPFLAGS += -DHPCOMBI_CONSTEXPR_FUN_ARGS endif ifdef LIBSEMIGROUPS_HPCOMBI_ENABLED -KEXT_CXXFLAGS += $(HPCOMBI_CXXFLAGS) +KEXT_CXXFLAGS += @HPCOMBI_CXXFLAGS@ endif ifdef WITH_INCLUDED_LIBSEMIGROUPS diff --git a/m4/ax_check_hpcombi.m4 b/m4/ax_check_hpcombi.m4 index 1594192e8..3b4af7ea7 100644 --- a/m4/ax_check_hpcombi.m4 +++ b/m4/ax_check_hpcombi.m4 @@ -28,8 +28,8 @@ AC_DEFUN([AX_CHECK_HPCOMBI], [ AC_MSG_RESULT([$enable_hpcombi]) AS_IF([test "x$enable_hpcombi" = xyes], - [AS_IF([test -f $srcdir/extern/HPCombi/VERSION], - [], + [AS_IF([test -f $srcdir/libsemigroups/extern/HPCombi/VERSION], + [], [AC_MSG_WARN([HPCombi is not available]) [enable_hpcombi=no]])]) @@ -40,36 +40,36 @@ AC_DEFUN([AX_CHECK_HPCOMBI], [ AS_IF([test "x$enable_hpcombi" = xyes], [AC_MSG_CHECKING([the version of HPCombi that's present]) - FOUND_HPCOMBI="$(cat $srcdir/extern/HPCombi/VERSION)" + FOUND_HPCOMBI="$(cat $srcdir/libsemigroups/extern/HPCombi/VERSION)" AC_MSG_RESULT([$FOUND_HPCOMBI])]) AS_IF([test "x$enable_hpcombi" = xyes], - [AX_COMPARE_VERSION($FOUND_HPCOMBI, - [ge], + [AX_COMPARE_VERSION($FOUND_HPCOMBI, + [ge], $MIN_HPCOMBI_VERSION, [], - [AC_MSG_WARN([the incorrect version of HPCombi is present, HPCombi is disabled]) + [AC_MSG_WARN([the incorrect version of HPCombi is present, HPCombi is disabled]) enable_hpcombi=no])]) - - dnl # Check if the flags required for HPCombi are supported - AS_IF([test "x$enable_hpcombi" = xyes], - [AX_CHECK_COMPILE_FLAG(-mavx, + + dnl # Check if the flags required for HPCombi are supported + AS_IF([test "x$enable_hpcombi" = xyes], + [AX_CHECK_COMPILE_FLAG(-mavx, AX_APPEND_FLAG(-mavx, [ax_hpcombi_cxxflags_variable]), [AC_MSG_WARN([flag -mavx not supported, HPCombi is disabled]) enable_hpcombi=no])]) - AS_IF([test "x$enable_hpcombi" = xyes], - [AX_CHECK_COMPILE_FLAG(-flax-vector-conversions, + AS_IF([test "x$enable_hpcombi" = xyes], + [AX_CHECK_COMPILE_FLAG(-flax-vector-conversions, AX_APPEND_FLAG(-flax-vector-conversions, [ax_hpcombi_cxxflags_variable]), [AC_MSG_WARN([flag -flax-vector-conversions not supported, HPCombi is disabled]) enable_hpcombi=no])]) dnl # Check if the x86intrin.h header is available - AS_IF([test "x$enable_hpcombi" = xyes], + AS_IF([test "x$enable_hpcombi" = xyes], [AC_CHECK_HEADERS([x86intrin.h], [], [AC_MSG_WARN([header x86intrin.h is required for HPCombi, HPCombi is disabled]) enable_hpcombi=no])]) - - AS_IF([test "x$enable_hpcombi" = xyes], + + AS_IF([test "x$enable_hpcombi" = xyes], [enable_hpcombi_before_builtin_check=yes]) AS_IF([test "x$enable_hpcombi" = xyes], [CHECK_INTRINSIC([_mm_blendv_epi8],[__m128i{},__m128i{},__m128i{}])]) @@ -100,10 +100,10 @@ AC_DEFUN([AX_CHECK_HPCOMBI], [ AC_SUBST(LIBSEMIGROUPS_HPCOMBI_ENABLED, yes)) dnl # check for HPCombi's preprocessor macro - AS_IF([test "x$enable_hpcombi" = xyes], + AS_IF([test "x$enable_hpcombi" = xyes], [AC_MSG_CHECKING([for HPCOMBI_CONSTEXPR_FUN_ARGS]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( [[using T = int; constexpr int exec(T f()) { return f(); } constexpr int foo() { return 1; } static_assert(exec(foo) == 1, "Failed exec");]] From f7c49dfb81d5bae14c0a66d155a674cb81d02a54 Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Mon, 22 Jan 2024 19:09:13 +0000 Subject: [PATCH 3/3] kernel: fix for HPCombi There was some missing functionality that compiling with HPCombi enabled required. This commit adds that functionality and fixes a FIXME that actually comes up in semiquo.tst when compiling with HPCombi enabled. --- gap/libsemigroups/froidure-pin.gi | 48 +++++++++++---- gapbind14/include/gapbind14/cpp_fn.hpp | 2 +- src/to_cpp.hpp | 81 ++++++++++++++++++++++---- 3 files changed, 108 insertions(+), 23 deletions(-) diff --git a/gap/libsemigroups/froidure-pin.gi b/gap/libsemigroups/froidure-pin.gi index 163b78b2b..e4de024b0 100644 --- a/gap/libsemigroups/froidure-pin.gi +++ b/gap/libsemigroups/froidure-pin.gi @@ -48,16 +48,33 @@ Q -> CanUseLibsemigroupsCongruence(QuotientSemigroupCongruence(Q))); ########################################################################### DeclareOperation("FroidurePinMemFnRec", [IsSemigroup]); +DeclareOperation("FroidurePinMemFnRec", + [IsSemigroup, IsListOrCollection]); -InstallMethod(FroidurePinMemFnRec, "for a transformation semigroup", -[IsTransformationSemigroup], -function(S) - if DegreeOfTransformationSemigroup(S) <= 16 +InstallMethod(FroidurePinMemFnRec, "for a semigroup", +[IsSemigroup], S -> FroidurePinMemFnRec(S, [])); + +InstallMethod(FroidurePinMemFnRec, "for a semigroup", +[IsSemigroup, IsListOrCollection], {S, coll} -> FroidurePinMemFnRec(S)); + +InstallMethod(FroidurePinMemFnRec, +"for a transformation semigroup and list or coll.", +[IsTransformationSemigroup, IsListOrCollection], +function(S, coll) + local N; + N := DegreeOfTransformationSemigroup(S); + if IsTransformationCollection(coll) then + N := Maximum(N, DegreeOfTransformationCollection(coll)); + elif not IsEmpty(coll) then + Error("Expected a transf. coll. or empty list, found ", + TNAM_OBJ(coll)); + fi; + if N <= 16 and IsBound(LIBSEMIGROUPS_HPCOMBI_ENABLED) then return libsemigroups.FroidurePinTransf16; - elif DegreeOfTransformationSemigroup(S) <= 2 ^ 16 then + elif N <= 2 ^ 16 then return libsemigroups.FroidurePinTransfUInt2; - elif DegreeOfTransformationSemigroup(S) <= 2 ^ 32 then + elif N <= 2 ^ 32 then return libsemigroups.FroidurePinTransfUInt4; else # Cannot currently test the next line @@ -65,12 +82,21 @@ function(S) fi; end); -InstallMethod(FroidurePinMemFnRec, "for a partial perm semigroup", -[IsPartialPermSemigroup], -function(S) +InstallMethod(FroidurePinMemFnRec, +"for a partial perm. semigroup and list or coll.", +[IsPartialPermSemigroup, IsListOrCollection], +function(S, coll) local N; N := Maximum(DegreeOfPartialPermSemigroup(S), CodegreeOfPartialPermSemigroup(S)); + if IsPartialPermCollection(coll) then + N := Maximum(N, + DegreeOfPartialPermCollection(coll), + CodegreeOfPartialPermCollection(coll)); + elif not IsEmpty(coll) then + Error("Expected a partial perm. coll. or empty list, found ", + TNAM_OBJ(coll)); + fi; if N <= 16 and IsBound(LIBSEMIGROUPS_HPCOMBI_ENABLED) then return libsemigroups.FroidurePinPPerm16; elif N <= 2 ^ 16 then @@ -860,7 +886,7 @@ function(Constructor, S, coll, opts) Sort(coll, IsGreensDGreaterThanFunc(Semigroup(coll))); fi; - R := FroidurePinMemFnRec(S); + R := FroidurePinMemFnRec(S, coll); # Perform the closure if IsPartialPermSemigroup(S) or IsTransformationSemigroup(S) then @@ -875,8 +901,6 @@ function(Constructor, S, coll, opts) fi; if M > N then # Can't use closure, TODO(later) use copy_closure - # FIXME(later) if M goes larger than the type of R can support this will - # end badly CppT := R.make(); add_generator := R.add_generator; for x in GeneratorsOfSemigroup(S) do diff --git a/gapbind14/include/gapbind14/cpp_fn.hpp b/gapbind14/include/gapbind14/cpp_fn.hpp index 371106a94..af973883f 100644 --- a/gapbind14/include/gapbind14/cpp_fn.hpp +++ b/gapbind14/include/gapbind14/cpp_fn.hpp @@ -35,7 +35,7 @@ namespace gapbind14 { - constexpr size_t MAX_FUNCTIONS = 64; + constexpr size_t MAX_FUNCTIONS = 96; extern UInt T_GAPBIND14_OBJ; //////////////////////////////////////////////////////////////////////// diff --git a/src/to_cpp.hpp b/src/to_cpp.hpp index 0bc9461c9..ca6b7f2c9 100644 --- a/src/to_cpp.hpp +++ b/src/to_cpp.hpp @@ -27,8 +27,6 @@ #include // for max, min, sort #include // for size_t #include // for uint32_t -#include // for exception -#include // for __unwrap_reference<>::type #include // for make_unique, unique_ptr #include // for string #include // for decay_t, is_same, conditional_t @@ -444,12 +442,28 @@ namespace gapbind14 { x[i] = i; } } + template + TransfType new_transf(size_t N) { + return TransfType(N); + } + +#ifdef LIBSEMIGROUPS_HPCOMBI_ENABLED + template <> + inline HPCombi::Transf16 new_transf(size_t N) { + if (N > 16) { + ErrorQuit("expected transformation of degree at most 16, found %d", + (Int) N, + 0L); + } + return HPCombi::Transf16(); + } +#endif } // namespace detail - template - struct to_cpp> { - using cpp_type = Transf<0, Scalar>; + template + struct ToTransf { + using cpp_type = TransfType; cpp_type operator()(Obj t) const { if (!IS_PLIST(t)) { @@ -477,7 +491,7 @@ namespace gapbind14 { (Int) DEG_TRANS(x)); } - cpp_type result(N); + cpp_type result = detail::new_transf(N); if (TNUM_OBJ(x) == T_TRANS2) { detail::to_cpp_transf( result, ADDR_TRANS2(x), std::min(DEG_TRANS(x), N)); @@ -492,6 +506,20 @@ namespace gapbind14 { } }; + template + struct to_cpp> : ToTransf> {}; + +#ifdef LIBSEMIGROUPS_HPCOMBI_ENABLED + template <> + struct to_cpp : public ToTransf {}; + + template <> + struct to_cpp : ToTransf {}; + + template <> + struct to_cpp : ToTransf {}; +#endif + //////////////////////////////////////////////////////////////////////// // Partial perms //////////////////////////////////////////////////////////////////////// @@ -532,11 +560,29 @@ namespace gapbind14 { x[i] = undef; } } + + template + PPermType new_pperm(size_t N) { + return PPermType(N); + } + +#ifdef LIBSEMIGROUPS_HPCOMBI_ENABLED + template <> + inline HPCombi::PPerm16 new_pperm(size_t N) { + if (N > 16) { + ErrorQuit("expected partial perm of degree at most 16, found %d", + (Int) N, + 0L); + } + return HPCombi::PPerm16(); + } +#endif + } // namespace detail - template - struct to_cpp> { - using cpp_type = PPerm<0, Scalar>; + template + struct ToPPerm { + using cpp_type = PPermType; cpp_type operator()(Obj t) const { if (!IS_PLIST(t)) { @@ -573,7 +619,8 @@ namespace gapbind14 { (Int) M); } - cpp_type result(N); + cpp_type result = detail::new_pperm(N); + if (TNUM_OBJ(x) == T_PPERM2) { detail::to_cpp_pperm(result, ADDR_PPERM2(x), DEG_PPERM2(x)); } else if (TNUM_OBJ(x) == T_PPERM4) { @@ -598,6 +645,20 @@ namespace gapbind14 { } }; + template + struct to_cpp> : ToPPerm> {}; + +#ifdef LIBSEMIGROUPS_HPCOMBI_ENABLED + template <> + struct to_cpp : ToPPerm {}; + + template <> + struct to_cpp : ToPPerm {}; + + template <> + struct to_cpp : ToPPerm {}; +#endif + //////////////////////////////////////////////////////////////////////// // Bipartition ////////////////////////////////////////////////////////////////////////