[mathicgb] 78/393: Moving closer to adding support for parallel matrix construction. This changed the order that rows are constructed which surprisingly gave an 8% speedup on hcyc8 on Cygwin when running on 2 cores.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58: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 bb9af1e3b8ab2a39502bf2f9dc768f2bf2c9d431
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Wed Oct 24 19:54:41 2012 +0200

    Moving closer to adding support for parallel matrix construction. This changed the order that rows are constructed which surprisingly gave an 8% speedup on hcyc8 on Cygwin when running on 2 cores.
---
 src/mathicgb/F4MatrixBuilder.cpp |  75 ++++++++++++---
 src/mathicgb/F4MatrixBuilder.hpp |   7 +-
 src/mathicgb/F4Reducer.cpp       |   6 +-
 src/mathicgb/QuadMatrix.cpp      |  40 ++++++++
 src/mathicgb/QuadMatrix.hpp      |  13 +++
 src/mathicgb/SparseMatrix.cpp    |  10 ++
 src/mathicgb/SparseMatrix.hpp    |   8 +-
 src/test/F4MatrixBuilder.cpp     | 198 ++++++++++++++++++++-------------------
 8 files changed, 239 insertions(+), 118 deletions(-)

diff --git a/src/mathicgb/F4MatrixBuilder.cpp b/src/mathicgb/F4MatrixBuilder.cpp
index c7041ea..b0d46e5 100755
--- a/src/mathicgb/F4MatrixBuilder.cpp
+++ b/src/mathicgb/F4MatrixBuilder.cpp
@@ -1,8 +1,18 @@
 #include "stdinc.h"
 #include "F4MatrixBuilder.hpp"
 
-F4MatrixBuilder::F4MatrixBuilder(const PolyBasis& basis):
-  mBasis(basis), mBuilder(basis.ring()), tmp(basis.ring().allocMonomial()) {}
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
+F4MatrixBuilder::F4MatrixBuilder(const PolyBasis& basis, const int threadCount):
+  mThreadCount(threadCount),
+  mBasis(basis),
+  mBuilder(basis.ring()),
+  tmp(basis.ring().allocMonomial())
+{
+  MATHICGB_ASSERT(threadCount >= 1);
+}
 
 void F4MatrixBuilder::addSPolynomialToMatrix
 (const Poly& polyA, const Poly& polyB) {
@@ -141,7 +151,7 @@ void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) {
 	    MATHICGB_ASSERT(c < std::numeric_limits<QuadMatrixBuilder::Scalar>::max());
         auto col = mBuilder.findColumn(mono);
         if (!col.valid())
-          col = this->createColumn(mono);
+          col = this->createColumn(mono, mBuilder);
         mBuilder.appendEntryBottom(col,
           static_cast<QuadMatrixBuilder::Scalar>(c));
 	  }
@@ -153,11 +163,42 @@ void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) {
 
   // Process pending rows until we are done. Note that the methods
   // we are calling here can add more items to mTodo.
+
+#ifdef _OPENMP
+  struct ThreadData {
+    QuadMatrixBuilder* builder;
+  };
+  MATHICGB_ASSERT(mThreadCount >= 1);
+  std::vector<ThreadData> threadData(mThreadCount);
+  for (size_t i = 0; i < threadData.size(); ++i) {
+    // this will change once parallelism is properly implemented
+    threadData[i].builder = &mBuilder;
+    //threadData[i].builder = i == 0 ? &mBuilder : new QuadMatrixBuilder(ring());
+  }
+#endif
+
+  decltype(mTodo) currentTasks;
   while (!mTodo.empty()) {
-    RowTask task = mTodo.back();
-    MATHICGB_ASSERT(ring().hashValid(task.multiple));
-    mTodo.pop_back();
-    appendRowTop(task.multiple, *task.poly);
+    currentTasks.clear();
+    mTodo.swap(currentTasks);
+    const auto taskCountOMP = static_cast<OMPIndex>(currentTasks.size());
+#pragma omp parallel for num_threads(mThreadCount) schedule(dynamic)
+    for (OMPIndex taskOMP = 0; taskOMP < taskCountOMP; ++taskOMP) {
+      const size_t taskIndex = taskOMP;
+#ifdef _OPENMP
+      QuadMatrixBuilder& builder = *threadData[omp_get_thread_num()].builder;
+#else
+      QuadMatrixBuilder& builder = mBuilder;
+#endif
+      const RowTask task = currentTasks[taskIndex];
+      MATHICGB_ASSERT(ring().hashValid(task.multiple));
+
+      // this will change once parallelism is properly implemented
+#pragma omp critical
+      {
+        appendRowTop(task.multiple, *task.poly, builder);
+      }
+    }
   }
 
   mBuilder.sortColumnsLeft(mBasis.order());
@@ -166,9 +207,15 @@ void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) {
 }
 
 F4MatrixBuilder::LeftRightColIndex
