[mathicgb] 356/393: Replaced the interface and implementation of PolyHashTable with the better hash table from BjarkeGeobucket2. That made BjarkeGeobucket2 superfluous, so it was removed.

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 1eab165fc0b4d94a679f5f761d533ec3656e21d1
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Tue Sep 3 15:57:08 2013 +0200

    Replaced the interface and implementation of PolyHashTable with the better hash table from BjarkeGeobucket2. That made BjarkeGeobucket2 superfluous, so it was removed.
---
 Makefile.am                                        |   3 +-
 build/vs12/mathicgb-lib/mathicgb-lib.vcxproj       |   2 -
 .../vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters |   6 -
 src/mathicgb.cpp                                   |   2 +-
 src/mathicgb/BjarkeGeobucket2.cpp                  | 371 ---------------------
 src/mathicgb/BjarkeGeobucket2.hpp                  |  14 -
 src/mathicgb/F4Reducer.cpp                         |   2 +-
 src/mathicgb/MonoMonoid.hpp                        |   2 +-
 src/mathicgb/Poly.hpp                              |  12 +
 src/mathicgb/PolyHashTable.cpp                     | 238 -------------
 src/mathicgb/PolyHashTable.hpp                     | 286 +++++++++++++---
 src/mathicgb/Reducer.cpp                           |  16 +-
 src/mathicgb/Reducer.hpp                           |   2 -
 src/mathicgb/ReducerHash.hpp                       |  69 ++--
 src/mathicgb/ReducerHashPack.hpp                   |  55 +--
 src/test/gb-test.cpp                               | 209 ++++++------
 src/test/pict.in                                   |   2 +-
 17 files changed, 416 insertions(+), 875 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 5b19c25..bf38d98 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,8 +13,7 @@ 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/BjarkeGeobucket2.cpp			  \
-  src/mathicgb/BjarkeGeobucket2.hpp src/mathicgb/ClassicGBAlg.cpp	  \
+libmathicgb_la_SOURCES = 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		  \
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
index 541cb6a..6ed00ae 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
@@ -441,7 +441,6 @@
   <ItemGroup>
     <ClCompile Include="..\..\..\src\mathicgb.cpp" />
     <ClCompile Include="..\..\..\src\mathicgb\Basis.cpp" />
-    <ClCompile Include="..\..\..\src\mathicgb\BjarkeGeobucket2.cpp" />
     <ClCompile Include="..\..\..\src\mathicgb\CFile.cpp" />
     <ClCompile Include="..\..\..\src\mathicgb\ChainedHashTable.cpp" />
     <ClCompile Include="..\..\..\src\mathicgb\ClassicGBAlg.cpp" />
@@ -477,7 +476,6 @@
     <ClInclude Include="..\..\..\src\mathicgb.h" />
     <ClInclude Include="..\..\..\src\mathicgb\Atomic.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\Basis.hpp" />
-    <ClInclude Include="..\..\..\src\mathicgb\BjarkeGeobucket2.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\CFile.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\ChainedHashTable.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\ClassicGBAlg.hpp" />
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
index 4e35a20..4f8f7cd 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
@@ -11,9 +11,6 @@
     </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\..\..\src\mathicgb\BjarkeGeobucket2.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\..\src\mathicgb\ChainedHashTable.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -112,9 +109,6 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\..\src\mathicgb\BjarkeGeobucket2.hpp">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\..\src\mathicgb\ChainedHashTable.hpp">
       <Filter>Header Files</Filter>
     </ClInclude>
