[mathicgb] 359/393: Made registering a reducer type depend on a decentralized method instead of having a big function in Reducer.cpp do it, leading to long compile times when that file needs to be recompiled. The new method is now implemented and being used for ReducerPack. The remaining reducers are using the new method, but it is still being done from Reducer.cpp. Next up: migrate all new reducers to this new way of doing it.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:34 UTC 2015


This is an automated email from the git hooks/post-receive script.

dtorrance-guest pushed a commit to branch upstream
in repository mathicgb.

commit 090f2021f2c13a6f60d980470af250ad33bb38d0
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Fri Sep 6 11:51:37 2013 +0200

    Made registering a reducer type depend on a decentralized method instead of having a big function in Reducer.cpp do it, leading to long compile times when that file needs to be recompiled. The new method is now implemented and being used for ReducerPack. The remaining reducers are using the new method, but it is still being done from Reducer.cpp. Next up: migrate all new reducers to this new way of doing it.
---
 Makefile.am                                        |  18 +-
 build/vs12/mathicgb-lib/mathicgb-lib.vcxproj       |   1 +
 .../vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters |   9 +-
 src/mathicgb/Reducer.cpp                           | 253 ++++++++++++++-------
 src/mathicgb/Reducer.hpp                           |  31 ++-
 src/mathicgb/ReducerHelper.hpp                     |   2 +-
 src/mathicgb/{ReducerPack.hpp => ReducerPack.cpp}  |  87 +++----
 src/mathicgb/ReducerPack.hpp                       | 238 +------------------
 src/mathicgb/ScopeExit.hpp                         |  12 +-
 src/mathicgb/stdinc.h                              |  12 +
 src/test/gb-test.cpp                               | 204 ++++++++---------
 11 files changed, 392 insertions(+), 475 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index bf38d98..688a88f 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,7 +13,8 @@ libmathicgb_la_LIBADD= $(DEPS_LIBS)
 
 # the sources that are built to make libmathicgb. Listing the headers in
 # sources ensure that those files are included in distributions.
-libmathicgb_la_SOURCES = src/mathicgb/ClassicGBAlg.cpp				  \
+libmathicgb_la_SOURCES = src/mathicgb/ReducerPack.hpp				  \
+  src/mathicgb/ReducerPack.cpp src/mathicgb/ClassicGBAlg.cpp		  \
   src/mathicgb/ClassicGBAlg.hpp src/mathicgb/ChainedHashTable.cpp	  \
   src/mathicgb/ChainedHashTable.hpp src/mathicgb/MonoLookup.hpp		  \
   src/mathicgb/MonoLookup.cpp src/mathicgb/StaticMonoMap.hpp		  \
@@ -30,14 +31,13 @@ libmathicgb_la_SOURCES = src/mathicgb/ClassicGBAlg.cpp				  \
   src/mathicgb/Reducer.cpp src/mathicgb/Reducer.hpp					  \
   src/mathicgb/ReducerDedup.hpp src/mathicgb/ReducerHash.hpp		  \
   src/mathicgb/ReducerHashPack.hpp src/mathicgb/ReducerHelper.hpp	  \
-  src/mathicgb/ReducerNoDedup.hpp src/mathicgb/ReducerPack.hpp		  \
-  src/mathicgb/ReducerPackDedup.hpp src/mathicgb/SignatureGB.cpp	  \
-  src/mathicgb/SignatureGB.hpp src/mathicgb/SigSPairs.cpp			  \
-  src/mathicgb/SigSPairs.hpp src/mathicgb/SPairs.cpp				  \
-  src/mathicgb/SPairs.hpp src/mathicgb/stdinc.h						  \
-  src/mathicgb/SigSPairQueue.hpp src/mathicgb/SigSPairQueue.cpp		  \
-  src/mathicgb/SparseMatrix.hpp src/mathicgb/SparseMatrix.cpp		  \
-  src/mathicgb/QuadMatrixBuilder.hpp								  \
+  src/mathicgb/ReducerNoDedup.hpp src/mathicgb/ReducerPackDedup.hpp	  \
+  src/mathicgb/SignatureGB.cpp src/mathicgb/SignatureGB.hpp			  \
+  src/mathicgb/SigSPairs.cpp src/mathicgb/SigSPairs.hpp				  \
+  src/mathicgb/SPairs.cpp src/mathicgb/SPairs.hpp					  \
+  src/mathicgb/stdinc.h src/mathicgb/SigSPairQueue.hpp				  \
+  src/mathicgb/SigSPairQueue.cpp src/mathicgb/SparseMatrix.hpp		  \
+  src/mathicgb/SparseMatrix.cpp src/mathicgb/QuadMatrixBuilder.hpp	  \
   src/mathicgb/QuadMatrixBuilder.cpp src/mathicgb/TypicalReducer.cpp  \
   src/mathicgb/TypicalReducer.hpp src/mathicgb/F4Reducer.hpp		  \
   src/mathicgb/F4Reducer.cpp src/mathicgb/F4MatrixBuilder.hpp		  \
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
index 6ed00ae..ec8b218 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
@@ -463,6 +463,7 @@
     <ClCompile Include="..\..\..\src\mathicgb\QuadMatrix.cpp" />
     <ClCompile Include="..\..\..\src\mathicgb\QuadMatrixBuilder.cpp" />
     <ClCompile Include="..\..\..\src\mathicgb\Reducer.cpp" />
+    <ClCompile Include="..\..\..\src\mathicgb\ReducerPack.cpp" />
     <ClCompile Include="..\..\..\src\mathicgb\Scanner.cpp" />
     <ClCompile Include="..\..\..\src\mathicgb\SignatureGB.cpp" />
     <ClCompile Include="..\..\..\src\mathicgb\SigPolyBasis.cpp" />
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
index 4f8f7cd..b6797d1 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
@@ -107,6 +107,9 @@
     <ClCompile Include="..\..\..\src\mathicgb\ModuleMonoSet.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\src\mathicgb\ReducerPack.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\src\mathicgb\ChainedHashTable.hpp">
