[mathicgb] 206/393: Added hash functionality to MonoMonoid. Still need more tests.
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:01 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 b80fef20b72a720e792a712cac6d1589192a5a7b
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date: Fri Mar 29 00:44:56 2013 +0100
Added hash functionality to MonoMonoid. Still need more tests.
---
src/mathicgb/MonoMonoid.hpp | 147 ++++++++++++++++++++++++++++++++++++--------
src/test/MonoMonoid.cpp | 1 +
2 files changed, 124 insertions(+), 24 deletions(-)
diff --git a/src/mathicgb/MonoMonoid.hpp b/src/mathicgb/MonoMonoid.hpp
index 5130527..6fea03e 100755
--- a/src/mathicgb/MonoMonoid.hpp
+++ b/src/mathicgb/MonoMonoid.hpp
@@ -7,6 +7,7 @@
#include <type_traits>
#include <istream>
#include <ostream>
+#include <cstdlib>
#include <mathic.h>
/// Implements the monoid of (monic) monomials with integer
@@ -34,7 +35,7 @@ public:
typedef typename std::make_unsigned<E>::type Component;
/// Type used to store hash values of monomials.
- //typedef typename std::make_unsigned<E>::type HashValue;
+ typedef typename std::make_unsigned<E>::type HashValue;
/// Iterator for the exponents in a monomial.
typedef const Exponent* const_iterator;
@@ -93,8 +94,13 @@ public:
mVarCount(varCount),
mOrderEntryCount(1),
mOrderIndexBegin(1 + varCount),
- mOrderIndexEnd(2 + varCount)
- {}
+ mOrderIndexEnd(2 + varCount),
+ mHashCoefficients(varCount)
+ {
+ std::srand(0); // To use the same hash coefficients every time.
+ for (VarIndex var = 0; var < varCount; ++var)
+ mHashCoefficients[var] = static_cast<HashValue>(std::rand());
+ }
bool operator==(const MonoMonoid& monoid) const {
return this == &monoid;
@@ -127,6 +133,29 @@ public:
return begin(mono)[var];
}
+ /// Returns the component of the monomial. Monomials not from a
+ /// module have component zero. In a module mono*e_i has component
+ /// i. @todo: Have different monoids for module monomials and
+ /// monomials and only offer this method for the module monomials.
+ Component component(ConstMonoRef mono) const {
+ return mono.rawPtr()[componentIndex()];
+ }
+
+ /// Returns a hash value for the monomial. These are not guaranteed
+ /// to be unique.
+ HashValue hash(ConstMonoRef mono) const {
+ MATHICGB_ASSERT(debugHashValid(mono));
+ return static_cast<HashValue>(rawPtr(mono)[hashIndex()]);
+ }
+
+ /// Returns the hash of the product of a and b.
+ HashValue hashOfProduct(ConstMonoRef a, ConstMonoRef b) const {
+ // See computeHash() for an explanation of all the casts.
+ const auto hashA = static_cast<HashValue>(hash(a));
+ const auto hashB = static_cast<HashValue>(hash(b));
+ return static_cast<HashValue>(static_cast<Exponent>(hashA + hashB));
+ }
+
bool equal(ConstMonoRef a, ConstMonoRef b) const {
return std::equal(begin(a), end(a), begin(b));
}
@@ -138,10 +167,6 @@ public:
return std::all_of(begin(mono), end(mono), [](Exponent e) {return e == 0;});
}
- Component component(ConstMonoRef mono) const {
- return *(mono.rawPtr() + componentIndex());
- }
-
// Graded reverse lexicographic order. The grading is total degree.
CompareResult compare(ConstMonoRef a, ConstMonoRef b) const {
MATHICGB_ASSERT(debugOrderValid(a));
@@ -166,24 +191,38 @@ public:
// *** Monomial mutating computations
void copy(ConstMonoRef from, MonoRef to) const {
+ MATHICGB_ASSERT(debugValid(from));
std::copy_n(from.rawPtr(), entryCount(), to.rawPtr());
+ MATHICGB_ASSERT(debugValid(to));
}
- void setExponent(const VarIndex var, const Exponent e, MonoRef mono) const {
+ void setExponent(
+ const VarIndex var,
+ const Exponent newExponent,
+ MonoRef mono
+ ) const {
MATHICGB_ASSERT(var < varCount());
- auto& exponent = (rawPtr(mono) + exponentsIndexBegin())[var];
+ auto& exponent = rawPtr(mono)[exponentsIndexBegin() + var];
const auto oldExponent = exponent;
- exponent = e;
- updateOrderInformation(var, oldExponent, exponent, mono);
+ exponent = newExponent;
+
+ updateOrderData(var, oldExponent, newExponent, mono);
+ updateHashExponent(var, oldExponent, newExponent, mono);
+ MATHICGB_ASSERT(debugValid(mono));
}
void setIdentity(MonoRef mono) const {
- std::fill_n(mono.rawPtr(), entryCount(), static_cast<Exponent>(0));
+ std::fill_n(rawPtr(mono), entryCount(), static_cast<Exponent>(0));
+ MATHICGB_ASSERT(debugValid(mono));
MATHICGB_ASSERT(isIdentity(mono));
}
- void setComponent(Component comp, MonoRef mono) const {
- *(mono.rawPtr() + componentIndex()) = comp;
+ void setComponent(Component newComponent, MonoRef mono) const {
+ auto& component = mono.rawPtr()[componentIndex()];
+ const auto oldComponent = component;
+ component = newComponent;
+ updateHashComponent(oldComponent, newComponent, mono);
+ MATHICGB_ASSERT(debugValid(mono));
}
/// Parses a monomial out of a string. Valid examples: 1 abc a2bc
@@ -246,6 +285,8 @@ public:
}
setOrderData(mono);
+ setHash(mono);
+ MATHICGB_ASSERT(debugValid(mono));
}
// Inverse of parseM2().
@@ -555,6 +596,7 @@ public:
// ** Modifiers
void push_back(ConstMonoRef mono) {
+ MATHICGB_ASSERT(monoid().debugValid(mono));
const auto offset = mMonos.size();
mMonos.resize(offset + monoid().entryCount());
monoid().copy(mono, *MonoPtr(mMonos.data() + offset));
@@ -563,7 +605,9 @@ public:
/// Appends the identity.
void push_back() {
const auto offset = mMonos.size();
- mMonos.resize(offset + monoid().entryCount());
+ mMonos.resize(offset + monoid().entryCount());
+ MATHICGB_ASSERT(monoid().isIdentity(back()));
+ MATHICGB_ASSERT(monoid().debugValid(back()));
}
void swap(MonoVector& v) {
@@ -620,12 +664,19 @@ private:
template<class M>
static auto rawPtr(M&& m) -> decltype(m.rawPtr()) {return m.rawPtr();}
+ bool debugValid(ConstMonoRef mono) const {
+ MATHICGB_ASSERT(debugOrderValid(mono));
+ MATHICGB_ASSERT(debugHashValid(mono));
+ return true;
+ }
+
// *** Implementation of monomial ordering
bool debugOrderValid(ConstMonoRef mono) const {
#ifdef MATHICGB_DEBUG
// Check assumptions for layout in memory.
MATHICGB_ASSERT(orderIndexBegin() == exponentsIndexEnd());
MATHICGB_ASSERT(orderIndexBegin() + orderEntryCount() == orderIndexEnd());
+ MATHICGB_ASSERT(orderIndexEnd() < entryCount());
MATHICGB_ASSERT(orderEntryCount() == 1);
// Check the order data of mono
@@ -640,7 +691,7 @@ private:
MATHICGB_ASSERT(debugOrderValid(mono));
}
- void updateOrderInformation(
+ void updateOrderData(
const VarIndex var,
const Exponent oldExponent,
const Exponent newExponent,
@@ -650,7 +701,6 @@ private:
MATHICGB_ASSERT(debugOrderValid(mono));
}
-
Exponent computeTotalDegree(ConstMonoRef mono) const {
Exponent degree = 0;
const auto end = this->end(mono);
@@ -659,14 +709,64 @@ private:
return degree;
}
- // *** Code describing the layout of monomials in memory
+
+ // *** Implementation of hash value computation
+
+ bool debugHashValid(ConstMonoRef mono) const {
+ // We cannot call hash() here since it calls this method.
+ MATHICGB_ASSERT(hashIndex() < entryCount());
+ MATHICGB_ASSERT(rawPtr(mono)[hashIndex()] == computeHash(mono));
+ return true;
+ }
+
+ HashValue computeHash(ConstMonoRef mono) const {
+ HashValue hash = component(mono);
+ const auto exponents = begin(mono);
+ for (VarIndex var = 0; var < varCount(); ++var)
+ hash += static_cast<HashValue>(exponents[var]) * mHashCoefficients[var];
+
+ // Hash values are stored as exponents. If the cast to an exponent
+ // changes the value, then we need computeHashValue to match that
+ // change by casting to an exponent and back. Otherwise the computed
+ // hash value will not match a hash value that has been stored.
+ return static_cast<HashValue>(static_cast<Exponent>(hash));
+ }
+
+ void setHash(MonoRef mono) const {
+ rawPtr(mono)[hashIndex()] = computeHash(mono);
+ MATHICGB_ASSERT(debugHashValid(mono));
+ }
+
+ void updateHashComponent(
+ const Exponent oldComponent,
+ const Exponent newComponent,
+ MonoRef mono
+ ) const {
+ rawPtr(mono)[hashIndex()] += newComponent - oldComponent;
+ MATHICGB_ASSERT(debugHashValid(mono));
+ }
+
+ void updateHashExponent(
+ const VarIndex var,
+ const Exponent oldExponent,
+ const Exponent newExponent,
+ MonoRef mono
+ ) const {
+ MATHICGB_ASSERT(var < varCount());
+ rawPtr(mono)[hashIndex()] +=
+ (newExponent - oldExponent) * mHashCoefficients[var];
+ MATHICGB_ASSERT(debugHashValid(mono));
+ }
+
+
+ // *** Code determining the layout of monomials in memory
// Layout in memory:
// [component] [exponents...] [order data...] [hash]
/// Returns how many Exponents are necessary to store a
- /// monomial. This can include other information than the exponents,
- /// so this number can be larger than varCount().
- size_t entryCount() const {return mOrderIndexEnd;}
+ /// monomial. This can include other data than the exponents, so
+ /// this number can be larger than varCount().
+ size_t entryCount() const {return mOrderIndexEnd + 1;}
/// Returns how many Exponents are necessary to store the extra data
/// used to compare monomials quickly.
@@ -677,7 +777,7 @@ private:
VarIndex exponentsIndexEnd() const {return varCount() + 1;}
VarIndex orderIndexBegin() const {return mOrderIndexBegin;}
VarIndex orderIndexEnd() const {return mOrderIndexEnd;}
- //VarIndex hashIndex() const {return mOrderIndexEnd;
+ VarIndex hashIndex() const {return mOrderIndexEnd;}
const VarIndex mVarCount;
const VarIndex mOrderEntryCount;
@@ -685,8 +785,7 @@ private:
const VarIndex mOrderIndexEnd;
/// Take dot product of exponents with this vector to get hash value.
- //std::vector<HashValue> mHashVals;
-
+ std::vector<HashValue> mHashCoefficients;
};
#endif
diff --git a/src/test/MonoMonoid.cpp b/src/test/MonoMonoid.cpp
index 949339b..7d209e7 100755
--- a/src/test/MonoMonoid.cpp
+++ b/src/test/MonoMonoid.cpp
@@ -91,6 +91,7 @@ TEST(MonoMonoid, MonoVector) {
ASSERT_FALSE(v.empty()); // empty
ASSERT_EQ(i + 1, v.size()); // size
+
ASSERT_TRUE(monoid.isIdentity(v.back())); // isIdentity true, back non-const
bool allZero = true;
for (VarIndex var = 0; var < varCount; ++var) {
--
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