diff --git a/src/mathicgb.cpp b/src/mathicgb.cpp
index 406db27..a56a8ea 100755
--- a/src/mathicgb.cpp
+++ b/src/mathicgb.cpp
@@ -884,7 +884,7 @@ namespace mgbi {
     Reducer::ReducerType reducerType;
     switch (conf.reducer()) {
     case GConf::ClassicReducer:
-      reducerType = Reducer::Reducer_BjarkeGeo;
+      reducerType = Reducer::Reducer_Geobucket_Hashed;
       break;
 
     default:
diff --git a/src/mathicgb/BjarkeGeobucket2.cpp b/src/mathicgb/BjarkeGeobucket2.cpp
deleted file mode 100755
index 9bebd1e..0000000
--- a/src/mathicgb/BjarkeGeobucket2.cpp
+++ /dev/null
@@ -1,371 +0,0 @@
-// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
-// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
-#include "stdinc.h"
-#include "BjarkeGeobucket2.hpp"
-
-#include "TypicalReducer.hpp"
-#include "PolyHashTable.hpp"
-#include <mathic.h>
-
-MATHICGB_NAMESPACE_BEGIN
-
-class MonoMap {
-public:
-  typedef PolyRing::Monoid Monoid;
-  typedef Monoid::ConstMonoRef ConstMonoRef;
-  typedef Monoid::MonoRef MonoRef;
-  typedef coefficient Value;
-
-  class Node {
-  public:
-    ConstMonoRef mono() const {return *Monoid::toMonoPtr(mMono);}
-    MonoRef mono() {return *Monoid::toMonoPtr(mMono);}
-
-    Value& value() {return mValue;}
-    const Value& value() const {return mValue;}
-
-  private:
-    friend class MonoMap;
-
-    Node*& next() {return mNext;}
-    Node* next() const {return mNext;}
-
-    Node* mNext;
-    Value mValue;
-    exponent mMono[1];
-  };
-
-  // Construct a hash table with at least requestedBucketCount buckets. There
-  // may be more buckets. Currently the number is rounded up to the next power
-  // of two.
-  MonoMap(
-    const size_t requestedBucketCount,
-    const PolyRing& ring
-  ):
-    mHashToIndexMask(computeHashMask(requestedBucketCount)),
-    mBuckets
-      (make_unique_array<Node*>(hashMaskToBucketCount(mHashToIndexMask))),
-    mRing(ring),
-    mNodes(sizeofNode(ring)
-    ),
-    mSize()
-  {
-    std::fill_n(mBuckets.get(), bucketCount(), nullptr);
-  }
-
-  const PolyRing::Monoid& monoid() const {return mRing.monoid();}
-
-  void rehash(const size_t requestedBucketCount) {
-    const auto newHashToIndexMask = computeHashMask(requestedBucketCount);
-    const auto newBucketCount = hashMaskToBucketCount(newHashToIndexMask);
-    auto newBuckets = make_unique_array<Node*>(newBucketCount);
-    std::fill_n(newBuckets.get(), newBucketCount, nullptr);
-
-    const auto bucketsEnd = mBuckets.get() + bucketCount();
-    for (auto bucket = mBuckets.get(); bucket != bucketsEnd; ++bucket) {
-      for (auto node = *bucket; node != 0;) {
-        const auto hash = monoid().hash(node->mono());
-        const auto newIndex = hashToIndex(hash, newHashToIndexMask);
-        const auto next = node->next();
-        node->next() = newBuckets[newIndex];
-        newBuckets[newIndex] = node;
-        node = next;
-      }
-    }
-
-    mHashToIndexMask = newHashToIndexMask;
-    mBuckets = std::move(newBuckets);
-  }
-
-  /// Return how many buckets the hash table has.
-  size_t bucketCount() const {
-    return hashMaskToBucketCount(mHashToIndexMask);
-  }
-
-  /// Return the number of elements (not the number of buckets).
-  size_t size() const {return mSize;}
-
-  MATHICGB_INLINE
-  std::pair<Node*, bool> insertProduct(ConstMonoRef a, ConstMonoRef b) {
-    auto newNode = new (mNodes.alloc()) Node();
-    monoid().multiply(a, b, newNode->mono());
-    const auto abHash = monoid().hash(newNode->mono());
-    auto& bucket = mBuckets[hashToIndex(abHash)];
-
-    for (auto node = bucket; node != nullptr; node = node->next()) {
-      if (abHash != monoid().hash(node->mono()))
-        continue;
-      if (monoid().equal(newNode->mono(), node->mono())) {
-        mNodes.free(newNode);
-        return std::make_pair(node, false); // found a*b.
-      }
-    }
-
-    mRing.coefficientSet(newNode->value(), 0);
-    newNode->next() = bucket;
-    bucket = newNode;
-    ++mSize;
-    return std::make_pair(newNode, true); // inserted mono
-  }
-
-  MATHICGB_INLINE
-  void remove(Node* nodeToRemove) {
-    MATHICGB_ASSERT(nodeToRemove != 0);
-    MATHICGB_ASSERT(mNodes.fromPool(nodeToRemove));
-    const auto index = hashToIndex(monoid().hash(nodeToRemove->mono()));
-    auto nodePtr = &mBuckets[index];
-    while (*nodePtr != nodeToRemove) {
-      MATHICGB_ASSERT(*nodePtr != nullptr);
-      nodePtr = &(*nodePtr)->next();
-    }
-    *nodePtr = nodeToRemove->next();
-    mNodes.free(nodeToRemove);
-    --mSize;
-  }
-
-  /// Removes all elements and optimizes internal resources. This is
-  /// fast if there are no elements, so if you know that there are no
-  /// elements and that many operations have happened since the last clear,
-  /// then call clear for better cache performance. If there is even one
-  /// element, then this takes linear time in the number of buckets.
-  void clear() {
-    if (!empty()) {
-      std::fill_n(mBuckets.get(), bucketCount(), nullptr);
-      mSize = 0;
-    }
-    mNodes.freeAllBuffers();
-  }
-
-  bool empty() const {return mSize == 0;}
-
-private:
-  static HashValue computeHashMask(const size_t requestedBucketCount) {
-    // round request up to nearest power of 2.
-    size_t pow2 = 1;
-    while (pow2 < requestedBucketCount && 2 * pow2 != 0)
-      pow2 *= 2;
-    MATHICGB_ASSERT(pow2 > 0 && (pow2 & (pow2 - 1)) == 0); // power of two
-
-    // If casting to a hash value overflows, then we get the maximum
-    // possible number of buckets based on the range of the hash
-    // value type. Only unsigned overflow is defined, so we need
-    // to assert that the hash type is unsigned.
-    static_assert(!std::numeric_limits<HashValue>::is_signed, "");
-    const auto hashToIndexMask = static_cast<HashValue>(pow2 - 1);
-    MATHICGB_ASSERT(pow2 == hashMaskToBucketCount(hashToIndexMask));
-    return hashToIndexMask;
-  }
-
-  static size_t hashMaskToBucketCount(const HashValue mask) {
-    const auto count = static_cast<size_t>(mask) + 1u; // should be power of 2
-    MATHICGB_ASSERT(count > 0 && (count & (count - 1)) == 0); 
-    return count;
-  }
-
-  static size_t sizeofNode(const PolyRing& ring) {
-    return
-      sizeof(Node) +
-      sizeof(Value) -
-      sizeof(exponent) +
-      ring.maxMonomialByteSize();
-  }
-
-  size_t hashToIndex(const HashValue hash) const {
-    const auto index = hashToIndex(hash, mHashToIndexMask);
-    MATHICGB_ASSERT(index == hash % bucketCount());
-    return index;
-  }
-
-  static size_t hashToIndex(const HashValue hash, const HashValue mask) {
-    return hash & mask;
-  }
-
-  HashValue mHashToIndexMask;
-  std::unique_ptr<Node*[]> mBuckets;
-  const PolyRing& mRing;
-  memt::BufferPool mNodes;
-  size_t mSize;
-};
-
-
-class BjarkeGeobucket2 : public TypicalReducer {
-public:
-  BjarkeGeobucket2(const PolyRing& ring):
-    mRing(ring),
-    mMap(10000, ring),
-    mQueue2(QueueConfiguration2(ring.monoid()))
-  {}
-
-  virtual std::string description() const {return "bjarke geo buckets";}
-
-  void insertTail(const_term multiplier, const Poly *g1) {
-    MATHICGB_ASSERT(g1 != 0);
-    MATHICGB_ASSERT(g1->termsAreInDescendingOrder());
-
-    if (g1->nTerms() <= 1)
-      return;
-
-    mNodesTmp.clear();
-    auto it = g1->begin();
-    const auto end = g1->end();
-    for (++it; it != end; ++it) {
-      coefficient prod;
-      mRing.coefficientMult(it.getCoefficient(), multiplier.coeff, prod);
-      auto p = mMap.insertProduct(it.getMonomial(), multiplier.monom);
-      mRing.coefficientAddTo(p.first->value(), prod);
-      if (p.second)
-        mNodesTmp.emplace_back(p.first);
-    }
-    if (!mNodesTmp.empty())
-      mQueue2.push(mNodesTmp.begin(), mNodesTmp.end());
-  }
-
-  void insert(monomial multiplier, const Poly *g1) {
-    MATHICGB_ASSERT(g1 != 0);
-    MATHICGB_ASSERT(g1->termsAreInDescendingOrder());
-
-    mNodesTmp.clear();
-    const auto end = g1->end();
-    for (auto it = g1->begin(); it != end; ++it) {
-      auto p = mMap.insertProduct(it.getMonomial(), multiplier);
-      mRing.coefficientAddTo(p.first->value(), it.getCoefficient());
-      if (p.second)
-        mNodesTmp.emplace_back(p.first);
-    }
-    if (!mNodesTmp.empty())
-      mQueue2.push(mNodesTmp.begin(), mNodesTmp.end());
-  }
-
-  virtual bool leadTerm(const_term& result) {
-    while (!mQueue2.empty()) {
-      const auto node = mQueue2.top();
-      if (node->value() != 0) {
-        result.coeff = node->value();
-        result.monom = Monoid::toOld(node->mono());
-        return true;
-      }
-      mQueue2.pop();
-      mMap.remove(node);
-    }
-    return false;
-  }
-
-  virtual void removeLeadTerm() {
-    MATHICGB_ASSERT(!mQueue2.empty());
-    const auto node = mQueue2.top();
-    mQueue2.pop();
-    mMap.remove(node);
-  }
-
-  virtual size_t getMemoryUse() const {
-    size_t result = TypicalReducer::getMemoryUse();
-    //result += mMap.getMemoryUse();
-    return result;
-  }
-
-
-protected:
-  void resetReducer() {
-    const_term t;
-    while (!mQueue2.empty()) {
-      const auto node = mQueue2.top();
-      mQueue2.pop();
-      mMap.remove(node);
-    }
-    MATHICGB_ASSERT(mMap.empty());
-    MATHICGB_ASSERT(mQueue2.empty());
-    mMap.clear();
-  }
-
-private:
-  class QueueConfiguration {
-  public:
-    typedef PolyRing::Monoid Monoid;
-
-    QueueConfiguration(const Monoid& monoid):
-      mMonoid(monoid), geoBase(4), minBucketSize(1) {}
-
-    typedef PolyHashTable::node* Entry;
-
-    typedef bool CompareResult;
-    CompareResult compare(const Entry& a, const Entry& b) const {
-      return mMonoid.lessThan(a->mono(), b->mono());
-    }
-    bool cmpLessThan(CompareResult r) const {return r;}
-
-    static const bool supportDeduplication = false;
-    bool cmpEqual(CompareResult r) const {
-      MATHICGB_ASSERT(false); // Not supposed to be used.
-      return false;
-    }
-    Entry deduplicate(const Entry& a, const Entry& /* b */) const {
-      MATHICGB_ASSERT(false); // Not supposed to be used.
-      return a;
-    }
-
-    static const bool minBucketBinarySearch = true;
-    static const bool trackFront = true;
-    static const bool premerge = false;
-    static const bool collectMax = false;
-    static const mic::GeobucketBucketStorage bucketStorage =
-      static_cast<mic::GeobucketBucketStorage>(1);
-    static const size_t insertFactor = 1;
-
-    const size_t geoBase;
-    const size_t minBucketSize;
-
-  private:
-    const Monoid& mMonoid;
-  };
-
-  class QueueConfiguration2 {
-  public:
-    typedef PolyRing::Monoid Monoid;
-
-    QueueConfiguration2(const Monoid& monoid):
-      mMonoid(monoid), geoBase(4), minBucketSize(1) {}
-
-    typedef MonoMap::Node* Entry;
-
-    typedef bool CompareResult;
-    CompareResult compare(const Entry& a, const Entry& b) const {
-      return mMonoid.lessThan(a->mono(), b->mono());
-    }
-    bool cmpLessThan(CompareResult r) const {return r;}
-
-    static const bool supportDeduplication = false;
-    bool cmpEqual(CompareResult r) const {
-      MATHICGB_ASSERT(false); // Not supposed to be used.
-      return false;
-    }
-    Entry deduplicate(const Entry& a, const Entry& /* b */) const {
-      MATHICGB_ASSERT(false); // Not supposed to be used.
-      return a;
-    }
-
-    static const bool minBucketBinarySearch = true;
-    static const bool trackFront = true;
-    static const bool premerge = false;
-    static const bool collectMax = false;
-    static const mic::GeobucketBucketStorage bucketStorage =
-      static_cast<mic::GeobucketBucketStorage>(1);
-    static const size_t insertFactor = 1;
-
-    const size_t geoBase;
-    const size_t minBucketSize;
-
-  private:
-    const Monoid& mMonoid;
-  };
-
-  mutable std::vector<MonoMap::Node*> mNodesTmp;
-  const PolyRing& mRing;
-  MonoMap mMap;
-  mic::Geobucket<QueueConfiguration2> mQueue2;
-};
-
-std::unique_ptr<TypicalReducer> makeBjarkeGeobucket2(const PolyRing& ring) {
-  return make_unique<BjarkeGeobucket2>(ring);
-}
-
-MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/BjarkeGeobucket2.hpp b/src/mathicgb/BjarkeGeobucket2.hpp
deleted file mode 100755
index eaffe5c..0000000
--- a/src/mathicgb/BjarkeGeobucket2.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// 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_BJARKE_GEOBUCKET2_GUARD
-#define MATHICGB_BJARKE_GEOBUCKET2_GUARD
-
-MATHICGB_NAMESPACE_BEGIN
-
-class TypicalReducer;
-class PolyRing;
-
-std::unique_ptr<TypicalReducer> makeBjarkeGeobucket2(const PolyRing& ring);
-
-MATHICGB_NAMESPACE_END
-#endif
diff --git a/src/mathicgb/F4Reducer.cpp b/src/mathicgb/F4Reducer.cpp
index 023b914..360b74d 100755
--- a/src/mathicgb/F4Reducer.cpp
+++ b/src/mathicgb/F4Reducer.cpp
@@ -47,7 +47,7 @@ MATHICGB_NAMESPACE_BEGIN
 
 F4Reducer::F4Reducer(const PolyRing& ring, Type type):
   mType(type),
-  mFallback(Reducer::makeReducer(Reducer::Reducer_BjarkeGeo, ring)),
+  mFallback(Reducer::makeReducer(Reducer::Reducer_Geobucket_Hashed, ring)),
   mRing(ring),
   mMemoryQuantum(0),
   mStoreToFile(""),
diff --git a/src/mathicgb/MonoMonoid.hpp b/src/mathicgb/MonoMonoid.hpp
index c2aa125..def8cb3 100755
--- a/src/mathicgb/MonoMonoid.hpp
+++ b/src/mathicgb/MonoMonoid.hpp
@@ -1561,7 +1561,7 @@ private:
   friend class MonoVector;
   friend class MonoPool;
 
-  friend class MonoMap;
+  friend class PolyHashTable;
 
   typedef typename Base::Gradings Gradings;
 
diff --git a/src/mathicgb/Poly.hpp b/src/mathicgb/Poly.hpp
index 81ca69c..45ee1af 100755
--- a/src/mathicgb/Poly.hpp
+++ b/src/mathicgb/Poly.hpp
@@ -48,6 +48,12 @@ public:
     reference operator*() const {
       return std::pair<coefficient&, monomial>(getCoefficient(), getMonomial());
     }
+    const_term term() const {
+      const_term t;
+      t.monom = getMonomial();
+      t.coeff = getCoefficient();
+      return t;
+    }
   };
 
   class const_iterator {
@@ -77,6 +83,12 @@ public:
       return std::pair<coefficient, const_monomial>
         (getCoefficient(), getMonomial());
     }
+    const_term term() const {
+      const_term t;
+      t.monom = getMonomial();
+      t.coeff = getCoefficient();
+      return t;
+    }
   };
 
   void sortTermsDescending();