@@ -169,9 +172,6 @@
     <ClInclude Include="..\..\..\src\mathicgb\ReducerNoDedup.hpp">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\..\src\mathicgb\ReducerPack.hpp">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\..\src\mathicgb\ReducerPackDedup.hpp">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -277,5 +277,8 @@
     <ClInclude Include="..\..\..\src\mathicgb\ModuleMonoSet.hpp">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\src\mathicgb\ReducerPack.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/mathicgb/Reducer.cpp b/src/mathicgb/Reducer.cpp
index e6e30d0..6e336c7 100755
--- a/src/mathicgb/Reducer.cpp
+++ b/src/mathicgb/Reducer.cpp
@@ -16,7 +16,166 @@
 
 MATHICGB_NAMESPACE_BEGIN
 
-Reducer::~Reducer() {}
+// Calling these dummy methods from the various reducer file headers ensures
+// that those translation units are registered as necessary. Without this,
+// they will not be linked in, because apparently the linker does not consider
+// the presense of global object constructors as a reason to include a
+// translation unit into the library. It will simply note that no other
+// translation unit has a dependency on anything in that translation unit
+// and then not include it in the library. This was wonderful to diagnose.
+void dummyLinkerFix() {
+  reducerPackDependency();
+}
+
+Reducer::~Reducer() {
+  // Has to be called somewhere or GCC will eliminate it.
+  dummyLinkerFix();
+}
+
+/// Vector that stores the registered reducer typers. This has to be a
+/// function rather than just a naked object to ensure that the object
+/// gets initialized before it is used.
+std::vector<Reducer::Registration*>& reducerTypes() {
+  static std::vector<Reducer::Registration*> types;
+  return types;
+}
+
+Reducer::Registration::Registration(
+  const char* name, 
+  ReducerType id,
+  std::unique_ptr<Reducer> (*create)(const PolyRing&)
+):
+  mName(name),
+  mId(id),
+  mCreate(create)
+{
+  reducerTypes().push_back(this);
+}
+
+Reducer::Registration r1(
+  "TourNoDedup",
+  Reducer::Reducer_TourTree_NoDedup,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerNoDedup<mic::TourTree>>(ring);
+  }
+);
+
+Reducer::Registration r2(
+  "TourDedup",
+  Reducer::Reducer_TourTree_Dedup,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerDedup<mic::TourTree>>(ring);
+  }
+);
+Reducer::Registration r3(
+  "TourHash",
+  Reducer::Reducer_TourTree_Hashed,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerHash<mic::TourTree>>(ring);
+  }
+);
+ 
+ 
+Reducer::Registration r5(
+  "TourDedupPack",
+  Reducer::Reducer_TourTree_Dedup_Packed,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerPackDedup<mic::TourTree>>(ring);
+  }
+);
+  
+Reducer::Registration r6(
+  "TourHashPack",
+  Reducer::Reducer_TourTree_Hashed_Packed,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerHashPack<mic::TourTree>>(ring);
+  }
+);
+
+Reducer::Registration r7(
+  "HeapNoDedup",
+  Reducer::Reducer_Heap_NoDedup,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerNoDedup<mic::Heap>>(ring);
+  }
+);
+Reducer::Registration r8(
+  "HeapDedup",
+  Reducer::Reducer_Heap_Dedup,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerDedup<mic::Heap>>(ring);
+  }
+);
+ 
+Reducer::Registration r9(
+  "HeapHash",
+  Reducer::Reducer_Heap_Hashed,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerHash<mic::Heap>>(ring);
+  }
+);
+Reducer::Registration r11(
+  "HeapDedupPack",
+  Reducer::Reducer_Heap_Dedup_Packed,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerPackDedup<mic::Heap>>(ring);
+  }
+);
+Reducer::Registration r12(
+  "HeapHashPack",
+  Reducer::Reducer_Heap_Hashed_Packed,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerHashPack<mic::Heap>>(ring);
+  }
+);
+Reducer::Registration r13(
+  "GeoNoDedup",
+  Reducer::Reducer_Geobucket_NoDedup,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerNoDedup<mic::Geobucket>>(ring);
+  }
+);
+Reducer::Registration r14(
+  "GeoDedup",
+  Reducer::Reducer_Geobucket_Dedup,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerDedup<mic::Geobucket>>(ring);
+  }
+);
+Reducer::Registration r15(
+  "GeoHash",
+  Reducer::Reducer_Geobucket_Hashed,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerHash<mic::Geobucket>>(ring);
+  }
+);
+Reducer::Registration r17(
+  "GeoDedupPack",
+  Reducer::Reducer_Geobucket_Dedup_Packed,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerPackDedup<mic::Geobucket>>(ring);
+  }
+);
+Reducer::Registration r18(
+  "GeoHashPack",
+  Reducer::Reducer_Geobucket_Hashed_Packed,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<ReducerHashPack<mic::Geobucket>>(ring);
+  }
+);
+Reducer::Registration r19(
+  "F4Old",
+  Reducer::Reducer_F4_Old,
+  [](const PolyRing& ring) -> std::unique_ptr<Reducer> {
+    return make_unique<F4Reducer>(ring, F4Reducer::OldType);
+  }
+);
+
+MATHICGB_REGISTER_REDUCER(
+  "F4New",
+  Reducer_F4_New,
+  (make_unique<F4Reducer>(ring, F4Reducer::NewType))
+);
 
 std::unique_ptr<Reducer> Reducer::makeReducer(
   ReducerType type,
@@ -36,60 +195,16 @@ std::unique_ptr<Reducer> Reducer::makeReducerNullOnUnknown(
   ReducerType type,
   PolyRing const& ring
 ) {
-  switch (type) {
-  case Reducer_TourTree_NoDedup:
-    return std::unique_ptr<Reducer>(new ReducerNoDedup<mic::TourTree>(ring));
-  case Reducer_TourTree_Dedup:
-    return std::unique_ptr<Reducer>(new ReducerDedup<mic::TourTree>(ring));
-  case Reducer_TourTree_Hashed:
-    return std::unique_ptr<Reducer>(new ReducerHash<mic::TourTree>(ring));
-  case Reducer_TourTree_NoDedup_Packed:
-    return std::unique_ptr<Reducer>(new ReducerPack<mic::TourTree>(ring));
-  case Reducer_TourTree_Dedup_Packed:
-    return std::unique_ptr<Reducer>(new ReducerPackDedup<mic::TourTree>(ring));
-  case Reducer_TourTree_Hashed_Packed:
-    return std::unique_ptr<Reducer>(new ReducerHashPack<mic::TourTree>(ring));
-
-  case Reducer_Heap_NoDedup:
-    return std::unique_ptr<Reducer>(new ReducerNoDedup<mic::Heap>(ring));
-  case Reducer_Heap_Dedup:
-    return std::unique_ptr<Reducer>(new ReducerDedup<mic::Heap>(ring));
-  case Reducer_Heap_Hashed:
-    return std::unique_ptr<Reducer>(new ReducerHash<mic::Heap>(ring));
-  case Reducer_Heap_NoDedup_Packed:
-    return std::unique_ptr<Reducer>(new ReducerPack<mic::Heap>(ring));
-  case Reducer_Heap_Dedup_Packed:
-    return std::unique_ptr<Reducer>(new ReducerPackDedup<mic::Heap>(ring));
-  case Reducer_Heap_Hashed_Packed:
-    return std::unique_ptr<Reducer>(new ReducerHashPack<mic::Heap>(ring));
-
-  case Reducer_Geobucket_NoDedup:
-    return std::unique_ptr<Reducer>(new ReducerNoDedup<mic::Geobucket>(ring));
-  case Reducer_Geobucket_Dedup:
-    return std::unique_ptr<Reducer>(new ReducerDedup<mic::Geobucket>(ring));
-  case Reducer_Geobucket_Hashed:
-    return std::unique_ptr<Reducer>(new ReducerHash<mic::Geobucket>(ring));
-  case Reducer_Geobucket_NoDedup_Packed:
-    return std::unique_ptr<Reducer>(new ReducerPack<mic::Geobucket>(ring));
-  case Reducer_Geobucket_Dedup_Packed:
-    return std::unique_ptr<Reducer>(new ReducerPackDedup<mic::Geobucket>(ring));
-  case Reducer_Geobucket_Hashed_Packed:
-    return std::unique_ptr<Reducer>(new ReducerHashPack<mic::Geobucket>(ring));
-
-  case Reducer_F4_Old:
-    return make_unique<F4Reducer>(ring, F4Reducer::OldType);
-  case Reducer_F4_New:
-    return make_unique<F4Reducer>(ring, F4Reducer::NewType);
-
-  default:
-    break;
-  };
-  return std::unique_ptr<Reducer>();
+  for (const auto& r : reducerTypes()) {
+    if (type == r->mId)
+      return r->mCreate(ring);
+  }
+  return nullptr;
 }
 
-Reducer::ReducerType Reducer::reducerType(int typ)
+Reducer::ReducerType Reducer::reducerType(int type)
 {
-  switch (typ) {
+  switch (type) {
   case 7: return Reducer_TourTree_NoDedup;
   case 8: return Reducer_TourTree_Dedup;
   case 9: return Reducer_TourTree_Hashed;
@@ -118,32 +233,16 @@ Reducer::ReducerType Reducer::reducerType(int typ)
   }
 }
 
-void Reducer::displayReducerTypes(std::ostream &o)
+void Reducer::displayReducerTypes(std::ostream& out)
 {
-  o << "Reducer types:" << std::endl;
-  o << "   7   TournamentTree.NoDedup" << std::endl;
-  o << "   8   TournamentTree.Dedup" << std::endl;
-  o << "   9   TournamentTree.Hashed" << std::endl;
-  o << "  10   TournamentTree.NoDedup.Packed" << std::endl;
-  o << "  11   TournamentTree.Dedup.Packed" << std::endl;
-  o << "  12   TournamentTree.Hashed.Packed" << std::endl;
-
-  o << "  13   Heap.NoDedup" << std::endl; 
-  o << "  14   Heap.Dedup" << std::endl;
-  o << "  15   Heap.Hashed" << std::endl;
-  o << "  16   Heap.NoDedup.Packed" << std::endl;
-  o << "  17   Heap.Dedup.Packed" << std::endl;
-  o << "  18   Heap.Hashed.Packed" << std::endl;
-
-  o << "  19   Geobucket.NoDedup" << std::endl;
-  o << "  20   Geobucket.Dedup" << std::endl;
-  o << "  21   Geobucket.Hashed" << std::endl;
-  o << "  22   Geobucket.NoDedup.Packed" << std::endl;
-  o << "  23   Geobucket.Dedup.Packed" << std::endl;
-  o << "  24   Geobucket.Hashed.Packed" << std::endl;
-
-  o << "  25   F4 reducer, old" << std::endl;
-  o << "  26   F4 reducer, new" << std::endl;
+  mathic::ColumnPrinter pr;
+  auto& id = pr.addColumn(false, "  ");
+  auto& desc = pr.addColumn(true, "   ");
+  for (const auto& r : reducerTypes()) {
+    id << r->mId << '\n';
+    desc << r->mName << '\n';
+  }
+  out << "Reducer types:\n" << pr;
 }
 
 MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/Reducer.hpp b/src/mathicgb/Reducer.hpp
index e9e0473..4228d1f 100755
--- a/src/mathicgb/Reducer.hpp
+++ b/src/mathicgb/Reducer.hpp
@@ -116,8 +116,37 @@ public:
     (ReducerType t, const PolyRing& ring);
 
   static ReducerType reducerType(int typ);
-  static void displayReducerTypes(std::ostream& o);
+  static void displayReducerTypes(std::ostream& out);
+
+  class Registration {
+  public:
+    Registration(
+      const char* name, 
+      ReducerType id,
+      std::unique_ptr<Reducer> (*create)(const PolyRing&)
+    );
+
+  private:
+    friend class Reducer;
+
+    const char* mName; 
+    ReducerType mId;
+    std::unique_ptr<Reducer> (*mCreate)(const PolyRing&);
+  };
 };
 
+/// Registers a reducer type with the given name and id. The value of
+/// create, when executed, should be something convertible to a
+/// std::unique_ptr<Reducer>. CREATE may pick up a const PolyRing&
+/// by the name ring.
+#define MATHICGB_REGISTER_REDUCER(NAME, ID, CREATE) \
+  Reducer::Registration MATHICGB_UNIQUE(reducerRegistration) ( \
+    NAME, \
+    Reducer:: ID, \
+    [](const PolyRing& ring) -> std::unique_ptr<Reducer> { \
+      return CREATE; \
+    } \
+  )
+
 MATHICGB_NAMESPACE_END
 #endif
diff --git a/src/mathicgb/ReducerHelper.hpp b/src/mathicgb/ReducerHelper.hpp
index f32f190..caf933c 100755
--- a/src/mathicgb/ReducerHelper.hpp
+++ b/src/mathicgb/ReducerHelper.hpp
@@ -80,7 +80,7 @@ namespace ReducerHelper {
 
   // ************** Utility functions **********************
 
-  const_term allocTermCopy(const PolyRing& ring, const_term term) {
+  inline const_term allocTermCopy(const PolyRing& ring, const_term term) {
     monomial mono = ring.allocMonomial();
     ring.monomialCopy(term.monom, mono);
     return const_term(term.coeff, mono);
diff --git a/src/mathicgb/ReducerPack.hpp b/src/mathicgb/ReducerPack.cpp
old mode 100755
new mode 100644
similarity index 84%
copy from src/mathicgb/ReducerPack.hpp
copy to src/mathicgb/ReducerPack.cpp
index 97984f9..a7151aa
--- a/src/mathicgb/ReducerPack.hpp
+++ b/src/mathicgb/ReducerPack.cpp
@@ -1,7 +1,7 @@
 // MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
 // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
-#ifndef MATHICGB_REDUCER_PACK_GUARD
-#define MATHICGB_REDUCER_PACK_GUARD
+#include "stdinc.h"
+#include "ReducerPack.hpp"
 
 #include "TypicalReducer.hpp"
 #include "ReducerHelper.hpp"
@@ -10,11 +10,23 @@
 
 MATHICGB_NAMESPACE_BEGIN
 
+void reducerPackDependency() {}
+
 template<template<typename> class Queue>
 class ReducerPack : public TypicalReducer {
 public:
-  ReducerPack(const PolyRing& ring);
-  virtual ~ReducerPack();
+  ReducerPack(const PolyRing& ring):
+    mRing(ring),
+    mLeadTerm(0, mRing.allocMonomial()),
+    mLeadTermKnown(false),
+    mQueue(Configuration(ring)),
+    mPool(sizeof(MultipleWithPos))
+  {}
+
+  virtual ~ReducerPack() {
+    resetReducer();
+    mRing.freeMonomial(mLeadTerm.monom);
+  }
 
   virtual std::string description() const {
     return mQueue.getName() + "-packed";
@@ -61,9 +73,20 @@ public:
       return ring().monomialLT(a->current, b->current);
     }
   };
+
 private:
+  class MonomialFree {
+  public:
+    MonomialFree(const PolyRing& ring): mRing(ring) {}
 
-  class MonomialFree;
+    bool proceed(MultipleWithPos* entry) {
+      entry->destroy(mRing);
+      return true;
+    }
+
+  private:
+    const PolyRing& mRing;
+  };
   
   const PolyRing& mRing;
   term mLeadTerm;
@@ -73,41 +96,6 @@ private:
 };
 
 template<template<typename> class Q>
-ReducerPack<Q>::ReducerPack(const PolyRing& ring):
-  mRing(ring),
-  mLeadTerm(0, mRing.allocMonomial()),
-  mLeadTermKnown(false),
-  mQueue(Configuration(ring)),
-  mPool(sizeof(MultipleWithPos))
-{
-}
-
-template<template<typename> class Q>
-class ReducerPack<Q>::MonomialFree
-{
-public:
-  MonomialFree(const PolyRing& ring): mRing(ring) {}
-
-  bool proceed(MultipleWithPos* entry)
-  {
-    entry->destroy(mRing);
-    return true;
-  }
-private:
-  const PolyRing& mRing;
-};
-
-template<template<typename> class Q>
-ReducerPack<Q>::~ReducerPack()
-{
-  resetReducer();
-  mRing.freeMonomial(mLeadTerm.monom);
-}
-
-///////////////////////////////////////
-// External interface routines ////////
-///////////////////////////////////////
-template<template<typename> class Q>
 void ReducerPack<Q>::insertTail(const_term multiple, const Poly* poly)
 {
   if (poly->nTerms() <= 1)
@@ -239,5 +227,22 @@ size_t ReducerPack<Q>::getMemoryUse() const
     mPool.getMemoryUse();
 }
 
+MATHICGB_REGISTER_REDUCER(
+  "TourNoDedupPack",
+  Reducer_TourTree_NoDedup_Packed,
+  make_unique<ReducerPack<mic::TourTree>>(ring)
+);
+
+MATHICGB_REGISTER_REDUCER(
+  "HeapNoDedupPack",
+  Reducer_Heap_NoDedup_Packed,
+  make_unique<ReducerPack<mic::Heap>>(ring)
+);
+
+MATHICGB_REGISTER_REDUCER(
+  "GeoNoDedupPack",
+  Reducer_Geobucket_NoDedup_Packed,
+  make_unique<ReducerPack<mic::Geobucket>>(ring)
+);
+
 MATHICGB_NAMESPACE_END
-#endif
diff --git a/src/mathicgb/ReducerPack.hpp b/src/mathicgb/ReducerPack.hpp
old mode 100755
new mode 100644
index 97984f9..6b7e399
--- a/src/mathicgb/ReducerPack.hpp
+++ b/src/mathicgb/ReducerPack.hpp
@@ -3,241 +3,13 @@
 #ifndef MATHICGB_REDUCER_PACK_GUARD
 #define MATHICGB_REDUCER_PACK_GUARD
 
-#include "TypicalReducer.hpp"
-#include "ReducerHelper.hpp"
-#include <memtailor.h>
-#include <mathic.h>
-
 MATHICGB_NAMESPACE_BEGIN
 
-template<template<typename> class Queue>
-class ReducerPack : public TypicalReducer {
-public:
-  ReducerPack(const PolyRing& ring);
-  virtual ~ReducerPack();
-
-  virtual std::string description() const {
-    return mQueue.getName() + "-packed";
-  }
-
-  virtual void insertTail(const_term multiplier, const Poly* f);
-  virtual void insert(monomial multiplier, const Poly* f);
-
-  virtual bool leadTerm(const_term& result);
-  virtual void removeLeadTerm();
-
-  virtual size_t getMemoryUse() const;
-
-protected:
-  virtual void resetReducer();
-
-private:
-  // Represents a term multiple of a polynomial, 
-  // together with a current term of the multiple.
-public:
-  struct MultipleWithPos {
-    MultipleWithPos(const Poly& poly, const_term multiple);
-
-    Poly::const_iterator pos;
-    Poly::const_iterator const end;
-    const_term const multiple;
-
-    // invariant: current is the monomial product of multiple.monom 
-    // and pos.getMonomial().
-    monomial current;
-
-    // Ensures the invariant, so sets current to the product of
-    // multiple.monom and pos.getMonomial().
-    void computeCurrent(const PolyRing& ring);
-    void currentCoefficient(const PolyRing& ring, coefficient& coeff);
-    void destroy(const PolyRing& ring);
-  };
-
-  class Configuration : public ReducerHelper::PlainConfiguration {
-  public:
-    typedef MultipleWithPos* Entry;
-    Configuration(const PolyRing& ring) : PlainConfiguration(ring) {}
-    CompareResult compare(const Entry& a, const Entry& b) const {
-      return ring().monomialLT(a->current, b->current);
-    }
-  };
-private:
-
-  class MonomialFree;
-  
-  const PolyRing& mRing;
-  term mLeadTerm;
-  bool mLeadTermKnown;
-  Queue<Configuration> mQueue;
-  memt::BufferPool mPool;
-};
-
-template<template<typename> class Q>
-ReducerPack<Q>::ReducerPack(const PolyRing& ring):
-  mRing(ring),
-  mLeadTerm(0, mRing.allocMonomial()),
-  mLeadTermKnown(false),
-  mQueue(Configuration(ring)),
-  mPool(sizeof(MultipleWithPos))
-{
-}
-
-template<template<typename> class Q>
-class ReducerPack<Q>::MonomialFree
-{
-public:
-  MonomialFree(const PolyRing& ring): mRing(ring) {}
-
-  bool proceed(MultipleWithPos* entry)
-  {
-    entry->destroy(mRing);
-    return true;
-  }
-private:
-  const PolyRing& mRing;
-};
-
-template<template<typename> class Q>
-ReducerPack<Q>::~ReducerPack()
-{
-  resetReducer();
-  mRing.freeMonomial(mLeadTerm.monom);
-}
-
-///////////////////////////////////////
-// External interface routines ////////
-///////////////////////////////////////
-template<template<typename> class Q>
-void ReducerPack<Q>::insertTail(const_term multiple, const Poly* poly)
-{
-  if (poly->nTerms() <= 1)
-    return;
-  mLeadTermKnown = false;
-
-  MultipleWithPos* entry =
-    new (mPool.alloc()) MultipleWithPos(*poly, multiple);
-  ++entry->pos;
-  entry->computeCurrent(poly->ring());
-  mQueue.push(entry);
-}
-
-template<template<typename> class Q>
-void ReducerPack<Q>::insert(monomial multiple, const Poly* poly)
-{
-  if (poly->isZero())
-    return;
-  mLeadTermKnown = false;
-
-  // todo: avoid multiplication by 1
-  term termMultiple(1, multiple);
-  MultipleWithPos* entry =
-    new (mPool.alloc()) MultipleWithPos(*poly, termMultiple);
-  entry->computeCurrent(poly->ring());
-  mQueue.push(entry);
-}
-
-template<template<typename> class Q>
-ReducerPack<Q>::MultipleWithPos::MultipleWithPos
-(const Poly& poly, const_term multipleParam):
-  pos(poly.begin()),
-  end(poly.end()),
-  multiple(ReducerHelper::allocTermCopy(poly.ring(), multipleParam)),
-  current(poly.ring().allocMonomial()) {}
-
-template<template<typename> class Q>
-void ReducerPack<Q>::MultipleWithPos::computeCurrent(const PolyRing& ring) {
-  ring.monomialMult(multiple.monom, pos.getMonomial(), current);  
-}
-
-template<template<typename> class Q>
-void ReducerPack<Q>::MultipleWithPos::currentCoefficient
-(const PolyRing& ring, coefficient& coeff) {
-  ring.coefficientMult(multiple.coeff, pos.getCoefficient(), coeff);
-}
-
-template<template<typename> class Q>
-void ReducerPack<Q>::MultipleWithPos::destroy(const PolyRing& ring) {
-  ring.freeMonomial(current);
-  ConstMonomial& monom = const_cast<ConstMonomial&>(multiple.monom);
-  ring.freeMonomial(monom.castAwayConst());
-
-  // Call the destructor to destruct the iterators into std::vector.
-  // In debug mode MSVC puts those in a linked list and the destructor
-  // has to be called since it takes an iterator off the list. We had
-  // memory corruption problems before doing this.
-  this->~MultipleWithPos();
-}
-
-template<template<typename> class Q>
-bool ReducerPack<Q>::leadTerm(const_term& result)
-{
-  if (mLeadTermKnown) {
-    result = mLeadTerm;
-    return true;
-  }
-
-  do {
-    if (mQueue.empty())
-      return false;
-    MultipleWithPos* entry = mQueue.top();
-    mLeadTerm.monom.swap(entry->current);
-    entry->currentCoefficient(mRing, mLeadTerm.coeff);
-    
-    while (true) {
-      ++entry->pos;
-      if (entry->pos == entry->end) {
-        mQueue.pop();
-        entry->destroy(mRing);
-        mPool.free(entry);
-      } else {
-        entry->computeCurrent(mRing);
-        mQueue.decreaseTop(entry);
-      }
-      
-      if (mQueue.empty())
-        break;
-      
-      entry = mQueue.top();
-      if (!mRing.monomialEQ(entry->current, mLeadTerm.monom))
-        break;
-      coefficient coeff;
-      entry->currentCoefficient(mRing, coeff);
-      mRing.coefficientAddTo
-        (mLeadTerm.coeff, const_cast<const coefficient&>(coeff));
-    }
-  } while (mRing.coefficientIsZero(mLeadTerm.coeff));
-
-  result = mLeadTerm;
-  mLeadTermKnown = true;
-  return true;
-}
-
-template<template<typename> class Q>
-void ReducerPack<Q>::removeLeadTerm()
-{
-  if (!mLeadTermKnown) {
-    const_term dummy;
-    leadTerm(dummy);
-  }
-  mLeadTermKnown = false;
-}
-
-template<template<typename> class Q>
-void ReducerPack<Q>::resetReducer()
-{
-  MonomialFree freeer(mRing);
-  mQueue.forAll(freeer);
-  mQueue.clear();
-}
-
-template<template<typename> class Q>
-size_t ReducerPack<Q>::getMemoryUse() const
-{
-  return
-    TypicalReducer::getMemoryUse() +
-    mQueue.getMemoryUse() +
-    mPool.getMemoryUse();
-}
+// This translation unit has to expose something that is needed elsewhere.
+// Otherwise, the compiler will think it is not needed and exclude the
+// whole thing, despite there being important global objects in the .cpp file.
+void reducerPackDependency();
 
 MATHICGB_NAMESPACE_END
+
 #endif
diff --git a/src/mathicgb/ScopeExit.hpp b/src/mathicgb/ScopeExit.hpp
index 3189333..fa45b8a 100755
--- a/src/mathicgb/ScopeExit.hpp
+++ b/src/mathicgb/ScopeExit.hpp
@@ -59,10 +59,6 @@ private:
 
 MATHICGB_NAMESPACE_END
 
-#define MYLIB__CAT_HELPER(A, B) A##B
-#define MYLIB__CAT(A, B) MYLIB__CAT_HELPER(A, B)
-#define MYLIB__UNIQUE(NAME) MYLIB__CAT(MyLib_,MYLIB__CAT(NAME,__LINE__))
-
 // Example, with no need to dismiss:
 //   FILE* file = fopen("file.txt", "r");
 //   MATHICGB_SCOPE_EXIT() {
@@ -89,10 +85,10 @@ MATHICGB_NAMESPACE_END
 // to copy, but this way we can keep the copy constructor private
 // and help out any compiler that has issue with eliding that copy.
 #define MATHICGB_SCOPE_EXIT(NAME) \
-  bool MYLIB__UNIQUE(active) = true; \
-  ::mgb::Dismisser NAME(static_cast<bool&>(MYLIB__UNIQUE(active)));    \
-  const auto& MYLIB__UNIQUE(guard) = \
-    ::mgb::GuardMaker(MYLIB__UNIQUE(active)) + [&]
+  bool MATHICGB_UNIQUE(active) = true; \
+  ::mgb::Dismisser NAME(static_cast<bool&>(MATHICGB_UNIQUE(active))); \
+  const auto& MATHICGB_UNIQUE(guard) = \
+    ::mgb::GuardMaker(MATHICGB_UNIQUE(active)) + [&]
 
 // Without this pragma, MSVC will say
 //  warning C4003: not enough actual parameters for macro 'MYLIB_SCOPE_EXIT'
diff --git a/src/mathicgb/stdinc.h b/src/mathicgb/stdinc.h
index 91812ff..e2fae03 100755
--- a/src/mathicgb/stdinc.h
+++ b/src/mathicgb/stdinc.h
@@ -160,6 +160,18 @@
 /// as that macro does.
 #define MATHICGB_CONCATENATE_AFTER_EXPANSION(A,B) MATHICGB_CONCATENATE(A,B)
 
+/// Returns an identifier that will be unique in the current file. If you need
+/// two different identifiers on the same line, you'll need to pass in two
+/// different ID paramters. Otherwise the ID parameter can be any identifier.
+/// On the same line, the identifier will be the same if the ID is the same.
+/// This can be useful in some macroes.
+#define MATHICGB_UNIQUE(ID) \
+  MATHICGB_CONCATENATE_AFTER_EXPANSION( \
+    MathicGB_unique_identifier_, \
+    MATHICGB_CONCATENATE_AFTER_EXPANSION(ID,__LINE__) \
+  )
+
+
 /// Opens the mgb namespace. The purpose of having this be a macro is
 /// that otherwise editors the world over would automatically indent ALL
 /// CODE in MathicGB by an extra level to no benefit. By hiding the
diff --git a/src/test/gb-test.cpp b/src/test/gb-test.cpp
index cef0d30..649bb1f 100755
--- a/src/test/gb-test.cpp
+++ b/src/test/gb-test.cpp
@@ -50,108 +50,108 @@ void testGB(
   // pict.in for details.
 #define MATHICGB_ESCAPE_MULTILINE_STRING(str) #str
 char const allPairsTests[] = MATHICGB_ESCAPE_MULTILINE_STRING(
-spairQueue	reducerType	divLookup	monTable	buchberger	postponeKoszul	useBaseDivisors	autoTailReduce	autoTopReduce	preferSparseReducers	useSingularCriterionEarly	sPairGroupSize	threadCount
-0	25	4	1	1	0	0	0	0	0	0	1	1
-3	11	3	2	0	1	1	0	0	1	1	100	2
-1	9	1	4	1	0	0	1	1	1	0	2	8
-2	21	2	3	1	0	0	1	1	0	0	10	2
-1	9	2	4	0	1	1	0	0	0	1	1	2
-2	7	1	3	0	0	1	0	0	1	1	1	8
-0	21	4	1	0	1	0	0	0	1	1	100	1
-3	26	3	2	1	0	0	0	1	1	0	10	1
-3	26	3	1	1	0	0	1	1	0	0	1	8
-0	25	4	2	1	0	0	1	1	1	0	0	8
-0	14	1	1	0	1	1	0	0	0	1	10	8
-2	22	4	4	1	0	0	1	0	0	0	10	1
-1	14	4	3	0	1	1	0	0	1	0	2	1
-2	10	2	2	0	1	1	0	0	0	1	2	2
-3	17	2	1	0	1	1	0	0	0	1	0	2
-0	18	1	2	0	1	1	0	0	1	1	1	2
-0	23	2	3	1	0	0	1	1	1	0	10	1
-1	10	3	4	1	0	0	1	1	0	0	100	8
-2	19	3	3	0	1	1	0	0	0	1	0	1
-0	26	4	1	1	0	0	0	0	1	0	2	2
-3	13	1	4	1	0	0	1	0	1	0	2	1
-1	15	2	1	1	0	0	1	0	0	0	10	8
-0	21	3	4	1	0	0	1	1	0	0	2	8
-3	10	4	3	0	0	1	0	0	1	1	1	1
-1	12	1	2	0	0	1	0	0	0	1	10	8
-2	19	1	1	1	0	0	1	1	1	0	100	8
-1	19	4	2	1	0	0	0	1	1	0	10	2
-1	16	1	4	1	0	0	0	1	1	0	0	1
-1	26	2	3	1	0	0	1	0	0	0	100	8
-2	16	4	3	0	1	1	0	0	0	1	1	2
-0	7	2	1	1	0	0	1	1	0	0	10	2
-3	9	4	2	0	1	0	0	0	0	1	10	1
-1	17	3	3	1	0	0	1	1	1	0	10	1
-1	23	1	2	0	1	1	0	0	0	1	1	2
-2	14	3	4	1	0	0	1	1	1	0	100	2
-1	7	4	4	1	0	0	1	1	0	0	2	1
-1	13	4	3	0	1	1	0	0	0	1	1	2
-3	23	4	1	0	0	1	0	0	0	1	0	8
-3	7	3	2	0	1	1	0	0	1	1	0	2
-0	17	1	2	1	0	0	1	1	0	0	100	8
-0	10	1	1	0	1	1	0	0	1	0	10	8
-0	12	2	4	1	0	0	1	1	1	0	1	2
-2	12	4	1	1	0	0	1	1	1	0	0	1
-1	18	4	1	1	0	0	1	1	0	0	2	8
-1	22	1	1	0	1	1	0	0	1	1	2	2
-1	21	1	2	0	0	1	0	0	0	1	0	1
-2	11	4	4	1	0	0	1	1	0	0	10	8
-0	15	3	3	0	1	1	0	0	1	1	1	2
-2	23	3	4	1	0	0	0	0	0	0	2	8
-2	17	4	4	0	1	0	0	0	0	1	2	1
-0	13	2	2	1	0	0	1	1	1	0	0	8
-2	13	3	1	0	1	1	0	0	0	1	100	2
-0	9	3	1	1	0	0	1	0	1	0	0	8
-0	20	1	3	0	1	0	0	0	1	1	2	8
-0	11	1	3	1	0	0	0	1	1	0	1	1
-2	8	1	4	1	0	0	1	0	1	0	2	1
-1	20	2	1	1	0	0	1	1	0	0	100	2
-0	22	2	3	0	0	0	0	0	0	1	100	8
-1	13	4	4	1	0	0	0	0	1	0	10	8
-0	16	3	2	0	1	0	0	0	1	1	2	8
-3	22	3	2	0	0	0	0	0	1	1	0	8
-1	8	2	1	0	1	1	0	0	0	1	10	8
-0	19	2	4	0	1	1	0	0	0	1	1	8
-1	11	2	1	1	0	0	1	0	0	0	0	2
-3	15	1	2	1	0	0	0	1	0	0	100	1
-1	17	4	3	0	1	0	0	0	1	1	1	1
-3	24	2	4	0	1	1	0	0	1	1	1	8
-2	24	3	3	1	0	0	1	1	0	0	2	1
-3	8	3	2	1	0	0	1	1	0	0	100	2
-3	21	3	4	0	0	0	0	0	0	0	1	8
-2	26	1	4	1	0	0	1	1	0	0	0	2
-3	14	2	2	0	1	1	0	0	1	1	0	1
-0	8	4	3	0	0	1	0	0	0	1	1	1
-2	9	1	3	1	0	0	1	0	1	0	100	2
-3	12	3	3	0	1	1	0	0	0	1	100	8
-0	7	1	4	1	0	0	1	1	1	0	100	8
-0	10	4	2	0	0	1	0	0	0	1	0	2
-1	24	4	1	0	0	1	0	0	0	1	0	2
-3	16	2	1	0	0	0	0	0	1	1	10	1
-3	18	2	3	0	1	1	0	0	1	1	0	1
-2	16	3	4	0	1	1	0	0	0	1	100	8
-0	11	1	3	0	0	1	0	0	0	1	2	1
-2	14	2	2	0	1	0	0	0	0	1	1	8
-2	12	4	3	1	0	0	1	1	1	0	2	8
-0	8	1	4	0	0	1	0	0	0	1	0	1
-3	25	2	3	1	0	0	1	0	1	0	2	2
-2	15	4	4	1	0	0	1	1	0	0	2	1
-3	20	3	2	1	0	0	1	1	0	0	0	1
-3	23	4	4	0	1	1	0	0	0	1	100	2
-2	25	3	4	1	0	0	0	0	1	0	100	2
-1	25	1	2	1	0	0	0	1	1	0	10	8
-0	24	1	2	0	0	1	0	0	1	1	10	1
-1	15	4	3	1	0	0	1	1	1	0	0	2
-1	24	3	4	0	1	0	0	0	0	1	100	1
-2	20	4	4	0	1	1	0	0	1	0	1	1
-1	22	4	3	1	0	0	0	1	0	0	1	2
-2	18	3	4	0	0	0	0	0	0	0	100	8
-3	19	2	4	0	0	0	0	0	0	1	2	1
-2	18	1	1	1	0	0	0	1	0	0	10	1
-3	16	2	3	1	0	0	1	1	1	0	10	8
-2	20	4	1	0	1	1	0	0	0	1	10	8
+spairQueue	reducerType	divLookup	monTable	buchberger	postponeKoszul	useBaseDivisors	autoTailReduce	autoTopReduce	preferSparseReducers	useSingularCriterionEarly	sPairGroupSize	threadCount
+0	25	4	1	1	0	0	0	0	0	0	1	1
+3	11	3	2	0	1	1	0	0	1	1	100	2
+1	9	1	4	1	0	0	1	1	1	0	2	8
+2	21	2	3	1	0	0	1	1	0	0	10	2
+1	9	2	4	0	1	1	0	0	0	1	1	2
+2	7	1	3	0	0	1	0	0	1	1	1	8
+0	21	4	1	0	1	0	0	0	1	1	100	1
+3	26	3	2	1	0	0	0	1	1	0	10	1
+3	26	3	1	1	0	0	1	1	0	0	1	8
+0	25	4	2	1	0	0	1	1	1	0	0	8
+0	14	1	1	0	1	1	0	0	0	1	10	8
+2	22	4	4	1	0	0	1	0	0	0	10	1
+1	14	4	3	0	1	1	0	0	1	0	2	1
+2	10	2	2	0	1	1	0	0	0	1	2	2
+3	17	2	1	0	1	1	0	0	0	1	0	2
+0	18	1	2	0	1	1	0	0	1	1	1	2
+0	23	2	3	1	0	0	1	1	1	0	10	1
+1	10	3	4	1	0	0	1	1	0	0	100	8
+2	19	3	3	0	1	1	0	0	0	1	0	1
+0	26	4	1	1	0	0	0	0	1	0	2	2
+3	13	1	4	1	0	0	1	0	1	0	2	1
+1	15	2	1	1	0	0	1	0	0	0	10	8
+0	21	3	4	1	0	0	1	1	0	0	2	8
+3	10	4	3	0	0	1	0	0	1	1	1	1
+1	12	1	2	0	0	1	0	0	0	1	10	8
+2	19	1	1	1	0	0	1	1	1	0	100	8
+1	19	4	2	1	0	0	0	1	1	0	10	2
+1	16	1	4	1	0	0	0	1	1	0	0	1
+1	26	2	3	1	0	0	1	0	0	0	100	8
+2	16	4	3	0	1	1	0	0	0	1	1	2
+0	7	2	1	1	0	0	1	1	0	0	10	2
+3	9	4	2	0	1	0	0	0	0	1	10	1
+1	17	3	3	1	0	0	1	1	1	0	10	1
+1	23	1	2	0	1	1	0	0	0	1	1	2
+2	14	3	4	1	0	0	1	1	1	0	100	2
+1	7	4	4	1	0	0	1	1	0	0	2	1
+1	13	4	3	0	1	1	0	0	0	1	1	2
+3	23	4	1	0	0	1	0	0	0	1	0	8
+3	7	3	2	0	1	1	0	0	1	1	0	2
+0	17	1	2	1	0	0	1	1	0	0	100	8
+0	10	1	1	0	1	1	0	0	1	0	10	8
+0	12	2	4	1	0	0	1	1	1	0	1	2
+2	12	4	1	1	0	0	1	1	1	0	0	1
+1	18	4	1	1	0	0	1	1	0	0	2	8
+1	22	1	1	0	1	1	0	0	1	1	2	2
+1	21	1	2	0	0	1	0	0	0	1	0	1
+2	11	4	4	1	0	0	1	1	0	0	10	8
+0	15	3	3	0	1	1	0	0	1	1	1	2
+2	23	3	4	1	0	0	0	0	0	0	2	8
+2	17	4	4	0	1	0	0	0	0	1	2	1
+0	13	2	2	1	0	0	1	1	1	0	0	8
+2	13	3	1	0	1	1	0	0	0	1	100	2
+0	9	3	1	1	0	0	1	0	1	0	0	8
+0	20	1	3	0	1	0	0	0	1	1	2	8
+0	11	1	3	1	0	0	0	1	1	0	1	1
+2	8	1	4	1	0	0	1	0	1	0	2	1
+1	20	2	1	1	0	0	1	1	0	0	100	2
+0	22	2	3	0	0	0	0	0	0	1	100	8
+1	13	4	4	1	0	0	0	0	1	0	10	8
+0	16	3	2	0	1	0	0	0	1	1	2	8
+3	22	3	2	0	0	0	0	0	1	1	0	8
+1	8	2	1	0	1	1	0	0	0	1	10	8
+0	19	2	4	0	1	1	0	0	0	1	1	8
+1	11	2	1	1	0	0	1	0	0	0	0	2
+3	15	1	2	1	0	0	0	1	0	0	100	1
+1	17	4	3	0	1	0	0	0	1	1	1	1
+3	24	2	4	0	1	1	0	0	1	1	1	8
+2	24	3	3	1	0	0	1	1	0	0	2	1
+3	8	3	2	1	0	0	1	1	0	0	100	2
+3	21	3	4	0	0	0	0	0	0	0	1	8
+2	26	1	4	1	0	0	1	1	0	0	0	2
+3	14	2	2	0	1	1	0	0	1	1	0	1
+0	8	4	3	0	0	1	0	0	0	1	1	1
+2	9	1	3	1	0	0	1	0	1	0	100	2
+3	12	3	3	0	1	1	0	0	0	1	100	8
+0	7	1	4	1	0	0	1	1	1	0	100	8
+0	10	4	2	0	0	1	0	0	0	1	0	2
+1	24	4	1	0	0	1	0	0	0	1	0	2
+3	16	2	1	0	0	0	0	0	1	1	10	1
+3	18	2	3	0	1	1	0	0	1	1	0	1
+2	16	3	4	0	1	1	0	0	0	1	100	8
+0	11	1	3	0	0	1	0	0	0	1	2	1
+2	14	2	2	0	1	0	0	0	0	1	1	8
+2	12	4	3	1	0	0	1	1	1	0	2	8
+0	8	1	4	0	0	1	0	0	0	1	0	1
+3	25	2	3	1	0	0	1	0	1	0	2	2
+2	15	4	4	1	0	0	1	1	0	0	2	1
+3	20	3	2	1	0	0	1	1	0	0	0	1
+3	23	4	4	0	1	1	0	0	0	1	100	2
+2	25	3	4	1	0	0	0	0	1	0	100	2
+1	25	1	2	1	0	0	0	1	1	0	10	8
+0	24	1	2	0	0	1	0	0	1	1	10	1
+1	15	4	3	1	0	0	1	1	1	0	0	2
+1	24	3	4	0	1	0	0	0	0	1	100	1
+2	20	4	4	0	1	1	0	0	1	0	1	1
+1	22	4	3	1	0	0	0	1	0	0	1	2
+2	18	3	4	0	0	0	0	0	0	0	100	8
+3	19	2	4	0	0	0	0	0	0	1	2	1
+2	18	1	1	1	0	0	0	1	0	0	10	1
+3	16	2	3	1	0	0	1	1	1	0	10	8
+2	20	4	1	0	1	1	0	0	0	1	10	8
 );
   std::istringstream tests(allPairsTests);
   // skip the initial line with the parameter names.

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathicgb.git



More information about the debian-science-commits mailing list