[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