diff --git a/src/mathicgb/PolyHashTable.cpp b/src/mathicgb/PolyHashTable.cpp
index d111b19..563cd0e 100755
--- a/src/mathicgb/PolyHashTable.cpp
+++ b/src/mathicgb/PolyHashTable.cpp
@@ -9,244 +9,6 @@
 
 MATHICGB_NAMESPACE_BEGIN
 
-PolyHashTable::PolyHashTable(const PolyRing *R, int nbits)
-  : mRing(*R),
-    mHashMask((static_cast<size_t>(1) << nbits)-1),
-    mTableSize(static_cast<size_t>(1) << nbits),
-    mLogTableSize(nbits),
-    mNodeCount(0),
-    mBinCount(0),
-    mMaxCountBeforeRebuild(0)
-{
-  mHashTable.resize(mTableSize);
 
-  mMonomialSize = R->maxMonomialSize() * sizeof(exponent);
-  // set each entry of mHashTable to null
-
-  reset();
-}
-
-void PolyHashTable::reset()
-{
-  // The following no longer needs to be done
-
-  // Clear the table, and memory areas.
-
-#if 0
-  MATHICGB_ASSERT(mNodeCount != 0);
-  for (size_t count = 0; count < mTableSize; ++count)
-    {
-      if ( mHashTable[count] != 0)
-        std::cerr << "error: hash table is not zero on reset" << std::endl;
-    }
-#endif
-
-  mArena.freeAllAllocs();
-
-  mBinCount = 0;
-  mNodeCount = 0;
-}
-
-void PolyHashTable::resize(size_t new_nbits)
-// Don't change the nodes, table, but do recreate mHashTable
-{
-  // Make a new vector of node *'s.
-  // swap the two.
-  // Loop through each one, reinserting the node into the proper bin.
-
-  //  std::cout << "resizing PolyHashTable to " << new_nbits << " bits" << " count=" << mNodeCount << std::endl;
-  size_t const old_table_size = mTableSize;
-  mTableSize = static_cast<size_t>(1) << new_nbits;
-  mLogTableSize = new_nbits;
-  mHashMask = mTableSize-1;
-  MonomialArray old_table(mTableSize);
-
-  std::swap(old_table, mHashTable);
-  mBinCount = 0;
   
-  for (size_t i = 0; i < old_table_size; ++i)
-    {
-      node *p = old_table[i];
-      while (p != 0)
-        {
-          node *q = p;
-          p = p->next();
-          q->next() = 0;
-          // Reinsert node.  We know that it is unique
-          const_monomial m = q->monom;
-          size_t hashval = mRing.monomialHashValue(m) & mHashMask;
-          node *r = mHashTable[hashval];
-          if (r == 0) 
-            {
-              mBinCount++;
-              q->next() = r;
-              mHashTable[hashval] = q;
-            }
-          else
-            {
-              // put it at the end
-              for ( ; r->next() != 0; r = r->next()) { }
-              r->next() = q;
-            }
-        }
-    }
-
-  // todo: consider if this can overflow or something else nasty might happen
-  const double threshold = 0.1;
-  mMaxCountBeforeRebuild =
-    static_cast<size_t>(std::floor(mTableSize * threshold));
-}
-
-PolyHashTable::node * PolyHashTable::makeNode(coefficient coeff, const_monomial monom)
-{
-  mNodeCount++;
-  node *q = static_cast<node *>(mArena.allocObjectNoCon<node>());
-  q->next() = 0;
-  q->monom = monom; 
-  mRing.coefficientSet(q->coeff, coeff);
-  return q;
-}
-
-bool PolyHashTable::lookup_and_insert(const_monomial m, coefficient val, node *& result)
-// Returns true if m is in the table, else inserts m into the hash table (as is, without copying it)
-{
-  size_t fullHashVal = mRing.monomialHashValue(m);
-  size_t hashval = fullHashVal & mHashMask;
-
-  MATHICGB_ASSERT(hashval < mHashTable.size());
-  node *tmpNode = mHashTable[hashval];
-  if (tmpNode == 0) {
-    result = makeNode(val, m);
-    mHashTable[hashval] = result;
-  } else {
-    while (true) {
-      if (mRing.monomialHashValue(tmpNode->monom) == fullHashVal && mRing.monomialEQ(m, tmpNode->monom)) {
-        mRing.coefficientAddTo(tmpNode->coeff, val);
-        result = tmpNode;
-        return true;
-      }
-      if (tmpNode->next() == 0) {
-        result = makeNode(val, m);
-        tmpNode->next() = result;
-        break;
-      }
-      tmpNode = tmpNode->next();
-    }
-  }
-
-  if (mNodeCount > mMaxCountBeforeRebuild)
-    resize(mLogTableSize + 2);  // increase by a factor of 4??
-
-  return false;
-}
-
-void PolyHashTable::insert(
-  Poly::const_iterator first, 
-  Poly::const_iterator last,
-  MonomialArray &result
-) {
-  for (auto i = first; i != last; ++i) {
-    monomial monomspace = mRing.allocMonomial(mArena);
-    node* p;
-    mRing.monomialCopy(i.getMonomial(), monomspace);
-    bool found = lookup_and_insert(monomspace, i.getCoefficient(), p);
-    if (found)
-      mRing.freeTopMonomial(mArena,monomspace);
-    else
-      result.push_back(p);
-  }
-}
-
-void PolyHashTable::insert(
-  const_term multiplier, 
-  Poly::const_iterator first, 
-  Poly::const_iterator last,
-  MonomialArray &result
-) {
-  for (auto i = first; i != last; ++i) {
-    monomial monomspace = mRing.allocMonomial(mArena);
-    coefficient c;
-    mRing.coefficientSet(c, multiplier.coeff);
-    node* p;
-    mRing.monomialMult(multiplier.monom, i.getMonomial(), monomspace);
-    mRing.coefficientMultTo(c, i.getCoefficient());
-    bool found = lookup_and_insert(monomspace, c, p);
-    if (found)
-      mRing.freeTopMonomial(mArena,monomspace);
-    else
-      result.push_back(p);
-  }
-}
-
-void PolyHashTable::insert(
-  const_monomial multiplier, 
-  Poly::const_iterator first, 
-  Poly::const_iterator last,
-  MonomialArray& result
-) {
-  for (Poly::const_iterator i = first; i != last; ++i) {
-    monomial monomspace = mRing.allocMonomial(mArena);
-    node* p;
-    mRing.monomialMult(multiplier, i.getMonomial(), monomspace);
-    bool found = lookup_and_insert(monomspace, i.getCoefficient(), p);
-    if (found)
-      mRing.freeTopMonomial(mArena,monomspace);
-    else
-      result.push_back(p);
-  }
-}
-
-std::pair<bool, PolyHashTable::node*>
-PolyHashTable::insert(const_term termToInsert) {
-  node* n;
-  bool alreadyInThere = lookup_and_insert
-    (termToInsert.monom, termToInsert.coeff, n);
-  return std::make_pair(!alreadyInThere, n);
-}
-
-void PolyHashTable::unlink(node* p)
-{
-  mNodeCount--;
-  size_t const hashval = mRing.monomialHashValue(p->monom) & mHashMask;
-
-  node head;
-  node* tmpNode = mHashTable[hashval];
-  head.next() = tmpNode;
-  for (node* q = &head; q->next() != 0; q = q->next()) {
-    if (q->next() == p) {
-      q->next() = p->next();
-      mHashTable[hashval] = head.next();
-      return;
-    }
-  }
-  // If we get here, then the node is not at its supposed hash value.
-  // That probably means either that the node has been deleted twice
-  // or that the value in the node changed so that its hash value
-  // changed. That is not allowed.
-  MATHICGB_ASSERT(false);
-}
-
-void PolyHashTable::remove(node* n) {
-  unlink(n);
-}
-
-bool PolyHashTable::popTerm(node *p, coefficient &result_coeff, const_monomial &result_monom)
-{
-  unlink(p);
-  if (!mRing.coefficientIsZero(p->coeff))
-    {
-      result_coeff = p->coeff;
-      result_monom = p->monom;
-      return true;
-    }
-  return false;
-}
-
-size_t PolyHashTable::getMemoryUse() const
-{
-  size_t result = mHashTable.capacity() * sizeof(node *);
-  result += mArena.getMemoryUse();
-  return result;
-}
-
 MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/PolyHashTable.hpp b/src/mathicgb/PolyHashTable.hpp
