[mathicgb] 362/393: Converted all non-F4 reducers to new MonoMonoid monomials and documented them.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:35 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 2fd2f02fc26dc11a9a9913806678cfa308313bf1
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Fri Sep 6 17:06:36 2013 +0200

    Converted all non-F4 reducers to new MonoMonoid monomials and documented them.
---
 src/mathicgb/F4Reducer.cpp        |   8 +-
 src/mathicgb/Poly.hpp             |   8 +-
 src/mathicgb/PolyHashTable.hpp    |   6 +-
 src/mathicgb/PolyRing.hpp         |  15 +++
 src/mathicgb/Reducer.hpp          |  31 +++--
 src/mathicgb/ReducerDedup.cpp     | 129 +++++++++-----------
 src/mathicgb/ReducerHash.cpp      |  32 ++---
 src/mathicgb/ReducerHashPack.cpp  | 115 +++++++++---------
 src/mathicgb/ReducerHelper.hpp    |   1 -
 src/mathicgb/ReducerNoDedup.cpp   | 139 +++++++++++----------
 src/mathicgb/ReducerPack.cpp      | 170 +++++++++++++-------------
 src/mathicgb/ReducerPackDedup.cpp | 247 +++++++++++++++++++-------------------
 src/mathicgb/TypicalReducer.cpp   |  13 +-
 src/mathicgb/TypicalReducer.hpp   |  33 ++++-
 14 files changed, 502 insertions(+), 445 deletions(-)

diff --git a/src/mathicgb/F4Reducer.cpp b/src/mathicgb/F4Reducer.cpp
index 2f0f25a..ae219f6 100755
--- a/src/mathicgb/F4Reducer.cpp
+++ b/src/mathicgb/F4Reducer.cpp
@@ -90,8 +90,8 @@ public:
   );
 
   virtual std::unique_ptr<Poly> regularReduce(
-    const_monomial sig,
-    const_monomial multiple,
+    ConstMonoRef sig,
+    ConstMonoRef multiple,
     size_t basisElement,
     const SigPolyBasis& basis
   );
@@ -297,8 +297,8 @@ void F4Reducer::classicReducePolySet(
 }
 
 std::unique_ptr<Poly> F4Reducer::regularReduce(
-  const_monomial sig,
-  const_monomial multiple,
+  ConstMonoRef sig,
+  ConstMonoRef multiple,
   size_t basisElement,
   const SigPolyBasis& basis
 ) {
diff --git a/src/mathicgb/Poly.hpp b/src/mathicgb/Poly.hpp
index 45ee1af..01c22c0 100755
--- a/src/mathicgb/Poly.hpp
+++ b/src/mathicgb/Poly.hpp
@@ -83,10 +83,10 @@ public:
       return std::pair<coefficient, const_monomial>
         (getCoefficient(), getMonomial());
     }
-    const_term term() const {
-      const_term t;
-      t.monom = getMonomial();
-      t.coeff = getCoefficient();
+    NewConstTerm term() const {
+      NewConstTerm t;
+      t.mono = getMonomial();
+      t.coef = getCoefficient();
       return t;
     }
   };
diff --git a/src/mathicgb/PolyHashTable.hpp b/src/mathicgb/PolyHashTable.hpp
index 88b45d6..0fd124b 100755
--- a/src/mathicgb/PolyHashTable.hpp
+++ b/src/mathicgb/PolyHashTable.hpp
@@ -87,11 +87,11 @@ public:
   }
 
   MATHICGB_INLINE
-  std::pair<Node*, bool> insertProduct(const_term a, const_term b)
+  std::pair<Node*, bool> insertProduct(NewConstTerm a, NewConstTerm b)
   {
     Value prod;
-    mRing.coefficientMult(a.coeff, b.coeff, prod);
-    return insertProduct(a.monom, b.monom, prod);
+    mRing.coefficientMult(a.coef, b.coef, prod);
+    return insertProduct(*a.mono, *b.mono, prod);
   }
 
   MATHICGB_INLINE
diff --git a/src/mathicgb/PolyRing.hpp b/src/mathicgb/PolyRing.hpp
index 237833b..c3781f3 100755
--- a/src/mathicgb/PolyRing.hpp
+++ b/src/mathicgb/PolyRing.hpp
@@ -195,6 +195,21 @@ typedef MonoMonoid<exponent>::ConstMonoPtr const_monomial;
 typedef MonoMonoid<exponent>::ConstMonoPtr ConstMonomial;
 #endif
 
+struct NewConstTerm {
+  MonoMonoid<exponent>::ConstMonoPtr mono;
+  coefficient coef;
+};
+
+struct NewTerm {
+  MonoMonoid<exponent>::MonoPtr mono;
+  coefficient coef;
+
+  operator NewConstTerm() const {
+    NewConstTerm t = {mono, coef};
+    return t;
+  }
+};
+
 struct const_term {
   const_term() {}
   const_term(const_coefficient c, const_monomial m) : coeff(c), monom(m) {}
diff --git a/src/mathicgb/Reducer.hpp b/src/mathicgb/Reducer.hpp
index 4228d1f..116ab3f 100755
--- a/src/mathicgb/Reducer.hpp
+++ b/src/mathicgb/Reducer.hpp
@@ -4,12 +4,12 @@
 #define MATHICGB_REDUCER_GUARD
 
 #include "PolyRing.hpp"
-#include "Poly.hpp"
 #include <memtailor.h>
 #include <memory>
 
 MATHICGB_NAMESPACE_BEGIN
 
+class Poly;
 class SigPolyBasis;
 class PolyBasis;
 
@@ -18,6 +18,15 @@ class PolyBasis;
 /// @todo: consider changing name of findLeadTerm to leadTerm.
 class Reducer {
 public:
+  typedef PolyRing::Monoid Monoid;
+  typedef Monoid::Mono Mono;
+  typedef Monoid::MonoRef MonoRef;
+  typedef Monoid::ConstMonoRef ConstMonoRef;
+  typedef Monoid::MonoPtr MonoPtr;
+  typedef Monoid::ConstMonoPtr ConstMonoPtr;
+
+  typedef coefficient Coefficient;
+
   virtual ~Reducer();
 
   /// Returns the preferred number of reductions to do at a time. A classic
@@ -70,8 +79,8 @@ public:
   /// is not regular top reducible -- this indicates a singular
   /// reduction.
   virtual std::unique_ptr<Poly> regularReduce(
-    const_monomial sig,
-    const_monomial multiple,
+    ConstMonoRef sig,
+    ConstMonoRef multiple,
     size_t basisElement,
     const SigPolyBasis& basis
   ) = 0;
@@ -140,13 +149,15 @@ public:
 /// 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; \
-    } \
-  )
+  namespace { \
+    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/ReducerDedup.cpp b/src/mathicgb/ReducerDedup.cpp
index 7a324c8..f02110d 100644
--- a/src/mathicgb/ReducerDedup.cpp
+++ b/src/mathicgb/ReducerDedup.cpp
@@ -12,6 +12,8 @@ MATHICGB_NAMESPACE_BEGIN
 
 void reducerDedupDependency() {}
 
+/// As ReducerNoDedup, except that if two like terms are compared, then
+/// they are removed and replaced by their sum.
 template<template<typename> class Queue>
 class ReducerDedup : public TypicalReducer {
 public:
@@ -22,41 +24,37 @@ public:
     return mQueue.getName() + "-dedup"; 
   }
 
-  virtual void insertTail(const_term multiplier, const Poly *f);
-  virtual void insert(monomial multiplier, const Poly *f);
+  virtual void insertTail(NewConstTerm multiplier, const Poly& f);
+  virtual void insert(ConstMonoRef multiplier, const Poly& f);
 
-  virtual bool leadTerm(const_term &result);
+  virtual bool leadTerm(NewConstTerm& result);
   virtual void removeLeadTerm();
 
   virtual size_t getMemoryUse() const;
 
-protected:
   virtual void resetReducer();
 
 public:
   // This Configuration is designed to work with
   // mathic::TourTree, mathic::Heap, and mathic::Geobucket
-
   class Configuration : public ReducerHelper::DedupConfiguration {
   public:
-    typedef term Entry;
+    typedef NewTerm Entry;
     Configuration(const PolyRing& ring): DedupConfiguration(ring) {}
     CompareResult compare(const Entry& a, const Entry& b) const {
-      return ring().monomialCompare(a.monom, b.monom);
+      return ring().monoid().compare(*a.mono, *b.mono);
     }
     Entry deduplicate(Entry a, Entry b) const {
       // change a.coeff, and free b.monom
-      ring().coefficientAddTo(a.coeff, b.coeff);
-      ring().freeMonomial(b.monom);
+      ring().coefficientAddTo(a.coef, b.coef);
+      ring().monoid().freeRaw(*b.mono);
       return a;
     }
   };
 
 private:
-  class MonomialFree;
-  
   const PolyRing& mRing;
-  term mLeadTerm;
+  NewTerm mLeadTerm;
   bool mLeadTermKnown;
   Queue<Configuration> mQueue;
 };
