[mathicgb] 61/393: Added a MonomialMap template. This removes a lot of complexity and ifdef'ing from QuadMatrixBuilder. Also, I expect to use this outside of QuadMatrixBuilder in future.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:32 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 c4cf0ff9a6d2229a67520b3731ff0f7bb7f6d20c
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Fri Oct 12 22:28:50 2012 +0200

    Added a MonomialMap template. This removes a lot of complexity and ifdef'ing from QuadMatrixBuilder. Also, I expect to use this outside of QuadMatrixBuilder in future.
---
 Makefile.am                                        |   2 +-
 build/vs12/mathicgb-lib/mathicgb-lib.vcxproj       |   1 +
 .../vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters |   3 +
 src/mathicgb/F4MatrixBuilder.cpp                   |   4 +-
 src/mathicgb/MonomialMap.hpp                       | 182 +++++++++++++++++++++
 src/mathicgb/QuadMatrixBuilder.cpp                 |  20 +--
 src/mathicgb/QuadMatrixBuilder.hpp                 | 125 ++------------
 src/test/QuadMatrixBuilder.cpp                     |  14 +-
 8 files changed, 224 insertions(+), 127 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 32c45f0..1e0ed08 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -61,7 +61,7 @@ libmathicgb_la_SOURCES = src/mathicgb/BjarkeGeobucket2.cpp				\
   src/mathicgb/F4Reducer.cpp src/mathicgb/F4MatrixBuilder.hpp			\
   src/mathicgb/F4MatrixBuilder.cpp src/mathicgb/QuadMatrix.hpp			\
   src/mathicgb/QuadMatrix.cpp src/mathicgb/F4MatrixReducer.cpp			\
-  src/mathicgb/F4MatrixReducer.hpp
+  src/mathicgb/F4MatrixReducer.hpp src/mathicgb/MonomialMap.hpp
 
 # When making a distribution file, Automake knows to include all files
 # that are necessary to build the project. EXTRA_DIST specifies files
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
index d5a7c5e..d853efd 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
@@ -452,6 +452,7 @@
     <ClInclude Include="..\..\..\src\mathicgb\io-util.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\KoszulQueue.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\MonomialHashTable.hpp" />
+    <ClInclude Include="..\..\..\src\mathicgb\MonomialMap.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\MonTableDivList.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\MonTableKDTree.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\MonTableNaive.hpp" />
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
index a034b12..84c8e87 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
@@ -275,5 +275,8 @@
     <ClInclude Include="..\..\..\src\mathicgb\TypicalReducer.hpp">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\src\mathicgb\MonomialMap.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/mathicgb/F4MatrixBuilder.cpp b/src/mathicgb/F4MatrixBuilder.cpp
