[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