index 9c4127f..5040ed0 100755
--- a/src/mathicgb/PolyHashTable.hpp
+++ b/src/mathicgb/PolyHashTable.hpp
@@ -11,6 +11,211 @@
 
 MATHICGB_NAMESPACE_BEGIN
 
+class PolyHashTable {
+public:
+  typedef PolyRing::Monoid Monoid;
+  typedef Monoid::ConstMonoRef ConstMonoRef;
+  typedef Monoid::MonoRef MonoRef;
+  typedef coefficient Value;
+
+  class Node {
+  public:
+    ConstMonoRef mono() const {return *Monoid::toMonoPtr(mMono);}
+    MonoRef mono() {return *Monoid::toMonoPtr(mMono);}
+
+    Value& value() {return mValue;}
+    const Value& value() const {return mValue;}
+
+  private:
+    friend class PolyHashTable;
+
+    Node*& next() {return mNext;}
+    Node* next() const {return mNext;}
+
+    Node* mNext;
+    Value mValue;
+    exponent mMono[1];
+  };
+
+  // Construct a hash table with at least requestedBucketCount buckets. There
+  // may be more buckets. Currently the number is rounded up to the next power
+  // of two.
+  PolyHashTable(const PolyRing& ring):
+    mHashToIndexMask(computeHashMask(1000)),
+    mBuckets
+      (make_unique_array<Node*>(hashMaskToBucketCount(mHashToIndexMask))),
+    mRing(ring),
+    mNodes(sizeofNode(ring)
+    ),
+    mSize()
+  {
+    mMaxSize = static_cast<size_t>(bucketCount() * maxLoadFactor());
+    std::fill_n(mBuckets.get(), bucketCount(), nullptr);
+  }
+
+  const PolyRing::Monoid& monoid() const {return mRing.monoid();}
+
+  /// Return how many buckets the hash table has.
+  size_t bucketCount() const {
+    return hashMaskToBucketCount(mHashToIndexMask);
+  }
+
+  /// Return the number of elements (not the number of buckets).
+  size_t size() const {return mSize;}
+
+  MATHICGB_INLINE
+  std::pair<Node*, bool> insertProduct(ConstMonoRef a, ConstMonoRef b) {
+    auto newNode = new (mNodes.alloc()) Node();
+    monoid().multiply(a, b, newNode->mono());
+    const auto abHash = monoid().hash(newNode->mono());
+    auto& bucket = mBuckets[hashToIndex(abHash)];
+
+    for (auto node = bucket; node != nullptr; node = node->next()) {
+      if (abHash != monoid().hash(node->mono()))
+        continue;
+      if (monoid().equal(newNode->mono(), node->mono())) {
+        mNodes.free(newNode);
+        return std::make_pair(node, false); // found a*b.
+      }
+    }
+
+    mRing.coefficientSet(newNode->value(), 0);
+    newNode->next() = bucket;
+    bucket = newNode;
+    ++mSize;
+    if (mSize >= mMaxSize)
+      rehash(bucketCount() * 2);
+    return std::make_pair(newNode, true); // inserted mono
+  }
+
+  MATHICGB_INLINE
+  std::pair<Node*, bool> insertProduct
+    (ConstMonoRef a, ConstMonoRef b, Value add)
+  {
+    auto p = insertProduct(a, b);
+    mRing.coefficientAddTo(p.first->value(), add);
+    return p;
+  }
+
+  MATHICGB_INLINE
+  std::pair<Node*, bool> insertProduct(const_term a, const_term b)
+  {
+    Value prod;
+    mRing.coefficientMult(a.coeff, b.coeff, prod);
+    return insertProduct(a.monom, b.monom, prod);
+  }
+
+  MATHICGB_INLINE
+  void remove(Node* nodeToRemove) {
+    MATHICGB_ASSERT(nodeToRemove != 0);
+    MATHICGB_ASSERT(mNodes.fromPool(nodeToRemove));
+    const auto index = hashToIndex(monoid().hash(nodeToRemove->mono()));
+    auto nodePtr = &mBuckets[index];
+    while (*nodePtr != nodeToRemove) {
+      MATHICGB_ASSERT(*nodePtr != nullptr);
+      nodePtr = &(*nodePtr)->next();
+    }
+    *nodePtr = nodeToRemove->next();
+    mNodes.free(nodeToRemove);
+    --mSize;
+  }
+
+  /// Removes all elements and optimizes internal resources. This is
+  /// fast if there are no elements, so if you know that there are no
+  /// elements and that many operations have happened since the last clear,
+  /// then call clear for better cache performance. If there is even one
+  /// element, then this takes linear time in the number of buckets.
+  void clear() {
+    if (!empty()) {
+      std::fill_n(mBuckets.get(), bucketCount(), nullptr);
+      mSize = 0;
+    }
+    mNodes.freeAllBuffers();
+  }
+
+  bool empty() const {return mSize == 0;}
+
+  size_t getMemoryUse() const {
+    return bucketCount() * sizeof(mBuckets[0]) + mNodes.getMemoryUse();
+  }
+
+private:
+  void rehash(const size_t requestedBucketCount) {
+    const auto newHashToIndexMask = computeHashMask(requestedBucketCount);
+    const auto newBucketCount = hashMaskToBucketCount(newHashToIndexMask);
+    auto newBuckets = make_unique_array<Node*>(newBucketCount);
+    std::fill_n(newBuckets.get(), newBucketCount, nullptr);
+
+    const auto bucketsEnd = mBuckets.get() + bucketCount();
+    for (auto bucket = mBuckets.get(); bucket != bucketsEnd; ++bucket) {
+      for (auto node = *bucket; node != 0;) {
+        const auto hash = monoid().hash(node->mono());
+        const auto newIndex = hashToIndex(hash, newHashToIndexMask);
+        const auto next = node->next();
+        node->next() = newBuckets[newIndex];
+        newBuckets[newIndex] = node;
+        node = next;
+      }
+    }
+
+    mHashToIndexMask = newHashToIndexMask;
+    mBuckets = std::move(newBuckets);
+    mMaxSize = static_cast<size_t>(bucketCount() * maxLoadFactor());
+  }
+
+  static HashValue computeHashMask(const size_t requestedBucketCount) {
+    // round request up to nearest power of 2.
+    size_t pow2 = 1;
+    while (pow2 < requestedBucketCount && 2 * pow2 != 0)
+      pow2 *= 2;
+    MATHICGB_ASSERT(pow2 > 0 && (pow2 & (pow2 - 1)) == 0); // power of two
+
+    // If casting to a hash value overflows, then we get the maximum
+    // possible number of buckets based on the range of the hash
+    // value type. Only unsigned overflow is defined, so we need
+    // to assert that the hash type is unsigned.
+    static_assert(!std::numeric_limits<HashValue>::is_signed, "");
+    const auto hashToIndexMask = static_cast<HashValue>(pow2 - 1);
+    MATHICGB_ASSERT(pow2 == hashMaskToBucketCount(hashToIndexMask));
+    return hashToIndexMask;
+  }
+
+  static size_t hashMaskToBucketCount(const HashValue mask) {
+    const auto count = static_cast<size_t>(mask) + 1u; // should be power of 2
+    MATHICGB_ASSERT(count > 0 && (count & (count - 1)) == 0); 
+    return count;
+  }
+
+  static size_t sizeofNode(const PolyRing& ring) {
+    return
+      sizeof(Node) +
+      sizeof(Value) -
+      sizeof(exponent) +
+      ring.maxMonomialByteSize();
+  }
+
+  /// The maximum allowed value of elementCount() / bucketCount().
+  static double maxLoadFactor() {return 0.10;}
+
+  size_t hashToIndex(const HashValue hash) const {
+    const auto index = hashToIndex(hash, mHashToIndexMask);
+    MATHICGB_ASSERT(index == hash % bucketCount());
+    return index;
+  }
+
+  static size_t hashToIndex(const HashValue hash, const HashValue mask) {
+    return hash & mask;
+  }
+
+  HashValue mHashToIndexMask;
+  std::unique_ptr<Node*[]> mBuckets;
+  const PolyRing& mRing;
+  memt::BufferPool mNodes;
+  size_t mSize;
+  size_t mMaxSize;
+};
+
+/*
 // The hash table is a map:  monomial => coeff
 // Operations required on monomials:
 //  hash (this will currently pick out one entry of a monomial)
@@ -31,9 +236,8 @@ public:
 
   class Node {
   public:
-
-    const_monomial& mono() {return monom;}
-    const const_monomial& mono() const {return monom;}
+    const const_monomial& mono() {return mMonom;}
+    const const_monomial& mono() const {return mMonom;}
 
     Value& value() {return coeff;}
     const Value& value() const {return coeff;}
@@ -46,61 +250,51 @@ public:
 
     Node* mNext;
     coefficient coeff;
-    const_monomial monom;
+    const_monomial mMonom;
   };
-  typedef Node node; // todo: remove
-
-  typedef std::vector<node*> MonomialArray;
 
-  PolyHashTable(const PolyRing *R, int nbits);
+  PolyHashTable(const PolyRing& ring);
 
-  std::string description() const {return "polynomial hash table";}
 
-  void reset();  // Clear the table, and memory areas.
+  const Monoid& monoid() const {return mRing.monoid();}
 
-  void resize(size_t new_nbits);  // Don't change the nodes, table, but do recreate hashtable_
+  std::pair<Node*, bool> insertProduct
+    (ConstMonoRef a, ConstMonoRef b);
 
-  size_t getMemoryUse() const;
+  std::pair<Node*, bool> insertProduct
+    (ConstMonoRef a, ConstMonoRef b, Value add)
+  {
+    auto p = insertProduct(a, b);
+    mRing.coefficientAddTo(p.first->value(), add);
+    return p;
+  }
 
-  //@ insert multiplier * g: any monomials already in the hash table are removed,
-  // but their field coefficients in the table are modified accordingly.
-  // Resulting pointers to 'node's are placed, in order, into result.
-  void insert(Poly::const_iterator first, 
-              Poly::const_iterator last,
-              MonomialArray &result);
-  void insert(const_term multiplier, 
-              Poly::const_iterator first, 
-              Poly::const_iterator last,
-              MonomialArray &result);
-  void insert(const_monomial multiplier, 
-              Poly::const_iterator first, 
-              Poly::const_iterator last,
-              MonomialArray &result);
-
-  // Inserts t into the hashtable. Returns true if there is not already
-  // a node with the monomial t.monom. If there is already such a node,
-  // then t.coeff is added to the coefficient of that node. In either case,
-  // node will point to the node for t.monom. The original value of
-  // nodeOut is not used.
-  std::pair<bool, node*> insert(const_term termToInsert);
+  std::pair<Node*, bool> insertProduct(const_term a, const_term b)
+  {
+    Value prod;
+    mRing.coefficientMult(a.coeff, b.coeff, prod);
+    return insertProduct(a.monom, b.monom, prod);
+  }
 
   // Removes the node from the hash table.
-  void remove(node* n);
+  void remove(Node* n);
+
+  void clear();  // Clear the table, and memory areas.
 
-  // deprecated: use remove instead
-  // popTerm removes 'p' from the hash table, setting result_coeff and result_monom if the coefficient is not zero.
-  // result_monom is set with a pointer into monomial space in this class, so will only
-  // be valid until a 'reset' is called.
-  bool popTerm(node *p, coefficient &result_coeff, const_monomial &result_monom);
+  bool empty() const {return mNodeCount == 0;}
 
-protected:
-  node * makeNode(coefficient coeff, const_monomial monom);
-  void unlink(node *p);
-  bool lookup_and_insert(const_monomial m, coefficient val, node *&result);
+  size_t getMemoryUse() const;
+
+private:
+  typedef std::vector<Node*> MonomialArray;
+  void resize(size_t new_nbits);  // Don't change the nodes, table, but do recreate hashtable_
+
+  Node* makeNode(const_monomial monom);
+  bool lookup_and_insert(const_monomial m, Node *&result);
 
   const PolyRing& mRing;
-  std::vector<node*> mHashTable;
-  size_t mHashMask; // this is the number, in binary:  00001111...1, where
+  std::vector<Node*> mHashTable;
+  HashValue mHashMask; // this is the number, in binary:  00001111...1, where
                     // the number of 1's is mLogTableSize
 
   memt::Arena mArena; // space for monomials represented in this class.  Also nodes??
@@ -114,6 +308,6 @@ protected:
 
   size_t mMonomialSize;
 };
-
+*/
 MATHICGB_NAMESPACE_END
 #endif