@@ -64,98 +62,78 @@ private:
 template<template<typename> class Q>
 ReducerDedup<Q>::ReducerDedup(const PolyRing& ring):
   mRing(ring),
-  mLeadTerm(0, mRing.allocMonomial()),
   mLeadTermKnown(false),
-  mQueue(Configuration(ring)) {
+  mQueue(Configuration(ring))
+{
+  mLeadTerm.mono = mRing.monoid().alloc().release();
 }
 
 template<template<typename> class Q>
-class ReducerDedup<Q>::MonomialFree {
-public:
-  MonomialFree(const PolyRing& ring): mRing(ring) {}
-
-  bool proceed(term entry)
-  {
-    mRing.freeMonomial(entry.monom);
-    return true;
-  }
-private:
-  const PolyRing& mRing;
-};
-
-template<template<typename> class Q>
 ReducerDedup<Q>::~ReducerDedup() {
   resetReducer();
-  mRing.freeMonomial(mLeadTerm.monom);
+  mRing.monoid().freeRaw(*mLeadTerm.mono);
 }
 
-///////////////////////////////////////
-// External interface routines ////////
-///////////////////////////////////////
 template<template<typename> class Q>
-void ReducerDedup<Q>::insertTail(const_term multiple, const Poly* poly) {
-  if (poly->nTerms() <= 1)
+void ReducerDedup<Q>::insertTail(NewConstTerm multiple, const Poly& poly) {
+  if (poly.nTerms() <= 1)
     return;
   mLeadTermKnown = false;
 
-  Poly::const_iterator i = poly->begin();
-  for (++i; i != poly->end(); ++i) {
-    term t;
-    t.monom = mRing.allocMonomial();
-    mRing.monomialMult(multiple.monom, i.getMonomial(), t.monom);
-    mRing.coefficientMult(multiple.coeff, i.getCoefficient(), t.coeff);
+  auto it = poly.begin();
+  const auto end = poly.end();
+  for (++it; it != end; ++it) {
+    NewTerm t;
+    t.mono = mRing.monoid().alloc().release();
+    mRing.monoid().multiply(*multiple.mono, it.getMonomial(), *t.mono);
+    mRing.coefficientMult(multiple.coef, it.getCoefficient(), t.coef);
     mQueue.push(t);
   }
 }
 
 template<template<typename> class Q>
-void ReducerDedup<Q>::insert(monomial multiple, const Poly* poly) {
-  if (poly->isZero())
+void ReducerDedup<Q>::insert(ConstMonoRef multiple, const Poly& poly) {
+  if (poly.isZero())
     return;
   mLeadTermKnown = false;
 
-  for (Poly::const_iterator i = poly->begin(); i != poly->end(); ++i) {
-    term t(i.getCoefficient(), mRing.allocMonomial());
-    mRing.monomialMult(multiple, i.getMonomial(), t.monom);
+  const auto end = poly.end();
+  for (auto it = poly.begin(); it != end; ++it) {
+    NewTerm t = {mRing.monoid().alloc().release(), it.getCoefficient()};
+    mRing.monoid().multiply(multiple, it.getMonomial(), *t.mono);
     mQueue.push(t);
   }
 }
 
 template<template<typename> class Q>
-bool ReducerDedup<Q>::leadTerm(const_term& result) {
-  if (mLeadTermKnown) {
-    result = mLeadTerm;
-    return true;
-  }
-
-  do {
-    if (mQueue.empty())
-      return false;
-    mLeadTerm = mQueue.top();
-    mQueue.pop();
-    
-    while (true) {
+bool ReducerDedup<Q>::leadTerm(NewConstTerm& result) {
+  if (!mLeadTermKnown) {
+    do {
       if (mQueue.empty())
-        break;
-      
-      term entry = mQueue.top();
-      if (!mRing.monomialEQ(entry.monom, mLeadTerm.monom))
-        break;
-      mRing.coefficientAddTo(mLeadTerm.coeff, entry.coeff);
-      mRing.freeMonomial(entry.monom);
+        return false;
+      mLeadTerm = mQueue.top();
       mQueue.pop();
-    }
-  } while (mRing.coefficientIsZero(mLeadTerm.coeff));
+    
+      while (!mQueue.empty()) {
+        auto entry = mQueue.top();
+        if (!mRing.monoid().equal(*entry.mono, *mLeadTerm.mono))
+          break;
+        mRing.coefficientAddTo(mLeadTerm.coef, entry.coef);
+        mRing.monoid().freeRaw(*entry.mono);
+        mQueue.pop();
+      }
+    } while (mRing.coefficientIsZero(mLeadTerm.coef));
+    mLeadTermKnown = true;
+  }
 
   result = mLeadTerm;
-  mLeadTermKnown = true;
   return true;
 }
 
 template<template<typename> class Q>
 void ReducerDedup<Q>::removeLeadTerm() {
   if (!mLeadTermKnown) {
-    const_term dummy;
+    NewConstTerm dummy;
     leadTerm(dummy);
   }
   mLeadTermKnown = false;
@@ -163,6 +141,19 @@ void ReducerDedup<Q>::removeLeadTerm() {
 
 template<template<typename> class Q>
 void ReducerDedup<Q>::resetReducer() {
+  class MonomialFree {
+  public:
+    MonomialFree(const PolyRing& ring): mRing(ring) {}
+
+    bool proceed(NewTerm entry)
+    {
+      mRing.monoid().freeRaw(*entry.mono);
+      return true;
+    }
+  private:
+    const PolyRing& mRing;
+  };
+
   MonomialFree freeer(mRing);
   mQueue.forAll(freeer);
   mQueue.clear();
diff --git a/src/mathicgb/ReducerHash.cpp b/src/mathicgb/ReducerHash.cpp
index b19561f..e0f4028 100644
--- a/src/mathicgb/ReducerHash.cpp
+++ b/src/mathicgb/ReducerHash.cpp
@@ -13,6 +13,10 @@ MATHICGB_NAMESPACE_BEGIN
 
 void reducerHashDependency() {}
 
+/// The simplest reducer using a hashtable. All terms are in the hash table
+/// and in the queue. There are no duplicates as new terms are looked up in
+/// the hash table before insertion into the queue. The coefficient is
+/// stored in the hash table.
 template<template<typename> class Queue>
 class ReducerHash : public TypicalReducer {
 public:
@@ -22,15 +26,14 @@ public:
     return mQueue.getName() + "-hashed";
   }
 
-  void insertTail(const_term multiplier, const Poly *f);
-  void insert(monomial multiplier, const Poly *f);
+  void insertTail(NewConstTerm multiplier, const Poly& f);
+  void insert(ConstMonoRef multiplier, const Poly& f);
 
-  virtual bool leadTerm(const_term& result);
+  virtual bool leadTerm(NewConstTerm& result);
   void removeLeadTerm();
 
   size_t getMemoryUse() const;
 
-protected:
   void resetReducer();
 
 public:
@@ -60,12 +63,13 @@ ReducerHash<Q>::ReducerHash(const PolyRing &ring):
 {}
 
 template<template<typename> class Q>
-void ReducerHash<Q>::insertTail(const_term multiplier, const Poly *g1) {
-  if (g1->nTerms() <= 1) return;
+void ReducerHash<Q>::insertTail(NewConstTerm multiplier, const Poly& f) {
+  if (f.nTerms() <= 1)
+    return;
 
   mNodesTmp.clear();
-  auto it = g1->begin();
-  const auto end = g1->end();
+  auto it = f.begin();
+  const auto end = f.end();
   for (++it; it != end; ++it) {
     auto p = mHashTable.insertProduct(it.term(), multiplier);
     if (p.second)
@@ -76,10 +80,10 @@ void ReducerHash<Q>::insertTail(const_term multiplier, const Poly *g1) {
 }
 
 template<template<typename> class Q>
-void ReducerHash<Q>::insert(monomial multiplier, const Poly *g1) {
+void ReducerHash<Q>::insert(ConstMonoRef multiplier, const Poly& f) {
   mNodesTmp.clear();
-  const auto end = g1->end();
-  for (auto it = g1->begin(); it != end; ++it) {
+  const auto end = f.end();
+  for (auto it = f.begin(); it != end; ++it) {
     auto p = mHashTable.insertProduct
       (it.getMonomial(), multiplier, it.getCoefficient());
     if (p.second)
@@ -90,12 +94,12 @@ void ReducerHash<Q>::insert(monomial multiplier, const Poly *g1) {
 }
 
 template<template<typename> class Q>
-bool ReducerHash<Q>::leadTerm(const_term& result) {
+bool ReducerHash<Q>::leadTerm(NewConstTerm& result) {
   while (!mQueue.empty()) {
     const auto top = mQueue.top();
     if (!mRing.coefficientIsZero(top->value())) {
-      result.coeff = top->value();
-      result.monom = Monoid::toOld(top->mono());
+      result.coef = top->value();
+      result.mono = top->mono().ptr();
       return true;
     }
     mQueue.pop();
diff --git a/src/mathicgb/ReducerHashPack.cpp b/src/mathicgb/ReducerHashPack.cpp
index 7864d95..c71d879 100644
--- a/src/mathicgb/ReducerHashPack.cpp
+++ b/src/mathicgb/ReducerHashPack.cpp
@@ -13,6 +13,21 @@ MATHICGB_NAMESPACE_BEGIN
 
 void reducerHashPackDependency() {}
 
+/// A combination of ReducerHash and ReducerPack. Each entry in the queue
+/// corresponds to a term (times a multiplier) of a polynomial. When such a
+/// term is taken off the queue, we advance it to the next term of the
+/// corresponding polynomial and push that back into the queue. Each entry
+/// in the queue is also associated to a hash table entry, where the
+/// data is stored - the entries in the queue are just pointers into
+/// hash table nodes. There are no like terms to add up in the queue, since
+/// the hash table identifies such before insertion into the queue.
+///
+/// There is no need for the complexity of chaining as in ReducerPackDedup,
+/// since we simply keep advancing through the terms in a polynomial until
+/// there are no more terms or we get a term that is unlike any other term
+/// in the queue. We could have stored a list of like terms for each
+/// entry in the queue as in ReducerPackDedup, which might reduce the size of
+/// the queue, but this is a good compromise that leads to simpler code.
 template<template<typename> class Queue>
 class ReducerHashPack : public TypicalReducer {
 public:
@@ -23,26 +38,25 @@ public:
     return mQueue.getName() + "-hashed-packed";
   }
 
-  virtual void insertTail(const_term multiplier, const Poly *f);
-  virtual void insert(monomial multiplier, const Poly *f);
+  virtual void insertTail(NewConstTerm multiplier, const Poly& f);
+  virtual void insert(ConstMonoRef multiplier, const Poly& f);
 
-  virtual bool leadTerm(const_term &result);
+  virtual bool leadTerm(NewConstTerm& 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.
   struct MultipleWithPos {
-    MultipleWithPos(const Poly& poly, const_term multiple);
+    MultipleWithPos(const Poly& poly, NewConstTerm multiple);
 
     Poly::const_iterator pos;
     Poly::const_iterator const end;
-    const_term const multiple;
+    NewTerm multiple;
     PolyHashTable::Node* node;
 
     void destroy(const PolyRing& ring);
@@ -57,8 +71,6 @@ private:
     }
   };
 
-  class MonomialFree;
-
   void insertEntry(MultipleWithPos* entry);
 
   const PolyRing& mRing;
@@ -76,85 +88,63 @@ ReducerHashPack<Q>::ReducerHashPack(const PolyRing& ring):
 {}
 
 template<template<typename> class Q>
-class ReducerHashPack<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>
 ReducerHashPack<Q>::~ReducerHashPack() {
   resetReducer();
 }
 
 template<template<typename> class Q>
-void ReducerHashPack<Q>::insertTail(const_term multiple, const Poly* poly) {
-  MATHICGB_ASSERT(poly != 0);
-  MATHICGB_ASSERT(&poly->ring() == &mRing);
-  if (poly->nTerms() < 2)
+void ReducerHashPack<Q>::insertTail(NewConstTerm multiple, const Poly& poly) {
+  MATHICGB_ASSERT(&poly.ring() == &mRing);
+  if (poly.nTerms() <= 1)
     return;
-  MultipleWithPos* entry =
-    new (mPool.alloc()) MultipleWithPos(*poly, multiple);
+  auto entry = new (mPool.alloc()) MultipleWithPos(poly, multiple);
   ++entry->pos;
   insertEntry(entry);
 }
 
 template<template<typename> class Q>
-void ReducerHashPack<Q>::insert(monomial multiple, const Poly* poly) {
-  MATHICGB_ASSERT(poly != 0);
-  MATHICGB_ASSERT(&poly->ring() == &mRing);
-  if (poly->isZero())
+void ReducerHashPack<Q>::insert(ConstMonoRef multiple, const Poly& poly) {
+  MATHICGB_ASSERT(&poly.ring() == &mRing);
+  if (poly.isZero())
     return;
-  term termMultiple(1, multiple);
-  insertEntry(new (mPool.alloc()) MultipleWithPos(*poly, termMultiple));
-}
-
-namespace {
-  const_term allocTerm(const PolyRing& ring, const_term term) {
-    monomial mono = ring.allocMonomial();
-    ring.monomialCopy(term.monom, mono);
-    return const_term(term.coeff, mono);
-  }
+  NewConstTerm termMultiple = {multiple.ptr(), 1};
+  insertEntry(new (mPool.alloc()) MultipleWithPos(poly, termMultiple));
 }
 
 template<template<typename> class Q>
 ReducerHashPack<Q>::MultipleWithPos::MultipleWithPos(
   const Poly& poly,
-  const_term multiple
+  NewConstTerm multipleParam
 ):
   pos(poly.begin()),
   end(poly.end()),
-  multiple(allocTerm(poly.ring(), multiple)),
   node(0)
-{}  
+{
+  multiple.mono = poly.ring().monoid().alloc().release();
+  poly.ring().monoid().copy(*multipleParam.mono, *multiple.mono);
+  multiple.coef = multipleParam.coef;
+}
 
 template<template<typename> class Q>
 void ReducerHashPack<Q>::MultipleWithPos::destroy(const PolyRing& ring) {
-  ring.freeMonomial
-    (const_cast<ConstMonomial&>(multiple.monom).castAwayConst());
+  ring.monoid().freeRaw(*multiple.mono);
 
   // 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.
+  // has to be called since it takes an iterator off the list. There were
+  // memory corruption problems in debug mode on MSVC before doing this.
   this->~MultipleWithPos();
 }
 
 template<template<typename> class Q>
-bool ReducerHashPack<Q>::leadTerm(const_term& result) {
+bool ReducerHashPack<Q>::leadTerm(NewConstTerm& result) {
   while (!mQueue.empty()) {
-    MultipleWithPos* entry = mQueue.top();
-    MATHICGB_ASSERT(entry != 0);
+    auto entry = mQueue.top();
+    MATHICGB_ASSERT(entry != nullptr);
 
     if (!mRing.coefficientIsZero(entry->node->value())) {
-      result.coeff = entry->node->value();
-      result.monom = Monoid::toOld(entry->node->mono());
+      result.coef = entry->node->value();
+      result.mono = entry->node->mono().ptr();
       return true;
     }
     removeLeadTerm();
@@ -166,12 +156,12 @@ template<template<typename> class Q>
 void ReducerHashPack<Q>::removeLeadTerm() {
   MATHICGB_ASSERT(!mQueue.empty());
 
-  MultipleWithPos* entry = mQueue.top();
+  auto entry = mQueue.top();
   MATHICGB_ASSERT(entry != 0);
 
   // remove node from hash table first since we are going to be changing
   // the monomial after this, and if we do that before the hash value will
-  // change.
+  // change. That might prompt an assert inside the hash table.
   mHashTable.remove(entry->node);
 
   MATHICGB_ASSERT(entry->pos != entry->end);
@@ -183,7 +173,7 @@ void ReducerHashPack<Q>::removeLeadTerm() {
       mPool.free(entry);
       break;
     }
-   
+
     const auto p = mHashTable.insertProduct
       (entry->multiple, entry->pos.term());
     if (p.second) {
@@ -212,6 +202,18 @@ void ReducerHashPack<Q>::insertEntry(MultipleWithPos* entry) {
 
 template<template<typename> class Q>
 void ReducerHashPack<Q>::resetReducer() {
+  class MonomialFree {
+  public:
+    MonomialFree(const PolyRing& ring): mRing(ring) {}
+
+    bool proceed(MultipleWithPos* entry) {
+      entry->destroy(mRing);
+      return true;
+    }
+  private:
+    const PolyRing& mRing;
+  };
+
   MonomialFree freeer(mRing);
   mQueue.forAll(freeer);
   mQueue.clear();
@@ -225,6 +227,7 @@ size_t ReducerHashPack<Q>::getMemoryUse() const {
     mHashTable.getMemoryUse();
 }
 
+
 MATHICGB_REGISTER_REDUCER(
   "TourHashPack",
   Reducer_TourTree_Hashed_Packed,
diff --git a/src/mathicgb/ReducerHelper.hpp b/src/mathicgb/ReducerHelper.hpp
index caf933c..fc7d4d1 100755
--- a/src/mathicgb/ReducerHelper.hpp
+++ b/src/mathicgb/ReducerHelper.hpp
@@ -85,7 +85,6 @@ namespace ReducerHelper {
     ring.monomialCopy(term.monom, mono);
     return const_term(term.coeff, mono);
   }
-
 }
 
 MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/ReducerNoDedup.cpp b/src/mathicgb/ReducerNoDedup.cpp
index 90b47a1..067e438 100644
--- a/src/mathicgb/ReducerNoDedup.cpp
+++ b/src/mathicgb/ReducerNoDedup.cpp
@@ -12,6 +12,11 @@ MATHICGB_NAMESPACE_BEGIN
 
 void reducerNoDedupDependency() {}
 
+/// The most straight forward of the reducers. Simply keep a priority queue
+/// with all the pending terms. If two like monomials are compared in the
+/// queue, they are not combined - both stay in the queue. The sum of like
+/// terms is only taken at the end, when the leading term and its
+/// coefficient is determined.
 template<template<typename> class Queue>
 class ReducerNoDedup : public TypicalReducer {
 public:
@@ -22,34 +27,30 @@ public:
     return mQueue.getName() + "-nodedup"; 
   }
 
-  virtual void insertTail(const_term multiplier, const Poly *f);
-  virtual void insert(monomial multiplier, const Poly *f);
+  virtual void insertTail(NewConstTerm multiplier, const Poly& f);
+  virtual void insert(ConstMonoRef multiplier, const Poly& f);
 
-  virtual bool leadTerm(const_term &result);
+  virtual bool leadTerm(NewConstTerm& result);
   virtual void removeLeadTerm();
 
   virtual size_t getMemoryUse() const;
 
-protected:
   virtual void resetReducer();
 
-public:
+private:
   // This Configuration is designed to work with
   // mathic::TourTree, mathic::Heap, and mathic::Geobucket
   class Configuration : public ReducerHelper::PlainConfiguration {
   public:
-    typedef term Entry;
+    typedef NewTerm Entry;
     Configuration(const PolyRing& ring): PlainConfiguration(ring) {}
     CompareResult compare(const Entry& a, const Entry& b) const {
-      return ring().monomialLT(a.monom, b.monom);
+      return ring().monoid().lessThan(*a.mono, *b.mono);
     }
   };
 
-private:
-  class MonomialFree;
-  
   const PolyRing& mRing;
-  term mLeadTerm;
+  NewTerm mLeadTerm;
   bool mLeadTermKnown;
   Queue<Configuration> mQueue;
 };
@@ -57,96 +58,81 @@ private:
 template<template<typename> class Q>
 ReducerNoDedup<Q>::ReducerNoDedup(const PolyRing& ring):
   mRing(ring),
-  mLeadTerm(0, mRing.allocMonomial()),
   mLeadTermKnown(false),
-  mQueue(Configuration(ring)) {
+  mQueue(Configuration(ring))
+{
+  mLeadTerm.mono = mRing.monoid().alloc().release();
 }
 
 template<template<typename> class Q>
-class ReducerNoDedup<Q>::MonomialFree {
-public:
-  MonomialFree(const PolyRing& ring): mRing(ring) {}
-
-  bool proceed(term entry)
-  {
-    mRing.freeMonomial(entry.monom);
-    return true;
-  }
-private:
-  const PolyRing& mRing;
-};
-
-template<template<typename> class Q>
 ReducerNoDedup<Q>::~ReducerNoDedup() {
   resetReducer();
-  mRing.freeMonomial(mLeadTerm.monom);
+  mRing.monoid().freeRaw(*mLeadTerm.mono);
 }
 
 template<template<typename> class Q>
-void ReducerNoDedup<Q>::insertTail(const_term multiple, const Poly* poly) {
-  if (poly->nTerms() <= 1)
+void ReducerNoDedup<Q>::insertTail(NewConstTerm multiple, const Poly& poly) {
+  if (poly.nTerms() <= 1)
     return;
   mLeadTermKnown = false;
 
-  Poly::const_iterator i = poly->begin();
-  for (++i; i != poly->end(); ++i)
-    {
-      term t;
-      t.monom = mRing.allocMonomial();
-      mRing.monomialMult(multiple.monom, i.getMonomial(), t.monom);
-      mRing.coefficientMult(multiple.coeff, i.getCoefficient(), t.coeff);
-      mQueue.push(t);
-    }
+  auto it = poly.begin();
+  const auto end = poly.end();
+  for (++it; it != end; ++it) {
+    NewTerm t;
+    t.mono = mRing.allocMonomial();
+    mRing.monoid().multiply(*multiple.mono, it.getMonomial(), *t.mono);
+    mRing.coefficientMult(multiple.coef, it.getCoefficient(), t.coef);
+    mQueue.push(t);
+  }
 }
 
 template<template<typename> class Q>
-void ReducerNoDedup<Q>::insert(monomial multiple, const Poly* poly) {
-  if (poly->isZero())
+void ReducerNoDedup<Q>::insert(ConstMonoRef multiple, const Poly& poly) {
+  if (poly.isZero())
     return;
   mLeadTermKnown = false;
 
-  for (Poly::const_iterator i = poly->begin(); i != poly->end(); ++i) {
-    term t(i.getCoefficient(), mRing.allocMonomial());
-    mRing.monomialMult(multiple, i.getMonomial(), t.monom);
+  const auto end = poly.end();
+  for (auto it = poly.begin(); it != end; ++it) {
+    NewTerm t = {mRing.monoid().alloc().release(), it.getCoefficient()};
+    mRing.monoid().multiply(multiple, it.getMonomial(), *t.mono);
     mQueue.push(t);
   }
 }
 
 template<template<typename> class Q>
-bool ReducerNoDedup<Q>::leadTerm(const_term& result) {
-  if (mLeadTermKnown) {
-    result = mLeadTerm;
-    return true;
-  }
-
-  do {
-    if (mQueue.empty())
-      return false;
-    mLeadTerm = mQueue.top();
-    mQueue.pop();
-    
-    while (true) {
+bool ReducerNoDedup<Q>::leadTerm(NewConstTerm& result) {
+  if (!mLeadTermKnown) {
+    do {
       if (mQueue.empty())
-        break;
-      
-      term entry = mQueue.top();
-      if (!mRing.monomialEQ(entry.monom, mLeadTerm.monom))
-        break;
-      mRing.coefficientAddTo(mLeadTerm.coeff, entry.coeff);
-      mRing.freeMonomial(entry.monom);
+        return false;
+      mLeadTerm = mQueue.top();
       mQueue.pop();
-    }
-  } while (mRing.coefficientIsZero(mLeadTerm.coeff));
+    
+      while (true) {
+        if (mQueue.empty())
+          break;
+      
+        auto entry = mQueue.top();
+        if (!mRing.monoid().equal(*entry.mono, *mLeadTerm.mono))
+          break;
+        mRing.coefficientAddTo(mLeadTerm.coef, entry.coef);
+        mRing.monoid().freeRaw(*entry.mono);
+        mQueue.pop();
+      }
+    } while (mRing.coefficientIsZero(mLeadTerm.coef));
+    mLeadTermKnown = true;
+  }
 
   result = mLeadTerm;
-  mLeadTermKnown = true;
   return true;
 }
 
 template<template<typename> class Q>
 void ReducerNoDedup<Q>::removeLeadTerm() {
   if (!mLeadTermKnown) {
-    const_term dummy;
+    NewConstTerm dummy;
     leadTerm(dummy);
   }
   mLeadTermKnown = false;
@@ -154,9 +140,22 @@ void ReducerNoDedup<Q>::removeLeadTerm() {
 
 template<template<typename> class Q>
 void ReducerNoDedup<Q>::resetReducer() {
+  class MonomialFree {
+  public:
+    MonomialFree(const PolyRing& ring): mRing(ring) {}
+
+    bool proceed(NewTerm entry) {
+      mRing.monoid().freeRaw(*entry.mono);
+      return true;
+    }
+
+  private:
+    const PolyRing& mRing;
+  };
+
   MonomialFree freeer(mRing);
-  //mQueue.forAll(freeer);
-  //  mQueue.clear();
+  mQueue.forAll(freeer);
+  mQueue.clear();
 }
 
 template<template<typename> class Q>
diff --git a/src/mathicgb/ReducerPack.cpp b/src/mathicgb/ReducerPack.cpp
index 60ca977..12583e5 100644
--- a/src/mathicgb/ReducerPack.cpp
+++ b/src/mathicgb/ReducerPack.cpp
@@ -12,50 +12,56 @@ MATHICGB_NAMESPACE_BEGIN
 
 void reducerPackDependency() {}
 
+/// Keep a priority queue with entries that represent a term of a polynomial
+/// times a multiplier. When an entry is popped, move on to the next
+/// term of the polynomial, if any, and push that back into the queue. The
+/// idea is that this reduces the number of elements in the queue, leading
+/// to faster queue operations. Memory is also saved compared to expanding
+/// each new polynomial with n terms into n entries in the queue.
 template<template<typename> class Queue>
 class ReducerPack : public TypicalReducer {
 public:
   ReducerPack(const PolyRing& ring):
     mRing(ring),
-    mLeadTerm(0, mRing.allocMonomial()),
     mLeadTermKnown(false),
     mQueue(Configuration(ring)),
     mPool(sizeof(MultipleWithPos))
-  {}
+  {
+    mLeadTerm.mono = mRing.monoid().alloc().release();
+  }
 
   virtual ~ReducerPack() {
     resetReducer();
-    mRing.freeMonomial(mLeadTerm.monom);
+    mRing.monoid().freeRaw(*mLeadTerm.mono);
   }
 
   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 void insertTail(NewConstTerm multiplier, const Poly& f);
+  virtual void insert(ConstMonoRef multiplier, const Poly& f);
 
-  virtual bool leadTerm(const_term& result);
+  virtual bool leadTerm(NewConstTerm& result);
   virtual void removeLeadTerm();
 
   virtual size_t getMemoryUse() const;
 
-protected:
+private:
   virtual void resetReducer();
 
-private:
   // Represents a term multiple of a polynomial, 
   // together with a current term of the multiple.
   struct MultipleWithPos {
-    MultipleWithPos(const Poly& poly, const_term multiple);
+    MultipleWithPos(const Poly& poly, NewConstTerm multiple);
 
     Poly::const_iterator pos;
     Poly::const_iterator const end;
-    const_term const multiple;
+    NewTerm multiple;
 
     // invariant: current is the monomial product of multiple.monom 
     // and pos.getMonomial().
-    monomial current;
+    MonoPtr current;
 
     // Ensures the invariant, so sets current to the product of
     // multiple.monom and pos.getMonomial().
@@ -69,130 +75,117 @@ 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->current, *b->current);
     }
   };
 
 private:
-  class MonomialFree {
-  public:
-    MonomialFree(const PolyRing& ring): mRing(ring) {}
-
-    bool proceed(MultipleWithPos* entry) {
-      entry->destroy(mRing);
-      return true;
-    }
-
-  private:
-    const PolyRing& mRing;
-  };
-  
   const PolyRing& mRing;
-  term mLeadTerm;
+  NewTerm mLeadTerm;
   bool mLeadTermKnown;
   Queue<Configuration> mQueue;
   memt::BufferPool mPool;
 };
 
 template<template<typename> class Q>
-void ReducerPack<Q>::insertTail(const_term multiple, const Poly* poly)
+void ReducerPack<Q>::insertTail(NewConstTerm multiple, const Poly& poly)
 {
-  if (poly->nTerms() <= 1)
+  if (poly.nTerms() <= 1)
     return;
   mLeadTermKnown = false;
 
   MultipleWithPos* entry =
-    new (mPool.alloc()) MultipleWithPos(*poly, multiple);
+    new (mPool.alloc()) MultipleWithPos(poly, multiple);
   ++entry->pos;
-  entry->computeCurrent(poly->ring());
+  entry->computeCurrent(poly.ring());
   mQueue.push(entry);
 }
 
 template<template<typename> class Q>
-void ReducerPack<Q>::insert(monomial multiple, const Poly* poly)
+void ReducerPack<Q>::insert(ConstMonoRef multiple, const Poly& poly)
 {
-  if (poly->isZero())
+  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());
+  NewConstTerm termMultiple = {multiple.ptr(), 1};
+  auto 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):
+ReducerPack<Q>::MultipleWithPos::MultipleWithPos(
+  const Poly& poly,
+  NewConstTerm multipleParam
+):
   pos(poly.begin()),
   end(poly.end()),
-  multiple(ReducerHelper::allocTermCopy(poly.ring(), multipleParam)),
-  current(poly.ring().allocMonomial()) {}
+  current(poly.ring().allocMonomial())
+{
+  multiple.mono = poly.ring().monoid().alloc().release();
+  poly.ring().monoid().copy(*multipleParam.mono, *multiple.mono);
+  multiple.coef = multipleParam.coef;
+}
 
 template<template<typename> class Q>
 void ReducerPack<Q>::MultipleWithPos::computeCurrent(const PolyRing& ring) {
-  ring.monomialMult(multiple.monom, pos.getMonomial(), current);  
+  ring.monoid().multiply(*multiple.mono, 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);
+  ring.coefficientMult(multiple.coef, 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());
+  ring.monoid().freeRaw(*current);
+  ring.monoid().freeRaw(*multiple.mono);
 
   // 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.
+  // has to be called since it takes an iterator off the list. There were
+  // memory corruption problems in debug mode before doing this on MSVC.
   this->~MultipleWithPos();
 }
 
 template<template<typename> class Q>
-bool ReducerPack<Q>::leadTerm(const_term& result)
+bool ReducerPack<Q>::leadTerm(NewConstTerm& 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);
+  if (!mLeadTermKnown) {
+    do {
+      if (mQueue.empty())
+        return false;
+      MultipleWithPos* entry = mQueue.top();
+      std::swap(mLeadTerm.mono, entry->current);
+      entry->currentCoefficient(mRing, mLeadTerm.coef);
     
-    while (true) {
-      ++entry->pos;
-      if (entry->pos == entry->end) {
-        mQueue.pop();
-        entry->destroy(mRing);
-        mPool.free(entry);
-      } else {
-        entry->computeCurrent(mRing);
-        mQueue.decreaseTop(entry);
-      }
+      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;
+        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));
+        entry = mQueue.top();
+        if (!mRing.monoid().equal(*entry->current, *mLeadTerm.mono))
+          break;
+        coefficient coef;
+        entry->currentCoefficient(mRing, coef);
+        mRing.coefficientAddTo
+          (mLeadTerm.coef, const_cast<const coefficient&>(coef));
+      }
+    } while (mRing.coefficientIsZero(mLeadTerm.coef));
+  }
 
   result = mLeadTerm;
   mLeadTermKnown = true;
@@ -203,7 +196,7 @@ template<template<typename> class Q>
 void ReducerPack<Q>::removeLeadTerm()
 {
   if (!mLeadTermKnown) {
-    const_term dummy;
+    NewConstTerm dummy;
     leadTerm(dummy);
   }
   mLeadTermKnown = false;
@@ -212,6 +205,19 @@ void ReducerPack<Q>::removeLeadTerm()
 template<template<typename> class Q>
 void ReducerPack<Q>::resetReducer()
 {
+  class MonomialFree {
+  public:
+    MonomialFree(const PolyRing& ring): mRing(ring) {}
+
+    bool proceed(MultipleWithPos* entry) {
+      entry->destroy(mRing);
+      return true;
+    }
+
+  private:
+    const PolyRing& mRing;
+  };
+
   MonomialFree freeer(mRing);
   mQueue.forAll(freeer);
   mQueue.clear();
diff --git a/src/mathicgb/ReducerPackDedup.cpp b/src/mathicgb/ReducerPackDedup.cpp
index 848168b..5ef4d2e 100644
--- a/src/mathicgb/ReducerPackDedup.cpp
+++ b/src/mathicgb/ReducerPackDedup.cpp
@@ -12,6 +12,18 @@ MATHICGB_NAMESPACE_BEGIN
 
 void reducerPackDedupDependency() {}
 
+/// As ReducerPack, with an extra feature: if two items with the same current
+/// monomial in the queue are compared by the queue, then combine the first
+/// into the second. That way, the second can be removed from the queue.
+/// This requires keeping a linked list with each entry of the other entries
+/// that have been combined into it, since we need to move on to the next term
+/// of all of those entries. This technique further reduces the number of
+/// entries in the queue.
+///
+/// Note that the linked lists are circular to make it fast to append two
+/// linked lists. The trick is that you can combine two distinct circular
+/// lists by swapping the next pointers of any one node in the first list and
+/// of any one node in the second list.
 template<template<typename> class Queue>
 class ReducerPackDedup : public TypicalReducer {
 public:
@@ -22,37 +34,35 @@ public:
     return mQueue.getName() + "-packed";
   }
 
-  virtual void insertTail(const_term multiplier, const Poly* f);
-  virtual void insert(monomial multiplier, const Poly* f);
+  virtual void insertTail(NewConstTerm multiplier, const Poly& f);
+  virtual void insert(ConstMonoRef multiplier, const Poly& f);
 
-  virtual bool leadTerm(const_term& result);
+  virtual bool leadTerm(NewConstTerm& 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);
+    MultipleWithPos(const Poly& poly, NewConstTerm multiple);
 
     Poly::const_iterator pos;
     Poly::const_iterator const end;
-    const_term const multiple;
+    NewTerm multiple;
 
     // invariant: current is the monomial product of multiple.monom 
     // and pos.getMonomial().
-    monomial current;
+    MonoPtr 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 addCurrentCoefficient(const PolyRing& ring, coefficient& coeff);
+    void currentCoefficient(const PolyRing& ring, Coefficient& coeff);
+    void addCurrentCoefficient(const PolyRing& ring, Coefficient& coeff);
     void destroy(const PolyRing& ring);
 
     // Points to a circular list of entries that have the same current
@@ -72,7 +82,7 @@ public:
     typedef MultipleWithPos* Entry;
     Configuration(const PolyRing& ring): DedupConfiguration(ring) {}
     CompareResult compare(const Entry& a, const Entry& b) const {
-      return ring().monomialCompare(a->current, b->current);
+      return ring().monoid().compare(*a->current, *b->current);
     }
     Entry deduplicate(Entry a, Entry b) const {
       a->mergeChains(*b);
@@ -83,7 +93,7 @@ private:
   class MonomialFree;
   
   const PolyRing& mRing;
-  term mLeadTerm;
+  NewTerm mLeadTerm;
   bool mLeadTermKnown;
   Queue<Configuration> mQueue;
   memt::BufferPool mPool;
@@ -92,94 +102,80 @@ private:
 template<template<typename> class Q>
 ReducerPackDedup<Q>::ReducerPackDedup(const PolyRing& ring):
   mRing(ring),
-  mLeadTerm(0, mRing.allocMonomial()),
   mLeadTermKnown(false),
   mQueue(Configuration(ring)),
-  mPool(sizeof(MultipleWithPos)) {
-}
-
-template<template<typename> class Q>
-class ReducerPackDedup<Q>::MonomialFree
+  mPool(sizeof(MultipleWithPos))
 {
-public:
-  MonomialFree(const PolyRing& ring): mRing(ring) {}
-
-  bool proceed(MultipleWithPos* entry)
-  {
-    entry->destroy(mRing);
-    return true;
-  }
-private:
-  const PolyRing& mRing;
-};
+  mLeadTerm.mono = mRing.monoid().alloc().release();
+}
 
 template<template<typename> class Q>
 ReducerPackDedup<Q>::~ReducerPackDedup() {
   resetReducer();
-  mRing.freeMonomial(mLeadTerm.monom);
+  mRing.monoid().freeRaw(*mLeadTerm.mono);
 }
 
 template<template<typename> class Q>
-void ReducerPackDedup<Q>::insertTail(const_term multiple, const Poly* poly) {
-  if (poly->nTerms() <= 1)
+void ReducerPackDedup<Q>::insertTail(NewConstTerm multiple, const Poly& poly) {
+  if (poly.nTerms() <= 1)
     return;
   mLeadTermKnown = false;
 
-  MultipleWithPos* entry =
-    new (mPool.alloc()) MultipleWithPos(*poly, multiple);
+  auto entry = new (mPool.alloc()) MultipleWithPos(poly, multiple);
   ++entry->pos;
-  entry->computeCurrent(poly->ring());
+  entry->computeCurrent(poly.ring());
   mQueue.push(entry);
 }
 
 template<template<typename> class Q>
-void ReducerPackDedup<Q>::insert(monomial multiple, const Poly* poly) {
-  if (poly->isZero())
+void ReducerPackDedup<Q>::insert(ConstMonoRef 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());
+  NewConstTerm termMultiple = {multiple.ptr(), 1};
+  auto entry = new (mPool.alloc()) MultipleWithPos(poly, termMultiple);
+  entry->computeCurrent(poly.ring());
   mQueue.push(entry);
 }
 
 template<template<typename> class Q>
 ReducerPackDedup<Q>::MultipleWithPos::MultipleWithPos(
   const Poly& poly,
-  const_term multipleParam
+  NewConstTerm multipleParam
 ):
   pos(poly.begin()),
   end(poly.end()),
-  multiple(ReducerHelper::allocTermCopy(poly.ring(), multipleParam)),
-  current(poly.ring().allocMonomial()),
+  current(poly.ring().monoid().alloc().release()),
   chain(this)
-{}
+{
+  multiple.mono = poly.ring().monoid().alloc().release();
+  poly.ring().monoid().copy(*multipleParam.mono, *multiple.mono);
+  multiple.coef = multipleParam.coef;
+}
 
 template<template<typename> class Q>
-void ReducerPackDedup<Q>::MultipleWithPos::computeCurrent
-  (const PolyRing& ring)
-{
-  ring.monomialMult(multiple.monom, pos.getMonomial(), current);  
+void ReducerPackDedup<Q>::MultipleWithPos::computeCurrent(
+  const PolyRing& ring
+) {
+  ring.monoid().multiply(*multiple.mono, pos.getMonomial(), *current);
 }
 
 template<template<typename> class Q>
 void ReducerPackDedup<Q>::MultipleWithPos::currentCoefficient(
   const PolyRing& ring,
-  coefficient& coeff
+  Coefficient& coef
 ) {
-  ring.coefficientMult(multiple.coeff, pos.getCoefficient(), coeff);
+  ring.coefficientMult(multiple.coef, pos.getCoefficient(), coef);
 }
 
 template<template<typename> class Q>
 void ReducerPackDedup<Q>::MultipleWithPos::addCurrentCoefficient(
   const PolyRing& ring,
-  coefficient& coeff
+  Coefficient& coeff
 ) {
-  coefficient tmp;
-  ring.coefficientMult(multiple.coeff, pos.getCoefficient(), tmp);
+  Coefficient tmp;
+  ring.coefficientMult(multiple.coef, pos.getCoefficient(), tmp);
   ring.coefficientAddTo(coeff, tmp);
 }
 
@@ -187,16 +183,15 @@ template<template<typename> class Q>
 void ReducerPackDedup<Q>::MultipleWithPos::destroy(const PolyRing& ring) {
   MultipleWithPos* entry = this;
   do {
-    ring.freeMonomial(entry->current);
-    ConstMonomial& monom = const_cast<ConstMonomial&>(entry->multiple.monom);
-    ring.freeMonomial(monom.castAwayConst());
+    ring.monoid().freeRaw(*entry->current);
+    ring.monoid().freeRaw(*entry->multiple.mono);
     MultipleWithPos* next = entry->chain;
     MATHICGB_ASSERT(next != 0);
 
     // 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.
+    // has to be called since it takes an iterator off the list. There were
+    // memory corruption problems in debug mode on MSVC before doing this.
     entry->~MultipleWithPos();
 
     entry = next;
@@ -204,81 +199,78 @@ void ReducerPackDedup<Q>::MultipleWithPos::destroy(const PolyRing& ring) {
 }
 
 template<template<typename> class Q>
-bool ReducerPackDedup<Q>::leadTerm(const_term& result) {
-  if (mLeadTermKnown) {
-    result = mLeadTerm;
-    return true;
-  }
-
-  do {
-    if (mQueue.empty())
-      return false;
-    MultipleWithPos* entry = mQueue.top();
-    entry->currentCoefficient(mRing, mLeadTerm.coeff);
-    while (true) {
-      // store the chained elements
-      MultipleWithPos* const chainBegin = entry->chain;
-      MultipleWithPos* const chainEnd = entry; // the list is circular
-      entry->chain = entry; // detach any chained elements
-
-      // handle the entry itself
-      mLeadTerm.monom.swap(entry->current);
-      ++entry->pos;
-      if (entry->pos == entry->end) {
-        mQueue.pop();
-        entry->destroy(mRing);
-        mPool.free(entry);
-      } else {
-        entry->computeCurrent(mRing);
-        // Inserted spans must be in descending order
-        MATHICGB_ASSERT(mQueue.getConfiguration().ring().
-          monomialLT(entry->current, mLeadTerm.monom));
-        mQueue.decreaseTop(entry);
-      }
-
-      // handle any chained elements
-      MultipleWithPos* chain = chainBegin;
-      while (chain != chainEnd) {
-        MATHICGB_ASSERT(chain != 0);
-        MATHICGB_ASSERT(mRing.monomialEQ(chain->current, mLeadTerm.monom));
-
-        MultipleWithPos* const next = chain->chain;
-        chain->chain = chain; // detach from remaining chained elements
-
-        chain->addCurrentCoefficient(mRing, mLeadTerm.coeff);
-        ++chain->pos;
-        if (chain->pos == chain->end) {
-          chain->destroy(mRing);
-          mPool.free(chain);
+bool ReducerPackDedup<Q>::leadTerm(NewConstTerm& result) {
+  if (!mLeadTermKnown) {
+    do {
+      if (mQueue.empty())
+        return false;
+      auto entry = mQueue.top();
+      entry->currentCoefficient(mRing, mLeadTerm.coef);
+      while (true) {
+        // store the chained elements
+        const auto chainBegin = entry->chain;
+        const auto chainEnd = entry; // the list is circular
+        entry->chain = entry; // detach any chained elements
+
+        // handle the entry itself
+        std::swap(mLeadTerm.mono, entry->current);
+        ++entry->pos;
+        if (entry->pos == entry->end) {
+          mQueue.pop();
+          entry->destroy(mRing);
+          mPool.free(entry);
         } else {
-          chain->computeCurrent(mRing);
+          entry->computeCurrent(mRing);
           // Inserted spans must be in descending order
           MATHICGB_ASSERT(mQueue.getConfiguration().ring().
-            monomialLT(chain->current, mLeadTerm.monom));
-          mQueue.push(chain);
+            monoid().lessThan(*entry->current, *mLeadTerm.mono));
+          mQueue.decreaseTop(entry);
+        }
+
+        // handle any chained elements
+        auto chain = chainBegin;
+        while (chain != chainEnd) {
+          MATHICGB_ASSERT(chain != 0);
+          MATHICGB_ASSERT(mRing.monoid().equal(*chain->current, *mLeadTerm.mono));
+
+          const auto next = chain->chain;
+          chain->chain = chain; // detach from remaining chained elements
+
+          chain->addCurrentCoefficient(mRing, mLeadTerm.coef);
+          ++chain->pos;
+          if (chain->pos == chain->end) {
+            chain->destroy(mRing);
+            mPool.free(chain);
+          } else {
+            chain->computeCurrent(mRing);
+            // Inserted spans must be in descending order
+            MATHICGB_ASSERT(mQueue.getConfiguration().ring().
+              monoid().lessThan(*chain->current, *mLeadTerm.mono));
+            mQueue.push(chain);
+          }
+          chain = next;
         }
-        chain = next;
-      }
       
-      if (mQueue.empty())
-        break;
+        if (mQueue.empty())
+          break;
       
-      entry = mQueue.top();
-      if (!mRing.monomialEQ(entry->current, mLeadTerm.monom))
-        break;
-      entry->addCurrentCoefficient(mRing, mLeadTerm.coeff);
-    }
-  } while (mRing.coefficientIsZero(mLeadTerm.coeff));
+        entry = mQueue.top();
+        if (!mRing.monoid().equal(*entry->current, *mLeadTerm.mono))
+          break;
+        entry->addCurrentCoefficient(mRing, mLeadTerm.coef);
+      }
+    } while (mRing.coefficientIsZero(mLeadTerm.coef));
+    mLeadTermKnown = true;
+  }
 
   result = mLeadTerm;
-  mLeadTermKnown = true;
   return true;
 }
 
 template<template<typename> class Q>
 void ReducerPackDedup<Q>::removeLeadTerm() {
   if (!mLeadTermKnown) {
-    const_term dummy;
+    NewConstTerm dummy;
     leadTerm(dummy);
   }
   mLeadTermKnown = false;
@@ -286,6 +278,19 @@ void ReducerPackDedup<Q>::removeLeadTerm() {
 
 template<template<typename> class Q>
 void ReducerPackDedup<Q>::resetReducer() {
+  class MonomialFree {
+  public:
+    MonomialFree(const PolyRing& ring): mRing(ring) {}
+
+    bool proceed(MultipleWithPos* entry) {
+      entry->destroy(mRing);
+      return true;
+    }
+
+  private:
+    const PolyRing& mRing;
+  };
+
   MonomialFree freeer(mRing);
   mQueue.forAll(freeer);
   mQueue.clear();
diff --git a/src/mathicgb/TypicalReducer.cpp b/src/mathicgb/TypicalReducer.cpp
index c0ca77d..53eb20b 100755
--- a/src/mathicgb/TypicalReducer.cpp
+++ b/src/mathicgb/TypicalReducer.cpp
@@ -24,18 +24,19 @@ size_t TypicalReducer::getMemoryUse() const {
 }
 
 std::unique_ptr<Poly> TypicalReducer::regularReduce(
-  const_monomial sig,
-  const_monomial multiple,
+  ConstMonoRef sig,
+  ConstMonoRef multiple,
   size_t basisElement,
   const SigPolyBasis& basis)
 {
   const PolyRing& ring = basis.ring();
+  const auto& monoid = ring.monoid();
 
   monomial tproduct = ring.allocMonomial(mArena);
   monomial u = ring.allocMonomial(mArena);
-  ring.monomialMult(multiple, basis.getLeadMonomial(basisElement), tproduct);
+  monoid.multiply(multiple, basis.getLeadMonomial(basisElement), tproduct);
 
-  size_t reducer = basis.regularReducer(sig, tproduct);
+  size_t reducer = basis.regularReducer(Monoid::toOld(sig), tproduct);
   if (reducer == static_cast<size_t>(-1)) {
     mArena.freeAllAllocs();
     return nullptr; // singular reduction: no regular top reduction possible
@@ -45,7 +46,7 @@ std::unique_ptr<Poly> TypicalReducer::regularReduce(
 
   coefficient coef;
   ring.coefficientSet(coef, 1);
-  insertTail(const_term(coef, multiple), &basis.poly(basisElement));
+  insertTail(const_term(coef, Monoid::toOld(multiple)), &basis.poly(basisElement));
 
   MATHICGB_ASSERT(ring.coefficientIsOne(basis.getLeadCoefficient(reducer)));
   ring.coefficientFromInt(coef, -1);
@@ -57,7 +58,7 @@ std::unique_ptr<Poly> TypicalReducer::regularReduce(
   unsigned long long steps = 2; // number of steps in this reduction
   for (const_term v; leadTerm(v);) {
     MATHICGB_ASSERT(v.coeff != 0);
-    reducer = basis.regularReducer(sig, v.monom);
+    reducer = basis.regularReducer(Monoid::toOld(sig), v.monom);
     if (reducer == static_cast<size_t>(-1)) { // no reducer found
       result->appendTerm(v.coeff, v.monom);
       removeLeadTerm();
diff --git a/src/mathicgb/TypicalReducer.hpp b/src/mathicgb/TypicalReducer.hpp
index 19a1228..5e6c1fb 100755
--- a/src/mathicgb/TypicalReducer.hpp
+++ b/src/mathicgb/TypicalReducer.hpp
@@ -26,8 +26,8 @@ public:
   virtual unsigned int preferredSetSize() const;
 
   virtual std::unique_ptr<Poly> regularReduce(
-    const_monomial sig,
-    const_monomial multiple,
+    ConstMonoRef sig,
+    ConstMonoRef multiple,
     size_t basisElement,
     const SigPolyBasis& basis
   );
@@ -58,9 +58,32 @@ public:
 protected:
   // These are the methods that sub-classes define in order to carry
   // out sub-steps in the reduction.
-  virtual void insertTail(const_term multiplier, const Poly *f) = 0;
-  virtual void insert(monomial multiplier, const Poly *f) = 0;
-  virtual bool leadTerm(const_term& result) = 0;
+  virtual void insertTail(const_term multiplier, const Poly* f) {
+    MATHICGB_ASSERT(f != 0);
+    NewConstTerm t = {multiplier.monom, multiplier.coeff};
+    insertTail(t, *f);
+  }
+
+  virtual void insert(monomial multiplier, const Poly* f) {
+    MATHICGB_ASSERT(f != 0);
+    ConstMonoRef mono = multiplier;
+    insert(mono, *f);
+  }
+
+  virtual bool leadTerm(const_term& result) {
+    NewConstTerm t;
+    auto hasLead = leadTerm(t);
+    if (hasLead) {
+      result.monom = Monoid::toOld(*t.mono);
+      result.coeff = t.coef;
+    }
+    return hasLead;
+  }
+
+  virtual void insertTail(NewConstTerm multiplier, const Poly& f) {}
+  virtual void insert(ConstMonoRef multiplier, const Poly& f) {}
+  virtual bool leadTerm(NewConstTerm& lead) {return false;}
+
   virtual void removeLeadTerm() = 0;
   virtual void resetReducer() = 0;
 

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