[mathicgb] 112/393: Small changes that allow for exponent to be a char/int8. That was a problem with IO code since >>char is different from >>int in that the former reads a single character while the latter reads a possibly multi-character integer.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:43 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 b04df39a0b072b20247d980ce07a42f84520f03e
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Thu Nov 15 19:47:48 2012 +0100

    Small changes that allow for exponent to be a char/int8. That was a problem with IO code since >>char is different from >>int in that the former reads a single character while the latter reads a possibly multi-character integer.
---
 src/mathicgb/F4MatrixBuilder.cpp |  6 +++--
 src/mathicgb/PolyRing.cpp        | 53 ++++++++++++++++++++--------------------
 src/mathicgb/PolyRing.hpp        | 42 ++++++++++++++++++++++++-------
 src/test/poly-test.cpp           |  2 +-
 4 files changed, 65 insertions(+), 38 deletions(-)

diff --git a/src/mathicgb/F4MatrixBuilder.cpp b/src/mathicgb/F4MatrixBuilder.cpp
index ec4cca5..6647d33 100755
--- a/src/mathicgb/F4MatrixBuilder.cpp
+++ b/src/mathicgb/F4MatrixBuilder.cpp
@@ -244,6 +244,8 @@ F4MatrixBuilder::createColumn(
 
   // The column really does not exist, so we need to create it
   ring().monomialMult(monoA, monoB, mTmp);
+  if (!ring().monomialHasAmpleCapacity(mTmp))
+    mathic::reportError("Monomial exponent overflow in F4MatrixBuilder.");
   MATHICGB_ASSERT(ring().hashValid(mTmp));
 
   // look for a reducer of mTmp
@@ -251,12 +253,12 @@ F4MatrixBuilder::createColumn(
   const bool insertLeft = (reducerIndex != static_cast<size_t>(-1));
 
   // Create the new left or right column
-  const auto colCount = insertLeft ? mLeftColCount : mRightColCount;
+  auto& colCount = insertLeft ? mLeftColCount : mRightColCount;
   if (colCount == std::numeric_limits<ColIndex>::max())
     throw std::overflow_error("Too many columns in QuadMatrix");
   const auto inserted = mMap.insert
     (std::make_pair(mTmp, LeftRightColIndex(colCount, insertLeft)));
-  insertLeft ? ++mLeftColCount : ++mRightColCount;
+  ++colCount;
   MATHICGB_ASSERT(inserted.second);
   MATHICGB_ASSERT(inserted.first.first != 0);
 
diff --git a/src/mathicgb/PolyRing.cpp b/src/mathicgb/PolyRing.cpp
index ad22a52..2602c02 100755
--- a/src/mathicgb/PolyRing.cpp
+++ b/src/mathicgb/PolyRing.cpp
@@ -225,7 +225,7 @@ void PolyRing::monomialParse(std::istream &i,
   // first initialize result:
   for (size_t j=0; j<mMaxMonomialSize; j++) result[j] = 0;
 
-  exponent e;
+  uint64 e;
   int v, x;
   // now look at the next char
   for (;;)
@@ -243,9 +243,7 @@ void PolyRing::monomialParse(std::istream &i,
           next = i.peek();
           e = 1;
           if (isdigit(next))
-            {
-              i >> e;
-            }
+            i >> e;
           result[v+1] = e;
         }
       else if (next == '<')
@@ -273,19 +271,19 @@ void PolyRing::monomialDisplay(std::ostream &o,
   // print_one: only is consulted in print_comp is false.
 
   bool printed_any = false;
-  for (size_t i=0; i<mNumVars; i++)
-    if (a[i+1] != 0)
-      {
-        printed_any = true;
-        if (i <= 25)
-          o << static_cast<unsigned char>('a' + i);
-        else
-          o << static_cast<unsigned char>('A' + (i - 26));
-        if (a[i+1] != 1)
-          o << a[i+1];
-      }
+  for (size_t i=0; i<mNumVars; i++) {
+    if (a[i+1] != 0) {
+      printed_any = true;
+      if (i <= 25)
+        o << static_cast<unsigned char>('a' + i);
+      else
+        o << static_cast<unsigned char>('A' + (i - 26));
+      if (a[i+1] != 1)
+        o << static_cast<int64>(a[i+1]);
+    }
+  }
   if (print_comp)
-    o << '<' << *a.mValue << '>';
+    o << '<' << static_cast<int64>(*a.mValue) << '>';
   else if (!printed_any && print_one)
     o << "1";
 }
@@ -655,24 +653,27 @@ void PolyRing::printMonomialFrobbyM2Format(std::ostream& out, const_monomial m)
 
 PolyRing *PolyRing::read(std::istream &i)
 {
+  int64 characInt;
   coefficient charac;
   int mNumVars, mNumWeights;
 
-  i >> charac;
+  i >> characInt;
+  charac = characInt;
   i >> mNumVars;
   i >> mNumWeights;
-  PolyRing *R = new PolyRing(charac, mNumVars, mNumWeights);
+  PolyRing* R = new PolyRing(charac, mNumVars, mNumWeights);
   int wtlen = mNumVars * mNumWeights;
   R->mWeights.resize(wtlen);
   R->mTotalDegreeGradedOnly = (mNumWeights == 1);
-  for (int j=0; j <mNumVars * mNumWeights; j++)
-    {
-      exponent a;
-      i >> a;
-      R->mWeights[j] = -a;
-      if (R->mWeights[j] != -1)
-        R->mTotalDegreeGradedOnly = false;
-    }
+  for (int j=0; j <mNumVars * mNumWeights; j++) {
+    exponent a;
+    int64 aInt;
+    i >> aInt;
+    a = aInt;
+    R->mWeights[j] = -a;
+    if (R->mWeights[j] != -1)
+      R->mTotalDegreeGradedOnly = false;
+  }
   return R;
 }
 
diff --git a/src/mathicgb/PolyRing.hpp b/src/mathicgb/PolyRing.hpp
index c875612..90bd347 100755
--- a/src/mathicgb/PolyRing.hpp
+++ b/src/mathicgb/PolyRing.hpp
@@ -360,14 +360,18 @@ public:
 
   bool weightsCorrect(ConstMonomial a) const;
 
+  // returns LT, EQ, or GT, depending on sig ? (m2 * sig2).
   int monomialCompare(ConstMonomial a, 
                       ConstMonomial b) const; 
   // returns LT, EQ or GT
-
   int monomialCompare(ConstMonomial sig, 
                       ConstMonomial m2, 
                       ConstMonomial sig2) const;
-  // returns LT, EQ, or GT, depending on sig ? (m2 * sig2).
+
+  // If this method returns true for monomials a and b then it is guaranteed
+  // the multiplying a and b together will not overflow the underlying
+  // exponent integer. Does not work for negative exponents.
+  bool monomialHasAmpleCapacity(ConstMonomial mono) const;
 
   bool monomialLT(ConstMonomial a, ConstMonomial b) const {
     for (size_t i = mTopIndex; i != static_cast<size_t>(-1); --i)
@@ -435,8 +439,9 @@ public:
 
   /// Returns the hash of the product of a and b.
   HashValue monomialHashOfProduct(ConstMonomial a, ConstMonomial b) const {
-    return static_cast<HashValue>(a[mHashIndex]) +
-      static_cast<HashValue>(b[mHashIndex]);
+    return static_cast<exponent>(
+      static_cast<HashValue>(a[mHashIndex]) +
+      static_cast<HashValue>(b[mHashIndex]));
   }
 
   void monomialCopy(ConstMonomial  a, Monomial &result) const;
@@ -667,6 +672,9 @@ inline bool PolyRing::monomialIsProductOfHintTrue(
   // for unaligned access. Performance seems to be no worse than for using
   // 32 bit integers directly.
 
+  if (sizeof(exponent) < 4)
+    return monomialIsProductOf(a, b, ab);
+
   uint64 orOfXor = 0;
   for (size_t i = mNumVars / 2; i != static_cast<size_t>(-1); --i) {
     uint64 A, B, AB;
@@ -691,6 +699,10 @@ MATHICGB_INLINE bool PolyRing::monomialIsTwoProductsOfHintTrue(
   const ConstMonomial a1b,
   const ConstMonomial a2b
 ) const {
+  if (sizeof(exponent) < 4)
+    return (monomialIsProductOf(a1, b, a1b) &&
+      monomialIsProductOf(a2, b, a2b));
+
   uint64 orOfXor = 0;
   for (size_t i = mNumVars / 2; i != static_cast<size_t>(-1); --i) {
     uint64 A1, A2, B, A1B, A2B;
@@ -725,7 +737,7 @@ inline void PolyRing::monomialMult(ConstMonomial a,
   for (size_t i = mHashIndex; i != static_cast<size_t>(-1); --i)
     result[i] = a[i] + b[i];
   MATHICGB_ASSERT(computeHashValue(result) ==
-                  computeHashValue(a) + computeHashValue(b));
+    static_cast<exponent>(computeHashValue(a) + computeHashValue(b)));
 
 #if 0
   // testing different things to see if we can speed it up further.
@@ -761,7 +773,10 @@ inline HashValue PolyRing::computeHashValue(const_monomial a1) const {
   a++;
   for (size_t i = 0; i < mNumVars; ++i)
     hash += static_cast<HashValue>(a[i]) * mHashVals[i];
-  return hash;
+  // cast to potentially discard precision that will also be lost
+  // when storing a hash value as an exponent. Otherwise the hash
+  // value that is computed will not match the stored hash value.
+  return static_cast<exponent>(hash);
 }
 
 inline void PolyRing::setHashOnly(Monomial& a1) const
@@ -842,10 +857,11 @@ inline void PolyRing::monomialDivideToNegative(ConstMonomial a,
 {
   for (size_t i = 0; i <= mHashIndex; ++i)
     result[i] = a[i] - b[i];
-  MATHICGB_ASSERT(monomialHashValue(result) == monomialHashValue(a) - monomialHashValue(b));
+  MATHICGB_ASSERT(monomialHashValue(result) ==
+    static_cast<exponent>(monomialHashValue(a) - monomialHashValue(b)));
   MATHICGB_ASSERT(!hashValid(a) || !hashValid(b) || hashValid(result));
-  MATHICGB_ASSERT(computeHashValue(result) ==
-                  computeHashValue(a) - computeHashValue(b));
+  MATHICGB_ASSERT(computeHashValue(result) == static_cast<exponent>
+    (computeHashValue(a) - computeHashValue(b)));
 }
 
 inline bool PolyRing::monomialRelativelyPrime(ConstMonomial a, 
@@ -1125,6 +1141,14 @@ inline void PolyRing::coefficientMult(coefficient a, coefficient b, coefficient
   result = c % mCharac;
 }
 
+inline bool PolyRing::monomialHasAmpleCapacity(ConstMonomial mono) const {
+  const auto halfMax = std::numeric_limits<exponent>::max() / 2;
+  for (size_t i = mTopIndex; i != 0; --i)
+    if (mono[i] > halfMax)
+      return false;
+  return true;
+}
+
 #endif
 
 // Local Variables:
diff --git a/src/test/poly-test.cpp b/src/test/poly-test.cpp
index bbb6e88..f92fc3c 100755
--- a/src/test/poly-test.cpp
+++ b/src/test/poly-test.cpp
@@ -282,7 +282,7 @@ TEST(Monomial, ops)
   testMonomialOps(R.get(), "<0>", "<0>");
   testMonomialOps(R.get(), "a<0>", "a<0>");
   testMonomialOps(R.get(), "a<0>", "b<0>");
-  testMonomialOps(R.get(), "a1000b1000c1000d1000e1000f1000<0>", "b2f5<0>");
+  testMonomialOps(R.get(), "a10b10c10d10e10f10<0>", "b2f5<0>");
 }
 
 TEST(Monomial, ei)

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