diff --git a/src/mathicgb/Reducer.cpp b/src/mathicgb/Reducer.cpp
index f0af4ef..0459942 100755
--- a/src/mathicgb/Reducer.cpp
+++ b/src/mathicgb/Reducer.cpp
@@ -3,7 +3,6 @@
 #include "stdinc.h"
 #include "Reducer.hpp"
 
-#include "BjarkeGeobucket2.hpp"
 #include "ReducerPack.hpp"
 #include "ReducerPackDedup.hpp"
 #include "ReducerNoDedup.hpp"
@@ -45,9 +44,6 @@ std::unique_ptr<Reducer> Reducer::makeReducerNullOnUnknown(
   PolyRing const& ring
 ) {
   switch (type) {
-  case Reducer_BjarkeGeo:
-    return makeBjarkeGeobucket2(ring);
-
   case Reducer_TourTree_NoDedup:
     return std::unique_ptr<Reducer>(new ReducerNoDedup<mic::TourTree>(ring));
   case Reducer_TourTree_Dedup:
@@ -101,8 +97,6 @@ std::unique_ptr<Reducer> Reducer::makeReducerNullOnUnknown(
 Reducer::ReducerType Reducer::reducerType(int typ)
 {
   switch (typ) {
-  case 4: return Reducer_BjarkeGeo;
-
   case 7: return Reducer_TourTree_NoDedup;
   case 8: return Reducer_TourTree_Dedup;
   case 9: return Reducer_TourTree_Hashed;
@@ -127,21 +121,13 @@ Reducer::ReducerType Reducer::reducerType(int typ)
   case 25: return Reducer_F4_Old;
   case 26: return Reducer_F4_New;
 
-  default: return Reducer_BjarkeGeo;
+  default: return Reducer_Geobucket_Hashed;
   }
 }
 
 void Reducer::displayReducerTypes(std::ostream &o)
 {
   o << "Reducer types:" << std::endl;
-  o << "   0   PolyHeap" << std::endl;
-  o << "   1   PolyGeoBucket" << std::endl;
-  o << "   2   Poly" << std::endl;
-  o << "   3   PolyHash" << std::endl;
-  o << "   4   BjarkeGeo2" << std::endl;
-  o << "   5   Tournament tree" << std::endl;
-  o << "   6   Hashed Tournament tree" << std::endl;
-
   o << "   7   TournamentTree.NoDedup" << std::endl;
   o << "   8   TournamentTree.Dedup" << std::endl;
   o << "   9   TournamentTree.Hashed" << std::endl;
diff --git a/src/mathicgb/Reducer.hpp b/src/mathicgb/Reducer.hpp
index ca3efb7..f2878be 100755
--- a/src/mathicgb/Reducer.hpp
+++ b/src/mathicgb/Reducer.hpp
@@ -78,8 +78,6 @@ public:
   // ***** Kinds of reducers and creating a Reducer 
 
   enum ReducerType {
-    Reducer_BjarkeGeo = 4, // uses hash table on front to remove duplicates
-
     Reducer_TourTree_NoDedup = 7,
     Reducer_TourTree_Dedup,
     Reducer_TourTree_Hashed,
diff --git a/src/mathicgb/ReducerHash.hpp b/src/mathicgb/ReducerHash.hpp
index 0568535..1244ead 100755
--- a/src/mathicgb/ReducerHash.hpp
+++ b/src/mathicgb/ReducerHash.hpp
@@ -36,16 +36,17 @@ protected:
 public:
   class Configuration : public ReducerHelper::PlainConfiguration {
   public:
-    typedef PolyHashTable::node * Entry;
+    typedef PolyHashTable::Node* Entry;
 
     Configuration(const PolyRing& ring): PlainConfiguration(ring) {}
 
     CompareResult compare(const Entry& a, const Entry& b) const {
-      return ring().monomialLT(a->mono(), b->mono());
+      return ring().monoid().lessThan(a->mono(), b->mono());
     }
   };
   
 private:
+  mutable std::vector<PolyHashTable::Node*> mNodesTmp;
   const PolyRing &mRing;
   PolyHashTable mHashTable;
   Queue<Configuration> mQueue;
@@ -54,7 +55,7 @@ private:
 template<template<typename> class Q>
 ReducerHash<Q>::ReducerHash(const PolyRing &ring):
   mRing(ring),
-  mHashTable(&ring,10),
+  mHashTable(ring),
   mQueue(Configuration(ring))
 {}
 
@@ -67,33 +68,46 @@ void ReducerHash<Q>::insertTail(const_term multiplier, const Poly *g1)
 {
   if (g1->nTerms() <= 1) return;
 
-  PolyHashTable::MonomialArray M;
-  mHashTable.insert(multiplier, ++(g1->begin()), g1->end(), M);
-  if (!M.empty())
-    mQueue.push(M.begin(),M.end());
+  mNodesTmp.clear();
+  auto it = g1->begin();
+  const auto end = g1->end();
+  for (++it; it != end; ++it) {
+    auto p = mHashTable.insertProduct(it.term(), multiplier);
+    if (p.second)
+      mNodesTmp.emplace_back(p.first);
+  }
+  if (!mNodesTmp.empty())
+    mQueue.push(mNodesTmp.begin(), mNodesTmp.end());
 }
 
 template<template<typename> class Q>
 void ReducerHash<Q>::insert(monomial multiplier, const Poly *g1)
 {
-  PolyHashTable::MonomialArray M;
-
-  mHashTable.insert(multiplier, g1->begin(), g1->end(), M);
-
-  if (!M.empty())
-    mQueue.push(M.begin(),M.end());
+  mNodesTmp.clear();
+  const auto end = g1->end();
+  for (auto it = g1->begin(); it != end; ++it) {
+    auto p = mHashTable.insertProduct
+      (it.getMonomial(), multiplier, it.getCoefficient());
+    if (p.second)
+      mNodesTmp.emplace_back(p.first);
+  }
+  if (!mNodesTmp.empty())
+    mQueue.push(mNodesTmp.begin(), mNodesTmp.end());
 }
 
 template<template<typename> class Q>
-bool ReducerHash<Q>::leadTerm(const_term &result)
+bool ReducerHash<Q>::leadTerm(const_term& result)
 {
-  while (!mQueue.empty())
-    {
-      if (mHashTable.popTerm(mQueue.top(), result.coeff, result.monom))
-        // returns true if mQueue.top() is not the zero element
-        return true;
-      mQueue.pop();
+  while (!mQueue.empty()) {
+    const auto top = mQueue.top();
+    if (!mRing.coefficientIsZero(top->value())) {
+      result.coeff = top->value();
+      result.monom = Monoid::toOld(top->mono());
+      return true;
     }
+    mQueue.pop();
+    mHashTable.remove(top);
+  }
   return false;
 }
 
@@ -101,19 +115,20 @@ template<template<typename> class Q>
 void ReducerHash<Q>::removeLeadTerm()
 // returns true if there is a term to extract
 {
+  const auto top = mQueue.top();
   mQueue.pop();
+  mHashTable.remove(top);
 }
 
 template<template<typename> class Q>
 void ReducerHash<Q>::resetReducer()
 {
-  const_term t;
-  while (leadTerm(t))
-    {
-      mQueue.pop();
-    }
-  mHashTable.reset();
-  // how to reset mQueue ?
+  while (!mQueue.empty()) {
+    const auto top = mQueue.top();
+    mQueue.pop();
+    mHashTable.remove(top);
+  }
+  mHashTable.clear();
 }
 
 template<template<typename> class Q>
diff --git a/src/mathicgb/ReducerHashPack.hpp b/src/mathicgb/ReducerHashPack.hpp
index 834d202..4c90880 100755
--- a/src/mathicgb/ReducerHashPack.hpp
+++ b/src/mathicgb/ReducerHashPack.hpp
@@ -43,11 +43,8 @@ private:
     Poly::const_iterator pos;
     Poly::const_iterator const end;
     const_term const multiple;
-    monomial current; // multiple.monom * pos.getMonomial()
-    PolyHashTable::node* node;
+    PolyHashTable::Node* node;
 
-    void computeCurrent(const PolyRing& ring, monomial current);
-    void currentCoefficient(const PolyRing& ring, coefficient& coeff);
     void destroy(const PolyRing& ring);
   };
 
@@ -56,7 +53,7 @@ private:
     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);
+      return ring().monoid().lessThan(a->node->mono(), b->node->mono());
     }
   };
 
@@ -74,10 +71,9 @@ template<template<typename> class Q>
 ReducerHashPack<Q>::ReducerHashPack(const PolyRing& ring):
   mRing(ring),
   mQueue(Configuration(ring)),
-  mHashTable(&ring, 10),
+  mHashTable(ring),
   mPool(sizeof(MultipleWithPos))
-{
-}
+{}
 
 template<template<typename> class Q>
 class ReducerHashPack<Q>::MonomialFree
@@ -140,24 +136,10 @@ ReducerHashPack<Q>::MultipleWithPos::MultipleWithPos
   pos(poly.begin()),
   end(poly.end()),
   multiple(allocTerm(poly.ring(), multiple)),
-  current(poly.ring().allocMonomial()),
   node(0) {}
 
 template<template<typename> class Q>
-void ReducerHashPack<Q>::MultipleWithPos::
-computeCurrent(const PolyRing& ring, monomial current) {
-  ring.monomialMult(multiple.monom, pos.getMonomial(), current);  
-}
-
-template<template<typename> class Q>
-void ReducerHashPack<Q>::MultipleWithPos::currentCoefficient
-(const PolyRing& ring, coefficient& coeff) {
-  ring.coefficientMult(multiple.coeff, pos.getCoefficient(), coeff);
-}
-
-template<template<typename> class Q>
 void ReducerHashPack<Q>::MultipleWithPos::destroy(const PolyRing& ring) {
-  ring.freeMonomial(current);
   ring.freeMonomial(const_cast<ConstMonomial&>(multiple.monom).castAwayConst());
 
   // Call the destructor to destruct the iterators into std::vector.
@@ -175,7 +157,7 @@ bool ReducerHashPack<Q>::leadTerm(const_term& result) {
 
     if (!mRing.coefficientIsZero(entry->node->value())) {
       result.coeff = entry->node->value();
-      result.monom = entry->node->mono();
+      result.monom = Monoid::toOld(entry->node->mono());
       return true;
     }
     removeLeadTerm();
@@ -204,14 +186,11 @@ void ReducerHashPack<Q>::removeLeadTerm() {
       mPool.free(entry);
       break;
     }
-    term t;
-    t.monom = entry->current;
-    entry->computeCurrent(mRing, t.monom);
-    entry->currentCoefficient(mRing, t.coeff);
-
-    std::pair<bool, PolyHashTable::node*> p = mHashTable.insert(t);
-    if (p.first) {
-      entry->node = p.second;
+   
+    const auto p = mHashTable.insertProduct
+      (entry->multiple, entry->pos.term());
+    if (p.second) {
+      entry->node = p.first;
       mQueue.decreaseTop(entry);
       break;
     }
@@ -222,14 +201,10 @@ template<template<typename> class Q>
 void ReducerHashPack<Q>::insertEntry(MultipleWithPos* entry) {
   MATHICGB_ASSERT(entry != 0);
   for (; entry->pos != entry->end; ++entry->pos) {
-    term t;
-    t.monom = entry->current;
-    entry->computeCurrent(mRing, t.monom);
-    entry->currentCoefficient(mRing, t.coeff);
-
-    std::pair<bool, PolyHashTable::node*> p = mHashTable.insert(t);
-    if (p.first) {
-      entry->node = p.second;
+    const auto p = mHashTable.insertProduct
+      (entry->multiple, entry->pos.term());
+    if (p.second) {
+      entry->node = p.first;
       mQueue.push(entry);
       return;
     }
@@ -244,7 +219,7 @@ void ReducerHashPack<Q>::resetReducer()
   MonomialFree freeer(mRing);
   mQueue.forAll(freeer);
   mQueue.clear();
-  mHashTable.reset();
+  mHashTable.clear();
 }
 
 template<template<typename> class Q>
diff --git a/src/test/gb-test.cpp b/src/test/gb-test.cpp
index 273a5bd..0e01cd0 100755
--- a/src/test/gb-test.cpp
+++ b/src/test/gb-test.cpp
@@ -51,114 +51,107 @@ void testGB(
 #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
-1	23	3	1	0	0	0	0	0	0	0	1	1
-2	14	1	2	0	1	1	0	0	1	1	2	2
-0	10	2	3	0	0	0	0	0	1	1	1	8
-3	23	4	4	1	0	0	1	1	1	0	100	2
-2	26	1	2	1	0	0	1	1	0	0	2	8
-3	4	4	4	0	1	1	0	0	0	1	2	1
-1	22	2	3	1	0	0	1	1	1	0	10	1
-0	17	3	1	0	1	1	0	0	0	1	10	8
-0	7	2	1	1	0	0	0	1	0	0	2	2
-1	23	4	3	0	1	1	0	0	1	1	10	8
-0	14	3	1	1	0	0	1	1	0	0	0	1
-2	18	2	2	0	1	1	0	0	0	1	100	1
-3	15	3	3	1	0	0	1	0	1	0	2	2
-3	7	1	4	0	1	1	0	0	1	1	10	8
-1	13	1	3	1	0	0	1	1	0	0	2	2
-2	12	2	4	0	1	1	0	0	1	1	0	8
-0	26	1	1	1	0	0	0	0	1	0	100	1
-1	21	4	2	1	0	0	1	0	0	0	0	2
-0	12	3	2	1	0	0	1	1	0	0	10	2
-2	8	4	1	1	0	0	0	1	1	0	2	2
-3	23	2	2	1	0	0	1	0	0	0	2	8
-2	21	3	4	0	1	1	0	0	1	1	1	1
-0	22	4	2	0	1	1	0	0	0	1	1	2
-3	26	4	3	1	0	0	1	1	1	0	0	2
-3	8	1	4	0	1	1	0	0	0	1	1	1
-0	25	1	4	1	0	0	1	1	1	0	0	1
-3	22	3	1	0	1	1	0	0	1	0	100	8
-2	20	2	3	0	0	1	0	0	0	1	1	8
-0	21	1	1	1	0	0	0	1	0	0	10	8
-1	19	3	4	1	0	0	0	1	0	0	0	8
-1	25	3	3	1	0	0	0	0	0	0	100	2
-0	15	1	4	0	1	1	0	0	0	1	100	1
-0	20	4	4	1	0	0	1	1	1	0	100	1
-2	24	1	4	0	1	0	0	0	1	1	2	1
-3	24	3	3	1	0	0	1	1	0	0	1	8
-2	10	4	2	1	0	0	1	1	0	0	100	1
-3	16	1	1	0	1	1	0	0	0	0	0	2
-3	19	1	3	0	1	1	0	0	1	1	2	2
-2	25	2	1	1	0	0	0	1	1	0	10	8
-3	12	1	3	0	0	1	0	0	1	0	1	1
-1	4	3	2	1	0	0	1	1	1	0	10	8
-1	12	4	1	0	0	1	0	0	0	1	100	8
-2	16	4	4	0	0	0	0	0	1	1	2	1
-2	15	4	1	1	0	0	1	1	0	0	0	8
-1	8	3	2	0	0	0	0	0	0	1	0	8
-3	20	1	1	0	1	0	0	0	1	1	10	2
-1	10	1	4	1	0	0	1	0	1	0	10	2
-0	23	1	2	0	1	0	0	0	0	1	0	8
-3	21	2	3	0	0	0	0	0	0	1	100	1
-0	19	2	1	0	0	0	0	0	0	1	1	1
-2	19	4	2	1	0	0	1	0	1	0	10	1
-3	18	1	3	1	0	0	1	1	1	0	0	8
-1	7	4	3	0	1	1	0	0	1	1	0	1
-2	11	4	3	0	1	1	0	0	0	0	1	2
-0	8	2	3	0	1	0	0	0	1	1	10	8
-1	15	2	2	1	0	0	1	0	1	0	10	8
-1	11	3	1	0	0	0	0	0	1	1	2	1
-2	9	4	1	0	0	0	0	0	1	0	1	1
-0	16	2	2	1	0	0	1	1	0	0	100	8
-1	16	3	3	0	0	0	0	0	0	1	10	1
-2	22	1	4	1	0	0	0	0	1	0	2	8
-3	25	4	2	1	0	0	0	1	0	0	1	2
-3	14	2	3	1	0	0	0	1	0	0	10	8
-0	13	3	4	0	1	1	0	0	1	1	0	1
-0	8	4	2	0	1	1	0	0	0	1	100	2
-2	13	4	1	1	0	0	1	1	0	0	1	8
-3	13	2	2	1	0	0	1	0	0	0	10	8
-3	17	4	4	1	0	0	1	1	1	0	0	1
-0	11	2	4	1	0	0	1	1	0	0	0	8
-2	12	1	4	0	1	1	0	0	0	1	2	1
-1	14	4	4	0	0	1	0	0	1	1	1	1
-1	20	3	2	0	0	0	0	0	1	1	2	2
-0	18	3	1	1	0	0	1	0	0	0	2	2
-3	16	2	4	0	0	1	0	0	0	0	1	8
-0	21	3	2	0	1	0	0	0	0	0	2	2
-2	4	1	3	0	1	0	0	0	1	1	1	2
-1	18	4	4	0	1	0	0	0	1	1	10	1
-3	14	2	4	0	1	1	0	0	0	0	100	1
-2	17	1	2	0	0	0	0	0	1	1	1	2
-1	24	4	2	1	0	0	1	1	0	0	10	2
-3	10	3	1	0	1	1	0	0	0	1	2	8
-2	7	3	2	0	1	1	0	0	0	1	1	2
-1	17	2	3	0	0	0	0	0	0	1	2	2
-0	24	2	1	0	1	1	0	0	0	1	0	1
-1	15	4	4	1	0	0	1	0	0	0	1	1
-1	18	1	1	0	0	0	0	0	0	1	1	8
-1	26	2	4	1	0	0	0	1	0	0	10	8
-3	11	1	2	0	1	0	0	0	0	0	10	8
-1	9	1	2	0	1	1	0	0	0	1	100	8
-3	19	4	4	1	0	0	1	0	0	0	100	8
-3	11	2	3	0	0	0	0	0	0	1	100	1
-3	9	2	3	1	0	0	1	1	1	0	2	2
-0	9	3	4	1	0	0	0	1	0	0	10	1
-0	4	2	1	1	0	0	0	1	1	0	0	1
-0	13	3	2	1	0	0	1	1	0	0	100	8
-3	7	1	4	0	1	0	0	0	1	1	100	8
-1	22	4	4	1	0	0	0	1	1	0	0	2
-3	24	2	4	1	0	0	1	0	0	0	100	1
-0	20	3	1	0	1	1	0	0	0	1	0	1
-1	25	3	1	1	0	0	1	0	0	0	2	2
-2	10	3	1	0	1	0	0	0	1	1	0	1
-2	4	2	1	0	0	0	0	0	0	1	100	8
-0	17	4	3	0	0	1	0	0	1	1	100	8
-1	9	2	3	1	0	0	1	0	0	0	0	2
-0	8	4	2	1	0	0	1	1	0	0	1	8
-2	7	2	1	1	0	0	1	0	0	0	2	8
-2	23	4	4	0	1	1	0	0	0	1	100	2
-1	26	3	4	1	0	0	0	0	0	0	1	8
+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.
diff --git a/src/test/pict.in b/src/test/pict.in
index 15e9089..77968bb 100755
--- a/src/test/pict.in
+++ b/src/test/pict.in
@@ -23,7 +23,7 @@
 # This is the PICT model specifying all parameters and their values
 #
 spairQueue: 0,1,2,3
-reducerType: 4,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
+reducerType: 7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
 divLookup: 1, 2, 3, 4
 monTable: 1, 2, 3, 4
 buchberger: 0, 1

-- 
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