-F4MatrixBuilder::createColumn(const_monomial mono) {
+F4MatrixBuilder::createColumn(const_monomial mono, QuadMatrixBuilder& builder) {
   MATHICGB_ASSERT(ring().hashValid(mono));
-  MATHICGB_ASSERT(!mBuilder.findColumn(mono).valid());
+  MATHICGB_ASSERT(!builder.findColumn(mono).valid());
+#ifdef _OPENMP
+  // this will change once parallelism is properly implemented
+  MATHICGB_ASSERT(&builder == &mBuilder);
+#else
+  MATHICGB_ASSERT(&builder == &mBuilder);
+#endif
 
   // look for a reducer of mono
   size_t reducerIndex = mBasis.divisor(mono);
@@ -187,19 +234,19 @@ F4MatrixBuilder::createColumn(const_monomial mono) {
   return mBuilder.createColumnLeft(mono);
 }
 
-void F4MatrixBuilder::appendRowTop(const_monomial multiple, const Poly& poly) {
+void F4MatrixBuilder::appendRowTop(const_monomial multiple, const Poly& poly, QuadMatrixBuilder& builder) {
   Poly::const_iterator end = poly.end();
   for (Poly::const_iterator it = poly.begin(); it != end; ++it) {
 	MATHICGB_ASSERT(it.getCoefficient() <
       std::numeric_limits<QuadMatrixBuilder::Scalar>::max());
-    auto col = mBuilder.findColumnProduct(it.getMonomial(), multiple);
+    auto col = builder.findColumnProduct(it.getMonomial(), multiple);
     if (!col.valid()) {
       ring().monomialMult(it.getMonomial(), multiple, tmp);
-      col = createColumn(tmp);
+      col = createColumn(tmp, builder);
     }
     const auto scalar =
       static_cast<QuadMatrixBuilder::Scalar>(it.getCoefficient());
-    mBuilder.appendEntryTop(col, scalar);
+    builder.appendEntryTop(col, scalar);
   }
-  mBuilder.rowDoneTopLeftAndRight();
+  builder.rowDoneTopLeftAndRight();
 }
diff --git a/src/mathicgb/F4MatrixBuilder.hpp b/src/mathicgb/F4MatrixBuilder.hpp
index ca60dae..7755923 100755
--- a/src/mathicgb/F4MatrixBuilder.hpp
+++ b/src/mathicgb/F4MatrixBuilder.hpp
@@ -21,7 +21,7 @@ private:
   typedef QuadMatrixBuilder::LeftRightColIndex LeftRightColIndex;
 
 public:
-  F4MatrixBuilder(const PolyBasis& basis);
+  F4MatrixBuilder(const PolyBasis& basis, int threadCount);
 
   /** Schedules a row representing the S-polynomial between polyA and
     polyB to be added to the matrix. No ownership is taken, but polyA
@@ -63,9 +63,9 @@ public:
 private:
   /** Creates a column with monomial label mono and schedules a new row to
     reduce that column if possible. */
-  LeftRightColIndex createColumn(const_monomial mono);
+  LeftRightColIndex createColumn(const_monomial mono, QuadMatrixBuilder& builder);
 
-  void appendRowTop(const_monomial multiple, const Poly& poly);
+  void appendRowTop(const_monomial multiple, const Poly& poly, QuadMatrixBuilder& builder);
 
   /// Represents an S-pair that was added to the matrix for reduction
   /// or, if polyB is null, a polynomial that was added to the matrix
@@ -83,6 +83,7 @@ private:
     monomial multiple;
   };
 
+  const int mThreadCount;
   monomial tmp;
   std::vector<SPairTask> mSPairTodo;
   std::vector<RowTask> mTodo;
diff --git a/src/mathicgb/F4Reducer.cpp b/src/mathicgb/F4Reducer.cpp
index 7046ddf..1d29ae9 100755
--- a/src/mathicgb/F4Reducer.cpp
+++ b/src/mathicgb/F4Reducer.cpp
@@ -48,7 +48,7 @@ std::unique_ptr<Poly> F4Reducer::classicReduceSPoly
 
   QuadMatrix qm;
   {
-    F4MatrixBuilder builder(basis);
+    F4MatrixBuilder builder(basis, mThreadCount);
     builder.addSPolynomialToMatrix(a, b);
     builder.buildMatrixAndClear(qm);
 
@@ -95,7 +95,7 @@ void F4Reducer::classicReduceSPolySet
   {
     QuadMatrix qm;
     {
-      F4MatrixBuilder builder(basis);
+      F4MatrixBuilder builder(basis, mThreadCount);
       for (auto it = spairs.begin(); it != spairs.end(); ++it) {
         builder.addSPolynomialToMatrix
           (basis.poly(it->first), basis.poly(it->second));
@@ -145,7 +145,7 @@ void F4Reducer::classicReducePolySet
   {
     QuadMatrix qm;
     {
-      F4MatrixBuilder builder(basis);
+      F4MatrixBuilder builder(basis, mThreadCount);
       for (auto it = polys.begin(); it != polys.end(); ++it)
         builder.addPolynomialToMatrix(**it);
       builder.buildMatrixAndClear(qm);
diff --git a/src/mathicgb/QuadMatrix.cpp b/src/mathicgb/QuadMatrix.cpp
index f846f8f..ae13b61 100755
--- a/src/mathicgb/QuadMatrix.cpp
+++ b/src/mathicgb/QuadMatrix.cpp
@@ -62,6 +62,46 @@ std::string QuadMatrix::toString() const {
   return out.str();
 }
 
+QuadMatrix QuadMatrix::toCanonical() const {
+  std::vector<size_t> rows;
+  for (size_t row = 0; row < topLeft.rowCount(); ++row)
+    rows.push_back(row);
+  class RowComparer {
+  public:
+    RowComparer(const SparseMatrix& matrix): mMatrix(matrix) {}
+    bool operator()(size_t a, size_t b) const {
+      // if you need this to work for empty rows or identical leading columns
+      // then update this code.
+      MATHICGB_ASSERT(!mMatrix.emptyRow(a));
+      MATHICGB_ASSERT(!mMatrix.emptyRow(b));
+      return mMatrix.leadCol(a) > mMatrix.leadCol(b);
+    }
+
+  private:
+    const SparseMatrix& mMatrix;
+  };
+  {
+    RowComparer comparer(topLeft);
+    std::sort(rows.begin(), rows.end(), comparer);
+  }
+
+  QuadMatrix matrix;
+  matrix.topLeft.clear(topLeft.colCount());
+  matrix.topRight.clear(topRight.colCount());
+  for (size_t i = 0; i < rows.size(); ++i) {
+    matrix.topLeft.appendRow(topLeft, rows[i]);
+    matrix.topRight.appendRow(topRight, rows[i]);
+  }
+
+  matrix.bottomLeft = bottomLeft;
+  matrix.bottomRight = bottomRight;
+  matrix.leftColumnMonomials = leftColumnMonomials;
+  matrix.rightColumnMonomials = rightColumnMonomials;
+  matrix.ring = ring;
+  
+  return std::move(matrix);
+}
+
 std::ostream& operator<<(std::ostream& out, const QuadMatrix& qm) {
   qm.print(out);
   return out;
diff --git a/src/mathicgb/QuadMatrix.hpp b/src/mathicgb/QuadMatrix.hpp
index a8fb565..d7282ad 100755
--- a/src/mathicgb/QuadMatrix.hpp
+++ b/src/mathicgb/QuadMatrix.hpp
@@ -18,6 +18,15 @@ class ostream;
 class QuadMatrix {
 public:
   QuadMatrix() {}
+  QuadMatrix(QuadMatrix&& matrix):
+    topLeft(matrix.topLeft),
+    topRight(matrix.topRight),
+    bottomLeft(matrix.bottomLeft),
+    bottomRight(matrix.bottomRight),
+    leftColumnMonomials(matrix.leftColumnMonomials),
+    rightColumnMonomials(matrix.rightColumnMonomials),
+    ring(matrix.ring)
+  {}
 
   SparseMatrix topLeft; 
   SparseMatrix topRight;
@@ -34,6 +43,10 @@ public:
   /// Shows whole matrix in a string. Useful for debugging.
   std::string toString() const;
 
+  /// Makes a copy of this matrix whose rows are sorted in some canonical way.
+  /// TODO: Actually only coarsely sorts the top rows right now.
+  QuadMatrix toCanonical() const;
+
 #ifdef MATHICGB_DEBUG
   bool debugAssertValid() const;
 #endif
diff --git a/src/mathicgb/SparseMatrix.cpp b/src/mathicgb/SparseMatrix.cpp
index c3790e7..80281b7 100755
--- a/src/mathicgb/SparseMatrix.cpp
+++ b/src/mathicgb/SparseMatrix.cpp
@@ -116,6 +116,16 @@ void SparseMatrix::appendRow(const SparseMatrix& matrix, const RowIndex row) {
   rowDone();
 }
   
+SparseMatrix& SparseMatrix::operator=(const SparseMatrix& matrix) {
+  clear(matrix.colCount());
+  // A version that works on each block would be faster, but this is not
+  // used anywhere time-critical right now. Improve this if it turns
+  // up in profiling at some point.
+  for (size_t row = 0; row < matrix.rowCount(); ++row)
+    appendRow(matrix, row);
+  return *this;
+}
+
 void SparseMatrix::swap(SparseMatrix& matrix) {
   mBlock.swap(matrix.mBlock);
   using std::swap;
diff --git a/src/mathicgb/SparseMatrix.hpp b/src/mathicgb/SparseMatrix.hpp
index e7d6b59..076ca5d 100755
--- a/src/mathicgb/SparseMatrix.hpp
+++ b/src/mathicgb/SparseMatrix.hpp
@@ -63,10 +63,12 @@ public:
     return *this;
   }
 
+  SparseMatrix(const SparseMatrix& matrix) {*this = matrix;}
+
   ~SparseMatrix() {clear();}
 
+  SparseMatrix& operator=(const SparseMatrix&);
   void swap(SparseMatrix& matrix);
-
   void clear(ColIndex newColCount = 0);
 
   RowIndex rowCount() const {return mRows.size();}
@@ -267,10 +269,8 @@ public:
     const Scalar* mScalarIt;
   };
 
-private:
-  SparseMatrix(const SparseMatrix&); // not available
-  void operator=(const SparseMatrix&); // not available
 
+private:
   NO_INLINE void growEntryCapacity();
 
   /// Contains information about a row in the matrix.
diff --git a/src/test/F4MatrixBuilder.cpp b/src/test/F4MatrixBuilder.cpp
index 2bdace6..5661a18 100755
--- a/src/test/F4MatrixBuilder.cpp
+++ b/src/test/F4MatrixBuilder.cpp
@@ -18,7 +18,8 @@ namespace {
   // @todo: This whole thing is fairly ridiculous - some kind of more
   // general dependency injection mechanism might be nice here.
   struct BuilderMaker {
-    BuilderMaker():
+    BuilderMaker(int threadCount):
+      mThreadCount(threadCount),
       mRing(ringFromString("101 6 1\n1 1 1 1 1 1")),
       mIdeal(*mRing),
       mOrder(FreeModuleOrder::makeOrder(1, &mIdeal)),
@@ -35,13 +36,14 @@ namespace {
 
     F4MatrixBuilder& create() {
       MATHICGB_ASSERT(mBuilder.get() == 0);
-      mBuilder.reset(new F4MatrixBuilder(mBasis));
+      mBuilder.reset(new F4MatrixBuilder(mBasis, mThreadCount));
       return *mBuilder;
     }
 
     const PolyRing& ring() const {return *mRing;}
      
   private:
+    const int mThreadCount;
     std::unique_ptr<PolyRing> mRing;
     Ideal mIdeal;
     std::unique_ptr<FreeModuleOrder> mOrder;
@@ -51,110 +53,118 @@ namespace {
 }
 
 TEST(F4MatrixBuilder, Empty) {
-  BuilderMaker maker;
-  F4MatrixBuilder& builder = maker.create();
-
-  QuadMatrix matrix;
-  builder.buildMatrixAndClear(matrix);
-  ASSERT_EQ(0, matrix.topLeft.rowCount());
-  ASSERT_EQ(0, matrix.bottomLeft.rowCount());
-  ASSERT_EQ(0, matrix.topLeft.colCount());
-  ASSERT_EQ(0, matrix.topRight.colCount());
-  ASSERT_EQ(0, matrix.leftColumnMonomials.size());
-  ASSERT_EQ(0, matrix.rightColumnMonomials.size());
+  for (int threadCount = 1; threadCount < 4; ++threadCount) {
+    BuilderMaker maker(threadCount);
+    F4MatrixBuilder& builder = maker.create();
+
+    QuadMatrix matrix;
+    builder.buildMatrixAndClear(matrix);
+    ASSERT_EQ(0, matrix.topLeft.rowCount());
+    ASSERT_EQ(0, matrix.bottomLeft.rowCount());
+    ASSERT_EQ(0, matrix.topLeft.colCount());
+    ASSERT_EQ(0, matrix.topRight.colCount());
+    ASSERT_EQ(0, matrix.leftColumnMonomials.size());
+    ASSERT_EQ(0, matrix.rightColumnMonomials.size());
+  }
 }
 
 TEST(F4MatrixBuilder, SPair) {
-  BuilderMaker maker;
-  const Poly& p1 = maker.addBasisElement("a4c2-d");
-  const Poly& p2 = maker.addBasisElement("a4b+d");
-  // S-pair of p1 and p2 is -c2d-bd
-  const Poly& p3 = maker.addBasisElement("c2d+3");
-  F4MatrixBuilder& builder = maker.create();
-  builder.addSPolynomialToMatrix(p1, p2);
-  QuadMatrix qm;
-  builder.buildMatrixAndClear(qm);
-  const char* str = 
-    "Left columns: c2d\n"
-    "Right columns: bd 1\n"
-    "0: 0#1   | 0: 1#3  \n"
-    "         |         \n"
-    "0: 0#100 | 0: 0#100\n";
-  ASSERT_EQ(str, qm.toString());
+  for (int threadCount = 1; threadCount < 4; ++threadCount) {
+    BuilderMaker maker(threadCount);
+    const Poly& p1 = maker.addBasisElement("a4c2-d");
+    const Poly& p2 = maker.addBasisElement("a4b+d");
+    // S-pair of p1 and p2 is -c2d-bd
+    const Poly& p3 = maker.addBasisElement("c2d+3");
+    F4MatrixBuilder& builder = maker.create();
+    builder.addSPolynomialToMatrix(p1, p2);
+    QuadMatrix qm;
+    builder.buildMatrixAndClear(qm);
+    const char* str = 
+      "Left columns: c2d\n"
+      "Right columns: bd 1\n"
+      "0: 0#1   | 0: 1#3  \n"
+      "         |         \n"
+      "0: 0#100 | 0: 0#100\n";
+    ASSERT_EQ(str, qm.toString());
+  }
 }
 
 TEST(F4MatrixBuilder, OneByOne) {
-  BuilderMaker maker;
-  const Poly& p = maker.addBasisElement("a");
-  F4MatrixBuilder& builder = maker.create();
-  builder.addPolynomialToMatrix(p.getLeadMonomial(), p);
-  QuadMatrix qm;
-  builder.buildMatrixAndClear(qm);
-  const char* str = 
-    "Left columns: a2\n"
-    "Right columns:\n"
-    "0: 0#1 | 0:\n"
-    "       |   \n"
-    "0: 0#1 | 0:\n";
-  ASSERT_EQ(str, qm.toString()) << "** qm:\n" << qm;
+  for (int threadCount = 1; threadCount < 4; ++threadCount) {
+    BuilderMaker maker(threadCount);
+    const Poly& p = maker.addBasisElement("a");
+    F4MatrixBuilder& builder = maker.create();
+    builder.addPolynomialToMatrix(p.getLeadMonomial(), p);
+    QuadMatrix qm;
+    builder.buildMatrixAndClear(qm);
+    const char* str = 
+      "Left columns: a2\n"
+      "Right columns:\n"
+      "0: 0#1 | 0:\n"
+      "       |   \n"
+      "0: 0#1 | 0:\n";
+    ASSERT_EQ(str, qm.toString()) << "** qm:\n" << qm;
+  }
 }
 
 TEST(F4MatrixBuilder, DirectReducers) {
-  BuilderMaker maker;
-  maker.addBasisElement("a6<0>"); // reducer == to lead term
-  maker.addBasisElement("a3b2<0>+a3c"); // reducer == to lower order term
-  maker.addBasisElement("c<0>"); // reducer divides
-  maker.addBasisElement("d2<0>"); // does not divide
-  F4MatrixBuilder& builder = maker.create();
-
-  Poly p1(builder.ring());
-  { 
-    std::istringstream in("a3<0>+b2+c+d");
-    p1.parse(in);
-    builder.addPolynomialToMatrix(p1.getLeadMonomial(), p1);
-  }
+  for (int threadCount = 1; threadCount < 4; ++threadCount) {
+    BuilderMaker maker(threadCount);
+    maker.addBasisElement("a6<0>"); // reducer == to lead term
+    maker.addBasisElement("a3b2<0>+a3c"); // reducer == to lower order term
+    maker.addBasisElement("c<0>"); // reducer divides
+    maker.addBasisElement("d2<0>"); // does not divide
+    F4MatrixBuilder& builder = maker.create();
+
+    Poly p1(builder.ring());
+    { 
+      std::istringstream in("a3<0>+b2+c+d");
+      p1.parse(in);
+      builder.addPolynomialToMatrix(p1.getLeadMonomial(), p1);
+    }
 
-  Poly p2(builder.ring());
-  {
-    std::istringstream in("a3<0>+2b2+3c+4d");
-    p2.parse(in);
-    builder.addPolynomialToMatrix(p2.getLeadMonomial(), p2);
-  }
+    Poly p2(builder.ring());
+    {
+      std::istringstream in("a3<0>+2b2+3c+4d");
+      p2.parse(in);
+      builder.addPolynomialToMatrix(p2.getLeadMonomial(), p2);
+    }
 
-  QuadMatrix qm;
-  builder.buildMatrixAndClear(qm);
-
-  const char* str =
-    "Left columns: a6 a3b2 a3c\n"
-    "Right columns: a3d\n"
-    "0: 2#1         | 0:    \n"
-    "1: 1#1 2#1     | 1:    \n"
-    "2: 0#1         | 2:    \n"
-    "               |       \n"
-    "0: 0#1 1#1 2#1 | 0: 0#1\n"
-    "1: 0#1 1#2 2#3 | 1: 0#4\n";
-  // This quest is currently fragile because of the possibility of
-  // reordering of the rows.
-  ASSERT_EQ(str, qm.toString()) << "** qm:\n" << qm;
+    QuadMatrix qm;
+    builder.buildMatrixAndClear(qm);
+
+    const char* str =
+      "Left columns: a6 a3b2 a3c\n"
+      "Right columns: a3d\n"
+      "0: 2#1         | 0:    \n"
+      "1: 1#1 2#1     | 1:    \n"
+      "2: 0#1         | 2:    \n"
+      "               |       \n"
+      "0: 0#1 1#1 2#1 | 0: 0#1\n"
+      "1: 0#1 1#2 2#3 | 1: 0#4\n";
+    ASSERT_EQ(str, qm.toCanonical().toString()) << "** qm:\n" << qm;
+  }
 }
 
 TEST(F4MatrixBuilder, IteratedReducer) {
-  BuilderMaker maker;
-  const Poly& p1 = maker.addBasisElement("a4-a3");
-  const Poly& p2 = maker.addBasisElement("a-1");
-  F4MatrixBuilder& builder = maker.create();
-  builder.addPolynomialToMatrix(p1.getLeadMonomial(), p2);
-  QuadMatrix qm;
-  builder.buildMatrixAndClear(qm);
-  const char* str = 
-    "Left columns: a5 a4 a3 a2 a\n"
-    "Right columns: 1\n"
-    "0: 1#1 2#100 | 0:      \n"
-    "1: 2#1 3#100 | 1:      \n"
-    "2: 3#1 4#100 | 2:      \n"
-    "3: 4#1       | 3: 0#100\n"
-    "4: 0#1 1#100 | 4:      \n"
-    "             |         \n"
-    "0: 0#1 1#100 | 0:      \n";
-  ASSERT_EQ(str, qm.toString()) << "** qm:\n" << qm;
+  for (int threadCount = 1; threadCount < 4; ++threadCount) {
+    BuilderMaker maker(threadCount);
+    const Poly& p1 = maker.addBasisElement("a4-a3");
+    const Poly& p2 = maker.addBasisElement("a-1");
+    F4MatrixBuilder& builder = maker.create();
+    builder.addPolynomialToMatrix(p1.getLeadMonomial(), p2);
+    QuadMatrix qm;
+    builder.buildMatrixAndClear(qm);
+    const char* str = 
+      "Left columns: a5 a4 a3 a2 a\n"
+      "Right columns: 1\n"
+      "0: 4#1       | 0: 0#100\n"
+      "1: 3#1 4#100 | 1:      \n"
+      "2: 2#1 3#100 | 2:      \n"
+      "3: 1#1 2#100 | 3:      \n"
+      "4: 0#1 1#100 | 4:      \n"
+      "             |         \n"
+      "0: 0#1 1#100 | 0:      \n";
+    ASSERT_EQ(str, qm.toCanonical().toString()) << "** qm:\n" << qm;
+  }
 }

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