index 2828aeb..1c4a629 100755
--- a/src/mathicgb/F4MatrixBuilder.cpp
+++ b/src/mathicgb/F4MatrixBuilder.cpp
@@ -174,7 +174,7 @@ F4MatrixBuilder::createOrFindColumnOf(const_monomial mono) {
   // mono did not already have a column so look for a reducer
   size_t reducerIndex = mBasis.divisor(mono);
   if (reducerIndex == static_cast<size_t>(-1))
-    return LeftRightColIndex(mBuilder.createColumnRight(mono), false);
+    return mBuilder.createColumnRight(mono);
 
   // schedule the reducer to be added as a row
   RowTask task;
@@ -186,7 +186,7 @@ F4MatrixBuilder::createOrFindColumnOf(const_monomial mono) {
   MATHICGB_ASSERT(ring().hashValid(task.multiple));
   mTodo.push_back(task);
 
-  return LeftRightColIndex(mBuilder.createColumnLeft(mono), true);
+  return mBuilder.createColumnLeft(mono);
 }
 
 void F4MatrixBuilder::appendRowTop(const_monomial multiple, const Poly& poly) {
diff --git a/src/mathicgb/MonomialMap.hpp b/src/mathicgb/MonomialMap.hpp
new file mode 100755
index 0000000..22f9678
--- /dev/null
+++ b/src/mathicgb/MonomialMap.hpp
@@ -0,0 +1,182 @@
+#ifndef MATHICGB_MONOMIAL_MAP_GUARD
+#define MATHICGB_MONOMIAL_MAP_GUARD
+
+#include "PolyRing.hpp"
+#include <limits>
+
+#define MATHICGB_USE_STD_HASH
+
+#ifdef MATHICGB_USE_STD_HASH
+#include <unordered_map>
+#else
+#include <map>
+#endif
+
+/** A mapping from monomials to MapToType. The interface is the same as
+  for STL maps. The interface is not complete. Add methods you need when
+  you need it.
+*/
+template<class MapToType>
+class MonomialMap;
+
+namespace MonomialMapInternal {
+  // The map type MapClass is defined here. This is here in
+  // this namespace to avoid cluttering the class definition with
+  // a lot of ifdef's.
+
+#ifndef MATHICGB_USE_STD_HASH
+  /// We need SOME ordering to make std::map work.
+  class ArbitraryOrdering {
+  public:
+    ArbitraryOrdering(const PolyRing& ring): mRing(ring) {}
+    bool operator()(const_monomial a, const_monomial b) const {
+      return mRing.monomialLT(a, b);
+    }
+    const PolyRing& ring() const {return mRing;}
+
+  private:
+    const PolyRing& mRing;
+  };
+
+  template<class MTT>
+  class MapClass {
+  public:
+    typedef std::map<const_monomial, MTT, ArbitraryOrdering> Map;
+
+    MapClass(const PolyRing& ring): mMap(ArbitraryOrdering(ring)) {}
+    Map& map() {return mMap;}
+    const Map& map() const {return mMap;}
+    const PolyRing& ring() const {return mMap.key_cmp().ring();}
+
+  private:
+    Map mMap;
+  };
+
+#else
+  class Hash {
+  public:
+    Hash(const PolyRing& ring): mRing(ring) {}
+    size_t operator()(const_monomial m) const {
+      MATHICGB_ASSERT(mRing.hashValid(m));
+      return mRing.monomialHashValue(m);
+    }
+    const PolyRing& ring() const {return mRing;}
+
+  private:
+    const PolyRing& mRing;
+  };
+
+  class Equal {
+  public:
+    Equal(const PolyRing& ring): mRing(ring) {}
+    size_t operator()(const_monomial a, const_monomial b) const {
+      return mRing.monomialEQ(a, b);
+    }
+    const PolyRing& ring() const {return mRing;}
+
+  private:
+    const PolyRing& mRing;
+  };
+
+  // This has to be a template to support rebind().
+  template<class T>
+  class TemplateHashAllocator {
+  public:
+    typedef T value_type;
+    typedef T* pointer;
+    typedef T& reference;
+    typedef const T* const_pointer;
+    typedef const T& const_reference;
+    typedef ::size_t size_type;
+    typedef ::ptrdiff_t difference_type;
+
+    template<class T2>
+    struct rebind {
+      typedef TemplateHashAllocator<T2> other;
+    };
+
+    TemplateHashAllocator() {}
+    TemplateHashAllocator(memt::Arena& arena): mArena(arena) {}
+    template<class X>
+    TemplateHashAllocator(const TemplateHashAllocator<X>& a):
+      mArena(a.arena()) {}
+    TemplateHashAllocator(const TemplateHashAllocator<T>& a):
+      mArena(a.arena()) {}
+
+    pointer address(reference x) {return &x;}
+    const_pointer address(const_reference x) const {return &x;}
+    pointer allocate(size_type n, void* hint = 0) {
+      return static_cast<pointer>(mArena.alloc(sizeof(T) * n));
+    }
+    void deallocate(pointer p, size_t n) {}
+    size_type max_size() const {return std::numeric_limits<size_type>::max();}
+    void construct(pointer p, const_reference val) {new (p) T(val);}
+    void destroy(pointer p) {p->~T();}
+    memt::Arena& arena() const {return mArena;}
+
+  private:
+    mutable memt::Arena& mArena;
+  };
+  template<class MTT>
+  class MapClass {
+  public:
+    typedef TemplateHashAllocator<std::pair<const const_monomial, MTT>>
+      HashAllocator;
+    typedef std::unordered_map<const_monomial, MTT, Hash, Equal, HashAllocator>
+      Map;
+
+    MapClass(const PolyRing& ring):
+      mArena(),
+      mMap(100, Hash(ring), Equal(ring), HashAllocator(mArena))
+    {
+      mMap.max_load_factor(0.3f);
+    }
+
+    Map& map() {return mMap;}
+    const Map& map() const {return mMap;}
+    const PolyRing& ring() const {return mMap.key_eq().ring();}
+
+  private:
+    memt::Arena mArena;
+    Map mMap;
+  };
+#endif
+}
+
+template<class MTT>
+class MonomialMap {
+public:
+  typedef MTT mapped_type;
+  typedef MonomialMapInternal::MapClass<MTT> MapType;
+
+  typedef typename MapType::Map::iterator iterator;
+  typedef typename MapType::Map::const_iterator const_iterator;
+  typedef typename MapType::Map::value_type value_type;
+
+  MonomialMap(const PolyRing& ring): mMap(ring) {}
+
+  iterator begin() {return map().begin();}
+  const_iterator begin() const {return map().begin();}
+  iterator end() {return map().end();}
+  const_iterator end() const {return map().end();}
+  iterator find(const_monomial m) {return map().find(m);}
+  const_iterator find(const_monomial m) const {return map().find(m);}
+
+  size_t size() const {return map().size();}
+  void clear() {map().clear();}
+  std::pair<iterator, bool> insert(const value_type& val) {
+    return map().insert(val);
+  }
+
+  inline const PolyRing& ring() const {return mMap.ring();}
+
+private:
+  typename MapType::Map& map() {return mMap.map();}
+  const typename MapType::Map& map() const {return mMap.map();}
+
+  MapType mMap;
+};
+
+
+
+#endif
diff --git a/src/mathicgb/QuadMatrixBuilder.cpp b/src/mathicgb/QuadMatrixBuilder.cpp
index a70c0f2..7c20002 100755
--- a/src/mathicgb/QuadMatrixBuilder.cpp
+++ b/src/mathicgb/QuadMatrixBuilder.cpp
@@ -7,15 +7,7 @@
 #include <sstream>
 
 QuadMatrixBuilder::QuadMatrixBuilder(const PolyRing& ring):
-#ifndef MATHICGB_USE_QUADMATRIX_STD_HASH
-  mMonomialToCol(ArbitraryOrdering(ring)) {}
-#else
-mMonomialToColArena(),
-  mMonomialToCol(100, Hash(ring), Equal(ring),
-                 SpecificHashAllocator(mMonomialToColArena)) {
-  mMonomialToCol.max_load_factor(0.3f);
-}
-#endif
+  mMonomialToCol(ring) {}
 
 namespace {
   /// Creates a column and updates the associated data structures that
@@ -24,7 +16,7 @@ namespace {
   /// template in order to avoid referring to private types of
   /// QuadMatrixBuilder.
   template<class ToMono, class ToCol>
-  QuadMatrixBuilder::ColIndex createCol
+  QuadMatrixBuilder::LeftRightColIndex createCol
   (const_monomial mono,
    SparseMatrix& top,
    SparseMatrix& bottom,
@@ -41,7 +33,7 @@ namespace {
     if (colCount == std::numeric_limits<QuadMatrixBuilder::ColIndex>::max())
       throw std::overflow_error("Too many columns in QuadMatrixBuilder");
 
-    toMonomial.push_back(0); // allocate memory ahead of time to avoid bad_alloc
+    toMonomial.push_back(0); // allocate memory now to avoid bad_alloc later
     monomial copied = ring.allocMonomial();
     ring.monomialCopy(mono, copied);
     try {
@@ -57,11 +49,11 @@ namespace {
 
     top.ensureAtLeastThisManyColumns(colCount + 1);
     bottom.ensureAtLeastThisManyColumns(colCount + 1);
-    return colCount;
+    return QuadMatrixBuilder::LeftRightColIndex(colCount, left);
   }
 }
 
-QuadMatrixBuilder::ColIndex QuadMatrixBuilder::createColumnLeft
+QuadMatrixBuilder::LeftRightColIndex QuadMatrixBuilder::createColumnLeft
 (const_monomial monomialToBeCopied) {
   return createCol
     (monomialToBeCopied,
@@ -76,7 +68,7 @@ QuadMatrixBuilder::ColIndex QuadMatrixBuilder::createColumnLeft
     (findColumn(monomialToBeCopied).leftIndex() == leftColCount() - 1);
 }
 
-QuadMatrixBuilder::ColIndex QuadMatrixBuilder::createColumnRight
+QuadMatrixBuilder::LeftRightColIndex QuadMatrixBuilder::createColumnRight
 (const_monomial monomialToBeCopied) {
   return createCol
     (monomialToBeCopied,
diff --git a/src/mathicgb/QuadMatrixBuilder.hpp b/src/mathicgb/QuadMatrixBuilder.hpp
index 289325f..b36aa8e 100755
--- a/src/mathicgb/QuadMatrixBuilder.hpp
+++ b/src/mathicgb/QuadMatrixBuilder.hpp
@@ -3,6 +3,8 @@
 
 #define MATHICGB_USE_QUADMATRIX_STD_HASH
 
+#include "MonomialMap.hpp"
+
 #include "SparseMatrix.hpp"
 #include "PolyRing.hpp"
 #include <vector>
@@ -52,7 +54,7 @@ class QuadMatrixBuilder {
     }
 
     /// Use leftIndex() or rightIndex() instead if you know what side
-    /// you are expecting, as check the side in assert mode.
+    /// you are expecting, as this does an assert on your expectation.
     ColIndex index() const {
       MATHICGB_ASSERT(valid());
       return mRawIndex;
@@ -132,20 +134,22 @@ class QuadMatrixBuilder {
   }
 
   // *** Creating and reordering columns
-  // Unlike the interface for SparseMatrix, here you have to create
-  // columns before you can append entries in those columns. All
-  // passed in monomials are copied so that ownership of the memory is
-  // not taken over.
+  // You have to create columns before you can append entries in those columns.
+  // All passed in monomials are copied so that ownership of the memory is
+  // not taken over. The creation methods return a LeftRightColIndex instead
+  // of just a ColIndex to allow more of a chance for asserts to catch errors
+  // and to avoid the need for the client to immediately construct a
+  // LeftRightColIndex based on the return value.
 
   /** Creates a new column associated to the monomial
     monomialToBeCopied to the left matrices. There must not already
     exist a column for this monomial on the left or on the right. */
-  ColIndex createColumnLeft(const_monomial monomialToBeCopied);
+  LeftRightColIndex createColumnLeft(const_monomial monomialToBeCopied);
 
   /** Creates a new column associated to the monomial monomialToBeCopied
     to the right matrices. There must not already exist a column for
     this monomial on the left or on the right. */
-  ColIndex createColumnRight(const_monomial monomialToBeCopied);
+  LeftRightColIndex createColumnRight(const_monomial monomialToBeCopied);
 
   /** Sorts the left columns to be decreasing with respect to
     order. Also updates the column indices already in the matrix to
@@ -164,7 +168,7 @@ class QuadMatrixBuilder {
   // left and right side. Returns an invalid index if no such column
   // exists.
   LeftRightColIndex findColumn(const_monomial findThis) const {
-    MonomialToColType::const_iterator it = mMonomialToCol.find(findThis);
+    auto it = mMonomialToCol.find(findThis);
     if (it != mMonomialToCol.end())
       return it->second;
     else
@@ -200,16 +204,7 @@ class QuadMatrixBuilder {
   // String representation intended for debugging.
   std::string toString() const;
 
-  const PolyRing& ring() const {
-    // The key comparer object already has a ring reference - we might
-    // as well use that one instead of adding another reference to
-    // this object.
-#ifndef MATHICGB_USE_QUADMATRIX_STD_HASH
-    return mMonomialToCol.key_comp().ring();
-#else
-    return mMonomialToCol.key_eq().ring();
-#endif
-  }
+  const PolyRing& ring() const {return mMonomialToCol.ring();}
 
   ColIndex leftColCount() const {
     MATHICGB_ASSERT(topLeft().colCount() == bottomLeft().colCount());
@@ -226,98 +221,12 @@ class QuadMatrixBuilder {
   void buildMatrixAndClear(QuadMatrix& out);
 
 private:
-  // Store the monomials for each left and right column respectivewy.
   typedef std::vector<monomial> MonomialsType;
-  MonomialsType mMonomialsLeft;
-  MonomialsType mMonomialsRight;
-
-#ifndef MATHICGB_USE_QUADMATRIX_STD_HASH
-  /// We need SOME ordering to make std::map work.
-  class ArbitraryOrdering {
-  public:
-    ArbitraryOrdering(const PolyRing& ring): mRing(ring) {}
-    bool operator()(const_monomial a, const_monomial b) const {
-      return mRing.monomialLT(a, b);
-    }
-    const PolyRing& ring() const {return mRing;}
-
-  private:
-    const PolyRing& mRing;
-  };
-  /// Allows fast determination of which column has a given monomial.
-  typedef std::map<const_monomial, LeftRightColIndex, ArbitraryOrdering>
-    MonomialToColType;
-  MonomialToColType mMonomialToCol;
-#else
-  struct Hash {
-  public:
-    Hash(const PolyRing& ring): mRing(ring) {}
-    size_t operator()(const_monomial m) const {
-      MATHICGB_ASSERT(mRing.hashValid(m));
-      return mRing.monomialHashValue(m);
-    }
-    const PolyRing& ring() const {return mRing;}
-
-  private:
-    const PolyRing& mRing;
-  };
-  struct Equal {
-  public:
-    Equal(const PolyRing& ring): mRing(ring) {}
-    size_t operator()(const_monomial a, const_monomial b) const {
-      return mRing.monomialEQ(a, b);
-    }
-    const PolyRing& ring() const {return mRing;}
+  MonomialsType mMonomialsLeft; /// stores one monomial per left column
+  MonomialsType mMonomialsRight; /// stores one monomial per right column
 
-  private:
-    const PolyRing& mRing;
-  };
-
-  template<class T>
-  class HashAllocator {
-  public:
-    HashAllocator(memt::Arena& arena): mArena(arena) {}
-
-    typedef T value_type;
-    typedef T* pointer;
-    typedef T& reference;
-    typedef const T* const_pointer;
-    typedef const T& const_reference;
-    typedef ::size_t size_type;
-    typedef ::ptrdiff_t difference_type;
-
-    template<class T2>
-    struct rebind {
-      typedef HashAllocator<T2> other;
-    };
-
-    HashAllocator() {}
-    template<class X>
-    HashAllocator(const HashAllocator<X>& a): mArena(a.arena()) {}
-    HashAllocator(const HashAllocator<T>& a): mArena(a.arena()) {}
-
-    pointer address(reference x) {return &x;}
-    const_pointer address(const_reference x) const {return &x;}
-    pointer allocate(size_type n, void* hint = 0) {
-      return static_cast<pointer>(mArena.alloc(sizeof(T) * n));
-    }
-    void deallocate(pointer p, size_t n) {}
-    size_type max_size() const {return std::numeric_limits<size_type>::max();}
-    void construct(pointer p, const_reference val) {new (p) T(val);}
-    void destroy(pointer p) {p->~T();}
-    memt::Arena& arena() const {return mArena;}
-
-  private:
-    mutable memt::Arena& mArena;
-  };
-  typedef HashAllocator<std::pair<const const_monomial, LeftRightColIndex> >
-    SpecificHashAllocator;
-
-  typedef std::unordered_map<const_monomial, LeftRightColIndex, Hash, Equal,
-                             SpecificHashAllocator> MonomialToColType;
-  memt::Arena mMonomialToColArena;
-  MonomialToColType mMonomialToCol;
-#endif
+  /// Used for fast determination of which column has a given monomial.
+  MonomialMap<LeftRightColIndex> mMonomialToCol;
 
   SparseMatrix mTopLeft;
   SparseMatrix mTopRight;
diff --git a/src/test/QuadMatrixBuilder.cpp b/src/test/QuadMatrixBuilder.cpp
index 7b42578..7ce69c7 100755
--- a/src/test/QuadMatrixBuilder.cpp
+++ b/src/test/QuadMatrixBuilder.cpp
@@ -25,7 +25,12 @@ namespace {
       p.parseDoNotOrder(in);
       size_t colCount = 0;
       for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
-        QuadMatrixBuilder::ColIndex col = b.createColumnLeft(it.getMonomial());
+        QuadMatrixBuilder::LeftRightColIndex lrCol =
+          b.createColumnLeft(it.getMonomial());
+        ASSERT_TRUE(lrCol.left());
+        ASSERT_FALSE(lrCol.right());
+        auto col = lrCol.leftIndex();
+        ASSERT_EQ(col, lrCol.index());
         ASSERT_EQ(colCount, col);
         ++colCount;
         // not equal as pointers
@@ -42,7 +47,12 @@ namespace {
       p.parseDoNotOrder(in);
       size_t colCount = 0;
       for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
-        QuadMatrixBuilder::ColIndex col = b.createColumnRight(it.getMonomial());
+        QuadMatrixBuilder::LeftRightColIndex lrCol =
+          b.createColumnRight(it.getMonomial());
+        ASSERT_TRUE(lrCol.right());
+        ASSERT_FALSE(lrCol.left());
+        auto col = lrCol.rightIndex();
+        ASSERT_EQ(col, lrCol.index());
         ASSERT_EQ(colCount, col);
         ++colCount;
         // not equal as pointers

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