[mathicgb] 322/393: Went through ALL source files to give them a common copyright header, to put everything in namespace mgb to avoid name clashes and to normalize header inclusion order of system versus non-system headers. Apparently there is a bug or some issue here somewhere that requires using ::std::X to refer to std::X. That was really fun. Yep.
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:29 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 0a6fe2a64af597135f3700fd4b1f09fdc31a6c76
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date: Mon May 13 22:27:10 2013 +0200
Went through ALL source files to give them a common copyright header, to put everything in namespace mgb to avoid name clashes and to normalize header inclusion order of system versus non-system headers. Apparently there is a bug or some issue here somewhere that requires using ::std::X to refer to std::X. That was really fun. Yep.
---
src/checksource/CheckSource.cpp | 14 +-
src/cli/CommonParams.cpp | 6 +
src/cli/CommonParams.hpp | 6 +
src/cli/GBAction.cpp | 6 +
src/cli/GBAction.hpp | 5 +
src/cli/GBCommonParams.cpp | 6 +
src/cli/GBCommonParams.hpp | 5 +
src/cli/GBMain.cpp | 22 +-
src/cli/HelpAction.cpp | 7 +-
src/cli/HelpAction.hpp | 28 +-
src/cli/MatrixAction.cpp | 24 +-
src/cli/MatrixAction.hpp | 5 +
src/cli/SigGBAction.cpp | 30 +-
src/cli/SigGBAction.hpp | 5 +
src/mathicgb.cpp | 2 +
src/mathicgb/Atomic.hpp | 77 +-
src/mathicgb/Basis.cpp | 9 +-
src/mathicgb/Basis.hpp | 25 +-
src/mathicgb/BjarkeGeobucket.cpp | 11 +-
src/mathicgb/BjarkeGeobucket.hpp | 18 +-
src/mathicgb/BjarkeGeobucket2.cpp | 10 +-
src/mathicgb/BjarkeGeobucket2.hpp | 18 +-
src/mathicgb/CFile.cpp | 62 +-
src/mathicgb/CFile.hpp | 79 +-
src/mathicgb/ChainedHashTable.cpp | 11 +-
src/mathicgb/ChainedHashTable.hpp | 19 +-
src/mathicgb/ClassicGBAlg.cpp | 14 +-
src/mathicgb/ClassicGBAlg.hpp | 5 +
src/mathicgb/DivLookup.hpp | 19 +-
src/mathicgb/DivisorLookup.cpp | 13 +-
src/mathicgb/DivisorLookup.hpp | 27 +-
src/mathicgb/F4MatrixBuilder.cpp | 44 +-
src/mathicgb/F4MatrixBuilder.hpp | 320 +--
src/mathicgb/F4MatrixBuilder2.cpp | 60 +-
src/mathicgb/F4MatrixBuilder2.hpp | 289 +--
src/mathicgb/F4MatrixProjection.cpp | 68 +-
src/mathicgb/F4MatrixProjection.hpp | 14 +-
src/mathicgb/F4MatrixReducer.cpp | 73 +-
src/mathicgb/F4MatrixReducer.hpp | 84 +-
src/mathicgb/F4ProtoMatrix.cpp | 26 +-
src/mathicgb/F4ProtoMatrix.hpp | 13 +-
src/mathicgb/F4Reducer.cpp | 70 +-
src/mathicgb/F4Reducer.hpp | 11 +-
src/mathicgb/FixedSizeMonomialMap.h | 66 +-
src/mathicgb/HashTourReducer.cpp | 12 +-
src/mathicgb/HashTourReducer.hpp | 16 +-
src/mathicgb/KoszulQueue.cpp | 7 -
src/mathicgb/KoszulQueue.hpp | 9 +-
src/mathicgb/LogDomain.cpp | 224 +-
src/mathicgb/LogDomain.hpp | 664 +++---
src/mathicgb/LogDomainSet.cpp | 6 +
src/mathicgb/LogDomainSet.hpp | 185 +-
src/mathicgb/MTArray.cpp | 9 +-
src/mathicgb/MTArray.hpp | 16 +-
src/mathicgb/MathicIO.cpp | 752 +++----
src/mathicgb/MathicIO.hpp | 287 +--
src/mathicgb/MonTableDivList.hpp | 17 +-
src/mathicgb/MonTableKDTree.hpp | 15 +-
src/mathicgb/MonTableNaive.cpp | 14 +-
src/mathicgb/MonTableNaive.hpp | 19 +-
src/mathicgb/MonoMonoid.hpp | 4023 ++++++++++++++++++-----------------
src/mathicgb/MonoOrder.hpp | 17 +-
src/mathicgb/MonoProcessor.hpp | 267 +--
src/mathicgb/MonomialHashTable.hpp | 14 +-
src/mathicgb/MonomialMap.hpp | 41 +-
src/mathicgb/NonCopyable.hpp | 49 +-
src/mathicgb/PairTriangle.cpp | 6 +
src/mathicgb/PairTriangle.hpp | 31 +-
src/mathicgb/Poly.cpp | 13 +-
src/mathicgb/Poly.hpp | 53 +-
src/mathicgb/PolyBasis.cpp | 8 +-
src/mathicgb/PolyBasis.hpp | 27 +-
src/mathicgb/PolyGeoBucket.cpp | 12 +-
src/mathicgb/PolyGeoBucket.hpp | 17 +-
src/mathicgb/PolyHashReducer.cpp | 11 +-
src/mathicgb/PolyHashReducer.hpp | 16 +-
src/mathicgb/PolyHashTable.cpp | 10 +-
src/mathicgb/PolyHashTable.hpp | 23 +-
src/mathicgb/PolyHeap.cpp | 10 +-
src/mathicgb/PolyHeap.hpp | 16 +-
src/mathicgb/PolyReducer.cpp | 10 +-
src/mathicgb/PolyReducer.hpp | 16 +-
src/mathicgb/PolyRing.cpp | 10 +-
src/mathicgb/PolyRing.hpp | 41 +-
src/mathicgb/PrimeField.hpp | 29 +-
src/mathicgb/QuadMatrix.cpp | 58 +-
src/mathicgb/QuadMatrix.hpp | 33 +-
src/mathicgb/QuadMatrixBuilder.cpp | 260 +--
src/mathicgb/QuadMatrixBuilder.hpp | 403 ++--
src/mathicgb/RawVector.hpp | 619 +++---
src/mathicgb/Reducer.cpp | 10 +-
src/mathicgb/Reducer.hpp | 16 +-
src/mathicgb/ReducerDedup.hpp | 20 +-
src/mathicgb/ReducerHash.hpp | 21 +-
src/mathicgb/ReducerHashPack.hpp | 21 +-
src/mathicgb/ReducerHelper.hpp | 14 +-
src/mathicgb/ReducerNoDedup.hpp | 20 +-
src/mathicgb/ReducerPack.hpp | 19 +-
src/mathicgb/ReducerPackDedup.hpp | 20 +-
src/mathicgb/SPairs.cpp | 6 +
src/mathicgb/SPairs.hpp | 45 +-
src/mathicgb/Scanner.cpp | 6 +
src/mathicgb/Scanner.hpp | 5 +
src/mathicgb/ScopeExit.hpp | 202 +-
src/mathicgb/SigPolyBasis.cpp | 7 +-
src/mathicgb/SigPolyBasis.hpp | 8 +-
src/mathicgb/SigSPairQueue.cpp | 47 +-
src/mathicgb/SigSPairQueue.hpp | 151 +-
src/mathicgb/SigSPairs.cpp | 10 +-
src/mathicgb/SigSPairs.hpp | 15 +-
src/mathicgb/SignatureGB.cpp | 10 +-
src/mathicgb/SignatureGB.hpp | 16 +-
src/mathicgb/SparseMatrix.cpp | 68 +-
src/mathicgb/SparseMatrix.hpp | 64 +-
src/mathicgb/TournamentReducer.cpp | 12 +-
src/mathicgb/TournamentReducer.hpp | 16 +-
src/mathicgb/TypicalReducer.cpp | 462 ++--
src/mathicgb/TypicalReducer.hpp | 148 +-
src/mathicgb/Unchar.hpp | 82 +-
src/mathicgb/io-util.cpp | 83 +-
src/mathicgb/io-util.hpp | 47 +-
src/mathicgb/mtbb.hpp | 368 ++--
src/mathicgb/stdinc.h | 14 +
src/test/F4MatrixBuilder.cpp | 360 ++--
src/test/F4MatrixReducer.cpp | 256 +--
src/test/MathicIO.cpp | 630 +++---
src/test/MonoMonoid.cpp | 1733 +++++++--------
src/test/PrimeField.cpp | 6 +-
src/test/QuadMatrixBuilder.cpp | 492 ++---
src/test/Scanner.cpp | 244 +--
src/test/SparseMatrix.cpp | 175 +-
src/test/gb-test.cpp | 12 +-
src/test/gtestInclude.cpp | 27 +-
src/test/ideals.cpp | 679 +++---
src/test/ideals.hpp | 135 +-
src/test/mathicgb.cpp | 1118 +++++-----
src/test/monoidPict.in | 58 +-
src/test/monoidPict.seed | 18 +-
src/test/pict.in | 116 +-
src/test/poly-test.cpp | 23 +-
src/test/testMain.cpp | 6 +
141 files changed, 9306 insertions(+), 8956 deletions(-)
diff --git a/src/checksource/CheckSource.cpp b/src/checksource/CheckSource.cpp
index 94773c5..3440b78 100755
--- a/src/checksource/CheckSource.cpp
+++ b/src/checksource/CheckSource.cpp
@@ -57,13 +57,14 @@ void checkCopyrightHeader(Scanner& in) {
"MathicGB comes with ABSOLUTELY\n";
const char* const l2 =
"// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.\n";
- in.match(l1);
- in.match(l2);
+ in.expect(l1);
+ in.expect(l2);
}
void checkStdInc(Scanner& in) {
in.eatWhite();
- in.expect("#include \"stdinc.h\"");
+ if (!in.match("#include \"mathicgb/stdinc.h\"\n"))
+ in.expect("#include \"stdinc.h\"\n");
}
void checkIncludes(Scanner& in) {
@@ -113,6 +114,9 @@ void checkInclusionGuard(Scanner& in, const std::string& filename) {
void checkOther(const std::string& filename) {
std::ifstream file(filename.c_str(), std::ios_base::binary);
+ file.peek();
+ if (!file)
+ error("could not open file");
Scanner in(file);
bool mgbNamespace = false;
while (!in.matchEOF()) {
@@ -142,6 +146,7 @@ void checkFile(std::string filename) {
const bool cpp = endsWith(filename, ".cpp");
if (!hpp && !cpp)
return;
+ checkOther(filename);
std::ifstream file(filename.c_str());
if (!file)
@@ -162,9 +167,6 @@ void checkFile(std::string filename) {
else
checkInclusionGuard(in, filename);
checkIncludes(in);
- file.close();
-
- checkOther(filename);
} catch (std::exception& e) {
std::cout << "*** ERROR in file " << filename << " ***\n"
<< e.what() << std::endl;
diff --git a/src/cli/CommonParams.cpp b/src/cli/CommonParams.cpp
index 8413491..29e7786 100755
--- a/src/cli/CommonParams.cpp
+++ b/src/cli/CommonParams.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
#include "CommonParams.hpp"
@@ -6,6 +8,8 @@
MATHICGB_DEFINE_LOG_ALIAS("default", "F4Detail,SPairs");
+MATHICGB_NAMESPACE_BEGIN
+
CommonParams::CommonParams(size_t minDirectParams, size_t maxDirectParams):
mTracingLevel("tracingLevel",
"How much information to print out about what the program does. No "
@@ -99,3 +103,5 @@ std::string CommonParams::inputFileNameExtension(size_t i) {
}
return std::string();
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/cli/CommonParams.hpp b/src/cli/CommonParams.hpp
old mode 100644
new mode 100755
index 9843706..9357eff
--- a/src/cli/CommonParams.hpp
+++ b/src/cli/CommonParams.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_COMMON_PARAMS_GUARD
#define MATHICGB_COMMON_PARAMS_GUARD
@@ -5,6 +7,8 @@
#include <mathic.h>
#include <vector>
+MATHICGB_NAMESPACE_BEGIN
+
class CommonParams {
public:
CommonParams(size_t minDirectParams, size_t maxDirectParams);
@@ -50,4 +54,6 @@ private:
std::vector<std::string> mDirectParameters;
};
+MATHICGB_NAMESPACE_END
+
#endif
diff --git a/src/cli/GBAction.cpp b/src/cli/GBAction.cpp
index 2aa818a..feaef86 100755
--- a/src/cli/GBAction.cpp
+++ b/src/cli/GBAction.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
#include "GBAction.hpp"
@@ -10,6 +12,8 @@
#include <fstream>
#include <iostream>
+MATHICGB_NAMESPACE_BEGIN
+
GBAction::GBAction():
mAutoTailReduce("autoTailReduce",
"Reduce the non-leading terms of all polynomials whenever an element "
@@ -136,3 +140,5 @@ void GBAction::pushBackParameters(
parameters.push_back(&mSPairGroupSize);
parameters.push_back(&mMinMatrixToStore);
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/cli/GBAction.hpp b/src/cli/GBAction.hpp
old mode 100644
new mode 100755
index 83849ff..4afbe0a
--- a/src/cli/GBAction.hpp
+++ b/src/cli/GBAction.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_G_B_ACTION_GUARD
#define MATHICGB_G_B_ACTION_GUARD
@@ -5,6 +7,8 @@
#include "CommonParams.hpp"
#include <mathic.h>
+MATHICGB_NAMESPACE_BEGIN
+
/// Calculates a classic Grobner basis using Buchberger's algorithm
class GBAction : public mathic::Action {
public:
@@ -35,4 +39,5 @@ private:
mathic::IntegerParameter mMinMatrixToStore;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/cli/GBCommonParams.cpp b/src/cli/GBCommonParams.cpp
index b2b4079..f541742 100755
--- a/src/cli/GBCommonParams.cpp
+++ b/src/cli/GBCommonParams.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
#include "GBCommonParams.hpp"
@@ -5,6 +7,8 @@
#include "mathicgb/PolyReducer.hpp"
#include "mathicgb/DivisorLookup.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
GBCommonParams::GBCommonParams():
mPreferSparseReducers("preferSparseReducers",
"If true, always use the sparsest reducer in polynomial reduction. "
@@ -88,3 +92,5 @@ void GBCommonParams::pushBackParameters(
void GBCommonParams::perform() {
// currently there is nothing to do
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/cli/GBCommonParams.hpp b/src/cli/GBCommonParams.hpp
index 04a4cfd..65441a5 100755
--- a/src/cli/GBCommonParams.hpp
+++ b/src/cli/GBCommonParams.hpp
@@ -1,8 +1,12 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_GB_COMMON_PARAMS_GUARD
#define MATHICGB_GB_COMMON_PARAMS_GUARD
#include <mathic.h>
+MATHICGB_NAMESPACE_BEGIN
+
class GBCommonParams {
public:
GBCommonParams();
@@ -21,4 +25,5 @@ public:
mathic::IntegerParameter mMemoryQuantum;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/cli/GBMain.cpp b/src/cli/GBMain.cpp
index e94f4c0..4c052a4 100755
--- a/src/cli/GBMain.cpp
+++ b/src/cli/GBMain.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
#include "GBAction.hpp"
@@ -10,13 +12,18 @@
#include <iostream>
#include <exception>
+// This is to satisfy the code checker that requires every file to contain
+// these macroes.
+MATHICGB_NAMESPACE_BEGIN
+MATHICGB_NAMESPACE_END
+
int main(int argc, char **argv) {
try {
mathic::CliParser parser;
- parser.registerAction<SigGBAction>();
- parser.registerAction<GBAction>();
- parser.registerAction<MatrixAction>();
- parser.registerAction<HelpAction>();
+ parser.registerAction<mgb::SigGBAction>();
+ parser.registerAction<mgb::GBAction>();
+ parser.registerAction<mgb::MatrixAction>();
+ parser.registerAction<mgb::HelpAction>();
std::vector<std::string> commandLine(argv, argv + argc);
commandLine.erase(commandLine.begin());
@@ -35,11 +42,6 @@ int main(int argc, char **argv) {
throw;
}
- LogDomainSet::singleton().printReport(std::cerr);
+ mgb::LogDomainSet::singleton().printReport(std::cerr);
return 0;
};
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/cli/HelpAction.cpp b/src/cli/HelpAction.cpp
index 6dd4590..73620c8 100755
--- a/src/cli/HelpAction.cpp
+++ b/src/cli/HelpAction.cpp
@@ -1,11 +1,14 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
#include "HelpAction.hpp"
#include "mathicgb/LogDomain.hpp"
#include "mathicgb/LogDomainSet.hpp"
-
#include <iostream>
+MATHICGB_NAMESPACE_BEGIN
+
void HelpAction::performAction() {
if (topic() != "logs") {
mathic::HelpAction::performAction();
@@ -78,3 +81,5 @@ void HelpAction::performAction() {
" all expands to all log names\n";
"\n";
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/cli/HelpAction.hpp b/src/cli/HelpAction.hpp
index 5bba19c..d263143 100755
--- a/src/cli/HelpAction.hpp
+++ b/src/cli/HelpAction.hpp
@@ -1,11 +1,17 @@
-#ifndef MATHICGB_HELP_ACTION_GUARD
-#define MATHICGB_HELP_ACTION_GUARD
-
-#include <mathic.h>
-
-class HelpAction : public mathic::HelpAction {
-public:
- virtual void performAction();
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_HELP_ACTION_GUARD
+#define MATHICGB_HELP_ACTION_GUARD
+
+#include <mathic.h>
+
+MATHICGB_NAMESPACE_BEGIN
+
+class HelpAction : public mathic::HelpAction {
+public:
+ virtual void performAction();
+};
+
+MATHICGB_NAMESPACE_END
+
+#endif
diff --git a/src/cli/MatrixAction.cpp b/src/cli/MatrixAction.cpp
old mode 100644
new mode 100755
index dd7c75f..d81b441
--- a/src/cli/MatrixAction.cpp
+++ b/src/cli/MatrixAction.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
#include "MatrixAction.hpp"
@@ -11,6 +13,8 @@
#include <fstream>
#include <iostream>
+MATHICGB_NAMESPACE_BEGIN
+
namespace {
static const char* QuadMatrixExtension = ".qmat";
static const char* LowerRightMatrixExtension = ".brmat";
@@ -24,13 +28,13 @@ namespace {
/// portable. There could be a solution with freopen, but unfortunately
/// freopen is allowed to fail on any change to the mode so it is not
/// a portable solution.
- bool fileExists(const std::string fileName) {
+ bool fileExists(const ::std::string fileName) {
return CFile(fileName, "r", CFile::NoThrowTag()).hasFile();
}
}
MatrixAction::MatrixAction():
- mParams(1, std::numeric_limits<size_t>::max()) {
+ mParams(1, ::std::numeric_limits<size_t>::max()) {
mParams.registerFileNameExtension(QuadMatrixExtension);
mParams.registerFileNameExtension(LowerRightMatrixExtension);
mParams.registerFileNameExtension(ReducedLowerRightMatrixExtension);
@@ -38,7 +42,7 @@ MatrixAction::MatrixAction():
}
void MatrixAction::directOptions(
- std::vector<std::string> tokens,
+ ::std::vector< ::std::string> tokens,
mic::CliParser& parser
) {
mParams.directOptions(tokens, parser);
@@ -53,7 +57,7 @@ void MatrixAction::performAction() {
const auto lowerRightFileName = fileNameStem + LowerRightMatrixExtension;
const auto reducedLowerRightFileName =
fileNameStem + ReducedLowerRightMatrixExtension;
- std::string inputFileName;
+ ::std::string inputFileName;
SparseMatrix lowerRightMatrix;
SparseMatrix::Scalar modulus;
@@ -99,10 +103,10 @@ void MatrixAction::performAction() {
referenceMatrix.read(file.handle());
if (lowerRightMatrix != referenceMatrix) {
- const std::string wrongFile =
+ const ::std::string wrongFile =
fileNameStem + ".out" + ReducedLowerRightMatrixExtension;
- const std::string wrongFilePbm = fileNameStem + ".out.pbm";
- std::cerr << "Reducing " << inputFileName
+ const ::std::string wrongFilePbm = fileNameStem + ".out.pbm";
+ ::std::cerr << "Reducing " << inputFileName
<< " does not yield the matrix "
<< reducedLowerRightFileName << ".\n"
<< "Writing computed matrix to " << wrongFile << ".\n";
@@ -111,7 +115,7 @@ void MatrixAction::performAction() {
CFile filePbm(wrongFilePbm, "wb");
lowerRightMatrix.writePBM(filePbm.handle());
} else if (tracingLevel > 0) {
- std::cerr << "Match for " << inputFileName
+ ::std::cerr << "Match for " << inputFileName
<< " -> " << ReducedLowerRightMatrixExtension << ".\n";
}
}
@@ -136,7 +140,9 @@ const char* MatrixAction::shortDescription() const {
}
void MatrixAction::pushBackParameters(
- std::vector<mic::CliParameter*>& parameters
+ ::std::vector<mic::CliParameter*>& parameters
) {
mParams.pushBackParameters(parameters);
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/cli/MatrixAction.hpp b/src/cli/MatrixAction.hpp
old mode 100644
new mode 100755
index 7156454..31c6147
--- a/src/cli/MatrixAction.hpp
+++ b/src/cli/MatrixAction.hpp
@@ -1,9 +1,13 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_MATRIX_ACTION_GUARD
#define MATHICGB_MATRIX_ACTION_GUARD
#include "CommonParams.hpp"
#include <mathic.h>
+MATHICGB_NAMESPACE_BEGIN
+
/// Performs computations on matrices.
class MatrixAction : public mathic::Action {
public:
@@ -28,4 +32,5 @@ private:
CommonParams mParams;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/cli/SigGBAction.cpp b/src/cli/SigGBAction.cpp
index 14eaee6..a18a587 100755
--- a/src/cli/SigGBAction.cpp
+++ b/src/cli/SigGBAction.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
#include "SigGBAction.hpp"
@@ -9,6 +11,8 @@
#include <fstream>
#include <iostream>
+MATHICGB_NAMESPACE_BEGIN
+
SigGBAction::SigGBAction():
mUseSingularCriterionEarly(
"earlySingularCriterion",
@@ -30,7 +34,7 @@ SigGBAction::SigGBAction():
{}
void SigGBAction::directOptions(
- std::vector<std::string> tokens,
+ ::std::vector< ::std::string> tokens,
mic::CliParser& parser
) {
mParams.directOptions(tokens, parser);
@@ -41,8 +45,8 @@ void SigGBAction::performAction() {
mGBParams.perform();
// read input file
- const std::string inputBasisFile = mParams.inputFileNameStem(0) + ".ideal";
- std::ifstream inputFile(inputBasisFile.c_str());
+ const ::std::string inputBasisFile = mParams.inputFileNameStem(0) + ".ideal";
+ ::std::ifstream inputFile(inputBasisFile.c_str());
if (inputFile.fail())
mic::reportError("Could not read input file \"" + inputBasisFile + '\n');
@@ -56,8 +60,8 @@ void SigGBAction::performAction() {
processor.setSchreyerMultipliers(basis);
SignatureGB alg(
- std::move(basis),
- std::move(processor),
+ ::std::move(basis),
+ ::std::move(processor),
Reducer::reducerType(mGBParams.mReducer.value()),
mGBParams.mDivisorLookup.value(),
mGBParams.mMonomialTable.value(),
@@ -71,10 +75,10 @@ void SigGBAction::performAction() {
alg.computeGrobnerBasis();
// print statistics
- alg.displayStats(std::cout);
- alg.displayPaperStats(std::cout);
+ alg.displayStats(::std::cout);
+ alg.displayPaperStats(::std::cout);
{
- std::ofstream statsOut((mParams.inputFileNameStem(0) + ".stats").c_str());
+ ::std::ofstream statsOut((mParams.inputFileNameStem(0) + ".stats").c_str());
alg.displayStats(statsOut);
alg.displayPaperStats(statsOut);
}
@@ -83,17 +87,17 @@ void SigGBAction::performAction() {
{
// print basis
{
- std::ofstream ogb((mParams.inputFileNameStem(0) + ".gb").c_str());
+ ::std::ofstream ogb((mParams.inputFileNameStem(0) + ".gb").c_str());
ogb << "-- gb: ----\n";
alg.getGB()->display(ogb);
}
// print syzygy basis
{
- std::ofstream syzygyOut((mParams.inputFileNameStem(0) + ".syz").c_str());
+ ::std::ofstream syzygyOut((mParams.inputFileNameStem(0) + ".syz").c_str());
syzygyOut << "-- syz: ----\n";
alg.getSyzTable()->display(syzygyOut, 1);
- syzygyOut << std::endl;
+ syzygyOut << ::std::endl;
}
}
}
@@ -116,7 +120,7 @@ const char* SigGBAction::shortDescription() const {
}
void SigGBAction::pushBackParameters(
- std::vector<mic::CliParameter*>& parameters
+ ::std::vector<mic::CliParameter*>& parameters
) {
mParams.pushBackParameters(parameters);
mGBParams.pushBackParameters(parameters);
@@ -124,3 +128,5 @@ void SigGBAction::pushBackParameters(
parameters.push_back(&mPostponeKoszul);
parameters.push_back(&mUseBaseDivisors);
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/cli/SigGBAction.hpp b/src/cli/SigGBAction.hpp
index c25e199..5c0fae7 100755
--- a/src/cli/SigGBAction.hpp
+++ b/src/cli/SigGBAction.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_SIG_G_B_ACTION_GUARD
#define MATHICGB_SIG_G_B_ACTION_GUARD
@@ -5,6 +7,8 @@
#include "CommonParams.hpp"
#include <mathic.h>
+MATHICGB_NAMESPACE_BEGIN
+
class SigGBAction : public mic::Action {
public:
SigGBAction();
@@ -32,4 +36,5 @@ private:
mic::BoolParameter mUseBaseDivisors;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb.cpp b/src/mathicgb.cpp
index 4ff4b61..388cea5 100755
--- a/src/mathicgb.cpp
+++ b/src/mathicgb.cpp
@@ -10,6 +10,8 @@
#include "mathicgb/LogDomainSet.hpp"
#include <mathic.h>
+using namespace mgb;
+
namespace {
bool isPrime(unsigned int n) {
if (n == 0 || n == 1)
diff --git a/src/mathicgb/Atomic.hpp b/src/mathicgb/Atomic.hpp
index 49c0690..aa5ef5f 100755
--- a/src/mathicgb/Atomic.hpp
+++ b/src/mathicgb/Atomic.hpp
@@ -1,10 +1,14 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_ATOMIC_GUARD
#define MATHICGB_ATOMIC_GUARD
-// We need this include for std::memory_order even if we are not
-// using std::atomic.
+// We need this include for ::std::memory_order even if we are not
+// using ::std::atomic.
#include <atomic>
+MATHICGB_NAMESPACE_BEGIN
+
namespace AtomicInternal {
/// Tells the compiler (not the CPU) to not reorder reads across this line.
inline void compilerReadMemoryBarrier();
@@ -96,8 +100,8 @@ namespace AtomicInternal {
public:
FakeAtomic(): mValue() {}
FakeAtomic(T value): mValue(value) {}
- T load(const std::memory_order) const {return mValue;}
- void store(const T value, const std::memory_order order) {mValue = value;}
+ T load(const ::std::memory_order) const {return mValue;}
+ void store(const T value, const ::std::memory_order order) {mValue = value;}
private:
T mValue;
@@ -110,11 +114,11 @@ namespace AtomicInternal {
#else
/// Class for deciding which implementation of atomic to use. The default is
- /// to use std::atomic which is a fine choice if std::atomic is implemented
+ /// to use ::std::atomic which is a fine choice if ::std::atomic is implemented
/// in a reasonable way by the standard library implementation you are using.
template<class T, size_t size>
struct ChooseAtomic {
- typedef std::atomic<T> type;
+ typedef ::std::atomic<T> type;
};
#endif
}
@@ -126,7 +130,7 @@ namespace AtomicInternal {
/// writes are guaranteed to be atomic - this class only takes care of the
/// ordering constraints using CPU and compiler fences. Since the directives
/// to achieve this are coming from the compiler it is surprising that
- /// any compiler ships with a std::atomic that is worse than this - but
+ /// any compiler ships with a ::std::atomic that is worse than this - but
/// that is very much the case. Though implementing atomic load and store
/// is very little code, as you can see, it is quite tricky and took me
/// a long time to understand everything well enough to actually know what
@@ -182,9 +186,9 @@ namespace AtomicInternal {
CustomAtomicX86X64(T value): mValue(value) {}
MATHICGB_INLINE
- T load(const std::memory_order order) const {
+ T load(const ::std::memory_order order) const {
switch (order) {
- case std::memory_order_relaxed:
+ case ::std::memory_order_relaxed:
// There are two constraints for memory_order_relaxed. The first
// constraint is that if you read *p, then you will never
// after that read a value of *p that was stored before the value
@@ -199,7 +203,7 @@ namespace AtomicInternal {
// this constraint is broken, but clearly the written value must turn
// up eventually. This constraint could be broken in cases like this:
//
- // while (x.load(std::memory_order_relaxed) == 0) {
+ // while (x.load(::std::memory_order_relaxed) == 0) {
// // do something that does not write to x
// }
//
@@ -208,7 +212,7 @@ namespace AtomicInternal {
// the value for every iteration, so the code can safely be transformed
// to:
//
- // if (x.load(std::memory_order_relaxed) == 0) {
+ // if (x.load(::std::memory_order_relaxed) == 0) {
// while (true) {
// // ...
// }
@@ -229,7 +233,7 @@ namespace AtomicInternal {
// volatile read since it is the best choice on GCC.
return const_cast<volatile T&>(mValue);
- case std::memory_order_consume: {
+ case ::std::memory_order_consume: {
// Loads in this thread that depend on the loaded value must not be
// reordered to before this load. So no DLL reorderings past this
// load from after to before (up). So we need a read barrier AFTER the
@@ -240,7 +244,7 @@ namespace AtomicInternal {
return value;
}
- case std::memory_order_acquire: {
+ case ::std::memory_order_acquire: {
// Loads in this thread must not be reordered to before this load.
// So no LL reorderings past this load from after to before (up).
// So we need a read barrier AFTER the load. It is a compiler only
@@ -250,35 +254,35 @@ namespace AtomicInternal {
return value;
}
- case std::memory_order_seq_cst: {
+ case ::std::memory_order_seq_cst: {
// There must be some global order in which all sequentially consistent
// atomic operations are considered to have happened in. On x86 and x64
// this is guaranteed by just a normal read as long as all writes use
// locked instructions like XHCG. See: http://goo.gl/U8xTK
//
// We still need to prevent the compiler from reordering the reads,
- // which is the same constraint as for std::memory_order_acquire.
+ // which is the same constraint as for ::std::memory_order_acquire.
const auto value = mValue;
compilerReadMemoryBarrier();
return value;
}
- case std::memory_order_release: // not available for load
- case std::memory_order_acq_rel: // not available for load
- default: // specified value is not a known std::memory_order
+ case ::std::memory_order_release: // not available for load
+ case ::std::memory_order_acq_rel: // not available for load
+ default: // specified value is not a known ::std::memory_order
MATHICGB_UNREACHABLE;
}
}
MATHICGB_INLINE
- void store(const T value, const std::memory_order order) {
+ void store(const T value, const ::std::memory_order order) {
switch (order) {
- case std::memory_order_relaxed:
+ case ::std::memory_order_relaxed:
// There are no reordering constraints here but we need to tell the
// compiler that it must actually write out the value to memory in
// a scenario like this:
//
- // x.store(1, std::memory_order_relaxed);
+ // x.store(1, ::std::memory_order_relaxed);
// while (true) {}
//
// So as for relaxed store we need either a volatile access or a memory
@@ -287,7 +291,7 @@ namespace AtomicInternal {
const_cast<volatile T&>(mValue) = value;
break;
- case std::memory_order_release:
+ case ::std::memory_order_release:
// Stores in this thread must not be reordered to after this store.
// So no SS reorderings past this load from before to after (down).
// So we need a barrier BEFORE the load. It is a compiler only barrier
@@ -296,9 +300,9 @@ namespace AtomicInternal {
mValue = value;
break;
- case std::memory_order_acq_rel:
- // Combine the guarantees for std::memory_order_acquire and
- // std::memory_order_release. So no loads moved up past here (SL) and
+ case ::std::memory_order_acq_rel:
+ // Combine the guarantees for ::std::memory_order_acquire and
+ // ::std::memory_order_release. So no loads moved up past here (SL) and
// no stores moved down past here (LL). We need a compiler barrier
// BEFORE the load to avoid LL and a CPU (+compiler) barrier AFTER the
// load to avoid SL, since x86 and x64 CPUs can in fact do SL
@@ -308,14 +312,14 @@ namespace AtomicInternal {
cpuReadWriteMemoryBarrier();
break;
- case std::memory_order_seq_cst:
+ case ::std::memory_order_seq_cst:
// All operations happen in a globally consistent total order.
seqCstStore(value, mValue);
break;
- case std::memory_order_consume: // not available for store
- case std::memory_order_acquire: // not available for store
- default: // specified value is not a known std::memory_order
+ case ::std::memory_order_consume: // not available for store
+ case ::std::memory_order_acquire: // not available for store
+ default: // specified value is not a known ::std::memory_order
MATHICGB_UNREACHABLE;
}
}
@@ -340,18 +344,18 @@ namespace AtomicInternal {
}
#endif
-/// This class is equivalent to std::atomic<T>. Some functions from the
-/// interface of std::atomic are missing - add them as necessary. Do not add
+/// This class is equivalent to ::std::atomic<T>. Some functions from the
+/// interface of ::std::atomic are missing - add them as necessary. Do not add
/// operator= and operator T() --- it is better to make the code explicit
/// about when and how loading and storing of atomic variables occurs.
///
/// The purpose of the class is that it performs far better than
-/// std::atomic for some implementations. For example the std::atomic in MSVC
+/// ::std::atomic for some implementations. For example the ::std::atomic in MSVC
/// 2012 performs a compare-and-swap operation on a load even with the
-/// paramter std::memory_order_relaxed.
+/// paramter ::std::memory_order_relaxed.
///
/// We force all the functions to be inline because they can contain switches
-/// on the value of std::memory_order. This will usually be a compile-time
+/// on the value of ::std::memory_order. This will usually be a compile-time
/// constant parameter so that after inlining the switch will disappear. Yet
/// the code size of the switch may make some compilers avoid the inline.
template<class T>
@@ -361,7 +365,7 @@ public:
Atomic(T value): mValue(value) {}
MATHICGB_INLINE
- T load(const std::memory_order order = std::memory_order_seq_cst) const {
+ T load(const ::std::memory_order order = ::std::memory_order_seq_cst) const {
MATHICGB_ASSERT(debugAligned());
return mValue.load(order);
}
@@ -369,7 +373,7 @@ public:
MATHICGB_INLINE
void store(
const T value,
- const std::memory_order order = std::memory_order_seq_cst
+ const ::std::memory_order order = ::std::memory_order_seq_cst
) {
MATHICGB_ASSERT(debugAligned());
mValue.store(value, order);
@@ -386,4 +390,5 @@ private:
typename AtomicInternal::ChooseAtomic<T, sizeof(T)>::type mValue;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/Basis.cpp b/src/mathicgb/Basis.cpp
index 9e3c201..e416afb 100755
--- a/src/mathicgb/Basis.cpp
+++ b/src/mathicgb/Basis.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "Basis.hpp"
@@ -9,6 +11,8 @@
#include <iostream>
#include <cctype>
+MATHICGB_NAMESPACE_BEGIN
+
void Basis::insert(std::unique_ptr<Poly>&& p) {
MATHICGB_ASSERT(p.get() != 0);
MATHICGB_ASSERT(p->termsAreInDescendingOrder());
@@ -36,7 +40,4 @@ void Basis::display(std::ostream& out, bool printComponent, bool componentIncrea
}
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/Basis.hpp b/src/mathicgb/Basis.hpp
index 3afbf11..44af198 100755
--- a/src/mathicgb/Basis.hpp
+++ b/src/mathicgb/Basis.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_BASIS_GUARD
#define MATHICGB_BASIS_GUARD
@@ -8,6 +10,8 @@
#include <algorithm>
#include <vector>
+MATHICGB_NAMESPACE_BEGIN
+
class Poly;
// Really: a list of polynomials
@@ -15,17 +19,22 @@ class Poly;
class Basis {
public:
Basis(const PolyRing &R) : mRing(R) {}
- Basis(Basis&& basis): mRing(basis.ring()), mGenerators(std::move(basis.mGenerators)) {}
+ Basis(Basis&& basis):
+ mRing(basis.ring()), mGenerators(::std::move(basis.mGenerators)) {}
- void insert(std::unique_ptr<Poly>&& p);
+ void insert(::std::unique_ptr<Poly>&& p);
/// inverse operation to parse().
- void display(std::ostream &o, bool print_comp, bool componentIncreasingDesired) const;
+ void display(
+ ::std::ostream &o,
+ bool print_comp,
+ bool componentIncreasingDesired
+ ) const;
const PolyRing& ring() const { return mRing; }
const PolyRing *getPolyRing() const { return &mRing; }
- const std::vector<std::unique_ptr<Poly>>& viewGenerators() {
+ const ::std::vector< ::std::unique_ptr<Poly>>& viewGenerators() {
return mGenerators;
}
const Poly *getPoly(size_t i) const {
@@ -42,12 +51,8 @@ private:
Basis(const Basis&); // not available
const PolyRing& mRing;
- std::vector<std::unique_ptr<Poly>> mGenerators;
+ ::std::vector< ::std::unique_ptr<Poly>> mGenerators;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/BjarkeGeobucket.cpp b/src/mathicgb/BjarkeGeobucket.cpp
old mode 100644
new mode 100755
index 9e27781..2937fdf
--- a/src/mathicgb/BjarkeGeobucket.cpp
+++ b/src/mathicgb/BjarkeGeobucket.cpp
@@ -1,8 +1,10 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "BjarkeGeobucket.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
BjarkeGeobucket::BjarkeGeobucket(const PolyRing *R0)
: Reducer(),
R_(R0),
@@ -127,7 +129,4 @@ void BjarkeGeobucket::dump() const
H_.dump(0);
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/BjarkeGeobucket.hpp b/src/mathicgb/BjarkeGeobucket.hpp
index 35e638c..9fce567 100755
--- a/src/mathicgb/BjarkeGeobucket.hpp
+++ b/src/mathicgb/BjarkeGeobucket.hpp
@@ -1,11 +1,13 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_BJARKE_GEOBUCKET_GUARD
+#define MATHICGB_BJARKE_GEOBUCKET_GUARD
-#ifndef _bjarkeGeoBucket_h_
-#define _bjarkeGeoBucket_h_
-
-#include <mathic.h>
#include "Reducer.hpp"
#include "PolyHashTable.hpp"
+#include <mathic.h>
+
+MATHICGB_NAMESPACE_BEGIN
template<
bool TrackFront,
@@ -95,9 +97,5 @@ private:
mic::Geobucket< Configuration > G_;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/BjarkeGeobucket2.cpp b/src/mathicgb/BjarkeGeobucket2.cpp
index 5468f74..61ef930 100755
--- a/src/mathicgb/BjarkeGeobucket2.cpp
+++ b/src/mathicgb/BjarkeGeobucket2.cpp
@@ -1,9 +1,12 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "BjarkeGeobucket2.hpp"
#include <iostream>
+MATHICGB_NAMESPACE_BEGIN
+
BjarkeGeobucket2::BjarkeGeobucket2(const PolyRing *R0):
mRing(*R0),
mHashTableOLD(R0, 10),
@@ -125,7 +128,4 @@ void BjarkeGeobucket2::dump() const
mHashTableOLD.dump(0);
}
-// Local Variables:
-// compile-command: "make -C $MATHIC/mathicgb "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/BjarkeGeobucket2.hpp b/src/mathicgb/BjarkeGeobucket2.hpp
index 016a35a..2f4443c 100755
--- a/src/mathicgb/BjarkeGeobucket2.hpp
+++ b/src/mathicgb/BjarkeGeobucket2.hpp
@@ -1,11 +1,13 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_BJARKE_GEOBUCKET2_GUARD
+#define MATHICGB_BJARKE_GEOBUCKET2_GUARD
-#ifndef _bjarkeGeoBucket_h_
-#define _bjarkeGeoBucket_h_
-
-#include <mathic.h>
#include "TypicalReducer.hpp"
#include "PolyHashTable.hpp"
+#include <mathic.h>
+
+MATHICGB_NAMESPACE_BEGIN
class GeoConfiguration {
public:
@@ -105,9 +107,5 @@ private:
mic::Geobucket< GeoConfiguration > mHeap;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// indent-tabs-mode: nil
-// compile-command: "make -C $MATHIC/mathicgb "
-// End:
diff --git a/src/mathicgb/CFile.cpp b/src/mathicgb/CFile.cpp
index b882aa0..025010d 100755
--- a/src/mathicgb/CFile.cpp
+++ b/src/mathicgb/CFile.cpp
@@ -1,28 +1,34 @@
-#include "stdinc.h"
-#include "CFile.hpp"
-
-#include <mathic.h>
-#include <sstream>
-
-CFile::CFile(const std::string& fileName, const char* mode, NoThrowTag):
- mFile(fopen(fileName.c_str(), mode)
-) {}
-
-CFile::CFile(const std::string& fileName, const char* mode):
- mFile(fopen(fileName.c_str(), mode)
-) {
- if (mFile == 0) {
- std::ostringstream error;
- error << "Could not open file " << fileName << " in mode " << mode << '.';
- mathic::reportError(error.str());
- }
-}
-
-CFile::~CFile() {
- close();
-}
-
-void CFile::close() {
- if (mFile != 0)
- fclose(mFile);
-}
\ No newline at end of file
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "stdinc.h"
+#include "CFile.hpp"
+
+#include <mathic.h>
+#include <sstream>
+
+MATHICGB_NAMESPACE_BEGIN
+
+CFile::CFile(const std::string& fileName, const char* mode, NoThrowTag):
+ mFile(fopen(fileName.c_str(), mode)
+) {}
+
+CFile::CFile(const std::string& fileName, const char* mode):
+ mFile(fopen(fileName.c_str(), mode)
+) {
+ if (mFile == 0) {
+ std::ostringstream error;
+ error << "Could not open file " << fileName << " in mode " << mode << '.';
+ mathic::reportError(error.str());
+ }
+}
+
+CFile::~CFile() {
+ close();
+}
+
+void CFile::close() {
+ if (mFile != 0)
+ fclose(mFile);
+}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/CFile.hpp b/src/mathicgb/CFile.hpp
index 1474443..257e239 100755
--- a/src/mathicgb/CFile.hpp
+++ b/src/mathicgb/CFile.hpp
@@ -1,37 +1,42 @@
-#ifndef MATHICGB_C_FILE_GUARD
-#define MATHICGB_C_FILE_GUARD
-
-#include <string>
-#include <cstdio>
-
-/// RAII handle for a C FILE*.
-///
-/// The purpose of using the C IO interface instead of iostreams is that the
-/// former is faster to a ridiculous degree. This class wraps the C IO
-/// interface to be more useful in a C++ context. For example the file is
-/// automatically closed in the destructor and if the file cannot be opened
-/// then an exception is thrown instead of returning a null pointer.
-class CFile {
-public:
- struct NoThrowTag {};
-
- /// Sets the handle to null if the file cannot be opened - does not
- /// throw an exception. The purpose of the NoTrowTag parameter is only
- /// to indicate that no exception should be thrown on error.
- CFile(const std::string& fileName, const char* mode, NoThrowTag);
-
- /// Opens the file and throws an exception if the file cannot be opened.
- CFile(const std::string& fileName, const char* mode);
-
- ~CFile();
-
- bool hasFile() const {return mFile != 0;}
-
- FILE* handle() {return mFile;}
- void close();
-
-private:
- FILE* mFile;
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_C_FILE_GUARD
+#define MATHICGB_C_FILE_GUARD
+
+#include <string>
+#include <cstdio>
+
+MATHICGB_NAMESPACE_BEGIN
+
+/// RAII handle for a C FILE*.
+///
+/// The purpose of using the C IO interface instead of iostreams is that the
+/// former is faster to a ridiculous degree. This class wraps the C IO
+/// interface to be more useful in a C++ context. For example the file is
+/// automatically closed in the destructor and if the file cannot be opened
+/// then an exception is thrown instead of returning a null pointer.
+class CFile {
+public:
+ struct NoThrowTag {};
+
+ /// Sets the handle to null if the file cannot be opened - does not
+ /// throw an exception. The purpose of the NoTrowTag parameter is only
+ /// to indicate that no exception should be thrown on error.
+ CFile(const ::std::string& fileName, const char* mode, NoThrowTag);
+
+ /// Opens the file and throws an exception if the file cannot be opened.
+ CFile(const ::std::string& fileName, const char* mode);
+
+ ~CFile();
+
+ bool hasFile() const {return mFile != 0;}
+
+ FILE* handle() {return mFile;}
+ void close();
+
+private:
+ FILE* mFile;
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/ChainedHashTable.cpp b/src/mathicgb/ChainedHashTable.cpp
old mode 100644
new mode 100755
index a68487a..97191be
--- a/src/mathicgb/ChainedHashTable.cpp
+++ b/src/mathicgb/ChainedHashTable.cpp
@@ -1,11 +1,10 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "ChainedHashTable.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
template class ChainedHashTable<HashControlExample>;
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/ChainedHashTable.hpp b/src/mathicgb/ChainedHashTable.hpp
old mode 100644
new mode 100755
index f6e3cef..b2a1c42
--- a/src/mathicgb/ChainedHashTable.hpp
+++ b/src/mathicgb/ChainedHashTable.hpp
@@ -1,14 +1,14 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _chainedHashTable_h_
-#define _chainedHashTable_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_CHAINED_HASH_TABLE_GUARD
+#define MATHICGB_CHAINED_HASH_TABLE_GUARD
#include <vector>
#include <iostream>
-
+#include <ostream>
#include <memtailor.h>
-class ostream;
+MATHICGB_NAMESPACE_BEGIN
// One template parameter, with the following:
// types:
@@ -281,10 +281,5 @@ void ChainedHashTable<HashControl>::dump(int level) const
}
}
-
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/ClassicGBAlg.cpp b/src/mathicgb/ClassicGBAlg.cpp
index 5603cd7..f4447f3 100755
--- a/src/mathicgb/ClassicGBAlg.cpp
+++ b/src/mathicgb/ClassicGBAlg.cpp
@@ -1,15 +1,20 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "ClassicGBAlg.hpp"
-#include "Basis.hpp"
+#include "Basis.hpp"
#include "LogDomain.hpp"
#include <iostream>
MATHICGB_DEFINE_LOG_DOMAIN(
SPairDegree,
- "Displays the degree of the S-pairs being considered in Buchberger's algorithm."
+ "Displays the degree of the S-pairs being considered in "
+ "Buchberger's algorithm."
);
+MATHICGB_NAMESPACE_BEGIN
+
ClassicGBAlg::ClassicGBAlg(
const Basis& basis,
Reducer& reducer,
@@ -545,7 +550,4 @@ void ClassicGBAlg::printMemoryUse(std::ostream& out) const
out << "*** Memory use by component ***\n" << pr << std::flush;
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/ClassicGBAlg.hpp b/src/mathicgb/ClassicGBAlg.hpp
index 7c9839d..f98af63 100755
--- a/src/mathicgb/ClassicGBAlg.hpp
+++ b/src/mathicgb/ClassicGBAlg.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_CLASSIC_GB_ALG_GUARD
#define MATHICGB_CLASSIC_GB_ALG_GUARD
@@ -9,6 +11,8 @@
#include <ostream>
#include <vector>
+MATHICGB_NAMESPACE_BEGIN
+
class Basis;
/// Calculates a classic Grobner basis using Buchberger's algorithm.
@@ -99,4 +103,5 @@ private:
unsigned long long mSPolyReductionCount;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/DivLookup.hpp b/src/mathicgb/DivLookup.hpp
index ae55b12..806ac79 100755
--- a/src/mathicgb/DivLookup.hpp
+++ b/src/mathicgb/DivLookup.hpp
@@ -1,13 +1,16 @@
-#ifndef __div_lookup_guard_
-#define __div_lookup_guard_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_DIV_LOOKUP_GUARD
+#define MATHICGB_DIV_LOOKUP_GUARD
+#include "SigPolyBasis.hpp"
+#include "DivisorLookup.hpp"
+#include "PolyRing.hpp"
#include <string>
#include <vector>
#include <iostream>
-#include "SigPolyBasis.hpp"
-#include "DivisorLookup.hpp"
-#include "PolyRing.hpp"
+MATHICGB_NAMESPACE_BEGIN
/** Configuration class for interface to KDTree, DivList */
/* As such, it has entries that both will expect */
@@ -602,9 +605,5 @@ size_t DivLookup<C>::getMemoryUse() const
return 4 * sizeof(void *) * _finder.size(); // NOT CORRECT!!
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/DivisorLookup.cpp b/src/mathicgb/DivisorLookup.cpp
index 2d280c3..04102dd 100755
--- a/src/mathicgb/DivisorLookup.cpp
+++ b/src/mathicgb/DivisorLookup.cpp
@@ -1,11 +1,13 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "DivisorLookup.hpp"
-#include <mathic.h>
#include "SigPolyBasis.hpp"
#include "DivLookup.hpp"
+#include <mathic.h>
+
+MATHICGB_NAMESPACE_BEGIN
namespace {
struct DefaultParams {
@@ -123,7 +125,4 @@ void DivisorLookup::displayDivisorLookupTypes(std::ostream &o)
o << " 4 kdtree" << std::endl;
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/DivisorLookup.hpp b/src/mathicgb/DivisorLookup.hpp
index 4ac6997..009de78 100755
--- a/src/mathicgb/DivisorLookup.hpp
+++ b/src/mathicgb/DivisorLookup.hpp
@@ -1,11 +1,13 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _divisor_lookup_h_
-#define _divisor_lookup_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_DIVISOR_LOOKUP_GUARD
+#define MATHICGB_DIVISOR_LOOKUP_GUARD
#include "PolyRing.hpp"
#include <vector>
+MATHICGB_NAMESPACE_BEGIN
+
class PolyBasis;
class SigPolyBasis;
@@ -38,27 +40,28 @@ public:
// but the outcome must be deterministic.
virtual size_t classicReducer(const_monomial mon) const = 0;
- virtual std::string getName() const = 0;
+ virtual ::std::string getName() const = 0;
virtual size_t getMemoryUse() const = 0;
virtual size_t highBaseDivisor(size_t newGenerator) const = 0;
virtual void lowBaseDivisors(
- std::vector<size_t>& divisors,
+ ::std::vector<size_t>& divisors,
size_t maxDivisors,
size_t newGenerator) const = 0;
virtual size_t minimalLeadInSig(const_monomial sig) const = 0;
virtual int type() const = 0;
- static void displayDivisorLookupTypes(std::ostream &o);
+ static void displayDivisorLookupTypes(::std::ostream &o);
class Factory {
public:
- virtual std::unique_ptr<DivisorLookup> create
+ virtual ::std::unique_ptr<DivisorLookup> create
(bool preferSparseReducers, bool allowRemovals) const = 0;
};
- static std::unique_ptr<Factory> makeFactory(const PolyRing& ring, int type);
+ static ::std::unique_ptr<Factory> makeFactory
+ (const PolyRing& ring, int type);
// choices for type: 1: divlist, 2:kdtree.
class EntryOutput {
@@ -88,9 +91,5 @@ public:
virtual size_t size() const = 0;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/F4MatrixBuilder.cpp b/src/mathicgb/F4MatrixBuilder.cpp
index a23b43e..c5bf37f 100755
--- a/src/mathicgb/F4MatrixBuilder.cpp
+++ b/src/mathicgb/F4MatrixBuilder.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "F4MatrixBuilder.hpp"
@@ -9,8 +11,10 @@ MATHICGB_DEFINE_LOG_DOMAIN(
"Displays statistics about F4 matrix construction."
);
+MATHICGB_NAMESPACE_BEGIN
+
MATHICGB_NO_INLINE
-std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
+::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
F4MatrixBuilder::findOrCreateColumn(
const const_monomial monoA,
const const_monomial monoB,
@@ -20,12 +24,12 @@ F4MatrixBuilder::findOrCreateColumn(
MATHICGB_ASSERT(!monoB.isNull());
const auto col = ColReader(mMap).findProduct(monoA, monoB);
if (col.first != 0)
- return std::make_pair(*col.first, col.second);
+ return ::std::make_pair(*col.first, col.second);
return createColumn(monoA, monoB, feeder);
}
MATHICGB_INLINE
-std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
+::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
F4MatrixBuilder::findOrCreateColumn(
const const_monomial monoA,
const const_monomial monoB,
@@ -37,7 +41,7 @@ F4MatrixBuilder::findOrCreateColumn(
const auto col = colMap.findProduct(monoA, monoB);
if (col.first == 0)
return findOrCreateColumn(monoA, monoB, feeder);
- return std::make_pair(*col.first, col.second);
+ return ::std::make_pair(*col.first, col.second);
}
MATHICGB_NO_INLINE
@@ -66,7 +70,7 @@ F4MatrixBuilder::F4MatrixBuilder(
{
// This assert to be _NO_ASSUME since otherwise the compiler will assume that
// the error checking branch here cannot be taken and optimize it away.
- const Scalar maxScalar = std::numeric_limits<Scalar>::max();
+ const Scalar maxScalar = ::std::numeric_limits<Scalar>::max();
MATHICGB_ASSERT_NO_ASSUME(ring().charac() <= maxScalar);
if (ring().charac() > maxScalar)
mathic::reportInternalError("F4MatrixBuilder: too large characteristic.");
@@ -143,7 +147,7 @@ void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) {
data.tmp1 = ring().allocMonomial();
data.tmp2 = ring().allocMonomial();
}
- return std::move(data);
+ return ::std::move(data);
});
mgb::tbb::parallel_do(mTodo.begin(), mTodo.end(),
@@ -226,7 +230,7 @@ void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) {
mMap.clearNonConcurrent();
}
-std::pair<F4MatrixBuilder::LeftRightColIndex, ConstMonomial>
+::std::pair<F4MatrixBuilder::LeftRightColIndex, ConstMonomial>
F4MatrixBuilder::createColumn(
const const_monomial monoA,
const const_monomial monoB,
@@ -240,7 +244,7 @@ F4MatrixBuilder::createColumn(
{
const auto found(ColReader(mMap).findProduct(monoA, monoB));
if (found.first != 0)
- return std::make_pair(*found.first, found.second);
+ return ::std::make_pair(*found.first, found.second);
}
// The column really does not exist, so we need to create it
@@ -254,10 +258,10 @@ F4MatrixBuilder::createColumn(
// Create the new left or right column
auto& colCount = insertLeft ? mLeftColCount : mRightColCount;
- if (colCount == std::numeric_limits<ColIndex>::max())
- throw std::overflow_error("Too many columns in QuadMatrix");
+ 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)));
+ (::std::make_pair(mTmp, LeftRightColIndex(colCount, insertLeft)));
++colCount;
MATHICGB_ASSERT(inserted.second);
MATHICGB_ASSERT(inserted.first.first != 0);
@@ -271,7 +275,7 @@ F4MatrixBuilder::createColumn(
feeder.add(task);
}
- return std::make_pair(*inserted.first.first, inserted.first.second);
+ return ::std::make_pair(*inserted.first.first, inserted.first.second);
}
void F4MatrixBuilder::appendRowBottom(
@@ -303,7 +307,7 @@ updateReader:
MATHICGB_ASSERT(origScalar != 0);
const auto maybeNegated =
negate ? ring().coefficientNegateNonZero(origScalar) : origScalar;
- MATHICGB_ASSERT(maybeNegated < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(maybeNegated < ::std::numeric_limits<Scalar>::max());
builder.appendEntryBottom(*col.first, static_cast<Scalar>(maybeNegated));
}
builder.rowDoneBottomLeftAndRight();
@@ -321,11 +325,11 @@ void F4MatrixBuilder::appendRowTop(
auto it = poly.begin();
const auto end = poly.end();
- if ((std::distance(it, end) % 2) == 1) {
+ if ((::std::distance(it, end) % 2) == 1) {
ColReader reader(mMap);
const auto col = findOrCreateColumn
(it.getMonomial(), multiple, reader, feeder);
- MATHICGB_ASSERT(it.getCoefficient() < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(it.getCoefficient() < ::std::numeric_limits<Scalar>::max());
MATHICGB_ASSERT(it.getCoefficient());
builder.appendEntryTop
(col.first, static_cast<Scalar>(it.getCoefficient()));
@@ -333,16 +337,16 @@ void F4MatrixBuilder::appendRowTop(
}
updateReader:
ColReader colMap(mMap);
- MATHICGB_ASSERT((std::distance(it, end) % 2) == 0);
+ MATHICGB_ASSERT((::std::distance(it, end) % 2) == 0);
while (it != end) {
- MATHICGB_ASSERT(it.getCoefficient() < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(it.getCoefficient() < ::std::numeric_limits<Scalar>::max());
MATHICGB_ASSERT(it.getCoefficient() != 0);
const auto scalar1 = static_cast<Scalar>(it.getCoefficient());
const const_monomial mono1 = it.getMonomial();
auto it2 = it;
++it2;
- MATHICGB_ASSERT(it2.getCoefficient() < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(it2.getCoefficient() < ::std::numeric_limits<Scalar>::max());
MATHICGB_ASSERT(it2.getCoefficient() != 0);
const auto scalar2 = static_cast<Scalar>(it2.getCoefficient());
const const_monomial mono2 = it2.getMonomial();
@@ -420,8 +424,10 @@ void F4MatrixBuilder::appendRowBottom(
col = colB.first;
++itB;
}
- MATHICGB_ASSERT(coeff < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(coeff < ::std::numeric_limits<Scalar>::max());
if (coeff != 0)
builder.appendEntryBottom(col, static_cast<Scalar>(coeff));
}
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/F4MatrixBuilder.hpp b/src/mathicgb/F4MatrixBuilder.hpp
index 9e3f267..91a53e6 100755
--- a/src/mathicgb/F4MatrixBuilder.hpp
+++ b/src/mathicgb/F4MatrixBuilder.hpp
@@ -1,157 +1,163 @@
-#ifndef F4_MATRIX_BUILDER_GUARD
-#define F4_MATRIX_BUILDER_GUARD
-
-#include "QuadMatrixBuilder.hpp"
-#include "Poly.hpp"
-#include "PolyRing.hpp"
-#include "PolyBasis.hpp"
-#include "QuadMatrix.hpp"
-#include "mtbb.hpp"
-#include <vector>
-
-/** Class for constructing an F4 matrix. This class is reponsible for
- figuring out what matrix to build and then it uses QuadMatrixBuilder
- to create that matrix.
-
- @todo: this class does not offer exception guarantees. It's just not
- very workable without an RAII monomial handle, so add one of those
- before fixing this. */
-class F4MatrixBuilder {
-private:
- typedef QuadMatrixBuilder::ColIndex ColIndex;
- typedef QuadMatrixBuilder::LeftRightColIndex LeftRightColIndex;
- typedef QuadMatrixBuilder::Scalar Scalar;
- typedef QuadMatrixBuilder::Map Map;
- typedef QuadMatrixBuilder::MonomialsType Monomials;
-
-public:
- /// memoryQuantum is how much to increase the memory size by each time the
- /// current amount of memory is exhausted. A value of 0 indicates to start
- /// small and double the quantum at each exhaustion.
- F4MatrixBuilder(const PolyBasis& basis, size_t memoryQuantum = 0);
-
- /** Schedules a row representing the S-polynomial between polyA and
- polyB to be added to the matrix. No ownership is taken, but polyA
- and polyB must remain valid until the matrix is constructed.
-
- Currently, the two monomials must be monic, though this is just
- because they always happen to be monic so there was no reason to
- support the non-monic case. */
- void addSPolynomialToMatrix(const Poly& polyA, const Poly& polyB);
-
- /** Schedules a row representing multiple*poly to be added to the
- matrix. No ownership is taken, but poly must remain valid until
- the matrix is constructed. multiple is copied so it need not
- remain valid. */
- void addPolynomialToMatrix(const_monomial multiple, const Poly& poly);
-
- /// as the overload with a multiple, just letting multiple be the
- /// identity.
- void addPolynomialToMatrix(const Poly& poly);
-
- /** Builds an F4 matrix to the specifications given. Also clears the
- information in this object.
-
- The right columns are ordered by decreasing monomial of each
- column according to the order from the basis. The left columns are
- ordered in some way so that the first entry in each top row (the
- pivot) has a lower index than any other entries in that row.
-
- The matrix contains a reducer/pivot for every monomial that can be
- reduced by the basis and that is present in the matrix. There is
- no guarantee that the bottom part of the matrix contains rows that
- exactly correspond to the polynomials that have been scheduled to
- be added to the matrix. It is only guaranteed that the whole matrix has
- the same row-space as though that had been the case. */
- void buildMatrixAndClear(QuadMatrix& matrix);
-
- const PolyRing& ring() const {return mBuilder.ring();}
-
-private:
- typedef const MonomialMap<LeftRightColIndex>::Reader ColReader;
-
- /// Represents the task of adding a row to the matrix. If sPairPoly is null
- /// then the row to add is multiply * poly. Otherwise, the row to add is
- /// multiply * poly - sPairMultiply * sPairPoly
- /// where sPairMultiply makes the lead terms cancel.
- struct RowTask {
- bool addToTop; // add the row to the bottom if false
- monomial desiredLead; // multiply monomial onto poly to get this lead
- const Poly* poly;
- const Poly* sPairPoly;
- monomial sPairMultiply;
- };
- typedef ::mgb::tbb::parallel_do_feeder<RowTask> TaskFeeder;
-
- /// Creates a column with monomial label x and schedules a new row to
- /// reduce that column if possible. Here x is monoA if monoB is
- /// null and otherwise x is the product of monoA and monoB.
- MATHICGB_NO_INLINE
- std::pair<LeftRightColIndex, ConstMonomial>
- createColumn(
- const_monomial monoA,
- const_monomial monoB,
- TaskFeeder& feeder
- );
-
- void appendRowTop(
- const_monomial multiple,
- const Poly& poly,
- QuadMatrixBuilder& builder,
- TaskFeeder& feeder
- );
- void appendRowBottom(
- const Poly* poly,
- monomial multiply,
- const Poly* sPairPoly,
- monomial sPairMultiply,
- QuadMatrixBuilder& builder,
- TaskFeeder& feeder
- );
- void appendRowBottom(
- const_monomial multiple,
- bool negate,
- Poly::const_iterator begin,
- Poly::const_iterator end,
- QuadMatrixBuilder& builder,
- TaskFeeder& feeder
- );
-
- MATHICGB_NO_INLINE
- std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
- findOrCreateColumn(
- const_monomial monoA,
- const_monomial monoB,
- TaskFeeder& feeder
- );
-
- MATHICGB_INLINE
- std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
- findOrCreateColumn(
- const_monomial monoA,
- const_monomial monoB,
- const ColReader& colMap,
- TaskFeeder& feeder
- );
-
- MATHICGB_NO_INLINE
- void createTwoColumns(
- const const_monomial monoA1,
- const const_monomial monoA2,
- const const_monomial monoB,
- TaskFeeder& feeder
- );
-
- mgb::tbb::mutex mCreateColumnLock;
- ColIndex mLeftColCount;
- ColIndex mRightColCount;
- monomial mTmp;
- const PolyBasis& mBasis;
- Monomials mMonomialsLeft;
- Monomials mMonomialsRight;
- QuadMatrixBuilder mBuilder;
- Map mMap;
- std::vector<RowTask> mTodo;
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_F4_MATRIX_BUILDER_GUARD
+#define MATHICGB_F4_MATRIX_BUILDER_GUARD
+
+#include "QuadMatrixBuilder.hpp"
+#include "Poly.hpp"
+#include "PolyRing.hpp"
+#include "PolyBasis.hpp"
+#include "QuadMatrix.hpp"
+#include "mtbb.hpp"
+#include <vector>
+
+MATHICGB_NAMESPACE_BEGIN
+
+/** Class for constructing an F4 matrix. This class is reponsible for
+ figuring out what matrix to build and then it uses QuadMatrixBuilder
+ to create that matrix.
+
+ @todo: this class does not offer exception guarantees. It's just not
+ very workable without an RAII monomial handle, so add one of those
+ before fixing this. */
+class F4MatrixBuilder {
+private:
+ typedef QuadMatrixBuilder::ColIndex ColIndex;
+ typedef QuadMatrixBuilder::LeftRightColIndex LeftRightColIndex;
+ typedef QuadMatrixBuilder::Scalar Scalar;
+ typedef QuadMatrixBuilder::Map Map;
+ typedef QuadMatrixBuilder::MonomialsType Monomials;
+
+public:
+ /// memoryQuantum is how much to increase the memory size by each time the
+ /// current amount of memory is exhausted. A value of 0 indicates to start
+ /// small and double the quantum at each exhaustion.
+ F4MatrixBuilder(const PolyBasis& basis, size_t memoryQuantum = 0);
+
+ /** Schedules a row representing the S-polynomial between polyA and
+ polyB to be added to the matrix. No ownership is taken, but polyA
+ and polyB must remain valid until the matrix is constructed.
+
+ Currently, the two monomials must be monic, though this is just
+ because they always happen to be monic so there was no reason to
+ support the non-monic case. */
+ void addSPolynomialToMatrix(const Poly& polyA, const Poly& polyB);
+
+ /** Schedules a row representing multiple*poly to be added to the
+ matrix. No ownership is taken, but poly must remain valid until
+ the matrix is constructed. multiple is copied so it need not
+ remain valid. */
+ void addPolynomialToMatrix(const_monomial multiple, const Poly& poly);
+
+ /// as the overload with a multiple, just letting multiple be the
+ /// identity.
+ void addPolynomialToMatrix(const Poly& poly);
+
+ /** Builds an F4 matrix to the specifications given. Also clears the
+ information in this object.
+
+ The right columns are ordered by decreasing monomial of each
+ column according to the order from the basis. The left columns are
+ ordered in some way so that the first entry in each top row (the
+ pivot) has a lower index than any other entries in that row.
+
+ The matrix contains a reducer/pivot for every monomial that can be
+ reduced by the basis and that is present in the matrix. There is
+ no guarantee that the bottom part of the matrix contains rows that
+ exactly correspond to the polynomials that have been scheduled to
+ be added to the matrix. It is only guaranteed that the whole matrix has
+ the same row-space as though that had been the case. */
+ void buildMatrixAndClear(QuadMatrix& matrix);
+
+ const PolyRing& ring() const {return mBuilder.ring();}
+
+private:
+ typedef const MonomialMap<LeftRightColIndex>::Reader ColReader;
+
+ /// Represents the task of adding a row to the matrix. If sPairPoly is null
+ /// then the row to add is multiply * poly. Otherwise, the row to add is
+ /// multiply * poly - sPairMultiply * sPairPoly
+ /// where sPairMultiply makes the lead terms cancel.
+ struct RowTask {
+ bool addToTop; // add the row to the bottom if false
+ monomial desiredLead; // multiply monomial onto poly to get this lead
+ const Poly* poly;
+ const Poly* sPairPoly;
+ monomial sPairMultiply;
+ };
+ typedef ::mgb::tbb::parallel_do_feeder<RowTask> TaskFeeder;
+
+ /// Creates a column with monomial label x and schedules a new row to
+ /// reduce that column if possible. Here x is monoA if monoB is
+ /// null and otherwise x is the product of monoA and monoB.
+ MATHICGB_NO_INLINE
+ ::std::pair<LeftRightColIndex, ConstMonomial>
+ createColumn(
+ const_monomial monoA,
+ const_monomial monoB,
+ TaskFeeder& feeder
+ );
+
+ void appendRowTop(
+ const_monomial multiple,
+ const Poly& poly,
+ QuadMatrixBuilder& builder,
+ TaskFeeder& feeder
+ );
+ void appendRowBottom(
+ const Poly* poly,
+ monomial multiply,
+ const Poly* sPairPoly,
+ monomial sPairMultiply,
+ QuadMatrixBuilder& builder,
+ TaskFeeder& feeder
+ );
+ void appendRowBottom(
+ const_monomial multiple,
+ bool negate,
+ Poly::const_iterator begin,
+ Poly::const_iterator end,
+ QuadMatrixBuilder& builder,
+ TaskFeeder& feeder
+ );
+
+ MATHICGB_NO_INLINE
+ ::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
+ findOrCreateColumn(
+ const_monomial monoA,
+ const_monomial monoB,
+ TaskFeeder& feeder
+ );
+
+ MATHICGB_INLINE
+ ::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
+ findOrCreateColumn(
+ const_monomial monoA,
+ const_monomial monoB,
+ const ColReader& colMap,
+ TaskFeeder& feeder
+ );
+
+ MATHICGB_NO_INLINE
+ void createTwoColumns(
+ const const_monomial monoA1,
+ const const_monomial monoA2,
+ const const_monomial monoB,
+ TaskFeeder& feeder
+ );
+
+ mgb::tbb::mutex mCreateColumnLock;
+ ColIndex mLeftColCount;
+ ColIndex mRightColCount;
+ monomial mTmp;
+ const PolyBasis& mBasis;
+ Monomials mMonomialsLeft;
+ Monomials mMonomialsRight;
+ QuadMatrixBuilder mBuilder;
+ Map mMap;
+ ::std::vector<RowTask> mTodo;
+};
+
+MATHICGB_NAMESPACE_END
+
+#endif
diff --git a/src/mathicgb/F4MatrixBuilder2.cpp b/src/mathicgb/F4MatrixBuilder2.cpp
index 484332a..3fc82d8 100755
--- a/src/mathicgb/F4MatrixBuilder2.cpp
+++ b/src/mathicgb/F4MatrixBuilder2.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "F4MatrixBuilder2.hpp"
@@ -14,8 +16,10 @@ MATHICGB_DEFINE_LOG_DOMAIN(
"Displays row and column count for each F4 matrix construction."
);
+MATHICGB_NAMESPACE_BEGIN
+
MATHICGB_NO_INLINE
-std::pair<F4MatrixBuilder2::ColIndex, ConstMonomial>
+::std::pair<F4MatrixBuilder2::ColIndex, ConstMonomial>
F4MatrixBuilder2::findOrCreateColumn(
const const_monomial monoA,
const const_monomial monoB,
@@ -25,12 +29,12 @@ F4MatrixBuilder2::findOrCreateColumn(
MATHICGB_ASSERT(!monoB.isNull());
const auto col = ColReader(mMap).findProduct(monoA, monoB);
if (col.first != 0)
- return std::make_pair(*col.first, col.second);
+ return ::std::make_pair(*col.first, col.second);
return createColumn(monoA, monoB, feeder);
}
MATHICGB_INLINE
-std::pair<F4MatrixBuilder2::ColIndex, ConstMonomial>
+::std::pair<F4MatrixBuilder2::ColIndex, ConstMonomial>
F4MatrixBuilder2::findOrCreateColumn(
const const_monomial monoA,
const const_monomial monoB,
@@ -42,7 +46,7 @@ F4MatrixBuilder2::findOrCreateColumn(
const auto col = colMap.findProduct(monoA, monoB);
if (col.first == 0)
return findOrCreateColumn(monoA, monoB, feeder);
- return std::make_pair(*col.first, col.second);
+ return ::std::make_pair(*col.first, col.second);
}
MATHICGB_NO_INLINE
@@ -67,7 +71,7 @@ F4MatrixBuilder2::F4MatrixBuilder2(
{
// This assert has to be _NO_ASSUME since otherwise the compiler will assume
// that the error checking branch here cannot be taken and optimize it away.
- const Scalar maxScalar = std::numeric_limits<Scalar>::max();
+ const Scalar maxScalar = ::std::numeric_limits<Scalar>::max();
MATHICGB_ASSERT_NO_ASSUME(ring().charac() <= maxScalar);
if (ring().charac() > maxScalar)
mathic::reportInternalError("F4MatrixBuilder2: too large characteristic.");
@@ -146,11 +150,11 @@ void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) {
MATHICGB_ASSERT(ColReader(mMap).find(mTodo[i].desiredLead).first == 0);
// Create column for the lead term that cancels in the S-pair
- if (mIsColumnToLeft.size() >= std::numeric_limits<ColIndex>::max())
- throw std::overflow_error("Too many columns in QuadMatrix");
+ if (mIsColumnToLeft.size() >= ::std::numeric_limits<ColIndex>::max())
+ throw ::std::overflow_error("Too many columns in QuadMatrix");
const auto newIndex = static_cast<ColIndex>(mIsColumnToLeft.size());
const auto inserted =
- mMap.insert(std::make_pair(mTodo[i].desiredLead, newIndex));
+ mMap.insert(::std::make_pair(mTodo[i].desiredLead, newIndex));
mIsColumnToLeft.push_back(true);
const auto& mono = inserted.first.second;
@@ -204,7 +208,7 @@ void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) {
data.tmp1 = ring().allocMonomial();
data.tmp2 = ring().allocMonomial();
}
- return std::move(data);
+ return ::std::move(data);
});
// Construct the matrix as pre-blocks
@@ -256,15 +260,15 @@ void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) {
(ring(), static_cast<ColIndex>(mMap.entryCount()));
const auto end = threadData.end();
for (auto it = threadData.begin(); it != end; ++it) {
- projection.addProtoMatrix(std::move(it->block));
+ projection.addProtoMatrix(::std::move(it->block));
ring().freeMonomial(it->tmp1);
ring().freeMonomial(it->tmp2);
}
// Sort columns by monomial and tell the projection of the resulting order
MonomialMap<ColIndex>::Reader reader(mMap);
- typedef std::pair<ColIndex, ConstMonomial> IndexMono;
- std::vector<IndexMono> columns(reader.begin(), reader.end());
+ typedef ::std::pair<ColIndex, ConstMonomial> IndexMono;
+ ::std::vector<IndexMono> columns(reader.begin(), reader.end());
const auto cmp = [&](const IndexMono& a, const IndexMono b) {
return ring().monomialLT(b.second, a.second);
};
@@ -285,7 +289,7 @@ void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) {
<< " by "
<< mathic::ColumnPrinter::commafy(
quadMatrix.computeLeftColCount() + quadMatrix.computeRightColCount())
- << "]" << std::endl;
+ << "]" << ::std::endl;
#ifdef MATHICGB_DEBUG
for (size_t side = 0; side < 2; ++side) {
@@ -303,7 +307,7 @@ void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) {
#endif
}
-std::pair<F4MatrixBuilder2::ColIndex, ConstMonomial>
+::std::pair<F4MatrixBuilder2::ColIndex, ConstMonomial>
F4MatrixBuilder2::createColumn(
const const_monomial monoA,
const const_monomial monoB,
@@ -317,7 +321,7 @@ F4MatrixBuilder2::createColumn(
{
const auto found(ColReader(mMap).findProduct(monoA, monoB));
if (found.first != 0)
- return std::make_pair(*found.first, found.second);
+ return ::std::make_pair(*found.first, found.second);
}
// The column really does not exist, so we need to create it
@@ -330,10 +334,10 @@ F4MatrixBuilder2::createColumn(
const bool insertLeft = (reducerIndex != static_cast<size_t>(-1));
// Create the new left or right column
- if (mIsColumnToLeft.size() >= std::numeric_limits<ColIndex>::max())
- throw std::overflow_error("Too many columns in QuadMatrix");
+ if (mIsColumnToLeft.size() >= ::std::numeric_limits<ColIndex>::max())
+ throw ::std::overflow_error("Too many columns in QuadMatrix");
const auto newIndex = static_cast<ColIndex>(mIsColumnToLeft.size());
- const auto inserted = mMap.insert(std::make_pair(mTmp, newIndex));
+ const auto inserted = mMap.insert(::std::make_pair(mTmp, newIndex));
mIsColumnToLeft.push_back(insertLeft);
// schedule new task if we found a reducer
@@ -344,7 +348,7 @@ F4MatrixBuilder2::createColumn(
feeder.add(task);
}
- return std::make_pair(*inserted.first.first, inserted.first.second);
+ return ::std::make_pair(*inserted.first.first, inserted.first.second);
}
void F4MatrixBuilder2::appendRow(
@@ -357,8 +361,8 @@ void F4MatrixBuilder2::appendRow(
const auto begin = poly.begin();
const auto end = poly.end();
- const auto count = static_cast<size_t>(std::distance(begin, end));
- MATHICGB_ASSERT(count < std::numeric_limits<ColIndex>::max());
+ const auto count = static_cast<size_t>(::std::distance(begin, end));
+ MATHICGB_ASSERT(count < ::std::numeric_limits<ColIndex>::max());
auto indices = block.makeRowWithTheseScalars(poly);
auto it = begin;
@@ -366,7 +370,7 @@ void F4MatrixBuilder2::appendRow(
ColReader reader(mMap);
const auto col = findOrCreateColumn
(it.getMonomial(), multiple, reader, feeder);
- MATHICGB_ASSERT(it.getCoefficient() < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(it.getCoefficient() < ::std::numeric_limits<Scalar>::max());
MATHICGB_ASSERT(it.getCoefficient());
//matrix.appendEntry(col.first, static_cast<Scalar>(it.getCoefficient()));
*indices = col.first;
@@ -377,16 +381,16 @@ void F4MatrixBuilder2::appendRow(
}
updateReader:
ColReader colMap(mMap);
- MATHICGB_ASSERT((std::distance(it, end) % 2) == 0);
+ MATHICGB_ASSERT((::std::distance(it, end) % 2) == 0);
while (it != end) {
- MATHICGB_ASSERT(it.getCoefficient() < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(it.getCoefficient() < ::std::numeric_limits<Scalar>::max());
MATHICGB_ASSERT(it.getCoefficient() != 0);
const auto scalar1 = static_cast<Scalar>(it.getCoefficient());
const const_monomial mono1 = it.getMonomial();
auto it2 = it;
++it2;
- MATHICGB_ASSERT(it2.getCoefficient() < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(it2.getCoefficient() < ::std::numeric_limits<Scalar>::max());
MATHICGB_ASSERT(it2.getCoefficient() != 0);
const auto scalar2 = static_cast<Scalar>(it2.getCoefficient());
const const_monomial mono2 = it2.getMonomial();
@@ -441,7 +445,7 @@ void F4MatrixBuilder2::appendRowSPair(
// @todo: handle overflow of termCount addition here
MATHICGB_ASSERT(poly->termCount() + sPairPoly->termCount() - 2 <=
- std::numeric_limits<ColIndex>::max());
+ ::std::numeric_limits<ColIndex>::max());
const auto maxCols =
static_cast<ColIndex>(poly->termCount() + sPairPoly->termCount() - 2);
auto row = block.makeRow(maxCols);
@@ -470,7 +474,7 @@ void F4MatrixBuilder2::appendRowSPair(
col = colB.first;
++itB;
}
- MATHICGB_ASSERT(coeff < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(coeff < ::std::numeric_limits<Scalar>::max());
if (coeff != 0) {
//matrix.appendEntry(col, static_cast<Scalar>(coeff));
*row.first++ = col;
@@ -499,3 +503,5 @@ void F4MatrixBuilder2::appendRowSPair(
maxCols - static_cast<ColIndex>(row.first - indicesBegin);
block.removeLastEntries(block.rowCount() - 1, toRemove);
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/F4MatrixBuilder2.hpp b/src/mathicgb/F4MatrixBuilder2.hpp
index f11328e..ab6bb1b 100755
--- a/src/mathicgb/F4MatrixBuilder2.hpp
+++ b/src/mathicgb/F4MatrixBuilder2.hpp
@@ -1,142 +1,147 @@
-#ifndef F4_MATRIX_BUILDER_2_GUARD
-#define F4_MATRIX_BUILDER_2_GUARD
-
-#include "SparseMatrix.hpp"
-#include "Poly.hpp"
-#include "PolyRing.hpp"
-#include "PolyBasis.hpp"
-#include "QuadMatrix.hpp"
-#include "MonomialMap.hpp"
-#include "F4ProtoMatrix.hpp"
-#include "mtbb.hpp"
-#include <vector>
-
-/** Class for constructing an F4 matrix.
-
- @todo: this class does not offer exception guarantees. It's just not
- very workable without an RAII monomial handle or a scope exit functionality,
- so add one of those before fixing this. */
-class F4MatrixBuilder2 {
-private:
- typedef SparseMatrix::ColIndex ColIndex;
- typedef SparseMatrix::Scalar Scalar;
- typedef MonomialMap<ColIndex> Map;
- typedef SparseMatrix::RowIndex RowIndex;
-
-public:
- /// memoryQuantum is how much to increase the memory size by each time the
- /// current amount of memory is exhausted. A value of 0 indicates to start
- /// small and double the quantum at each exhaustion.
- F4MatrixBuilder2(const PolyBasis& basis, size_t memoryQuantum = 0);
-
- /** Schedules a row representing the S-polynomial between polyA and
- polyB to be added to the matrix. No ownership is taken, but polyA
- and polyB must remain valid until the matrix is constructed.
-
- Currently, the two monomials must be monic, though this is just
- because they always happen to be monic so there was no reason to
- support the non-monic case. */
- void addSPolynomialToMatrix(const Poly& polyA, const Poly& polyB);
-
- /** Schedules a row representing multiple*poly to be added to the
- matrix. No ownership is taken, but poly must remain valid until
- the matrix is constructed. multiple is copied so it need not
- remain valid. */
- void addPolynomialToMatrix(const_monomial multiple, const Poly& poly);
-
- /// as the overload with a multiple, just letting multiple be the
- /// identity.
- void addPolynomialToMatrix(const Poly& poly);
-
- /** Builds an F4 matrix to the specifications given. Also clears the
- information in this object.
-
- The right columns are ordered by decreasing monomial of each
- column according to the order from the basis. The left columns are
- ordered in some way so that the first entry in each top row (the
- pivot) has a lower index than any other entries in that row.
-
- The matrix contains a reducer/pivot for every monomial that can be
- reduced by the basis and that is present in the matrix. There is
- no guarantee that the bottom part of the matrix contains rows that
- exactly correspond to the polynomials that have been scheduled to
- be added to the matrix. It is only guaranteed that the whole matrix has
- the same row-space as though that had been the case. */
- void buildMatrixAndClear(QuadMatrix& matrix);
-
- const PolyRing& ring() const {return mBasis.ring();}
-
-private:
- typedef const Map::Reader ColReader;
- typedef std::vector<monomial> Monomials;
-
- /// Represents the task of adding a row to the matrix. If sPairPoly is null
- /// then the row to add is multiply * poly. Otherwise, the row to add is
- /// multiply * poly - sPairMultiply * sPairPoly
- /// where multiply and sPairMultiply are such that the leading terms become
- /// desiredLead.
- struct RowTask {
- monomial desiredLead; // multiply monomial onto poly to get this lead
- const Poly* poly;
- const Poly* sPairPoly;
- };
- typedef mgb::tbb::parallel_do_feeder<RowTask> TaskFeeder;
-
- /// Creates a column with monomial label x and schedules a new row to
- /// reduce that column if possible. Here x is monoA if monoB is
- /// null and otherwise x is the product of monoA and monoB.
- MATHICGB_NO_INLINE
- std::pair<ColIndex, ConstMonomial> createColumn(
- const_monomial monoA,
- const_monomial monoB,
- TaskFeeder& feeder
- );
-
- void appendRow(
- const_monomial multiple,
- const Poly& poly,
- F4ProtoMatrix& block,
- TaskFeeder& feeder
- );
- void appendRowSPair(
- const Poly* poly,
- monomial multiply,
- const Poly* sPairPoly,
- monomial sPairMultiply,
- F4ProtoMatrix& block,
- TaskFeeder& feeder
- );
-
- MATHICGB_NO_INLINE
- std::pair<ColIndex, ConstMonomial> findOrCreateColumn(
- const_monomial monoA,
- const_monomial monoB,
- TaskFeeder& feeder
- );
-
- MATHICGB_INLINE
- std::pair<ColIndex, ConstMonomial> findOrCreateColumn(
- const_monomial monoA,
- const_monomial monoB,
- const ColReader& colMap,
- TaskFeeder& feeder
- );
-
- MATHICGB_NO_INLINE
- void createTwoColumns(
- const const_monomial monoA1,
- const const_monomial monoA2,
- const const_monomial monoB,
- TaskFeeder& feeder
- );
-
- std::vector<char> mIsColumnToLeft;
- const size_t mMemoryQuantum;
- mgb::tbb::mutex mCreateColumnLock;
- monomial mTmp;
- const PolyBasis& mBasis;
- Map mMap;
- std::vector<RowTask> mTodo;
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_F4_MATRIX_BUILDER_2_GUARD
+#define MATHICGB_F4_MATRIX_BUILDER_2_GUARD
+
+#include "SparseMatrix.hpp"
+#include "Poly.hpp"
+#include "PolyRing.hpp"
+#include "PolyBasis.hpp"
+#include "QuadMatrix.hpp"
+#include "MonomialMap.hpp"
+#include "F4ProtoMatrix.hpp"
+#include "mtbb.hpp"
+#include <vector>
+
+MATHICGB_NAMESPACE_BEGIN
+
+/** Class for constructing an F4 matrix.
+
+ @todo: this class does not offer exception guarantees. It's just not
+ very workable without an RAII monomial handle or a scope exit functionality,
+ so add one of those before fixing this. */
+class F4MatrixBuilder2 {
+private:
+ typedef SparseMatrix::ColIndex ColIndex;
+ typedef SparseMatrix::Scalar Scalar;
+ typedef MonomialMap<ColIndex> Map;
+ typedef SparseMatrix::RowIndex RowIndex;
+
+public:
+ /// memoryQuantum is how much to increase the memory size by each time the
+ /// current amount of memory is exhausted. A value of 0 indicates to start
+ /// small and double the quantum at each exhaustion.
+ F4MatrixBuilder2(const PolyBasis& basis, size_t memoryQuantum = 0);
+
+ /** Schedules a row representing the S-polynomial between polyA and
+ polyB to be added to the matrix. No ownership is taken, but polyA
+ and polyB must remain valid until the matrix is constructed.
+
+ Currently, the two monomials must be monic, though this is just
+ because they always happen to be monic so there was no reason to
+ support the non-monic case. */
+ void addSPolynomialToMatrix(const Poly& polyA, const Poly& polyB);
+
+ /** Schedules a row representing multiple*poly to be added to the
+ matrix. No ownership is taken, but poly must remain valid until
+ the matrix is constructed. multiple is copied so it need not
+ remain valid. */
+ void addPolynomialToMatrix(const_monomial multiple, const Poly& poly);
+
+ /// as the overload with a multiple, just letting multiple be the
+ /// identity.
+ void addPolynomialToMatrix(const Poly& poly);
+
+ /** Builds an F4 matrix to the specifications given. Also clears the
+ information in this object.
+
+ The right columns are ordered by decreasing monomial of each
+ column according to the order from the basis. The left columns are
+ ordered in some way so that the first entry in each top row (the
+ pivot) has a lower index than any other entries in that row.
+
+ The matrix contains a reducer/pivot for every monomial that can be
+ reduced by the basis and that is present in the matrix. There is
+ no guarantee that the bottom part of the matrix contains rows that
+ exactly correspond to the polynomials that have been scheduled to
+ be added to the matrix. It is only guaranteed that the whole matrix has
+ the same row-space as though that had been the case. */
+ void buildMatrixAndClear(QuadMatrix& matrix);
+
+ const PolyRing& ring() const {return mBasis.ring();}
+
+private:
+ typedef const Map::Reader ColReader;
+ typedef ::std::vector<monomial> Monomials;
+
+ /// Represents the task of adding a row to the matrix. If sPairPoly is null
+ /// then the row to add is multiply * poly. Otherwise, the row to add is
+ /// multiply * poly - sPairMultiply * sPairPoly
+ /// where multiply and sPairMultiply are such that the leading terms become
+ /// desiredLead.
+ struct RowTask {
+ monomial desiredLead; // multiply monomial onto poly to get this lead
+ const Poly* poly;
+ const Poly* sPairPoly;
+ };
+ typedef mgb::tbb::parallel_do_feeder<RowTask> TaskFeeder;
+
+ /// Creates a column with monomial label x and schedules a new row to
+ /// reduce that column if possible. Here x is monoA if monoB is
+ /// null and otherwise x is the product of monoA and monoB.
+ MATHICGB_NO_INLINE
+ ::std::pair<ColIndex, ConstMonomial> createColumn(
+ const_monomial monoA,
+ const_monomial monoB,
+ TaskFeeder& feeder
+ );
+
+ void appendRow(
+ const_monomial multiple,
+ const Poly& poly,
+ F4ProtoMatrix& block,
+ TaskFeeder& feeder
+ );
+ void appendRowSPair(
+ const Poly* poly,
+ monomial multiply,
+ const Poly* sPairPoly,
+ monomial sPairMultiply,
+ F4ProtoMatrix& block,
+ TaskFeeder& feeder
+ );
+
+ MATHICGB_NO_INLINE
+ ::std::pair<ColIndex, ConstMonomial> findOrCreateColumn(
+ const_monomial monoA,
+ const_monomial monoB,
+ TaskFeeder& feeder
+ );
+
+ MATHICGB_INLINE
+ ::std::pair<ColIndex, ConstMonomial> findOrCreateColumn(
+ const_monomial monoA,
+ const_monomial monoB,
+ const ColReader& colMap,
+ TaskFeeder& feeder
+ );
+
+ MATHICGB_NO_INLINE
+ void createTwoColumns(
+ const const_monomial monoA1,
+ const const_monomial monoA2,
+ const const_monomial monoB,
+ TaskFeeder& feeder
+ );
+
+ ::std::vector<char> mIsColumnToLeft;
+ const size_t mMemoryQuantum;
+ mgb::tbb::mutex mCreateColumnLock;
+ monomial mTmp;
+ const PolyBasis& mBasis;
+ Map mMap;
+ ::std::vector<RowTask> mTodo;
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/F4MatrixProjection.cpp b/src/mathicgb/F4MatrixProjection.cpp
index 80b22ab..0855170 100755
--- a/src/mathicgb/F4MatrixProjection.cpp
+++ b/src/mathicgb/F4MatrixProjection.cpp
@@ -1,8 +1,12 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "F4MatrixProjection.hpp"
#include "ScopeExit.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
F4MatrixProjection::F4MatrixProjection(
const PolyRing& ring,
ColIndex colCount
@@ -43,27 +47,27 @@ struct RowData : F4ProtoMatrix::Row {
RowData(const F4ProtoMatrix::Row& row): F4ProtoMatrix::Row(row) {}
};
-typedef std::pair<RowData, SparseMatrix::Scalar> RowProjectFrom;
+typedef ::std::pair<RowData, SparseMatrix::Scalar> RowProjectFrom;
template<class Row>
class F4MatrixProjection::TopBottom {
public:
- typedef std::pair<Row, Scalar> RowMultiple;
- typedef std::vector<RowMultiple> RowVector;
+ typedef ::std::pair<Row, Scalar> RowMultiple;
+ typedef ::std::vector<RowMultiple> RowVector;
TopBottom(const size_t leftColCount, const PolyRing& ring):
mModulus(static_cast<Scalar>(ring.charac())),
mTopRows(leftColCount)
{
- MATHICGB_ASSERT(ring.charac() <= std::numeric_limits<Scalar>::max());
- MATHICGB_ASSERT(leftColCount <= std::numeric_limits<ColIndex>::max());
+ MATHICGB_ASSERT(ring.charac() <= ::std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(leftColCount <= ::std::numeric_limits<ColIndex>::max());
}
void addRow(const Row& row, ColIndex leadIndex, Scalar leadScalar) {
if (row.entryCount == 0)
return; // Skip zero rows.
- if (leadIndex == std::numeric_limits<ColIndex>::max()) {
+ if (leadIndex == ::std::numeric_limits<ColIndex>::max()) {
// this row has no left entries, so it cannot be a top row.
mBottomRows.push_back(RowMultiple(row, 1));
return;
@@ -77,7 +81,7 @@ public:
mBottomRows.push_back(RowMultiple(row, 1));
} else {
if (currentTop.entryCount != 0)
- mBottomRows.push_back(std::make_pair(currentTop, 1));
+ mBottomRows.push_back(::std::make_pair(currentTop, 1));
MATHICGB_ASSERT(leadScalar != 0);
const auto inverse = leadScalar == 1 ? // 1 is a common case
1 : modularInverse(leadScalar, mModulus);
@@ -91,8 +95,8 @@ public:
MATHICGB_ASSERT(r.first.entryCount > 0);
MATHICGB_ASSERT(r.second != 0);
};
- std::for_each(mTopRows.begin(), mTopRows.end(), check);
- std::for_each(mBottomRows.begin(), mBottomRows.end(), check);
+ ::std::for_each(mTopRows.begin(), mTopRows.end(), check);
+ ::std::for_each(mBottomRows.begin(), mBottomRows.end(), check);
#endif
return true;
}
@@ -116,7 +120,7 @@ public:
typedef F4ProtoMatrix::Row Row;
LeftRight(
- const std::vector<ColProjectTo>& colProjectTo,
+ const ::std::vector<ColProjectTo>& colProjectTo,
const PolyRing& ring,
const size_t quantum
):
@@ -125,19 +129,19 @@ public:
mLeft(quantum),
mRight(quantum)
{
- MATHICGB_ASSERT(ring.charac() < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(ring.charac() < ::std::numeric_limits<Scalar>::max());
mLeft.clear();
mRight.clear();
}
template<class Pair>
- void appendRowsPermuted(const std::vector<Pair>& rows) {
+ void appendRowsPermuted(const ::std::vector<Pair>& rows) {
const auto end = rows.end();
for (auto it = rows.begin(); it != end; ++it)
appendRow(it->first, it->second);
}
- void appendRows(const std::vector<F4ProtoMatrix*>& preBlocks) {
+ void appendRows(const ::std::vector<F4ProtoMatrix*>& preBlocks) {
const auto end = preBlocks.end();
for (auto it = preBlocks.begin(); it != end; ++it) {
auto& block = **it;
@@ -194,7 +198,7 @@ public:
}
void appendEntry(const ColIndex projectMe, const ExternalScalar scalar) {
- MATHICGB_ASSERT(scalar <= std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(scalar <= ::std::numeric_limits<Scalar>::max());
appendEntry(projectMe, static_cast<Scalar>(scalar));
}
@@ -207,11 +211,11 @@ public:
const SparseMatrix& left() const {return mLeft;}
const SparseMatrix& right() const {return mRight;}
- SparseMatrix moveLeft() {return std::move(mLeft);}
- SparseMatrix moveRight() {return std::move(mRight);}
+ SparseMatrix moveLeft() {return ::std::move(mLeft);}
+ SparseMatrix moveRight() {return ::std::move(mRight);}
private:
- const std::vector<ColProjectTo>& mColProjectTo;
+ const ::std::vector<ColProjectTo>& mColProjectTo;
const Scalar mModulus;
SparseMatrix mLeft;
@@ -251,7 +255,7 @@ QuadMatrix F4MatrixProjection::makeAndClearOneStep(const size_t quantum) {
}
}
// Did not find any left entry.
- tb.addRow(row, std::numeric_limits<ColIndex>::max(), 0);
+ tb.addRow(row, ::std::numeric_limits<ColIndex>::max(), 0);
done:;
}
}
@@ -267,21 +271,21 @@ done:;
// Move the data into place
QuadMatrix qm;
qm.ring = &ring();
- qm.leftColumnMonomials = std::move(mLeftMonomials);
- qm.rightColumnMonomials = std::move(mRightMonomials);
+ qm.leftColumnMonomials = ::std::move(mLeftMonomials);
+ qm.rightColumnMonomials = ::std::move(mRightMonomials);
qm.topLeft = top.moveLeft();
qm.topRight = top.moveRight();
qm.bottomLeft = bottom.moveLeft();
qm.bottomRight = bottom.moveRight();
- return std::move(qm);
+ return ::std::move(qm);
}
namespace {
// Helper function for F4MatrixProjection::makeAndClearTwoStep
template<class TopBottom>
- std::pair<SparseMatrix, SparseMatrix> projectRows(
+ ::std::pair<SparseMatrix, SparseMatrix> projectRows(
const TopBottom& tb,
size_t quantum,
SparseMatrix&& in
@@ -309,7 +313,7 @@ namespace {
}
in.clear();
- return std::make_pair(std::move(top), std::move(bottom));
+ return ::std::make_pair(::std::move(top), ::std::move(bottom));
}
}
@@ -334,7 +338,7 @@ QuadMatrix F4MatrixProjection::makeAndClearTwoStep(const size_t quantum) {
const Row r = {row, entryCount};
if (leftEntryCount == 0)
- tb.addRow(r, std::numeric_limits<ColIndex>::max(), 0);
+ tb.addRow(r, ::std::numeric_limits<ColIndex>::max(), 0);
else {
const auto entry = lr.left().rowBegin(row);
tb.addRow(r, entry.index(), entry.scalar());
@@ -347,11 +351,13 @@ QuadMatrix F4MatrixProjection::makeAndClearTwoStep(const size_t quantum) {
auto right = projectRows(tb, quantum, lr.moveRight());
qm.ring = &ring();
- qm.topLeft = std::move(left.first);
- qm.bottomLeft = std::move(left.second);
- qm.topRight = std::move(right.first);
- qm.bottomRight = std::move(right.second);
- qm.leftColumnMonomials = std::move(mLeftMonomials);
- qm.rightColumnMonomials = std::move(mRightMonomials);
- return std::move(qm);
+ qm.topLeft = ::std::move(left.first);
+ qm.bottomLeft = ::std::move(left.second);
+ qm.topRight = ::std::move(right.first);
+ qm.bottomRight = ::std::move(right.second);
+ qm.leftColumnMonomials = ::std::move(mLeftMonomials);
+ qm.rightColumnMonomials = ::std::move(mRightMonomials);
+ return ::std::move(qm);
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/F4MatrixProjection.hpp b/src/mathicgb/F4MatrixProjection.hpp
old mode 100644
new mode 100755
index c34c75f..66c8ffc
--- a/src/mathicgb/F4MatrixProjection.hpp
+++ b/src/mathicgb/F4MatrixProjection.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_F4_MATRIX_PROJECTION_GUARD
#define MATHICGB_F4_MATRIX_PROJECTION_GUARD
@@ -8,6 +10,8 @@
#include "ScopeExit.hpp"
#include <vector>
+MATHICGB_NAMESPACE_BEGIN
+
class F4MatrixProjection {
public:
typedef SparseMatrix::RowIndex RowIndex;
@@ -41,12 +45,14 @@ private:
ColIndex index;
bool isLeft;
};
- std::vector<ColProjectTo> mColProjectTo;
+ ::std::vector<ColProjectTo> mColProjectTo;
- std::vector<F4ProtoMatrix*> mMatrices;
- std::vector<monomial> mLeftMonomials;
- std::vector<monomial> mRightMonomials;
+ ::std::vector<F4ProtoMatrix*> mMatrices;
+ ::std::vector<monomial> mLeftMonomials;
+ ::std::vector<monomial> mRightMonomials;
const PolyRing& mRing;
};
+MATHICGB_NAMESPACE_END
+
#endif
diff --git a/src/mathicgb/F4MatrixReducer.cpp b/src/mathicgb/F4MatrixReducer.cpp
index 99b71d8..f556901 100755
--- a/src/mathicgb/F4MatrixReducer.cpp
+++ b/src/mathicgb/F4MatrixReducer.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "F4MatrixReducer.hpp"
@@ -6,7 +8,6 @@
#include "PolyRing.hpp"
#include "LogDomain.hpp"
#include "mtbb.hpp"
-
#include <algorithm>
#include <vector>
#include <stdexcept>
@@ -30,6 +31,8 @@ MATHICGB_DEFINE_LOG_DOMAIN(
"Displays time to reduce the bottom right submatrix of each F4 matrix."
);
+MATHICGB_NAMESPACE_BEGIN
+
namespace {
class DenseRow {
public:
@@ -148,7 +151,7 @@ namespace {
// method).
auto it = begin;
- if (std::distance(begin, end) % 2 == 1) {
+ if (::std::distance(begin, end) % 2 == 1) {
// Replacing this by a goto into the middle of the following loop
// (similar to Duff's device) made the code slower on MSVC 2012.
multiplyAdd(it.scalar(), multiple, entries[it.index()]);
@@ -185,7 +188,7 @@ namespace {
}
private:
- std::vector<ScalarProductSum> mEntries;
+ ::std::vector<ScalarProductSum> mEntries;
};
SparseMatrix reduce(
@@ -211,10 +214,10 @@ namespace {
// Store column indexes instead of row indices as the matrix is square
// anyway (so all indices fit) and we are going to store this as a column
// index later on.
- std::vector<SparseMatrix::ColIndex> rowThatReducesCol(pivotCount);
+ ::std::vector<SparseMatrix::ColIndex> rowThatReducesCol(pivotCount);
#ifdef MATHICGB_DEBUG
// fill in an invalid value that can be recognized by asserts to be invalid.
- std::fill(rowThatReducesCol.begin(), rowThatReducesCol.end(), pivotCount);
+ ::std::fill(rowThatReducesCol.begin(), rowThatReducesCol.end(), pivotCount);
#endif
for (SparseMatrix::ColIndex pivot = 0; pivot < pivotCount; ++pivot) {
MATHICGB_ASSERT(!reduceByLeft.emptyRow(pivot));
@@ -236,7 +239,7 @@ namespace {
SparseMatrix tmp(qm.topRight.memoryQuantum());
- std::vector<SparseMatrix::RowIndex> rowOrder(rowCount);
+ ::std::vector<SparseMatrix::RowIndex> rowOrder(rowCount);
mgb::tbb::mutex lock;
mgb::tbb::parallel_for(mgb::tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount, 2),
@@ -261,7 +264,7 @@ namespace {
MATHICGB_ASSERT(row < pivotCount);
MATHICGB_ASSERT(!reduceByLeft.emptyRow(row));
MATHICGB_ASSERT(reduceByLeft.leadCol(row) == pivot);
- MATHICGB_ASSERT(entry < std::numeric_limits<SparseMatrix::Scalar>::max());
+ MATHICGB_ASSERT(entry < ::std::numeric_limits<SparseMatrix::Scalar>::max());
denseRow.addRowMultiple(
static_cast<SparseMatrix::Scalar>(entry),
++reduceByLeft.rowBegin(row),
@@ -273,7 +276,7 @@ namespace {
}
mgb::tbb::mutex::scoped_lock lockGuard(lock);
for (size_t pivot = 0; pivot < pivotCount; ++pivot) {
- MATHICGB_ASSERT(denseRow[pivot] < std::numeric_limits<SparseMatrix::Scalar>::max());
+ MATHICGB_ASSERT(denseRow[pivot] < ::std::numeric_limits<SparseMatrix::Scalar>::max());
if (denseRow[pivot] != 0)
tmp.appendEntry(rowThatReducesCol[pivot], static_cast<SparseMatrix::Scalar>(denseRow[pivot]));
}
@@ -313,7 +316,7 @@ namespace {
if (!zero)
reduced.rowDone();
}});
- return std::move(reduced);
+ return ::std::move(reduced);
}
SparseMatrix reduceToEchelonFormSparse(
@@ -326,7 +329,7 @@ namespace {
// pivotRowOfCol[i] is the pivot in column i or noRow
// if we have not identified such a pivot so far.
- std::vector<SparseMatrix::RowIndex> pivotRowOfCol(colCount, noRow);
+ ::std::vector<SparseMatrix::RowIndex> pivotRowOfCol(colCount, noRow);
DenseRow rowToReduce(colCount);
@@ -391,7 +394,7 @@ namespace {
pivotRowOfCol[pivotCol] = reduced.rowCount();
rowToReduce.appendTo(reduced);
}
- return std::move(reduced);
+ return ::std::move(reduced);
}
SparseMatrix reduceToEchelonForm(
@@ -402,7 +405,7 @@ namespace {
const auto rowCount = toReduce.rowCount();
// convert to dense representation
- std::vector<DenseRow> dense(rowCount);
+ ::std::vector<DenseRow> dense(rowCount);
mgb::tbb::parallel_for(mgb::tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount),
[&](const mgb::tbb::blocked_range<SparseMatrix::RowIndex>& range)
{for (auto it = range.begin(); it != range.end(); ++it)
@@ -415,28 +418,28 @@ namespace {
}});
// invariant: all columns in row to the left of leadCols[row] are zero.
- std::vector<SparseMatrix::ColIndex> leadCols(rowCount);
+ ::std::vector<SparseMatrix::ColIndex> leadCols(rowCount);
// pivot rows get copied here before being used to reduce the matrix.
SparseMatrix reduced(toReduce.memoryQuantum());
// (col,row) in nextReducers, then use row as a pivot in column col
// for the next iteration.
- std::vector<std::pair<SparseMatrix::ColIndex, SparseMatrix::RowIndex> > nextReducers;
+ ::std::vector< ::std::pair<SparseMatrix::ColIndex, SparseMatrix::RowIndex> > nextReducers;
// isPivotRow[row] is true if row is or has been used as a pivot.
- std::vector<bool> isPivotRow(rowCount);
+ ::std::vector<bool> isPivotRow(rowCount);
// columnHasPivot[col] is true if a pivot row for column col has
// been chosen.
- std::vector<bool> columnHasPivot(colCount);
+ ::std::vector<bool> columnHasPivot(colCount);
bool firstIteration = true;
while (firstIteration || reduced.rowCount() > 0) {
firstIteration = false;
size_t const reducerCount = reduced.rowCount();
- //std::cout << "reducing " << reduced.rowCount() << " out of " << toReduce.rowCount() << std::endl;
+ //::std::cout << "reducing " << reduced.rowCount() << " out of " << toReduce.rowCount() << ::std::endl;
mgb::tbb::mutex lock;
mgb::tbb::parallel_for(mgb::tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount),
[&](const mgb::tbb::blocked_range<SparseMatrix::RowIndex>& range)
@@ -478,17 +481,17 @@ namespace {
if (!columnHasPivot[col]) {
columnHasPivot[col] = true;
isNewReducer = true;
- nextReducers.push_back(std::make_pair(col, row));
+ nextReducers.push_back(::std::make_pair(col, row));
}
}
if (isNewReducer)
denseRow.makeUnitary(modulus, col);
}
}});
- //std::cout << "done reducing that batch" << std::endl;
+ //::std::cout << "done reducing that batch" << ::std::endl;
reduced.clear();
- std::sort(nextReducers.begin(), nextReducers.end());
+ ::std::sort(nextReducers.begin(), nextReducers.end());
for (size_t i = 0; i < nextReducers.size(); ++i) {
size_t const row = nextReducers[i].second;
@@ -514,7 +517,7 @@ namespace {
}});
#ifdef MATHICGB_DEBUG
- std::vector<char> sawPivot(colCount);
+ ::std::vector<char> sawPivot(colCount);
for (SparseMatrix::RowIndex row = 0; row < rowCount; ++row) {
if (dense[row].empty()) {
MATHICGB_ASSERT(!isPivotRow[row]);
@@ -546,7 +549,7 @@ namespace {
for (size_t row = 0; row < rowCount; ++row)
if (!dense[row].empty())
dense[row].appendTo(reduced);
- return std::move(reduced);
+ return ::std::move(reduced);
}
}
@@ -581,7 +584,7 @@ private:
};
*/
void addRowMultipleInplace(
- std::vector<std::vector<SparseMatrix::Scalar> >& matrix,
+ ::std::vector< ::std::vector<SparseMatrix::Scalar> >& matrix,
const SparseMatrix::RowIndex addRow,
const SparseMatrix::Scalar multiple,
const SparseMatrix::RowIndex row,
@@ -603,7 +606,7 @@ void addRowMultipleInplace(
}
void makeRowUnitary(
- std::vector<std::vector<SparseMatrix::Scalar>>& matrix,
+ ::std::vector< ::std::vector<SparseMatrix::Scalar>>& matrix,
const SparseMatrix::RowIndex row,
const SparseMatrix::ColIndex colCount,
const SparseMatrix::ColIndex leadingCol,
@@ -624,7 +627,7 @@ void makeRowUnitary(
// todo: make this take a parameter startAtCol ::DONE
SparseMatrix::ColIndex leadingColumn(
- const std::vector<std::vector<SparseMatrix::Scalar>>& matrix,
+ const ::std::vector< ::std::vector<SparseMatrix::Scalar>>& matrix,
const SparseMatrix::RowIndex row,
const SparseMatrix::ColIndex colCount,
SparseMatrix::ColIndex startAtCol
@@ -639,7 +642,7 @@ SparseMatrix::ColIndex leadingColumn(
}
void rowReducedEchelonMatrix(
- std::vector<std::vector<SparseMatrix::Scalar> >& matrix,
+ ::std::vector< ::std::vector<SparseMatrix::Scalar> >& matrix,
const SparseMatrix::ColIndex colCount,
const SparseMatrix::Scalar modulus
) {
@@ -648,7 +651,7 @@ void rowReducedEchelonMatrix(
static_cast<SparseMatrix::RowIndex>(matrix.size());
// pivotRowOfCol[i] is the pivot in column i or rowCount
// if we have not identified such a pivot so far.
- std::vector<SparseMatrix::RowIndex> pivotRowOfCol(colCount, rowCount);
+ ::std::vector<SparseMatrix::RowIndex> pivotRowOfCol(colCount, rowCount);
// row reduce to row echelon form
for(SparseMatrix::RowIndex row=0; row<rowCount;++row) {
@@ -693,7 +696,7 @@ SparseMatrix reduceToEchelonFormShrawan(
const auto colCount = toReduce.computeColCount();
// Convert input matrix to dense format
- std::vector<std::vector<SparseMatrix::Scalar>> matrix(rowCount);
+ ::std::vector< ::std::vector<SparseMatrix::Scalar>> matrix(rowCount);
for (SparseMatrix::RowIndex row = 0; row < rowCount; ++row) {
MATHICGB_ASSERT(!toReduce.emptyRow(row));
matrix[row].resize(colCount);
@@ -721,7 +724,7 @@ SparseMatrix reduceToEchelonFormShrawan(
if (!rowIsZero)
reduced.rowDone();
}
- return std::move(reduced);
+ return ::std::move(reduced);
}
SparseMatrix reduceToEchelonFormShrawanDelayedModulus(
@@ -733,7 +736,7 @@ SparseMatrix reduceToEchelonFormShrawanDelayedModulus(
const auto colCount = toReduce.computeColCount();
// Convert input matrix to dense format
- std::vector<std::vector<SparseMatrix::Scalar>> matrix(rowCount);
+ ::std::vector< ::std::vector<SparseMatrix::Scalar>> matrix(rowCount);
for (SparseMatrix::RowIndex row = 0; row < rowCount; ++row) {
MATHICGB_ASSERT(!toReduce.emptyRow(row));
matrix[row].resize(colCount);
@@ -759,7 +762,7 @@ SparseMatrix reduceToEchelonFormShrawanDelayedModulus(
if (!rowIsZero)
reduced.rowDone();
}
- return std::move(reduced);
+ return ::std::move(reduced);
}
SparseMatrix F4MatrixReducer::reduceToBottomRight(const QuadMatrix& matrix) {
@@ -815,12 +818,14 @@ namespace {
// this assert has to be NO_ASSUME as otherwise the branch below will get
// optimized out.
MATHICGB_ASSERT_NO_ASSUME(modulus <=
- std::numeric_limits<SparseMatrix::Scalar>::max());
- if (modulus > std::numeric_limits<SparseMatrix::Scalar>::max())
- throw std::overflow_error("Too large modulus in F4 matrix reduction.");
+ ::std::numeric_limits<SparseMatrix::Scalar>::max());
+ if (modulus > ::std::numeric_limits<SparseMatrix::Scalar>::max())
+ throw ::std::overflow_error("Too large modulus in F4 matrix reduction.");
return static_cast<SparseMatrix::Scalar>(modulus);
}
}
F4MatrixReducer::F4MatrixReducer(const coefficient modulus):
mModulus(checkModulus(modulus)) {}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/F4MatrixReducer.hpp b/src/mathicgb/F4MatrixReducer.hpp
index 92b2f33..29e2d42 100755
--- a/src/mathicgb/F4MatrixReducer.hpp
+++ b/src/mathicgb/F4MatrixReducer.hpp
@@ -1,39 +1,45 @@
-#ifndef F4_MATRIX_REDUCER_GUARD
-#define F4_MATRIX_REDUCER_GUARD
-
-#include "SparseMatrix.hpp"
-class QuadMatrix;
-class PolyRing;
-
-/// Class that reduces an F4 matrix represented as a QuadMatrix. The
-/// answer that you get is the submatrix that contains new pivots.
-///
-/// All QuadMatrix parameters passed into methods on this class are
-/// assumed to have a permutation of the top rows and left columns so
-/// that the top left matrix is upper unitriangular. In this way the
-/// lower left part of the matrix becomes all-zero after row reduction.
-class F4MatrixReducer {
-public:
- /// The ring used is Z/pZ where modulus is the prime p.
- ///
- ///
- F4MatrixReducer(coefficient modulus);
-
- /// Reduces the bottom rows by the top rows and returns the bottom right
- /// submatrix of the resulting quad matrix. The lower left submatrix
- /// is not returned because it is always zero after row reduction.
- SparseMatrix reduceToBottomRight(const QuadMatrix& matrix);
-
- /// Returns the reduced row echelon form of matrix.
- SparseMatrix reducedRowEchelonForm(const SparseMatrix& matrix);
-
- /// Returns the lower right submatrix of the reduced row echelon
- /// form of matrix. The lower left part is not returned because it is
- /// always zero after row reduction.
- SparseMatrix reducedRowEchelonFormBottomRight(const QuadMatrix& matrix);
-
-private:
- const SparseMatrix::Scalar mModulus;
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_F4_MATRIX_REDUCER_GUARD
+#define MATHICGB_F4_MATRIX_REDUCER_GUARD
+
+#include "SparseMatrix.hpp"
+
+MATHICGB_NAMESPACE_BEGIN
+
+class QuadMatrix;
+class PolyRing;
+
+/// Class that reduces an F4 matrix represented as a QuadMatrix. The
+/// answer that you get is the submatrix that contains new pivots.
+///
+/// All QuadMatrix parameters passed into methods on this class are
+/// assumed to have a permutation of the top rows and left columns so
+/// that the top left matrix is upper unitriangular. In this way the
+/// lower left part of the matrix becomes all-zero after row reduction.
+class F4MatrixReducer {
+public:
+ /// The ring used is Z/pZ where modulus is the prime p.
+ ///
+ ///
+ F4MatrixReducer(coefficient modulus);
+
+ /// Reduces the bottom rows by the top rows and returns the bottom right
+ /// submatrix of the resulting quad matrix. The lower left submatrix
+ /// is not returned because it is always zero after row reduction.
+ SparseMatrix reduceToBottomRight(const QuadMatrix& matrix);
+
+ /// Returns the reduced row echelon form of matrix.
+ SparseMatrix reducedRowEchelonForm(const SparseMatrix& matrix);
+
+ /// Returns the lower right submatrix of the reduced row echelon
+ /// form of matrix. The lower left part is not returned because it is
+ /// always zero after row reduction.
+ SparseMatrix reducedRowEchelonFormBottomRight(const QuadMatrix& matrix);
+
+private:
+ const SparseMatrix::Scalar mModulus;
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/F4ProtoMatrix.cpp b/src/mathicgb/F4ProtoMatrix.cpp
old mode 100644
new mode 100755
index 66a0499..90d0f65
--- a/src/mathicgb/F4ProtoMatrix.cpp
+++ b/src/mathicgb/F4ProtoMatrix.cpp
@@ -1,6 +1,10 @@
-#include "stdinc.h"
-#include "F4ProtoMatrix.hpp"
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "stdinc.h"
+#include "F4ProtoMatrix.hpp"
+
+MATHICGB_NAMESPACE_BEGIN
+
auto F4ProtoMatrix::row(const RowIndex row) const -> Row {
MATHICGB_ASSERT(row < mRows.size());
const auto& r = mRows[row];
@@ -16,15 +20,15 @@ auto F4ProtoMatrix::row(const RowIndex row) const -> Row {
}
return rr;
}
-
+
auto F4ProtoMatrix::makeRowWithTheseScalars(const Poly& scalars) -> ColIndex*
{
- MATHICGB_ASSERT(rowCount() < std::numeric_limits<RowIndex>::max());
- MATHICGB_ASSERT(scalars.termCount() < std::numeric_limits<ColIndex>::max());
+ MATHICGB_ASSERT(rowCount() < ::std::numeric_limits<RowIndex>::max());
+ MATHICGB_ASSERT(scalars.termCount() < ::std::numeric_limits<ColIndex>::max());
InternalRow row;
row.indicesBegin = mIndices.size();
- row.scalarsBegin = std::numeric_limits<decltype(row.scalarsBegin)>::max();
+ row.scalarsBegin = ::std::numeric_limits<decltype(row.scalarsBegin)>::max();
row.entryCount = static_cast<ColIndex>(scalars.termCount());
row.externalScalars = scalars.coefficientBegin();
mRows.push_back(row);
@@ -33,8 +37,8 @@ auto F4ProtoMatrix::makeRowWithTheseScalars(const Poly& scalars) -> ColIndex*
return mIndices.data() + row.indicesBegin;
}
-auto F4ProtoMatrix::makeRow(ColIndex entryCount) -> std::pair<ColIndex*, Scalar*> {
- MATHICGB_ASSERT(rowCount() < std::numeric_limits<RowIndex>::max());
+auto F4ProtoMatrix::makeRow(ColIndex entryCount) -> ::std::pair<ColIndex*, Scalar*> {
+ MATHICGB_ASSERT(rowCount() < ::std::numeric_limits<RowIndex>::max());
InternalRow row;
row.indicesBegin = mIndices.size();
@@ -45,7 +49,7 @@ auto F4ProtoMatrix::makeRow(ColIndex entryCount) -> std::pair<ColIndex*, Scalar*
mIndices.resize(mIndices.size() + entryCount);
mScalars.resize(mScalars.size() + entryCount);
- return std::make_pair(
+ return ::std::make_pair(
mIndices.data() + row.indicesBegin,
mScalars.data() + row.scalarsBegin
);
@@ -61,3 +65,5 @@ void F4ProtoMatrix::removeLastEntries(const RowIndex row, const ColIndex count)
if (mRows[row].externalScalars == 0)
mScalars.resize(mScalars.size() - count);
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/F4ProtoMatrix.hpp b/src/mathicgb/F4ProtoMatrix.hpp
old mode 100644
new mode 100755
index cff26d0..cb5f797
--- a/src/mathicgb/F4ProtoMatrix.hpp
+++ b/src/mathicgb/F4ProtoMatrix.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_F4_PROTO_MATRIX_GUARD
#define MATHICGB_F4_PROTO_MATRIX_GUARD
@@ -5,6 +7,8 @@
#include "SparseMatrix.hpp"
#include "Poly.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
class F4ProtoMatrix {
public:
typedef uint32 RowIndex;
@@ -25,7 +29,7 @@ public:
ColIndex* makeRowWithTheseScalars(const Poly& scalars);
- std::pair<ColIndex*, Scalar*> makeRow(ColIndex entryCount);
+ ::std::pair<ColIndex*, Scalar*> makeRow(ColIndex entryCount);
void removeLastEntries(const RowIndex row, const ColIndex count);
@@ -37,9 +41,10 @@ private:
const ExternalScalar* externalScalars;
};
- std::vector<ColIndex> mIndices;
- std::vector<Scalar> mScalars;
- std::vector<InternalRow> mRows;
+ ::std::vector<ColIndex> mIndices;
+ ::std::vector<Scalar> mScalars;
+ ::std::vector<InternalRow> mRows;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/F4Reducer.cpp b/src/mathicgb/F4Reducer.cpp
index 4d8f563..ae5c3ca 100755
--- a/src/mathicgb/F4Reducer.cpp
+++ b/src/mathicgb/F4Reducer.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "F4Reducer.hpp"
@@ -41,6 +43,8 @@ MATHICGB_DEFINE_LOG_ALIAS(
"F4MatReduceTop,F4RedBottomRight"
);
+MATHICGB_NAMESPACE_BEGIN
+
F4Reducer::F4Reducer(const PolyRing& ring, Type type):
mType(type),
mFallback(Reducer::makeReducer(Reducer::Reducer_BjarkeGeo, ring)),
@@ -55,58 +59,58 @@ size_t F4Reducer::preferredSetSize() const {
return 100000;
}
-void F4Reducer::writeMatricesTo(std::string file, size_t minEntries) {
- mStoreToFile = std::move(file);
+void F4Reducer::writeMatricesTo(::std::string file, size_t minEntries) {
+ mStoreToFile = ::std::move(file);
mMinEntryCountForStore = minEntries;
mMatrixSaveCount = 0;
}
-std::unique_ptr<Poly> F4Reducer::classicReduce
+::std::unique_ptr<Poly> F4Reducer::classicReduce
(const Poly& poly, const PolyBasis& basis) {
if (tracingLevel >= 2)
- std::cerr <<
+ ::std::cerr <<
"F4Reducer: Using fall-back reducer for single classic reduction\n";
auto p = mFallback->classicReduce(poly, basis);
mSigStats = mFallback->sigStats();
mClassicStats = mFallback->classicStats();
- return std::move(p);
+ return ::std::move(p);
}
-std::unique_ptr<Poly> F4Reducer::classicTailReduce
+::std::unique_ptr<Poly> F4Reducer::classicTailReduce
(const Poly& poly, const PolyBasis& basis) {
if (tracingLevel >= 2)
- std::cerr <<
+ ::std::cerr <<
"F4Reducer: Using fall-back reducer for single classic tail reduction\n";
auto p = mFallback->classicTailReduce(poly, basis);
mSigStats = mFallback->sigStats();
mClassicStats = mFallback->classicStats();
- return std::move(p);
+ return ::std::move(p);
}
-std::unique_ptr<Poly> F4Reducer::classicReduceSPoly(
+::std::unique_ptr<Poly> F4Reducer::classicReduceSPoly(
const Poly& a,
const Poly& b,
const PolyBasis& basis
) {
if (tracingLevel >= 2)
- std::cerr << "F4Reducer: "
+ ::std::cerr << "F4Reducer: "
"Using fall-back reducer for single classic S-pair reduction\n";
auto p = mFallback->classicReduceSPoly(a, b, basis);
mSigStats = mFallback->sigStats();
mClassicStats = mFallback->classicStats();
- return std::move(p);
+ return ::std::move(p);
}
void F4Reducer::classicReduceSPolySet(
- std::vector<std::pair<size_t, size_t> >& spairs,
+ ::std::vector< ::std::pair<size_t, size_t> >& spairs,
const PolyBasis& basis,
- std::vector<std::unique_ptr<Poly> >& reducedOut
+ ::std::vector< ::std::unique_ptr<Poly> >& reducedOut
) {
if (spairs.size() <= 1 && false) {
if (tracingLevel >= 2)
- std::cerr << "F4Reducer: Using fall-back reducer for "
+ ::std::cerr << "F4Reducer: Using fall-back reducer for "
<< spairs.size() << " S-pairs.\n";
mFallback->classicReduceSPolySet(spairs, basis, reducedOut);
mSigStats = mFallback->sigStats();
@@ -117,10 +121,10 @@ void F4Reducer::classicReduceSPolySet(
MATHICGB_ASSERT(!spairs.empty());
if (tracingLevel >= 2 && false)
- std::cerr << "F4Reducer: Reducing " << spairs.size() << " S-polynomials.\n";
+ ::std::cerr << "F4Reducer: Reducing " << spairs.size() << " S-polynomials.\n";
SparseMatrix reduced;
- std::vector<monomial> monomials;
+ ::std::vector<monomial> monomials;
{
QuadMatrix qm;
{
@@ -147,20 +151,20 @@ void F4Reducer::classicReduceSPolySet(
saveMatrix(qm);
reduced = F4MatrixReducer(basis.ring().charac()).
reducedRowEchelonFormBottomRight(qm);
- monomials = std::move(qm.rightColumnMonomials);
+ monomials = ::std::move(qm.rightColumnMonomials);
const auto end = qm.leftColumnMonomials.end();
for (auto it = qm.leftColumnMonomials.begin(); it != end; ++it)
mRing.freeMonomial(*it);
}
if (tracingLevel >= 2 && false)
- std::cerr << "F4Reducer: Extracted " << reduced.rowCount()
+ ::std::cerr << "F4Reducer: Extracted " << reduced.rowCount()
<< " non-zero rows\n";
for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) {
auto p = make_unique<Poly>(basis.ring());
reduced.rowToPolynomial(row, monomials, *p);
- reducedOut.push_back(std::move(p));
+ reducedOut.push_back(::std::move(p));
}
const auto end = monomials.end();
for (auto it = monomials.begin(); it != end; ++it)
@@ -168,13 +172,13 @@ void F4Reducer::classicReduceSPolySet(
}
void F4Reducer::classicReducePolySet
-(const std::vector<std::unique_ptr<Poly> >& polys,
+(const ::std::vector< ::std::unique_ptr<Poly> >& polys,
const PolyBasis& basis,
- std::vector<std::unique_ptr<Poly> >& reducedOut)
+ ::std::vector< ::std::unique_ptr<Poly> >& reducedOut)
{
if (polys.size() <= 1 && false) {
if (tracingLevel >= 2)
- std::cerr << "F4Reducer: Using fall-back reducer for "
+ ::std::cerr << "F4Reducer: Using fall-back reducer for "
<< polys.size() << " polynomials.\n";
mFallback->classicReducePolySet(polys, basis, reducedOut);
mSigStats = mFallback->sigStats();
@@ -186,10 +190,10 @@ void F4Reducer::classicReducePolySet
MATHICGB_ASSERT(!polys.empty());
if (tracingLevel >= 2 && false)
- std::cerr << "F4Reducer: Reducing " << polys.size() << " polynomials.\n";
+ ::std::cerr << "F4Reducer: Reducing " << polys.size() << " polynomials.\n";
SparseMatrix reduced;
- std::vector<monomial> monomials;
+ ::std::vector<monomial> monomials;
{
QuadMatrix qm;
{
@@ -212,20 +216,20 @@ void F4Reducer::classicReducePolySet
saveMatrix(qm);
reduced = F4MatrixReducer(basis.ring().charac()).
reducedRowEchelonFormBottomRight(qm);
- monomials = std::move(qm.rightColumnMonomials);
+ monomials = ::std::move(qm.rightColumnMonomials);
for (auto it = qm.leftColumnMonomials.begin();
it != qm.leftColumnMonomials.end(); ++it)
mRing.freeMonomial(*it);
}
if (tracingLevel >= 2 && false)
- std::cerr << "F4Reducer: Extracted " << reduced.rowCount()
+ ::std::cerr << "F4Reducer: Extracted " << reduced.rowCount()
<< " non-zero rows\n";
for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) {
auto p = make_unique<Poly>(basis.ring());
reduced.rowToPolynomial(row, monomials, *p);
- reducedOut.push_back(std::move(p));
+ reducedOut.push_back(::std::move(p));
}
const auto end = monomials.end();
for (auto it = monomials.begin(); it != end; ++it)
@@ -239,19 +243,19 @@ Poly* F4Reducer::regularReduce(
const SigPolyBasis& basis
) {
if (tracingLevel >= 2)
- std::cerr <<
+ ::std::cerr <<
"F4Reducer: Using fall-back reducer for single regular reduction\n";
auto p = mFallback->regularReduce(sig, multiple, basisElement, basis);
mSigStats = mFallback->sigStats();
mClassicStats = mFallback->classicStats();
- return std::move(p);
+ return ::std::move(p);
}
void F4Reducer::setMemoryQuantum(size_t quantum) {
mMemoryQuantum = quantum;
}
-std::string F4Reducer::description() const {
+::std::string F4Reducer::description() const {
return "F4 reducer";
}
@@ -266,12 +270,14 @@ void F4Reducer::saveMatrix(const QuadMatrix& matrix) {
if (mMinEntryCountForStore > entryCount)
return;
++mMatrixSaveCount;
- std::ostringstream fileName;
+ ::std::ostringstream fileName;
fileName << mStoreToFile << '-' << mMatrixSaveCount << ".qmat";
if (tracingLevel > 2)
- std::cerr << "F4Reducer: Saving matrix to " << fileName.str() << '\n';
+ ::std::cerr << "F4Reducer: Saving matrix to " << fileName.str() << '\n';
FILE* file = fopen(fileName.str().c_str(), "wb");
// @todo: fix leak of file on exception
matrix.write(static_cast<SparseMatrix::Scalar>(mRing.charac()), file);
fclose(file);
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/F4Reducer.hpp b/src/mathicgb/F4Reducer.hpp
index 8a07cce..47d7a3d 100755
--- a/src/mathicgb/F4Reducer.hpp
+++ b/src/mathicgb/F4Reducer.hpp
@@ -1,9 +1,14 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_F4_REDUCER_GUARD
#define MATHICGB_F4_REDUCER_GUARD
#include "Reducer.hpp"
#include "PolyRing.hpp"
#include <string>
+
+MATHICGB_NAMESPACE_BEGIN
+
class QuadMatrix;
class F4Reducer : public Reducer {
@@ -68,9 +73,5 @@ private:
size_t mMatrixSaveCount; // how many matrices have been saved
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/FixedSizeMonomialMap.h b/src/mathicgb/FixedSizeMonomialMap.h
index fa7a60f..9751e7b 100755
--- a/src/mathicgb/FixedSizeMonomialMap.h
+++ b/src/mathicgb/FixedSizeMonomialMap.h
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_FIXED_SIZE_MONOMIAL_MAP_GUARD
#define MATHICGB_FIXED_SIZE_MONOMIAL_MAP_GUARD
@@ -9,6 +11,8 @@
#include <vector>
#include <algorithm>
+MATHICGB_NAMESPACE_BEGIN
+
/// Concurrent hashtable mapping from monomials to T with a fixed number of
/// buckets. Lookups are lockless while insertions grab a lock.
///
@@ -23,7 +27,7 @@ template<class T>
class FixedSizeMonomialMap {
public:
typedef T mapped_type;
- typedef std::pair<const_monomial, mapped_type> value_type;
+ typedef ::std::pair<const_monomial, mapped_type> value_type;
/// Iterates through entries in the hash table.
class const_iterator;
@@ -42,7 +46,7 @@ public:
mRing(ring),
mNodeAlloc(sizeofNode(ring))
{
- // Calling new int[x] does not zero the array. std::atomic has a trivial
+ // Calling new int[x] does not zero the array. ::std::atomic has a trivial
// constructor so the same thing is true of new atomic[x]. Calling
// new int[x]() is supposed to zero initialize but this apparently
// does not work on GCC. So we have to fill the table with nulls
@@ -68,7 +72,7 @@ public:
make_unique_array<Atomic<Node*>>(hashMaskToBucketCount(mHashToIndexMask))
),
mRing(map.ring()),
- mNodeAlloc(std::move(map.mNodeAlloc))
+ mNodeAlloc(::std::move(map.mNodeAlloc))
{
// We can store relaxed as the constructor does not run concurrently.
setTableEntriesToNullRelaxed();
@@ -78,7 +82,7 @@ public:
const size_t index = hashToIndex(mRing.monomialHashValue(node->mono));
Node* const next = node->next.load();
node->next.store(mBuckets[index].load());
- mBuckets[index].store(node, std::memory_order_relaxed);
+ mBuckets[index].store(node, ::std::memory_order_relaxed);
node = next;
}
}
@@ -109,44 +113,44 @@ public:
/// Returns the value associated to mono or null if there is no such value.
/// Also returns an internal monomial that equals mono of such a monomial
/// exists.
- std::pair<const mapped_type*, ConstMonomial>
+ ::std::pair<const mapped_type*, ConstMonomial>
find(const const_monomial mono) const {
const HashValue monoHash = mRing.monomialHashValue(mono);
const Node* node = bucketAtIndex(hashToIndex(monoHash));
- for (; node != 0; node = node->next.load(std::memory_order_consume)) {
+ for (; node != 0; node = node->next.load(::std::memory_order_consume)) {
// To my surprise, it seems to be faster to comment out this branch.
// I guess the hash table has too few collisions to make it worth it.
//if (monoHash != mRing.monomialHashValue(node->mono))
// continue;
if (mRing.monomialEqualHintTrue(mono, node->mono))
- return std::make_pair(&node->value, node->mono);
+ return ::std::make_pair(&node->value, node->mono);
}
- return std::make_pair(static_cast<const mapped_type*>(0), ConstMonomial(0));
+ return ::std::make_pair(static_cast<const mapped_type*>(0), ConstMonomial(0));
}
// As find on the product a*b but also returns the monomial that is the
// product.
MATHICGB_INLINE
- std::pair<const mapped_type*, ConstMonomial> findProduct(
+ ::std::pair<const mapped_type*, ConstMonomial> findProduct(
const const_monomial a,
const const_monomial b
) const {
const HashValue abHash = mRing.monomialHashOfProduct(a, b);
const Node* node = bucketAtIndex(hashToIndex(abHash));
- for (; node != 0; node = node->next.load(std::memory_order_consume)) {
+ for (; node != 0; node = node->next.load(::std::memory_order_consume)) {
// To my surprise, it seems to be faster to comment out this branch.
// I guess the hash table has too few collisions to make it worth it.
//if (abHash != mRing.monomialHashValue(node->mono))
// continue;
if (mRing.monomialIsProductOfHintTrue(a, b, node->mono))
- return std::make_pair(&node->value, node->mono);
+ return ::std::make_pair(&node->value, node->mono);
}
- return std::make_pair(static_cast<const mapped_type*>(0), ConstMonomial(0));
+ return ::std::make_pair(static_cast<const mapped_type*>(0), ConstMonomial(0));
}
/// As findProduct but looks for a1*b and a2*b at one time.
MATHICGB_INLINE
- std::pair<const mapped_type*, const mapped_type*> findTwoProducts(
+ ::std::pair<const mapped_type*, const mapped_type*> findTwoProducts(
const const_monomial a1,
const const_monomial a2,
const const_monomial b
@@ -159,9 +163,9 @@ public:
if (node1 != 0 && node2 != 0 && mRing.monomialIsTwoProductsOfHintTrue
(a1, a2, b, node1->mono, node2->mono)
)
- return std::make_pair(&node1->value, &node2->value);
+ return ::std::make_pair(&node1->value, &node2->value);
else
- return std::make_pair(findProduct(a1, b).first, findProduct(a2, b).first);
+ return ::std::make_pair(findProduct(a1, b).first, findProduct(a2, b).first);
}
/// Makes value.first map to value.second unless value.first is already
@@ -172,7 +176,7 @@ public:
/// inserted value equals the already present value.
///
/// p.first.second is a internal monomial that equals value.first.
- std::pair<std::pair<const mapped_type*, ConstMonomial>, bool>
+ ::std::pair< ::std::pair<const mapped_type*, ConstMonomial>, bool>
insert(const value_type& value) {
const mgb::tbb::mutex::scoped_lock lockGuard(mInsertionMutex);
// find() loads buckets with memory_order_consume, so it may seem like
@@ -186,7 +190,7 @@ public:
{
const auto found = find(value.first);
if (found.first != 0)
- return std::make_pair(found, false); // key already present
+ return ::std::make_pair(found, false); // key already present
}
const auto node = static_cast<Node*>(mNodeAlloc.alloc());
@@ -201,8 +205,8 @@ public:
// we cannot store with memory_order_relaxed here because unlocking the
// lock only synchronizes with threads who later grab the lock - it does
// not synchronize with reading threads since they do not grab the lock.
- mBuckets[index].store(node, std::memory_order_release);
- return std::make_pair(std::make_pair(&node->value, node->mono), true); // successful insertion
+ mBuckets[index].store(node, ::std::memory_order_release);
+ return ::std::make_pair(::std::make_pair(&node->value, node->mono), true); // successful insertion
}
/// This operation removes all entries from the table. This operation
@@ -231,7 +235,7 @@ private:
void setTableEntriesToNullRelaxed() {
const auto tableEnd = mBuckets.get() + bucketCount();
for (auto tableIt = mBuckets.get(); tableIt != tableEnd; ++tableIt)
- tableIt->store(0, std::memory_order_relaxed);
+ tableIt->store(0, ::std::memory_order_relaxed);
}
struct Node {
@@ -253,7 +257,7 @@ private:
// possible number of buckets based on the range of the hash
// value type. Only unsigned overflow is defined, so we need
// to assert that the hash type is unsigned.
- static_assert(!std::numeric_limits<HashValue>::is_signed, "");
+ static_assert(!::std::numeric_limits<HashValue>::is_signed, "");
const auto hashToIndexMask = static_cast<HashValue>(pow2 - 1);
MATHICGB_ASSERT(pow2 == hashMaskToBucketCount(hashToIndexMask));
return hashToIndexMask;
@@ -277,16 +281,16 @@ private:
Node* bucketAtIndex(size_t index) {
MATHICGB_ASSERT(index < bucketCount());
- return mBuckets[index].load(std::memory_order_consume);
+ return mBuckets[index].load(::std::memory_order_consume);
}
const Node* bucketAtIndex(size_t index) const {
MATHICGB_ASSERT(index < bucketCount());
- return mBuckets[index].load(std::memory_order_consume);
+ return mBuckets[index].load(::std::memory_order_consume);
}
const HashValue mHashToIndexMask;
- std::unique_ptr<Atomic<Node*>[]> const mBuckets;
+ ::std::unique_ptr<Atomic<Node*>[]> const mBuckets;
const PolyRing& mRing;
memt::BufferPool mNodeAlloc; // nodes are allocated from here.
mgb::tbb::mutex mInsertionMutex;
@@ -294,8 +298,8 @@ private:
public:
class const_iterator {
public:
- typedef std::forward_iterator_tag iterator_category;
- typedef std::pair<mapped_type, ConstMonomial> value_type;
+ typedef ::std::forward_iterator_tag iterator_category;
+ typedef ::std::pair<mapped_type, ConstMonomial> value_type;
typedef ptrdiff_t difference_type;
typedef size_t distance_type;
typedef value_type* pointer;
@@ -306,7 +310,7 @@ public:
const_iterator& operator++() {
MATHICGB_ASSERT(mNode != 0);
MATHICGB_ASSERT(mBucket != mBucketsEnd);
- const Node* const node = mNode->next.load(std::memory_order_consume);
+ const Node* const node = mNode->next.load(::std::memory_order_consume);
if (node != 0)
mNode = node;
else
@@ -325,7 +329,7 @@ public:
const value_type operator*() const {
MATHICGB_ASSERT(mNode != 0);
- return std::make_pair(mNode->value, mNode->mono);
+ return ::std::make_pair(mNode->value, mNode->mono);
}
private:
@@ -341,7 +345,7 @@ public:
mNode = 0;
return;
}
- const Node* const node = bucketBegin->load(std::memory_order_consume);
+ const Node* const node = bucketBegin->load(::std::memory_order_consume);
if (node != 0)
mNode = node;
else
@@ -356,7 +360,7 @@ public:
mNode = 0;
break;
}
- const Node* const node = mBucket->load(std::memory_order_consume);
+ const Node* const node = mBucket->load(::std::memory_order_consume);
if (node != 0) {
mNode = node;
break;
@@ -374,4 +378,6 @@ public:
};
};
+MATHICGB_NAMESPACE_END
+
#endif
diff --git a/src/mathicgb/HashTourReducer.cpp b/src/mathicgb/HashTourReducer.cpp
index ba990a1..9a1bd21 100755
--- a/src/mathicgb/HashTourReducer.cpp
+++ b/src/mathicgb/HashTourReducer.cpp
@@ -1,10 +1,12 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "HashTourReducer.hpp"
#include <utility>
+MATHICGB_NAMESPACE_BEGIN
+
HashTourReducer::HashTourReducer(const PolyRing& ring):
mRing(ring),
mLeadTerm(0, mRing.allocMonomial()),
@@ -209,8 +211,4 @@ void HashTourReducer::dump() const
{
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
-
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/HashTourReducer.hpp b/src/mathicgb/HashTourReducer.hpp
index 8953679..234bad9 100755
--- a/src/mathicgb/HashTourReducer.hpp
+++ b/src/mathicgb/HashTourReducer.hpp
@@ -1,13 +1,15 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
-#ifndef _hash_tour_reducer_h_
-#define _hash_tour_reducer_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_HASH_TOUR_REDUCER_GUARD
+#define MATHICGB_HASH_TOUR_REDUCER_GUARD
#include "TypicalReducer.hpp"
#include "PolyHashTable.hpp"
#include <mathic.h>
#include <memtailor.h>
+MATHICGB_NAMESPACE_BEGIN
+
class HashTourReducer : public TypicalReducer {
public:
HashTourReducer(const PolyRing& R);
@@ -80,9 +82,5 @@ private:
memt::BufferPool mPool;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/KoszulQueue.cpp b/src/mathicgb/KoszulQueue.cpp
deleted file mode 100755
index 3a4daca..0000000
--- a/src/mathicgb/KoszulQueue.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "stdinc.h"
-#include "KoszulQueue.hpp"
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/KoszulQueue.hpp b/src/mathicgb/KoszulQueue.hpp
index 78986e7..bec77cb 100755
--- a/src/mathicgb/KoszulQueue.hpp
+++ b/src/mathicgb/KoszulQueue.hpp
@@ -1,10 +1,14 @@
-#ifndef koszul_queue_guard
-#define koszul_queue_guard
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_KOSZUL_QUEUE_GUARD
+#define MATHICGB_KOSZUL_QUEUE_GUARD
#include "PolyRing.hpp"
#include "NonCopyable.hpp"
#include <mathic.h>
+MATHICGB_NAMESPACE_BEGIN
+
class KoszulQueue : public NonCopyable<KoszulQueue> {
public:
typedef PolyRing::Monoid Monoid;
@@ -78,4 +82,5 @@ private:
mic::Heap<Configuration> mQueue;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/LogDomain.cpp b/src/mathicgb/LogDomain.cpp
index 74e9012..006a073 100755
--- a/src/mathicgb/LogDomain.cpp
+++ b/src/mathicgb/LogDomain.cpp
@@ -1,109 +1,115 @@
-#include "stdinc.h"
-#include "LogDomain.hpp"
-
-#include "LogDomainSet.hpp"
-#include <mathic.h>
-#include <iostream>
-
-static const auto logDomainGlobalStartTime = mgb::tbb::tick_count::now();
-
-LogDomain<true>::LogDomain(
- const char* const name,
- const char* const description,
- const bool enabled,
- const bool streamEnabled
-):
- mEnabled(enabled),
- mOriginallyEnabled(enabled),
- mStreamEnabled(streamEnabled),
- mOriginallyStreamEnabled(streamEnabled),
- mName(name),
- mDescription(description),
- mInterval(),
- mHasTime(false),
- mCount(0),
- mHasCount(false)
-{
- LogDomainSet::singleton().registerLogDomain(*this);
-}
-
-void LogDomain<true>::reset() {
- mEnabled = mOriginallyEnabled;
- mStreamEnabled = mOriginallyStreamEnabled;
- mInterval = TimeInterval();
- mHasTime = false;
- mCount = 0;
- mHasCount = false;
-}
-
-std::ostream& LogDomain<true>::stream() {
- return std::cerr;
-}
-
-LogDomain<true>::Timer LogDomain<true>::timer() {
- return Timer(*this);
-}
-
-double LogDomain<true>::loggedSecondsReal() const {
- return mInterval.realSeconds;
-}
-
-void LogDomain<true>::TimeInterval::print(std::ostream& out) const {
- const auto oldFlags = out.flags();
- const auto oldPrecision = out.precision();
- out.precision(3);
- out << std::fixed << realSeconds << "s (real)";
- // todo: restore the stream state using RAII, since the above code might
- // throw an exception.
- out.precision(oldPrecision);
- out.flags(oldFlags);
-}
-
-void LogDomain<true>::recordTime(TimeInterval interval) {
- if (!enabled())
- return;
- mInterval.realSeconds += interval.realSeconds;
- mHasTime = true;
-
- if (streamEnabled()) {
- MATHICGB_ASSERT(mName != 0);
- stream() << mName << " time recorded: ";
- interval.print(stream());
- stream() << std::endl;
- }
-}
-
-LogDomain<true>::Timer::Timer(LogDomain<true>& logger):
- mLogger(logger),
- mTimerRunning(false),
- mRealTicks()
-{
- start();
-}
-
-LogDomain<true>::Timer::~Timer() {
- stop();
-}
-
-void LogDomain<true>::Timer::stop() {
- if (!running())
- return;
- mTimerRunning = false;
- if (!mLogger.enabled())
- return;
- TimeInterval interval;
- interval.realSeconds = (mgb::tbb::tick_count::now() - mRealTicks).seconds();
- mLogger.recordTime(interval);
- return;
-}
-
-void LogDomain<true>::Timer::start() {
- if (!mLogger.enabled() || mTimerRunning)
- return;
- mTimerRunning = true;
- mRealTicks = mgb::tbb::tick_count::now();
-}
-
-LogDomainInternal::LogAliasRegisterer::LogAliasRegisterer(const char* alias, const char* of) {
- LogDomainSet::singleton().registerLogAlias(alias, of);
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "stdinc.h"
+#include "LogDomain.hpp"
+
+#include "LogDomainSet.hpp"
+#include <mathic.h>
+#include <iostream>
+
+MATHICGB_NAMESPACE_BEGIN
+
+static const auto logDomainGlobalStartTime = mgb::tbb::tick_count::now();
+
+LogDomain<true>::LogDomain(
+ const char* const name,
+ const char* const description,
+ const bool enabled,
+ const bool streamEnabled
+):
+ mEnabled(enabled),
+ mOriginallyEnabled(enabled),
+ mStreamEnabled(streamEnabled),
+ mOriginallyStreamEnabled(streamEnabled),
+ mName(name),
+ mDescription(description),
+ mInterval(),
+ mHasTime(false),
+ mCount(0),
+ mHasCount(false)
+{
+ LogDomainSet::singleton().registerLogDomain(*this);
+}
+
+void LogDomain<true>::reset() {
+ mEnabled = mOriginallyEnabled;
+ mStreamEnabled = mOriginallyStreamEnabled;
+ mInterval = TimeInterval();
+ mHasTime = false;
+ mCount = 0;
+ mHasCount = false;
+}
+
+std::ostream& LogDomain<true>::stream() {
+ return std::cerr;
+}
+
+LogDomain<true>::Timer LogDomain<true>::timer() {
+ return Timer(*this);
+}
+
+double LogDomain<true>::loggedSecondsReal() const {
+ return mInterval.realSeconds;
+}
+
+void LogDomain<true>::TimeInterval::print(std::ostream& out) const {
+ const auto oldFlags = out.flags();
+ const auto oldPrecision = out.precision();
+ out.precision(3);
+ out << std::fixed << realSeconds << "s (real)";
+ // todo: restore the stream state using RAII, since the above code might
+ // throw an exception.
+ out.precision(oldPrecision);
+ out.flags(oldFlags);
+}
+
+void LogDomain<true>::recordTime(TimeInterval interval) {
+ if (!enabled())
+ return;
+ mInterval.realSeconds += interval.realSeconds;
+ mHasTime = true;
+
+ if (streamEnabled()) {
+ MATHICGB_ASSERT(mName != 0);
+ stream() << mName << " time recorded: ";
+ interval.print(stream());
+ stream() << std::endl;
+ }
+}
+
+LogDomain<true>::Timer::Timer(LogDomain<true>& logger):
+ mLogger(logger),
+ mTimerRunning(false),
+ mRealTicks()
+{
+ start();
+}
+
+LogDomain<true>::Timer::~Timer() {
+ stop();
+}
+
+void LogDomain<true>::Timer::stop() {
+ if (!running())
+ return;
+ mTimerRunning = false;
+ if (!mLogger.enabled())
+ return;
+ TimeInterval interval;
+ interval.realSeconds = (mgb::tbb::tick_count::now() - mRealTicks).seconds();
+ mLogger.recordTime(interval);
+ return;
+}
+
+void LogDomain<true>::Timer::start() {
+ if (!mLogger.enabled() || mTimerRunning)
+ return;
+ mTimerRunning = true;
+ mRealTicks = mgb::tbb::tick_count::now();
+}
+
+LogDomainInternal::LogAliasRegisterer::LogAliasRegisterer(const char* alias, const char* of) {
+ LogDomainSet::singleton().registerLogAlias(alias, of);
+}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/LogDomain.hpp b/src/mathicgb/LogDomain.hpp
index 8e4156f..8fd741d 100755
--- a/src/mathicgb/LogDomain.hpp
+++ b/src/mathicgb/LogDomain.hpp
@@ -1,329 +1,335 @@
-#ifndef MATHICGB_LOG_DOMAIN_GUARD
-#define MATHICGB_LOG_DOMAIN_GUARD
-
-#include "mtbb.hpp"
-#include <ostream>
-#include <ctime>
-#include <sstream>
-
-/// A named area of logging that can be turned on or off at runtime and at
-/// compile time.
-///
-/// A logger that is turned off at compile time emits no code
-/// into the executable and all the code that writes to that logger is also
-/// removed by the optimizer if it is written in the correct way. Use the
-/// logging macroes to ensure proper use so that compile-time disabled
-/// LogDomains properly have zero overhead. LogDomains can be turned on
-/// and off at compile time and at runtime individually.
-///
-/// Compile-time enabled loggers automatically register themselves at start-up
-/// with LogDomainSet::singleton().
-///
-/// @todo: support turning all loggers off globally with a macro, regardless
-/// of their individual compile-time on/off setting.
-
-template<bool CompileTimeEnabled>
-class LogDomain {};
-
-template<>
-class LogDomain<true> {
-public:
- static const bool compileTimeEnabled = true;
-
- LogDomain(
- const char* const name,
- const char* const description,
- const bool enabled,
- const bool streamEnabled
- );
-
- const char* name() const {return mName;}
- const char* description() const {return mDescription;}
- bool enabled() const {return mEnabled;}
- bool streamEnabledPure() const {return mStreamEnabled;}
- bool streamEnabled() const {return enabled() && streamEnabledPure();}
-
- void setEnabled(const bool enabled) {mEnabled = enabled;}
- void setStreamEnabled(const bool enabled) {mStreamEnabled = enabled;}
-
- std::ostream& stream();
-
- /// Class for recording time that is logged. Movable.
- class Timer;
-
- /// Returns a started timer.
- Timer timer();
-
- /// Returns true if any time has been logged on this logger, even if the
- /// duration of that time was zero (that is., less than the resolution
- /// of the timer).
- bool hasTime() const {return mHasTime;}
-
- double loggedSecondsReal() const;
-
-
- typedef unsigned long long Counter;
-
- Counter count() const {return mCount;}
-
- void setCount(const Counter counter) {
- if (enabled()) {
- mCount = counter;
- mHasCount = true;
- }
- }
-
- /// Returns true if setCount has been called.
- bool hasCount() const {return mHasCount;}
-
- /// Resets this object to the state it had when it was
- /// constructed.
- void reset();
-
-private:
- struct TimeInterval {
- // todo: support user time too. clock() doesn't seem to sum the time
- // for all threads, so that didn't work.
- double realSeconds;
-
- void print(std::ostream& out) const;
- };
- void recordTime(TimeInterval interval);
-
- bool mEnabled;
- const bool mOriginallyEnabled;
- bool mStreamEnabled;
- const bool mOriginallyStreamEnabled;
- const char* mName;
- const char* mDescription;
-
- TimeInterval mInterval; /// Total amount of time recorded on this log.
- bool mHasTime; /// Whether any time has been registered (even if 0s).
-
- Counter mCount;
- bool mHasCount; /// Whether the count has been set (even if set to zero)
-};
-
-class LogDomain<true>::Timer {
-public:
- /// Start the timer running. The elapsed time will be logged to the logger
- /// once the timer is stopped or destructed.
- Timer(LogDomain<true>& logger);
-
- /// Stops the timer.
- ~Timer();
-
- /// Returns true if the timer is currently recording time.
- bool running() const {return mTimerRunning;}
-
- /// Stops recording time and logs the elapsed time to the logger.
- ///
- /// This is a no-op if the timer is not running. If the logger
- /// is disabled then no time is logged.
- void stop();
-
- /// Start recording time on a stopped timer.
- ///
- /// This is a no-op if the timer is already running or if the logger is
- /// disabled.
- void start();
-
-private:
- LogDomain<true>& mLogger;
- bool mTimerRunning;
- mgb::tbb::tick_count mRealTicks; // high precision
-};
-
-/// This is a compile-time disabled logger. You are not supposed to dynamically
-/// call any non-const methods on it other than the constructor. Code that
-/// calls other code will compile but it is an error if any of those
-/// methods get called at runtime.
-template<>
-class LogDomain<false> {
-public:
- static const bool compileTimeEnabled = false;
-
- LogDomain(const char* const, const char* const, const bool) {}
-
- bool enabled() const {return false;}
- bool streamEnabled() const {return false;}
-
- class Timer {
- public:
- Timer(LogDomain<false>&) {}
- bool running() const {return false;}
- void stop() {MATHICGB_ASSERT(false);}
- void start() {MATHICGB_ASSERT(false);}
- };
- Timer timer() {
- MATHICGB_ASSERT(false);
- return Timer(*this);
- }
-
- std::ostream& stream() {
- MATHICGB_ASSERT(false);
- return *static_cast<std::ostream*>(0);
- }
-
- typedef unsigned long long Counter;
- Counter count() const {return 0;}
- void setCount(const Counter counter) {MATHICGB_ASSERT(false);}
- bool hasCount() const {return false;}
- void reset() {}
-};
-
-namespace LogDomainInternal {
- // Helpers for the logging macroes
-
- template<class Tag, bool Default>
- struct SelectValue {static const bool value = Default;};
-
- template<class> struct Tag_ {};
- template<class> struct Tag_0 {};
- template<class> struct Tag_1 {};
-
- template<bool Default>
- struct SelectValue<Tag_0<int>, Default> {static const bool value = false;};
-
- template<bool Default>
- struct SelectValue<Tag_1<int>, Default> {static const bool value = true;};
-
- template<class L>
- struct LambdaRunner {L& log;};
- template<class L>
- LambdaRunner<L> lambdaRunner(L& l) {
- LambdaRunner<L> r = {l};
- return r;
- }
- template<class L, class T>
- void operator+(LambdaRunner<L> runner, T&& lambda) {
- lambda(runner.log, runner.log.stream());
- }
-
- struct LogAliasRegisterer {
- LogAliasRegisterer(const char* alias, const char* of);
- };
-}
-
-/// Defines LogDomainInternal::value_##NAME to be equal to the value of
-/// the macro MATHICGB_LOG_##NAME if that macro expands to 0 or 1. Otherwise
-/// the macro MATHICGB_LOG_##NAME is ignored and instead DEFAULT_VALUE is used.
-#define MATHICGB_CAPTURE_LOG_ENABLED(NAME, DEFAULT_VALUE) \
- namespace LogDomainInternal { \
- template<class> struct Tag_MATHICGB_LOG_##NAME {}; \
- typedef MATHICGB_CONCATENATE_AFTER_EXPANSION(Tag_, MATHICGB_LOG_##NAME)<int> \
- SelectedTag_##NAME; \
- static const bool value_##NAME = \
- SelectValue<SelectedTag_##NAME, DEFAULT_VALUE>::value; \
- }
-
-/// Defines a LogDomain with the given name and description.
-///
-/// The logger is default compile-time enabled depending on MATHICGB_LOG_##NAME
-/// (see MATHICGB_CAPTURE_LOG_ENABLED) and it is initially runtime
-/// enabled depending on the value of DEFAULT_RUNTIME_ENABLED. It is default
-/// runtime enabled for streaming (when also enabled in general) depending on
-/// DEFAULT_RUNTIME_STREAM_ENABLED.
-#define MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS( \
- NAME, DESCRIPTION, \
- DEFAULT_RUNTIME_ENABLED, \
- DEFAULT_RUNTIME_STREAM_ENABLED, \
- DEFAULT_COMPILE_TIME_ENABLED \
-) \
- MATHICGB_CAPTURE_LOG_ENABLED(NAME, DEFAULT_COMPILE_TIME_ENABLED); \
- namespace logs { \
- typedef LogDomain< ::LogDomainInternal::value_##NAME> Type##NAME; \
- Type##NAME NAME( \
- #NAME, \
- DESCRIPTION, \
- DEFAULT_RUNTIME_ENABLED, \
- DEFAULT_RUNTIME_STREAM_ENABLED \
- ); \
- }
-
-/// Defines a LogDomain with the given name and description.
-///
-/// The defaults for the logger are as follows.
-/// compile-time: enabled,
-/// runtime: disabled,
-/// runtime streaming: enabled (only takes effect if also enabled)
-#define MATHICGB_DEFINE_LOG_DOMAIN(NAME, DESCRIPTION) \
- MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS(NAME, DESCRIPTION, 0, 1, 1);
-
-#define MATHICGB_DEFINE_LOG_ALIAS(ALIAS, OF) \
- namespace LogDomainInternal { \
- LogAliasRegisterer MATHICGB_CONCATENATE_AFTER_EXPANSION(reg_, __LINE__) \
- (ALIAS, OF); \
- }
-
-/// This expression yields an l-value reference to the indicated logger.
-///
-/// Example:
-/// auto timer = MATHICGB_LOGGER(MyDomain).timer();
-#define MATHICGB_LOGGER(DOMAIN) ::logs::DOMAIN
-
-/// This expression yields the type of the indicated logger.
-///
-/// Example:
-/// if (MATHICGB_LOGGER_TYPE(MyDomain)::compileTimeEnabled)
-/// std::ostream << "MyDomain is compiled time enabled";
-#define MATHICGB_LOGGER_TYPE(DOMAIN) ::logs::Type##DOMAIN
-
-/// Runs the code in the following scope delimited by braces {} if the
-/// indicated logger is enabled for streaming - otherwise does
-/// nothing. Within the following scope there is a local reference
-/// variable log that refers to the indicated logger and a local
-/// reference variable stream that refers to log.stream().
-///
-/// Example:
-/// MATHICGB_IF_STREAM_LOG(MyDomain) {
-/// std::string msg;
-/// expensiveFunction(msg);
-/// stream << msg; // or log.stream() << msg;
-/// }
-#define MATHICGB_IF_STREAM_LOG(DOMAIN) \
- if (MATHICGB_LOGGER(DOMAIN).streamEnabled()) \
- LogDomainInternal::lambdaRunner(MATHICGB_LOGGER(DOMAIN)) + \
- [&](MATHICGB_LOGGER_TYPE(DOMAIN)& log, std::ostream& stream)
-
-/// Display information to the log using <<.
-/// If domain is not enabled and stream enabled then the log message is not
-/// displayed and the code after << is not executed.
-///
-/// Example: (f() only called if logger is enabled)
-/// MATHICGB_LOG(domain) << "f() = " << f();
-#define MATHICGB_LOG(DOMAIN) \
- if (MATHICGB_LOGGER(DOMAIN).streamEnabled()) MATHICGB_LOGGER(DOMAIN).stream()
-
-/// Will log the time to execute the remaining code in the current scope
-/// to the indicated domain. Also supports printing a message using <<.
-/// The message is printed right away while the time is printed when
-/// the scope ends.
-///
-/// Example:
-/// MATHICGB_LOG_SCOPE_TIME(MyDomain) << "Starting timed task";
-#define MATHICGB_LOG_TIME(DOMAIN) \
- auto MATHICGB_CONCATENATE_AFTER_EXPANSION( \
- DOMAIN, MATHICGB_CONCATENATE_AFTER_EXPANSION(_timer_, __LINE__)) \
- (MATHICGB_LOGGER(DOMAIN).timer()); \
- MATHICGB_LOG(DOMAIN)
-
-/// Increments the count of DOMAIN by the value of the expression BY. The
-/// expression BY is evaluated at most once and it is not evaluated if
-/// DOMAIN is disabled.
-///
-/// Example:
-/// MATHICGB_LOG_INCREMENT_BY(MyDomain, 3);
-#define MATHICGB_LOG_INCREMENT_BY(DOMAIN, BY) \
- do { \
- auto& MGBLOG_log = MATHICGB_LOGGER(DOMAIN); \
- if (MGBLOG_log.enabled()) { \
- MGBLOG_log.setCount(MGBLOG_log.count() + BY); \
- } \
- } while (false)
-
-/// Increments the count of DOMAIN by 1.
-#define MATHICGB_LOG_INCREMENT(DOMAIN) \
- MATHICGB_LOG_INCREMENT_BY(DOMAIN, 1)
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_LOG_DOMAIN_GUARD
+#define MATHICGB_LOG_DOMAIN_GUARD
+
+#include "mtbb.hpp"
+#include <ostream>
+#include <ctime>
+#include <sstream>
+
+MATHICGB_NAMESPACE_BEGIN
+
+/// A named area of logging that can be turned on or off at runtime and at
+/// compile time.
+///
+/// A logger that is turned off at compile time emits no code
+/// into the executable and all the code that writes to that logger is also
+/// removed by the optimizer if it is written in the correct way. Use the
+/// logging macroes to ensure proper use so that compile-time disabled
+/// LogDomains properly have zero overhead. LogDomains can be turned on
+/// and off at compile time and at runtime individually.
+///
+/// Compile-time enabled loggers automatically register themselves at start-up
+/// with LogDomainSet::singleton().
+///
+/// @todo: support turning all loggers off globally with a macro, regardless
+/// of their individual compile-time on/off setting.
+
+template<bool CompileTimeEnabled>
+class LogDomain {};
+
+template<>
+class LogDomain<true> {
+public:
+ static const bool compileTimeEnabled = true;
+
+ LogDomain(
+ const char* const name,
+ const char* const description,
+ const bool enabled,
+ const bool streamEnabled
+ );
+
+ const char* name() const {return mName;}
+ const char* description() const {return mDescription;}
+ bool enabled() const {return mEnabled;}
+ bool streamEnabledPure() const {return mStreamEnabled;}
+ bool streamEnabled() const {return enabled() && streamEnabledPure();}
+
+ void setEnabled(const bool enabled) {mEnabled = enabled;}
+ void setStreamEnabled(const bool enabled) {mStreamEnabled = enabled;}
+
+ ::std::ostream& stream();
+
+ /// Class for recording time that is logged. Movable.
+ class Timer;
+
+ /// Returns a started timer.
+ Timer timer();
+
+ /// Returns true if any time has been logged on this logger, even if the
+ /// duration of that time was zero (that is., less than the resolution
+ /// of the timer).
+ bool hasTime() const {return mHasTime;}
+
+ double loggedSecondsReal() const;
+
+
+ typedef unsigned long long Counter;
+
+ Counter count() const {return mCount;}
+
+ void setCount(const Counter counter) {
+ if (enabled()) {
+ mCount = counter;
+ mHasCount = true;
+ }
+ }
+
+ /// Returns true if setCount has been called.
+ bool hasCount() const {return mHasCount;}
+
+ /// Resets this object to the state it had when it was
+ /// constructed.
+ void reset();
+
+private:
+ struct TimeInterval {
+ // todo: support user time too. clock() doesn't seem to sum the time
+ // for all threads, so that didn't work.
+ double realSeconds;
+
+ void print(::std::ostream& out) const;
+ };
+ void recordTime(TimeInterval interval);
+
+ bool mEnabled;
+ const bool mOriginallyEnabled;
+ bool mStreamEnabled;
+ const bool mOriginallyStreamEnabled;
+ const char* mName;
+ const char* mDescription;
+
+ TimeInterval mInterval; /// Total amount of time recorded on this log.
+ bool mHasTime; /// Whether any time has been registered (even if 0s).
+
+ Counter mCount;
+ bool mHasCount; /// Whether the count has been set (even if set to zero)
+};
+
+class LogDomain<true>::Timer {
+public:
+ /// Start the timer running. The elapsed time will be logged to the logger
+ /// once the timer is stopped or destructed.
+ Timer(LogDomain<true>& logger);
+
+ /// Stops the timer.
+ ~Timer();
+
+ /// Returns true if the timer is currently recording time.
+ bool running() const {return mTimerRunning;}
+
+ /// Stops recording time and logs the elapsed time to the logger.
+ ///
+ /// This is a no-op if the timer is not running. If the logger
+ /// is disabled then no time is logged.
+ void stop();
+
+ /// Start recording time on a stopped timer.
+ ///
+ /// This is a no-op if the timer is already running or if the logger is
+ /// disabled.
+ void start();
+
+private:
+ LogDomain<true>& mLogger;
+ bool mTimerRunning;
+ mgb::tbb::tick_count mRealTicks; // high precision
+};
+
+/// This is a compile-time disabled logger. You are not supposed to dynamically
+/// call any non-const methods on it other than the constructor. Code that
+/// calls other code will compile but it is an error if any of those
+/// methods get called at runtime.
+template<>
+class LogDomain<false> {
+public:
+ static const bool compileTimeEnabled = false;
+
+ LogDomain(const char* const, const char* const, const bool) {}
+
+ bool enabled() const {return false;}
+ bool streamEnabled() const {return false;}
+
+ class Timer {
+ public:
+ Timer(LogDomain<false>&) {}
+ bool running() const {return false;}
+ void stop() {MATHICGB_ASSERT(false);}
+ void start() {MATHICGB_ASSERT(false);}
+ };
+ Timer timer() {
+ MATHICGB_ASSERT(false);
+ return Timer(*this);
+ }
+
+ ::std::ostream& stream() {
+ MATHICGB_ASSERT(false);
+ return *static_cast< ::std::ostream*>(0);
+ }
+
+ typedef unsigned long long Counter;
+ Counter count() const {return 0;}
+ void setCount(const Counter counter) {MATHICGB_ASSERT(false);}
+ bool hasCount() const {return false;}
+ void reset() {}
+};
+
+namespace LogDomainInternal {
+ // Helpers for the logging macroes
+
+ template<class Tag, bool Default>
+ struct SelectValue {static const bool value = Default;};
+
+ template<class> struct Tag_ {};
+ template<class> struct Tag_0 {};
+ template<class> struct Tag_1 {};
+
+ template<bool Default>
+ struct SelectValue<Tag_0<int>, Default> {static const bool value = false;};
+
+ template<bool Default>
+ struct SelectValue<Tag_1<int>, Default> {static const bool value = true;};
+
+ template<class L>
+ struct LambdaRunner {L& log;};
+ template<class L>
+ LambdaRunner<L> lambdaRunner(L& l) {
+ LambdaRunner<L> r = {l};
+ return r;
+ }
+ template<class L, class T>
+ void operator+(LambdaRunner<L> runner, T&& lambda) {
+ lambda(runner.log, runner.log.stream());
+ }
+
+ struct LogAliasRegisterer {
+ LogAliasRegisterer(const char* alias, const char* of);
+ };
+}
+
+MATHICGB_NAMESPACE_END
+
+/// Defines LogDomainInternal::value_##NAME to be equal to the value of
+/// the macro MATHICGB_LOG_##NAME if that macro expands to 0 or 1. Otherwise
+/// the macro MATHICGB_LOG_##NAME is ignored and instead DEFAULT_VALUE is used.
+#define MATHICGB_CAPTURE_LOG_ENABLED(NAME, DEFAULT_VALUE) \
+ namespace mgb{namespace LogDomainInternal { \
+ template<class> struct Tag_MATHICGB_LOG_##NAME {}; \
+ typedef MATHICGB_CONCATENATE_AFTER_EXPANSION(Tag_, MATHICGB_LOG_##NAME)<int> \
+ SelectedTag_##NAME; \
+ static const bool value_##NAME = \
+ SelectValue<SelectedTag_##NAME, DEFAULT_VALUE>::value; \
+ }}
+
+/// Defines a LogDomain with the given name and description.
+///
+/// The logger is default compile-time enabled depending on MATHICGB_LOG_##NAME
+/// (see MATHICGB_CAPTURE_LOG_ENABLED) and it is initially runtime
+/// enabled depending on the value of DEFAULT_RUNTIME_ENABLED. It is default
+/// runtime enabled for streaming (when also enabled in general) depending on
+/// DEFAULT_RUNTIME_STREAM_ENABLED.
+#define MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS( \
+ NAME, DESCRIPTION, \
+ DEFAULT_RUNTIME_ENABLED, \
+ DEFAULT_RUNTIME_STREAM_ENABLED, \
+ DEFAULT_COMPILE_TIME_ENABLED \
+) \
+ MATHICGB_CAPTURE_LOG_ENABLED(NAME, DEFAULT_COMPILE_TIME_ENABLED); \
+ namespace mgb{namespace logs { \
+ typedef LogDomain< ::mgb::LogDomainInternal::value_##NAME> Type##NAME; \
+ Type##NAME NAME( \
+ #NAME, \
+ DESCRIPTION, \
+ DEFAULT_RUNTIME_ENABLED, \
+ DEFAULT_RUNTIME_STREAM_ENABLED \
+ ); \
+ }}
+
+/// Defines a LogDomain with the given name and description.
+///
+/// The defaults for the logger are as follows.
+/// compile-time: enabled,
+/// runtime: disabled,
+/// runtime streaming: enabled (only takes effect if also enabled)
+#define MATHICGB_DEFINE_LOG_DOMAIN(NAME, DESCRIPTION) \
+ MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS(NAME, DESCRIPTION, 0, 1, 1);
+
+#define MATHICGB_DEFINE_LOG_ALIAS(ALIAS, OF) \
+ namespace mgb{namespace LogDomainInternal { \
+ LogAliasRegisterer MATHICGB_CONCATENATE_AFTER_EXPANSION(reg_, __LINE__) \
+ (ALIAS, OF); \
+ }}
+
+/// This expression yields an l-value reference to the indicated logger.
+///
+/// Example:
+/// auto timer = MATHICGB_LOGGER(MyDomain).timer();
+#define MATHICGB_LOGGER(DOMAIN) ::mgb::logs::DOMAIN
+
+/// This expression yields the type of the indicated logger.
+///
+/// Example:
+/// if (MATHICGB_LOGGER_TYPE(MyDomain)::compileTimeEnabled)
+/// ::std::ostream << "MyDomain is compiled time enabled";
+#define MATHICGB_LOGGER_TYPE(DOMAIN) ::mgb::logs::Type##DOMAIN
+
+/// Runs the code in the following scope delimited by braces {} if the
+/// indicated logger is enabled for streaming - otherwise does
+/// nothing. Within the following scope there is a local reference
+/// variable log that refers to the indicated logger and a local
+/// reference variable stream that refers to log.stream().
+///
+/// Example:
+/// MATHICGB_IF_STREAM_LOG(MyDomain) {
+/// ::std::string msg;
+/// expensiveFunction(msg);
+/// stream << msg; // or log.stream() << msg;
+/// }
+#define MATHICGB_IF_STREAM_LOG(DOMAIN) \
+ if (MATHICGB_LOGGER(DOMAIN).streamEnabled()) \
+ LogDomainInternal::lambdaRunner(MATHICGB_LOGGER(DOMAIN)) + \
+ [&](MATHICGB_LOGGER_TYPE(DOMAIN)& log, ::std::ostream& stream)
+
+/// Display information to the log using <<.
+/// If domain is not enabled and stream enabled then the log message is not
+/// displayed and the code after << is not executed.
+///
+/// Example: (f() only called if logger is enabled)
+/// MATHICGB_LOG(domain) << "f() = " << f();
+#define MATHICGB_LOG(DOMAIN) \
+ if (MATHICGB_LOGGER(DOMAIN).streamEnabled()) MATHICGB_LOGGER(DOMAIN).stream()
+
+/// Will log the time to execute the remaining code in the current scope
+/// to the indicated domain. Also supports printing a message using <<.
+/// The message is printed right away while the time is printed when
+/// the scope ends.
+///
+/// Example:
+/// MATHICGB_LOG_SCOPE_TIME(MyDomain) << "Starting timed task";
+#define MATHICGB_LOG_TIME(DOMAIN) \
+ auto MATHICGB_CONCATENATE_AFTER_EXPANSION( \
+ DOMAIN, MATHICGB_CONCATENATE_AFTER_EXPANSION(_timer_, __LINE__)) \
+ (MATHICGB_LOGGER(DOMAIN).timer()); \
+ MATHICGB_LOG(DOMAIN)
+
+/// Increments the count of DOMAIN by the value of the expression BY. The
+/// expression BY is evaluated at most once and it is not evaluated if
+/// DOMAIN is disabled.
+///
+/// Example:
+/// MATHICGB_LOG_INCREMENT_BY(MyDomain, 3);
+#define MATHICGB_LOG_INCREMENT_BY(DOMAIN, BY) \
+ do { \
+ auto& MGBLOG_log = MATHICGB_LOGGER(DOMAIN); \
+ if (MGBLOG_log.enabled()) { \
+ MGBLOG_log.setCount(MGBLOG_log.count() + BY); \
+ } \
+ } while (false)
+
+/// Increments the count of DOMAIN by 1.
+#define MATHICGB_LOG_INCREMENT(DOMAIN) \
+ MATHICGB_LOG_INCREMENT_BY(DOMAIN, 1)
+
+#endif
diff --git a/src/mathicgb/LogDomainSet.cpp b/src/mathicgb/LogDomainSet.cpp
index 7ced995..995a789 100755
--- a/src/mathicgb/LogDomainSet.cpp
+++ b/src/mathicgb/LogDomainSet.cpp
@@ -1,8 +1,12 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "LogDomainSet.hpp"
#include <mathic.h>
+MATHICGB_NAMESPACE_BEGIN
+
LogDomainSet::LogDomainSet():
mStartTime(mgb::tbb::tick_count::now()) {
}
@@ -208,3 +212,5 @@ LogDomainSet& LogDomainSet::singleton() {
static LogDomainSet set;
return set;
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/LogDomainSet.hpp b/src/mathicgb/LogDomainSet.hpp
index f73481b..cfa5ccd 100755
--- a/src/mathicgb/LogDomainSet.hpp
+++ b/src/mathicgb/LogDomainSet.hpp
@@ -1,90 +1,95 @@
-#ifndef MATHICGB_LOG_DOMAIN_SET_GUARD
-#define MATHICGB_LOG_DOMAIN_SET_GUARD
-
-#include "LogDomain.hpp"
-#include "mtbb.hpp"
-#include <string>
-#include <vector>
-#include <algorithm>
-#include <cstring>
-#include <ostream>
-
-class LogDomainSet {
-public:
- void registerLogDomain(LogDomain<true>& domain);
- void registerLogDomain(const LogDomain<false>& domain) {}
-
- void registerLogAlias(const char* alias, const char* of);
-
- /// A log command has the format AXB, where
- /// X the name of a compile-time enabled log domain
- /// A a prefix
- /// B a suffix
- /// The possible values of A are
- /// enable X (this is the empty string)
- /// + enable X
- /// - disable X
- /// 0 do nothing
- /// The possible values of B are
- /// do nothing (this is the empty string)
- /// + stream-enabled X
- /// - stream-disable X
- /// 0 do nothing
- ///
- /// No white-space is allowed.
- /// If the command cannot be parsed then you will get an exception.
- ///
- /// *** Example ***
- /// Consider this sequence of commands:
- /// "+MyLog-" will enabled MyLog, but silence any streaming from it.
- /// "+MyLog" will make no difference, as MyLog is already enabled.
- /// "-MyLog+" will disable MyLog, but set the streaming state to enabled.
- /// As MyLog is disabled there will still be no streaming output.
- /// "+MyLog" will enabled MyLog. Since the streaming state was enabled
- /// before, we now get streaming.
- ///
- void performLogCommand(std::string cmd)
- {performLogCommandInternal(' ', std::move(cmd), ' ');}
-
- /// Performs a comma-seperated list of commands. No white-space is allowed.
- void performLogCommands(const std::string& cmds)
- {performLogCommandsInternal(' ', cmds, ' ');}
-
- LogDomain<true>* logDomain(const char* const name);
-
- const char* alias(const char* name);
-
- const std::vector<LogDomain<true>*>& logDomains() const {return mLogDomains;}
- const std::vector<std::pair<const char*, const char*>>& aliases() const
- {return mAliases;}
-
- void printReport(std::ostream& out) const;
- void printTimeReport(std::ostream& out) const;
- void printCountReport(std::ostream& out) const;
-
- /// Resets the logging system as though the program had just started up.
- /// This resets all counts, all recorded time and the enabledness of all logs.
- /// You should not have a timer running for a log when you call this method.
- void reset();
-
- static LogDomainSet& singleton();
-
-private:
- void performLogCommandInternal(
- char prefix,
- std::string name,
- char suffix
- );
- void performLogCommandsInternal(
- const char prefix,
- const std::string& cmds,
- const char suffix
- );
- LogDomainSet(); // private for singleton
-
- std::vector<LogDomain<true>*> mLogDomains;
- std::vector<std::pair<const char*, const char*>> mAliases;
- mgb::tbb::tick_count mStartTime;
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_LOG_DOMAIN_SET_GUARD
+#define MATHICGB_LOG_DOMAIN_SET_GUARD
+
+#include "LogDomain.hpp"
+#include "mtbb.hpp"
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <cstring>
+#include <ostream>
+
+MATHICGB_NAMESPACE_BEGIN
+
+class LogDomainSet {
+public:
+ void registerLogDomain(LogDomain<true>& domain);
+ void registerLogDomain(const LogDomain<false>& domain) {}
+
+ void registerLogAlias(const char* alias, const char* of);
+
+ /// A log command has the format AXB, where
+ /// X the name of a compile-time enabled log domain
+ /// A a prefix
+ /// B a suffix
+ /// The possible values of A are
+ /// enable X (this is the empty string)
+ /// + enable X
+ /// - disable X
+ /// 0 do nothing
+ /// The possible values of B are
+ /// do nothing (this is the empty string)
+ /// + stream-enabled X
+ /// - stream-disable X
+ /// 0 do nothing
+ ///
+ /// No white-space is allowed.
+ /// If the command cannot be parsed then you will get an exception.
+ ///
+ /// *** Example ***
+ /// Consider this sequence of commands:
+ /// "+MyLog-" will enabled MyLog, but silence any streaming from it.
+ /// "+MyLog" will make no difference, as MyLog is already enabled.
+ /// "-MyLog+" will disable MyLog, but set the streaming state to enabled.
+ /// As MyLog is disabled there will still be no streaming output.
+ /// "+MyLog" will enabled MyLog. Since the streaming state was enabled
+ /// before, we now get streaming.
+ ///
+ void performLogCommand(std::string cmd)
+ {performLogCommandInternal(' ', std::move(cmd), ' ');}
+
+ /// Performs a comma-seperated list of commands. No white-space is allowed.
+ void performLogCommands(const std::string& cmds)
+ {performLogCommandsInternal(' ', cmds, ' ');}
+
+ LogDomain<true>* logDomain(const char* const name);
+
+ const char* alias(const char* name);
+
+ const std::vector<LogDomain<true>*>& logDomains() const {return mLogDomains;}
+ const std::vector<std::pair<const char*, const char*>>& aliases() const
+ {return mAliases;}
+
+ void printReport(std::ostream& out) const;
+ void printTimeReport(std::ostream& out) const;
+ void printCountReport(std::ostream& out) const;
+
+ /// Resets the logging system as though the program had just started up.
+ /// This resets all counts, all recorded time and the enabledness of all logs.
+ /// You should not have a timer running for a log when you call this method.
+ void reset();
+
+ static LogDomainSet& singleton();
+
+private:
+ void performLogCommandInternal(
+ char prefix,
+ std::string name,
+ char suffix
+ );
+ void performLogCommandsInternal(
+ const char prefix,
+ const std::string& cmds,
+ const char suffix
+ );
+ LogDomainSet(); // private for singleton
+
+ std::vector<LogDomain<true>*> mLogDomains;
+ std::vector<std::pair<const char*, const char*>> mAliases;
+ mgb::tbb::tick_count mStartTime;
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/MTArray.cpp b/src/mathicgb/MTArray.cpp
index 53ff925..42bb736 100755
--- a/src/mathicgb/MTArray.cpp
+++ b/src/mathicgb/MTArray.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "MTArray.hpp"
@@ -5,6 +7,8 @@
#include "MonTableKDTree.hpp"
#include "MonTableDivList.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
template <typename MT>
class MTArrayT : public MonomialTableArray
{
@@ -254,7 +258,4 @@ std::unique_ptr<MonomialTableArray> MonomialTableArray::make(const PolyRing *R,
}
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/MTArray.hpp b/src/mathicgb/MTArray.hpp
index 22a5573..28d84a1 100755
--- a/src/mathicgb/MTArray.hpp
+++ b/src/mathicgb/MTArray.hpp
@@ -1,13 +1,15 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _monomial_module_h_
-#define _monomial_module_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_M_T_ARRAY_GUARD
+#define MATHICGB_M_T_ARRAY_GUARD
#include "PolyRing.hpp"
#include <vector>
#include <iostream>
#include <algorithm>
+MATHICGB_NAMESPACE_BEGIN
+
class MonomialTableArray
{
public:
@@ -99,9 +101,5 @@ protected:
const PolyRing *R;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/MathicIO.cpp b/src/mathicgb/MathicIO.cpp
index 2f0dd0d..ecd51fd 100755
--- a/src/mathicgb/MathicIO.cpp
+++ b/src/mathicgb/MathicIO.cpp
@@ -1,373 +1,379 @@
-#include "stdinc.h"
-#include "MathicIO.hpp"
-
-auto MathicIO::readBaseField(Scanner& in) -> BaseField {
- return BaseField(in.readInteger<RawCoefficient>());
-}
-
-void MathicIO::writeBaseField(const BaseField& field, std::ostream& out) {
- out << field.charac();
-}
-
-auto MathicIO::readRing(
- const bool withComponent,
- Scanner& in
-) -> std::pair<std::unique_ptr<PolyRing>, Processor> {
- auto baseField = readBaseField(in);
- const auto varCount = in.readInteger<VarIndex>();
- auto order = readOrder(varCount, withComponent, in);
- const bool componentsAscendingDesired = order.componentsAscendingDesired();
- const bool schreyering = order.schreyering();
- auto ring = make_unique<PolyRing>
- (std::move(baseField), Monoid(std::move(order)));
-
- Processor processor(ring->monoid(), componentsAscendingDesired, schreyering);
-
- return std::make_pair(std::move(ring), std::move(processor));
-}
-
-void MathicIO::writeRing(
- const PolyRing& ring,
- const Processor& processor,
- const bool withComponent,
- std::ostream& out
-){
- writeBaseField(ring.field(), out);
- out << ' ' << ring.varCount() << '\n';
-
- auto&& order = ring.monoid().makeOrder(
- processor.componentsAscendingDesired(),
- processor.schreyering()
- );
- writeOrder(order, withComponent, out);
-}
-
-auto MathicIO::readOrder(
- const VarIndex varCount,
- const bool withComponent,
- Scanner& in
-) -> Order {
- const bool schreyering = in.match("schreyer");
- bool lexBaseOrder = !in.match("revlex") && in.match("lex");
-
- const auto gradingCount = in.readInteger<VarIndex>();
- bool componentsAscendingDesired = true;
- auto componentCompareIndex = Order::ComponentAfterBaseOrder;
- Gradings gradings(static_cast<size_t>(varCount) * gradingCount);
- size_t index = 0;
- for (VarIndex grading = 0; grading < gradingCount; ++grading) {
- const bool com = in.match("component");
- if (com || in.match("revcomponent")) {
- if (!withComponent)
- in.reportError("Cannot specify component comparison for non-modules.");
- MATHICGB_ASSERT(Monoid::HasComponent);
- if (componentCompareIndex != Order::ComponentAfterBaseOrder)
- in.reportError("Component comparison must be specified at most once.");
- componentsAscendingDesired = com;
- componentCompareIndex = grading;
- index += varCount;
- } else {
- for (VarIndex i = 0; i < varCount; ++i, ++index)
- gradings[index] = in.readInteger<Exponent>();
- }
- }
- MATHICGB_ASSERT(index == gradings.size());
-
- const bool moreLex = in.match("_lex");
- if (moreLex || in.match("_revlex")) {
- lexBaseOrder = moreLex;
- const bool moreCom = in.match("component");
- if (moreCom || in.match("revcomponent")) {
- if (!withComponent)
- in.reportError("Cannot specify component comparison for non-modules.");
- MATHICGB_ASSERT(Monoid::HasComponent);
- componentsAscendingDesired = moreCom;
- }
- }
-
- Order order(
- varCount,
- std::move(gradings),
- lexBaseOrder ? Order::LexBaseOrder : Order::RevLexBaseOrder,
- componentCompareIndex,
- componentsAscendingDesired,
- schreyering
- );
- return std::move(order);
-}
-
-void MathicIO::writeOrder(
- const Order& order,
- const bool withComponent,
- std::ostream& out
-) {
- MATHICGB_ASSERT(Monoid::HasComponent || !withComponent);
-
- const auto baseOrder =
- order.baseOrder() == Order::LexBaseOrder ? "lex" : "revlex";
- const auto componentOrder =
- order.componentsAscendingDesired() ? "component" : "revcomponent";
-
- if (order.schreyering())
- out << "schreyer ";
- out << baseOrder << ' ' << order.gradingCount() << '\n';
- for (VarIndex grading = 0; grading < order.gradingCount(); ++grading) {
- if (withComponent && grading == order.componentGradingIndex())
- out << ' ' << componentOrder;
- else {
- for (VarIndex var = 0; var < order.varCount(); ++var) {
- const auto index = var + grading * order.varCount();
- out << ' ' << unchar(order.gradings()[index]);
- }
- }
- out << '\n';
- }
- if (
- withComponent &&
- !order.componentsAscendingDesired() &&
- order.componentGradingIndex() == Order::ComponentAfterBaseOrder
- ) {
- out << " _" << baseOrder << "\n " << componentOrder << '\n';
- }
-}
-
-Basis MathicIO::readBasis(
- const PolyRing& ring,
- const bool readComponent,
- Scanner& in
-) {
- const auto polyCount = in.readInteger<size_t>();
- Basis basis(ring);
- for (size_t i = 0; i < polyCount; ++i) {
- auto p = make_unique<Poly>(readPoly(ring, readComponent, in));
- p->sortTermsDescending();
- basis.insert(std::move(p));
- }
- return std::move(basis);
-}
-
-void MathicIO::writeBasis(
- const Basis& basis,
- const bool writeComponent,
- std::ostream& out
-) {
- out << basis.size() << '\n';
- for (size_t i = 0; i < basis.size(); ++i) {
- out << ' ';
- writePoly(*basis.getPoly(i), writeComponent, out);
- out << '\n';
- }
-}
-
-Poly MathicIO::readPoly(
- const PolyRing& ring,
- const bool readComponent,
- Scanner& in
-) {
- Poly p(ring);
-
- // also skips whitespace
- if (in.match('0') || in.match("+0") || in.match("-0"))
- return std::move(p);
- MATHICGB_ASSERT(!in.peekWhite());
-
- auto mono = ring.monoid().alloc();
- auto coef = ring.field().zero();
- do {
- if (!p.isZero() && !in.peekSign())
- in.expect('+', '-');
- readTerm(ring, readComponent, coef, mono, in);
- p.appendTerm(coef.value(), mono);
- } while (!in.peekWhite() && !in.matchEOF());
- return std::move(p);
-}
-
-void MathicIO::writePoly(
- const Poly& poly,
- const bool writeComponent,
- std::ostream& out
-) {
- if (poly.isZero()) {
- out << '0';
- return;
- }
-
- const auto end = poly.end();
- for (auto it = poly.begin(); it != end; ++it) {
- if (it != poly.begin())
- out << '+';
- writeTerm(
- poly.ring(),
- writeComponent,
- poly.ring().field().toElement(it.getCoefficient()),
- it.getMonomial(),
- out
- );
- }
-}
-
-void MathicIO::readTerm(
- const PolyRing& ring,
- const bool readComponent,
- Coefficient& coef,
- MonoRef mono,
- Scanner& in
-) {
- // ** Read coefficient, if any.
- const auto& field = ring.field();
- const auto& monoid = ring.monoid();
- const bool negate = !in.match('+') && in.match('-');
- if (in.peekDigit()) {
- coef = in.readModular(field, negate);
-
- if (!in.peekAlpha()) {
- // Identify a number c on its own as the monomial 1 times c.
- monoid.setIdentity(mono);
- if (readComponent)
- this->readComponent(monoid, mono, in);
- return;
- }
- } else if (negate)
- coef = field.minusOne();
- else
- coef = field.one();
-
- readMonomial(monoid, readComponent, mono, in);
-}
-
-void MathicIO::writeTerm(
- const PolyRing& ring,
- const bool writeComponent,
- const Coefficient coef,
- ConstMonoRef mono,
- std::ostream& out
-) {
- if (!ring.field().isOne(coef)) {
- out << unchar(coef.value());
- if (ring.monoid().isIdentity(mono)) {
- if (writeComponent)
- this->writeComponent(ring.monoid(), mono, out);
- return;
- }
- }
- writeMonomial(ring.monoid(), writeComponent, mono, out);
-}
-
-void MathicIO::readMonomial(
- const Monoid& monoid,
- const bool readComponent,
- MonoRef mono,
- Scanner& in
-) {
- MATHICGB_ASSERT(!readComponent || Monoid::HasComponent);
-
- monoid.setIdentity(mono);
- if (in.peek() == '1') {
- const auto e = in.readInteger<Exponent>();
- if (e != 1) {
- std::ostringstream err;
- err << "Expected monomial, but got " << e << " (did you mean 1?).";
- in.reportError(err.str());
- }
- } else {
- bool sawSome = false;
- while (true) {
- const auto letterCount = 'z' - 'a' + 1;
- const auto letter = in.peek();
-
- VarIndex var;
- if ('a' <= letter && letter <= 'z')
- var = letter - 'a';
- else if ('A' <= letter && letter <= 'Z')
- var = (letter - 'A') + letterCount;
- else if (sawSome)
- break;
- else {
- std::ostringstream err;
- err << "Expected letter while reading monomial, but got '"
- << static_cast<char>(letter) << "'.";
- in.reportError(err.str());
- return;
- }
- in.get(); // skip past letter
-
- MATHICGB_ASSERT(var < 2 * letterCount);
- if (var >= monoid.varCount()) {
- std::ostringstream err;
- err << "Saw the variable " << static_cast<char>(letter)
- << ", but the monoid only has "
- << monoid.varCount() << " variables.";
- in.reportError(err.str());
- return;
- }
- if (monoid.exponent(mono, var) > static_cast<Exponent>(0)) {
- std::ostringstream err;
- err << "Variable " << static_cast<char>(letter) <<
- " must not be written twice in one monomial.";
- in.reportError(err.str());
- }
-
- if (in.peekDigit())
- monoid.setExponent(var, in.readInteger<Exponent>(), mono);
- else
- monoid.setExponent(var, static_cast<Exponent>(1), mono);
- sawSome = true;
- }
- }
-
- if (readComponent)
- this->readComponent(monoid, mono, in);
-}
-
-void MathicIO::readComponent(
- const Monoid& monoid,
- MonoRef mono,
- Scanner& in
-) {
- MATHICGB_ASSERT(Monoid::HasComponent);
- in.expect('<');
- monoid.setComponent(in.readInteger<Exponent>(), mono);
- in.expect('>');
-}
-
-void MathicIO::writeComponent(
- const Monoid& monoid,
- ConstMonoRef mono,
- std::ostream& out
-) {
- MATHICGB_ASSERT(Monoid::HasComponent);
- out << '<' << unchar(monoid.component(mono)) << '>';
-}
-
-/// Print a monomial with no coefficient.
-void MathicIO::writeMonomial(
- const Monoid& monoid,
- const bool writeComponent,
- ConstMonoRef mono,
- std::ostream& out
-) {
- const auto letterCount = 'z' - 'a' + 1;
-
- bool printedSome = false;
- for (VarIndex var = 0; var < monoid.varCount(); ++var) {
- if (monoid.exponent(mono, var) == 0)
- continue;
- char letter;
- if (var < letterCount)
- letter = 'a' + static_cast<char>(var);
- else if (var < 2 * letterCount)
- letter = 'A' + (static_cast<char>(var) - letterCount);
- else {
- mathic::reportError("Too few letters in alphabet to print variable.");
- return;
- }
- printedSome = true;
- out << letter;
- if (monoid.exponent(mono, var) != 1)
- out << unchar(monoid.exponent(mono, var));
- }
- if (!printedSome)
- out << '1';
- if (writeComponent)
- this->writeComponent(monoid, mono, out);
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "stdinc.h"
+#include "MathicIO.hpp"
+
+MATHICGB_NAMESPACE_BEGIN
+
+auto MathicIO::readBaseField(Scanner& in) -> BaseField {
+ return BaseField(in.readInteger<RawCoefficient>());
+}
+
+void MathicIO::writeBaseField(const BaseField& field, std::ostream& out) {
+ out << field.charac();
+}
+
+auto MathicIO::readRing(
+ const bool withComponent,
+ Scanner& in
+) -> std::pair<std::unique_ptr<PolyRing>, Processor> {
+ auto baseField = readBaseField(in);
+ const auto varCount = in.readInteger<VarIndex>();
+ auto order = readOrder(varCount, withComponent, in);
+ const bool componentsAscendingDesired = order.componentsAscendingDesired();
+ const bool schreyering = order.schreyering();
+ auto ring = make_unique<PolyRing>
+ (std::move(baseField), Monoid(std::move(order)));
+
+ Processor processor(ring->monoid(), componentsAscendingDesired, schreyering);
+
+ return std::make_pair(std::move(ring), std::move(processor));
+}
+
+void MathicIO::writeRing(
+ const PolyRing& ring,
+ const Processor& processor,
+ const bool withComponent,
+ std::ostream& out
+){
+ writeBaseField(ring.field(), out);
+ out << ' ' << ring.varCount() << '\n';
+
+ auto&& order = ring.monoid().makeOrder(
+ processor.componentsAscendingDesired(),
+ processor.schreyering()
+ );
+ writeOrder(order, withComponent, out);
+}
+
+auto MathicIO::readOrder(
+ const VarIndex varCount,
+ const bool withComponent,
+ Scanner& in
+) -> Order {
+ const bool schreyering = in.match("schreyer");
+ bool lexBaseOrder = !in.match("revlex") && in.match("lex");
+
+ const auto gradingCount = in.readInteger<VarIndex>();
+ bool componentsAscendingDesired = true;
+ auto componentCompareIndex = Order::ComponentAfterBaseOrder;
+ Gradings gradings(static_cast<size_t>(varCount) * gradingCount);
+ size_t index = 0;
+ for (VarIndex grading = 0; grading < gradingCount; ++grading) {
+ const bool com = in.match("component");
+ if (com || in.match("revcomponent")) {
+ if (!withComponent)
+ in.reportError("Cannot specify component comparison for non-modules.");
+ MATHICGB_ASSERT(Monoid::HasComponent);
+ if (componentCompareIndex != Order::ComponentAfterBaseOrder)
+ in.reportError("Component comparison must be specified at most once.");
+ componentsAscendingDesired = com;
+ componentCompareIndex = grading;
+ index += varCount;
+ } else {
+ for (VarIndex i = 0; i < varCount; ++i, ++index)
+ gradings[index] = in.readInteger<Exponent>();
+ }
+ }
+ MATHICGB_ASSERT(index == gradings.size());
+
+ const bool moreLex = in.match("_lex");
+ if (moreLex || in.match("_revlex")) {
+ lexBaseOrder = moreLex;
+ const bool moreCom = in.match("component");
+ if (moreCom || in.match("revcomponent")) {
+ if (!withComponent)
+ in.reportError("Cannot specify component comparison for non-modules.");
+ MATHICGB_ASSERT(Monoid::HasComponent);
+ componentsAscendingDesired = moreCom;
+ }
+ }
+
+ Order order(
+ varCount,
+ std::move(gradings),
+ lexBaseOrder ? Order::LexBaseOrder : Order::RevLexBaseOrder,
+ componentCompareIndex,
+ componentsAscendingDesired,
+ schreyering
+ );
+ return std::move(order);
+}
+
+void MathicIO::writeOrder(
+ const Order& order,
+ const bool withComponent,
+ std::ostream& out
+) {
+ MATHICGB_ASSERT(Monoid::HasComponent || !withComponent);
+
+ const auto baseOrder =
+ order.baseOrder() == Order::LexBaseOrder ? "lex" : "revlex";
+ const auto componentOrder =
+ order.componentsAscendingDesired() ? "component" : "revcomponent";
+
+ if (order.schreyering())
+ out << "schreyer ";
+ out << baseOrder << ' ' << order.gradingCount() << '\n';
+ for (VarIndex grading = 0; grading < order.gradingCount(); ++grading) {
+ if (withComponent && grading == order.componentGradingIndex())
+ out << ' ' << componentOrder;
+ else {
+ for (VarIndex var = 0; var < order.varCount(); ++var) {
+ const auto index = var + grading * order.varCount();
+ out << ' ' << unchar(order.gradings()[index]);
+ }
+ }
+ out << '\n';
+ }
+ if (
+ withComponent &&
+ !order.componentsAscendingDesired() &&
+ order.componentGradingIndex() == Order::ComponentAfterBaseOrder
+ ) {
+ out << " _" << baseOrder << "\n " << componentOrder << '\n';
+ }
+}
+
+Basis MathicIO::readBasis(
+ const PolyRing& ring,
+ const bool readComponent,
+ Scanner& in
+) {
+ const auto polyCount = in.readInteger<size_t>();
+ Basis basis(ring);
+ for (size_t i = 0; i < polyCount; ++i) {
+ auto p = make_unique<Poly>(readPoly(ring, readComponent, in));
+ p->sortTermsDescending();
+ basis.insert(std::move(p));
+ }
+ return std::move(basis);
+}
+
+void MathicIO::writeBasis(
+ const Basis& basis,
+ const bool writeComponent,
+ std::ostream& out
+) {
+ out << basis.size() << '\n';
+ for (size_t i = 0; i < basis.size(); ++i) {
+ out << ' ';
+ writePoly(*basis.getPoly(i), writeComponent, out);
+ out << '\n';
+ }
+}
+
+Poly MathicIO::readPoly(
+ const PolyRing& ring,
+ const bool readComponent,
+ Scanner& in
+) {
+ Poly p(ring);
+
+ // also skips whitespace
+ if (in.match('0') || in.match("+0") || in.match("-0"))
+ return std::move(p);
+ MATHICGB_ASSERT(!in.peekWhite());
+
+ auto mono = ring.monoid().alloc();
+ auto coef = ring.field().zero();
+ do {
+ if (!p.isZero() && !in.peekSign())
+ in.expect('+', '-');
+ readTerm(ring, readComponent, coef, mono, in);
+ p.appendTerm(coef.value(), mono);
+ } while (!in.peekWhite() && !in.matchEOF());
+ return std::move(p);
+}
+
+void MathicIO::writePoly(
+ const Poly& poly,
+ const bool writeComponent,
+ std::ostream& out
+) {
+ if (poly.isZero()) {
+ out << '0';
+ return;
+ }
+
+ const auto end = poly.end();
+ for (auto it = poly.begin(); it != end; ++it) {
+ if (it != poly.begin())
+ out << '+';
+ writeTerm(
+ poly.ring(),
+ writeComponent,
+ poly.ring().field().toElement(it.getCoefficient()),
+ it.getMonomial(),
+ out
+ );
+ }
+}
+
+void MathicIO::readTerm(
+ const PolyRing& ring,
+ const bool readComponent,
+ Coefficient& coef,
+ MonoRef mono,
+ Scanner& in
+) {
+ // ** Read coefficient, if any.
+ const auto& field = ring.field();
+ const auto& monoid = ring.monoid();
+ const bool negate = !in.match('+') && in.match('-');
+ if (in.peekDigit()) {
+ coef = in.readModular(field, negate);
+
+ if (!in.peekAlpha()) {
+ // Identify a number c on its own as the monomial 1 times c.
+ monoid.setIdentity(mono);
+ if (readComponent)
+ this->readComponent(monoid, mono, in);
+ return;
+ }
+ } else if (negate)
+ coef = field.minusOne();
+ else
+ coef = field.one();
+
+ readMonomial(monoid, readComponent, mono, in);
+}
+
+void MathicIO::writeTerm(
+ const PolyRing& ring,
+ const bool writeComponent,
+ const Coefficient coef,
+ ConstMonoRef mono,
+ std::ostream& out
+) {
+ if (!ring.field().isOne(coef)) {
+ out << unchar(coef.value());
+ if (ring.monoid().isIdentity(mono)) {
+ if (writeComponent)
+ this->writeComponent(ring.monoid(), mono, out);
+ return;
+ }
+ }
+ writeMonomial(ring.monoid(), writeComponent, mono, out);
+}
+
+void MathicIO::readMonomial(
+ const Monoid& monoid,
+ const bool readComponent,
+ MonoRef mono,
+ Scanner& in
+) {
+ MATHICGB_ASSERT(!readComponent || Monoid::HasComponent);
+
+ monoid.setIdentity(mono);
+ if (in.peek() == '1') {
+ const auto e = in.readInteger<Exponent>();
+ if (e != 1) {
+ std::ostringstream err;
+ err << "Expected monomial, but got " << e << " (did you mean 1?).";
+ in.reportError(err.str());
+ }
+ } else {
+ bool sawSome = false;
+ while (true) {
+ const auto letterCount = 'z' - 'a' + 1;
+ const auto letter = in.peek();
+
+ VarIndex var;
+ if ('a' <= letter && letter <= 'z')
+ var = letter - 'a';
+ else if ('A' <= letter && letter <= 'Z')
+ var = (letter - 'A') + letterCount;
+ else if (sawSome)
+ break;
+ else {
+ std::ostringstream err;
+ err << "Expected letter while reading monomial, but got '"
+ << static_cast<char>(letter) << "'.";
+ in.reportError(err.str());
+ return;
+ }
+ in.get(); // skip past letter
+
+ MATHICGB_ASSERT(var < 2 * letterCount);
+ if (var >= monoid.varCount()) {
+ std::ostringstream err;
+ err << "Saw the variable " << static_cast<char>(letter)
+ << ", but the monoid only has "
+ << monoid.varCount() << " variables.";
+ in.reportError(err.str());
+ return;
+ }
+ if (monoid.exponent(mono, var) > static_cast<Exponent>(0)) {
+ std::ostringstream err;
+ err << "Variable " << static_cast<char>(letter) <<
+ " must not be written twice in one monomial.";
+ in.reportError(err.str());
+ }
+
+ if (in.peekDigit())
+ monoid.setExponent(var, in.readInteger<Exponent>(), mono);
+ else
+ monoid.setExponent(var, static_cast<Exponent>(1), mono);
+ sawSome = true;
+ }
+ }
+
+ if (readComponent)
+ this->readComponent(monoid, mono, in);
+}
+
+void MathicIO::readComponent(
+ const Monoid& monoid,
+ MonoRef mono,
+ Scanner& in
+) {
+ MATHICGB_ASSERT(Monoid::HasComponent);
+ in.expect('<');
+ monoid.setComponent(in.readInteger<Exponent>(), mono);
+ in.expect('>');
+}
+
+void MathicIO::writeComponent(
+ const Monoid& monoid,
+ ConstMonoRef mono,
+ std::ostream& out
+) {
+ MATHICGB_ASSERT(Monoid::HasComponent);
+ out << '<' << unchar(monoid.component(mono)) << '>';
+}
+
+/// Print a monomial with no coefficient.
+void MathicIO::writeMonomial(
+ const Monoid& monoid,
+ const bool writeComponent,
+ ConstMonoRef mono,
+ std::ostream& out
+) {
+ const auto letterCount = 'z' - 'a' + 1;
+
+ bool printedSome = false;
+ for (VarIndex var = 0; var < monoid.varCount(); ++var) {
+ if (monoid.exponent(mono, var) == 0)
+ continue;
+ char letter;
+ if (var < letterCount)
+ letter = 'a' + static_cast<char>(var);
+ else if (var < 2 * letterCount)
+ letter = 'A' + (static_cast<char>(var) - letterCount);
+ else {
+ mathic::reportError("Too few letters in alphabet to print variable.");
+ return;
+ }
+ printedSome = true;
+ out << letter;
+ if (monoid.exponent(mono, var) != 1)
+ out << unchar(monoid.exponent(mono, var));
+ }
+ if (!printedSome)
+ out << '1';
+ if (writeComponent)
+ this->writeComponent(monoid, mono, out);
+}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/MathicIO.hpp b/src/mathicgb/MathicIO.hpp
index 6352ec3..9a3a75b 100755
--- a/src/mathicgb/MathicIO.hpp
+++ b/src/mathicgb/MathicIO.hpp
@@ -1,141 +1,146 @@
-#ifndef MATHICGB_MATHIC_IO_GUARD
-#define MATHICGB_MATHIC_IO_GUARD
-
-#include "Basis.hpp"
-#include "Poly.hpp"
-#include "Scanner.hpp"
-#include "PolyRing.hpp"
-#include "MonoProcessor.hpp"
-#include <ostream>
-#include <string>
-
-/// Class for input and output in Mathic's format.
-class MathicIO {
-public:
- typedef PolyRing::Field BaseField;
- typedef BaseField::Element Coefficient;
- typedef BaseField::RawElement RawCoefficient;
-
- typedef PolyRing::Monoid Monoid;
- typedef Monoid::MonoRef MonoRef;
- typedef Monoid::Exponent Exponent;
- typedef Monoid::VarIndex VarIndex;
- typedef Monoid::ConstMonoRef ConstMonoRef;
- typedef Monoid::Order Order;
- typedef MonoProcessor<Monoid> Processor;
-
- typedef Order::Gradings Gradings;
-
-/*
- /// reads ring, #gens, each generator in turn
- typedef std::tuple<
- std::unique_ptr<PolyRing>,
- std::unique_ptr<Basis>,
- std::unique_ptr<MonoProcessor<PolyRing::Monoid>>
- > BasisData;
- BasisData readBasis();
-
-
-
-*/
- BaseField readBaseField(Scanner& in);
- void writeBaseField(const BaseField& field, std::ostream& out);
-
- std::pair<std::unique_ptr<PolyRing>, Processor> readRing(
- const bool withComponent,
- Scanner& in
- );
- void writeRing(
- const PolyRing& ring,
- const Processor& processor,
- const bool withComponent,
- std::ostream& out
- );
-
- Order readOrder(
- const VarIndex varCount,
- const bool withComponent,
- Scanner& in
- );
-
- void writeOrder(
- const Order& order,
- const bool withComponent,
- std::ostream& out
- );
-
- Basis readBasis(
- const PolyRing& ring,
- const bool readComponent,
- Scanner& in
- );
-
- void writeBasis(
- const Basis& basis,
- const bool writeComponent,
- std::ostream& out
- );
-
- Poly readPoly(
- const PolyRing& ring,
- const bool readComponent,
- Scanner& in
- );
-
- void writePoly(
- const Poly& poly,
- const bool writeComponent,
- std::ostream& out
- );
-
- void readTerm(
- const PolyRing& ring,
- const bool readComponent,
- Coefficient& coef,
- MonoRef mono,
- Scanner& in
- );
-
- void writeTerm(
- const PolyRing& ring,
- const bool writeComponent,
- const Coefficient coef,
- ConstMonoRef mono,
- std::ostream& out
- );
-
- /// Read a monomial with no coefficient. A 1 on its own is not
- /// considered a coefficient here - it is the monomial with all
- /// exponents zero and no coefficient.
- ///
- /// @todo: Eventually, pick up readComponent from Monoid::HasComponent.
- void readMonomial(
- const Monoid& monoid,
- const bool readComponent,
- MonoRef mono,
- Scanner& in
- );
-
- /// Print a monomial with no coefficient.
- void writeMonomial(
- const Monoid& monoid,
- const bool writeComponent,
- ConstMonoRef mono,
- std::ostream& out
- );
-
- /// Read the trailing indicator of the component of a module monomial.
- void readComponent(
- const Monoid& monoid,
- MonoRef mono,
- Scanner& in
- );
-
- void writeComponent(
- const Monoid& monoid,
- ConstMonoRef mono,
- std::ostream& out
- );
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_MATHIC_IO_GUARD
+#define MATHICGB_MATHIC_IO_GUARD
+
+#include "Basis.hpp"
+#include "Poly.hpp"
+#include "Scanner.hpp"
+#include "PolyRing.hpp"
+#include "MonoProcessor.hpp"
+#include <ostream>
+#include <string>
+
+MATHICGB_NAMESPACE_BEGIN
+
+/// Class for input and output in Mathic's format.
+class MathicIO {
+public:
+ typedef PolyRing::Field BaseField;
+ typedef BaseField::Element Coefficient;
+ typedef BaseField::RawElement RawCoefficient;
+
+ typedef PolyRing::Monoid Monoid;
+ typedef Monoid::MonoRef MonoRef;
+ typedef Monoid::Exponent Exponent;
+ typedef Monoid::VarIndex VarIndex;
+ typedef Monoid::ConstMonoRef ConstMonoRef;
+ typedef Monoid::Order Order;
+ typedef MonoProcessor<Monoid> Processor;
+
+ typedef Order::Gradings Gradings;
+
+/*
+ /// reads ring, #gens, each generator in turn
+ typedef std::tuple<
+ std::unique_ptr<PolyRing>,
+ std::unique_ptr<Basis>,
+ std::unique_ptr<MonoProcessor<PolyRing::Monoid>>
+ > BasisData;
+ BasisData readBasis();
+
+
+
+*/
+ BaseField readBaseField(Scanner& in);
+ void writeBaseField(const BaseField& field, std::ostream& out);
+
+ std::pair<std::unique_ptr<PolyRing>, Processor> readRing(
+ const bool withComponent,
+ Scanner& in
+ );
+ void writeRing(
+ const PolyRing& ring,
+ const Processor& processor,
+ const bool withComponent,
+ std::ostream& out
+ );
+
+ Order readOrder(
+ const VarIndex varCount,
+ const bool withComponent,
+ Scanner& in
+ );
+
+ void writeOrder(
+ const Order& order,
+ const bool withComponent,
+ std::ostream& out
+ );
+
+ Basis readBasis(
+ const PolyRing& ring,
+ const bool readComponent,
+ Scanner& in
+ );
+
+ void writeBasis(
+ const Basis& basis,
+ const bool writeComponent,
+ std::ostream& out
+ );
+
+ Poly readPoly(
+ const PolyRing& ring,
+ const bool readComponent,
+ Scanner& in
+ );
+
+ void writePoly(
+ const Poly& poly,
+ const bool writeComponent,
+ std::ostream& out
+ );
+
+ void readTerm(
+ const PolyRing& ring,
+ const bool readComponent,
+ Coefficient& coef,
+ MonoRef mono,
+ Scanner& in
+ );
+
+ void writeTerm(
+ const PolyRing& ring,
+ const bool writeComponent,
+ const Coefficient coef,
+ ConstMonoRef mono,
+ std::ostream& out
+ );
+
+ /// Read a monomial with no coefficient. A 1 on its own is not
+ /// considered a coefficient here - it is the monomial with all
+ /// exponents zero and no coefficient.
+ ///
+ /// @todo: Eventually, pick up readComponent from Monoid::HasComponent.
+ void readMonomial(
+ const Monoid& monoid,
+ const bool readComponent,
+ MonoRef mono,
+ Scanner& in
+ );
+
+ /// Print a monomial with no coefficient.
+ void writeMonomial(
+ const Monoid& monoid,
+ const bool writeComponent,
+ ConstMonoRef mono,
+ std::ostream& out
+ );
+
+ /// Read the trailing indicator of the component of a module monomial.
+ void readComponent(
+ const Monoid& monoid,
+ MonoRef mono,
+ Scanner& in
+ );
+
+ void writeComponent(
+ const Monoid& monoid,
+ ConstMonoRef mono,
+ std::ostream& out
+ );
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/MonTableDivList.hpp b/src/mathicgb/MonTableDivList.hpp
old mode 100644
new mode 100755
index 5e94d5c..d8e4220
--- a/src/mathicgb/MonTableDivList.hpp
+++ b/src/mathicgb/MonTableDivList.hpp
@@ -1,12 +1,15 @@
-#ifndef DIV_ARRAY_MODEL_GUARD
-#define DIV_ARRAY_MODEL_GUARD
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_MON_TABLE_DIV_LIST_GUARD
+#define MATHICGB_MON_TABLE_DIV_LIST_GUARD
+#include "PolyRing.hpp"
#include <string>
#include <vector>
#include <iostream>
-
#include <mathic.h>
-#include "PolyRing.hpp"
+
+MATHICGB_NAMESPACE_BEGIN
/** Helper class for MonTableDivList. */
template<bool UseLinkedList, bool UseDivMask>
@@ -279,9 +282,5 @@ void MonTableDivList<UDL, UDM>::getMonomials(std::vector<const_monomial>& monomi
monomials.insert(monomials.begin(), begin(), end());
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/MonTableKDTree.hpp b/src/mathicgb/MonTableKDTree.hpp
index ddc8372..32da9da 100755
--- a/src/mathicgb/MonTableKDTree.hpp
+++ b/src/mathicgb/MonTableKDTree.hpp
@@ -1,13 +1,16 @@
-#ifndef K_D_TREE_MODEL_GUARD
-#define K_D_TREE_MODEL_GUARD
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_MON_TABLE_K_D_TREE_GUARD
+#define MATHICGB_MON_TABLE_K_D_TREE_GUARD
+#include "PolyRing.hpp"
#include <string>
#include <vector>
#include <iostream>
#include <memtailor.h>
#include <mathic.h>
-#include "PolyRing.hpp"
+MATHICGB_NAMESPACE_BEGIN
/** Helper class for KDTreeModel. */
template<bool UseDivMask, bool UseTreeDivMask, size_t LeafSize, bool AllowRemovals>
@@ -284,9 +287,5 @@ void MonTableKDTree<UDM, UTM, LS, AR>::getMonomials(std::vector<const_monomial>&
_finder.forAll(copier);
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/MonTableNaive.cpp b/src/mathicgb/MonTableNaive.cpp
old mode 100644
new mode 100755
index 3543ec1..35a90dd
--- a/src/mathicgb/MonTableNaive.cpp
+++ b/src/mathicgb/MonTableNaive.cpp
@@ -1,10 +1,13 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
-#include <ostream>
#include "MonTableNaive.hpp"
+
+#include <ostream>
#include <iostream>
+MATHICGB_NAMESPACE_BEGIN
+
MonTableNaive::MonTableNaive(const PolyRing *R) :
conf_(R),
mPool(sizeof(mon_node)),
@@ -163,7 +166,4 @@ size_t MonTableNaive::getMemoryUse() const
return mPool.getMemoryUse();
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/MonTableNaive.hpp b/src/mathicgb/MonTableNaive.hpp
old mode 100644
new mode 100755
index 4d135a5..f570401
--- a/src/mathicgb/MonTableNaive.hpp
+++ b/src/mathicgb/MonTableNaive.hpp
@@ -1,10 +1,12 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_MON_TABLE_NAIVE_GUARD
+#define MATHICGB_MON_TABLE_NAIVE_GUARD
-#ifndef _monomial_table_h_
-#define _monomial_table_h_
-
-#include <memtailor.h>
#include "PolyRing.hpp"
+#include <memtailor.h>
+
+MATHICGB_NAMESPACE_BEGIN
struct mon_node { // each node is in 'nodes' arena
mon_node *next;
@@ -75,10 +77,5 @@ private:
mutable Stats stats_;
};
-
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/MonoMonoid.hpp b/src/mathicgb/MonoMonoid.hpp
index c81b60a..a94ed25 100755
--- a/src/mathicgb/MonoMonoid.hpp
+++ b/src/mathicgb/MonoMonoid.hpp
@@ -1,2009 +1,2014 @@
-#ifndef MATHICGB_MONO_MONOID_GUARD
-#define MATHICGB_MONO_MONOID_GUARD
-
-#include "MonoOrder.hpp"
-#include "NonCopyable.hpp"
-#include <vector>
-#include <algorithm>
-#include <memtailor.h>
-#include <type_traits>
-#include <istream>
-#include <utility>
-#include <ostream>
-#include <cstdlib>
-#include <cstring>
-#include <mathic.h>
-
-/// Implements the monoid of (monic) monomials with integer
-/// non-negative exponents. Exponent must be an unsigned integer type that is
-/// used to store each exponent of a monomial.
-template<
- class Exponent,
- bool HasComponent = true,
- bool StoreHash = true,
- bool StoreOrder = true
->
-class MonoMonoid;
-
-namespace MonoMonoidInternal {
- template<class E, bool HC, bool SH, bool SO>
- class Base {
- public:
- static const bool HasComponent = HC;
- static const bool StoreHash = SH;
- static const bool StoreOrder = SO;
-
- typedef size_t VarIndex;
- typedef E Exponent;
- typedef typename std::make_unsigned<E>::type Component;
- typedef typename std::make_unsigned<E>::type HashValue;
- typedef const Exponent* const_iterator;
- typedef MonoOrder<Exponent> Order;
-
- Base(const Order& order):
- mVarCount(order.varCount()),
- mGradingCount(order.gradingCount()),
- mOrderIndexBegin(HasComponent + order.varCount()),
- mOrderIndexEnd(mOrderIndexBegin + StoreOrder * order.gradingCount()),
- mEntryCount(std::max<VarIndex>(mOrderIndexEnd + StoreHash, 1)),
- mHashCoefficients(makeHashCoefficients(order.varCount())),
- mOrderIsTotalDegreeRevLex
- (order.baseOrder() == Order::RevLexBaseOrder && order.isTotalDegree()),
- mLexBaseOrder(order.baseOrder() == Order::LexBaseOrder),
- mGradings(makeGradings(order)),
- mComponentGradingIndex(
- reverseComponentGradingIndex
- (order.gradingCount(), order.componentGradingIndex())
- )
- {
- }
-
- VarIndex varCount() const {return mVarCount;}
- VarIndex gradingCount() const {return mGradingCount;}
-
- VarIndex entryCount() const {return mEntryCount;}
- VarIndex orderIndexEnd() const {return mOrderIndexEnd;}
- VarIndex orderIndexBegin() const {return mOrderIndexBegin;}
- VarIndex hashIndex() const {return mOrderIndexEnd;}
- VarIndex componentGradingIndex() const {return mComponentGradingIndex;}
-
- protected:
- typedef std::vector<Exponent> HashCoefficients;
- typedef std::vector<Exponent> Gradings;
-
- static Gradings makeGradings(const Order& order) {
- auto gradings = order.gradings();
- reverseGradings(order.varCount(), gradings);
- if (order.baseOrder() == Order::RevLexBaseOrder)
- negateGradings(gradings);
- return gradings;
- }
-
- /// Reverse the relative order among the gradings - the first one
- /// becomes the last one, the second first becomes the second last
- /// and so on.
- static void reverseGradings(const VarIndex varCount, Gradings& gradings) {
- if (varCount == 0)
- return;
- MATHICGB_ASSERT(gradings.size() % varCount == 0);
- const auto gradingCount = gradings.size() / varCount;
-
- for (VarIndex grading = 0; grading < gradingCount / 2; ++grading) {
- for (VarIndex var = 0; var < varCount; ++var) {
- const auto index = gradingsIndex(grading, var, varCount);
- const auto oppositeIndex = gradingsOppositeRowIndex
- (grading, gradingCount, var, varCount);
- std::swap(gradings[index], gradings[oppositeIndex]);
- }
- }
- }
-
- /// Replace each entry in the grading matrix with its negative.
- static void negateGradings(Gradings& gradings) {
- const auto size = gradings.size();
- for (size_t i = 0; i < size; ++i)
- gradings[i] = -gradings[i];
- }
-
- /// Since comparisons go opposite direction, we need to reverse
- /// the component grading index, unless it's the special value
- /// indicating that it goes last.
- static VarIndex reverseComponentGradingIndex(
- const VarIndex gradingCount,
- const VarIndex componentGradingIndex
- ) {
- if (componentGradingIndex == Order::ComponentAfterBaseOrder)
- return Order::ComponentAfterBaseOrder;
- else
- return gradingCount - 1 - componentGradingIndex;
- }
-
- const HashCoefficients& hashCoefficients() const {return mHashCoefficients;}
- bool orderIsTotalDegreeRevLex() const {return mOrderIsTotalDegreeRevLex;}
- Gradings& gradings() {return mGradings;} // todo: remove this overload
- const Gradings& gradings() const {return mGradings;}
- bool isLexBaseOrder() const {return mLexBaseOrder;}
-
- static size_t gradingsIndex(
- const VarIndex grading,
- const VarIndex var,
- const VarIndex varCount
- ) {
- MATHICGB_ASSERT(var < varCount);
- return grading * static_cast<size_t>(varCount) + var;
- }
-
- size_t gradingsIndex(const VarIndex grading, const VarIndex var) const {
- MATHICGB_ASSERT(grading < gradingCount());
- MATHICGB_ASSERT(var < varCount());
- const auto index = gradingsIndex(grading, var, varCount());
- MATHICGB_ASSERT(index < gradings().size());
- return index;
- }
-
- static size_t gradingsOppositeRowIndex(
- const VarIndex grading,
- const VarIndex gradingCount,
- const VarIndex var,
- const VarIndex varCount
- ) {
- MATHICGB_ASSERT(grading < gradingCount);
- MATHICGB_ASSERT(var < varCount);
- return gradingsIndex(gradingCount - 1 - grading, var, varCount);
- }
-
- size_t gradingsOppositeRowIndex(
- const VarIndex grading,
- const VarIndex var
- ) const {
- MATHICGB_ASSERT(grading < gradingCount());
- MATHICGB_ASSERT(var < varCount());
- const auto index =
- gradingsOppositeRowIndex(grading, gradingCount(), var, varCount());
- MATHICGB_ASSERT(index < gradings().size());
- return index;
- }
-
- private:
- HashCoefficients static makeHashCoefficients(const VarIndex varCount) {
- std::srand(0); // To use the same hash coefficients every time.
- HashCoefficients coeffs(varCount);
- for (VarIndex var = 0; var < varCount; ++var)
- coeffs[var] = static_cast<HashValue>(std::rand());
- return coeffs;
- }
-
- const VarIndex mVarCount;
- const VarIndex mGradingCount;
- const VarIndex mOrderIndexBegin;
- const VarIndex mOrderIndexEnd;
- const VarIndex mEntryCount;
- const VarIndex mComponentGradingIndex;
-
- /// Take dot product of exponents with this vector to get hash value.
- const HashCoefficients mHashCoefficients;
-
- /// This is initialized before mGradings, so it has to be ordered
- /// above mGradings.
- const bool mOrderIsTotalDegreeRevLex;
-
- /// If true then lex is used to break ties. Otherwise, revlex is
- /// used. This applies as well to degrees, which implies that
- /// degrees have to be stored negated if doing revlex.
- const bool mLexBaseOrder;
-
- /// Defines a matrix where each row is a grading. The degree of a
- /// monomial with respect to grading g is the dot product of the
- /// exponent vector of that monomial with row g of the matrix
- /// (starting at g=0). The matrix is stored in row-major order. If
- /// mOrderIsTotalDegreeRevLex is true then mGradings is empty but
- /// implicitly it is a single grading consisting of all 1s and the
- /// base order is revlex.
- std::vector<Exponent> mGradings;
- };
-}
-
-template<class E, bool HC, bool SH, bool SO>
-class MonoMonoid : private MonoMonoidInternal::Base<E, HC, SH, SO> {
-private:
- typedef MonoMonoidInternal::Base<E, HC, SH, SO> Base;
-
-public:
- static_assert(std::numeric_limits<E>::is_signed, "");
-
- // *** Types
-
- // Integer index representing a variable. Indices start at 0 and go
- // up to varCount() - 1 where varCount() is the number of variables.
- typedef typename Base::VarIndex VarIndex;
-
- /// The type of each exponent of a monomial.
- typedef typename Base::Exponent Exponent;
-
- /// Is true if the monomials come from a module.
- using Base::HasComponent;
-
- /// Is true if the hash value is stored rather than computed at each
- /// hash request. This imposes extra computation when updating a monomial,
- /// but for most operations that overhead is much less than the time for
- /// computing a hash value from scratch.
- using Base::StoreHash;
-
- /// Is true if data to compare monomials is stored rather than computed
- /// at each comparison. As storeHash, there is overhead for this, but it
- /// is not much for most operations.
- using Base::StoreOrder;
-
- /// Type used to indicate the component of a module monomial. For example,
- /// the component of xe_3 is 3.
- typedef typename Base::Component Component;
-
- /// Type used to store hash values of monomials.
- typedef typename Base::HashValue HashValue;
-
- /// Iterator for the exponents in a monomial.
- typedef typename Base::const_iterator const_iterator;
-
- /// Represents a monomial and manages the memory underlying it. To
- /// refer to a non-owned monomial or to refer to a Mono, use MonoRef
- /// or ConstMonoRef. Do not use Mono& or Mono* if you do not have
- /// to, since that implies a double indirection when accessing the
- /// monomial.
- class Mono;
-
- /// A reference to a non-const monomial. Cannot be null, cannot be
- /// reassigned to refer to a different monomial and does not connote
- /// ownership - the same semantics as C++ references.
- class MonoRef;
-
- /// A reference to a monomial. As MonoRef, but you cannot change the
- /// monomial through this reference. Prefer this class over the
- /// other reference/pointer classes unless there is a reason not to.
- class ConstMonoRef;
-
- /// A pointer to a non-const monomial. Can be null and can be
- /// reassigned to refer to a different monomial - the same semantics
- /// as C++ pointers. Does not connote ownership.
- class MonoPtr;
-
- /// A pointer to a monomial. As MonoPtr, but you cannot change the
- /// monomial through this pointer.
- class ConstMonoPtr;
-
- /// A pool of memory for monomials.
- ///
- /// @todo: This approach is a poor fit for variable-sized
- /// monomials. So prefer other solutions where reasonable.
- class MonoPool;
-
- /// A vector of monomials. The interface is a subset of
- /// std::vector. Monomials can be appended (push_back). Only the
- /// last monomial can be mutated and monomials cannot be reordered
- /// or removed. These restrictions should make it easier to support
- /// variable-sized monomials in future. Change it if you need to
- /// break these restrictions, but first try to find an alternative.
- class MonoVector;
-
- /// For indicating the result of comparing one monomial to another.
- enum CompareResult {
- LessThan = -1,
- EqualTo = 0,
- GreaterThan = 1
- };
-
- /// Used to describe a monomial order when constructing a monoid.
- typedef typename Base::Order Order;
-
- // *** Temporary compatibility code for migrating off PolyRing
- friend class PolyRing;
- friend class Poly;
- static MonoRef toRef(Exponent* e) {return MonoRef(e);}
- static ConstMonoRef toRef(const Exponent* e) {return ConstMonoRef(e);}
- static Exponent* toOld(MonoRef e) {return rawPtr(e);}
- static const Exponent* toOld(ConstMonoRef e) {return rawPtr(e);}
-
-
- // *** Constructors and accessors
-
- MonoMonoid(MonoMonoid&& monoid): Base(std::move(monoid)), mPool(*this) {
- MATHICGB_ASSERT(debugAssertValid());
- }
-
- MonoMonoid(const MonoMonoid& monoid): Base(monoid), mPool(*this) {
- MATHICGB_ASSERT(debugAssertValid());
- }
-
- MonoMonoid(const Order& order): Base(order), mPool(*this) {
- MATHICGB_ASSERT(debugAssertValid());
- }
-
- /// Creates a compatible copy of monoid.
- template<class E2, bool HC2, bool SH2, bool SO2>
- static MonoMonoid create(const MonoMonoid<E2, HC2, SH2, SO2>& monoid) {
- return MonoMonoid(monoid.makeOrder(false, false));
- }
-
- /// The second.first value of the return pair indicates whether it
- /// is desired that i>j => e_i > e_j. the second.second value
- /// indicates whether to do a Schreyer order. TODO: clearly this is
- /// a mess that needs to be cleaned up. Step 1 is to move IO out of
- /// MonoMonoid entirely.
- static std::pair<MonoMonoid, std::pair<bool, bool>> readMonoid(std::istream& in);
- void printMonoid
- (const bool componentsAscendingDesired, std::ostream& out) const;
-
- /// Returns an Order object that is equivalent to the order that
- /// this monoid was constructed with. The settings not handled by
- /// the monoid, and therefore not known by the monoid, are passed in
- /// as parameters. The purpose of that is to make it clear that this
- /// information must be supplied separately.
- Order makeOrder(
- const bool componentsAscendingDesired,
- const bool schreyering
- ) const {
- std::vector<Exponent> orderGradings(gradings());
- reverseGradings(varCount(), orderGradings);
- if (!isLexBaseOrder())
- negateGradings(orderGradings);
- return Order(
- varCount(),
- std::move(orderGradings),
- isLexBaseOrder() ? Order::LexBaseOrder : Order::RevLexBaseOrder,
- Base::reverseComponentGradingIndex
- (gradingCount(), componentGradingIndex()),
- componentsAscendingDesired,
- schreyering
- );
- }
-
- bool operator==(const MonoMonoid& monoid) const {
- return this == &monoid;
- }
-
- bool operator!=(const MonoMonoid& monoid) const {
- return !(*this == monoid);
- }
-
- /// Returns true if higher component is considered greater when
- /// comparing module monomials. Only relevant once actually
- /// considering the component. This is only relevant for module
- /// monomials.
- bool componentsAscending() const {return isLexBaseOrder();}
-
- /// Returns the number of variables. This is also the number of
- /// exponents in the exponent vector of a monomial.
- using Base::varCount;
- //VarIndex varCount() const {return mVarCount;}
-
-
- // *** Monomial accessors and queries
-
- /// Returns iterator to the first exponent.
- const_iterator begin(ConstMonoRef mono) const {
- return ptr(mono, exponentsIndexBegin());
- }
-
- /// Returns iterator to one-past-the-end of the range of exponents.
- const_iterator end(ConstMonoRef mono) const {
- return ptr(mono, exponentsIndexEnd());
- }
-
- /// Returns the exponent of var in mono.
- Exponent exponent(ConstMonoRef mono, const VarIndex var) const {
- MATHICGB_ASSERT(var < varCount());
- return access(mono, exponentsIndexBegin() + 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 {
- MATHICGB_ASSERT(HasComponent);
- return access(mono, componentIndex());
- }
-
- /// Returns a hash value for the monomial. These are not guaranteed
- /// to be unique.
- HashValue hash(ConstMonoRef mono) const {
- MATHICGB_ASSERT(debugHashValid(mono));
- if (StoreHash)
- return static_cast<HashValue>(access(mono, hashIndex()));
- else
- return computeHash(mono);
- }
-
- /// Returns true if a and b are equal. Includes check for component.
- bool equal(ConstMonoRef a, ConstMonoRef b) const {
- for (auto i = entriesIndexBegin(); i != exponentsIndexEnd(); ++i)
- if (access(a, i) != access(b, i))
- return false;
- return true;
- }
-
- template<class MonoidA>
- bool equal(
- const MonoidA& monoidA,
- typename MonoidA::ConstMonoRef a,
- ConstMonoRef b
- ) const {
- // todo: assert compatible
- for (VarIndex var = 0; var < varCount(); ++var)
- if (monoidA.exponent(a, var) != exponent(b, var))
- return false;
- return true;
- }
-
- /// As equal(), but optimized for the case where true is returned.
- bool equalHintTrue(ConstMonoRef a, ConstMonoRef b) const {
- // if a[i] != b[i] then a[i] ^ b[i] != 0, so the or of all xors is zero
- // if and only if a equals b. This way we avoid having a branch to check
- // equality for every iteration of the loop, which is a win in the case
- // that none of the early-exit branches are taken - that is, when a equals
- // b.
- Exponent orOfXor = 0;
- for (VarIndex i = lastExponentIndex(); i != beforeEntriesIndexBegin(); --i)
- orOfXor |= access(a, i) ^ access(b, i);
- MATHICGB_ASSERT((orOfXor == 0) == equal(a, b));
- return orOfXor == 0;
- }
-
- bool isProductOf(
- ConstMonoRef a,
- ConstMonoRef b,
- ConstMonoRef ab
- ) const {
- for (VarIndex i = entriesIndexBegin(); i != exponentsIndexEnd(); ++i)
- if (access(ab, i) != access(a, i) + access(b, i))
- return false;
- return true;
- }
-
- bool isProductOfHintTrue(
- ConstMonoRef a,
- ConstMonoRef b,
- ConstMonoRef ab
- ) const {
- // We compare more than one exponent at a time using 64 bit integers. This
- // might go one 32 bit value at the end too far, but since that space is
- // either a degree or a hash value that is fine --- those values will also
- // match if the monomials are equal. This does not work for negative
- // exponents since the overflowing bit will go into the next word.
- // It is OK that the degree field can be negative (a field we might go
- // into without caring about it because it shares a 64 bit field with
- // the last exponent), because it is at the end so the overflowing
- // bit will not interfere. For this reason we need to have a degree
- // or a hash value stored there - otherwise two equal monomials could
- // have different things stored next to them which would confuse this code.
-
- // todo: ensure 8 byte alignment. Though there seem to be no ill effects
- // for unaligned access. Performance seems to be no worse than for using
- // 32 bit integers directly.
-
- if (sizeof(Exponent) != 4 || (!StoreHash && !StoreOrder))
- return isProductOf(a, b, ab);
-
- uint64 orOfXor = 0;
- for (VarIndex i = varCount() / 2; i != beforeEntriesIndexBegin(); --i) {
- MATHICGB_ASSERT(access(a, i*2) >= 0);
- MATHICGB_ASSERT(i == varCount() / 2 || access(a, i*2+1) >= 0);
-
- uint64 A, B, AB;
- // We have to use std::memcpy here because just casting to a int64 breaks
- // the strict aliasing rule which implies undefined behavior. Both MSVC and
- // gcc don't actually call memcpy here. MSVC is a tiny bit slower for this
- // code than for casting while GCC seems to be exactly the same speed.
- std::memcpy(&A, ptr(a, i*2), 8);
- std::memcpy(&B, ptr(b, i*2), 8);
- std::memcpy(&AB, ptr(ab, i*2), 8);
- orOfXor |= AB ^ (A + B);
- }
- MATHICGB_ASSERT((orOfXor == 0) == isProductOf(a, b, ab));
- return orOfXor == 0;
- }
-
- MATHICGB_INLINE bool isTwoProductsOfHintTrue(
- ConstMonoRef a1,
- ConstMonoRef a2,
- ConstMonoRef b,
- ConstMonoRef a1b,
- ConstMonoRef a2b
- ) const {
- if (sizeof(Exponent) != 4 || (!StoreHash && !StoreOrder))
- return (isProductOf(a1, b, a1b) && isProductOf(a2, b, a2b));
-
- uint64 orOfXor = 0;
- for (VarIndex i = varCount() / 2; i != beforeEntriesIndexBegin(); --i) {
- uint64 A1, A2, B, A1B, A2B;
- std::memcpy(&A1, ptr(a1, i*2), 8);
- std::memcpy(&A2, ptr(a2, i*2), 8);
- std::memcpy(&B, ptr(b, i*2), 8);
- std::memcpy(&A1B, ptr(a1b, i*2), 8);
- std::memcpy(&A2B, ptr(a2b, i*2), 8);
- orOfXor |= (A1B ^ (A1 + B)) | (A2B ^ (A2 + B));
- }
- MATHICGB_ASSERT
- ((orOfXor == 0) == (isProductOf(a1, b, a1b) && isProductOf(a2, b, a2b)));
- return orOfXor == 0;
- }
-
- /// 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));
- }
-
- /// Returns true if all the exponents of mono are zero. In other
- /// words, returns true if mono is the identity for multiplication
- /// of monomials.
- bool isIdentity(ConstMonoRef mono) const {
- return std::all_of(begin(mono), end(mono), [](Exponent e) {return e == 0;});
- }
-
- /// Returns true if a divides b. Equal monomials divide each other.
- bool divides(ConstMonoRef div, ConstMonoRef into) const {
- // todo: enable this when the code works with it
- //if (HasComponent && component(div) != component(into))
- // return false;
- for (auto i = exponentsIndexBegin(); i < exponentsIndexEnd(); ++i)
- if (access(div, i) > access(into, i))
- return false;
- return true;
- }
-
- template<class MonoidA>
- bool divides(
- const MonoidA& monoidA,
- typename MonoidA::ConstMonoRef a,
- ConstMonoRef b
- ) const {
- // todo: fix other divisibility functions to work properly for component too.
- MATHICGB_ASSERT(monoidA.varCount() == varCount());
- MATHICGB_ASSERT(!MonoidA::HasComponent || HasComponent);
- MATHICGB_ASSERT(monoidA.debugValid(a));
- MATHICGB_ASSERT(debugValid(b));
- // todo: enable this when the code works with it
- //if (HasComponent && component(div) != component(into))
- // return false;
- //if (
- // MonoidA::HasComponent &&
- // HasComponent &&
- // monoidA.component(a) != component(b)
- //)
- // return false;
- for (VarIndex var = 0; var < varCount(); ++var)
- if (monoidA.exponent(a, var) > exponent(b, var))
- return false;
- return true;
- }
-
- /// Returns true if div divides lcm(a, b).
- bool dividesLcm(ConstMonoRef div, ConstMonoRef a, ConstMonoRef b) const {
- MATHICGB_ASSERT(debugLcmCheck(*this, a, *this, b));
- MATHICGB_ASSERT(debugValid(div));
-
- for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) {
- const auto dive = access(div, i);
- if (access(div, i) > access(a, i) && access(div, i) > access(b, i))
- return false;
- }
- return true;
- }
-
- template<class MonoidDiv, class MonoidA>
- bool dividesLcm(
- const MonoidDiv& monoidDiv,
- typename MonoidDiv::ConstMonoRef div,
- const MonoidA& monoidA,
- typename MonoidA::ConstMonoRef a,
- ConstMonoRef b
- ) const {
- MATHICGB_ASSERT(monoidDiv.debugLcmCheck(monoidA, a, *this, b));
- MATHICGB_ASSERT(monoidDiv.debugValid(div));
-
- for (VarIndex var = 0; var < varCount(); ++var) {
- const auto e = monoidDiv.exponent(div, var);
- if (e > monoidA.exponent(a, var) && e > exponent(b, var))
- return false;
- }
- return true;
- }
-
- /// Returns true if lcm(a,b) == lcmAB.
- bool isLcm(ConstMonoRef a, ConstMonoRef b, ConstMonoRef lcmAB) const {
- MATHICGB_ASSERT(debugLcmCheck(*this, a, *this, b));
- MATHICGB_ASSERT(debugValid(lcmAB));
-
- for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i)
- if (access(lcmAB, i) != std::max(access(a, i), access(b, i)))
- return false;
- return true;
- }
-
- template<class MonoidA, class MonoidB>
- bool isLcm(
- const MonoidA& monoidA,
- typename MonoidA::ConstMonoRef a,
- const MonoidB& monoidB,
- typename MonoidB::ConstMonoRef b,
- ConstMonoRef lcmAB
- ) const {
- MATHICGB_ASSERT(debugLcmCheck(monoidA, a, monoidB, b));
- MATHICGB_ASSERT(debugValid(lcmAB));
-
- if (HasComponent) {
- if (MonoidA::HasComponent) {
- if (monoidA.component(a) != component(lcmAB))
- return false;
- } else {
- MATHICGB_ASSERT(MonoidB::HasComponent);
- if (monoidB.component(b) != component(lcmAB))
- return false;
- }
- }
-
- for (VarIndex var = 0; var < varCount(); ++var) {
- if (
- ptr(lcmAB, exponentsIndexBegin())[var] !=
- std::max(monoidA.exponent(a, var), monoidB.exponent(b, var))
- )
- return false;
- }
- return true;
- }
-
- CompareResult compare(ConstMonoRef a, ConstMonoRef b) const {
- MATHICGB_ASSERT(debugOrderValid(a));
- MATHICGB_ASSERT(debugOrderValid(b));
-
- VarIndex index;
-
- if (StoreOrder)
- index = orderIndexEnd();
- else {
- // Check the degrees seperately since they are not stored.
- auto grading = gradingCount();
- while (grading != 0) {
- --grading;
- const auto cmp = degree(a, grading) - degree(b, grading);
- if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan;
- if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan;
- }
- index = exponentsIndexEnd();
- }
-
- // If StoreOrder is true then this first checks the degrees.
- // Then the exponents are checked.
- // Finally, if HasComponent is true, the component is checked.
- while (index != entriesIndexBegin()) {
- --index;
- const auto cmp = access(a, index) - access(b, index);
- if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan;
- if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan;
- }
- return EqualTo;
- }
-
- /// Compares a to b1*b2.
- /// @todo: Test this method. Also, is this method actually useful, or could
- /// it just as well be replaced by a multiplication and a comparison?
- CompareResult compare(ConstMonoRef a, ConstMonoRef b1, ConstMonoRef b2) const {
- MATHICGB_ASSERT(debugOrderValid(a));
- MATHICGB_ASSERT(debugOrderValid(b1));
- MATHICGB_ASSERT(debugOrderValid(b2));
-
- VarIndex index;
-
- if (StoreOrder)
- index = orderIndexEnd();
- else {
- // Check the degrees seperately since they are not stored.
- auto grading = gradingCount();
- while (grading != 0) {
- --grading;
- const auto cmp =
- degree(a, grading) - (degree(b1, grading) + degree(b2, grading));
- if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan;
- if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan;
- }
- index = exponentsIndexEnd();
- }
-
- // If StoreOrder is true then this first checks the degrees.
- // Then the exponents are checked.
- // Finally, if HasComponent is true, the component is checked.
- while (index != entriesIndexBegin()) {
- --index;
- const auto cmp =
- access(a, index) - (access(b1, index) + access(b2, index));
- if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan;
- if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan;
- }
- return EqualTo;
- }
-
- bool lessThan(ConstMonoRef a, ConstMonoRef b) const {
- return compare(a, b) == LessThan;
- }
-
- /// Returns true if gcd(a, b) == 1.
- bool relativelyPrime(ConstMonoRef a, ConstMonoRef b) const {
- for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i)
- if (access(a, i) > 0 && access(b, i) > 0)
- return false;
- return true;
- }
-
- // If this method returns true for monomials a and b then it is
- // guaranteed that multiplying a and b together will not overflow
- // the integers in the representation.
- bool hasAmpleCapacity(ConstMonoRef mono) const {
- const auto halfMin = std::numeric_limits<Exponent>::min() / 2;
- const auto halfMax = std::numeric_limits<Exponent>::max() / 2;
- MATHICGB_ASSERT(halfMin <= 0);
- const auto limit = std::min(-halfMin, halfMax);
- const auto inRange = [&](Exponent value)
- {return -limit <= value && value <= limit;};
-
- for (VarIndex i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i)
- if (!inRange(access(mono, i)))
- return false;
- for (VarIndex grading = 0; grading < gradingCount(); ++grading)
- if (!inRange(degree(mono, grading)))
- return false;
- return true;
- }
-
- /// Returns the degree of mono using the most significant grading on
- /// the monoid. This is the grading with index gradingCount() -
- /// 1. This object must have at least one grading associated to it
- /// before calling this method.
- Exponent degree(ConstMonoRef mono) const {
- MATHICGB_ASSERT(gradingCount() > 0);
- return degree(mono, gradingCount() - 1);
- }
-
- /// Returns the degree of mono according to the grading with the
- /// given index.
- Exponent degree(ConstMonoRef mono, VarIndex grading) const {
- MATHICGB_ASSERT(grading < gradingCount());
- MATHICGB_ASSERT(debugOrderValid(mono));
- if (StoreOrder)
- return access(mono, orderIndexBegin() + grading);
- else
- return computeDegree(mono, grading);
- }
-
- /// Returns the number of gradings.
- using Base::gradingCount;
-
-
- // *** Monomial mutating computations
-
- /// Copes the parameter from to the parameter to.
- void copy(ConstMonoRef from, MonoRef to) const {
- MATHICGB_ASSERT(debugValid(from));
-
- std::copy_n(rawPtr(from), entryCount(), rawPtr(to));
-
- MATHICGB_ASSERT(debugValid(to));
- }
-
- template<class MonoidFrom>
- void copy(
- const MonoidFrom& monoidFrom,
- typename MonoidFrom::ConstMonoRef from,
- MonoRef to
- ) const {
- // todo: extract this in checker method
- MATHICGB_ASSERT(HasComponent == MonoidFrom::HasComponent);
- MATHICGB_ASSERT(monoidFrom.debugValid(from));
- MATHICGB_ASSERT(monoidFrom.varCount() == varCount());
- MATHICGB_ASSERT
- ((std::is_same<Exponent, typename MonoidFrom::Exponent>::value));
-
- if (HasComponent)
- access(to, componentIndex()) = monoidFrom.component(from);
- const auto expsTo = ptr(to, exponentsIndexBegin());
- for (VarIndex var = 0; var < varCount(); ++var)
- expsTo[var] = monoidFrom.exponent(from, var);
- if (StoreOrder) {
- const auto degrees = ptr(to, orderIndexBegin());
- for (VarIndex grading = 0; grading < gradingCount(); ++grading)
- degrees[grading] = monoidFrom.degree(from, grading);
- }
- if (StoreHash)
- access(to, hashIndex()) = monoidFrom.hash(from);
-
- MATHICGB_ASSERT(debugValid(to));
- // todo: check equal
- }
-
- /// Set the exponent of var to newExponent in mono.
- void setExponent(
- const VarIndex var,
- const Exponent newExponent,
- MonoRef mono
- ) const {
- MATHICGB_ASSERT(var < varCount());
-
- auto& exponent = access(mono, exponentsIndexBegin() + var);
- const auto oldExponent = exponent;
- exponent = newExponent;
-
- updateOrderData(var, oldExponent, newExponent, mono);
- updateHashExponent(var, oldExponent, newExponent, mono);
-
- MATHICGB_ASSERT(debugValid(mono));
- }
-
- /// Sets all the exponents of mono. exponents must point to an array
- /// of size varCount().
- void setExponents(const Exponent* exponents, MonoRef mono) const {
- MATHICGB_ASSERT(exponents != 0);
-
- if (HasComponent)
- access(mono, componentIndex()) = 0;
- std::copy_n(exponents, varCount(), ptr(mono, exponentsIndexBegin()));
- setOrderData(mono);
- setHash(mono);
-
- MATHICGB_ASSERT(debugValid(mono));
- }
-
- /// Sets mono to 1, which is the identity for multiplication.
- void setIdentity(MonoRef mono) const {
- std::fill_n(rawPtr(mono), entryCount(), static_cast<Exponent>(0));
-
- MATHICGB_ASSERT(debugValid(mono));
- MATHICGB_ASSERT(isIdentity(mono));
- }
-
- /// Sets the component of mono to newComponent.
- void setComponent(Component newComponent, MonoRef mono) const {
- MATHICGB_ASSERT(HasComponent);
-
- auto& component = access(mono, componentIndex());
- const auto oldComponent = component;
- component = newComponent;
- updateHashComponent(oldComponent, newComponent, mono);
- updateOrderComponent(newComponent, mono);
-
- MATHICGB_ASSERT(debugValid(mono));
- }
-
- /// Sets prod to a*b.
- void multiply(ConstMonoRef a, ConstMonoRef b, MonoRef prod) const {
- MATHICGB_ASSERT(debugValid(a));
- MATHICGB_ASSERT(debugValid(b));
-
- for (auto i = lastEntryIndex(); i != beforeEntriesIndexBegin(); --i)
- access(prod, i) = access(a, i) + access(b, i);
-
- MATHICGB_ASSERT(debugValid(prod));
- }
-
- /// Sets prod to a*prod.
- void multiplyInPlace(ConstMonoRef a, MonoRef prod) const {
- MATHICGB_ASSERT(debugValid(a));
- MATHICGB_ASSERT(debugValid(prod));
-
- for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i)
- access(prod, i) += access(a, i);
-
- MATHICGB_ASSERT(debugValid(prod));
- }
-
- /// Sets quo to num/by. by must divide num.
- void divide(ConstMonoRef by, ConstMonoRef num, MonoRef quo) const {
- MATHICGB_ASSERT(divides(by, num));
- MATHICGB_ASSERT(debugValid(num));
- MATHICGB_ASSERT(debugValid(by));
-
- for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i)
- access(quo, i) = access(num, i) - access(by, i);
-
- MATHICGB_ASSERT(debugValid(quo));
- }
-
- /// Sets num to num/by. by must divide num.
- void divideInPlace(ConstMonoRef by, MonoRef num) const {
- MATHICGB_ASSERT(divides(by, num));
- MATHICGB_ASSERT(debugValid(by));
- MATHICGB_ASSERT(debugValid(num));
-
- for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i)
- access(num, i) -= access(by, i);
-
- MATHICGB_ASSERT(debugValid(num));
- }
-
- /// Sets quo to num/by. If by does not divide num then quo will have
- /// negative exponents.
- void divideToNegative(ConstMonoRef by, ConstMonoRef num, MonoRef quo) const {
- MATHICGB_ASSERT(debugValid(num));
- MATHICGB_ASSERT(debugValid(by));
- MATHICGB_ASSERT(
- !HasComponent ||
- component(by) == 0 ||
- component(by) == component(num)
- );
-
- for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i)
- access(quo, i) = access(num, i) - access(by, i);
-
- MATHICGB_ASSERT(debugValid(quo));
- }
-
- /// Set out to (colonBy : colonNum) * mult.
- /// @todo: test
- void colonMultiply(
- ConstMonoRef colonBy,
- ConstMonoRef colonNum,
- ConstMonoRef mult,
- MonoRef out
- ) const {
- // todo: consider what happens with exponent overflow here
- if (HasComponent) {
- MATHICGB_ASSERT(component(colonBy) == component(colonNum));
- access(out, componentIndex()) = component(mult);
- }
- for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) {
- const auto colon = access(colonNum, i) - access(colonBy, i);
- auto result = access(mult, i);
- if (colon > 0)
- result += colon;
- access(out, i) = result;
- }
- setOrderData(out);
- setHash(out);
- MATHICGB_ASSERT(debugValid(out));
- }
-
- /// Returns the number of variables that divide mono.
- /// @todo: test
- VarIndex sizeOfSupport(ConstMonoRef mono) const {
- VarIndex count = 0;
- for (VarIndex var = 0; var < varCount(); ++var)
- if (exponent(mono, var) != 0)
- ++count;
- return count;
- }
-
- /// Sets aColonB to a:b and bColonA to b:a.
- void colons(
- ConstMonoRef a,
- ConstMonoRef b,
- MonoRef aColonB,
- MonoRef bColonA
- ) const {
- MATHICGB_ASSERT(debugValid(a));
- MATHICGB_ASSERT(debugValid(b));
-
- if (HasComponent) {
- MATHICGB_ASSERT(component(a) == component(b));
- access(aColonB, componentIndex()) = 0;
- access(bColonA, componentIndex()) = 0;
- }
-
- for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) {
- const auto ae = access(a, i);
- const auto be = access(b, i);
- const auto max = std::max(ae, be);
- access(aColonB, i) = max - be;
- access(bColonA, i) = max - ae;
- }
- setOrderData(aColonB);
- setHash(aColonB);
- setOrderData(bColonA);
- setHash(bColonA);
-
- MATHICGB_ASSERT(debugValid(aColonB));
- MATHICGB_ASSERT(debugValid(bColonA));
- }
-
- /// Sets lcmAB to the lcm of a and b.
- void lcm(ConstMonoRef a, ConstMonoRef b, MonoRef lcmAB) const {
- if (HasComponent) {
- MATHICGB_ASSERT(component(a) == component(b));
- access(lcmAB, componentIndex()) = access(a, componentIndex());
- }
- for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i)
- access(lcmAB, i) = std::max(access(a, i), access(b, i));
- setOrderData(lcmAB);
- setHash(lcmAB);
-
- MATHICGB_ASSERT(debugValid(lcmAB));
- MATHICGB_ASSERT(isLcm(a, b, lcmAB));
- }
-
- template<class MonoidA, class MonoidB>
- void lcm(
- const MonoidA& monoidA,
- typename MonoidA::ConstMonoRef a,
- const MonoidB& monoidB,
- typename MonoidB::ConstMonoRef b,
- MonoRef lcmAB
- ) const {
- MATHICGB_ASSERT(debugLcmCheck(monoidA, a, monoidB, b));
-
- if (HasComponent) {
- access(lcmAB, componentIndex()) =
- MonoidA::HasComponent ? monoidA.component(a) : monoidB.component(b);
- }
-
- for (VarIndex var = 0; var < varCount(); ++var) {
- ptr(lcmAB, exponentsIndexBegin())[var] =
- std::max(monoidA.exponent(a, var), monoidB.exponent(b, var));
- }
-
- setOrderData(lcmAB);
- setHash(lcmAB);
-
- MATHICGB_ASSERT(debugValid(lcmAB));
- MATHICGB_ASSERT(isLcm(monoidA, a, monoidB, b, lcmAB));
- }
-
- Mono alloc() const {return mPool.alloc();}
- void free(Mono&& mono) const {mPool.free(std::move(mono));}
- void freeRaw(MonoRef mono) const {mPool.freeRaw(mono);}
- bool fromPool(ConstMonoRef mono) const {mPool.fromPool(mono);}
-
- /// Parses a monomial out of a string. Valid examples: 1 abc a2bc
- /// aA. Variable names are case sensitive. Whitespace terminates the
- /// parse as does any other character that is not a letter or a
- /// digit. The monomial must not include a coefficient, not even 1,
- /// except for the special case of a 1 on its own. An input like 1a
- /// will be parsed as two separate monomials. A suffix like <2> puts
- /// the monomial in component 2, so a5<2> is a^5e_2. The default
- /// component is 0.
- void parseM2(std::istream& in, MonoRef mono) const;
-
- // Inverse of parseM2().
- void printM2(ConstMonoRef mono, std::ostream& out) const;
-
- // As printM2, but returns a string.
- std::string toString(ConstMonoRef mono) const {
- std::ostringstream out;
- printM2(mono, out);
- return out.str();
- }
-
-
- // *** Classes for holding and referring to monomials
-
- class ConstMonoPtr {
- public:
- ConstMonoPtr(): mMono(0) {}
- ConstMonoPtr(const ConstMonoPtr& mono): mMono(rawPtr(mono)) {}
-
- ConstMonoPtr operator=(const ConstMonoPtr& mono) {
- mMono = mono.mMono;
- return *this;
- }
-
- ConstMonoRef operator*() const {return *this;}
-
- bool isNull() const {return mMono == 0;}
- void toNull() {mMono = 0;}
-
- private:
- friend class MonoMonoid;
-
- const Exponent* internalRawPtr() const {return mMono;}
- ConstMonoPtr(const Exponent* mono): mMono(mono) {}
-
- const Exponent* mMono;
- };
-
- class MonoPtr {
- public:
- MonoPtr(): mMono(0) {}
- MonoPtr(const MonoPtr& mono): mMono(mono.mMono) {}
-
- MonoPtr operator=(const MonoPtr& mono) {
- mMono = mono.mMono;
- return *this;
- }
-
- MonoRef operator*() const {return *this;}
-
- bool isNull() const {return mMono == 0;}
- void toNull() {mMono = 0;}
-
- operator ConstMonoPtr() const {return ConstMonoPtr(mMono);}
-
- private:
- friend class MonoMonoid;
- friend class PolyRing; // todo: remove
- friend class Poly; // todo: remove
-
- Exponent* internalRawPtr() const {return mMono;}
- MonoPtr(Exponent* mono): mMono(mono) {}
-
- Exponent* mMono;
- };
-
- class Mono : public NonCopyable<Mono> {
- public:
- Mono(): mMono(), mPool(0) {}
-
- /// Passes ownership of the resources of mono to this object. Mono must
- /// have been allocated from pool and it must have no other owner.
- /// In particular, it must have been release()'ed from its original
- /// owner.
- Mono(MonoRef mono, MonoPool& pool):
- mMono(mono.ptr()), mPool(&pool)
- {
- MATHICGB_ASSERT(pool.fromPool(mono));
- }
-
- Mono(Mono&& mono): mMono(mono.mMono), mPool(mono.mPool) {
- mono.mMono.toNull();
- mono.mPool = 0;
- }
-
- ~Mono() {toNull();}
-
- void operator=(Mono&& mono) {
- toNull();
-
- mMono = mono.mMono;
- mono.mMono.toNull();
-
- mPool = mono.mPool;
- mono.mPool = 0;
- }
-
- /// Sets this object to null but does NOT free the resources previously
- /// held by this object. The returned MonoPtr points to the resources
- /// that this object had prior to calling release(). If this object was
- /// already null then the returned MonoPtr is also null.
- MonoPtr release() {
- const auto oldPtr = ptr();
- mMono = 0;
- mPool = 0;
- return oldPtr;
- }
-
- bool isNull() const {return mMono.isNull();}
- void toNull() {mPool->free(std::move(*this));}
-
- MonoPtr ptr() const {return mMono;}
-
- operator MonoRef() const {
- MATHICGB_ASSERT(!isNull());
- return *mMono;
- }
-
- private:
- friend class MonoMonoid;
-
- Exponent* internalRawPtr() const {return rawPtr(mMono);}
-
- MonoPtr mMono;
- MonoPool* mPool;
- };
-
- class MonoRef {
- public:
- MonoRef(const MonoRef& mono): mMono(mono.ptr()) {}
-
- MonoPtr ptr() const {return mMono;}
-
- operator ConstMonoRef() const {return *static_cast<ConstMonoPtr>(mMono);}
-
- private:
- void operator=(const MonoRef&); // not available
- friend class MonoMonoid;
-
- MonoRef(MonoPtr mono): mMono(mono) {}
- Exponent* internalRawPtr() const {return rawPtr(mMono);}
-
- const MonoPtr mMono;
- };
-
- class ConstMonoRef {
- public:
- ConstMonoRef(const ConstMonoRef& mono): mMono(mono.ptr()) {}
- ConstMonoRef(const Mono& mono): mMono(mono.ptr()) {
- MATHICGB_ASSERT(!mono.isNull());
- }
-
- ConstMonoPtr ptr() const {return mMono;}
-
- private:
- void operator=(const MonoRef&); // not available
- friend class MonoMonoid;
-
- ConstMonoRef(ConstMonoPtr mono): mMono(mono) {}
- const Exponent* internalRawPtr() const {return rawPtr(mMono);}
-
- const ConstMonoPtr mMono;
- };
-
-
- // *** Classes that provide memory resources for monomials
-
- class MonoPool : public NonCopyable<MonoPool> {
- public:
- MonoPool(const MonoMonoid& monoid):
- mMonoid(monoid),
- mPool(sizeof(Exponent) * mMonoid.entryCount())
- {}
-
- MonoPool(MonoPool&& pool):
- mMonoid(pool.mMonoid),
- mPool(std::move(pool.mPool))
- {}
-
- Mono alloc() {
- const auto ptr = static_cast<Exponent*>(mPool.alloc());
- Mono mono(*MonoPtr(ptr), *this);
- monoid().setIdentity(mono);
- return mono;
- }
-
- void free(Mono&& mono) {
- if (mono.isNull())
- return;
- freeRaw(mono);
- mono.mMono = 0;
- mono.mPool = 0;
- }
- void freeRaw(MonoRef mono) {mPool.free(rawPtr(mono));}
-
- const MonoMonoid& monoid() const {return mMonoid;}
-
- bool fromPool(ConstMonoRef mono) const {
- return mPool.fromPool(rawPtr(mono));
- }
-
- private:
- const MonoMonoid& mMonoid;
- memt::BufferPool mPool;
- };
-
- class MonoVector {
- private:
- typedef std::vector<Exponent> RawVector;
-
- public:
- /// Class for iterating through the monomials in a MonoVector.
- ///
- /// There is no operator->() since MonoRef does not have any
- /// relevant methods to call. Implement it if you need it.
- ///
- /// There are no postfix increment operator as prefix is
- /// better. Add it if you y need it (you probably do not).
- ///
- /// We could make this a random access iterator, but that would
- /// make it tricky to support variable-sized exponent vectors
- /// (e.g. sparse) in future and so far we have not needed random
- /// access.
- class const_iterator {
- public:
- typedef std::forward_iterator_tag iterator_category;
- typedef ConstMonoPtr value_type;
-
- const_iterator(): mIt(), mEntriesPerMono(0) {}
- const_iterator(const const_iterator& it):
- mIt(it.mIt), mEntriesPerMono(it.mEntriesPerMono) {}
-
- bool operator==(const const_iterator& it) const {return mIt == it.mIt;}
- bool operator!=(const const_iterator& it) const {return mIt != it.mIt;}
-
- ConstMonoRef operator*() {
- MATHICGB_ASSERT(debugValid());
- return *ConstMonoPtr(&*mIt);
- }
-
- const_iterator operator++() {
- MATHICGB_ASSERT(debugValid());
- mIt += mEntriesPerMono;
- return *this;
- }
-
- private:
- friend class MonoVector;
- bool debugValid() {return mEntriesPerMono > 0;}
-
- const_iterator(
- typename RawVector::const_iterator it,
- size_t entryCount
- ): mIt(it), mEntriesPerMono(entryCount) {}
-
- typename RawVector::const_iterator mIt;
- size_t mEntriesPerMono;
- };
-
- // ** Constructors and assignment
- MonoVector(const MonoMonoid& monoid): mMonoid(monoid) {}
- MonoVector(const MonoVector& v): mMonos(v.mMonos), mMonoid(v.monoid()) {}
- MonoVector(MonoVector&& v):
- mMonos(std::move(v.mMonos)), mMonoid(v.monoid()) {}
-
- MonoVector& operator=(const MonoVector& v) {
- MATHICGB_ASSERT(monoid() == v.monoid());
- mMonos = v.mMonos;
- return *this;
- }
-
- MonoVector& operator=(MonoVector&& v) {
- MATHICGB_ASSERT(monoid() == v.monoid());
- mMonos = std::move(v.mMonos);
- return *this;
- }
-
- // ** Iterators
- const_iterator begin() const {
- return const_iterator(mMonos.begin(), mMonoid.entryCount());
- }
-
- const_iterator end() const {
- return const_iterator(mMonos.end(), mMonoid.entryCount());
- }
-
- const_iterator cbegin() const {return begin();}
- const_iterator cend() const {return end();}
-
- // ** Capacity
- size_t size() const {return mMonos.size() / monoid().entryCount();}
- bool empty() const {return mMonos.empty();}
-
- // ** Element access
- ConstMonoRef front() const {
- MATHICGB_ASSERT(!empty());
- return *begin();
- }
-
- MonoRef back() {
- MATHICGB_ASSERT(!empty());
- const auto offset = mMonos.size() - monoid().entryCount();
- return *MonoPtr(mMonos.data() + offset);
- }
-
- ConstMonoRef back() const {
- MATHICGB_ASSERT(!empty());
- const auto offset = mMonos.size() - monoid().entryCount();
- return *ConstMonoPtr(mMonos.data() + offset);
- }
-
- // ** Modifiers
-
- void reserve(size_t count) {
- mMonos.reserve(count * monoid().entryCount());
- }
-
- /// Appends the identity.
- void push_back() {
- const auto offset = mMonos.size();
- mMonos.resize(offset + monoid().entryCount());
- MATHICGB_ASSERT(monoid().isIdentity(back()));
- MATHICGB_ASSERT(monoid().debugValid(back()));
- }
-
- 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));
- MATHICGB_ASSERT(monoid().debugValid(back()));
- }
-
- template<class Monoid>
- void push_back(
- const Monoid& monoidMono,
- typename Monoid::ConstMonoRef mono
- ) {
- MATHICGB_ASSERT(monoidMono.debugValid(mono));
- const auto offset = mMonos.size();
- mMonos.resize(offset + monoid().entryCount());
- monoid().copy(monoidMono, mono, *MonoPtr(mMonos.data() + offset));
- MATHICGB_ASSERT(monoid().debugValid(back()));
- }
-
- void swap(MonoVector& v) {
- MATHICGB_ASSERT(&monoid() == &v.monoid());
- mMonos.swap(v.mMonos);
- }
-
- void clear() {mMonos.clear();}
-
- // ** Relational operators
- bool operator==(const MonoVector& v) const {
- MATHICGB_ASSERT(monoid() == v.monoid());
- return mMonos == v.mMonos;
- }
- bool operator!=(const MonoVector& v) const {return !(*this == v);}
-
- // ** Other
- size_t memoryBytesUsed() const {
- return mMonos.capacity() * sizeof(mMonos[0]);
- }
-
- /// As parseM2 on monoid, but accepts a non-empty space-separated
- /// list of monomials. The monomials are appended to the end of
- /// the vector.
- void parseM2(std::istream& in) {
- while(true) {
- push_back();
- monoid().parseM2(in, back());
- if (in.peek() != ' ')
- break;
- in.get();
- }
- }
-
- /// The inverse of parseM2.
- void printM2(std::ostream& out) const {
- for (auto it = begin(); it != end(); ++it) {
- if (it != begin())
- out << ' ';
- monoid().printM2(*it, out);
- }
- out << '\n';
- }
-
- const MonoMonoid& monoid() const {return mMonoid;}
-
- private:
- RawVector mMonos;
- const MonoMonoid& mMonoid;
- };
-
-
-private:
- void operator=(MonoMonoid&); // not available
-
- // Grants access to other template instantiations.
- template<class E2, bool HC2, bool SH2, bool SO2>
- friend class MonoMonoid;
-
- // The main point here is to grant access to rawPtr().
- friend class Mono;
- friend class MonoRef;
- friend class ConstMonoRef;
- friend class MonoPtr;
- friend class ConstMonoPtr;
- friend class MonoVector;
- friend class MonoPool;
-
- typedef typename Base::Gradings Gradings;
-
- bool debugAssertValid() const {
-#ifdef MATHICGB_DEBUG
- // ** Order checks
- MATHICGB_ASSERT(orderIndexBegin() == exponentsIndexEnd());
- const auto storedDegrees = StoreOrder * gradingCount();
- MATHICGB_ASSERT(orderIndexEnd() == orderIndexBegin() + storedDegrees);
- MATHICGB_ASSERT(orderIndexEnd() <= entryCount());
- if (orderIndexEnd() + StoreHash == 0) {
- MATHICGB_ASSERT(entryCount() == 1);
- } else {
- MATHICGB_ASSERT(entryCount() == orderIndexEnd() + StoreHash);
- }
-
- MATHICGB_ASSERT(isLexBaseOrder() || varCount() == 0 || gradingCount() >= 1);
-
- MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount());
- if (orderIsTotalDegreeRevLex()) {
- MATHICGB_ASSERT(!isLexBaseOrder());
- MATHICGB_ASSERT(gradingCount() == 1);
- }
-
- if (componentGradingIndex() != Order::ComponentAfterBaseOrder) {
- MATHICGB_ASSERT(componentGradingIndex() < gradingCount());
- for (VarIndex var = 0; var < varCount(); ++var) {
- const auto index = gradingsIndex(componentGradingIndex(), var);
- MATHICGB_ASSERT(gradings()[index] == 0);
- }
- }
-
- // ** Hash checks
- if (StoreHash) {
- MATHICGB_ASSERT(hashIndex() < entryCount());
- MATHICGB_ASSERT(hashIndex() == orderIndexEnd());
- }
- MATHICGB_ASSERT(hashCoefficients().size() == varCount());
-#endif
- return true;
- }
-
- bool debugValid(ConstMonoRef mono) const {
- MATHICGB_ASSERT(debugOrderValid(mono));
- MATHICGB_ASSERT(debugHashValid(mono));
- return true;
- }
-
- template<class MonoidA, class MonoidB>
- bool debugLcmCheck(
- const MonoidA& monoidA,
- typename MonoidA::ConstMonoRef a,
- const MonoidB& monoidB,
- typename MonoidB::ConstMonoRef b
- ) const {
- MATHICGB_ASSERT(monoidA.varCount() == varCount());
- MATHICGB_ASSERT(monoidB.varCount() == varCount());
- MATHICGB_ASSERT
- ((std::is_same<Exponent, typename MonoidA::Exponent>::value));
- MATHICGB_ASSERT
- ((std::is_same<Exponent, typename MonoidB::Exponent>::value));
- MATHICGB_ASSERT
- (HasComponent == (MonoidA::HasComponent || MonoidB::HasComponent));
- MATHICGB_ASSERT(monoidA.debugValid(a));
- MATHICGB_ASSERT(monoidB.debugValid(b));
- MATHICGB_ASSERT(
- !HasComponent ||
- !MonoidA::HasComponent ||
- !MonoidB::HasComponent ||
- monoidA.component(a) == monoidB.component(b)
- );
-
- return true;
- }
-
- // *** Accessing fields of a monomial
- template<class M>
- static auto rawPtr(M&& m) -> decltype(m.internalRawPtr()) {
- return m.internalRawPtr();
- }
-
- Exponent* ptr(MonoRef& m, const VarIndex index) const {
- MATHICGB_ASSERT(index <= entryCount());
- return rawPtr(m) + index;
- }
-
- const Exponent* ptr(ConstMonoRef& m, const VarIndex index) const {
- MATHICGB_ASSERT(index <= entryCount());
- return rawPtr(m) + index;
- }
-
- Exponent& access(MonoRef& m, const VarIndex index) const {
- MATHICGB_ASSERT(index < entryCount());
- return rawPtr(m)[index];
- }
-
- const Exponent& access(ConstMonoRef& m, const VarIndex index) const {
- MATHICGB_ASSERT(index < entryCount());
- return rawPtr(m)[index];
- }
-
- // *** Implementation of monomial ordering
-
- using Base::gradingsOppositeRowIndex;
- using Base::gradingsIndex;
- using Base::reverseGradings;
- using Base::negateGradings;
-
- bool debugOrderValid(ConstMonoRef mono) const {
-#ifdef MATHICGB_DEBUG
- if (!StoreOrder)
- return true;
- // Check the order data of mono
- const auto degrees = ptr(mono, orderIndexBegin());
- for (VarIndex grading = 0; grading < gradingCount(); ++grading) {
- MATHICGB_ASSERT(degrees[grading] == computeDegree(mono, grading));
- }
-#endif
- return true;
- }
-
- void setOrderData(MonoRef mono) const {
- if (!StoreOrder)
- return;
-
- const auto degrees = ptr(mono, orderIndexBegin());
- for (VarIndex grading = 0; grading < gradingCount(); ++grading)
- degrees[grading] = computeDegree(mono, grading);
- MATHICGB_ASSERT(debugOrderValid(mono));
- }
-
- void updateOrderData(
- const VarIndex var,
- const Exponent oldExponent,
- const Exponent newExponent,
- MonoRef mono
- ) const {
- if (!StoreOrder)
- return;
-
- MATHICGB_ASSERT(var < varCount());
- if (orderIsTotalDegreeRevLex())
- rawPtr(mono)[orderIndexBegin()] -= newExponent - oldExponent;
- else {
- MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount());
- const auto degrees = ptr(mono, orderIndexBegin());
- for (VarIndex grading = 0; grading < gradingCount(); ++grading) {
- const auto index = gradingsIndex(grading, var);
- degrees[grading] += gradings()[index] * ( newExponent - oldExponent);
- }
- }
- MATHICGB_ASSERT(debugOrderValid(mono));
- }
-
- void updateOrderComponent(const VarIndex newComponent, MonoRef mono) const {
- if (componentGradingIndex() != Order::ComponentAfterBaseOrder)
- ptr(mono, orderIndexBegin())[componentGradingIndex()] = newComponent;
- }
-
- Exponent computeDegree(ConstMonoRef mono, VarIndex grading) const {
- MATHICGB_ASSERT(grading < gradingCount());
-
- Exponent degree = 0;
- if (orderIsTotalDegreeRevLex()) {
- MATHICGB_ASSERT(grading == 0);
- for (auto var = 0; var < varCount(); ++var)
- degree -= exponent(mono, var);
- } else if (HasComponent && componentGradingIndex() == grading)
- return component(mono);
- else {
- MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount());
- for (auto var = 0; var < varCount(); ++var) {
- const auto index = gradingsIndex(grading, var);
- degree += exponent(mono, var) * gradings()[index];
- }
- }
- return degree;
- }
-
-
- // *** Implementation of hash value computation
-
- bool debugHashValid(ConstMonoRef mono) const {
- if (!StoreHash)
- return true;
-
- // We cannot call hash() here since it calls this method.
- // todo: we cannot make this check right now because the legacy
- // integration with PolyRing can create monomials with unset hash.
- // MATHICGB_ASSERT(rawPtr(mono)[hashIndex()] == computeHash(mono));
- return true;
- }
-
- HashValue computeHash(ConstMonoRef mono) const {
- HashValue hash = HasComponent ? component(mono) : 0;
- for (VarIndex var = 0; var < varCount(); ++var) {
- hash +=
- static_cast<HashValue>(exponent(mono, var)) * hashCoefficients()[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 {
- if (!StoreHash)
- return;
- rawPtr(mono)[hashIndex()] = computeHash(mono);
- MATHICGB_ASSERT(debugHashValid(mono));
- }
-
- void updateHashComponent(
- const Exponent oldComponent,
- const Exponent newComponent,
- MonoRef mono
- ) const {
- if (!StoreHash)
- return;
- rawPtr(mono)[hashIndex()] += newComponent - oldComponent;
- MATHICGB_ASSERT(debugHashValid(mono));
- }
-
- void updateHashExponent(
- const VarIndex var,
- const Exponent oldExponent,
- const Exponent newExponent,
- MonoRef mono
- ) const {
- if (!StoreHash)
- return;
- MATHICGB_ASSERT(var < varCount());
- rawPtr(mono)[hashIndex()] +=
- (newExponent - oldExponent) * hashCoefficients()[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 data than the exponents, so
- /// this number can be larger than varCount().
- using Base::entryCount;
- //size_t entryCount() const {return mEntryCount;}
-
- VarIndex componentIndex() const {
- //static_assert(HasComponent, "");
- return 0;
- }
-
- VarIndex exponentsIndexBegin() const {return HasComponent;}
- VarIndex exponentsIndexEnd() const {return exponentsIndexBegin() + varCount();}
- VarIndex lastExponentIndex() const {return exponentsIndexEnd() - 1;}
-
- using Base::orderIndexBegin;
- using Base::orderIndexEnd;
- using Base::hashIndex;
- using Base::orderIsTotalDegreeRevLex;
- using Base::gradings;
- using Base::isLexBaseOrder;
- using Base::componentGradingIndex;
-
- VarIndex entriesIndexBegin() const {return 0;}
- VarIndex entriesIndexEnd() const {return entryCount();}
- VarIndex beforeEntriesIndexBegin() const {return entriesIndexBegin() - 1;}
- VarIndex lastEntryIndex() const {return entriesIndexEnd() - 1;}
-
- using Base::hashCoefficients;
-
- mutable MonoPool mPool;
-};
-
-namespace MonoMonoidHelper {
- /// ostream and istream handle characters differently from other
- /// integers. Use unchar to cast chars to a different type that get
- /// handled as other integers do.
- template<class T>
- struct unchar {typedef int type;};
-
- // Yes: char, signed char and unsigned char are 3 distinct types.
- template<>
- struct unchar<char> {typedef short type;};
- template<>
- struct unchar<signed char> {typedef short type;};
- template<>
- struct unchar<unsigned char> {typedef unsigned short type;};
-}
-
-template<class E, bool HC, bool SH, bool SO>
-auto MonoMonoid<E, HC, SH, SO>::readMonoid(std::istream& in) ->
- std::pair<MonoMonoid, std::pair<bool, bool>>
-{
- using MonoMonoidHelper::unchar;
- VarIndex varCount;
- in >> varCount;
-
- bool doSchreyer = false;
- bool lexBaseOrder = false;
- std::string str;
- char c;
- in >> c;
- in.unget();
- if (!std::isdigit(c)) {
- std::string str;
- in >> str;
- if (str == "schreyer") {
- doSchreyer = true;
- in >> str;
- }
-
- if (str == "revlex")
- lexBaseOrder = false;
- else if (str == "lex")
- lexBaseOrder = true;
- else
- mathic::reportError("Expected lex or revlex but read \"" + str + "\".");
- }
-
- VarIndex gradingCount;
- in >> gradingCount;
-
- Gradings gradings(static_cast<size_t>(varCount) * gradingCount);
- bool componentsAscendingDesired = true;
- auto componentCompareIndex = Order::ComponentAfterBaseOrder;
- size_t w = 0;
- for (VarIndex grading = 0; grading < gradingCount; ++grading) {
- char c;
- in >> c;
- in.unget();
- if (!std::isdigit(c)) {
- std::string str;
- in >> str;
-
- if (str == "component")
- componentsAscendingDesired = true;
- else if (str == "revcomponent")
- componentsAscendingDesired = false;
- else
- mathic::reportError
- ("Expected component or revcomponent but read \"" + str + "\".");
- if (!HasComponent)
- mathic::reportError
- ("Cannot specify component comparison for non-modules.");
- if (componentCompareIndex != Order::ComponentAfterBaseOrder)
- mathic::reportError("Component must be considered at most once.");
- componentCompareIndex = grading;
- w += varCount;
- } else {
- for (VarIndex i = 0; i < varCount; ++i, ++w) {
- typename unchar<Exponent>::type e;
- in >> e;
- gradings[w] = static_cast<Exponent>(e);
- }
- }
- }
- MATHICGB_ASSERT(w == gradings.size());
-
- in >> c;
- in.unget();
- if (c == '_') {
- in >> str;
-
- if (str == "_revlex")
- lexBaseOrder = false;
- else if (str == "_lex")
- lexBaseOrder = true;
- else
- mathic::reportError("Expected _lex or _revlex but read \"" + str + "\".");
-
- in >> c;
- in.unget();
- if (!std::isdigit(c)) {
- in >> str;
- if (str == "component")
- componentsAscendingDesired = true;
- else if (str == "revcomponent")
- componentsAscendingDesired = false;
- else
- mathic::reportError
- ("Expected component or revcomponent but read \"" + str + "\".");
- }
- }
-
- Order order(
- varCount,
- std::move(gradings),
- lexBaseOrder ? Order::LexBaseOrder : Order::RevLexBaseOrder,
- componentCompareIndex
- );
- return std::make_pair(
- MonoMonoid(order),
- std::make_pair(componentsAscendingDesired, doSchreyer)
- );
-}
-
-template<class E, bool HC, bool SH, bool SO>
-void MonoMonoid<E, HC, SH, SO>::printMonoid(
- const bool componentsAscendingDesired,
- std::ostream& out
-) const {
- using MonoMonoidHelper::unchar;
- typedef typename unchar<Exponent>::type UncharredExponent;
-
- out << varCount() << '\n'
- << (isLexBaseOrder() ? "lex" : "revlex")
- << ' ' << gradingCount() << '\n';
- MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount());
- for (VarIndex grading = 0; grading < gradingCount(); ++grading) {
- if (
- HasComponent &&
- grading == gradingCount() - 1 - componentGradingIndex()
- ) {
- out << (componentsAscendingDesired ? " component\n" : " revcomponent\n");
- continue;
- }
-
- for (VarIndex var = 0; var < varCount(); ++var) {
- auto w = gradings()[gradingsOppositeRowIndex(grading, var)];
- if (!isLexBaseOrder())
- w = -w;
- out << ' ' << static_cast<UncharredExponent>(w);
- }
- out << '\n';
- }
-}
-
-template<class E, bool HC, bool SH, bool SO>
-void MonoMonoid<E, HC, SH, SO>::parseM2(std::istream& in, MonoRef mono) const {
- using MonoMonoidHelper::unchar;
- // todo: signal error on exponent overflow
-
- setIdentity(mono);
-
- bool sawSome = false;
- while (true) {
- const char next = in.peek();
- if (!sawSome && next == '1') {
- in.get();
- break;
- }
-
- VarIndex var;
- const auto letterCount = 'z' - 'a' + 1;
- if ('a' <= next && next <= 'z')
- var = next - 'a';
- else if ('A' <= next && next <= 'Z')
- var = (next - 'A') + letterCount;
- else if (sawSome)
- break;
- else {
- mathic::reportError("Could not parse monomial.");
- return;
- }
- MATHICGB_ASSERT(var < 2 * letterCount);
- if (var >= varCount()) {
- mathic::reportError("Unknown variable.");
- return;
- }
-
- in.get();
- auto& exponent = access(mono, exponentsIndexBegin() + var);
- if (isdigit(in.peek())) {
- typename unchar<Exponent>::type e;
- in >> e;
- exponent = static_cast<Exponent>(e);
- } else
- exponent = 1;
- sawSome = true;
- }
-
- if (in.peek() == '<') {
- if (!HasComponent) {
- mathic::reportError("Read unexpected < for start of module component\n");
- return;
- }
-
- in.get();
- if (!isdigit(in.peek())) {
- mathic::reportError("Component was not integer.");
- return;
- }
- typename unchar<Exponent>::type e;
- in >> e;
- access(mono, componentIndex()) = static_cast<Exponent>(e);
- if (in.peek() != '>') {
- mathic::reportError("Component < was not matched by >.");
- return;
- }
- in.get();
- }
-
- setOrderData(mono);
- setHash(mono);
- MATHICGB_ASSERT(debugValid(mono));
-}
-
-template<class E, bool HC, bool SH, bool SO>
-void MonoMonoid<E, HC, SH, SO>::printM2(
- ConstMonoRef mono,
- std::ostream& out
-) const {
- using MonoMonoidHelper::unchar;
- const auto letterCount = 'z' - 'a' + 1;
-
- bool printedSome = false;
- for (VarIndex var = 0; var < varCount(); ++var) {
- if (exponent(mono, var) == 0)
- continue;
- char letter;
- if (var < letterCount)
- letter = 'a' + static_cast<char>(var);
- else if (var < 2 * letterCount)
- letter = 'A' + (static_cast<char>(var) - letterCount);
- else {
- mathic::reportError("Too few letters in alphabet to print variable.");
- return;
- }
- printedSome = true;
- out << letter;
- if (exponent(mono, var) != 1)
- out << static_cast<typename unchar<Exponent>::type>(exponent(mono, var));
- }
- if (!printedSome)
- out << '1';
- if (HasComponent && component(mono) != 0) {
- out << '<'
- << static_cast<typename unchar<Exponent>::type>(component(mono))
- << '>';
- }
-}
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_MONO_MONOID_GUARD
+#define MATHICGB_MONO_MONOID_GUARD
+
+#include "MonoOrder.hpp"
+#include "NonCopyable.hpp"
+#include <vector>
+#include <algorithm>
+#include <memtailor.h>
+#include <type_traits>
+#include <istream>
+#include <utility>
+#include <ostream>
+#include <cstdlib>
+#include <cstring>
+#include <mathic.h>
+
+MATHICGB_NAMESPACE_BEGIN
+
+/// Implements the monoid of (monic) monomials with integer
+/// non-negative exponents. Exponent must be an unsigned integer type that is
+/// used to store each exponent of a monomial.
+template<
+ class Exponent,
+ bool HasComponent = true,
+ bool StoreHash = true,
+ bool StoreOrder = true
+>
+class MonoMonoid;
+
+namespace MonoMonoidInternal {
+ template<class E, bool HC, bool SH, bool SO>
+ class Base {
+ public:
+ static const bool HasComponent = HC;
+ static const bool StoreHash = SH;
+ static const bool StoreOrder = SO;
+
+ typedef size_t VarIndex;
+ typedef E Exponent;
+ typedef typename ::std::make_unsigned<E>::type Component;
+ typedef typename ::std::make_unsigned<E>::type HashValue;
+ typedef const Exponent* const_iterator;
+ typedef MonoOrder<Exponent> Order;
+
+ Base(const Order& order):
+ mVarCount(order.varCount()),
+ mGradingCount(order.gradingCount()),
+ mOrderIndexBegin(HasComponent + order.varCount()),
+ mOrderIndexEnd(mOrderIndexBegin + StoreOrder * order.gradingCount()),
+ mEntryCount(::std::max<VarIndex>(mOrderIndexEnd + StoreHash, 1)),
+ mHashCoefficients(makeHashCoefficients(order.varCount())),
+ mOrderIsTotalDegreeRevLex
+ (order.baseOrder() == Order::RevLexBaseOrder && order.isTotalDegree()),
+ mLexBaseOrder(order.baseOrder() == Order::LexBaseOrder),
+ mGradings(makeGradings(order)),
+ mComponentGradingIndex(
+ reverseComponentGradingIndex
+ (order.gradingCount(), order.componentGradingIndex())
+ )
+ {
+ }
+
+ VarIndex varCount() const {return mVarCount;}
+ VarIndex gradingCount() const {return mGradingCount;}
+
+ VarIndex entryCount() const {return mEntryCount;}
+ VarIndex orderIndexEnd() const {return mOrderIndexEnd;}
+ VarIndex orderIndexBegin() const {return mOrderIndexBegin;}
+ VarIndex hashIndex() const {return mOrderIndexEnd;}
+ VarIndex componentGradingIndex() const {return mComponentGradingIndex;}
+
+ protected:
+ typedef ::std::vector<Exponent> HashCoefficients;
+ typedef ::std::vector<Exponent> Gradings;
+
+ static Gradings makeGradings(const Order& order) {
+ auto gradings = order.gradings();
+ reverseGradings(order.varCount(), gradings);
+ if (order.baseOrder() == Order::RevLexBaseOrder)
+ negateGradings(gradings);
+ return gradings;
+ }
+
+ /// Reverse the relative order among the gradings - the first one
+ /// becomes the last one, the second first becomes the second last
+ /// and so on.
+ static void reverseGradings(const VarIndex varCount, Gradings& gradings) {
+ if (varCount == 0)
+ return;
+ MATHICGB_ASSERT(gradings.size() % varCount == 0);
+ const auto gradingCount = gradings.size() / varCount;
+
+ for (VarIndex grading = 0; grading < gradingCount / 2; ++grading) {
+ for (VarIndex var = 0; var < varCount; ++var) {
+ const auto index = gradingsIndex(grading, var, varCount);
+ const auto oppositeIndex = gradingsOppositeRowIndex
+ (grading, gradingCount, var, varCount);
+ ::std::swap(gradings[index], gradings[oppositeIndex]);
+ }
+ }
+ }
+
+ /// Replace each entry in the grading matrix with its negative.
+ static void negateGradings(Gradings& gradings) {
+ const auto size = gradings.size();
+ for (size_t i = 0; i < size; ++i)
+ gradings[i] = -gradings[i];
+ }
+
+ /// Since comparisons go opposite direction, we need to reverse
+ /// the component grading index, unless it's the special value
+ /// indicating that it goes last.
+ static VarIndex reverseComponentGradingIndex(
+ const VarIndex gradingCount,
+ const VarIndex componentGradingIndex
+ ) {
+ if (componentGradingIndex == Order::ComponentAfterBaseOrder)
+ return Order::ComponentAfterBaseOrder;
+ else
+ return gradingCount - 1 - componentGradingIndex;
+ }
+
+ const HashCoefficients& hashCoefficients() const {return mHashCoefficients;}
+ bool orderIsTotalDegreeRevLex() const {return mOrderIsTotalDegreeRevLex;}
+ Gradings& gradings() {return mGradings;} // todo: remove this overload
+ const Gradings& gradings() const {return mGradings;}
+ bool isLexBaseOrder() const {return mLexBaseOrder;}
+
+ static size_t gradingsIndex(
+ const VarIndex grading,
+ const VarIndex var,
+ const VarIndex varCount
+ ) {
+ MATHICGB_ASSERT(var < varCount);
+ return grading * static_cast<size_t>(varCount) + var;
+ }
+
+ size_t gradingsIndex(const VarIndex grading, const VarIndex var) const {
+ MATHICGB_ASSERT(grading < gradingCount());
+ MATHICGB_ASSERT(var < varCount());
+ const auto index = gradingsIndex(grading, var, varCount());
+ MATHICGB_ASSERT(index < gradings().size());
+ return index;
+ }
+
+ static size_t gradingsOppositeRowIndex(
+ const VarIndex grading,
+ const VarIndex gradingCount,
+ const VarIndex var,
+ const VarIndex varCount
+ ) {
+ MATHICGB_ASSERT(grading < gradingCount);
+ MATHICGB_ASSERT(var < varCount);
+ return gradingsIndex(gradingCount - 1 - grading, var, varCount);
+ }
+
+ size_t gradingsOppositeRowIndex(
+ const VarIndex grading,
+ const VarIndex var
+ ) const {
+ MATHICGB_ASSERT(grading < gradingCount());
+ MATHICGB_ASSERT(var < varCount());
+ const auto index =
+ gradingsOppositeRowIndex(grading, gradingCount(), var, varCount());
+ MATHICGB_ASSERT(index < gradings().size());
+ return index;
+ }
+
+ private:
+ HashCoefficients static makeHashCoefficients(const VarIndex varCount) {
+ ::std::srand(0); // To use the same hash coefficients every time.
+ HashCoefficients coeffs(varCount);
+ for (VarIndex var = 0; var < varCount; ++var)
+ coeffs[var] = static_cast<HashValue>(::std::rand());
+ return coeffs;
+ }
+
+ const VarIndex mVarCount;
+ const VarIndex mGradingCount;
+ const VarIndex mOrderIndexBegin;
+ const VarIndex mOrderIndexEnd;
+ const VarIndex mEntryCount;
+ const VarIndex mComponentGradingIndex;
+
+ /// Take dot product of exponents with this vector to get hash value.
+ const HashCoefficients mHashCoefficients;
+
+ /// This is initialized before mGradings, so it has to be ordered
+ /// above mGradings.
+ const bool mOrderIsTotalDegreeRevLex;
+
+ /// If true then lex is used to break ties. Otherwise, revlex is
+ /// used. This applies as well to degrees, which implies that
+ /// degrees have to be stored negated if doing revlex.
+ const bool mLexBaseOrder;
+
+ /// Defines a matrix where each row is a grading. The degree of a
+ /// monomial with respect to grading g is the dot product of the
+ /// exponent vector of that monomial with row g of the matrix
+ /// (starting at g=0). The matrix is stored in row-major order. If
+ /// mOrderIsTotalDegreeRevLex is true then mGradings is empty but
+ /// implicitly it is a single grading consisting of all 1s and the
+ /// base order is revlex.
+ ::std::vector<Exponent> mGradings;
+ };
+}
+
+template<class E, bool HC, bool SH, bool SO>
+class MonoMonoid : private MonoMonoidInternal::Base<E, HC, SH, SO> {
+private:
+ typedef MonoMonoidInternal::Base<E, HC, SH, SO> Base;
+
+public:
+ static_assert(::std::numeric_limits<E>::is_signed, "");
+
+ // *** Types
+
+ // Integer index representing a variable. Indices start at 0 and go
+ // up to varCount() - 1 where varCount() is the number of variables.
+ typedef typename Base::VarIndex VarIndex;
+
+ /// The type of each exponent of a monomial.
+ typedef typename Base::Exponent Exponent;
+
+ /// Is true if the monomials come from a module.
+ using Base::HasComponent;
+
+ /// Is true if the hash value is stored rather than computed at each
+ /// hash request. This imposes extra computation when updating a monomial,
+ /// but for most operations that overhead is much less than the time for
+ /// computing a hash value from scratch.
+ using Base::StoreHash;
+
+ /// Is true if data to compare monomials is stored rather than computed
+ /// at each comparison. As storeHash, there is overhead for this, but it
+ /// is not much for most operations.
+ using Base::StoreOrder;
+
+ /// Type used to indicate the component of a module monomial. For example,
+ /// the component of xe_3 is 3.
+ typedef typename Base::Component Component;
+
+ /// Type used to store hash values of monomials.
+ typedef typename Base::HashValue HashValue;
+
+ /// Iterator for the exponents in a monomial.
+ typedef typename Base::const_iterator const_iterator;
+
+ /// Represents a monomial and manages the memory underlying it. To
+ /// refer to a non-owned monomial or to refer to a Mono, use MonoRef
+ /// or ConstMonoRef. Do not use Mono& or Mono* if you do not have
+ /// to, since that implies a double indirection when accessing the
+ /// monomial.
+ class Mono;
+
+ /// A reference to a non-const monomial. Cannot be null, cannot be
+ /// reassigned to refer to a different monomial and does not connote
+ /// ownership - the same semantics as C++ references.
+ class MonoRef;
+
+ /// A reference to a monomial. As MonoRef, but you cannot change the
+ /// monomial through this reference. Prefer this class over the
+ /// other reference/pointer classes unless there is a reason not to.
+ class ConstMonoRef;
+
+ /// A pointer to a non-const monomial. Can be null and can be
+ /// reassigned to refer to a different monomial - the same semantics
+ /// as C++ pointers. Does not connote ownership.
+ class MonoPtr;
+
+ /// A pointer to a monomial. As MonoPtr, but you cannot change the
+ /// monomial through this pointer.
+ class ConstMonoPtr;
+
+ /// A pool of memory for monomials.
+ ///
+ /// @todo: This approach is a poor fit for variable-sized
+ /// monomials. So prefer other solutions where reasonable.
+ class MonoPool;
+
+ /// A vector of monomials. The interface is a subset of
+ /// ::std::vector. Monomials can be appended (push_back). Only the
+ /// last monomial can be mutated and monomials cannot be reordered
+ /// or removed. These restrictions should make it easier to support
+ /// variable-sized monomials in future. Change it if you need to
+ /// break these restrictions, but first try to find an alternative.
+ class MonoVector;
+
+ /// For indicating the result of comparing one monomial to another.
+ enum CompareResult {
+ LessThan = -1,
+ EqualTo = 0,
+ GreaterThan = 1
+ };
+
+ /// Used to describe a monomial order when constructing a monoid.
+ typedef typename Base::Order Order;
+
+ // *** Temporary compatibility code for migrating off PolyRing
+ friend class PolyRing;
+ friend class Poly;
+ static MonoRef toRef(Exponent* e) {return MonoRef(e);}
+ static ConstMonoRef toRef(const Exponent* e) {return ConstMonoRef(e);}
+ static Exponent* toOld(MonoRef e) {return rawPtr(e);}
+ static const Exponent* toOld(ConstMonoRef e) {return rawPtr(e);}
+
+
+ // *** Constructors and accessors
+
+ MonoMonoid(MonoMonoid&& monoid): Base(::std::move(monoid)), mPool(*this) {
+ MATHICGB_ASSERT(debugAssertValid());
+ }
+
+ MonoMonoid(const MonoMonoid& monoid): Base(monoid), mPool(*this) {
+ MATHICGB_ASSERT(debugAssertValid());
+ }
+
+ MonoMonoid(const Order& order): Base(order), mPool(*this) {
+ MATHICGB_ASSERT(debugAssertValid());
+ }
+
+ /// Creates a compatible copy of monoid.
+ template<class E2, bool HC2, bool SH2, bool SO2>
+ static MonoMonoid create(const MonoMonoid<E2, HC2, SH2, SO2>& monoid) {
+ return MonoMonoid(monoid.makeOrder(false, false));
+ }
+
+ /// The second.first value of the return pair indicates whether it
+ /// is desired that i>j => e_i > e_j. the second.second value
+ /// indicates whether to do a Schreyer order. TODO: clearly this is
+ /// a mess that needs to be cleaned up. Step 1 is to move IO out of
+ /// MonoMonoid entirely.
+ static ::std::pair<MonoMonoid, ::std::pair<bool, bool>> readMonoid(::std::istream& in);
+ void printMonoid
+ (const bool componentsAscendingDesired, ::std::ostream& out) const;
+
+ /// Returns an Order object that is equivalent to the order that
+ /// this monoid was constructed with. The settings not handled by
+ /// the monoid, and therefore not known by the monoid, are passed in
+ /// as parameters. The purpose of that is to make it clear that this
+ /// information must be supplied separately.
+ Order makeOrder(
+ const bool componentsAscendingDesired,
+ const bool schreyering
+ ) const {
+ ::std::vector<Exponent> orderGradings(gradings());
+ reverseGradings(varCount(), orderGradings);
+ if (!isLexBaseOrder())
+ negateGradings(orderGradings);
+ return Order(
+ varCount(),
+ ::std::move(orderGradings),
+ isLexBaseOrder() ? Order::LexBaseOrder : Order::RevLexBaseOrder,
+ Base::reverseComponentGradingIndex
+ (gradingCount(), componentGradingIndex()),
+ componentsAscendingDesired,
+ schreyering
+ );
+ }
+
+ bool operator==(const MonoMonoid& monoid) const {
+ return this == &monoid;
+ }
+
+ bool operator!=(const MonoMonoid& monoid) const {
+ return !(*this == monoid);
+ }
+
+ /// Returns true if higher component is considered greater when
+ /// comparing module monomials. Only relevant once actually
+ /// considering the component. This is only relevant for module
+ /// monomials.
+ bool componentsAscending() const {return isLexBaseOrder();}
+
+ /// Returns the number of variables. This is also the number of
+ /// exponents in the exponent vector of a monomial.
+ using Base::varCount;
+ //VarIndex varCount() const {return mVarCount;}
+
+
+ // *** Monomial accessors and queries
+
+ /// Returns iterator to the first exponent.
+ const_iterator begin(ConstMonoRef mono) const {
+ return ptr(mono, exponentsIndexBegin());
+ }
+
+ /// Returns iterator to one-past-the-end of the range of exponents.
+ const_iterator end(ConstMonoRef mono) const {
+ return ptr(mono, exponentsIndexEnd());
+ }
+
+ /// Returns the exponent of var in mono.
+ Exponent exponent(ConstMonoRef mono, const VarIndex var) const {
+ MATHICGB_ASSERT(var < varCount());
+ return access(mono, exponentsIndexBegin() + 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 {
+ MATHICGB_ASSERT(HasComponent);
+ return access(mono, componentIndex());
+ }
+
+ /// Returns a hash value for the monomial. These are not guaranteed
+ /// to be unique.
+ HashValue hash(ConstMonoRef mono) const {
+ MATHICGB_ASSERT(debugHashValid(mono));
+ if (StoreHash)
+ return static_cast<HashValue>(access(mono, hashIndex()));
+ else
+ return computeHash(mono);
+ }
+
+ /// Returns true if a and b are equal. Includes check for component.
+ bool equal(ConstMonoRef a, ConstMonoRef b) const {
+ for (auto i = entriesIndexBegin(); i != exponentsIndexEnd(); ++i)
+ if (access(a, i) != access(b, i))
+ return false;
+ return true;
+ }
+
+ template<class MonoidA>
+ bool equal(
+ const MonoidA& monoidA,
+ typename MonoidA::ConstMonoRef a,
+ ConstMonoRef b
+ ) const {
+ // todo: assert compatible
+ for (VarIndex var = 0; var < varCount(); ++var)
+ if (monoidA.exponent(a, var) != exponent(b, var))
+ return false;
+ return true;
+ }
+
+ /// As equal(), but optimized for the case where true is returned.
+ bool equalHintTrue(ConstMonoRef a, ConstMonoRef b) const {
+ // if a[i] != b[i] then a[i] ^ b[i] != 0, so the or of all xors is zero
+ // if and only if a equals b. This way we avoid having a branch to check
+ // equality for every iteration of the loop, which is a win in the case
+ // that none of the early-exit branches are taken - that is, when a equals
+ // b.
+ Exponent orOfXor = 0;
+ for (VarIndex i = lastExponentIndex(); i != beforeEntriesIndexBegin(); --i)
+ orOfXor |= access(a, i) ^ access(b, i);
+ MATHICGB_ASSERT((orOfXor == 0) == equal(a, b));
+ return orOfXor == 0;
+ }
+
+ bool isProductOf(
+ ConstMonoRef a,
+ ConstMonoRef b,
+ ConstMonoRef ab
+ ) const {
+ for (VarIndex i = entriesIndexBegin(); i != exponentsIndexEnd(); ++i)
+ if (access(ab, i) != access(a, i) + access(b, i))
+ return false;
+ return true;
+ }
+
+ bool isProductOfHintTrue(
+ ConstMonoRef a,
+ ConstMonoRef b,
+ ConstMonoRef ab
+ ) const {
+ // We compare more than one exponent at a time using 64 bit integers. This
+ // might go one 32 bit value at the end too far, but since that space is
+ // either a degree or a hash value that is fine --- those values will also
+ // match if the monomials are equal. This does not work for negative
+ // exponents since the overflowing bit will go into the next word.
+ // It is OK that the degree field can be negative (a field we might go
+ // into without caring about it because it shares a 64 bit field with
+ // the last exponent), because it is at the end so the overflowing
+ // bit will not interfere. For this reason we need to have a degree
+ // or a hash value stored there - otherwise two equal monomials could
+ // have different things stored next to them which would confuse this code.
+
+ // todo: ensure 8 byte alignment. Though there seem to be no ill effects
+ // for unaligned access. Performance seems to be no worse than for using
+ // 32 bit integers directly.
+
+ if (sizeof(Exponent) != 4 || (!StoreHash && !StoreOrder))
+ return isProductOf(a, b, ab);
+
+ uint64 orOfXor = 0;
+ for (VarIndex i = varCount() / 2; i != beforeEntriesIndexBegin(); --i) {
+ MATHICGB_ASSERT(access(a, i*2) >= 0);
+ MATHICGB_ASSERT(i == varCount() / 2 || access(a, i*2+1) >= 0);
+
+ uint64 A, B, AB;
+ // We have to use ::std::memcpy here because just casting to a int64 breaks
+ // the strict aliasing rule which implies undefined behavior. Both MSVC and
+ // gcc don't actually call memcpy here. MSVC is a tiny bit slower for this
+ // code than for casting while GCC seems to be exactly the same speed.
+ ::std::memcpy(&A, ptr(a, i*2), 8);
+ ::std::memcpy(&B, ptr(b, i*2), 8);
+ ::std::memcpy(&AB, ptr(ab, i*2), 8);
+ orOfXor |= AB ^ (A + B);
+ }
+ MATHICGB_ASSERT((orOfXor == 0) == isProductOf(a, b, ab));
+ return orOfXor == 0;
+ }
+
+ MATHICGB_INLINE bool isTwoProductsOfHintTrue(
+ ConstMonoRef a1,
+ ConstMonoRef a2,
+ ConstMonoRef b,
+ ConstMonoRef a1b,
+ ConstMonoRef a2b
+ ) const {
+ if (sizeof(Exponent) != 4 || (!StoreHash && !StoreOrder))
+ return (isProductOf(a1, b, a1b) && isProductOf(a2, b, a2b));
+
+ uint64 orOfXor = 0;
+ for (VarIndex i = varCount() / 2; i != beforeEntriesIndexBegin(); --i) {
+ uint64 A1, A2, B, A1B, A2B;
+ ::std::memcpy(&A1, ptr(a1, i*2), 8);
+ ::std::memcpy(&A2, ptr(a2, i*2), 8);
+ ::std::memcpy(&B, ptr(b, i*2), 8);
+ ::std::memcpy(&A1B, ptr(a1b, i*2), 8);
+ ::std::memcpy(&A2B, ptr(a2b, i*2), 8);
+ orOfXor |= (A1B ^ (A1 + B)) | (A2B ^ (A2 + B));
+ }
+ MATHICGB_ASSERT
+ ((orOfXor == 0) == (isProductOf(a1, b, a1b) && isProductOf(a2, b, a2b)));
+ return orOfXor == 0;
+ }
+
+ /// 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));
+ }
+
+ /// Returns true if all the exponents of mono are zero. In other
+ /// words, returns true if mono is the identity for multiplication
+ /// of monomials.
+ bool isIdentity(ConstMonoRef mono) const {
+ return ::std::all_of(begin(mono), end(mono), [](Exponent e) {return e == 0;});
+ }
+
+ /// Returns true if a divides b. Equal monomials divide each other.
+ bool divides(ConstMonoRef div, ConstMonoRef into) const {
+ // todo: enable this when the code works with it
+ //if (HasComponent && component(div) != component(into))
+ // return false;
+ for (auto i = exponentsIndexBegin(); i < exponentsIndexEnd(); ++i)
+ if (access(div, i) > access(into, i))
+ return false;
+ return true;
+ }
+
+ template<class MonoidA>
+ bool divides(
+ const MonoidA& monoidA,
+ typename MonoidA::ConstMonoRef a,
+ ConstMonoRef b
+ ) const {
+ // todo: fix other divisibility functions to work properly for component too.
+ MATHICGB_ASSERT(monoidA.varCount() == varCount());
+ MATHICGB_ASSERT(!MonoidA::HasComponent || HasComponent);
+ MATHICGB_ASSERT(monoidA.debugValid(a));
+ MATHICGB_ASSERT(debugValid(b));
+ // todo: enable this when the code works with it
+ //if (HasComponent && component(div) != component(into))
+ // return false;
+ //if (
+ // MonoidA::HasComponent &&
+ // HasComponent &&
+ // monoidA.component(a) != component(b)
+ //)
+ // return false;
+ for (VarIndex var = 0; var < varCount(); ++var)
+ if (monoidA.exponent(a, var) > exponent(b, var))
+ return false;
+ return true;
+ }
+
+ /// Returns true if div divides lcm(a, b).
+ bool dividesLcm(ConstMonoRef div, ConstMonoRef a, ConstMonoRef b) const {
+ MATHICGB_ASSERT(debugLcmCheck(*this, a, *this, b));
+ MATHICGB_ASSERT(debugValid(div));
+
+ for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) {
+ const auto dive = access(div, i);
+ if (access(div, i) > access(a, i) && access(div, i) > access(b, i))
+ return false;
+ }
+ return true;
+ }
+
+ template<class MonoidDiv, class MonoidA>
+ bool dividesLcm(
+ const MonoidDiv& monoidDiv,
+ typename MonoidDiv::ConstMonoRef div,
+ const MonoidA& monoidA,
+ typename MonoidA::ConstMonoRef a,
+ ConstMonoRef b
+ ) const {
+ MATHICGB_ASSERT(monoidDiv.debugLcmCheck(monoidA, a, *this, b));
+ MATHICGB_ASSERT(monoidDiv.debugValid(div));
+
+ for (VarIndex var = 0; var < varCount(); ++var) {
+ const auto e = monoidDiv.exponent(div, var);
+ if (e > monoidA.exponent(a, var) && e > exponent(b, var))
+ return false;
+ }
+ return true;
+ }
+
+ /// Returns true if lcm(a,b) == lcmAB.
+ bool isLcm(ConstMonoRef a, ConstMonoRef b, ConstMonoRef lcmAB) const {
+ MATHICGB_ASSERT(debugLcmCheck(*this, a, *this, b));
+ MATHICGB_ASSERT(debugValid(lcmAB));
+
+ for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i)
+ if (access(lcmAB, i) != ::std::max(access(a, i), access(b, i)))
+ return false;
+ return true;
+ }
+
+ template<class MonoidA, class MonoidB>
+ bool isLcm(
+ const MonoidA& monoidA,
+ typename MonoidA::ConstMonoRef a,
+ const MonoidB& monoidB,
+ typename MonoidB::ConstMonoRef b,
+ ConstMonoRef lcmAB
+ ) const {
+ MATHICGB_ASSERT(debugLcmCheck(monoidA, a, monoidB, b));
+ MATHICGB_ASSERT(debugValid(lcmAB));
+
+ if (HasComponent) {
+ if (MonoidA::HasComponent) {
+ if (monoidA.component(a) != component(lcmAB))
+ return false;
+ } else {
+ MATHICGB_ASSERT(MonoidB::HasComponent);
+ if (monoidB.component(b) != component(lcmAB))
+ return false;
+ }
+ }
+
+ for (VarIndex var = 0; var < varCount(); ++var) {
+ if (
+ ptr(lcmAB, exponentsIndexBegin())[var] !=
+ ::std::max(monoidA.exponent(a, var), monoidB.exponent(b, var))
+ )
+ return false;
+ }
+ return true;
+ }
+
+ CompareResult compare(ConstMonoRef a, ConstMonoRef b) const {
+ MATHICGB_ASSERT(debugOrderValid(a));
+ MATHICGB_ASSERT(debugOrderValid(b));
+
+ VarIndex index;
+
+ if (StoreOrder)
+ index = orderIndexEnd();
+ else {
+ // Check the degrees seperately since they are not stored.
+ auto grading = gradingCount();
+ while (grading != 0) {
+ --grading;
+ const auto cmp = degree(a, grading) - degree(b, grading);
+ if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan;
+ if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan;
+ }
+ index = exponentsIndexEnd();
+ }
+
+ // If StoreOrder is true then this first checks the degrees.
+ // Then the exponents are checked.
+ // Finally, if HasComponent is true, the component is checked.
+ while (index != entriesIndexBegin()) {
+ --index;
+ const auto cmp = access(a, index) - access(b, index);
+ if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan;
+ if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan;
+ }
+ return EqualTo;
+ }
+
+ /// Compares a to b1*b2.
+ /// @todo: Test this method. Also, is this method actually useful, or could
+ /// it just as well be replaced by a multiplication and a comparison?
+ CompareResult compare(ConstMonoRef a, ConstMonoRef b1, ConstMonoRef b2) const {
+ MATHICGB_ASSERT(debugOrderValid(a));
+ MATHICGB_ASSERT(debugOrderValid(b1));
+ MATHICGB_ASSERT(debugOrderValid(b2));
+
+ VarIndex index;
+
+ if (StoreOrder)
+ index = orderIndexEnd();
+ else {
+ // Check the degrees seperately since they are not stored.
+ auto grading = gradingCount();
+ while (grading != 0) {
+ --grading;
+ const auto cmp =
+ degree(a, grading) - (degree(b1, grading) + degree(b2, grading));
+ if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan;
+ if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan;
+ }
+ index = exponentsIndexEnd();
+ }
+
+ // If StoreOrder is true then this first checks the degrees.
+ // Then the exponents are checked.
+ // Finally, if HasComponent is true, the component is checked.
+ while (index != entriesIndexBegin()) {
+ --index;
+ const auto cmp =
+ access(a, index) - (access(b1, index) + access(b2, index));
+ if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan;
+ if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan;
+ }
+ return EqualTo;
+ }
+
+ bool lessThan(ConstMonoRef a, ConstMonoRef b) const {
+ return compare(a, b) == LessThan;
+ }
+
+ /// Returns true if gcd(a, b) == 1.
+ bool relativelyPrime(ConstMonoRef a, ConstMonoRef b) const {
+ for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i)
+ if (access(a, i) > 0 && access(b, i) > 0)
+ return false;
+ return true;
+ }
+
+ // If this method returns true for monomials a and b then it is
+ // guaranteed that multiplying a and b together will not overflow
+ // the integers in the representation.
+ bool hasAmpleCapacity(ConstMonoRef mono) const {
+ const auto halfMin = ::std::numeric_limits<Exponent>::min() / 2;
+ const auto halfMax = ::std::numeric_limits<Exponent>::max() / 2;
+ MATHICGB_ASSERT(halfMin <= 0);
+ const auto limit = ::std::min(-halfMin, halfMax);
+ const auto inRange = [&](Exponent value)
+ {return -limit <= value && value <= limit;};
+
+ for (VarIndex i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i)
+ if (!inRange(access(mono, i)))
+ return false;
+ for (VarIndex grading = 0; grading < gradingCount(); ++grading)
+ if (!inRange(degree(mono, grading)))
+ return false;
+ return true;
+ }
+
+ /// Returns the degree of mono using the most significant grading on
+ /// the monoid. This is the grading with index gradingCount() -
+ /// 1. This object must have at least one grading associated to it
+ /// before calling this method.
+ Exponent degree(ConstMonoRef mono) const {
+ MATHICGB_ASSERT(gradingCount() > 0);
+ return degree(mono, gradingCount() - 1);
+ }
+
+ /// Returns the degree of mono according to the grading with the
+ /// given index.
+ Exponent degree(ConstMonoRef mono, VarIndex grading) const {
+ MATHICGB_ASSERT(grading < gradingCount());
+ MATHICGB_ASSERT(debugOrderValid(mono));
+ if (StoreOrder)
+ return access(mono, orderIndexBegin() + grading);
+ else
+ return computeDegree(mono, grading);
+ }
+
+ /// Returns the number of gradings.
+ using Base::gradingCount;
+
+
+ // *** Monomial mutating computations
+
+ /// Copes the parameter from to the parameter to.
+ void copy(ConstMonoRef from, MonoRef to) const {
+ MATHICGB_ASSERT(debugValid(from));
+
+ ::std::copy_n(rawPtr(from), entryCount(), rawPtr(to));
+
+ MATHICGB_ASSERT(debugValid(to));
+ }
+
+ template<class MonoidFrom>
+ void copy(
+ const MonoidFrom& monoidFrom,
+ typename MonoidFrom::ConstMonoRef from,
+ MonoRef to
+ ) const {
+ // todo: extract this in checker method
+ MATHICGB_ASSERT(HasComponent == MonoidFrom::HasComponent);
+ MATHICGB_ASSERT(monoidFrom.debugValid(from));
+ MATHICGB_ASSERT(monoidFrom.varCount() == varCount());
+ MATHICGB_ASSERT
+ ((::std::is_same<Exponent, typename MonoidFrom::Exponent>::value));
+
+ if (HasComponent)
+ access(to, componentIndex()) = monoidFrom.component(from);
+ const auto expsTo = ptr(to, exponentsIndexBegin());
+ for (VarIndex var = 0; var < varCount(); ++var)
+ expsTo[var] = monoidFrom.exponent(from, var);
+ if (StoreOrder) {
+ const auto degrees = ptr(to, orderIndexBegin());
+ for (VarIndex grading = 0; grading < gradingCount(); ++grading)
+ degrees[grading] = monoidFrom.degree(from, grading);
+ }
+ if (StoreHash)
+ access(to, hashIndex()) = monoidFrom.hash(from);
+
+ MATHICGB_ASSERT(debugValid(to));
+ // todo: check equal
+ }
+
+ /// Set the exponent of var to newExponent in mono.
+ void setExponent(
+ const VarIndex var,
+ const Exponent newExponent,
+ MonoRef mono
+ ) const {
+ MATHICGB_ASSERT(var < varCount());
+
+ auto& exponent = access(mono, exponentsIndexBegin() + var);
+ const auto oldExponent = exponent;
+ exponent = newExponent;
+
+ updateOrderData(var, oldExponent, newExponent, mono);
+ updateHashExponent(var, oldExponent, newExponent, mono);
+
+ MATHICGB_ASSERT(debugValid(mono));
+ }
+
+ /// Sets all the exponents of mono. exponents must point to an array
+ /// of size varCount().
+ void setExponents(const Exponent* exponents, MonoRef mono) const {
+ MATHICGB_ASSERT(exponents != 0);
+
+ if (HasComponent)
+ access(mono, componentIndex()) = 0;
+ ::std::copy_n(exponents, varCount(), ptr(mono, exponentsIndexBegin()));
+ setOrderData(mono);
+ setHash(mono);
+
+ MATHICGB_ASSERT(debugValid(mono));
+ }
+
+ /// Sets mono to 1, which is the identity for multiplication.
+ void setIdentity(MonoRef mono) const {
+ ::std::fill_n(rawPtr(mono), entryCount(), static_cast<Exponent>(0));
+
+ MATHICGB_ASSERT(debugValid(mono));
+ MATHICGB_ASSERT(isIdentity(mono));
+ }
+
+ /// Sets the component of mono to newComponent.
+ void setComponent(Component newComponent, MonoRef mono) const {
+ MATHICGB_ASSERT(HasComponent);
+
+ auto& component = access(mono, componentIndex());
+ const auto oldComponent = component;
+ component = newComponent;
+ updateHashComponent(oldComponent, newComponent, mono);
+ updateOrderComponent(newComponent, mono);
+
+ MATHICGB_ASSERT(debugValid(mono));
+ }
+
+ /// Sets prod to a*b.
+ void multiply(ConstMonoRef a, ConstMonoRef b, MonoRef prod) const {
+ MATHICGB_ASSERT(debugValid(a));
+ MATHICGB_ASSERT(debugValid(b));
+
+ for (auto i = lastEntryIndex(); i != beforeEntriesIndexBegin(); --i)
+ access(prod, i) = access(a, i) + access(b, i);
+
+ MATHICGB_ASSERT(debugValid(prod));
+ }
+
+ /// Sets prod to a*prod.
+ void multiplyInPlace(ConstMonoRef a, MonoRef prod) const {
+ MATHICGB_ASSERT(debugValid(a));
+ MATHICGB_ASSERT(debugValid(prod));
+
+ for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i)
+ access(prod, i) += access(a, i);
+
+ MATHICGB_ASSERT(debugValid(prod));
+ }
+
+ /// Sets quo to num/by. by must divide num.
+ void divide(ConstMonoRef by, ConstMonoRef num, MonoRef quo) const {
+ MATHICGB_ASSERT(divides(by, num));
+ MATHICGB_ASSERT(debugValid(num));
+ MATHICGB_ASSERT(debugValid(by));
+
+ for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i)
+ access(quo, i) = access(num, i) - access(by, i);
+
+ MATHICGB_ASSERT(debugValid(quo));
+ }
+
+ /// Sets num to num/by. by must divide num.
+ void divideInPlace(ConstMonoRef by, MonoRef num) const {
+ MATHICGB_ASSERT(divides(by, num));
+ MATHICGB_ASSERT(debugValid(by));
+ MATHICGB_ASSERT(debugValid(num));
+
+ for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i)
+ access(num, i) -= access(by, i);
+
+ MATHICGB_ASSERT(debugValid(num));
+ }
+
+ /// Sets quo to num/by. If by does not divide num then quo will have
+ /// negative exponents.
+ void divideToNegative(ConstMonoRef by, ConstMonoRef num, MonoRef quo) const {
+ MATHICGB_ASSERT(debugValid(num));
+ MATHICGB_ASSERT(debugValid(by));
+ MATHICGB_ASSERT(
+ !HasComponent ||
+ component(by) == 0 ||
+ component(by) == component(num)
+ );
+
+ for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i)
+ access(quo, i) = access(num, i) - access(by, i);
+
+ MATHICGB_ASSERT(debugValid(quo));
+ }
+
+ /// Set out to (colonBy : colonNum) * mult.
+ /// @todo: test
+ void colonMultiply(
+ ConstMonoRef colonBy,
+ ConstMonoRef colonNum,
+ ConstMonoRef mult,
+ MonoRef out
+ ) const {
+ // todo: consider what happens with exponent overflow here
+ if (HasComponent) {
+ MATHICGB_ASSERT(component(colonBy) == component(colonNum));
+ access(out, componentIndex()) = component(mult);
+ }
+ for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) {
+ const auto colon = access(colonNum, i) - access(colonBy, i);
+ auto result = access(mult, i);
+ if (colon > 0)
+ result += colon;
+ access(out, i) = result;
+ }
+ setOrderData(out);
+ setHash(out);
+ MATHICGB_ASSERT(debugValid(out));
+ }
+
+ /// Returns the number of variables that divide mono.
+ /// @todo: test
+ VarIndex sizeOfSupport(ConstMonoRef mono) const {
+ VarIndex count = 0;
+ for (VarIndex var = 0; var < varCount(); ++var)
+ if (exponent(mono, var) != 0)
+ ++count;
+ return count;
+ }
+
+ /// Sets aColonB to a:b and bColonA to b:a.
+ void colons(
+ ConstMonoRef a,
+ ConstMonoRef b,
+ MonoRef aColonB,
+ MonoRef bColonA
+ ) const {
+ MATHICGB_ASSERT(debugValid(a));
+ MATHICGB_ASSERT(debugValid(b));
+
+ if (HasComponent) {
+ MATHICGB_ASSERT(component(a) == component(b));
+ access(aColonB, componentIndex()) = 0;
+ access(bColonA, componentIndex()) = 0;
+ }
+
+ for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) {
+ const auto ae = access(a, i);
+ const auto be = access(b, i);
+ const auto max = ::std::max(ae, be);
+ access(aColonB, i) = max - be;
+ access(bColonA, i) = max - ae;
+ }
+ setOrderData(aColonB);
+ setHash(aColonB);
+ setOrderData(bColonA);
+ setHash(bColonA);
+
+ MATHICGB_ASSERT(debugValid(aColonB));
+ MATHICGB_ASSERT(debugValid(bColonA));
+ }
+
+ /// Sets lcmAB to the lcm of a and b.
+ void lcm(ConstMonoRef a, ConstMonoRef b, MonoRef lcmAB) const {
+ if (HasComponent) {
+ MATHICGB_ASSERT(component(a) == component(b));
+ access(lcmAB, componentIndex()) = access(a, componentIndex());
+ }
+ for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i)
+ access(lcmAB, i) = ::std::max(access(a, i), access(b, i));
+ setOrderData(lcmAB);
+ setHash(lcmAB);
+
+ MATHICGB_ASSERT(debugValid(lcmAB));
+ MATHICGB_ASSERT(isLcm(a, b, lcmAB));
+ }
+
+ template<class MonoidA, class MonoidB>
+ void lcm(
+ const MonoidA& monoidA,
+ typename MonoidA::ConstMonoRef a,
+ const MonoidB& monoidB,
+ typename MonoidB::ConstMonoRef b,
+ MonoRef lcmAB
+ ) const {
+ MATHICGB_ASSERT(debugLcmCheck(monoidA, a, monoidB, b));
+
+ if (HasComponent) {
+ access(lcmAB, componentIndex()) =
+ MonoidA::HasComponent ? monoidA.component(a) : monoidB.component(b);
+ }
+
+ for (VarIndex var = 0; var < varCount(); ++var) {
+ ptr(lcmAB, exponentsIndexBegin())[var] =
+ ::std::max(monoidA.exponent(a, var), monoidB.exponent(b, var));
+ }
+
+ setOrderData(lcmAB);
+ setHash(lcmAB);
+
+ MATHICGB_ASSERT(debugValid(lcmAB));
+ MATHICGB_ASSERT(isLcm(monoidA, a, monoidB, b, lcmAB));
+ }
+
+ Mono alloc() const {return mPool.alloc();}
+ void free(Mono&& mono) const {mPool.free(::std::move(mono));}
+ void freeRaw(MonoRef mono) const {mPool.freeRaw(mono);}
+ bool fromPool(ConstMonoRef mono) const {mPool.fromPool(mono);}
+
+ /// Parses a monomial out of a string. Valid examples: 1 abc a2bc
+ /// aA. Variable names are case sensitive. Whitespace terminates the
+ /// parse as does any other character that is not a letter or a
+ /// digit. The monomial must not include a coefficient, not even 1,
+ /// except for the special case of a 1 on its own. An input like 1a
+ /// will be parsed as two separate monomials. A suffix like <2> puts
+ /// the monomial in component 2, so a5<2> is a^5e_2. The default
+ /// component is 0.
+ void parseM2(::std::istream& in, MonoRef mono) const;
+
+ // Inverse of parseM2().
+ void printM2(ConstMonoRef mono, ::std::ostream& out) const;
+
+ // As printM2, but returns a string.
+ ::std::string toString(ConstMonoRef mono) const {
+ ::std::ostringstream out;
+ printM2(mono, out);
+ return out.str();
+ }
+
+
+ // *** Classes for holding and referring to monomials
+
+ class ConstMonoPtr {
+ public:
+ ConstMonoPtr(): mMono(0) {}
+ ConstMonoPtr(const ConstMonoPtr& mono): mMono(rawPtr(mono)) {}
+
+ ConstMonoPtr operator=(const ConstMonoPtr& mono) {
+ mMono = mono.mMono;
+ return *this;
+ }
+
+ ConstMonoRef operator*() const {return *this;}
+
+ bool isNull() const {return mMono == 0;}
+ void toNull() {mMono = 0;}
+
+ private:
+ friend class MonoMonoid;
+
+ const Exponent* internalRawPtr() const {return mMono;}
+ ConstMonoPtr(const Exponent* mono): mMono(mono) {}
+
+ const Exponent* mMono;
+ };
+
+ class MonoPtr {
+ public:
+ MonoPtr(): mMono(0) {}
+ MonoPtr(const MonoPtr& mono): mMono(mono.mMono) {}
+
+ MonoPtr operator=(const MonoPtr& mono) {
+ mMono = mono.mMono;
+ return *this;
+ }
+
+ MonoRef operator*() const {return *this;}
+
+ bool isNull() const {return mMono == 0;}
+ void toNull() {mMono = 0;}
+
+ operator ConstMonoPtr() const {return ConstMonoPtr(mMono);}
+
+ private:
+ friend class MonoMonoid;
+ friend class PolyRing; // todo: remove
+ friend class Poly; // todo: remove
+
+ Exponent* internalRawPtr() const {return mMono;}
+ MonoPtr(Exponent* mono): mMono(mono) {}
+
+ Exponent* mMono;
+ };
+
+ class Mono : public NonCopyable<Mono> {
+ public:
+ Mono(): mMono(), mPool(0) {}
+
+ /// Passes ownership of the resources of mono to this object. Mono must
+ /// have been allocated from pool and it must have no other owner.
+ /// In particular, it must have been release()'ed from its original
+ /// owner.
+ Mono(MonoRef mono, MonoPool& pool):
+ mMono(mono.ptr()), mPool(&pool)
+ {
+ MATHICGB_ASSERT(pool.fromPool(mono));
+ }
+
+ Mono(Mono&& mono): mMono(mono.mMono), mPool(mono.mPool) {
+ mono.mMono.toNull();
+ mono.mPool = 0;
+ }
+
+ ~Mono() {toNull();}
+
+ void operator=(Mono&& mono) {
+ toNull();
+
+ mMono = mono.mMono;
+ mono.mMono.toNull();
+
+ mPool = mono.mPool;
+ mono.mPool = 0;
+ }
+
+ /// Sets this object to null but does NOT free the resources previously
+ /// held by this object. The returned MonoPtr points to the resources
+ /// that this object had prior to calling release(). If this object was
+ /// already null then the returned MonoPtr is also null.
+ MonoPtr release() {
+ const auto oldPtr = ptr();
+ mMono = 0;
+ mPool = 0;
+ return oldPtr;
+ }
+
+ bool isNull() const {return mMono.isNull();}
+ void toNull() {mPool->free(::std::move(*this));}
+
+ MonoPtr ptr() const {return mMono;}
+
+ operator MonoRef() const {
+ MATHICGB_ASSERT(!isNull());
+ return *mMono;
+ }
+
+ private:
+ friend class MonoMonoid;
+
+ Exponent* internalRawPtr() const {return rawPtr(mMono);}
+
+ MonoPtr mMono;
+ MonoPool* mPool;
+ };
+
+ class MonoRef {
+ public:
+ MonoRef(const MonoRef& mono): mMono(mono.ptr()) {}
+
+ MonoPtr ptr() const {return mMono;}
+
+ operator ConstMonoRef() const {return *static_cast<ConstMonoPtr>(mMono);}
+
+ private:
+ void operator=(const MonoRef&); // not available
+ friend class MonoMonoid;
+
+ MonoRef(MonoPtr mono): mMono(mono) {}
+ Exponent* internalRawPtr() const {return rawPtr(mMono);}
+
+ const MonoPtr mMono;
+ };
+
+ class ConstMonoRef {
+ public:
+ ConstMonoRef(const ConstMonoRef& mono): mMono(mono.ptr()) {}
+ ConstMonoRef(const Mono& mono): mMono(mono.ptr()) {
+ MATHICGB_ASSERT(!mono.isNull());
+ }
+
+ ConstMonoPtr ptr() const {return mMono;}
+
+ private:
+ void operator=(const MonoRef&); // not available
+ friend class MonoMonoid;
+
+ ConstMonoRef(ConstMonoPtr mono): mMono(mono) {}
+ const Exponent* internalRawPtr() const {return rawPtr(mMono);}
+
+ const ConstMonoPtr mMono;
+ };
+
+
+ // *** Classes that provide memory resources for monomials
+
+ class MonoPool : public NonCopyable<MonoPool> {
+ public:
+ MonoPool(const MonoMonoid& monoid):
+ mMonoid(monoid),
+ mPool(sizeof(Exponent) * mMonoid.entryCount())
+ {}
+
+ MonoPool(MonoPool&& pool):
+ mMonoid(pool.mMonoid),
+ mPool(::std::move(pool.mPool))
+ {}
+
+ Mono alloc() {
+ const auto ptr = static_cast<Exponent*>(mPool.alloc());
+ Mono mono(*MonoPtr(ptr), *this);
+ monoid().setIdentity(mono);
+ return mono;
+ }
+
+ void free(Mono&& mono) {
+ if (mono.isNull())
+ return;
+ freeRaw(mono);
+ mono.mMono = 0;
+ mono.mPool = 0;
+ }
+ void freeRaw(MonoRef mono) {mPool.free(rawPtr(mono));}
+
+ const MonoMonoid& monoid() const {return mMonoid;}
+
+ bool fromPool(ConstMonoRef mono) const {
+ return mPool.fromPool(rawPtr(mono));
+ }
+
+ private:
+ const MonoMonoid& mMonoid;
+ memt::BufferPool mPool;
+ };
+
+ class MonoVector {
+ private:
+ typedef ::std::vector<Exponent> RawVector;
+
+ public:
+ /// Class for iterating through the monomials in a MonoVector.
+ ///
+ /// There is no operator->() since MonoRef does not have any
+ /// relevant methods to call. Implement it if you need it.
+ ///
+ /// There are no postfix increment operator as prefix is
+ /// better. Add it if you y need it (you probably do not).
+ ///
+ /// We could make this a random access iterator, but that would
+ /// make it tricky to support variable-sized exponent vectors
+ /// (e.g. sparse) in future and so far we have not needed random
+ /// access.
+ class const_iterator {
+ public:
+ typedef ::std::forward_iterator_tag iterator_category;
+ typedef ConstMonoPtr value_type;
+
+ const_iterator(): mIt(), mEntriesPerMono(0) {}
+ const_iterator(const const_iterator& it):
+ mIt(it.mIt), mEntriesPerMono(it.mEntriesPerMono) {}
+
+ bool operator==(const const_iterator& it) const {return mIt == it.mIt;}
+ bool operator!=(const const_iterator& it) const {return mIt != it.mIt;}
+
+ ConstMonoRef operator*() {
+ MATHICGB_ASSERT(debugValid());
+ return *ConstMonoPtr(&*mIt);
+ }
+
+ const_iterator operator++() {
+ MATHICGB_ASSERT(debugValid());
+ mIt += mEntriesPerMono;
+ return *this;
+ }
+
+ private:
+ friend class MonoVector;
+ bool debugValid() {return mEntriesPerMono > 0;}
+
+ const_iterator(
+ typename RawVector::const_iterator it,
+ size_t entryCount
+ ): mIt(it), mEntriesPerMono(entryCount) {}
+
+ typename RawVector::const_iterator mIt;
+ size_t mEntriesPerMono;
+ };
+
+ // ** Constructors and assignment
+ MonoVector(const MonoMonoid& monoid): mMonoid(monoid) {}
+ MonoVector(const MonoVector& v): mMonos(v.mMonos), mMonoid(v.monoid()) {}
+ MonoVector(MonoVector&& v):
+ mMonos(::std::move(v.mMonos)), mMonoid(v.monoid()) {}
+
+ MonoVector& operator=(const MonoVector& v) {
+ MATHICGB_ASSERT(monoid() == v.monoid());
+ mMonos = v.mMonos;
+ return *this;
+ }
+
+ MonoVector& operator=(MonoVector&& v) {
+ MATHICGB_ASSERT(monoid() == v.monoid());
+ mMonos = ::std::move(v.mMonos);
+ return *this;
+ }
+
+ // ** Iterators
+ const_iterator begin() const {
+ return const_iterator(mMonos.begin(), mMonoid.entryCount());
+ }
+
+ const_iterator end() const {
+ return const_iterator(mMonos.end(), mMonoid.entryCount());
+ }
+
+ const_iterator cbegin() const {return begin();}
+ const_iterator cend() const {return end();}
+
+ // ** Capacity
+ size_t size() const {return mMonos.size() / monoid().entryCount();}
+ bool empty() const {return mMonos.empty();}
+
+ // ** Element access
+ ConstMonoRef front() const {
+ MATHICGB_ASSERT(!empty());
+ return *begin();
+ }
+
+ MonoRef back() {
+ MATHICGB_ASSERT(!empty());
+ const auto offset = mMonos.size() - monoid().entryCount();
+ return *MonoPtr(mMonos.data() + offset);
+ }
+
+ ConstMonoRef back() const {
+ MATHICGB_ASSERT(!empty());
+ const auto offset = mMonos.size() - monoid().entryCount();
+ return *ConstMonoPtr(mMonos.data() + offset);
+ }
+
+ // ** Modifiers
+
+ void reserve(size_t count) {
+ mMonos.reserve(count * monoid().entryCount());
+ }
+
+ /// Appends the identity.
+ void push_back() {
+ const auto offset = mMonos.size();
+ mMonos.resize(offset + monoid().entryCount());
+ MATHICGB_ASSERT(monoid().isIdentity(back()));
+ MATHICGB_ASSERT(monoid().debugValid(back()));
+ }
+
+ 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));
+ MATHICGB_ASSERT(monoid().debugValid(back()));
+ }
+
+ template<class Monoid>
+ void push_back(
+ const Monoid& monoidMono,
+ typename Monoid::ConstMonoRef mono
+ ) {
+ MATHICGB_ASSERT(monoidMono.debugValid(mono));
+ const auto offset = mMonos.size();
+ mMonos.resize(offset + monoid().entryCount());
+ monoid().copy(monoidMono, mono, *MonoPtr(mMonos.data() + offset));
+ MATHICGB_ASSERT(monoid().debugValid(back()));
+ }
+
+ void swap(MonoVector& v) {
+ MATHICGB_ASSERT(&monoid() == &v.monoid());
+ mMonos.swap(v.mMonos);
+ }
+
+ void clear() {mMonos.clear();}
+
+ // ** Relational operators
+ bool operator==(const MonoVector& v) const {
+ MATHICGB_ASSERT(monoid() == v.monoid());
+ return mMonos == v.mMonos;
+ }
+ bool operator!=(const MonoVector& v) const {return !(*this == v);}
+
+ // ** Other
+ size_t memoryBytesUsed() const {
+ return mMonos.capacity() * sizeof(mMonos[0]);
+ }
+
+ /// As parseM2 on monoid, but accepts a non-empty space-separated
+ /// list of monomials. The monomials are appended to the end of
+ /// the vector.
+ void parseM2(::std::istream& in) {
+ while(true) {
+ push_back();
+ monoid().parseM2(in, back());
+ if (in.peek() != ' ')
+ break;
+ in.get();
+ }
+ }
+
+ /// The inverse of parseM2.
+ void printM2(::std::ostream& out) const {
+ for (auto it = begin(); it != end(); ++it) {
+ if (it != begin())
+ out << ' ';
+ monoid().printM2(*it, out);
+ }
+ out << '\n';
+ }
+
+ const MonoMonoid& monoid() const {return mMonoid;}
+
+ private:
+ RawVector mMonos;
+ const MonoMonoid& mMonoid;
+ };
+
+
+private:
+ void operator=(MonoMonoid&); // not available
+
+ // Grants access to other template instantiations.
+ template<class E2, bool HC2, bool SH2, bool SO2>
+ friend class MonoMonoid;
+
+ // The main point here is to grant access to rawPtr().
+ friend class Mono;
+ friend class MonoRef;
+ friend class ConstMonoRef;
+ friend class MonoPtr;
+ friend class ConstMonoPtr;
+ friend class MonoVector;
+ friend class MonoPool;
+
+ typedef typename Base::Gradings Gradings;
+
+ bool debugAssertValid() const {
+#ifdef MATHICGB_DEBUG
+ // ** Order checks
+ MATHICGB_ASSERT(orderIndexBegin() == exponentsIndexEnd());
+ const auto storedDegrees = StoreOrder * gradingCount();
+ MATHICGB_ASSERT(orderIndexEnd() == orderIndexBegin() + storedDegrees);
+ MATHICGB_ASSERT(orderIndexEnd() <= entryCount());
+ if (orderIndexEnd() + StoreHash == 0) {
+ MATHICGB_ASSERT(entryCount() == 1);
+ } else {
+ MATHICGB_ASSERT(entryCount() == orderIndexEnd() + StoreHash);
+ }
+
+ MATHICGB_ASSERT(isLexBaseOrder() || varCount() == 0 || gradingCount() >= 1);
+
+ MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount());
+ if (orderIsTotalDegreeRevLex()) {
+ MATHICGB_ASSERT(!isLexBaseOrder());
+ MATHICGB_ASSERT(gradingCount() == 1);
+ }
+
+ if (componentGradingIndex() != Order::ComponentAfterBaseOrder) {
+ MATHICGB_ASSERT(componentGradingIndex() < gradingCount());
+ for (VarIndex var = 0; var < varCount(); ++var) {
+ const auto index = gradingsIndex(componentGradingIndex(), var);
+ MATHICGB_ASSERT(gradings()[index] == 0);
+ }
+ }
+
+ // ** Hash checks
+ if (StoreHash) {
+ MATHICGB_ASSERT(hashIndex() < entryCount());
+ MATHICGB_ASSERT(hashIndex() == orderIndexEnd());
+ }
+ MATHICGB_ASSERT(hashCoefficients().size() == varCount());
+#endif
+ return true;
+ }
+
+ bool debugValid(ConstMonoRef mono) const {
+ MATHICGB_ASSERT(debugOrderValid(mono));
+ MATHICGB_ASSERT(debugHashValid(mono));
+ return true;
+ }
+
+ template<class MonoidA, class MonoidB>
+ bool debugLcmCheck(
+ const MonoidA& monoidA,
+ typename MonoidA::ConstMonoRef a,
+ const MonoidB& monoidB,
+ typename MonoidB::ConstMonoRef b
+ ) const {
+ MATHICGB_ASSERT(monoidA.varCount() == varCount());
+ MATHICGB_ASSERT(monoidB.varCount() == varCount());
+ MATHICGB_ASSERT
+ ((::std::is_same<Exponent, typename MonoidA::Exponent>::value));
+ MATHICGB_ASSERT
+ ((::std::is_same<Exponent, typename MonoidB::Exponent>::value));
+ MATHICGB_ASSERT
+ (HasComponent == (MonoidA::HasComponent || MonoidB::HasComponent));
+ MATHICGB_ASSERT(monoidA.debugValid(a));
+ MATHICGB_ASSERT(monoidB.debugValid(b));
+ MATHICGB_ASSERT(
+ !HasComponent ||
+ !MonoidA::HasComponent ||
+ !MonoidB::HasComponent ||
+ monoidA.component(a) == monoidB.component(b)
+ );
+
+ return true;
+ }
+
+ // *** Accessing fields of a monomial
+ template<class M>
+ static auto rawPtr(M&& m) -> decltype(m.internalRawPtr()) {
+ return m.internalRawPtr();
+ }
+
+ Exponent* ptr(MonoRef& m, const VarIndex index) const {
+ MATHICGB_ASSERT(index <= entryCount());
+ return rawPtr(m) + index;
+ }
+
+ const Exponent* ptr(ConstMonoRef& m, const VarIndex index) const {
+ MATHICGB_ASSERT(index <= entryCount());
+ return rawPtr(m) + index;
+ }
+
+ Exponent& access(MonoRef& m, const VarIndex index) const {
+ MATHICGB_ASSERT(index < entryCount());
+ return rawPtr(m)[index];
+ }
+
+ const Exponent& access(ConstMonoRef& m, const VarIndex index) const {
+ MATHICGB_ASSERT(index < entryCount());
+ return rawPtr(m)[index];
+ }
+
+ // *** Implementation of monomial ordering
+
+ using Base::gradingsOppositeRowIndex;
+ using Base::gradingsIndex;
+ using Base::reverseGradings;
+ using Base::negateGradings;
+
+ bool debugOrderValid(ConstMonoRef mono) const {
+#ifdef MATHICGB_DEBUG
+ if (!StoreOrder)
+ return true;
+ // Check the order data of mono
+ const auto degrees = ptr(mono, orderIndexBegin());
+ for (VarIndex grading = 0; grading < gradingCount(); ++grading) {
+ MATHICGB_ASSERT(degrees[grading] == computeDegree(mono, grading));
+ }
+#endif
+ return true;
+ }
+
+ void setOrderData(MonoRef mono) const {
+ if (!StoreOrder)
+ return;
+
+ const auto degrees = ptr(mono, orderIndexBegin());
+ for (VarIndex grading = 0; grading < gradingCount(); ++grading)
+ degrees[grading] = computeDegree(mono, grading);
+ MATHICGB_ASSERT(debugOrderValid(mono));
+ }
+
+ void updateOrderData(
+ const VarIndex var,
+ const Exponent oldExponent,
+ const Exponent newExponent,
+ MonoRef mono
+ ) const {
+ if (!StoreOrder)
+ return;
+
+ MATHICGB_ASSERT(var < varCount());
+ if (orderIsTotalDegreeRevLex())
+ rawPtr(mono)[orderIndexBegin()] -= newExponent - oldExponent;
+ else {
+ MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount());
+ const auto degrees = ptr(mono, orderIndexBegin());
+ for (VarIndex grading = 0; grading < gradingCount(); ++grading) {
+ const auto index = gradingsIndex(grading, var);
+ degrees[grading] += gradings()[index] * ( newExponent - oldExponent);
+ }
+ }
+ MATHICGB_ASSERT(debugOrderValid(mono));
+ }
+
+ void updateOrderComponent(const VarIndex newComponent, MonoRef mono) const {
+ if (componentGradingIndex() != Order::ComponentAfterBaseOrder)
+ ptr(mono, orderIndexBegin())[componentGradingIndex()] = newComponent;
+ }
+
+ Exponent computeDegree(ConstMonoRef mono, VarIndex grading) const {
+ MATHICGB_ASSERT(grading < gradingCount());
+
+ Exponent degree = 0;
+ if (orderIsTotalDegreeRevLex()) {
+ MATHICGB_ASSERT(grading == 0);
+ for (auto var = 0; var < varCount(); ++var)
+ degree -= exponent(mono, var);
+ } else if (HasComponent && componentGradingIndex() == grading)
+ return component(mono);
+ else {
+ MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount());
+ for (auto var = 0; var < varCount(); ++var) {
+ const auto index = gradingsIndex(grading, var);
+ degree += exponent(mono, var) * gradings()[index];
+ }
+ }
+ return degree;
+ }
+
+
+ // *** Implementation of hash value computation
+
+ bool debugHashValid(ConstMonoRef mono) const {
+ if (!StoreHash)
+ return true;
+
+ // We cannot call hash() here since it calls this method.
+ // todo: we cannot make this check right now because the legacy
+ // integration with PolyRing can create monomials with unset hash.
+ // MATHICGB_ASSERT(rawPtr(mono)[hashIndex()] == computeHash(mono));
+ return true;
+ }
+
+ HashValue computeHash(ConstMonoRef mono) const {
+ HashValue hash = HasComponent ? component(mono) : 0;
+ for (VarIndex var = 0; var < varCount(); ++var) {
+ hash +=
+ static_cast<HashValue>(exponent(mono, var)) * hashCoefficients()[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 {
+ if (!StoreHash)
+ return;
+ rawPtr(mono)[hashIndex()] = computeHash(mono);
+ MATHICGB_ASSERT(debugHashValid(mono));
+ }
+
+ void updateHashComponent(
+ const Exponent oldComponent,
+ const Exponent newComponent,
+ MonoRef mono
+ ) const {
+ if (!StoreHash)
+ return;
+ rawPtr(mono)[hashIndex()] += newComponent - oldComponent;
+ MATHICGB_ASSERT(debugHashValid(mono));
+ }
+
+ void updateHashExponent(
+ const VarIndex var,
+ const Exponent oldExponent,
+ const Exponent newExponent,
+ MonoRef mono
+ ) const {
+ if (!StoreHash)
+ return;
+ MATHICGB_ASSERT(var < varCount());
+ rawPtr(mono)[hashIndex()] +=
+ (newExponent - oldExponent) * hashCoefficients()[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 data than the exponents, so
+ /// this number can be larger than varCount().
+ using Base::entryCount;
+ //size_t entryCount() const {return mEntryCount;}
+
+ VarIndex componentIndex() const {
+ //static_assert(HasComponent, "");
+ return 0;
+ }
+
+ VarIndex exponentsIndexBegin() const {return HasComponent;}
+ VarIndex exponentsIndexEnd() const {return exponentsIndexBegin() + varCount();}
+ VarIndex lastExponentIndex() const {return exponentsIndexEnd() - 1;}
+
+ using Base::orderIndexBegin;
+ using Base::orderIndexEnd;
+ using Base::hashIndex;
+ using Base::orderIsTotalDegreeRevLex;
+ using Base::gradings;
+ using Base::isLexBaseOrder;
+ using Base::componentGradingIndex;
+
+ VarIndex entriesIndexBegin() const {return 0;}
+ VarIndex entriesIndexEnd() const {return entryCount();}
+ VarIndex beforeEntriesIndexBegin() const {return entriesIndexBegin() - 1;}
+ VarIndex lastEntryIndex() const {return entriesIndexEnd() - 1;}
+
+ using Base::hashCoefficients;
+
+ mutable MonoPool mPool;
+};
+
+namespace MonoMonoidHelper {
+ /// ostream and istream handle characters differently from other
+ /// integers. Use unchar to cast chars to a different type that get
+ /// handled as other integers do.
+ template<class T>
+ struct unchar {typedef int type;};
+
+ // Yes: char, signed char and unsigned char are 3 distinct types.
+ template<>
+ struct unchar<char> {typedef short type;};
+ template<>
+ struct unchar<signed char> {typedef short type;};
+ template<>
+ struct unchar<unsigned char> {typedef unsigned short type;};
+}
+
+template<class E, bool HC, bool SH, bool SO>
+auto MonoMonoid<E, HC, SH, SO>::readMonoid(::std::istream& in) ->
+ ::std::pair<MonoMonoid, ::std::pair<bool, bool>>
+{
+ using MonoMonoidHelper::unchar;
+ VarIndex varCount;
+ in >> varCount;
+
+ bool doSchreyer = false;
+ bool lexBaseOrder = false;
+ ::std::string str;
+ char c;
+ in >> c;
+ in.unget();
+ if (!::std::isdigit(c)) {
+ ::std::string str;
+ in >> str;
+ if (str == "schreyer") {
+ doSchreyer = true;
+ in >> str;
+ }
+
+ if (str == "revlex")
+ lexBaseOrder = false;
+ else if (str == "lex")
+ lexBaseOrder = true;
+ else
+ mathic::reportError("Expected lex or revlex but read \"" + str + "\".");
+ }
+
+ VarIndex gradingCount;
+ in >> gradingCount;
+
+ Gradings gradings(static_cast<size_t>(varCount) * gradingCount);
+ bool componentsAscendingDesired = true;
+ auto componentCompareIndex = Order::ComponentAfterBaseOrder;
+ size_t w = 0;
+ for (VarIndex grading = 0; grading < gradingCount; ++grading) {
+ char c;
+ in >> c;
+ in.unget();
+ if (!::std::isdigit(c)) {
+ ::std::string str;
+ in >> str;
+
+ if (str == "component")
+ componentsAscendingDesired = true;
+ else if (str == "revcomponent")
+ componentsAscendingDesired = false;
+ else
+ mathic::reportError
+ ("Expected component or revcomponent but read \"" + str + "\".");
+ if (!HasComponent)
+ mathic::reportError
+ ("Cannot specify component comparison for non-modules.");
+ if (componentCompareIndex != Order::ComponentAfterBaseOrder)
+ mathic::reportError("Component must be considered at most once.");
+ componentCompareIndex = grading;
+ w += varCount;
+ } else {
+ for (VarIndex i = 0; i < varCount; ++i, ++w) {
+ typename unchar<Exponent>::type e;
+ in >> e;
+ gradings[w] = static_cast<Exponent>(e);
+ }
+ }
+ }
+ MATHICGB_ASSERT(w == gradings.size());
+
+ in >> c;
+ in.unget();
+ if (c == '_') {
+ in >> str;
+
+ if (str == "_revlex")
+ lexBaseOrder = false;
+ else if (str == "_lex")
+ lexBaseOrder = true;
+ else
+ mathic::reportError("Expected _lex or _revlex but read \"" + str + "\".");
+
+ in >> c;
+ in.unget();
+ if (!::std::isdigit(c)) {
+ in >> str;
+ if (str == "component")
+ componentsAscendingDesired = true;
+ else if (str == "revcomponent")
+ componentsAscendingDesired = false;
+ else
+ mathic::reportError
+ ("Expected component or revcomponent but read \"" + str + "\".");
+ }
+ }
+
+ Order order(
+ varCount,
+ ::std::move(gradings),
+ lexBaseOrder ? Order::LexBaseOrder : Order::RevLexBaseOrder,
+ componentCompareIndex
+ );
+ return ::std::make_pair(
+ MonoMonoid(order),
+ ::std::make_pair(componentsAscendingDesired, doSchreyer)
+ );
+}
+
+template<class E, bool HC, bool SH, bool SO>
+void MonoMonoid<E, HC, SH, SO>::printMonoid(
+ const bool componentsAscendingDesired,
+ ::std::ostream& out
+) const {
+ using MonoMonoidHelper::unchar;
+ typedef typename unchar<Exponent>::type UncharredExponent;
+
+ out << varCount() << '\n'
+ << (isLexBaseOrder() ? "lex" : "revlex")
+ << ' ' << gradingCount() << '\n';
+ MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount());
+ for (VarIndex grading = 0; grading < gradingCount(); ++grading) {
+ if (
+ HasComponent &&
+ grading == gradingCount() - 1 - componentGradingIndex()
+ ) {
+ out << (componentsAscendingDesired ? " component\n" : " revcomponent\n");
+ continue;
+ }
+
+ for (VarIndex var = 0; var < varCount(); ++var) {
+ auto w = gradings()[gradingsOppositeRowIndex(grading, var)];
+ if (!isLexBaseOrder())
+ w = -w;
+ out << ' ' << static_cast<UncharredExponent>(w);
+ }
+ out << '\n';
+ }
+}
+
+template<class E, bool HC, bool SH, bool SO>
+void MonoMonoid<E, HC, SH, SO>::parseM2(::std::istream& in, MonoRef mono) const {
+ using MonoMonoidHelper::unchar;
+ // todo: signal error on exponent overflow
+
+ setIdentity(mono);
+
+ bool sawSome = false;
+ while (true) {
+ const char next = in.peek();
+ if (!sawSome && next == '1') {
+ in.get();
+ break;
+ }
+
+ VarIndex var;
+ const auto letterCount = 'z' - 'a' + 1;
+ if ('a' <= next && next <= 'z')
+ var = next - 'a';
+ else if ('A' <= next && next <= 'Z')
+ var = (next - 'A') + letterCount;
+ else if (sawSome)
+ break;
+ else {
+ mathic::reportError("Could not parse monomial.");
+ return;
+ }
+ MATHICGB_ASSERT(var < 2 * letterCount);
+ if (var >= varCount()) {
+ mathic::reportError("Unknown variable.");
+ return;
+ }
+
+ in.get();
+ auto& exponent = access(mono, exponentsIndexBegin() + var);
+ if (isdigit(in.peek())) {
+ typename unchar<Exponent>::type e;
+ in >> e;
+ exponent = static_cast<Exponent>(e);
+ } else
+ exponent = 1;
+ sawSome = true;
+ }
+
+ if (in.peek() == '<') {
+ if (!HasComponent) {
+ mathic::reportError("Read unexpected < for start of module component\n");
+ return;
+ }
+
+ in.get();
+ if (!isdigit(in.peek())) {
+ mathic::reportError("Component was not integer.");
+ return;
+ }
+ typename unchar<Exponent>::type e;
+ in >> e;
+ access(mono, componentIndex()) = static_cast<Exponent>(e);
+ if (in.peek() != '>') {
+ mathic::reportError("Component < was not matched by >.");
+ return;
+ }
+ in.get();
+ }
+
+ setOrderData(mono);
+ setHash(mono);
+ MATHICGB_ASSERT(debugValid(mono));
+}
+
+template<class E, bool HC, bool SH, bool SO>
+void MonoMonoid<E, HC, SH, SO>::printM2(
+ ConstMonoRef mono,
+ ::std::ostream& out
+) const {
+ using MonoMonoidHelper::unchar;
+ const auto letterCount = 'z' - 'a' + 1;
+
+ bool printedSome = false;
+ for (VarIndex var = 0; var < varCount(); ++var) {
+ if (exponent(mono, var) == 0)
+ continue;
+ char letter;
+ if (var < letterCount)
+ letter = 'a' + static_cast<char>(var);
+ else if (var < 2 * letterCount)
+ letter = 'A' + (static_cast<char>(var) - letterCount);
+ else {
+ mathic::reportError("Too few letters in alphabet to print variable.");
+ return;
+ }
+ printedSome = true;
+ out << letter;
+ if (exponent(mono, var) != 1)
+ out << static_cast<typename unchar<Exponent>::type>(exponent(mono, var));
+ }
+ if (!printedSome)
+ out << '1';
+ if (HasComponent && component(mono) != 0) {
+ out << '<'
+ << static_cast<typename unchar<Exponent>::type>(component(mono))
+ << '>';
+ }
+}
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/MonoOrder.hpp b/src/mathicgb/MonoOrder.hpp
index a85bdb0..a1029c9 100755
--- a/src/mathicgb/MonoOrder.hpp
+++ b/src/mathicgb/MonoOrder.hpp
@@ -1,9 +1,13 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_MONO_ORDER_GUARD
#define MATHICGB_MONO_ORDER_GUARD
#include <vector>
#include <algorithm>
+MATHICGB_NAMESPACE_BEGIN
+
/// Class used to describe an monomial order and/or a module monomial
/// order. Use this class to construct a monoid. The monoid does the
/// actual comparisons.
@@ -19,7 +23,7 @@ class MonoOrder {
public:
typedef W Weight;
typedef size_t VarIndex;
- typedef std::vector<Weight> Gradings;
+ typedef ::std::vector<Weight> Gradings;
static const size_t ComponentAfterBaseOrder = static_cast<size_t>(-1);
@@ -90,7 +94,7 @@ public:
const bool schreyering = true
):
mVarCount(varCount),
- mGradings(std::move(gradings)),
+ mGradings(::std::move(gradings)),
mBaseOrder(baseOrder),
mComponentGradingIndex(componentBefore),
mComponentsAscendingDesired(componentsAscendingDesired),
@@ -170,13 +174,13 @@ private:
const VarIndex componentBefore
) {
if (componentBefore == ComponentAfterBaseOrder)
- return std::move(gradings);
+ return ::std::move(gradings);
MATHICGB_ASSERT(componentBefore <= varCount);
gradings.resize(gradings.size() + varCount);
const auto newRow = gradings.begin() + varCount * componentBefore;
- std::copy_n(newRow, varCount, newRow + varCount);
- std::fill_n(newRow, varCount, static_cast<Weight>(0));
- return std::move(gradings);
+ ::std::copy_n(newRow, varCount, newRow + varCount);
+ ::std::fill_n(newRow, varCount, static_cast<Weight>(0));
+ return ::std::move(gradings);
}
bool debugAssertValid() {
@@ -208,4 +212,5 @@ private:
const bool mComponentsAscendingDesired;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/MonoProcessor.hpp b/src/mathicgb/MonoProcessor.hpp
index 854d8c2..d160fe8 100755
--- a/src/mathicgb/MonoProcessor.hpp
+++ b/src/mathicgb/MonoProcessor.hpp
@@ -1,131 +1,136 @@
-#ifndef MATHICGB_MONO_PROCESSOR_GUARD
-#define MATHICGB_MONO_PROCESSOR_GUARD
-
-#include "Basis.hpp"
-
-/// Does pre- and post-processing of monomials to implement monomial
-/// orders not directly supported by the monoid. This is so far only
-/// relevant for module monomials.
-///
-/// todo: distinguish monomials from module monomials using two
-/// different monoids.
-template<class Monoid>
-class MonoProcessor;
-
-template<class M>
-class MonoProcessor {
-public:
- typedef M Monoid;
- typedef typename Monoid::VarIndex VarIndex;
- typedef typename Monoid::MonoVector MonoVector;
- typedef typename Monoid::MonoRef MonoRef;
- typedef typename Monoid::ConstMonoRef ConstMonoRef;
- typedef typename Monoid::ConstMonoPtr ConstMonoPtr;
-
- MonoProcessor(
- const Monoid& monoid,
- const bool componentsAscendingDesired,
- const bool schreyering
- ):
- mComponentsAscendingDesired(componentsAscendingDesired),
- mComponentCount(0),
- mSchreyering(schreyering),
- mSchreyerMultipliersMemory(monoid)
- {}
-
- void setSchreyering(bool value) {mSchreyering = true;}
- bool schreyering() const {return mSchreyering;}
-
- void setSchreyerMultipliers(const Basis& basis) {
- MonoVector schreyer(monoid());
- for (size_t gen = 0; gen < basis.size(); ++gen)
- schreyer.push_back(basis.getPoly(gen)->getLeadMonomial());
- setSchreyerMultipliers(std::move(schreyer));
- }
-
- void setSchreyerMultipliers(MonoVector&& moduleAdjustments) {
- MATHICGB_ASSERT(moduleAdjustments.monoid() == monoid());
- MATHICGB_ASSERT(mSchreyerMultipliersMemory.empty() ||
- mSchreyerMultipliersMemory.size() == componentCount());
- mSchreyerMultipliersMemory = std::move(moduleAdjustments);
-
- mSchreyerMultipliers.clear();
- for (
- auto it = mSchreyerMultipliersMemory.begin();
- it != mSchreyerMultipliersMemory.end();
- ++it
- ) {
- // in the absence of a separate monoid for (non-module) monomials,
- // at least we can check that the component is zero.
- MATHICGB_ASSERT(this->monoid().component(*it) == 0);
-
- // todo: there should be a better way of indexing into a
- // MonoVector.
- mSchreyerMultipliers.emplace_back((*it).ptr());
- }
- }
-
-
- void preprocess(MonoRef mono) const {
- if (hasSchreyerMultipliers())
- monoid().multiplyInPlace(moduleAdjustment(mono), mono);
- if (needToReverseComponents())
- reverseComponent(mono);
- }
-
- void postprocess(MonoRef mono) const {
- if (needToReverseComponents())
- reverseComponent(mono);
- if (hasSchreyerMultipliers()) {
- MATHICGB_ASSERT(monoid().divides(moduleAdjustment(mono), mono));
- monoid().divideInPlace(moduleAdjustment(mono), mono);
- }
- }
-
- bool processingNeeded() const {
- return needToReverseComponents() || hasSchreyerMultipliers();
- }
-
- bool needToReverseComponents() const {
- return Monoid::HasComponent &&
- componentsAscendingDesired() != monoid().componentsAscending();
- }
-
- void setComponentsAscendingDesired(bool value) {
- mComponentsAscendingDesired = value;
- }
- bool componentsAscendingDesired() const {return mComponentsAscendingDesired;}
-
- bool hasSchreyerMultipliers() const {
- return !mSchreyerMultipliers.empty();
- }
-
- void setComponentCount(VarIndex count) {mComponentCount = count;}
- VarIndex componentCount() const {return mComponentCount;}
- const Monoid& monoid() const {return mSchreyerMultipliersMemory.monoid();}
-
-private:
- void operator==(const MonoProcessor&) const; // not available
-
- void reverseComponent(MonoRef mono) const {
- const auto component = monoid().component(mono);
- const auto newComponent = mComponentCount - 1 - component;
- monoid().setComponent(newComponent, mono);
- }
-
- ConstMonoRef moduleAdjustment(ConstMonoRef mono) const {
- MATHICGB_ASSERT(hasSchreyerMultipliers());
- const auto component = monoid().component(mono);
- MATHICGB_ASSERT(component < componentCount());
- MATHICGB_ASSERT(mSchreyerMultipliers.size() == componentCount());
- return *mSchreyerMultipliers[component];
- }
-
- bool mComponentsAscendingDesired;
- VarIndex mComponentCount;
- bool mSchreyering;
- MonoVector mSchreyerMultipliersMemory;
- std::vector<ConstMonoPtr> mSchreyerMultipliers;
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_MONO_PROCESSOR_GUARD
+#define MATHICGB_MONO_PROCESSOR_GUARD
+
+#include "Basis.hpp"
+
+MATHICGB_NAMESPACE_BEGIN
+
+/// Does pre- and post-processing of monomials to implement monomial
+/// orders not directly supported by the monoid. This is so far only
+/// relevant for module monomials.
+///
+/// todo: distinguish monomials from module monomials using two
+/// different monoids.
+template<class Monoid>
+class MonoProcessor;
+
+template<class M>
+class MonoProcessor {
+public:
+ typedef M Monoid;
+ typedef typename Monoid::VarIndex VarIndex;
+ typedef typename Monoid::MonoVector MonoVector;
+ typedef typename Monoid::MonoRef MonoRef;
+ typedef typename Monoid::ConstMonoRef ConstMonoRef;
+ typedef typename Monoid::ConstMonoPtr ConstMonoPtr;
+
+ MonoProcessor(
+ const Monoid& monoid,
+ const bool componentsAscendingDesired,
+ const bool schreyering
+ ):
+ mComponentsAscendingDesired(componentsAscendingDesired),
+ mComponentCount(0),
+ mSchreyering(schreyering),
+ mSchreyerMultipliersMemory(monoid)
+ {}
+
+ void setSchreyering(bool value) {mSchreyering = true;}
+ bool schreyering() const {return mSchreyering;}
+
+ void setSchreyerMultipliers(const Basis& basis) {
+ MonoVector schreyer(monoid());
+ for (size_t gen = 0; gen < basis.size(); ++gen)
+ schreyer.push_back(basis.getPoly(gen)->getLeadMonomial());
+ setSchreyerMultipliers(std::move(schreyer));
+ }
+
+ void setSchreyerMultipliers(MonoVector&& moduleAdjustments) {
+ MATHICGB_ASSERT(moduleAdjustments.monoid() == monoid());
+ MATHICGB_ASSERT(mSchreyerMultipliersMemory.empty() ||
+ mSchreyerMultipliersMemory.size() == componentCount());
+ mSchreyerMultipliersMemory = std::move(moduleAdjustments);
+
+ mSchreyerMultipliers.clear();
+ for (
+ auto it = mSchreyerMultipliersMemory.begin();
+ it != mSchreyerMultipliersMemory.end();
+ ++it
+ ) {
+ // in the absence of a separate monoid for (non-module) monomials,
+ // at least we can check that the component is zero.
+ MATHICGB_ASSERT(this->monoid().component(*it) == 0);
+
+ // todo: there should be a better way of indexing into a
+ // MonoVector.
+ mSchreyerMultipliers.emplace_back((*it).ptr());
+ }
+ }
+
+
+ void preprocess(MonoRef mono) const {
+ if (hasSchreyerMultipliers())
+ monoid().multiplyInPlace(moduleAdjustment(mono), mono);
+ if (needToReverseComponents())
+ reverseComponent(mono);
+ }
+
+ void postprocess(MonoRef mono) const {
+ if (needToReverseComponents())
+ reverseComponent(mono);
+ if (hasSchreyerMultipliers()) {
+ MATHICGB_ASSERT(monoid().divides(moduleAdjustment(mono), mono));
+ monoid().divideInPlace(moduleAdjustment(mono), mono);
+ }
+ }
+
+ bool processingNeeded() const {
+ return needToReverseComponents() || hasSchreyerMultipliers();
+ }
+
+ bool needToReverseComponents() const {
+ return Monoid::HasComponent &&
+ componentsAscendingDesired() != monoid().componentsAscending();
+ }
+
+ void setComponentsAscendingDesired(bool value) {
+ mComponentsAscendingDesired = value;
+ }
+ bool componentsAscendingDesired() const {return mComponentsAscendingDesired;}
+
+ bool hasSchreyerMultipliers() const {
+ return !mSchreyerMultipliers.empty();
+ }
+
+ void setComponentCount(VarIndex count) {mComponentCount = count;}
+ VarIndex componentCount() const {return mComponentCount;}
+ const Monoid& monoid() const {return mSchreyerMultipliersMemory.monoid();}
+
+private:
+ void operator==(const MonoProcessor&) const; // not available
+
+ void reverseComponent(MonoRef mono) const {
+ const auto component = monoid().component(mono);
+ const auto newComponent = mComponentCount - 1 - component;
+ monoid().setComponent(newComponent, mono);
+ }
+
+ ConstMonoRef moduleAdjustment(ConstMonoRef mono) const {
+ MATHICGB_ASSERT(hasSchreyerMultipliers());
+ const auto component = monoid().component(mono);
+ MATHICGB_ASSERT(component < componentCount());
+ MATHICGB_ASSERT(mSchreyerMultipliers.size() == componentCount());
+ return *mSchreyerMultipliers[component];
+ }
+
+ bool mComponentsAscendingDesired;
+ VarIndex mComponentCount;
+ bool mSchreyering;
+ MonoVector mSchreyerMultipliersMemory;
+ std::vector<ConstMonoPtr> mSchreyerMultipliers;
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/MonomialHashTable.hpp b/src/mathicgb/MonomialHashTable.hpp
index 1d2f33d..28fe9af 100755
--- a/src/mathicgb/MonomialHashTable.hpp
+++ b/src/mathicgb/MonomialHashTable.hpp
@@ -1,12 +1,13 @@
// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
-
-#ifndef _MonomialHashTable_h_
-#define _MonomialHashTable_h_
+#ifndef MATHICGB_MONOMIAL_HASH_TABLE_GUARD
+#define MATHICGB_MONOMIAL_HASH_TABLE_GUARD
#include "ChainedHashTable.hpp"
#include "PolyRing.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
class MonomialHashControl
{
public:
@@ -82,9 +83,6 @@ private:
memt::Arena mMonomialPool;
MonomialHashTableBasic H_;
};
-#endif
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/MonomialMap.hpp b/src/mathicgb/MonomialMap.hpp
index 6975c43..7787cd4 100755
--- a/src/mathicgb/MonomialMap.hpp
+++ b/src/mathicgb/MonomialMap.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_MONOMIAL_MAP_GUARD
#define MATHICGB_MONOMIAL_MAP_GUARD
@@ -10,6 +12,8 @@
#include <vector>
#include <algorithm>
+MATHICGB_NAMESPACE_BEGIN
+
/// A concurrent hash map from monomials to T. This map can resize itself
/// if there are too few buckets compared to entries.
///
@@ -44,10 +48,10 @@ public:
MonomialMap(const PolyRing& ring):
mMap(new FixedSizeMap(InitialBucketCount, ring)),
mCapacityUntilGrowth
- (maxEntries(mMap.load(std::memory_order_relaxed)->bucketCount())),
+ (maxEntries(mMap.load(::std::memory_order_relaxed)->bucketCount())),
mRing(ring)
{
- // We can load mMap as std::memory_order_relaxed because we just stored it
+ // We can load mMap as ::std::memory_order_relaxed because we just stored it
// and the constructor cannot run concurrently.
}
@@ -77,9 +81,9 @@ public:
class Reader {
public:
Reader(const MonomialMap<T>& map):
- mMap(*map.mMap.load(std::memory_order_seq_cst))
+ mMap(*map.mMap.load(::std::memory_order_seq_cst))
{
- // We grab the hash table pointer with std::memory_order_seq_cst in order
+ // We grab the hash table pointer with ::std::memory_order_seq_cst in order
// to force a CPU cache flush - in this way we are more likely to get an
// up to date value.
}
@@ -88,14 +92,14 @@ public:
/// inserted. Also returns the internal monomial that matches mono if such
/// a monomial exists. Misses can be spurious! Read the comments on the parent
/// class.
- std::pair<const mapped_type*, ConstMonomial>
+ ::std::pair<const mapped_type*, ConstMonomial>
find(const_monomial mono) const {
return mMap.find(mono);
}
// As find but looks for the product of a and b and also returns the
// monomal that is the product.
- std::pair<const mapped_type*, ConstMonomial> findProduct(
+ ::std::pair<const mapped_type*, ConstMonomial> findProduct(
const const_monomial a,
const const_monomial b
) const {
@@ -106,7 +110,7 @@ public:
/// simultaneously. The purpose of this is similar to that of unrolling a
/// loop.
MATHICGB_INLINE
- std::pair<const mapped_type*, const mapped_type*> findTwoProducts(
+ ::std::pair<const mapped_type*, const mapped_type*> findTwoProducts(
const const_monomial a1,
const const_monomial a2,
const const_monomial b
@@ -137,13 +141,13 @@ public:
/// equal value.second if an insertion was not performed - unless the
/// inserted value equals the already present value. p.first.second is an
/// internal monomial that equals value.first.
- std::pair<std::pair<const mapped_type*, ConstMonomial>, bool>
+ ::std::pair< ::std::pair<const mapped_type*, ConstMonomial>, bool>
insert(const value_type& value) {
const mgb::tbb::mutex::scoped_lock lockGuard(mInsertionMutex);
- // We can load mMap as std::memory_order_relaxed because we have already
+ // We can load mMap as ::std::memory_order_relaxed because we have already
// synchronized with all other mutators by locking mInsertionMutex;
- auto map = mMap.load(std::memory_order_relaxed);
+ auto map = mMap.load(::std::memory_order_relaxed);
// this is a loop since it is possible to set the growth factor and
// the initial size so low that several rounds are required. This should
@@ -152,21 +156,21 @@ public:
while (mCapacityUntilGrowth == 0) {
// Resize the table by making a bigger one and using that instead.
if (map->bucketCount() > // check overflow
- std::numeric_limits<size_t>::max() / GrowthFactor)
+ ::std::numeric_limits<size_t>::max() / GrowthFactor)
{
- throw std::bad_alloc();
+ throw ::std::bad_alloc();
}
const size_t newBucketCount = map->bucketCount() * GrowthFactor;
auto nextMap =
- make_unique<FixedSizeMap>(newBucketCount, std::move(*map));
+ make_unique<FixedSizeMap>(newBucketCount, ::std::move(*map));
mOldMaps.emplace_back(map);
mCapacityUntilGrowth =
maxEntries(nextMap->bucketCount()) - maxEntries(map->bucketCount());
- // Store with std::memory_order_seq_cst to force a memory flush so that
+ // Store with ::std::memory_order_seq_cst to force a memory flush so that
// readers see the new table as soon as possible.
map = nextMap.release();
- mMap.store(map, std::memory_order_seq_cst);
+ mMap.store(map, ::std::memory_order_seq_cst);
}
MATHICGB_ASSERT(mCapacityUntilGrowth > 0);
@@ -180,9 +184,9 @@ public:
/// call too much. The count may have
size_t entryCount() const {
const mgb::tbb::mutex::scoped_lock lockGuard(mInsertionMutex);
- // We can load with std::memory_order_relaxed because we are holding the
+ // We can load with ::std::memory_order_relaxed because we are holding the
// lock.
- auto& map = *mMap.load(std::memory_order_relaxed);
+ auto& map = *mMap.load(::std::memory_order_relaxed);
return maxEntries(map.bucketCount()) - mCapacityUntilGrowth;
}
@@ -207,7 +211,8 @@ private:
/// keep these around as we have no way to determine if there are still
/// readers looking at them. This could be changed at the cost of
/// more overhead in the Reader constructor and destructor.
- std::vector<std::unique_ptr<FixedSizeMap>> mOldMaps;
+ ::std::vector< ::std::unique_ptr<FixedSizeMap>> mOldMaps;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/NonCopyable.hpp b/src/mathicgb/NonCopyable.hpp
index e64dfa0..db95a00 100755
--- a/src/mathicgb/NonCopyable.hpp
+++ b/src/mathicgb/NonCopyable.hpp
@@ -1,22 +1,27 @@
-#ifndef MATHICGB_NON_COPYABLE_GUARD
-#define MATHICGB_NON_COPYABLE_GUARD
-
-/// Derive from this class to disable the compiler-generated copy
-/// constructor and assignment. T should be the class that is deriving
-/// from NonCopyable.
-///
-/// The purpose of the template parameter is to avoid any chance of
-/// getting a diamond-graph inheritance graph. Diamond graphs can lead
-/// to runtime overhead.
-template<class T>
-class NonCopyable {
-public:
- NonCopyable() {}
- NonCopyable(NonCopyable&&) {} // still movable.
-
-private:
- NonCopyable(const NonCopyable&); // unavailable
- void operator=(const NonCopyable&); // unavailable
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_NON_COPYABLE_GUARD
+#define MATHICGB_NON_COPYABLE_GUARD
+
+MATHICGB_NAMESPACE_BEGIN
+
+/// Derive from this class to disable the compiler-generated copy
+/// constructor and assignment. T should be the class that is deriving
+/// from NonCopyable.
+///
+/// The purpose of the template parameter is to avoid any chance of
+/// getting a diamond-graph inheritance graph. Diamond graphs can lead
+/// to runtime overhead.
+template<class T>
+class NonCopyable {
+public:
+ NonCopyable() {}
+ NonCopyable(NonCopyable&&) {} // still movable.
+
+private:
+ NonCopyable(const NonCopyable&); // unavailable
+ void operator=(const NonCopyable&); // unavailable
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/PairTriangle.cpp b/src/mathicgb/PairTriangle.cpp
index 056ad7f..715169c 100755
--- a/src/mathicgb/PairTriangle.cpp
+++ b/src/mathicgb/PairTriangle.cpp
@@ -1,9 +1,13 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "PairTriangle.hpp"
#include <limits>
#include <stdexcept>
+MATHICGB_NAMESPACE_BEGIN
+
PairTriangle::PairTriangle(const PolyRing& ring, size_t queueType):
mColumnCount(0),
mRing(ring),
@@ -104,3 +108,5 @@ std::pair<size_t, size_t> PairTriangle::topPair() const {
const_monomial PairTriangle::topOrderBy() const {
return mPairQueue.topPairData();
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/PairTriangle.hpp b/src/mathicgb/PairTriangle.hpp
index 20afc47..29a2aca 100755
--- a/src/mathicgb/PairTriangle.hpp
+++ b/src/mathicgb/PairTriangle.hpp
@@ -1,10 +1,14 @@
-#ifndef _pair_triangle_h
-#define _pair_triangle_h
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_PAIR_TRIANGLE_GUARD
+#define MATHICGB_PAIR_TRIANGLE_GUARD
-#include <memtailor.h>
-#include <mathic.h>
#include "PolyRing.hpp"
#include "SigSPairQueue.hpp"
+#include <memtailor.h>
+#include <mathic.h>
+
+MATHICGB_NAMESPACE_BEGIN
/*typedef unsigned short SmallIndex;
typedef unsigned int BigIndex;
@@ -101,23 +105,30 @@ private:
};
mathic::PairQueue<PC> mPairQueue;
friend void mathic::PairQueueNamespace::constructPairData<PC>(void*,Index,Index,PC&);
- friend void mathic::PairQueueNamespace::destructPairData<PC>(monomial*,Index,Index, PC&);
+ friend void mathic::PairQueueNamespace::destructPairData<PC>(PC::PairData*,Index,Index, PC&);
};
+MATHICGB_NAMESPACE_END
+
namespace mathic {
namespace PairQueueNamespace {
template<>
- inline void constructPairData<PairTriangle::PC>
- (void* memory, Index col, Index row, PairTriangle::PC& conf) {
+ inline void constructPairData<mgb::PairTriangle::PC>
+ (void* memory, Index col, Index row, mgb::PairTriangle::PC& conf) {
MATHICGB_ASSERT(memory != 0);
MATHICGB_ASSERT(col > row);
- monomial* pd = new (memory) monomial(conf.allocPairData());
+ auto pd = new (memory)
+ mgb::PairTriangle::PC::PairData(conf.allocPairData());
conf.computePairData(col, row, *pd);
}
template<>
- inline void destructPairData
- (monomial* pd, Index col, Index row, PairTriangle::PC& conf) {
+ inline void destructPairData<mgb::PairTriangle::PC>(
+ mgb::PairTriangle::PC::PairData* pd,
+ Index col,
+ Index row,
+ mgb::PairTriangle::PC& conf
+ ) {
MATHICGB_ASSERT(pd != 0);
MATHICGB_ASSERT(col > row);
conf.freePairData(*pd);
diff --git a/src/mathicgb/Poly.cpp b/src/mathicgb/Poly.cpp
index 5a8dcf8..80939b3 100755
--- a/src/mathicgb/Poly.cpp
+++ b/src/mathicgb/Poly.cpp
@@ -1,11 +1,14 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "Poly.hpp"
+
#include <ostream>
#include <iostream>
#include <algorithm>
+MATHICGB_NAMESPACE_BEGIN
+
// Format for input/output:
// #terms term1 term2 ...
// each term: coeff monom
@@ -388,8 +391,4 @@ bool Poly::termsAreInDescendingOrder() const {
return true;
}
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/Poly.hpp b/src/mathicgb/Poly.hpp
index 059ccf0..484cfc4 100755
--- a/src/mathicgb/Poly.hpp
+++ b/src/mathicgb/Poly.hpp
@@ -1,7 +1,7 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _poly_h_
-#define _poly_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_POLY_GUARD
+#define MATHICGB_POLY_GUARD
#include "PolyRing.hpp"
#include <vector>
@@ -10,31 +10,33 @@
#include <cstdio>
#include <iterator>
+MATHICGB_NAMESPACE_BEGIN
+
class Poly {
public:
Poly(const PolyRing& ring) : R(&ring) {MATHICGB_ASSERT(R != 0);}
- void parse(std::istream &i); // reads into this, sorts terms
- void parseDoNotOrder(std::istream &i); // reads into this, does not sort terms
+ void parse(::std::istream &i); // reads into this, sorts terms
+ void parseDoNotOrder(::std::istream &i); // reads into this, does not sort terms
void display(FILE* file, bool printComponent = true) const;
- void display(std::ostream& out, bool printComponent = true) const;
+ void display(::std::ostream& out, bool printComponent = true) const;
void see(bool print_comp) const;
class iterator {
// only for const objects...
size_t monsize;
- std::vector<coefficient>::iterator ic;
- std::vector<exponent>::iterator im;
+ ::std::vector<coefficient>::iterator ic;
+ ::std::vector<exponent>::iterator im;
friend class Poly;
iterator(Poly& f) : monsize(f.getRing()->maxMonomialSize()), ic(f.coeffs.begin()), im(f.monoms.begin()) {}
iterator(Poly& f,int) : ic(f.coeffs.end()), im() {}
public:
- typedef std::random_access_iterator_tag iterator_category;
- typedef std::pair<coefficient, const const_monomial> value_type;
+ typedef ::std::random_access_iterator_tag iterator_category;
+ typedef ::std::pair<coefficient, const const_monomial> value_type;
typedef ptrdiff_t difference_type;
typedef value_type* pointer; // todo: is this OK?
- typedef std::pair<coefficient&, const const_monomial> reference;
+ typedef ::std::pair<coefficient&, const const_monomial> reference;
iterator() {}
iterator operator++() { ++ic; im += monsize; return *this; }
@@ -44,25 +46,25 @@ public:
friend bool operator==(const iterator &a, const iterator &b);
friend bool operator!=(const iterator &a, const iterator &b);
reference operator*() const {
- return std::pair<coefficient&, monomial>(getCoefficient(), getMonomial());
+ return ::std::pair<coefficient&, monomial>(getCoefficient(), getMonomial());
}
};
class const_iterator {
// only for const objects...
size_t monsize;
- std::vector<coefficient>::const_iterator ic;
- std::vector<exponent>::const_iterator im;
+ ::std::vector<coefficient>::const_iterator ic;
+ ::std::vector<exponent>::const_iterator im;
friend class Poly;
const_iterator(const Poly& f) : monsize(f.getRing()->maxMonomialSize()), ic(f.coeffs.begin()), im(f.monoms.begin()) {}
const_iterator(const Poly& f,int) : ic(f.coeffs.end()), im() {}
public:
- typedef std::random_access_iterator_tag iterator_category;
- typedef std::pair<const coefficient, const const_monomial> value_type;
+ typedef ::std::random_access_iterator_tag iterator_category;
+ typedef ::std::pair<const coefficient, const const_monomial> value_type;
typedef ptrdiff_t difference_type;
typedef value_type* pointer; // todo: is this OK?
- typedef std::pair<const coefficient&, const const_monomial> reference;
+ typedef ::std::pair<const coefficient&, const const_monomial> reference;
const_iterator() {}
const_iterator operator++() { ++ic; im += monsize; return *this; }
@@ -72,7 +74,7 @@ public:
friend bool operator==(const const_iterator &a, const const_iterator &b);
friend bool operator!=(const const_iterator &a, const const_iterator &b);
const value_type operator*() const {
- return std::pair<coefficient, const_monomial>
+ return ::std::pair<coefficient, const_monomial>
(getCoefficient(), getMonomial());
}
};
@@ -150,11 +152,11 @@ public:
private:
const PolyRing *R;
- std::vector<coefficient> coeffs;
- std::vector<exponent> monoms;
+ ::std::vector<coefficient> coeffs;
+ ::std::vector<exponent> monoms;
};
-std::ostream& operator<<(std::ostream& out, const Poly& p);
+::std::ostream& operator<<(::std::ostream& out, const Poly& p);
inline bool operator==(const Poly::iterator &a, const Poly::iterator &b)
{
@@ -192,10 +194,5 @@ inline void Poly::appendTerm(coefficient a, PolyRing::Monoid::ConstMonoRef m) {
monoid.copy(m, *PolyRing::Monoid::MonoPtr(monoms.data() + offset));
}
-
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/PolyBasis.cpp b/src/mathicgb/PolyBasis.cpp
index a7f2be5..e2cf091 100755
--- a/src/mathicgb/PolyBasis.cpp
+++ b/src/mathicgb/PolyBasis.cpp
@@ -1,9 +1,13 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
-#include "Basis.hpp"
#include "PolyBasis.hpp"
+#include "Basis.hpp"
#include "DivisorLookup.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
PolyBasis::PolyBasis(
const PolyRing& ring,
std::unique_ptr<DivisorLookup> divisorLookup
@@ -189,3 +193,5 @@ PolyBasis::Entry::Entry():
usedAsReducerCount(0),
possibleReducerCount(0),
nonSignatureReducerCount(0) {}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/PolyBasis.hpp b/src/mathicgb/PolyBasis.hpp
index df8577c..a7d4d3a 100755
--- a/src/mathicgb/PolyBasis.hpp
+++ b/src/mathicgb/PolyBasis.hpp
@@ -1,11 +1,15 @@
-#ifndef _poly_basis_h_
-#define _poly_basis_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_POLY_BASIS_GUARD
+#define MATHICGB_POLY_BASIS_GUARD
#include "Poly.hpp"
#include "DivisorLookup.hpp"
#include <vector>
#include <memory>
+MATHICGB_NAMESPACE_BEGIN
+
class PolyRing;
class Basis;
@@ -16,19 +20,19 @@ public:
// Ring must live for as long as this object.
PolyBasis(
const PolyRing& ring,
- std::unique_ptr<DivisorLookup> divisorLookup
+ ::std::unique_ptr<DivisorLookup> divisorLookup
);
// Deletes the Poly's stored in the basis.
~PolyBasis();
// Returns the initial monomial basis of the basis.
- std::unique_ptr<Basis> initialIdeal() const;
+ ::std::unique_ptr<Basis> initialIdeal() const;
// Inserts a polynomial into the basis at index size().
// Lead monomials must be unique among basis elements.
// So the index is size() - 1 afterwards since size() will increase by 1.
- void insert(std::unique_ptr<Poly> poly);
+ void insert(::std::unique_ptr<Poly> poly);
// Returns the index of a basis element whose lead term divides mon.
// Returns -1 if there is no such basis element.
@@ -44,7 +48,7 @@ public:
// Replaces basis element at index with the given new value. The lead
// term of the new polynomial must be the same as the previous one.
// This is useful for auto-tail-reduction.
- void replaceSameLeadTerm(size_t index, std::unique_ptr<Poly> newValue) {
+ void replaceSameLeadTerm(size_t index, ::std::unique_ptr<Poly> newValue) {
MATHICGB_ASSERT(index < size());
MATHICGB_ASSERT(!retired(index));
MATHICGB_ASSERT(newValue.get() != 0);
@@ -72,12 +76,12 @@ public:
// Retires the basis element at index, which frees the memory associated
// to it, including the basis element polynomial, and marks it as retired.
- std::unique_ptr<Poly> retire(size_t index);
+ ::std::unique_ptr<Poly> retire(size_t index);
/// Returns an basis containing all non-retired basis elements and
/// retires all those basis elements. The point of the simultaneous
/// retirement is that this way no polynomials need be copied.
- std::unique_ptr<Basis> toBasisAndRetireAll();
+ ::std::unique_ptr<Basis> toBasisAndRetireAll();
// Returns true of the basis element at index has been retired.
bool retired(size_t index) const {
@@ -210,13 +214,14 @@ private:
mutable unsigned long long possibleReducerCount;
mutable unsigned long long nonSignatureReducerCount;
};
- typedef std::vector<Entry> EntryCont;
+ typedef ::std::vector<Entry> EntryCont;
typedef EntryCont::iterator EntryIter;
typedef EntryCont::const_iterator EntryCIter;
const PolyRing& mRing;
- std::unique_ptr<DivisorLookup> mDivisorLookup;
- std::vector<Entry> mEntries;
+ ::std::unique_ptr<DivisorLookup> mDivisorLookup;
+ ::std::vector<Entry> mEntries;
};
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/PolyGeoBucket.cpp b/src/mathicgb/PolyGeoBucket.cpp
index 6538c13..10d95a0 100755
--- a/src/mathicgb/PolyGeoBucket.cpp
+++ b/src/mathicgb/PolyGeoBucket.cpp
@@ -1,9 +1,12 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "PolyGeoBucket.hpp"
+
#include <mathic.h>
+MATHICGB_NAMESPACE_BEGIN
+
const size_t heap_size[GEOHEAP_SIZE] = {4, 16, 64, 256, 1024, 4096,
16384, 65536, 262144, 1048576, 4194304,
16777216, 67108864, 268435456,
@@ -259,7 +262,4 @@ void PolyGeoBucket::dump() const
{
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/PolyGeoBucket.hpp b/src/mathicgb/PolyGeoBucket.hpp
index ea95cab..97de1e3 100755
--- a/src/mathicgb/PolyGeoBucket.hpp
+++ b/src/mathicgb/PolyGeoBucket.hpp
@@ -1,10 +1,13 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _polyGeoBucket_h_
-#define _polyGeoBucket_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_POLY_GEO_BUCKET_GUARD
+#define MATHICGB_POLY_GEO_BUCKET_GUARD
#include "TypicalReducer.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
+/// @todo: shouldn't be a macro
#define GEOHEAP_SIZE 15
class PolyGeoBucket : public TypicalReducer {
@@ -51,9 +54,5 @@ private:
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/PolyHashReducer.cpp b/src/mathicgb/PolyHashReducer.cpp
index 3e97193..9164bc5 100755
--- a/src/mathicgb/PolyHashReducer.cpp
+++ b/src/mathicgb/PolyHashReducer.cpp
@@ -1,8 +1,10 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "PolyHashReducer.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
PolyHashReducer::PolyHashReducer(const PolyRing *R0):
R_(R0), H_(R0,15)
{
@@ -164,7 +166,4 @@ void PolyHashReducer::dump() const
H_.dump(0);
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/PolyHashReducer.hpp b/src/mathicgb/PolyHashReducer.hpp
index 749be06..d7c5e54 100755
--- a/src/mathicgb/PolyHashReducer.hpp
+++ b/src/mathicgb/PolyHashReducer.hpp
@@ -1,11 +1,13 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _polyHashReducer_h_
-#define _polyHashReducer_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_POLY_HASH_REDUCER_GUARD
+#define MATHICGB_POLY_HASH_REDUCER_GUARD
#include "TypicalReducer.hpp"
#include "PolyHashTable.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
class PolyHashReducer : public TypicalReducer {
public:
PolyHashReducer(const PolyRing *R);
@@ -48,9 +50,5 @@ private:
PolyHashTable H_;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/PolyHashTable.cpp b/src/mathicgb/PolyHashTable.cpp
index 075ea25..9df610d 100755
--- a/src/mathicgb/PolyHashTable.cpp
+++ b/src/mathicgb/PolyHashTable.cpp
@@ -1,4 +1,5 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "PolyHashTable.hpp"
@@ -6,6 +7,7 @@
#include <iostream>
#include <cmath>
+MATHICGB_NAMESPACE_BEGIN
const double PolyHashTable::threshold = 0.1;
const bool AlwaysInsertAtEnd = true;
@@ -455,10 +457,6 @@ void PolyHashTable::dump(int level) const
f.display(std::cout);
std::cout << std::endl;
}
-
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/PolyHashTable.hpp b/src/mathicgb/PolyHashTable.hpp
old mode 100644
new mode 100755
index 3119be8..d5801f0
--- a/src/mathicgb/PolyHashTable.hpp
+++ b/src/mathicgb/PolyHashTable.hpp
@@ -1,14 +1,15 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_POLY_HASH_TABLE_GUARD
+#define MATHICGB_POLY_HASH_TABLE_GUARD
-#ifndef _PolyHashTable_h_
-#define _PolyHashTable_h_
-
-#include <vector>
-
-#include <memtailor.h>
#include "PolyRing.hpp"
#include "Poly.hpp"
#include <utility>
+#include <memtailor.h>
+#include <vector>
+
+MATHICGB_NAMESPACE_BEGIN
// The hash table is a map: monomial => coeff
// Operations required on monomials:
@@ -137,11 +138,5 @@ protected:
size_t mMonomialSize;
};
-
-
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/PolyHeap.cpp b/src/mathicgb/PolyHeap.cpp
index 3d5f3af..ccf8c45 100755
--- a/src/mathicgb/PolyHeap.cpp
+++ b/src/mathicgb/PolyHeap.cpp
@@ -1,10 +1,13 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "PolyHeap.hpp"
#include <iostream>
#include <algorithm>
+MATHICGB_NAMESPACE_BEGIN
+
size_t PolyHeap::stats_static_n_compares = 0;
PolyHeap::PolyHeap(const PolyRing *R_):
@@ -173,7 +176,4 @@ void PolyHeap::dump() const
}
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/PolyHeap.hpp b/src/mathicgb/PolyHeap.hpp
index dbfdebd..a17c32e 100755
--- a/src/mathicgb/PolyHeap.hpp
+++ b/src/mathicgb/PolyHeap.hpp
@@ -1,10 +1,12 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _polyHeap_h_
-#define _polyHeap_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_POLY_HEAP_GUARD
+#define MATHICGB_POLY_HEAP_GUARD
#include "TypicalReducer.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
struct heap_term {
monomial actual; // multiplier * *first
const_term multiplier;
@@ -66,9 +68,5 @@ inline bool heapCompareFcn::operator()(heap_term &a, heap_term &b)
return R->monomialLT(a.actual, b.actual);
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/PolyReducer.cpp b/src/mathicgb/PolyReducer.cpp
index 50a189d..5f37ae4 100755
--- a/src/mathicgb/PolyReducer.cpp
+++ b/src/mathicgb/PolyReducer.cpp
@@ -1,7 +1,10 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "PolyReducer.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
PolyReducer::PolyReducer(const PolyRing *R0):
R(R0), mMemUsage(0)
{
@@ -108,7 +111,4 @@ size_t PolyReducer::getMemoryUse() const {
return mMemUsage;
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/PolyReducer.hpp b/src/mathicgb/PolyReducer.hpp
index 0de2c5d..d09450c 100755
--- a/src/mathicgb/PolyReducer.hpp
+++ b/src/mathicgb/PolyReducer.hpp
@@ -1,10 +1,12 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _polyReducer_h_
-#define _polyReducer_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_POLY_REDUCER_GUARD
+#define MATHICGB_POLY_REDUCER_GUARD
#include "TypicalReducer.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
class PolyReducer : public TypicalReducer {
public:
PolyReducer(const PolyRing *R);
@@ -37,9 +39,5 @@ private:
size_t mMemUsage;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/PolyRing.cpp b/src/mathicgb/PolyRing.cpp
index 1c50fd1..0c7e398 100755
--- a/src/mathicgb/PolyRing.cpp
+++ b/src/mathicgb/PolyRing.cpp
@@ -1,4 +1,5 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "PolyRing.hpp"
@@ -11,6 +12,8 @@
#include <cstdlib>
#include <limits>
+MATHICGB_NAMESPACE_BEGIN
+
PolyRing::PolyRing(const Field& field, Monoid&& monoid):
mField(field), mMonoid(std::move(monoid))
{}
@@ -244,7 +247,4 @@ void PolyRing::write(std::ostream &o, bool componentIncreasingDesired) const
monoid().printMonoid(componentIncreasingDesired, o);
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/PolyRing.hpp b/src/mathicgb/PolyRing.hpp
index 4b5e3f5..3be2658 100755
--- a/src/mathicgb/PolyRing.hpp
+++ b/src/mathicgb/PolyRing.hpp
@@ -1,7 +1,7 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _polyRing_h_
-#define _polyRing_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_POLY_RING_GUARD
+#define MATHICGB_POLY_RING_GUARD
#include "MonoMonoid.hpp"
#include "PrimeField.hpp"
@@ -13,6 +13,7 @@
#include <cstring>
#include <limits>
+MATHICGB_NAMESPACE_BEGIN
#define LT (-1)
#define EQ 0
@@ -21,8 +22,8 @@
template<class T>
PrimeField<
- typename std::make_unsigned<
- typename std::remove_reference<T>::type
+ typename ::std::make_unsigned<
+ typename ::std::remove_reference<T>::type
>::type
> makeField(T charac) {
return charac;
@@ -152,7 +153,7 @@ public:
Monomial(exponent *val) : ConstMonomial(val) {}
void swap(Monomial& monomial) {
- std::swap(mValue, monomial.mValue);
+ ::std::swap(mValue, monomial.mValue);
}
exponent * unsafeGetRepresentation() { return const_cast<exponent *>(mValue); }
@@ -204,7 +205,7 @@ public:
coefficient charac,
int nvars,
bool lexBaseOrder,
- std::vector<exponent>&& weights
+ ::std::vector<exponent>&& weights
);
PolyRing(const Field& field, Monoid&& monoid);
@@ -216,11 +217,11 @@ public:
coefficient charac() const { return mField.charac(); }
size_t getNumVars() const { return varCount();}
size_t varCount() const {return monoid().varCount();}
- // const std::vector<int> °s,
- // const std::string &monorder);
+ // const ::std::vector<int> °s,
+ // const ::std::string &monorder);
- static std::pair<PolyRing*, std::pair<bool, bool>> read(std::istream &i);
- void write(std::ostream &o, bool componentIncreasingDesired) const;
+ static ::std::pair<PolyRing*, ::std::pair<bool, bool>> read(::std::istream &i);
+ void write(::std::ostream &o, bool componentIncreasingDesired) const;
// Format for ring
// <char> <mNumVars> <deg1> ... <deg_n> <monorder>
@@ -233,7 +234,7 @@ public:
// fill with value that do not make sense to catch bugs in debug
// mode. The maximum value of setting all bits increases the
// chances of getting an assert.
- std::fill_n(reinterpret_cast<char*>(ptr), maxMonomialByteSize(),
+ ::std::fill_n(reinterpret_cast<char*>(ptr), maxMonomialByteSize(),
~static_cast<char>(0));
#endif
return ptr;
@@ -255,7 +256,7 @@ public:
// fill with value that do not make sense to catch bugs in debug
// mode. The maximum value of setting all bits increases the
// chances of getting an assert.
- std::fill_n(reinterpret_cast<char*>(ptr), maxMonomialByteSize(),
+ ::std::fill_n(reinterpret_cast<char*>(ptr), maxMonomialByteSize(),
~static_cast<char>(0));
#endif
return ptr;
@@ -458,10 +459,10 @@ public:
ConstMonomial smaller1,
ConstMonomial smaller2) const;
- void monomialParse(std::istream& i,
+ void monomialParse(::std::istream& i,
Monomial& result) const;
- void monomialDisplay(std::ostream& o,
+ void monomialDisplay(::std::ostream& o,
ConstMonomial a,
bool print_comp=true,
bool print_one=true) const;
@@ -470,7 +471,7 @@ public:
bool printComponent = true,
bool printOne = true) const;
- void printMonomialFrobbyM2Format(std::ostream& out, ConstMonomial m) const;
+ void printMonomialFrobbyM2Format(::std::ostream& out, ConstMonomial m) const;
///////////////////////////////////////////
///////////////////////////////////////////
@@ -699,9 +700,5 @@ inline bool PolyRing::monomialHasAmpleCapacity(ConstMonomial mono) const {
return monoid().hasAmpleCapacity(mono);
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/PrimeField.hpp b/src/mathicgb/PrimeField.hpp
index 4dcf4f3..1be98c5 100755
--- a/src/mathicgb/PrimeField.hpp
+++ b/src/mathicgb/PrimeField.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_PRIME_FIELD_GUARD
#define MATHICGB_PRIME_FIELD_GUARD
@@ -5,9 +7,11 @@
#include <type_traits>
#include <ostream>
+MATHICGB_NAMESPACE_BEGIN
+
/// Implements arithmetic in a prime field. T must be an unsigned integer type
/// that is used to store the elements of the field. The characteristic of the
-/// field must be a prime not exceeding std::numeric_limits<T>::max().
+/// field must be a prime not exceeding ::std::numeric_limits<T>::max().
template<class T>
class PrimeField {
public:
@@ -15,8 +19,8 @@ public:
class Element {
public:
- static_assert(!std::numeric_limits<T>::is_signed, "");
- static_assert(std::numeric_limits<T>::is_integer, "");
+ static_assert(!::std::numeric_limits<T>::is_signed, "");
+ static_assert(::std::numeric_limits<T>::is_integer, "");
Element(const Element& e): mValue(e.value()) {}
@@ -51,19 +55,19 @@ public:
/// Assumes that i is in the range [0;charac()).
template<class Integer>
Element toElementInRange(Integer&& i) const {
- typedef typename std::remove_reference<Integer>::type NoRefInteger;
- static_assert(std::numeric_limits<NoRefInteger>::is_integer, "");
+ typedef typename ::std::remove_reference<Integer>::type NoRefInteger;
+ static_assert(::std::numeric_limits<NoRefInteger>::is_integer, "");
MATHICGB_ASSERT(0 <= i);
- typedef typename std::make_unsigned<NoRefInteger>::type Unsigned;
+ typedef typename ::std::make_unsigned<NoRefInteger>::type Unsigned;
MATHICGB_ASSERT(static_cast<Unsigned>(i) < charac());
return Element(i);
}
template<class Integer>
Element toElement(Integer&& i) const {
- typedef typename std::remove_reference<Integer>::type NoRefInteger;
- static_assert(std::numeric_limits<NoRefInteger>::is_integer, "");
+ typedef typename ::std::remove_reference<Integer>::type NoRefInteger;
+ static_assert(::std::numeric_limits<NoRefInteger>::is_integer, "");
// We need to take the modulus of i to put it into the range [0;charac()).
// That is more tricky to get right than it might seem.
@@ -74,11 +78,11 @@ public:
// converted to a signed integer since it might not be representable that
// way.
//
- // If Integer is signed and i is std::numeric_limits<Integer>::min() then
+ // If Integer is signed and i is ::std::numeric_limits<Integer>::min() then
// it is undefined behavior to evaluate the expression -i since -i is not
// representable, leading to a signed overflow. So we have to cast to
// unsigned before doing the minus.
- typedef typename std::make_unsigned<NoRefInteger>::type Unsigned;
+ typedef typename ::std::make_unsigned<NoRefInteger>::type Unsigned;
if (i < 0) {
// Negate i to get a positive number, then negate again to cancel out
// the first negation. The first cast to unsigned is to avoid
@@ -223,12 +227,13 @@ auto PrimeField<T>::inverse(const Element elementA) const -> Element {
template<class T>
-std::ostream& operator<<(
- std::ostream& out,
+::std::ostream& operator<<(
+ ::std::ostream& out,
typename PrimeField<T>::Element e
) {
out << e.value();
return out;
}
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/QuadMatrix.cpp b/src/mathicgb/QuadMatrix.cpp
index d1a4944..58167f0 100755
--- a/src/mathicgb/QuadMatrix.cpp
+++ b/src/mathicgb/QuadMatrix.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "QuadMatrix.hpp"
@@ -6,6 +8,8 @@
#include <ostream>
#include <sstream>
+MATHICGB_NAMESPACE_BEGIN
+
bool QuadMatrix::debugAssertValid() const {
#ifndef MATHICGB_DEBUG
return true;
@@ -29,7 +33,7 @@ bool QuadMatrix::debugAssertValid() const {
#endif
}
-void QuadMatrix::print(std::ostream& out) const {
+void QuadMatrix::print(::std::ostream& out) const {
MATHICGB_ASSERT(debugAssertValid());
typedef SparseMatrix::ColIndex ColIndex;
@@ -74,22 +78,22 @@ SparseMatrix::ColIndex QuadMatrix::computeLeftColCount() const {
if (!leftColumnMonomials.empty()) {
MATHICGB_ASSERT(
leftColumnMonomials.size() <=
- std::numeric_limits<SparseMatrix::ColIndex>::max()
+ ::std::numeric_limits<SparseMatrix::ColIndex>::max()
);
return static_cast<SparseMatrix::ColIndex>(leftColumnMonomials.size());
}
- return std::max(topLeft.computeColCount(), bottomLeft.computeColCount());
+ return ::std::max(topLeft.computeColCount(), bottomLeft.computeColCount());
}
SparseMatrix::ColIndex QuadMatrix::computeRightColCount() const {
if (!rightColumnMonomials.empty()) {
MATHICGB_ASSERT(
rightColumnMonomials.size() <=
- std::numeric_limits<SparseMatrix::ColIndex>::max()
+ ::std::numeric_limits<SparseMatrix::ColIndex>::max()
);
return static_cast<SparseMatrix::ColIndex>(rightColumnMonomials.size());
}
- return std::max(topRight.computeColCount(), bottomRight.computeColCount());
+ return ::std::max(topRight.computeColCount(), bottomRight.computeColCount());
}
size_t QuadMatrix::entryCount() const {
@@ -98,8 +102,8 @@ size_t QuadMatrix::entryCount() const {
bottomLeft.entryCount() + bottomRight.entryCount();
}
-std::string QuadMatrix::toString() const {
- std::ostringstream out;
+::std::string QuadMatrix::toString() const {
+ ::std::ostringstream out;
print(out);
return out.str();
}
@@ -114,7 +118,7 @@ size_t QuadMatrix::memoryUseTrimmed() const {
bottomLeft.memoryUseTrimmed() + bottomRight.memoryUseTrimmed();
}
-void QuadMatrix::printStatistics(std::ostream& out) const {
+void QuadMatrix::printStatistics(::std::ostream& out) const {
typedef mathic::ColumnPrinter ColPr;
ColPr pr;
@@ -127,7 +131,7 @@ void QuadMatrix::printStatistics(std::ostream& out) const {
const auto totalMemory = memoryUse();
auto printDataCol = [&](
- std::ostream& out,
+ ::std::ostream& out,
const SparseMatrix& top,
const SparseMatrix& bottom,
const SparseMatrix::ColIndex colCount
@@ -209,12 +213,12 @@ QuadMatrix QuadMatrix::toCanonical() const {
// todo: eliminate left/right code duplication here
QuadMatrix matrix;
{ // left side
- std::vector<SparseMatrix::RowIndex> rows;
+ ::std::vector<SparseMatrix::RowIndex> rows;
for (SparseMatrix::RowIndex row = 0; row < topLeft.rowCount(); ++row)
rows.push_back(row);
{
RowComparer comparer(topLeft);
- std::sort(rows.begin(), rows.end(), comparer);
+ ::std::sort(rows.begin(), rows.end(), comparer);
}
matrix.topLeft.clear();
@@ -225,12 +229,12 @@ QuadMatrix QuadMatrix::toCanonical() const {
}
}
{ // right side
- std::vector<SparseMatrix::RowIndex> rows;
+ ::std::vector<SparseMatrix::RowIndex> rows;
for (SparseMatrix::RowIndex row = 0; row < bottomLeft.rowCount(); ++row)
rows.push_back(row);
{
RowComparer comparer(bottomLeft);
- std::sort(rows.begin(), rows.end(), comparer);
+ ::std::sort(rows.begin(), rows.end(), comparer);
}
matrix.bottomLeft.clear();
@@ -245,10 +249,10 @@ QuadMatrix QuadMatrix::toCanonical() const {
matrix.rightColumnMonomials = rightColumnMonomials;
matrix.ring = ring;
- return std::move(matrix);
+ return ::std::move(matrix);
}
-std::ostream& operator<<(std::ostream& out, const QuadMatrix& qm) {
+::std::ostream& operator<<(::std::ostream& out, const QuadMatrix& qm) {
qm.print(out);
return out;
}
@@ -259,7 +263,7 @@ namespace {
ColumnComparer(const PolyRing& ring): mRing(ring) {}
typedef SparseMatrix::ColIndex ColIndex;
- typedef std::pair<monomial, ColIndex> Pair;
+ typedef ::std::pair<monomial, ColIndex> Pair;
bool operator()(const Pair& a, const Pair b) const {
return mRing.monomialLT(b.first, a.first);
}
@@ -268,20 +272,20 @@ namespace {
const PolyRing& mRing;
};
- std::vector<SparseMatrix::ColIndex> sortColumnMonomialsAndMakePermutation(
- std::vector<monomial>& monomials,
+ ::std::vector<SparseMatrix::ColIndex> sortColumnMonomialsAndMakePermutation(
+ ::std::vector<monomial>& monomials,
const PolyRing& ring
) {
typedef SparseMatrix::ColIndex ColIndex;
- MATHICGB_ASSERT(monomials.size() <= std::numeric_limits<ColIndex>::max());
+ MATHICGB_ASSERT(monomials.size() <= ::std::numeric_limits<ColIndex>::max());
const ColIndex colCount = static_cast<ColIndex>(monomials.size());
// Monomial needs to be non-const as we are going to put these
// monomials back into the vector of monomials which is not const.
- std::vector<std::pair<monomial, ColIndex>> columns;
+ ::std::vector< ::std::pair<monomial, ColIndex>> columns;
columns.reserve(colCount);
for (ColIndex col = 0; col < colCount; ++col)
- columns.push_back(std::make_pair(monomials[col], col));
- std::sort(columns.begin(), columns.end(), ColumnComparer(ring));
+ columns.push_back(::std::make_pair(monomials[col], col));
+ ::std::sort(columns.begin(), columns.end(), ColumnComparer(ring));
// Apply sorting permutation to monomials. This is why it is necessary to
// copy the values in monomial out of there: in-place application of a
@@ -295,21 +299,21 @@ namespace {
}
// Construct permutation of indices to match permutation of monomials
- std::vector<ColIndex> permutation(colCount);
+ ::std::vector<ColIndex> permutation(colCount);
for (ColIndex col = 0; col < colCount; ++col) {
// The monomial for column columns[col].second is now the
// monomial for col, so we need the inverse map for indices.
permutation[columns[col].second] = col;
}
- return std::move(permutation);
+ return ::std::move(permutation);
}
}
void QuadMatrix::sortColumnsLeftRightParallel() {
typedef SparseMatrix::ColIndex ColIndex;
- std::vector<ColIndex> leftPermutation;
- std::vector<ColIndex> rightPermutation;
+ ::std::vector<ColIndex> leftPermutation;
+ ::std::vector<ColIndex> rightPermutation;
mgb::tbb::parallel_for(0, 2, 1, [&](int i) {
if (i == 0)
@@ -366,3 +370,5 @@ SparseMatrix::Scalar QuadMatrix::read(FILE* file) {
return topLeftModulus;
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/QuadMatrix.hpp b/src/mathicgb/QuadMatrix.hpp
index 35594df..81b9b0d 100755
--- a/src/mathicgb/QuadMatrix.hpp
+++ b/src/mathicgb/QuadMatrix.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_QUAD_MATRIX_GUARD
#define MATHICGB_QUAD_MATRIX_GUARD
@@ -6,6 +8,9 @@
#include <vector>
#include <string>
#include <ostream>
+
+MATHICGB_NAMESPACE_BEGIN
+
class ostream;
/** Represents a matrix composed of 4 sub-matrices that fit together
@@ -20,18 +25,18 @@ public:
QuadMatrix() {}
QuadMatrix(QuadMatrix&& matrix):
- topLeft(std::move(matrix.topLeft)),
- topRight(std::move(matrix.topRight)),
- bottomLeft(std::move(matrix.bottomLeft)),
- bottomRight(std::move(matrix.bottomRight)),
- leftColumnMonomials(std::move(matrix.leftColumnMonomials)),
- rightColumnMonomials(std::move(matrix.rightColumnMonomials)),
+ topLeft(::std::move(matrix.topLeft)),
+ topRight(::std::move(matrix.topRight)),
+ bottomLeft(::std::move(matrix.bottomLeft)),
+ bottomRight(::std::move(matrix.bottomRight)),
+ leftColumnMonomials(::std::move(matrix.leftColumnMonomials)),
+ rightColumnMonomials(::std::move(matrix.rightColumnMonomials)),
ring(matrix.ring)
{}
QuadMatrix& operator=(QuadMatrix&& matrix) {
this->~QuadMatrix();
- new (this) QuadMatrix(std::move(matrix));
+ new (this) QuadMatrix(::std::move(matrix));
return *this;
}
@@ -39,21 +44,21 @@ public:
SparseMatrix topRight;
SparseMatrix bottomLeft;
SparseMatrix bottomRight;
- std::vector<monomial> leftColumnMonomials;
- std::vector<monomial> rightColumnMonomials;
+ ::std::vector<monomial> leftColumnMonomials;
+ ::std::vector<monomial> rightColumnMonomials;
const PolyRing* ring;
/// Prints whole matrix to out in human-readable format. Useful for
/// debugging.
- void print(std::ostream& out) const;
+ void print(::std::ostream& out) const;
- void printStatistics(std::ostream& out) const;
+ void printStatistics(::std::ostream& out) const;
size_t memoryUse() const;
size_t memoryUseTrimmed() const;
/// Shows whole matrix in a string. Useful for debugging.
- std::string toString() const;
+ ::std::string toString() const;
/// Return the combined number of non-zero entries.
size_t entryCount() const;
@@ -89,6 +94,8 @@ private:
void operator=(const QuadMatrix&); // not available
};
-std::ostream& operator<<(std::ostream& out, const QuadMatrix& qm);
+::std::ostream& operator<<(::std::ostream& out, const QuadMatrix& qm);
+
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/QuadMatrixBuilder.cpp b/src/mathicgb/QuadMatrixBuilder.cpp
index 29a8a99..b963836 100755
--- a/src/mathicgb/QuadMatrixBuilder.cpp
+++ b/src/mathicgb/QuadMatrixBuilder.cpp
@@ -1,127 +1,133 @@
-#include "stdinc.h"
-#include "QuadMatrixBuilder.hpp"
-
-#include "QuadMatrix.hpp"
-#include <mathic.h>
-#include <sstream>
-
-QuadMatrixBuilder::QuadMatrixBuilder(
- const PolyRing& ring,
- Map& map,
- MonomialsType& monomialsLeft,
- MonomialsType& monomialsRight,
- const size_t memoryQuantum
-):
- mMonomialToCol(map),
- mTopLeft(memoryQuantum),
- mTopRight(memoryQuantum),
- mBottomLeft(memoryQuantum),
- mBottomRight(memoryQuantum),
- mMonomialsLeft(monomialsLeft),
- mMonomialsRight(monomialsRight)
-{}
-
-void QuadMatrixBuilder::takeRowsFrom(QuadMatrix&& matrix) {
- MATHICGB_ASSERT(&ring() == matrix.ring);
- MATHICGB_ASSERT(matrix.debugAssertValid());
-
- mTopLeft.takeRowsFrom(std::move(matrix.topLeft));
- mTopRight.takeRowsFrom(std::move(matrix.topRight));
- mBottomLeft.takeRowsFrom(std::move(matrix.bottomLeft));
- mBottomRight.takeRowsFrom(std::move(matrix.bottomRight));
-}
-
-
-namespace {
- /// Creates a column and updates the associated data structures that
- /// are passed in. Copies mono - ownership is not taken over. The
- /// purpose of this function is to avoid code duplication. It is a
- /// template in order to avoid referring to private types of
- /// QuadMatrixBuilder.
- template<class ToMono, class ToCol>
- std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
- createCol(
- const_monomial mono,
- SparseMatrix& top,
- SparseMatrix& bottom,
- ToMono& toMonomial,
- ToCol& toCol,
- const PolyRing& ring,
- const bool left
- ) {
- MATHICGB_ASSERT(typename ToCol::Reader(toCol).find(mono).first == 0);
-
- const auto colCount =
- static_cast<QuadMatrixBuilder::ColIndex>(toMonomial.size());
- if (colCount == std::numeric_limits<QuadMatrixBuilder::ColIndex>::max())
- throw std::overflow_error("Too many columns in QuadMatrixBuilder");
-
- toMonomial.push_back(0); // allocate memory now to avoid bad_alloc later
- monomial copied = ring.allocMonomial();
- ring.monomialCopy(mono, copied);
- std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial> p;
- try {
- auto inserted = toCol.insert(std::make_pair(
- copied, QuadMatrixBuilder::LeftRightColIndex(colCount, left))
- );
- MATHICGB_ASSERT(inserted.second);
- MATHICGB_ASSERT(inserted.first.first != 0);
- auto p(inserted.first);
- toMonomial.back() = copied;
-
- MATHICGB_ASSERT(ring.monomialEqualHintTrue(copied, p.second));
- MATHICGB_ASSERT(*p.first == QuadMatrixBuilder::LeftRightColIndex(colCount, left));
- return std::make_pair(*p.first, p.second);
- } catch (...) {
- toMonomial.pop_back();
- ring.freeMonomial(copied);
- throw;
- }
- }
-}
-
-std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
-QuadMatrixBuilder::createColumnLeft(
- const_monomial monomialToBeCopied
-) {
- return createCol
- (monomialToBeCopied,
- mTopLeft,
- mBottomLeft,
- mMonomialsLeft,
- mMonomialToCol,
- ring(),
- true);
-}
-
-std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
-QuadMatrixBuilder::createColumnRight(
- const_monomial monomialToBeCopied
-) {
- return createCol
- (monomialToBeCopied,
- mTopRight,
- mBottomRight,
- mMonomialsRight,
- mMonomialToCol,
- ring(),
- false);
-}
-
-QuadMatrix QuadMatrixBuilder::buildMatrixAndClear() {
- QuadMatrix out;
-
- mTopLeft.swap(out.topLeft);
- mTopRight.swap(out.topRight);
- mBottomLeft.swap(out.bottomLeft);
- mBottomRight.swap(out.bottomRight);
- out.ring = &ring();
-
- mTopLeft.clear();
- mTopRight.clear();
- mBottomLeft.clear();
- mBottomRight.clear();
-
- MATHICGB_ASSERT(out.debugAssertValid());
- return std::move(out);
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "stdinc.h"
+#include "QuadMatrixBuilder.hpp"
+
+#include "QuadMatrix.hpp"
+#include <mathic.h>
+#include <sstream>
+
+MATHICGB_NAMESPACE_BEGIN
+
+QuadMatrixBuilder::QuadMatrixBuilder(
+ const PolyRing& ring,
+ Map& map,
+ MonomialsType& monomialsLeft,
+ MonomialsType& monomialsRight,
+ const size_t memoryQuantum
+):
+ mMonomialToCol(map),
+ mTopLeft(memoryQuantum),
+ mTopRight(memoryQuantum),
+ mBottomLeft(memoryQuantum),
+ mBottomRight(memoryQuantum),
+ mMonomialsLeft(monomialsLeft),
+ mMonomialsRight(monomialsRight)
+{}
+
+void QuadMatrixBuilder::takeRowsFrom(QuadMatrix&& matrix) {
+ MATHICGB_ASSERT(&ring() == matrix.ring);
+ MATHICGB_ASSERT(matrix.debugAssertValid());
+
+ mTopLeft.takeRowsFrom(::std::move(matrix.topLeft));
+ mTopRight.takeRowsFrom(::std::move(matrix.topRight));
+ mBottomLeft.takeRowsFrom(::std::move(matrix.bottomLeft));
+ mBottomRight.takeRowsFrom(::std::move(matrix.bottomRight));
+}
+
+
+namespace {
+ /// Creates a column and updates the associated data structures that
+ /// are passed in. Copies mono - ownership is not taken over. The
+ /// purpose of this function is to avoid code duplication. It is a
+ /// template in order to avoid referring to private types of
+ /// QuadMatrixBuilder.
+ template<class ToMono, class ToCol>
+ ::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
+ createCol(
+ const_monomial mono,
+ SparseMatrix& top,
+ SparseMatrix& bottom,
+ ToMono& toMonomial,
+ ToCol& toCol,
+ const PolyRing& ring,
+ const bool left
+ ) {
+ MATHICGB_ASSERT(typename ToCol::Reader(toCol).find(mono).first == 0);
+
+ const auto colCount =
+ static_cast<QuadMatrixBuilder::ColIndex>(toMonomial.size());
+ if (colCount == ::std::numeric_limits<QuadMatrixBuilder::ColIndex>::max())
+ throw ::std::overflow_error("Too many columns in QuadMatrixBuilder");
+
+ toMonomial.push_back(0); // allocate memory now to avoid bad_alloc later
+ monomial copied = ring.allocMonomial();
+ ring.monomialCopy(mono, copied);
+ ::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial> p;
+ try {
+ auto inserted = toCol.insert(::std::make_pair(
+ copied, QuadMatrixBuilder::LeftRightColIndex(colCount, left))
+ );
+ MATHICGB_ASSERT(inserted.second);
+ MATHICGB_ASSERT(inserted.first.first != 0);
+ auto p(inserted.first);
+ toMonomial.back() = copied;
+
+ MATHICGB_ASSERT(ring.monomialEqualHintTrue(copied, p.second));
+ MATHICGB_ASSERT(*p.first == QuadMatrixBuilder::LeftRightColIndex(colCount, left));
+ return ::std::make_pair(*p.first, p.second);
+ } catch (...) {
+ toMonomial.pop_back();
+ ring.freeMonomial(copied);
+ throw;
+ }
+ }
+}
+
+::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
+QuadMatrixBuilder::createColumnLeft(
+ const_monomial monomialToBeCopied
+) {
+ return createCol
+ (monomialToBeCopied,
+ mTopLeft,
+ mBottomLeft,
+ mMonomialsLeft,
+ mMonomialToCol,
+ ring(),
+ true);
+}
+
+::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
+QuadMatrixBuilder::createColumnRight(
+ const_monomial monomialToBeCopied
+) {
+ return createCol
+ (monomialToBeCopied,
+ mTopRight,
+ mBottomRight,
+ mMonomialsRight,
+ mMonomialToCol,
+ ring(),
+ false);
+}
+
+QuadMatrix QuadMatrixBuilder::buildMatrixAndClear() {
+ QuadMatrix out;
+
+ mTopLeft.swap(out.topLeft);
+ mTopRight.swap(out.topRight);
+ mBottomLeft.swap(out.bottomLeft);
+ mBottomRight.swap(out.bottomRight);
+ out.ring = &ring();
+
+ mTopLeft.clear();
+ mTopRight.clear();
+ mBottomLeft.clear();
+ mBottomRight.clear();
+
+ MATHICGB_ASSERT(out.debugAssertValid());
+ return ::std::move(out);
+}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/QuadMatrixBuilder.hpp b/src/mathicgb/QuadMatrixBuilder.hpp
index 53763df..8b2b556 100755
--- a/src/mathicgb/QuadMatrixBuilder.hpp
+++ b/src/mathicgb/QuadMatrixBuilder.hpp
@@ -1,199 +1,204 @@
-#ifndef MATHICGB_QUAD_MATRIX_BUILDER_GUARD
-#define MATHICGB_QUAD_MATRIX_BUILDER_GUARD
-
-#include "MonomialMap.hpp"
-
-#include "SparseMatrix.hpp"
-#include "PolyRing.hpp"
-#include <vector>
-#include <map>
-#include <limits>
-#include <string>
-#include <ostream>
-#include <memtailor.h>
-class QuadMatrix;
-
-/** Builder for QuadMatrix. This is not quite the builder pattern in
- that the interface is not virtual and the implementation cannot be
- swapped out - it only follows the builder pattern in that it is a
- class that allows step-wise construction of a final product. */
-class QuadMatrixBuilder {
- public:
- typedef SparseMatrix::RowIndex RowIndex;
- typedef SparseMatrix::ColIndex ColIndex;
- typedef SparseMatrix::Scalar Scalar;
-
- /// The index of a column that can be either on the left or the
- /// right side. The largest representable ColIndex is an invalid
- /// index. This is the default value. The only allowed method to
- /// call for an invalid index is valid().
- class LeftRightColIndex {
- public:
- LeftRightColIndex():
- mRawIndex(std::numeric_limits<ColIndex>::max()), mLeft(false) {}
- LeftRightColIndex(ColIndex index, bool left):
- mRawIndex(index), mLeft(left) {
- }
-
- ColIndex leftIndex() const {
- MATHICGB_ASSERT(left());
- return index();
- }
-
- ColIndex rightIndex() const {
- MATHICGB_ASSERT(right());
- return index();
- }
-
- /// Use leftIndex() or rightIndex() instead if you know what side
- /// you are expecting, as this does an assert on your expectation.
- ColIndex index() const {
- MATHICGB_ASSERT(valid());
- return mRawIndex;
- }
-
- bool left() const {
- MATHICGB_ASSERT(valid());
- return mLeft;
- }
-
- bool right() const {
- MATHICGB_ASSERT(valid());
- return !left();
- }
-
- bool valid() const {
- return mRawIndex != std::numeric_limits<ColIndex>::max();
- }
-
- bool operator==(const LeftRightColIndex& index) const {
- return mRawIndex == index.mRawIndex && mLeft == index.mLeft;
- }
-
- bool operator!=(const LeftRightColIndex& index) const {
- return !(*this == index);
- }
-
- private:
- ColIndex mRawIndex;
- bool mLeft;
- };
-
- typedef MonomialMap<LeftRightColIndex> Map;
- typedef std::vector<monomial> MonomialsType;
-
- QuadMatrixBuilder(
- const PolyRing& ring,
- Map& map,
- MonomialsType& monomialsLeft,
- MonomialsType& monomialsRight,
- size_t memoryQuantum = 0
- );
-
- /// Inserts the rows from builder. To avoid an assert either the matrix must
- /// have no column monomials specified or the monomials that are specified
- /// must match exactly to the column monomials for this object --- including
- /// the ordering of the monomials.
- void takeRowsFrom(QuadMatrix&& matrix);
-
- size_t memoryQuantum() const {
- return mTopLeft.memoryQuantum();
- }
-
- // **** Appending entries to top matrices.
- // Same interface as SparseMatrix except with two matrices and here
- // you have to create columns before you can use them.
-
- void appendEntryTopLeft(ColIndex col, Scalar scalar) {
- mTopLeft.appendEntry(col, scalar);
- }
-
- void appendEntryTopRight(ColIndex col, Scalar scalar) {
- mTopRight.appendEntry(col, scalar);
- }
-
- void appendEntryTop(LeftRightColIndex col, Scalar scalar) {
- MATHICGB_ASSERT(col.valid());
- if (col.left())
- appendEntryTopLeft(col.leftIndex(), scalar);
- else
- appendEntryTopRight(col.rightIndex(), scalar);
- }
-
- void rowDoneTopLeftAndRight() {
- mTopLeft.rowDone();
- mTopRight.rowDone();
- }
-
- // **** Appending entries to bottom matrices
- // Same interface as SparseMatrix except with two matrices and here
- // you have to create columns before you can use them.
-
- void appendEntryBottomLeft(ColIndex col, Scalar scalar) {
- mBottomLeft.appendEntry(col, scalar);
- }
-
- void appendEntryBottomRight(ColIndex col, Scalar scalar) {
- mBottomRight.appendEntry(col, scalar);
- }
-
- void appendEntryBottom(LeftRightColIndex col, Scalar scalar) {
- MATHICGB_ASSERT(col.valid());
- if (col.left())
- appendEntryBottomLeft(col.leftIndex(), scalar);
- else
- appendEntryBottomRight(col.rightIndex(), scalar);
- }
-
- void rowDoneBottomLeftAndRight() {
- mBottomLeft.rowDone();
- mBottomRight.rowDone();
- }
-
- // *** Creating and reordering columns
- // 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. */
- std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
- 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. */
- std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
- createColumnRight(const_monomial monomialToBeCopied);
-
- // *** Querying columns
-
- const SparseMatrix& topLeft() const {return mTopLeft;}
- const SparseMatrix& topRight() const {return mTopRight;}
- const SparseMatrix& bottomLeft() const {return mBottomLeft;}
- const SparseMatrix& bottomRight() const {return mBottomRight;}
-
- const PolyRing& ring() const {return mMonomialToCol.ring();}
-
- /// Returns the built matrix and sets the builder to a state
- /// with no columns and no rows.
- QuadMatrix buildMatrixAndClear();
-
-private:
- MonomialsType& mMonomialsLeft; /// stores one monomial per left column
- MonomialsType& mMonomialsRight; /// stores one monomial per right column
-
- /// Used for fast determination of which column has a given monomial.
- Map& mMonomialToCol;
-
- SparseMatrix mTopLeft;
- SparseMatrix mTopRight;
- SparseMatrix mBottomLeft;
- SparseMatrix mBottomRight;
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_QUAD_MATRIX_BUILDER_GUARD
+#define MATHICGB_QUAD_MATRIX_BUILDER_GUARD
+
+#include "MonomialMap.hpp"
+#include "SparseMatrix.hpp"
+#include "PolyRing.hpp"
+#include <vector>
+#include <map>
+#include <limits>
+#include <string>
+#include <ostream>
+#include <memtailor.h>
+
+MATHICGB_NAMESPACE_BEGIN
+
+class QuadMatrix;
+
+/** Builder for QuadMatrix. This is not quite the builder pattern in
+ that the interface is not virtual and the implementation cannot be
+ swapped out - it only follows the builder pattern in that it is a
+ class that allows step-wise construction of a final product. */
+class QuadMatrixBuilder {
+ public:
+ typedef SparseMatrix::RowIndex RowIndex;
+ typedef SparseMatrix::ColIndex ColIndex;
+ typedef SparseMatrix::Scalar Scalar;
+
+ /// The index of a column that can be either on the left or the
+ /// right side. The largest representable ColIndex is an invalid
+ /// index. This is the default value. The only allowed method to
+ /// call for an invalid index is valid().
+ class LeftRightColIndex {
+ public:
+ LeftRightColIndex():
+ mRawIndex(::std::numeric_limits<ColIndex>::max()), mLeft(false) {}
+ LeftRightColIndex(ColIndex index, bool left):
+ mRawIndex(index), mLeft(left) {
+ }
+
+ ColIndex leftIndex() const {
+ MATHICGB_ASSERT(left());
+ return index();
+ }
+
+ ColIndex rightIndex() const {
+ MATHICGB_ASSERT(right());
+ return index();
+ }
+
+ /// Use leftIndex() or rightIndex() instead if you know what side
+ /// you are expecting, as this does an assert on your expectation.
+ ColIndex index() const {
+ MATHICGB_ASSERT(valid());
+ return mRawIndex;
+ }
+
+ bool left() const {
+ MATHICGB_ASSERT(valid());
+ return mLeft;
+ }
+
+ bool right() const {
+ MATHICGB_ASSERT(valid());
+ return !left();
+ }
+
+ bool valid() const {
+ return mRawIndex != ::std::numeric_limits<ColIndex>::max();
+ }
+
+ bool operator==(const LeftRightColIndex& index) const {
+ return mRawIndex == index.mRawIndex && mLeft == index.mLeft;
+ }
+
+ bool operator!=(const LeftRightColIndex& index) const {
+ return !(*this == index);
+ }
+
+ private:
+ ColIndex mRawIndex;
+ bool mLeft;
+ };
+
+ typedef MonomialMap<LeftRightColIndex> Map;
+ typedef ::std::vector<monomial> MonomialsType;
+
+ QuadMatrixBuilder(
+ const PolyRing& ring,
+ Map& map,
+ MonomialsType& monomialsLeft,
+ MonomialsType& monomialsRight,
+ size_t memoryQuantum = 0
+ );
+
+ /// Inserts the rows from builder. To avoid an assert either the matrix must
+ /// have no column monomials specified or the monomials that are specified
+ /// must match exactly to the column monomials for this object --- including
+ /// the ordering of the monomials.
+ void takeRowsFrom(QuadMatrix&& matrix);
+
+ size_t memoryQuantum() const {
+ return mTopLeft.memoryQuantum();
+ }
+
+ // **** Appending entries to top matrices.
+ // Same interface as SparseMatrix except with two matrices and here
+ // you have to create columns before you can use them.
+
+ void appendEntryTopLeft(ColIndex col, Scalar scalar) {
+ mTopLeft.appendEntry(col, scalar);
+ }
+
+ void appendEntryTopRight(ColIndex col, Scalar scalar) {
+ mTopRight.appendEntry(col, scalar);
+ }
+
+ void appendEntryTop(LeftRightColIndex col, Scalar scalar) {
+ MATHICGB_ASSERT(col.valid());
+ if (col.left())
+ appendEntryTopLeft(col.leftIndex(), scalar);
+ else
+ appendEntryTopRight(col.rightIndex(), scalar);
+ }
+
+ void rowDoneTopLeftAndRight() {
+ mTopLeft.rowDone();
+ mTopRight.rowDone();
+ }
+
+ // **** Appending entries to bottom matrices
+ // Same interface as SparseMatrix except with two matrices and here
+ // you have to create columns before you can use them.
+
+ void appendEntryBottomLeft(ColIndex col, Scalar scalar) {
+ mBottomLeft.appendEntry(col, scalar);
+ }
+
+ void appendEntryBottomRight(ColIndex col, Scalar scalar) {
+ mBottomRight.appendEntry(col, scalar);
+ }
+
+ void appendEntryBottom(LeftRightColIndex col, Scalar scalar) {
+ MATHICGB_ASSERT(col.valid());
+ if (col.left())
+ appendEntryBottomLeft(col.leftIndex(), scalar);
+ else
+ appendEntryBottomRight(col.rightIndex(), scalar);
+ }
+
+ void rowDoneBottomLeftAndRight() {
+ mBottomLeft.rowDone();
+ mBottomRight.rowDone();
+ }
+
+ // *** Creating and reordering columns
+ // 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. */
+ ::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
+ 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. */
+ ::std::pair<QuadMatrixBuilder::LeftRightColIndex, ConstMonomial>
+ createColumnRight(const_monomial monomialToBeCopied);
+
+ // *** Querying columns
+
+ const SparseMatrix& topLeft() const {return mTopLeft;}
+ const SparseMatrix& topRight() const {return mTopRight;}
+ const SparseMatrix& bottomLeft() const {return mBottomLeft;}
+ const SparseMatrix& bottomRight() const {return mBottomRight;}
+
+ const PolyRing& ring() const {return mMonomialToCol.ring();}
+
+ /// Returns the built matrix and sets the builder to a state
+ /// with no columns and no rows.
+ QuadMatrix buildMatrixAndClear();
+
+private:
+ MonomialsType& mMonomialsLeft; /// stores one monomial per left column
+ MonomialsType& mMonomialsRight; /// stores one monomial per right column
+
+ /// Used for fast determination of which column has a given monomial.
+ Map& mMonomialToCol;
+
+ SparseMatrix mTopLeft;
+ SparseMatrix mTopRight;
+ SparseMatrix mBottomLeft;
+ SparseMatrix mBottomRight;
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/RawVector.hpp b/src/mathicgb/RawVector.hpp
index 9c7d6e4..88a3447 100755
--- a/src/mathicgb/RawVector.hpp
+++ b/src/mathicgb/RawVector.hpp
@@ -1,307 +1,312 @@
-#ifndef MATHICGB_RAW_VECTOR_GUARD
-#define MATHICGB_RAW_VECTOR_GUARD
-
-#include <iterator>
-#include <cstddef>
-#include <memory>
-#include <utility>
-#include <algorithm>
-#include <stdexcept>
-#include <cstring>
-
-/// RawVector mimics std::vector except that it does not do memory management.
-/// So you can directly access the pointers to memory and you can replace them
-/// with any other pointers that you need to.
-///
-/// Warning: RawVector is called raw because it does not allocate any memory,
-/// so it is an error to insert elements that there is not enough space for -
-/// you need to make sure ahead of time that there is enough space.
-///
-/// This class makes it possible to have a lot of the convenience of the
-/// std::vector interface even in places where std::vector cannot be used
-/// because of a need for manual memory management.
-template<class T>
-class RawVector {
-public:
- typedef T& reference;
- typedef const T& const_reference;
- typedef T* iterator;
- typedef const T* const_iterator;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef T value_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
- /// Initializes to the null state.
- RawVector(): mBegin(0), mEnd(0), mCapacityEnd(0) {}
-
- /// Copies the pointers from v. It is a shallow copy.
- RawVector(const RawVector& v):
- mBegin(v.mBegin),
- mEnd(v.mEnd),
- mCapacityEnd(v.mCapacityEnd) {}
-
- /// Copies the pointers from v. It is a shallow copy. Sets v to a null state.
- RawVector(RawVector&& v):
- mBegin(v.mBegin),
- mEnd(v.mEnd),
- mCapacityEnd(v.mCapacityEnd)
- {
- v.releaseMemory();
- }
-
- RawVector(pointer begin, pointer end):
- mBegin(begin),
- mEnd(end),
- mCapacityEnd(end) {}
-
- RawVector(pointer begin, pointer end, pointer capacityEnd):
- mBegin(begin),
- mEnd(end),
- mCapacityEnd(capacityEnd) {}
-
- /// As clear() --- does not free memory.
- ~RawVector() {
- clear();
- }
-
- /// There is no operator== to avoid confusion about whether it compares
- /// pointers or contents. Instead, there is this.
- bool contentsEqual(const RawVector<T>& v) const {
- return std::equal(begin(), end(), v.begin());
- }
-
- /// Copies the pointers from v. It is a shallow copy.
- RawVector<T>& operator=(const RawVector& v) {
- mBegin = v.mBegin;
- mEnd = v.mEnd;
- mCapacityEnd = v.mCapacityEnd;
- return *this;
- }
-
- /// Copies the pointers from v. It is a shallow copy. Sets v to the null state.
- RawVector<T>& operator=(RawVector&& v) {
- mBegin = v.mBegin;
- mEnd = v.mEnd;
- mCapacityEnd = v.mCapacityEnd;
- v.releaseMemory();
- return *this;
- }
-
- iterator begin() {return mBegin;}
- const_iterator begin() const {return mBegin;}
- iterator end() {return mEnd;}
- const_iterator end() const {return mEnd;}
-
- reverse_iterator rbegin() {return reverse_iterator(end());}
- const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}
- reverse_iterator rend() {return reverse_iterator(begin());}
- const_reverse_iterator rend() const {return const_reverse_iterator(begin());}
-
- size_type size() const {return mEnd - mBegin;}
- size_type max_size() const {return std::numeric_limits<size_type>::max();}
-
- /// There must be enough capacity for the new size.
- void resize(const size_type newSize) {
- MATHICGB_ASSERT(newSize <= capacity());
- while (newSize > size()) {
- new (mEnd) T();
- ++mEnd;
- }
- while (newSize < size()) {
- --mEnd;
- mEnd->~T();
- }
- MATHICGB_ASSERT(newSize == size());
- }
-
- size_type capacity() const {return mCapacityEnd - mBegin;}
-
- bool empty() const {return mBegin == mEnd;}
-
- reference operator[](size_type index) {
- MATHICGB_ASSERT(index < size());
- return mBegin[index];
- }
-
- const_reference operator[](size_type index) const {
- MATHICGB_ASSERT(index < size());
- return mBegin[index];
- }
-
- reference at(size_type index) {
- if (index >= size())
- throw std::out_of_range("Invalid index in RawVector::at.");
- return mBegin[index];
- }
-
- const_reference at(size_type index) const {
- if (index >= size())
- throw std::out_of_range("Invalid index in RawVector::at.");
- return mBegin[index];
- }
-
- reference front() {
- MATHICGB_ASSERT(!empty());
- return *mBegin;
- }
-
- const_reference front() const {
- MATHICGB_ASSERT(!empty());
- return *mBegin;
- }
-
- reference back() {
- MATHICGB_ASSERT(!empty());
- return *(mEnd - 1);
- }
-
- const_reference back() const {
- MATHICGB_ASSERT(!empty());
- return *(mEnd - 1);
- }
-
- size_t memoryUse() const {
- return capacity() * sizeof(value_type);
- }
-
- size_t memoryUseTrimmed() const {
- return size() * sizeof(value_type);
- }
-
- /// There must be enough capacity for the new size.
- template<class Iter>
- void rawAssign(Iter begin, Iter end) {
- const size_t count = std::distance(begin, end);
- MATHICGB_ASSERT(count <= capacity());
- if (count > size())
- resize(count);
- std::copy(begin, end, mBegin);
- }
-
- /// There must be enough capacity for the new size.
- void rawAssign(size_type count, const T& t) {
- MATHICGB_ASSERT(count <= capacity());
- if (count > size())
- resize(count);
- std::fill_n(begin(), count, t);
- }
-
- /// There must be enough capacity for the new size. This is why there is no
- /// push_back and only a rawPushBack --- to remind you of the changed
- /// contract.
- void rawPushBack(const T& t) {
- MATHICGB_ASSERT(size() < capacity());
- new (mEnd) T(t);
- ++mEnd;
- }
-
- void pop_back() {
- MATHICGB_ASSERT(!empty());
- mEnd->~T();
- --mEnd;
- }
-
- void swap(RawVector<T>& v) {
- std::swap(mBegin, v.mBegin);
- std::swap(mEnd, v.mEnd);
- std::swap(mCapacityEnd, v.mCapacityEnd);
- }
-
- void clear() {
- while (!empty())
- pop_back();
- }
-
- // **** Extra functionality not available on std::vector
-
- // memcpy onto the end of the vector.
- void memcpy(const T* from, size_t countOfT) {
- MATHICGB_ASSERT(countOfT <= capacityToGo());
- std::memcpy(mEnd, from, countOfT * sizeof(T));
- mEnd += countOfT;
- }
-
- /// Unused capacity.
- size_t capacityToGo() const {
- return mCapacityEnd - mEnd;
- }
-
- /// Returns true if there is no more capacity left. That is, if
- /// capacity() == size().
- bool atCapacity() const {
- return mEnd == mCapacityEnd;
- }
-
- /// Sets this object to its null state without destructing memory. Returns
- /// a pointer to the previous beginning of the buffer.
- pointer releaseMemory() {
- const auto oldBegin = mBegin;
- mBegin = 0;
- mEnd = 0;
- mCapacityEnd = 0;
- return oldBegin;
- }
-
- /// Takes over the new memory that is passed in, copies the old values to the
- /// new memory and destructs the old values. Returns a pointer to the previous
- /// beginning of the buffer.
- pointer setMemoryAndCopy(
- pointer begin,
- pointer capacityEnd
- ) {
- MATHICGB_ASSERT(size() <=
- static_cast<size_type>(std::distance(begin, capacityEnd)));
- const auto oldBegin = mBegin;
- const auto end = std::copy(mBegin, mEnd, begin);
- *this = RawVector<T>(begin, end, capacityEnd);
- return oldBegin;
- }
-
- /// Takes over the new memory that is passed in without destructing memory.
- /// Returns a pointer to the previous beginning of the buffer.
- pointer releaseAndSetMemory(
- pointer begin,
- pointer end,
- pointer capacityEnd
- ) {
- const auto oldBegin = mBegin;
- mBegin = begin;
- mEnd = end;
- mCapacityEnd = capacityEnd;
- return oldBegin;
- }
-
- /// Destructs memory and then takes over the new memory that is passed in.
- /// Does not deallocate the backing memory. Returns a pointer to the previous
- /// beginning of the buffer.
- pointer clearAndSetMemory(
- pointer begin,
- pointer end,
- pointer capacityEnd
- ) {
- clear();
- const auto oldBegin = mBegin;
- mBegin = begin;
- mEnd = end;
- mCapacityEnd = capacityEnd;
- return oldBegin;
- }
-
-private:
- T* mBegin;
- T* mEnd;
- T* mCapacityEnd;
-};
-
-namespace std {
- template<class T>
- void swap(RawVector<T>& a, RawVector<T>& b) {
- a.swap(b);
- }
-}
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_RAW_VECTOR_GUARD
+#define MATHICGB_RAW_VECTOR_GUARD
+
+#include <iterator>
+#include <cstddef>
+#include <memory>
+#include <utility>
+#include <algorithm>
+#include <stdexcept>
+#include <cstring>
+
+MATHICGB_NAMESPACE_BEGIN
+
+/// RawVector mimics std::vector except that it does not do memory management.
+/// So you can directly access the pointers to memory and you can replace them
+/// with any other pointers that you need to.
+///
+/// Warning: RawVector is called raw because it does not allocate any memory,
+/// so it is an error to insert elements that there is not enough space for -
+/// you need to make sure ahead of time that there is enough space.
+///
+/// This class makes it possible to have a lot of the convenience of the
+/// std::vector interface even in places where std::vector cannot be used
+/// because of a need for manual memory management.
+template<class T>
+class RawVector {
+public:
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T* iterator;
+ typedef const T* const_iterator;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ /// Initializes to the null state.
+ RawVector(): mBegin(0), mEnd(0), mCapacityEnd(0) {}
+
+ /// Copies the pointers from v. It is a shallow copy.
+ RawVector(const RawVector& v):
+ mBegin(v.mBegin),
+ mEnd(v.mEnd),
+ mCapacityEnd(v.mCapacityEnd) {}
+
+ /// Copies the pointers from v. It is a shallow copy. Sets v to a null state.
+ RawVector(RawVector&& v):
+ mBegin(v.mBegin),
+ mEnd(v.mEnd),
+ mCapacityEnd(v.mCapacityEnd)
+ {
+ v.releaseMemory();
+ }
+
+ RawVector(pointer begin, pointer end):
+ mBegin(begin),
+ mEnd(end),
+ mCapacityEnd(end) {}
+
+ RawVector(pointer begin, pointer end, pointer capacityEnd):
+ mBegin(begin),
+ mEnd(end),
+ mCapacityEnd(capacityEnd) {}
+
+ /// As clear() --- does not free memory.
+ ~RawVector() {
+ clear();
+ }
+
+ /// There is no operator== to avoid confusion about whether it compares
+ /// pointers or contents. Instead, there is this.
+ bool contentsEqual(const RawVector<T>& v) const {
+ return std::equal(begin(), end(), v.begin());
+ }
+
+ /// Copies the pointers from v. It is a shallow copy.
+ RawVector<T>& operator=(const RawVector& v) {
+ mBegin = v.mBegin;
+ mEnd = v.mEnd;
+ mCapacityEnd = v.mCapacityEnd;
+ return *this;
+ }
+
+ /// Copies the pointers from v. It is a shallow copy. Sets v to the null state.
+ RawVector<T>& operator=(RawVector&& v) {
+ mBegin = v.mBegin;
+ mEnd = v.mEnd;
+ mCapacityEnd = v.mCapacityEnd;
+ v.releaseMemory();
+ return *this;
+ }
+
+ iterator begin() {return mBegin;}
+ const_iterator begin() const {return mBegin;}
+ iterator end() {return mEnd;}
+ const_iterator end() const {return mEnd;}
+
+ reverse_iterator rbegin() {return reverse_iterator(end());}
+ const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}
+ reverse_iterator rend() {return reverse_iterator(begin());}
+ const_reverse_iterator rend() const {return const_reverse_iterator(begin());}
+
+ size_type size() const {return mEnd - mBegin;}
+ size_type max_size() const {return std::numeric_limits<size_type>::max();}
+
+ /// There must be enough capacity for the new size.
+ void resize(const size_type newSize) {
+ MATHICGB_ASSERT(newSize <= capacity());
+ while (newSize > size()) {
+ new (mEnd) T();
+ ++mEnd;
+ }
+ while (newSize < size()) {
+ --mEnd;
+ mEnd->~T();
+ }
+ MATHICGB_ASSERT(newSize == size());
+ }
+
+ size_type capacity() const {return mCapacityEnd - mBegin;}
+
+ bool empty() const {return mBegin == mEnd;}
+
+ reference operator[](size_type index) {
+ MATHICGB_ASSERT(index < size());
+ return mBegin[index];
+ }
+
+ const_reference operator[](size_type index) const {
+ MATHICGB_ASSERT(index < size());
+ return mBegin[index];
+ }
+
+ reference at(size_type index) {
+ if (index >= size())
+ throw std::out_of_range("Invalid index in RawVector::at.");
+ return mBegin[index];
+ }
+
+ const_reference at(size_type index) const {
+ if (index >= size())
+ throw std::out_of_range("Invalid index in RawVector::at.");
+ return mBegin[index];
+ }
+
+ reference front() {
+ MATHICGB_ASSERT(!empty());
+ return *mBegin;
+ }
+
+ const_reference front() const {
+ MATHICGB_ASSERT(!empty());
+ return *mBegin;
+ }
+
+ reference back() {
+ MATHICGB_ASSERT(!empty());
+ return *(mEnd - 1);
+ }
+
+ const_reference back() const {
+ MATHICGB_ASSERT(!empty());
+ return *(mEnd - 1);
+ }
+
+ size_t memoryUse() const {
+ return capacity() * sizeof(value_type);
+ }
+
+ size_t memoryUseTrimmed() const {
+ return size() * sizeof(value_type);
+ }
+
+ /// There must be enough capacity for the new size.
+ template<class Iter>
+ void rawAssign(Iter begin, Iter end) {
+ const size_t count = std::distance(begin, end);
+ MATHICGB_ASSERT(count <= capacity());
+ if (count > size())
+ resize(count);
+ std::copy(begin, end, mBegin);
+ }
+
+ /// There must be enough capacity for the new size.
+ void rawAssign(size_type count, const T& t) {
+ MATHICGB_ASSERT(count <= capacity());
+ if (count > size())
+ resize(count);
+ std::fill_n(begin(), count, t);
+ }
+
+ /// There must be enough capacity for the new size. This is why there is no
+ /// push_back and only a rawPushBack --- to remind you of the changed
+ /// contract.
+ void rawPushBack(const T& t) {
+ MATHICGB_ASSERT(size() < capacity());
+ new (mEnd) T(t);
+ ++mEnd;
+ }
+
+ void pop_back() {
+ MATHICGB_ASSERT(!empty());
+ mEnd->~T();
+ --mEnd;
+ }
+
+ void swap(RawVector<T>& v) {
+ std::swap(mBegin, v.mBegin);
+ std::swap(mEnd, v.mEnd);
+ std::swap(mCapacityEnd, v.mCapacityEnd);
+ }
+
+ void clear() {
+ while (!empty())
+ pop_back();
+ }
+
+ // **** Extra functionality not available on std::vector
+
+ // memcpy onto the end of the vector.
+ void memcpy(const T* from, size_t countOfT) {
+ MATHICGB_ASSERT(countOfT <= capacityToGo());
+ std::memcpy(mEnd, from, countOfT * sizeof(T));
+ mEnd += countOfT;
+ }
+
+ /// Unused capacity.
+ size_t capacityToGo() const {
+ return mCapacityEnd - mEnd;
+ }
+
+ /// Returns true if there is no more capacity left. That is, if
+ /// capacity() == size().
+ bool atCapacity() const {
+ return mEnd == mCapacityEnd;
+ }
+
+ /// Sets this object to its null state without destructing memory. Returns
+ /// a pointer to the previous beginning of the buffer.
+ pointer releaseMemory() {
+ const auto oldBegin = mBegin;
+ mBegin = 0;
+ mEnd = 0;
+ mCapacityEnd = 0;
+ return oldBegin;
+ }
+
+ /// Takes over the new memory that is passed in, copies the old values to the
+ /// new memory and destructs the old values. Returns a pointer to the previous
+ /// beginning of the buffer.
+ pointer setMemoryAndCopy(
+ pointer begin,
+ pointer capacityEnd
+ ) {
+ MATHICGB_ASSERT(size() <=
+ static_cast<size_type>(std::distance(begin, capacityEnd)));
+ const auto oldBegin = mBegin;
+ const auto end = std::copy(mBegin, mEnd, begin);
+ *this = RawVector<T>(begin, end, capacityEnd);
+ return oldBegin;
+ }
+
+ /// Takes over the new memory that is passed in without destructing memory.
+ /// Returns a pointer to the previous beginning of the buffer.
+ pointer releaseAndSetMemory(
+ pointer begin,
+ pointer end,
+ pointer capacityEnd
+ ) {
+ const auto oldBegin = mBegin;
+ mBegin = begin;
+ mEnd = end;
+ mCapacityEnd = capacityEnd;
+ return oldBegin;
+ }
+
+ /// Destructs memory and then takes over the new memory that is passed in.
+ /// Does not deallocate the backing memory. Returns a pointer to the previous
+ /// beginning of the buffer.
+ pointer clearAndSetMemory(
+ pointer begin,
+ pointer end,
+ pointer capacityEnd
+ ) {
+ clear();
+ const auto oldBegin = mBegin;
+ mBegin = begin;
+ mEnd = end;
+ mCapacityEnd = capacityEnd;
+ return oldBegin;
+ }
+
+private:
+ T* mBegin;
+ T* mEnd;
+ T* mCapacityEnd;
+};
+
+namespace std {
+ template<class T>
+ void swap(RawVector<T>& a, RawVector<T>& b) {
+ a.swap(b);
+ }
+}
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/Reducer.cpp b/src/mathicgb/Reducer.cpp
index ed344cf..a06a7b4 100755
--- a/src/mathicgb/Reducer.cpp
+++ b/src/mathicgb/Reducer.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "Reducer.hpp"
@@ -15,11 +17,12 @@
#include "ReducerHash.hpp"
#include "ReducerHashPack.hpp"
#include "F4Reducer.hpp"
-
#include "SigPolyBasis.hpp"
#include <iostream>
#include <algorithm>
+MATHICGB_NAMESPACE_BEGIN
+
Reducer::Reducer():
stats_maxsize(0),
stats_maxsize_live(0),
@@ -199,7 +202,4 @@ Reducer::Stats::Stats():
void Reducer::dump() const {
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/Reducer.hpp b/src/mathicgb/Reducer.hpp
index fcdcbda..81a5e2d 100755
--- a/src/mathicgb/Reducer.hpp
+++ b/src/mathicgb/Reducer.hpp
@@ -1,13 +1,15 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _Reducer_h_
-#define _Reducer_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_REDUCER_GUARD
+#define MATHICGB_REDUCER_GUARD
#include "PolyRing.hpp"
#include "Poly.hpp"
#include <memtailor.h>
#include <memory>
+MATHICGB_NAMESPACE_BEGIN
+
class SigPolyBasis;
class PolyBasis;
@@ -164,9 +166,5 @@ protected:
Stats mClassicStats;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/ReducerDedup.hpp b/src/mathicgb/ReducerDedup.hpp
index 46f08fa..d194266 100755
--- a/src/mathicgb/ReducerDedup.hpp
+++ b/src/mathicgb/ReducerDedup.hpp
@@ -1,13 +1,14 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
-#ifndef _reducer_dedup_h_
-#define _reducer_dedup_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_REDUCER_DEDUP_GUARD
+#define MATHICGB_REDUCER_DEDUP_GUARD
+#include "TypicalReducer.hpp"
+#include "ReducerHelper.hpp"
#include <memtailor.h>
#include <mathic.h>
-#include "TypicalReducer.hpp"
-#include "ReducerHelper.hpp"
+MATHICGB_NAMESPACE_BEGIN
template<template<typename ConfigType> class Queue> class ReducerDedup;
@@ -181,10 +182,5 @@ size_t ReducerDedup<Q>::getMemoryUse() const
return TypicalReducer::getMemoryUse() + mQueue.getMemoryUse();
}
-
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/ReducerHash.hpp b/src/mathicgb/ReducerHash.hpp
index 098b306..0db8685 100755
--- a/src/mathicgb/ReducerHash.hpp
+++ b/src/mathicgb/ReducerHash.hpp
@@ -1,14 +1,15 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
-#ifndef _reducer_hash_h_
-#define _reducer_hash_h_
-
-#include <memtailor.h>
-#include <mathic.h>
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_REDUCER_HASH_GUARD
+#define MATHICGB_REDUCER_HASH_GUARD
#include "TypicalReducer.hpp"
#include "ReducerHelper.hpp"
#include "PolyHashTable.hpp"
+#include <memtailor.h>
+#include <mathic.h>
+
+MATHICGB_NAMESPACE_BEGIN
template<template<typename ConfigType> class Queue> class ReducerHash;
@@ -179,9 +180,5 @@ size_t ReducerHash<Q>::getMemoryUse() const
return result;
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/ReducerHashPack.hpp b/src/mathicgb/ReducerHashPack.hpp
index 53ca579..c965a94 100755
--- a/src/mathicgb/ReducerHashPack.hpp
+++ b/src/mathicgb/ReducerHashPack.hpp
@@ -1,14 +1,15 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
-#ifndef _reducer_hash_pack_h
-#define _reducer_hash_pack_h
-
-#include <mathic.h>
-#include <memtailor.h>
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_REDUCER_HASH_PACK_GUARD
+#define MATHICGB_REDUCER_HASH_PACK_GUARD
#include "TypicalReducer.hpp"
#include "ReducerHelper.hpp"
#include "PolyHashTable.hpp"
+#include <mathic.h>
+#include <memtailor.h>
+
+MATHICGB_NAMESPACE_BEGIN
template<template<typename ConfigType> class Queue> class ReducerHashPack;
@@ -276,9 +277,5 @@ size_t ReducerHashPack<Q>::getMemoryUse() const
mHashTable.getMemoryUse();
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/ReducerHelper.hpp b/src/mathicgb/ReducerHelper.hpp
old mode 100644
new mode 100755
index c604f23..f32f190
--- a/src/mathicgb/ReducerHelper.hpp
+++ b/src/mathicgb/ReducerHelper.hpp
@@ -1,11 +1,15 @@
-#ifndef _reducer_helper_h_
-#define _reducer_helper_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_REDUCER_HELPER_GUARD
+#define MATHICGB_REDUCER_HELPER_GUARD
// This namespace contains functions and classees that are useful for
// writing subclasses of Reducer.
#include "PolyRing.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
namespace ReducerHelper {
// ************** Configurations **********************
@@ -84,9 +88,5 @@ namespace ReducerHelper {
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/ReducerNoDedup.hpp b/src/mathicgb/ReducerNoDedup.hpp
index 630d5d5..e4634e6 100755
--- a/src/mathicgb/ReducerNoDedup.hpp
+++ b/src/mathicgb/ReducerNoDedup.hpp
@@ -1,13 +1,14 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
-#ifndef _reducer_nodedup_h_
-#define _reducer_nodedup_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_REDUCER_NO_DEDUP_GUARD
+#define MATHICGB_REDUCER_NO_DEDUP_GUARD
+#include "TypicalReducer.hpp"
+#include "ReducerHelper.hpp"
#include <memtailor.h>
#include <mathic.h>
-#include "TypicalReducer.hpp"
-#include "ReducerHelper.hpp"
+MATHICGB_NAMESPACE_BEGIN
template<template<typename ConfigType> class Queue> class ReducerNoDedup;
@@ -175,10 +176,5 @@ size_t ReducerNoDedup<Q>::getMemoryUse() const
return TypicalReducer::getMemoryUse() + mQueue.getMemoryUse();
}
-
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/ReducerPack.hpp b/src/mathicgb/ReducerPack.hpp
index a1d7c3c..97984f9 100755
--- a/src/mathicgb/ReducerPack.hpp
+++ b/src/mathicgb/ReducerPack.hpp
@@ -1,13 +1,14 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
-#ifndef _reducer_pack_h_
-#define _reducer_pack_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_REDUCER_PACK_GUARD
+#define MATHICGB_REDUCER_PACK_GUARD
+#include "TypicalReducer.hpp"
+#include "ReducerHelper.hpp"
#include <memtailor.h>
#include <mathic.h>
-#include "TypicalReducer.hpp"
-#include "ReducerHelper.hpp"
+MATHICGB_NAMESPACE_BEGIN
template<template<typename> class Queue>
class ReducerPack : public TypicalReducer {
@@ -238,9 +239,5 @@ size_t ReducerPack<Q>::getMemoryUse() const
mPool.getMemoryUse();
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/ReducerPackDedup.hpp b/src/mathicgb/ReducerPackDedup.hpp
index 07776b6..f27f78f 100755
--- a/src/mathicgb/ReducerPackDedup.hpp
+++ b/src/mathicgb/ReducerPackDedup.hpp
@@ -1,13 +1,14 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
-#ifndef _reducer_pack_dedup_h_
-#define _reducer_pack_dedup_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_REDUCER_PACK_DEDUP_GUARD
+#define MATHICGB_REDUCER_PACK_DEDUP_GUARD
+#include "TypicalReducer.hpp"
+#include "ReducerHelper.hpp"
#include <memtailor.h>
#include <mathic.h>
-#include "TypicalReducer.hpp"
-#include "ReducerHelper.hpp"
+MATHICGB_NAMESPACE_BEGIN
template<template<typename> class Queue>
class ReducerPackDedup : public TypicalReducer {
@@ -297,10 +298,5 @@ size_t ReducerPackDedup<Q>::getMemoryUse() const
mPool.getMemoryUse();
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
-
diff --git a/src/mathicgb/SPairs.cpp b/src/mathicgb/SPairs.cpp
index b9ce010..6551e71 100755
--- a/src/mathicgb/SPairs.cpp
+++ b/src/mathicgb/SPairs.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "SPairs.hpp"
@@ -25,6 +27,8 @@ MATHICGB_DEFINE_LOG_DOMAIN(
MATHICGB_DEFINE_LOG_ALIAS("SPairs", "SPairEarly,SPairLate");
MATHICGB_DEFINE_LOG_ALIAS("SPairsDetail", "SPairs,SPairDegree,SPairLcm");
+MATHICGB_NAMESPACE_BEGIN
+
SPairs::SPairs(const PolyBasis& basis, bool preferSparseSPairs):
mMonoid(basis.ring().monoid()),
mOrderMonoid(OrderMonoid::create(mMonoid)),
@@ -679,3 +683,5 @@ void SPairs::QueueConfiguration::computePairData(
orderMonoid().lcm(monoid(), leadA, monoid(), leadB, orderBy);
return; //todo: return true;
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/SPairs.hpp b/src/mathicgb/SPairs.hpp
index c37b373..bbd911b 100755
--- a/src/mathicgb/SPairs.hpp
+++ b/src/mathicgb/SPairs.hpp
@@ -1,11 +1,15 @@
-#ifndef _s_pairs_h_
-#define _s_pairs_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_S_PAIRS_GUARD
+#define MATHICGB_S_PAIRS_GUARD
#include "PolyBasis.hpp"
#include <utility>
#include <mathic.h>
#include <memory>
+MATHICGB_NAMESPACE_BEGIN
+
class PolyBasis;
// Stores the set of pending S-pairs for use in the classic Buchberger
@@ -252,32 +256,35 @@ private:
(OrderMonoid::Mono*, Index, Index, QueueConfiguration&);
};
+MATHICGB_NAMESPACE_END
+
namespace mathic {
namespace PairQueueNamespace {
- template<>
- inline void constructPairData<SPairs::QueueConfiguration>(
+ template<>
+ inline void constructPairData<mgb::SPairs::QueueConfiguration>(
void* memory,
const Index col,
const Index row,
- SPairs::QueueConfiguration& conf
+ mgb::SPairs::QueueConfiguration& conf
) {
- MATHICGB_ASSERT(memory != 0);
- MATHICGB_ASSERT(col > row);
- auto pd = new (memory) SPairs::OrderMonoid::Mono(conf.allocPairData());
- conf.computePairData(col, row, *pd);
- }
-
- template<>
- inline void destructPairData(
- SPairs::OrderMonoid::Mono* pd,
+ MATHICGB_ASSERT(memory != 0);
+ MATHICGB_ASSERT(col > row);
+ auto pd = new (memory)
+ mgb::SPairs::OrderMonoid::Mono(conf.allocPairData());
+ conf.computePairData(col, row, *pd);
+ }
+
+ template<>
+ inline void destructPairData(
+ mgb::SPairs::OrderMonoid::Mono* pd,
const Index col,
const Index row,
- SPairs::QueueConfiguration& conf
+ mgb::SPairs::QueueConfiguration& conf
) {
- MATHICGB_ASSERT(pd != 0);
- MATHICGB_ASSERT(col > row);
- conf.freePairData(std::move(*pd));
- }
+ MATHICGB_ASSERT(pd != 0);
+ MATHICGB_ASSERT(col > row);
+ conf.freePairData(std::move(*pd));
+ }
}
}
diff --git a/src/mathicgb/Scanner.cpp b/src/mathicgb/Scanner.cpp
index cc67dff..5d8ec09 100755
--- a/src/mathicgb/Scanner.cpp
+++ b/src/mathicgb/Scanner.cpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "Scanner.hpp"
@@ -6,6 +8,8 @@
#include <sstream>
#include <cstring>
+MATHICGB_NAMESPACE_BEGIN
+
static const size_t BufferSize =
#ifdef MATHICGB_DEBUG
1;
@@ -182,3 +186,5 @@ bool Scanner::readBuffer(size_t minRead) {
return didReadCount >= minRead;
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/Scanner.hpp b/src/mathicgb/Scanner.hpp
index fdbdc0f..d529ae9 100755
--- a/src/mathicgb/Scanner.hpp
+++ b/src/mathicgb/Scanner.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_SCANNER_GUARD
#define MATHICGB_SCANNER_GUARD
@@ -11,6 +13,8 @@
#include <sstream>
#include <istream>
+MATHICGB_NAMESPACE_BEGIN
+
/// This class offers an input interface which is more convenient and
/// often more efficient than dealing with a FILE* or std::istream
/// directly. It keeps track of the current line number to report
@@ -270,4 +274,5 @@ bool Scanner::matchReadIntegerNoSign(T& t, bool negate) {
return false;
}
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/ScopeExit.hpp b/src/mathicgb/ScopeExit.hpp
index 5ca876a..2cb7f81 100755
--- a/src/mathicgb/ScopeExit.hpp
+++ b/src/mathicgb/ScopeExit.hpp
@@ -1,98 +1,104 @@
-#ifndef MATHICGB_SCOPE_EXIT_GUARD
-#define MATHICGB_SCOPE_EXIT_GUARD
-
-// Guard holds an action to call and calls it unless it has been released.
-template<class T>
-class Guard {
-public:
- ~Guard() {
- if (mOwning && mActive)
- mAction();
- }
-
-private:
- friend struct GuardMaker;
- Guard(T&& action, const bool& active):
- mAction(std::move(action)), mOwning(true), mActive(active) {}
-
- // Most compilers should elide the call to this construtor, but it must be
- // here anyway and we should support even a crazy compiler that decides to
- // call it.
- Guard(Guard<T>&& guard):
- mAction(std::move(guard.mAction)), mOwning(true), mActive(guard.mActive)
- {
- assert(guard.mActive);
- guard.mOwning = false; // to avoid calling mAction twice
- }
-
- bool mOwning;
- const bool& mActive;
- const T mAction;
-};
-
-// The class user code interacts with to dismiss an action.
-class Dismisser {
-public:
- Dismisser(bool& active): mActive(active) {}
- void dismiss() {mActive = false;}
-
-private:
- bool& mActive;
-};
-
-// Helper class that allows convenient syntax for the macro by overloading
-// operator+.
-struct GuardMaker {
-public:
- GuardMaker(const bool& active): mActive(active) {}
-
- template<class T>
- Guard<T> operator+(T&& t) {return Guard<T>(std::forward<T>(t), mActive);}
-
-private:
- const bool& mActive;
-};
-
-#define MYLIB__CAT_HELPER(A, B) A##B
-#define MYLIB__CAT(A, B) MYLIB__CAT_HELPER(A, B)
-#define MYLIB__UNIQUE(NAME) MYLIB__CAT(MyLib_,MYLIB__CAT(NAME,__LINE__))
-
-// Example, with no need to dismiss:
-// FILE* file = fopen("file.txt", "r");
-// MATHICGB_SCOPE_EXIT() {
-// fclose(file);
-// std::cout << "file closed";
-// };
-// // ...
-// return; // the file is closed
-//
-// Example, with need to dismiss:
-// v.push_back(5);
-// MATHICGB_SCOPE_EXIT(name) {v.pop_back();};
-// // ...
-// if (error)
-// return; // the pop_back is done
-// name.dismiss();
-// return; // the pop_back is not done
-//
-// The middle line is a no-op if the name parameter expands to nothing.
-// When NAME expands to nothing, we need the static_cast to prevent
-// the compiler from parsing the middle line as a redeclaration of
-// myBool. In the final line we use that a const reference keeps
-// temporary objects alive until the end of the scope. It would be correct
-// to copy, but this way we can keep the copy constructor private
-// and help out any compiler that has issue with eliding that copy.
-#define MATHICGB_SCOPE_EXIT(NAME) \
- bool MYLIB__UNIQUE(active) = true; \
- ::Dismisser NAME(static_cast<bool&>(MYLIB__UNIQUE(active))); \
- const auto& MYLIB__UNIQUE(guard) = \
- ::GuardMaker(MYLIB__UNIQUE(active)) + [&]
-
-// Without this pragma, MSVC will say
-// warning C4003: not enough actual parameters for macro 'MYLIB_SCOPE_EXIT'
-// when using MYLIB_SCOPE_EXIT without a name parameter. Not very happy about
-// turning off the warning. I wonder if there is a way to avoid the warning in
-// this case without turning it off.
-#pragma warning (disable: 4003)
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_SCOPE_EXIT_GUARD
+#define MATHICGB_SCOPE_EXIT_GUARD
+
+MATHICGB_NAMESPACE_BEGIN
+
+// Guard holds an action to call and calls it unless it has been released.
+template<class T>
+class Guard {
+public:
+ ~Guard() {
+ if (mOwning && mActive)
+ mAction();
+ }
+
+private:
+ friend struct GuardMaker;
+ Guard(T&& action, const bool& active):
+ mAction(::std::move(action)), mOwning(true), mActive(active) {}
+
+ // Most compilers should elide the call to this construtor, but it must be
+ // here anyway and we should support even a crazy compiler that decides to
+ // call it.
+ Guard(Guard<T>&& guard):
+ mAction(::std::move(guard.mAction)), mOwning(true), mActive(guard.mActive)
+ {
+ assert(guard.mActive);
+ guard.mOwning = false; // to avoid calling mAction twice
+ }
+
+ bool mOwning;
+ const bool& mActive;
+ const T mAction;
+};
+
+// The class user code interacts with to dismiss an action.
+class Dismisser {
+public:
+ Dismisser(bool& active): mActive(active) {}
+ void dismiss() {mActive = false;}
+
+private:
+ bool& mActive;
+};
+
+// Helper class that allows convenient syntax for the macro by overloading
+// operator+.
+struct GuardMaker {
+public:
+ GuardMaker(const bool& active): mActive(active) {}
+
+ template<class T>
+ Guard<T> operator+(T&& t) {return Guard<T>(::std::forward<T>(t), mActive);}
+
+private:
+ const bool& mActive;
+};
+
+MATHICGB_NAMESPACE_END
+
+#define MYLIB__CAT_HELPER(A, B) A##B
+#define MYLIB__CAT(A, B) MYLIB__CAT_HELPER(A, B)
+#define MYLIB__UNIQUE(NAME) MYLIB__CAT(MyLib_,MYLIB__CAT(NAME,__LINE__))
+
+// Example, with no need to dismiss:
+// FILE* file = fopen("file.txt", "r");
+// MATHICGB_SCOPE_EXIT() {
+// fclose(file);
+// ::std::cout << "file closed";
+// };
+// // ...
+// return; // the file is closed
+//
+// Example, with need to dismiss:
+// v.push_back(5);
+// MATHICGB_SCOPE_EXIT(name) {v.pop_back();};
+// // ...
+// if (error)
+// return; // the pop_back is done
+// name.dismiss();
+// return; // the pop_back is not done
+//
+// The middle line is a no-op if the name parameter expands to nothing.
+// When NAME expands to nothing, we need the static_cast to prevent
+// the compiler from parsing the middle line as a redeclaration of
+// myBool. In the final line we use that a const reference keeps
+// temporary objects alive until the end of the scope. It would be correct
+// to copy, but this way we can keep the copy constructor private
+// and help out any compiler that has issue with eliding that copy.
+#define MATHICGB_SCOPE_EXIT(NAME) \
+ bool MYLIB__UNIQUE(active) = true; \
+ ::mgb::Dismisser NAME(static_cast<bool&>(MYLIB__UNIQUE(active))); \
+ const auto& MYLIB__UNIQUE(guard) = \
+ ::mgb::GuardMaker(MYLIB__UNIQUE(active)) + [&]
+
+// Without this pragma, MSVC will say
+// warning C4003: not enough actual parameters for macro 'MYLIB_SCOPE_EXIT'
+// when using MYLIB_SCOPE_EXIT without a name parameter. Not very happy about
+// turning off the warning. I wonder if there is a way to avoid the warning in
+// this case without turning it off.
+#pragma warning (disable: 4003)
+
+#endif
diff --git a/src/mathicgb/SigPolyBasis.cpp b/src/mathicgb/SigPolyBasis.cpp
index 8b1256d..f44551e 100755
--- a/src/mathicgb/SigPolyBasis.cpp
+++ b/src/mathicgb/SigPolyBasis.cpp
@@ -8,6 +8,8 @@
#include <iostream>
#include <iomanip>
+MATHICGB_NAMESPACE_BEGIN
+
SigPolyBasis::SigPolyBasis(
const PolyRing* R0,
int divisorLookupType,
@@ -489,7 +491,4 @@ SigPolyBasis::StoredRatioCmp::~StoredRatioCmp() {
mBasis.ring().freeMonomial(mTmp);
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/SigPolyBasis.hpp b/src/mathicgb/SigPolyBasis.hpp
index 225e571..ed3977a 100755
--- a/src/mathicgb/SigPolyBasis.hpp
+++ b/src/mathicgb/SigPolyBasis.hpp
@@ -11,6 +11,8 @@
#include <vector>
#include <set>
+MATHICGB_NAMESPACE_BEGIN
+
#ifndef USE_RATIO_RANK
#define USE_RATIO_RANK true
#endif
@@ -247,9 +249,5 @@ inline int SigPolyBasis::StoredRatioCmp::compare(size_t be) const {
}
}
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/SigSPairQueue.cpp b/src/mathicgb/SigSPairQueue.cpp
index e5f2def..bfe97e5 100755
--- a/src/mathicgb/SigSPairQueue.cpp
+++ b/src/mathicgb/SigSPairQueue.cpp
@@ -1,8 +1,12 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "SigSPairQueue.hpp"
#include "SigPolyBasis.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
SigSPairQueue::~SigSPairQueue() {}
namespace {
@@ -152,24 +156,45 @@ private:
mathic::PairQueueNamespace::DestructPairDataFunction<Configuration>;
};
+std::unique_ptr<SigSPairQueue> SigSPairQueue::create(
+ SigPolyBasis const& basis
+) {
+ return make_unique<ConcreteSigSPairQueue>(basis);
+}
+
+MATHICGB_NAMESPACE_END
+
namespace mathic {
namespace PairQueueNamespace {
template<>
- struct ConstructPairDataFunction<ConcreteSigSPairQueue::Configuration> {
- inline static void function
- (void* memory, Index col, Index row, ConcreteSigSPairQueue::Configuration& conf) {
+ struct ConstructPairDataFunction
+ <mgb::ConcreteSigSPairQueue::Configuration>
+ {
+ inline static void function(
+ void* memory,
+ Index col,
+ Index row,
+ mgb::ConcreteSigSPairQueue::Configuration& conf
+ ) {
MATHICGB_ASSERT(memory != 0);
MATHICGB_ASSERT(col > row);
- monomial* pd = new (memory) monomial
+ auto pd = new (memory)
+ mgb::ConcreteSigSPairQueue::Configuration::PairData
(conf.basis().ring().allocMonomial());
conf.computePairData(col, row, *pd);
}
- };
+ };
template<>
- struct DestructPairDataFunction<ConcreteSigSPairQueue::Configuration> {
- inline static void function
- (monomial* pd, Index col, Index row, ConcreteSigSPairQueue::Configuration& conf) {
+ struct DestructPairDataFunction
+ <mgb::ConcreteSigSPairQueue::Configuration>
+ {
+ inline static void function(
+ mgb::ConcreteSigSPairQueue::Configuration::PairData* pd,
+ Index col,
+ Index row,
+ mgb::ConcreteSigSPairQueue::Configuration& conf
+ ) {
MATHICGB_ASSERT(pd != 0);
MATHICGB_ASSERT(col > row);
conf.basis().ring().freeMonomial(*pd);
@@ -177,9 +202,3 @@ namespace mathic {
};
}
}
-
-std::unique_ptr<SigSPairQueue> SigSPairQueue::create(
- SigPolyBasis const& basis
-) {
- return make_unique<ConcreteSigSPairQueue>(basis);
-}
diff --git a/src/mathicgb/SigSPairQueue.hpp b/src/mathicgb/SigSPairQueue.hpp
index 0fb75ef..f745633 100755
--- a/src/mathicgb/SigSPairQueue.hpp
+++ b/src/mathicgb/SigSPairQueue.hpp
@@ -1,73 +1,78 @@
-#ifndef MATHICGB_SIG_S_PAIR_QUEUE_GUARD
-#define MATHICGB_SIG_S_PAIR_QUEUE_GUARD
-
-#include "PolyRing.hpp"
-#include <string>
-#include <vector>
-
-typedef unsigned short SmallIndex;
-typedef unsigned int BigIndex;
-
-struct PreSPair {
- BigIndex i;
- monomial signature;
-};
-
-class SigPolyBasis;
-
-// A priority queue on S-pairs where the priority is based on a
-// signature as in signature Grobner basis algorithms. The class is
-// not responsible for eliminating S-pairs or doing anything beyond
-// order the S-pairs.
-class SigSPairQueue {
-public:
- typedef PolyRing::Monoid Monoid;
-
- virtual ~SigSPairQueue();
-
- typedef std::pair<size_t, size_t> Pair;
- typedef std::vector<Pair> Pairs;
- //typedef std::pair<size_t, monomial> IndexSig;
- typedef PreSPair IndexSig;
- typedef std::vector<IndexSig> IndexSigs;
-
- // Takes the minimal signature in the queue and adds all S-pairs of
- // that signature to pairs. Clears pairs first. Returns null and
- // leaves pairs empty if the queue is empty.
- //
- // This class does not have an empty() method on purpose - you are
- // supposed to call this method until it returns null.
- virtual monomial popSignature(Pairs& pairs) = 0;
-
- // If (x, sig) is an element of pairsConsumed then (pairWith, x) is
- // added to the queue. sig must be the signature of the S-pair
- // (pairWith, x).
- //
- // ATTENTION: the class to pushPairs must have pairWith in the
- // sequence 0, 1, 2, 3 and so on. It follows from this that the
- // queue can figure out what pairWith is without being told. Thus
- // the purpose of pairWith is to make it possible to make an
- // assertion saying that the caller and the queue agree on what
- // pairWith is.
- //
- // ATTENTION: pairsConsumed will be cleared and the signatures in it
- // will be freed on the ring. This is because the queue will need to
- // alter pairsConsumed in various ways and clearing it after that is
- // cleaner than exposing what's being done to
- // pairsConsumed. Especially since after you did pushPairs there
- // would not be a reason to care about what its content was.
- virtual void pushPairs(size_t pairWith, IndexSigs& pairsConsumed) = 0;
-
- // Returns a string that describes the queue.
- virtual std::string name() const = 0;
-
- // Returns the number of pairs currently in the queue.
- virtual size_t pairCount() const = 0;
-
- // Returns number of bytes of memory used.
- virtual size_t memoryUse() const = 0;
-
- static std::unique_ptr<SigSPairQueue> create(SigPolyBasis const& basis);
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_SIG_S_PAIR_QUEUE_GUARD
+#define MATHICGB_SIG_S_PAIR_QUEUE_GUARD
+
+#include "PolyRing.hpp"
+#include <string>
+#include <vector>
+
+MATHICGB_NAMESPACE_BEGIN
+
+typedef unsigned short SmallIndex;
+typedef unsigned int BigIndex;
+
+struct PreSPair {
+ BigIndex i;
+ monomial signature;
+};
+
+class SigPolyBasis;
+
+// A priority queue on S-pairs where the priority is based on a
+// signature as in signature Grobner basis algorithms. The class is
+// not responsible for eliminating S-pairs or doing anything beyond
+// order the S-pairs.
+class SigSPairQueue {
+public:
+ typedef PolyRing::Monoid Monoid;
+
+ virtual ~SigSPairQueue();
+
+ typedef std::pair<size_t, size_t> Pair;
+ typedef std::vector<Pair> Pairs;
+ //typedef std::pair<size_t, monomial> IndexSig;
+ typedef PreSPair IndexSig;
+ typedef std::vector<IndexSig> IndexSigs;
+
+ // Takes the minimal signature in the queue and adds all S-pairs of
+ // that signature to pairs. Clears pairs first. Returns null and
+ // leaves pairs empty if the queue is empty.
+ //
+ // This class does not have an empty() method on purpose - you are
+ // supposed to call this method until it returns null.
+ virtual monomial popSignature(Pairs& pairs) = 0;
+
+ // If (x, sig) is an element of pairsConsumed then (pairWith, x) is
+ // added to the queue. sig must be the signature of the S-pair
+ // (pairWith, x).
+ //
+ // ATTENTION: the class to pushPairs must have pairWith in the
+ // sequence 0, 1, 2, 3 and so on. It follows from this that the
+ // queue can figure out what pairWith is without being told. Thus
+ // the purpose of pairWith is to make it possible to make an
+ // assertion saying that the caller and the queue agree on what
+ // pairWith is.
+ //
+ // ATTENTION: pairsConsumed will be cleared and the signatures in it
+ // will be freed on the ring. This is because the queue will need to
+ // alter pairsConsumed in various ways and clearing it after that is
+ // cleaner than exposing what's being done to
+ // pairsConsumed. Especially since after you did pushPairs there
+ // would not be a reason to care about what its content was.
+ virtual void pushPairs(size_t pairWith, IndexSigs& pairsConsumed) = 0;
+
+ // Returns a string that describes the queue.
+ virtual std::string name() const = 0;
+
+ // Returns the number of pairs currently in the queue.
+ virtual size_t pairCount() const = 0;
+
+ // Returns number of bytes of memory used.
+ virtual size_t memoryUse() const = 0;
+
+ static std::unique_ptr<SigSPairQueue> create(SigPolyBasis const& basis);
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/SigSPairs.cpp b/src/mathicgb/SigSPairs.cpp
index d3b7b81..696075a 100755
--- a/src/mathicgb/SigSPairs.cpp
+++ b/src/mathicgb/SigSPairs.cpp
@@ -1,4 +1,5 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "SigSPairs.hpp"
@@ -9,6 +10,8 @@
#include <stdexcept>
#include <iostream>
+MATHICGB_NAMESPACE_BEGIN
+
SigSPairs::SigSPairs(
const PolyRing *R0,
const SigPolyBasis *GB0,
@@ -317,7 +320,4 @@ size_t SigSPairs::getKnownSyzygyBitsMemoryUse() const {
return mKnownSyzygyTri.getMemoryUse();
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/SigSPairs.hpp b/src/mathicgb/SigSPairs.hpp
index 94a37f4..7518ad9 100755
--- a/src/mathicgb/SigSPairs.hpp
+++ b/src/mathicgb/SigSPairs.hpp
@@ -1,6 +1,7 @@
-
-#ifndef _spair_handler_h_
-#define _spair_handler_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_SIG_S_PAIRS_GUARD
+#define MATHICGB_SIG_S_PAIRS_GUARD
#include "PolyRing.hpp"
#include "KoszulQueue.hpp"
@@ -9,6 +10,8 @@
#include <memtailor.h>
#include <vector>
+MATHICGB_NAMESPACE_BEGIN
+
class Poly;
class MonomialTableArray;
class SigPolyBasis;
@@ -127,9 +130,5 @@ private:
mutable Stats mStats;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/SignatureGB.cpp b/src/mathicgb/SignatureGB.cpp
index 77f6524..c6ec1c0 100755
--- a/src/mathicgb/SignatureGB.cpp
+++ b/src/mathicgb/SignatureGB.cpp
@@ -1,4 +1,5 @@
-// Copyright 2011 Michael E. Stillman
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "SignatureGB.hpp"
@@ -9,6 +10,8 @@
#include "MTArray.hpp"
#include <mathic.h>
+MATHICGB_NAMESPACE_BEGIN
+
int tracingLevel = 0;
SignatureGB::SignatureGB(
@@ -729,7 +732,4 @@ unsigned long long SignatureGB::getSingularReductionCount() const {
return reducer->sigStats().singularReductions;
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/SignatureGB.hpp b/src/mathicgb/SignatureGB.hpp
index 282fe8a..109ff5e 100755
--- a/src/mathicgb/SignatureGB.hpp
+++ b/src/mathicgb/SignatureGB.hpp
@@ -1,7 +1,7 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _sig_gb_h_
-#define _sig_gb_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_SIGNATURE_G_B_GUARD
+#define MATHICGB_SIGNATURE_G_B_GUARD
#include "PolyRing.hpp"
#include "MTArray.hpp"
@@ -13,6 +13,8 @@
#include "MonoProcessor.hpp"
#include <map>
+MATHICGB_NAMESPACE_BEGIN
+
class SigSPairs;
class DivisorLookup;
@@ -104,9 +106,5 @@ private:
std::unique_ptr<MonoProcessor<Monoid>> mProcessor;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/SparseMatrix.cpp b/src/mathicgb/SparseMatrix.cpp
index 14171d8..6a2afb7 100755
--- a/src/mathicgb/SparseMatrix.cpp
+++ b/src/mathicgb/SparseMatrix.cpp
@@ -1,15 +1,19 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "SparseMatrix.hpp"
#include "Poly.hpp"
#include <algorithm>
+MATHICGB_NAMESPACE_BEGIN
+
void SparseMatrix::takeRowsFrom(SparseMatrix&& matrix) {
if (matrix.mRows.empty())
return;
if (mRows.empty()) {
- *this = std::move(matrix);
+ *this = ::std::move(matrix);
return;
}
@@ -20,8 +24,8 @@ void SparseMatrix::takeRowsFrom(SparseMatrix&& matrix) {
if (mBlock.mHasNoRows) // only put mBlock in chain of blocks if non-empty
oldestBlock->mPreviousBlock = mBlock.mPreviousBlock;
else
- oldestBlock->mPreviousBlock = new Block(std::move(mBlock));
- mBlock = std::move(matrix.mBlock);
+ oldestBlock->mPreviousBlock = new Block(::std::move(mBlock));
+ mBlock = ::std::move(matrix.mBlock);
mRows.insert(mRows.end(), matrix.mRows.begin(), matrix.mRows.end());
matrix.clear();
@@ -29,7 +33,7 @@ void SparseMatrix::takeRowsFrom(SparseMatrix&& matrix) {
void SparseMatrix::rowToPolynomial(
const RowIndex row,
- const std::vector<monomial>& colMonomials,
+ const ::std::vector<monomial>& colMonomials,
Poly& poly
) {
poly.setToZero();
@@ -47,7 +51,7 @@ void SparseMatrix::sortRowsByIncreasingPivots() {
SparseMatrix ordered;
const auto rowCount = this->rowCount();
- std::vector<RowIndex> rows(rowCount);
+ ::std::vector<RowIndex> rows(rowCount);
for (RowIndex row = 0; row < rowCount; ++row)
rows[row] = row;
@@ -66,16 +70,16 @@ void SparseMatrix::sortRowsByIncreasingPivots() {
}
return aIt == aEnd && bIt != bEnd;
};
- std::sort(rows.begin(), rows.end(), lexLess);
+ ::std::sort(rows.begin(), rows.end(), lexLess);
// construct ordered with pivot columns in increasing order
ordered.clear();
for (size_t i = 0; i < rowCount; ++i)
ordered.appendRow(*this, rows[i]);
- *this = std::move(ordered);
+ *this = ::std::move(ordered);
}
-void SparseMatrix::applyColumnMap(const std::vector<ColIndex>& colMap) {
+void SparseMatrix::applyColumnMap(const ::std::vector<ColIndex>& colMap) {
MATHICGB_ASSERT(colMap.size() >= computeColCount());
Block* block = &mBlock;
for (; block != 0; block = block->mPreviousBlock) {
@@ -96,7 +100,7 @@ void SparseMatrix::multiplyRow(
it.setScalar(modularProduct(it.scalar(), multiplier, modulus));
}
-void SparseMatrix::print(std::ostream& out) const {
+void SparseMatrix::print(::std::ostream& out) const {
if (rowCount() == 0)
out << "matrix with no rows\n";
for (RowIndex row = 0; row < rowCount(); ++row) {
@@ -108,7 +112,7 @@ void SparseMatrix::print(std::ostream& out) const {
}
}
-void SparseMatrix::printStatistics(std::ostream& out) const {
+void SparseMatrix::printStatistics(::std::ostream& out) const {
typedef mathic::ColumnPrinter ColPr;
ColPr pr;
@@ -139,8 +143,8 @@ void SparseMatrix::printStatistics(std::ostream& out) const {
out << '\n' << pr << "\n";
}
-std::string SparseMatrix::toString() const {
- std::ostringstream out;
+::std::string SparseMatrix::toString() const {
+ ::std::ostringstream out;
print(out);
return out.str();
}
@@ -199,7 +203,7 @@ SparseMatrix& SparseMatrix::operator=(const SparseMatrix& matrix) {
void SparseMatrix::swap(SparseMatrix& matrix) {
mBlock.swap(matrix.mBlock);
- using std::swap;
+ using ::std::swap;
swap(mRows, matrix.mRows);
swap(mMemoryQuantum, matrix.mMemoryQuantum);
}
@@ -228,7 +232,7 @@ SparseMatrix::ColIndex SparseMatrix::computeColCount() const {
for (RowIndex row = 0; row < rowCount(); ++row) {
const auto end = rowEnd(row);
for (auto it = rowBegin(row); it != end; ++it)
- colCount = std::max(colCount, it.index() + 1);
+ colCount = ::std::max(colCount, it.index() + 1);
}
return colCount;
}
@@ -249,7 +253,7 @@ void SparseMatrix::clear() {
}
void SparseMatrix::appendRowWithModulus(
- std::vector<uint64> const& v,
+ ::std::vector<uint64> const& v,
const Scalar modulus
) {
const auto count = static_cast<ColIndex>(v.size());
@@ -262,7 +266,7 @@ void SparseMatrix::appendRowWithModulus(
}
void SparseMatrix::appendRowWithModulusNormalized(
- std::vector<uint64> const& v,
+ ::std::vector<uint64> const& v,
const Scalar modulus
) {
uint16 multiply = 1;
@@ -286,7 +290,7 @@ void SparseMatrix::appendRowWithModulusNormalized(
}
bool SparseMatrix::appendRowWithModulusIfNonZero(
- std::vector<uint64> const& v,
+ ::std::vector<uint64> const& v,
const Scalar modulus
) {
appendRowWithModulus(v, modulus);
@@ -317,12 +321,12 @@ void SparseMatrix::reserveFreeEntries(const size_t freeCount) {
const size_t count = freeCount + ( // todo: detect overflow for this addition
mBlock.mHasNoRows ?
mBlock.mColIndices.size() :
- std::distance(mRows.back().mIndicesEnd, mBlock.mColIndices.end())
+ ::std::distance(mRows.back().mIndicesEnd, mBlock.mColIndices.end())
);
// @todo: fix memory leaks on exception
- auto oldBlock = new Block(std::move(mBlock));
+ auto oldBlock = new Block(::std::move(mBlock));
MATHICGB_ASSERT(mBlock.mColIndices.begin() == 0);
MATHICGB_ASSERT(mBlock.mScalars.begin() == 0);
MATHICGB_ASSERT(mBlock.mHasNoRows);
@@ -356,9 +360,9 @@ void SparseMatrix::reserveFreeEntries(const size_t freeCount) {
// remove the pending entries from old block so that counting the number
// of entries will give the correct result in future.
oldBlock->mColIndices.resize
- (std::distance(oldBlock->mColIndices.begin(), mRows.back().mIndicesEnd));
+ (::std::distance(oldBlock->mColIndices.begin(), mRows.back().mIndicesEnd));
oldBlock->mScalars.resize
- (std::distance(oldBlock->mScalars.begin(), mRows.back().mScalarsEnd));
+ (::std::distance(oldBlock->mScalars.begin(), mRows.back().mScalarsEnd));
mBlock.mPreviousBlock = oldBlock;
}
}
@@ -423,7 +427,7 @@ size_t SparseMatrix::Block::memoryUseTrimmed() const {
return mColIndices.memoryUseTrimmed() + mScalars.memoryUseTrimmed();
}
-std::ostream& operator<<(std::ostream& out, const SparseMatrix& matrix) {
+::std::ostream& operator<<(::std::ostream& out, const SparseMatrix& matrix) {
matrix.print(out);
return out;
}
@@ -444,7 +448,7 @@ namespace {
}
template<class T>
- void writeMany(const std::vector<T>& v, FILE* file) {
+ void writeMany(const ::std::vector<T>& v, FILE* file) {
if (v.empty())
return;
if (fwrite(v.data(), sizeof(T), v.size(), file) != v.size())
@@ -452,7 +456,7 @@ namespace {
}
template<class T>
- void readMany(FILE* file, size_t count, std::vector<T>& v) {
+ void readMany(FILE* file, size_t count, ::std::vector<T>& v) {
size_t const originalSize = v.size();
v.resize(originalSize + count);
if (fread(v.data() + originalSize, sizeof(T), count, file) != count)
@@ -483,7 +487,7 @@ void SparseMatrix::write(const Scalar modulus, FILE* file) const {
mathic::reportError("error while writing to file.");
}
- std::vector<uint32> entryCounts;
+ ::std::vector<uint32> entryCounts;
for (SparseMatrix::RowIndex row = 0; row < storedRowCount; ++row)
entryCounts.push_back(entryCountInRow(row));
writeMany<uint32>(entryCounts, file);
@@ -508,22 +512,22 @@ SparseMatrix::Scalar SparseMatrix::read(FILE* file) {
// Read scalars.
{
mBlock.mScalars.resize(entryCount);
- std::vector<uint16> scalars;
+ ::std::vector<uint16> scalars;
readMany(file, entryCount, scalars);
- std::copy(scalars.begin(), scalars.end(), mBlock.mScalars.begin());
+ ::std::copy(scalars.begin(), scalars.end(), mBlock.mScalars.begin());
}
// Read column indices.
{
mBlock.mColIndices.resize(entryCount);
- std::vector<uint32> indices;
+ ::std::vector<uint32> indices;
readMany(file, entryCount, indices);
- std::copy(indices.begin(), indices.end(), mBlock.mColIndices.begin());
+ ::std::copy(indices.begin(), indices.end(), mBlock.mColIndices.begin());
}
// Read where rows begin and end.
{
- std::vector<uint32> sizes;
+ ::std::vector<uint32> sizes;
readMany(file, rowCount, sizes);
uint32 runningOffset = 0;
for (auto it = sizes.begin(); it != sizes.end(); ++it) {
@@ -551,7 +555,7 @@ void SparseMatrix::writePBM(FILE* file) {
// Write PBM header
{
- std::stringstream out;
+ ::std::stringstream out;
out << "P1 " << colCount << ' ' << rowCount << '\n';
fputs(out.str().c_str(), file);
}
@@ -594,3 +598,5 @@ bool SparseMatrix::debugAssertValid() const {
}
return true;
}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/SparseMatrix.hpp b/src/mathicgb/SparseMatrix.hpp
index bbeef08..1ef19f6 100755
--- a/src/mathicgb/SparseMatrix.hpp
+++ b/src/mathicgb/SparseMatrix.hpp
@@ -1,3 +1,5 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#ifndef MATHICGB_SPARSE_MATRIX_GUARD
#define MATHICGB_SPARSE_MATRIX_GUARD
@@ -10,6 +12,9 @@
#include <sstream>
#include <string>
#include <iterator>
+
+MATHICGB_NAMESPACE_BEGIN
+
class Poly;
/** A class that implements a sparse matrix.
@@ -54,15 +59,15 @@ public:
{}
SparseMatrix(SparseMatrix&& matrix):
- mRows(std::move(matrix.mRows)),
- mBlock(std::move(matrix.mBlock)),
+ mRows(::std::move(matrix.mRows)),
+ mBlock(::std::move(matrix.mBlock)),
mMemoryQuantum(matrix.mMemoryQuantum)
{
}
SparseMatrix& operator=(SparseMatrix&& matrix) {
this->~SparseMatrix();
- new (this) SparseMatrix(std::move(matrix));
+ new (this) SparseMatrix(::std::move(matrix));
return *this;
}
@@ -154,11 +159,11 @@ public:
/// Prints the matrix in a human readable format to out.
/// Useful for debugging.
- void print(std::ostream& out) const;
+ void print(::std::ostream& out) const;
- void printStatistics(std::ostream& out) const;
+ void printStatistics(::std::ostream& out) const;
- std::string toString() const;
+ ::std::string toString() const;
/// Removes the leading trimThisMany columns. The columns are
/// removed by replacing all column indices col by col -
@@ -217,26 +222,26 @@ public:
void appendRow(const SparseMatrix& matrix, RowIndex row);
- void appendRowWithModulus(const std::vector<uint64>& v, Scalar modulus);
+ void appendRowWithModulus(const ::std::vector<uint64>& v, Scalar modulus);
template<class T>
- void appendRow(const std::vector<T>& v, ColIndex leadCol = 0);
+ void appendRow(const ::std::vector<T>& v, ColIndex leadCol = 0);
- void appendRowWithModulusNormalized(const std::vector<uint64>& v, Scalar modulus);
+ void appendRowWithModulusNormalized(const ::std::vector<uint64>& v, Scalar modulus);
// Returns true if the row was non-zero. Otherwise the row was not
// appended.
- bool appendRowWithModulusIfNonZero(const std::vector<uint64>& v, Scalar modulus);
+ bool appendRowWithModulusIfNonZero(const ::std::vector<uint64>& v, Scalar modulus);
/// Replaces all column indices i with colMap[i].
- void applyColumnMap(const std::vector<ColIndex>& colMap);
+ void applyColumnMap(const ::std::vector<ColIndex>& colMap);
void multiplyRow(RowIndex row, Scalar multiplier, Scalar modulus);
/// Let poly be the dot product of colMonomials and the given row.
void rowToPolynomial(
RowIndex row,
- const std::vector<monomial>& colMonomials,
+ const ::std::vector<monomial>& colMonomials,
Poly& poly);
/// Reorders the rows so that the index of the leading column in
@@ -257,12 +262,12 @@ public:
/// Iterates through the entries in a row.
class ConstRowIterator {
public:
- typedef const std::pair<ColIndex, Scalar> value_type;
+ typedef const ::std::pair<ColIndex, Scalar> value_type;
typedef ptrdiff_t difference_type;
typedef size_t distance_type;
typedef value_type* pointer;
typedef value_type& reference;
- typedef std::random_access_iterator_tag iterator_category;
+ typedef ::std::random_access_iterator_tag iterator_category;
ConstRowIterator& operator++() {
++mScalarIt;
@@ -312,12 +317,12 @@ public:
/// Iterates through the entries in a row.
class RowIterator {
public:
- typedef const std::pair<ColIndex, Scalar> value_type;
+ typedef const ::std::pair<ColIndex, Scalar> value_type;
typedef ptrdiff_t difference_type;
typedef size_t distance_type;
typedef value_type* pointer;
typedef value_type& reference;
- typedef std::random_access_iterator_tag iterator_category;
+ typedef ::std::random_access_iterator_tag iterator_category;
RowIterator& operator++() {
++mScalarIt;
@@ -383,20 +388,20 @@ private:
bool empty() const {return mIndicesBegin == mIndicesEnd;}
ColIndex size() const {
- return static_cast<ColIndex>(std::distance(mIndicesBegin, mIndicesEnd));
+ return static_cast<ColIndex>(::std::distance(mIndicesBegin, mIndicesEnd));
}
};
- std::vector<Row> mRows;
+ ::std::vector<Row> mRows;
/// Memory is allocated a block at a time. This avoids the need for copying
- /// that a std::vector normally does on reallocation. Believe it or not,
+ /// that a ::std::vector normally does on reallocation. Believe it or not,
/// copying sparse matrix memory due to reallocation was accounting for 5%
/// of the running time before this change.
struct Block {
Block(): mPreviousBlock(0), mHasNoRows(true) {}
Block(Block&& block):
- mColIndices(std::move(block.mColIndices)),
- mScalars(std::move(block.mScalars)),
+ mColIndices(::std::move(block.mColIndices)),
+ mScalars(::std::move(block.mScalars)),
mPreviousBlock(block.mPreviousBlock),
mHasNoRows(block.mHasNoRows)
{
@@ -405,15 +410,15 @@ private:
}
void swap(Block& block) {
- std::swap(mColIndices, block.mColIndices);
- std::swap(mScalars, block.mScalars);
- std::swap(mPreviousBlock, block.mPreviousBlock);
- std::swap(mHasNoRows, block.mHasNoRows);
+ ::std::swap(mColIndices, block.mColIndices);
+ ::std::swap(mScalars, block.mScalars);
+ ::std::swap(mPreviousBlock, block.mPreviousBlock);
+ ::std::swap(mHasNoRows, block.mHasNoRows);
}
Block& operator=(Block&& block) {
this->~Block();
- new (this) Block(std::move(block));
+ new (this) Block(::std::move(block));
return *this;
}
@@ -436,7 +441,7 @@ private:
template<class T>
void SparseMatrix::appendRow(
- std::vector<T> const& v,
+ ::std::vector<T> const& v,
const ColIndex leadCol
) {
#ifdef MATHICGB_DEBUG
@@ -447,7 +452,7 @@ void SparseMatrix::appendRow(
const auto count = static_cast<ColIndex>(v.size());
for (ColIndex col = leadCol; col < count; ++col) {
- MATHICGB_ASSERT(v[col] < std::numeric_limits<Scalar>::max());
+ MATHICGB_ASSERT(v[col] < ::std::numeric_limits<Scalar>::max());
if (v[col] != 0)
appendEntry(col, static_cast<Scalar>(v[col]));
}
@@ -459,6 +464,7 @@ inline void swap(SparseMatrix& a, SparseMatrix& b) {
a.swap(b);
}
-std::ostream& operator<<(std::ostream& out, const SparseMatrix& matrix);
+::std::ostream& operator<<(::std::ostream& out, const SparseMatrix& matrix);
+MATHICGB_NAMESPACE_END
#endif
diff --git a/src/mathicgb/TournamentReducer.cpp b/src/mathicgb/TournamentReducer.cpp
index 745063e..2add261 100755
--- a/src/mathicgb/TournamentReducer.cpp
+++ b/src/mathicgb/TournamentReducer.cpp
@@ -1,10 +1,12 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
#include "TournamentReducer.hpp"
#include <utility>
+MATHICGB_NAMESPACE_BEGIN
+
TournamentReducer::TournamentReducer(const PolyRing& ring):
mRing(ring),
mLeadTerm(0, mRing.allocMonomial()),
@@ -176,8 +178,4 @@ void TournamentReducer::dump() const
{
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
-
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/TournamentReducer.hpp b/src/mathicgb/TournamentReducer.hpp
index 5879517..b8de07c 100755
--- a/src/mathicgb/TournamentReducer.hpp
+++ b/src/mathicgb/TournamentReducer.hpp
@@ -1,12 +1,14 @@
-// Copyright 2011 Bjarke Roune, Michael E. Stillman
-
-#ifndef _tournament_reducer_h_
-#define _tournament_reducer_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_TOURNAMENT_REDUCER_GUARD
+#define MATHICGB_TOURNAMENT_REDUCER_GUARD
#include "TypicalReducer.hpp"
#include <mathic.h>
#include <memtailor.h>
+MATHICGB_NAMESPACE_BEGIN
+
class TournamentReducer : public TypicalReducer {
public:
TournamentReducer(const PolyRing& R);
@@ -74,9 +76,5 @@ private:
memt::BufferPool mPool;
};
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/TypicalReducer.cpp b/src/mathicgb/TypicalReducer.cpp
index e91cb5a..5c3f9df 100755
--- a/src/mathicgb/TypicalReducer.cpp
+++ b/src/mathicgb/TypicalReducer.cpp
@@ -1,228 +1,234 @@
-#include "stdinc.h"
-#include "TypicalReducer.hpp"
-
-#include "SigPolyBasis.hpp"
-#include "PolyBasis.hpp"
-#include <iostream>
-
-size_t TypicalReducer::preferredSetSize() const {
- return 1;
-}
-
-void TypicalReducer::reset()
-{
- mArena.freeAllAllocs();
- resetReducer();
-}
-
-size_t TypicalReducer::getMemoryUse() const {
- return mArena.getMemoryUse();
-}
-
-Poly* TypicalReducer::regularReduce(
- const_monomial sig,
- const_monomial multiple,
- size_t basisElement,
- const SigPolyBasis& basis)
-{
- const PolyRing& ring = basis.ring();
- ++mSigStats.reductions;
-
- monomial tproduct = ring.allocMonomial(mArena);
- monomial u = ring.allocMonomial(mArena);
- ring.monomialMult(multiple, basis.getLeadMonomial(basisElement), tproduct);
-
- size_t reducer = basis.regularReducer(sig, tproduct);
- if (reducer == static_cast<size_t>(-1)) {
- ++mSigStats.singularReductions;
- mArena.freeAllAllocs();
- return 0; // singular reduction: no regular top reduction possible
- }
-
- ring.monomialDivide(tproduct, basis.getLeadMonomial(reducer), u);
-
- coefficient coef;
- ring.coefficientSet(coef, 1);
- insertTail(const_term(coef, multiple), &basis.poly(basisElement));
-
- MATHICGB_ASSERT(ring.coefficientIsOne(basis.getLeadCoefficient(reducer)));
- ring.coefficientFromInt(coef, -1);
- insertTail(const_term(coef, u), &basis.poly(reducer));
- basis.basis().usedAsReducer(reducer);
-
- Poly* result = new Poly(ring);
-
- unsigned long long steps = 2; // number of steps in this reduction
- for (const_term v; leadTerm(v);) {
- MATHICGB_ASSERT(v.coeff != 0);
- reducer = basis.regularReducer(sig, v.monom);
- if (reducer == static_cast<size_t>(-1)) { // no reducer found
- result->appendTerm(v.coeff, v.monom);
- removeLeadTerm();
- } else { // reduce by reducer
- ++steps;
- basis.basis().usedAsReducer(reducer);
- monomial mon = ring.allocMonomial(mArena);
- ring.monomialDivide(v.monom, basis.getLeadMonomial(reducer), mon);
- ring.coefficientDivide(v.coeff, basis.getLeadCoefficient(reducer), coef);
- ring.coefficientNegateTo(coef);
- removeLeadTerm();
- insertTail(const_term(coef, mon), &basis.poly(reducer));
- }
- }
- result->makeMonic();
-
- mSigStats.steps += steps;
- mSigStats.maxSteps = std::max(mSigStats.maxSteps, steps);
- if (result->isZero())
- ++mSigStats.zeroReductions;
-
- reset();
- return result;
-}
-
-std::unique_ptr<Poly> TypicalReducer::classicReduce(const Poly& poly, const PolyBasis& basis) {
- monomial identity = basis.ring().allocMonomial(mArena);
- basis.ring().monomialSetIdentity(identity);
- insert(identity, &poly);
-
- return classicReduce(basis);
-}
-
-std::unique_ptr<Poly> TypicalReducer::classicTailReduce(const Poly& poly, const PolyBasis& basis) {
- MATHICGB_ASSERT(&poly.ring() == &basis.ring());
- MATHICGB_ASSERT(!poly.isZero());
- term identity;
- identity.monom = basis.ring().allocMonomial(mArena);
- basis.ring().monomialSetIdentity(identity.monom);
- basis.ring().coefficientSetOne(identity.coeff);
- insertTail(identity, &poly);
-
- std::unique_ptr<Poly> result(new Poly(basis.ring()));
- result->appendTerm(poly.getLeadCoefficient(), poly.getLeadMonomial());
-
- return classicReduce(std::move(result), basis);
-}
-
-std::unique_ptr<Poly> TypicalReducer::classicReduceSPoly(
- const Poly& a,
- const Poly& b,
- const PolyBasis& basis
-) {
- const PolyRing& ring = basis.ring();
-
- monomial lcm = ring.allocMonomial();
- ring.monomialLeastCommonMultiple
- (a.getLeadMonomial(), b.getLeadMonomial(), lcm);
-
- // insert tail of multiple of a
- monomial multiple1 = ring.allocMonomial();
- ring.monomialDivide(lcm, a.getLeadMonomial(), multiple1);
- coefficient plusOne;
- ring.coefficientSet(plusOne, 1);
- insertTail(const_term(plusOne, multiple1), &a);
-
- // insert tail of multiple of b
- monomial multiple2 = ring.allocMonomial();
- ring.monomialDivide(lcm, b.getLeadMonomial(), multiple2);
- coefficient minusOne = plusOne;
- ring.coefficientNegateTo(minusOne);
- insertTail(const_term(minusOne, multiple2), &b);
-
- std::unique_ptr<Poly> reduced = classicReduce(basis);
- ring.freeMonomial(lcm);
- ring.freeMonomial(multiple1);
- ring.freeMonomial(multiple2);
- return std::move(reduced);
-}
-
-void TypicalReducer::classicReduceSPolySet
-(std::vector<std::pair<size_t, size_t> >& spairs,
- const PolyBasis& basis,
- std::vector<std::unique_ptr<Poly> >& reducedOut) {
- for (auto it = spairs.begin(); it != spairs.end(); ++it) {
- auto reducedSPoly =
- classicReduceSPoly(basis.poly(it->first), basis.poly(it->second), basis);
- if (!reducedSPoly->isZero())
- reducedOut.push_back(std::move(reducedSPoly));
- }
-}
-
-void TypicalReducer::classicReducePolySet
-(const std::vector<std::unique_ptr<Poly> >& polys,
- const PolyBasis& basis,
- std::vector<std::unique_ptr<Poly> >& reducedOut)
-{
- for (auto it = polys.begin(); it != polys.end(); ++it) {
- auto reducedPoly = classicReduce(**it, basis);
- if (!reducedPoly->isZero())
- reducedOut.push_back(std::move(reducedPoly));
- }
-}
-
-void TypicalReducer::setMemoryQuantum(size_t quantum) {
-}
-
-std::unique_ptr<Poly> TypicalReducer::classicReduce
- (std::unique_ptr<Poly> result, const PolyBasis& basis) {
- const PolyRing& ring = basis.ring();
- MATHICGB_ASSERT(&result->ring() == &ring);
- ++mClassicStats.reductions;
-
- if (tracingLevel > 100)
- std::cerr << "Classic reduction begun." << std::endl;
-
- coefficient coef;
- unsigned long long steps = 0; // number of steps in this reduction
- for (const_term v; leadTerm(v);) {
- if (tracingLevel > 100) {
- std::cerr << "from reducer queue: ";
- basis.ring().monomialDisplay(std::cerr, v.monom);
- std::cerr << std::endl;
- }
-
- size_t reducer = basis.classicReducer(v.monom);
- if (reducer == static_cast<size_t>(-1)) { // no reducer found
- MATHICGB_ASSERT(
- result->isZero() ||
- basis.monoid().lessThan(v.monom, result->backMonomial())
- );
- result->appendTerm(v.coeff, v.monom);
- removeLeadTerm();
- } else { // reduce by reducer
- ++steps;
- basis.usedAsReducer(reducer);
- monomial mon = ring.allocMonomial(mArena);
- ring.monomialDivide(v.monom, basis.leadMonomial(reducer), mon);
- ring.coefficientDivide(v.coeff, basis.leadCoefficient(reducer), coef);
- ring.coefficientNegateTo(coef);
- removeLeadTerm();
- insertTail(const_term(coef, mon), &basis.poly(reducer));
-
- if (tracingLevel > 100) {
- std::cerr << "Reducing by basis element " << reducer << ": ";
- basis.poly(reducer).display(std::cerr);
- std::cerr << std::endl;
- std::cerr << "multiplied by: " << coef << " * ";
- basis.ring().monomialDisplay(std::cerr, mon);
- std::cerr << std::endl;
- }
- }
- }
- result->makeMonic();
-
- mClassicStats.steps += steps;
- mClassicStats.maxSteps = std::max(mClassicStats.maxSteps, steps);
- if (result->isZero())
- ++mClassicStats.zeroReductions;
-
- if (tracingLevel > 100)
- std::cerr << "Classic reduction done." << std::endl;
-
- reset();
- return std::move(result);
-}
-
-std::unique_ptr<Poly> TypicalReducer::classicReduce(const PolyBasis& basis) {
- return classicReduce(make_unique<Poly>(basis.ring()), basis);
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "stdinc.h"
+#include "TypicalReducer.hpp"
+
+#include "SigPolyBasis.hpp"
+#include "PolyBasis.hpp"
+#include <iostream>
+
+MATHICGB_NAMESPACE_BEGIN
+
+size_t TypicalReducer::preferredSetSize() const {
+ return 1;
+}
+
+void TypicalReducer::reset()
+{
+ mArena.freeAllAllocs();
+ resetReducer();
+}
+
+size_t TypicalReducer::getMemoryUse() const {
+ return mArena.getMemoryUse();
+}
+
+Poly* TypicalReducer::regularReduce(
+ const_monomial sig,
+ const_monomial multiple,
+ size_t basisElement,
+ const SigPolyBasis& basis)
+{
+ const PolyRing& ring = basis.ring();
+ ++mSigStats.reductions;
+
+ monomial tproduct = ring.allocMonomial(mArena);
+ monomial u = ring.allocMonomial(mArena);
+ ring.monomialMult(multiple, basis.getLeadMonomial(basisElement), tproduct);
+
+ size_t reducer = basis.regularReducer(sig, tproduct);
+ if (reducer == static_cast<size_t>(-1)) {
+ ++mSigStats.singularReductions;
+ mArena.freeAllAllocs();
+ return 0; // singular reduction: no regular top reduction possible
+ }
+
+ ring.monomialDivide(tproduct, basis.getLeadMonomial(reducer), u);
+
+ coefficient coef;
+ ring.coefficientSet(coef, 1);
+ insertTail(const_term(coef, multiple), &basis.poly(basisElement));
+
+ MATHICGB_ASSERT(ring.coefficientIsOne(basis.getLeadCoefficient(reducer)));
+ ring.coefficientFromInt(coef, -1);
+ insertTail(const_term(coef, u), &basis.poly(reducer));
+ basis.basis().usedAsReducer(reducer);
+
+ Poly* result = new Poly(ring);
+
+ unsigned long long steps = 2; // number of steps in this reduction
+ for (const_term v; leadTerm(v);) {
+ MATHICGB_ASSERT(v.coeff != 0);
+ reducer = basis.regularReducer(sig, v.monom);
+ if (reducer == static_cast<size_t>(-1)) { // no reducer found
+ result->appendTerm(v.coeff, v.monom);
+ removeLeadTerm();
+ } else { // reduce by reducer
+ ++steps;
+ basis.basis().usedAsReducer(reducer);
+ monomial mon = ring.allocMonomial(mArena);
+ ring.monomialDivide(v.monom, basis.getLeadMonomial(reducer), mon);
+ ring.coefficientDivide(v.coeff, basis.getLeadCoefficient(reducer), coef);
+ ring.coefficientNegateTo(coef);
+ removeLeadTerm();
+ insertTail(const_term(coef, mon), &basis.poly(reducer));
+ }
+ }
+ result->makeMonic();
+
+ mSigStats.steps += steps;
+ mSigStats.maxSteps = std::max(mSigStats.maxSteps, steps);
+ if (result->isZero())
+ ++mSigStats.zeroReductions;
+
+ reset();
+ return result;
+}
+
+std::unique_ptr<Poly> TypicalReducer::classicReduce(const Poly& poly, const PolyBasis& basis) {
+ monomial identity = basis.ring().allocMonomial(mArena);
+ basis.ring().monomialSetIdentity(identity);
+ insert(identity, &poly);
+
+ return classicReduce(basis);
+}
+
+std::unique_ptr<Poly> TypicalReducer::classicTailReduce(const Poly& poly, const PolyBasis& basis) {
+ MATHICGB_ASSERT(&poly.ring() == &basis.ring());
+ MATHICGB_ASSERT(!poly.isZero());
+ term identity;
+ identity.monom = basis.ring().allocMonomial(mArena);
+ basis.ring().monomialSetIdentity(identity.monom);
+ basis.ring().coefficientSetOne(identity.coeff);
+ insertTail(identity, &poly);
+
+ std::unique_ptr<Poly> result(new Poly(basis.ring()));
+ result->appendTerm(poly.getLeadCoefficient(), poly.getLeadMonomial());
+
+ return classicReduce(std::move(result), basis);
+}
+
+std::unique_ptr<Poly> TypicalReducer::classicReduceSPoly(
+ const Poly& a,
+ const Poly& b,
+ const PolyBasis& basis
+) {
+ const PolyRing& ring = basis.ring();
+
+ monomial lcm = ring.allocMonomial();
+ ring.monomialLeastCommonMultiple
+ (a.getLeadMonomial(), b.getLeadMonomial(), lcm);
+
+ // insert tail of multiple of a
+ monomial multiple1 = ring.allocMonomial();
+ ring.monomialDivide(lcm, a.getLeadMonomial(), multiple1);
+ coefficient plusOne;
+ ring.coefficientSet(plusOne, 1);
+ insertTail(const_term(plusOne, multiple1), &a);
+
+ // insert tail of multiple of b
+ monomial multiple2 = ring.allocMonomial();
+ ring.monomialDivide(lcm, b.getLeadMonomial(), multiple2);
+ coefficient minusOne = plusOne;
+ ring.coefficientNegateTo(minusOne);
+ insertTail(const_term(minusOne, multiple2), &b);
+
+ std::unique_ptr<Poly> reduced = classicReduce(basis);
+ ring.freeMonomial(lcm);
+ ring.freeMonomial(multiple1);
+ ring.freeMonomial(multiple2);
+ return std::move(reduced);
+}
+
+void TypicalReducer::classicReduceSPolySet
+(std::vector<std::pair<size_t, size_t> >& spairs,
+ const PolyBasis& basis,
+ std::vector<std::unique_ptr<Poly> >& reducedOut) {
+ for (auto it = spairs.begin(); it != spairs.end(); ++it) {
+ auto reducedSPoly =
+ classicReduceSPoly(basis.poly(it->first), basis.poly(it->second), basis);
+ if (!reducedSPoly->isZero())
+ reducedOut.push_back(std::move(reducedSPoly));
+ }
+}
+
+void TypicalReducer::classicReducePolySet
+(const std::vector<std::unique_ptr<Poly> >& polys,
+ const PolyBasis& basis,
+ std::vector<std::unique_ptr<Poly> >& reducedOut)
+{
+ for (auto it = polys.begin(); it != polys.end(); ++it) {
+ auto reducedPoly = classicReduce(**it, basis);
+ if (!reducedPoly->isZero())
+ reducedOut.push_back(std::move(reducedPoly));
+ }
+}
+
+void TypicalReducer::setMemoryQuantum(size_t quantum) {
+}
+
+std::unique_ptr<Poly> TypicalReducer::classicReduce
+ (std::unique_ptr<Poly> result, const PolyBasis& basis) {
+ const PolyRing& ring = basis.ring();
+ MATHICGB_ASSERT(&result->ring() == &ring);
+ ++mClassicStats.reductions;
+
+ if (tracingLevel > 100)
+ std::cerr << "Classic reduction begun." << std::endl;
+
+ coefficient coef;
+ unsigned long long steps = 0; // number of steps in this reduction
+ for (const_term v; leadTerm(v);) {
+ if (tracingLevel > 100) {
+ std::cerr << "from reducer queue: ";
+ basis.ring().monomialDisplay(std::cerr, v.monom);
+ std::cerr << std::endl;
+ }
+
+ size_t reducer = basis.classicReducer(v.monom);
+ if (reducer == static_cast<size_t>(-1)) { // no reducer found
+ MATHICGB_ASSERT(
+ result->isZero() ||
+ basis.monoid().lessThan(v.monom, result->backMonomial())
+ );
+ result->appendTerm(v.coeff, v.monom);
+ removeLeadTerm();
+ } else { // reduce by reducer
+ ++steps;
+ basis.usedAsReducer(reducer);
+ monomial mon = ring.allocMonomial(mArena);
+ ring.monomialDivide(v.monom, basis.leadMonomial(reducer), mon);
+ ring.coefficientDivide(v.coeff, basis.leadCoefficient(reducer), coef);
+ ring.coefficientNegateTo(coef);
+ removeLeadTerm();
+ insertTail(const_term(coef, mon), &basis.poly(reducer));
+
+ if (tracingLevel > 100) {
+ std::cerr << "Reducing by basis element " << reducer << ": ";
+ basis.poly(reducer).display(std::cerr);
+ std::cerr << std::endl;
+ std::cerr << "multiplied by: " << coef << " * ";
+ basis.ring().monomialDisplay(std::cerr, mon);
+ std::cerr << std::endl;
+ }
+ }
+ }
+ result->makeMonic();
+
+ mClassicStats.steps += steps;
+ mClassicStats.maxSteps = std::max(mClassicStats.maxSteps, steps);
+ if (result->isZero())
+ ++mClassicStats.zeroReductions;
+
+ if (tracingLevel > 100)
+ std::cerr << "Classic reduction done." << std::endl;
+
+ reset();
+ return std::move(result);
+}
+
+std::unique_ptr<Poly> TypicalReducer::classicReduce(const PolyBasis& basis) {
+ return classicReduce(make_unique<Poly>(basis.ring()), basis);
+}
+
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/TypicalReducer.hpp b/src/mathicgb/TypicalReducer.hpp
index ff21705..292cda6 100755
--- a/src/mathicgb/TypicalReducer.hpp
+++ b/src/mathicgb/TypicalReducer.hpp
@@ -1,71 +1,77 @@
-#ifndef MATHICGB_TYPICAL_REDUCER_GUARD
-#define MATHICGB_TYPICAL_REDUCER_GUARD
-
-#include "Reducer.hpp"
-#include "Poly.hpp"
-#include "PolyRing.hpp"
-class SigPolyBasis;
-class PolyBasis;
-
-/** Uses the template method pattern (not C++ templates) to implement
- reduction with some steps left to sub-classes.
-
- The template method pattern defines an algorithm that calls several
- virtual methods. Sub-classes can then redefine those methods to
- change some parts of the algorithm without recoding the whole
- thing. The word "template" here has nothing to do with C++
- templates. See http://en.wikipedia.org/wiki/Template_method_pattern
-*/
-class TypicalReducer : public Reducer {
-public:
- virtual size_t preferredSetSize() const;
-
- virtual Poly* regularReduce(
- const_monomial sig,
- const_monomial multiple,
- size_t basisElement,
- const SigPolyBasis& basis);
-
- virtual std::unique_ptr<Poly> classicReduce
- (const Poly& poly, const PolyBasis& basis);
-
- virtual std::unique_ptr<Poly> classicTailReduce
- (const Poly& poly, const PolyBasis& basis);
-
- virtual std::unique_ptr<Poly> classicReduceSPoly
- (const Poly& a, const Poly& b, const PolyBasis& basis);
-
- virtual void classicReduceSPolySet
- (std::vector<std::pair<size_t, size_t> >& spairs,
- const PolyBasis& basis,
- std::vector<std::unique_ptr<Poly> >& reducedOut);
-
- virtual void classicReducePolySet
- (const std::vector<std::unique_ptr<Poly> >& polys,
- const PolyBasis& basis,
- std::vector<std::unique_ptr<Poly> >& reducedOut);
-
- virtual void setMemoryQuantum(size_t quantum);
-
-protected:
- // These are the methods that sub-classes define in order to carry
- // out sub-steps in the reduction.
- virtual void insertTail(const_term multiplier, const Poly *f) = 0;
- virtual void insert(monomial multiplier, const Poly *f) = 0;
- virtual bool leadTerm(const_term& result) = 0;
- virtual void removeLeadTerm() = 0;
- virtual void resetReducer() = 0;
-
- virtual size_t getMemoryUse() const;
-
- // Sub-classes can use this
- memt::Arena mArena;
-
-private:
- void reset();
- std::unique_ptr<Poly> classicReduce(const PolyBasis& basis);
- std::unique_ptr<Poly> classicReduce
- (std::unique_ptr<Poly> partialResult, const PolyBasis& basis);
-};
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_TYPICAL_REDUCER_GUARD
+#define MATHICGB_TYPICAL_REDUCER_GUARD
+
+#include "Reducer.hpp"
+#include "Poly.hpp"
+#include "PolyRing.hpp"
+
+MATHICGB_NAMESPACE_BEGIN
+
+class SigPolyBasis;
+class PolyBasis;
+
+/** Uses the template method pattern (not C++ templates) to implement
+ reduction with some steps left to sub-classes.
+
+ The template method pattern defines an algorithm that calls several
+ virtual methods. Sub-classes can then redefine those methods to
+ change some parts of the algorithm without recoding the whole
+ thing. The word "template" here has nothing to do with C++
+ templates. See http://en.wikipedia.org/wiki/Template_method_pattern
+*/
+class TypicalReducer : public Reducer {
+public:
+ virtual size_t preferredSetSize() const;
+
+ virtual Poly* regularReduce(
+ const_monomial sig,
+ const_monomial multiple,
+ size_t basisElement,
+ const SigPolyBasis& basis);
+
+ virtual std::unique_ptr<Poly> classicReduce
+ (const Poly& poly, const PolyBasis& basis);
+
+ virtual std::unique_ptr<Poly> classicTailReduce
+ (const Poly& poly, const PolyBasis& basis);
+
+ virtual std::unique_ptr<Poly> classicReduceSPoly
+ (const Poly& a, const Poly& b, const PolyBasis& basis);
+
+ virtual void classicReduceSPolySet
+ (std::vector<std::pair<size_t, size_t> >& spairs,
+ const PolyBasis& basis,
+ std::vector<std::unique_ptr<Poly> >& reducedOut);
+
+ virtual void classicReducePolySet
+ (const std::vector<std::unique_ptr<Poly> >& polys,
+ const PolyBasis& basis,
+ std::vector<std::unique_ptr<Poly> >& reducedOut);
+
+ virtual void setMemoryQuantum(size_t quantum);
+
+protected:
+ // These are the methods that sub-classes define in order to carry
+ // out sub-steps in the reduction.
+ virtual void insertTail(const_term multiplier, const Poly *f) = 0;
+ virtual void insert(monomial multiplier, const Poly *f) = 0;
+ virtual bool leadTerm(const_term& result) = 0;
+ virtual void removeLeadTerm() = 0;
+ virtual void resetReducer() = 0;
+
+ virtual size_t getMemoryUse() const;
+
+ // Sub-classes can use this
+ memt::Arena mArena;
+
+private:
+ void reset();
+ std::unique_ptr<Poly> classicReduce(const PolyBasis& basis);
+ std::unique_ptr<Poly> classicReduce
+ (std::unique_ptr<Poly> partialResult, const PolyBasis& basis);
+};
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/Unchar.hpp b/src/mathicgb/Unchar.hpp
index f93e0fc..d560bbf 100755
--- a/src/mathicgb/Unchar.hpp
+++ b/src/mathicgb/Unchar.hpp
@@ -1,39 +1,43 @@
-#ifndef MATHICGB_UNCHAR_GUARD
-#define MATHICGB_UNCHAR_GUARD
-
-#include <type_traits>
-
-/// std::ostream and std::istream handle characters differently from
-/// other integers. That is not desired when using char as an
-/// integer. Use Unchar and unchar() to cast chars to a different type
-/// that get handled as other integers do.
-template<class T>
-struct Unchar {typedef T type;};
-
-// Strange but true: char, signed char and unsigned char are 3
-// distinct types. Also, the signedness of char is unspecified. This
-// is in contrast to all the other built-in types. For example, int
-// and signed int are always the exact same type.
-
-namespace UncharInternal {
- // Two cases depending on whether char is signed or not.
- template<bool Signed = std::is_signed<char>::value>
- struct ExtendedChar {typedef signed short type;};
- template<>
- struct ExtendedChar<false> {typedef unsigned short type;};
-
-};
-
-template<>
-struct Unchar<char> {
- typedef typename UncharInternal::ExtendedChar<>::type type;
-};
-template<>
-struct Unchar<signed char> {typedef short type;};
-template<>
-struct Unchar<unsigned char> {typedef unsigned short type;};
-
-template<class T>
-typename Unchar<T>::type unchar(const T& t) {return t;}
-
-#endif
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_UNCHAR_GUARD
+#define MATHICGB_UNCHAR_GUARD
+
+#include <type_traits>
+
+MATHICGB_NAMESPACE_BEGIN
+
+/// std::ostream and std::istream handle characters differently from
+/// other integers. That is not desired when using char as an
+/// integer. Use Unchar and unchar() to cast chars to a different type
+/// that get handled as other integers do.
+template<class T>
+struct Unchar {typedef T type;};
+
+// Strange but true: char, signed char and unsigned char are 3
+// distinct types. Also, the signedness of char is unspecified. This
+// is in contrast to all the other built-in types. For example, int
+// and signed int are always the exact same type.
+
+namespace UncharInternal {
+ // Two cases depending on whether char is signed or not.
+ template<bool Signed = std::is_signed<char>::value>
+ struct ExtendedChar {typedef signed short type;};
+ template<>
+ struct ExtendedChar<false> {typedef unsigned short type;};
+};
+
+template<>
+struct Unchar<char> {
+ typedef typename UncharInternal::ExtendedChar<>::type type;
+};
+template<>
+struct Unchar<signed char> {typedef short type;};
+template<>
+struct Unchar<unsigned char> {typedef unsigned short type;};
+
+template<class T>
+typename Unchar<T>::type unchar(const T& t) {return t;}
+
+MATHICGB_NAMESPACE_END
+#endif
diff --git a/src/mathicgb/io-util.cpp b/src/mathicgb/io-util.cpp
index 87248e6..cb3d77e 100755
--- a/src/mathicgb/io-util.cpp
+++ b/src/mathicgb/io-util.cpp
@@ -1,133 +1,135 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "stdinc.h"
-#include <cstdio>
-#include <string>
-#include <iostream>
-#include <sstream>
+#include "io-util.hpp"
+
#include "Poly.hpp"
#include "MTArray.hpp"
#include "io-util.hpp"
#include "Scanner.hpp"
#include "MathicIO.hpp"
-
#include "PolyHeap.hpp"
#include "PolyGeoBucket.hpp"
#include "SigPolyBasis.hpp"
#include "SignatureGB.hpp"
#include "MTArray.hpp"
-
#include "Basis.hpp"
#include "PolyBasis.hpp"
+#include <cstdio>
+#include <string>
+#include <iostream>
+#include <sstream>
+
+MATHICGB_NAMESPACE_BEGIN
-std::unique_ptr<Poly> polyParseFromString(const PolyRing *R, const std::string &s)
+::std::unique_ptr<Poly> polyParseFromString(const PolyRing *R, const ::std::string &s)
{
- std::unique_ptr<Poly> f(new Poly(*R));
- std::istringstream in(s);
+ ::std::unique_ptr<Poly> f(new Poly(*R));
+ ::std::istringstream in(s);
f->parse(in);
return f;
}
-std::string toString(const Poly *g)
+::std::string toString(const Poly *g)
{
- std::ostringstream o;
+ ::std::ostringstream o;
g->display(o);
return o.str();
}
-std::unique_ptr<Basis> basisParseFromString(std::string str)
+::std::unique_ptr<Basis> basisParseFromString(::std::string str)
{
- std::istringstream inStream(str);
+ ::std::istringstream inStream(str);
Scanner in(inStream);
auto p = MathicIO().readRing(true, in);
auto& ring = *p.first.release(); // todo: fix leak
return make_unique<Basis>(MathicIO().readBasis(ring, false, in));
}
-std::unique_ptr<PolyRing> ringFromString(std::string ringinfo)
+::std::unique_ptr<PolyRing> ringFromString(::std::string ringinfo)
{
- std::stringstream ifil(ringinfo);
- return std::unique_ptr<PolyRing>(PolyRing::read(ifil).first);
+ ::std::stringstream ifil(ringinfo);
+ return ::std::unique_ptr<PolyRing>(PolyRing::read(ifil).first);
}
-Monomial stringToMonomial(const PolyRing *R, std::string mon)
+Monomial stringToMonomial(const PolyRing *R, ::std::string mon)
{
Monomial result = R->allocMonomial();
- std::stringstream ifil(mon);
+ ::std::stringstream ifil(mon);
R->monomialParse(ifil, result);
return result;
}
-std::string monomialToString(const PolyRing *R, const Monomial& mon)
+::std::string monomialToString(const PolyRing *R, const Monomial& mon)
{
- std::ostringstream o;
+ ::std::ostringstream o;
R->monomialDisplay(o,mon);
return o.str();
}
-monomial monomialParseFromString(const PolyRing *R, std::string mon)
+monomial monomialParseFromString(const PolyRing *R, ::std::string mon)
{
// This is poor code, to only be used for testing!
monomial result = R->allocMonomial();
- std::stringstream ifil(mon);
+ ::std::stringstream ifil(mon);
R->monomialParse(ifil, result);
return result;
}
-std::string monomialDisplay(const PolyRing *R, const_monomial mon)
+::std::string monomialDisplay(const PolyRing *R, const_monomial mon)
{
- std::ostringstream o;
+ ::std::ostringstream o;
R->monomialDisplay(o,mon);
return o.str();
}
////////////////////////////////////////////////////////////////
-std::string toString(SigPolyBasis *I)
+::std::string toString(SigPolyBasis *I)
{
- std::ostringstream o;
+ ::std::ostringstream o;
for (size_t i=0; i<I->size(); i++)
{
o << " ";
I->poly(i).display(o, false);
- o << std::endl;
+ o << ::std::endl;
}
return o.str();
}
-std::string toString(SigPolyBasis *I, int)
+::std::string toString(SigPolyBasis *I, int)
{
- std::ostringstream o;
+ ::std::ostringstream o;
I->display(o);
return o.str();
}
-std::string toString(MonomialTableArray* H)
+::std::string toString(MonomialTableArray* H)
{
- std::ostringstream o;
+ ::std::ostringstream o;
H->display(o, 1);
return o.str();
}
-std::string toString(Basis *I)
+::std::string toString(Basis *I)
{
- std::ostringstream o;
+ ::std::ostringstream o;
for (size_t i=0; i<I->size(); i++)
{
o << " ";
I->getPoly(i)->display(o,false);
- o << std::endl;
+ o << ::std::endl;
}
return o.str();
}
-void output(std::ostream &o, const PolyBasis &I)
+void output(::std::ostream &o, const PolyBasis &I)
{
for (size_t i = 0; i < I.size(); i++)
{
if (!I.retired(i))
{
I.poly(i).display(o, false);
- o << std::endl;
+ o << ::std::endl;
}
}
}
@@ -144,7 +146,4 @@ void output(FILE* file, const PolyBasis &I)
}
}
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/io-util.hpp b/src/mathicgb/io-util.hpp
index 80926de..7d62859 100755
--- a/src/mathicgb/io-util.hpp
+++ b/src/mathicgb/io-util.hpp
@@ -1,40 +1,39 @@
-// Copyright 2011 Michael E. Stillman
-
-#ifndef _io_util_h_
-#define _io_util_h_
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_IO_UTIL_GUARD
+#define MATHICGB_IO_UTIL_GUARD
#include "PolyRing.hpp"
+MATHICGB_NAMESPACE_BEGIN
+
class Poly;
class SigPolyBasis;
class MonomialTableArray;
class PolyBasis;
class Basis;
-std::unique_ptr<PolyRing> ringFromString(std::string ringinfo);
-monomial monomialFromString(const PolyRing *R, std::string mon);
-monomial monomialParseFromString(const PolyRing *R, std::string mon);
-std::string monomialToString(const PolyRing *R, const_monomial mon);
-std::string monomialDisplay(const PolyRing *R, const_monomial mon);
+::std::unique_ptr<PolyRing> ringFromString(::std::string ringinfo);
+monomial monomialFromString(const PolyRing *R, ::std::string mon);
+monomial monomialParseFromString(const PolyRing *R, ::std::string mon);
+::std::string monomialToString(const PolyRing *R, const_monomial mon);
+::std::string monomialDisplay(const PolyRing *R, const_monomial mon);
-Monomial stringToMonomial(const PolyRing *R, std::string mon);
-std::string monomialToString(const PolyRing *R, const Monomial& mon);
+Monomial stringToMonomial(const PolyRing *R, ::std::string mon);
+::std::string monomialToString(const PolyRing *R, const Monomial& mon);
-std::string toString(SigPolyBasis *);
-std::string toString(MonomialTableArray *);
-std::string toString(SigPolyBasis *, int unused); // also displays signature
-std::string toString(Basis *);
-std::string toString(const Poly *);
+::std::string toString(SigPolyBasis *);
+::std::string toString(MonomialTableArray *);
+::std::string toString(SigPolyBasis *, int unused); // also displays signature
+::std::string toString(Basis *);
+::std::string toString(const Poly *);
-std::unique_ptr<Basis> basisParseFromString(std::string str);
-std::unique_ptr<Poly> polyParseFromString(const PolyRing *R, const std::string &s);
+::std::unique_ptr<Basis> basisParseFromString(::std::string str);
+::std::unique_ptr<Poly> polyParseFromString
+ (const PolyRing *R, const ::std::string &s);
-void output(std::ostream &o, const PolyBasis &I);
+void output(::std::ostream &o, const PolyBasis &I);
void output(FILE* file, const PolyBasis &I);
+MATHICGB_NAMESPACE_END
#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/mathicgb/mtbb.hpp b/src/mathicgb/mtbb.hpp
index e0e313b..5898260 100755
--- a/src/mathicgb/mtbb.hpp
+++ b/src/mathicgb/mtbb.hpp
@@ -1,237 +1,243 @@
-#ifndef MATHICGB_TBB_GUARD
-#define MATHICGB_TBB_GUARD
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_M_TBB_GUARD
+#define MATHICGB_M_TBB_GUARD
#ifndef MATHICGB_NO_TBB
#include <tbb/tbb.h>
-namespace mgb {
- namespace tbb {
- using ::tbb::task_scheduler_init;
- using ::tbb::mutex;
- using ::tbb::parallel_do_feeder;
- using ::tbb::enumerable_thread_specific;
- using ::tbb::parallel_do;
- using ::tbb::parallel_for;
- using ::tbb::parallel_sort;
- using ::tbb::blocked_range;
- using ::tbb::tick_count;
- }
+MATHICGB_NAMESPACE_BEGIN
+
+namespace tbb {
+ using ::tbb::task_scheduler_init;
+ using ::tbb::mutex;
+ using ::tbb::parallel_do_feeder;
+ using ::tbb::enumerable_thread_specific;
+ using ::tbb::parallel_do;
+ using ::tbb::parallel_for;
+ using ::tbb::parallel_sort;
+ using ::tbb::blocked_range;
+ using ::tbb::tick_count;
}
+MATHICGB_NAMESPACE_END
#else
+
#include <functional>
#include <vector>
#include <ctime>
#include <algorithm>
#include <chrono>
-namespace mgb {
- namespace tbb {
- class task_scheduler_init {
- public:
- task_scheduler_init(int) {}
- static const int automatic = 1;
- };
+MATHICGB_NAMESPACE_BEGIN
- class mutex {
+namespace tbb {
+ class task_scheduler_init {
+ public:
+ task_scheduler_init(int) {}
+ static const int automatic = 1;
+ };
+
+ class mutex {
+ public:
+ mutex(): mLocked(false) {}
+
+ class scoped_lock {
public:
- mutex(): mLocked(false) {}
-
- class scoped_lock {
- public:
- scoped_lock(): mMutex(0) {}
- scoped_lock(mutex& m): mMutex(&m) {mMutex->lock();}
- ~scoped_lock() {
- if (mMutex != 0)
- release();
- }
-
- void acquire(mutex& m) {
- MATHICGB_ASSERT(mMutex == 0);
- mMutex = &m;
- }
-
- bool try_acquire(mutex& m) {
- MATHICGB_ASSERT(mMutex == 0);
- if (!m.try_lock())
- return false;
- mMutex = &m;
- return true;
- }
-
- void release() {
- MATHICGB_ASSERT(mMutex != 0);
- mMutex->unlock();
- mMutex = 0;
- }
-
- private:
- mutex* mMutex;
- };
-
- void lock() {
- MATHICGB_ASSERT(!mLocked); // deadlock
- mLocked = true;
+ scoped_lock(): mMutex(0) {}
+ scoped_lock(mutex& m): mMutex(&m) {mMutex->lock();}
+ ~scoped_lock() {
+ if (mMutex != 0)
+ release();
}
- bool try_lock() {
- if (mLocked)
+ void acquire(mutex& m) {
+ MATHICGB_ASSERT(mMutex == 0);
+ mMutex = &m;
+ }
+
+ bool try_acquire(mutex& m) {
+ MATHICGB_ASSERT(mMutex == 0);
+ if (!m.try_lock())
return false;
- lock();
+ mMutex = &m;
return true;
}
- void unlock() {
- MATHICGB_ASSERT(mLocked);
- mLocked = false;
+ void release() {
+ MATHICGB_ASSERT(mMutex != 0);
+ mMutex->unlock();
+ mMutex = 0;
}
private:
- bool mLocked;
+ mutex* mMutex;
};
- template<class T>
- class enumerable_thread_specific {
- public:
- template<class Op>
- enumerable_thread_specific(Op&& creater): mCreater(creater) {}
-
- bool empty() const {return mObj.get() == 0;}
-
- T& local() {
- if (empty())
- mObj = make_unique<T>(mCreater());
- MATHICGB_ASSERT(!empty());
- return *mObj;
- }
-
- T* begin() {
- if (empty())
- return 0;
- else
- return mObj.get();
- }
-
- T* end() {
- if (empty())
- return 0;
- else
- return begin() + 1;
- }
+ void lock() {
+ MATHICGB_ASSERT(!mLocked); // deadlock
+ mLocked = true;
+ }
- void clear() {
- mObj.reset(0);
- }
+ bool try_lock() {
+ if (mLocked)
+ return false;
+ lock();
+ return true;
+ }
- private:
- std::function<T()> mCreater;
- std::unique_ptr<T> mObj;
- };
+ void unlock() {
+ MATHICGB_ASSERT(mLocked);
+ mLocked = false;
+ }
- template<class Value>
- class blocked_range {
- public:
- typedef size_t size_type;
- typedef Value const_iterator;
+ private:
+ bool mLocked;
+ };
- blocked_range(Value begin, Value end, size_t grainSize = 1):
- mBegin(begin), mEnd(end), mGrainSize(grainSize) {}
+ template<class T>
+ class enumerable_thread_specific {
+ public:
+ template<class Op>
+ enumerable_thread_specific(Op&& creater): mCreater(creater) {}
- size_type size() const {return end() - begin();}
- bool empty() const {return mBegin == mEnd;}
- size_type grainsize() const {return mGrainSize;}
- bool is_divisible() const {return false;}
+ bool empty() const {return mObj.get() == 0;}
- const_iterator begin() const {return mBegin;}
- const_iterator end() const {return mEnd;}
+ T& local() {
+ if (empty())
+ mObj = make_unique<T>(mCreater());
+ MATHICGB_ASSERT(!empty());
+ return *mObj;
+ }
- private:
- const_iterator mBegin;
- const_iterator mEnd;
- size_type mGrainSize;
- };
-
- template<class Range, class Func>
- void parallel_for(Range&& range, Func&& f) {
- f(range);
+ T* begin() {
+ if (empty())
+ return 0;
+ else
+ return mObj.get();
}
- template<class Index, class Func>
- void parallel_for(Index begin, Index end, Index step, Func&& f) {
- for (auto i = begin; i < end; i += step)
- f(i);
+ T* end() {
+ if (empty())
+ return 0;
+ else
+ return begin() + 1;
}
- template<class T>
- class parallel_do_feeder {
- public:
- parallel_do_feeder(std::vector<T>& tasks): mTasks(tasks) {}
+ void clear() {
+ mObj.reset(0);
+ }
- template<class TT>
- void add(TT&& t) {mTasks.push_back(std::forward<TT>(t));}
+ private:
+ ::std::function<T()> mCreater;
+ ::std::unique_ptr<T> mObj;
+ };
+
+ template<class Value>
+ class blocked_range {
+ public:
+ typedef size_t size_type;
+ typedef Value const_iterator;
+
+ blocked_range(Value begin, Value end, size_t grainSize = 1):
+ mBegin(begin), mEnd(end), mGrainSize(grainSize) {}
+
+ size_type size() const {return end() - begin();}
+ bool empty() const {return mBegin == mEnd;}
+ size_type grainsize() const {return mGrainSize;}
+ bool is_divisible() const {return false;}
+
+ const_iterator begin() const {return mBegin;}
+ const_iterator end() const {return mEnd;}
+
+ private:
+ const_iterator mBegin;
+ const_iterator mEnd;
+ size_type mGrainSize;
+ };
+
+ template<class Range, class Func>
+ void parallel_for(Range&& range, Func&& f) {
+ f(range);
+ }
- private:
- std::vector<T>& mTasks;
- };
+ template<class Index, class Func>
+ void parallel_for(Index begin, Index end, Index step, Func&& f) {
+ for (auto i = begin; i < end; i += step)
+ f(i);
+ }
- template<class InputIterator, class Body>
- void parallel_do(InputIterator begin, InputIterator end, Body body) {
- typedef typename std::remove_reference<decltype(*begin)>::type Task;
- std::vector<Task> tasks;
- parallel_do_feeder<Task> feeder(tasks);
- for (; begin != end; ++begin) {
- tasks.push_back(*begin);
- while (!tasks.empty()) {
- auto task = std::move(tasks.back());
- tasks.pop_back();
- body(task, feeder);
- }
+ template<class T>
+ class parallel_do_feeder {
+ public:
+ parallel_do_feeder(::std::vector<T>& tasks): mTasks(tasks) {}
+
+ template<class TT>
+ void add(TT&& t) {mTasks.push_back(::std::forward<TT>(t));}
+
+ private:
+ ::std::vector<T>& mTasks;
+ };
+
+ template<class InputIterator, class Body>
+ void parallel_do(InputIterator begin, InputIterator end, Body body) {
+ typedef typename ::std::remove_reference<decltype(*begin)>::type Task;
+ ::std::vector<Task> tasks;
+ parallel_do_feeder<Task> feeder(tasks);
+ for (; begin != end; ++begin) {
+ tasks.push_back(*begin);
+ while (!tasks.empty()) {
+ auto task = ::std::move(tasks.back());
+ tasks.pop_back();
+ body(task, feeder);
}
}
+ }
- template<class It, class Pred>
- void parallel_sort(It begin, It end, Pred&& pred) {
- std::sort(begin, end, pred);
- }
-
- class tick_count {
- private:
- // This really should be std::chrono::steady_clock, but GCC 4.5.3 doesn't
- // have that.
- typedef std::chrono::system_clock clock;
-
- public:
- tick_count(): mTime() {}
+ template<class It, class Pred>
+ void parallel_sort(It begin, It end, Pred&& pred) {
+ ::std::sort(begin, end, pred);
+ }
- static tick_count now() {
- tick_count t;
- t.mTime = clock::now();
- return t;
- }
+ class tick_count {
+ private:
+ // This really should be ::std::chrono::steady_clock, but GCC 4.5.3 doesn't
+ // have that.
+ typedef ::std::chrono::system_clock clock;
- class interval_t {
- public:
- interval_t(double seconds): mSeconds(seconds) {}
+ public:
+ tick_count(): mTime() {}
- double seconds() const {return mSeconds;}
+ static tick_count now() {
+ tick_count t;
+ t.mTime = clock::now();
+ return t;
+ }
- private:
- const double mSeconds;
- };
+ class interval_t {
+ public:
+ interval_t(double seconds): mSeconds(seconds) {}
- interval_t operator-(const tick_count t) const {
- typedef std::chrono::duration<double> SecondDuration;
- const auto duration =
- std::chrono::duration_cast<SecondDuration>(mTime - t.mTime);
- return duration.count();
- }
+ double seconds() const {return mSeconds;}
private:
- clock::time_point mTime;
+ const double mSeconds;
};
- }
+
+ interval_t operator-(const tick_count t) const {
+ typedef ::std::chrono::duration<double> SecondDuration;
+ const auto duration =
+ ::std::chrono::duration_cast<SecondDuration>(mTime - t.mTime);
+ return duration.count();
+ }
+
+ private:
+ clock::time_point mTime;
+ };
}
+
+MATHICGB_NAMESPACE_END
#endif
#endif
diff --git a/src/mathicgb/stdinc.h b/src/mathicgb/stdinc.h
index 792ee94..91812ff 100755
--- a/src/mathicgb/stdinc.h
+++ b/src/mathicgb/stdinc.h
@@ -160,6 +160,16 @@
/// as that macro does.
#define MATHICGB_CONCATENATE_AFTER_EXPANSION(A,B) MATHICGB_CONCATENATE(A,B)
+/// Opens the mgb namespace. The purpose of having this be a macro is
+/// that otherwise editors the world over would automatically indent ALL
+/// CODE in MathicGB by an extra level to no benefit. By hiding the
+/// open and close braces inside a macro, the editors cannot see it so they
+/// do not indent because of it. Also, while transitioning to using
+/// the namespace, this was a useful way to insert the proper code in
+/// each file while still keeping everything compiling mid-way.
+#define MATHICGB_NAMESPACE_BEGIN namespace mgb {
+#define MATHICGB_NAMESPACE_END }
+
#include <utility>
/*
See http://herbsutter.com/gotw/_102/ for a reason to have a
@@ -178,6 +188,8 @@ for N parameters! Add more overloads below if you need more
parameters.
*/
+MATHICGB_NAMESPACE_BEGIN
+
template<class T>
std::unique_ptr<T> make_unique() {
return std::unique_ptr<T>(new T());
@@ -291,3 +303,5 @@ static const size_t MemoryAlignment = sizeof(void*);
/// The higher the value the more detailed output about what the program
/// is doing.
extern int tracingLevel;
+
+MATHICGB_NAMESPACE_END
diff --git a/src/test/F4MatrixBuilder.cpp b/src/test/F4MatrixBuilder.cpp
index 0ac2828..549f7e4 100755
--- a/src/test/F4MatrixBuilder.cpp
+++ b/src/test/F4MatrixBuilder.cpp
@@ -1,178 +1,182 @@
-#include "mathicgb/stdinc.h"
-
-#include "mathicgb/Poly.hpp"
-#include "mathicgb/PolyRing.hpp"
-#include "mathicgb/F4MatrixBuilder.hpp"
-#include "mathicgb/Basis.hpp"
-#include "mathicgb/PolyBasis.hpp"
-#include "mathicgb/io-util.hpp"
-#include "mathicgb/mtbb.hpp"
-
-#include <gtest/gtest.h>
-#include <memory>
-
-namespace {
- // We need a struct to keep the ring and so on alive after
- // construction - we cannot just return an object.
- //
- // @todo: This whole thing is fairly ridiculous - some kind of more
- // general dependency injection mechanism might be nice here.
- struct BuilderMaker {
- BuilderMaker():
- mRing(ringFromString("101 6 1\n1 1 1 1 1 1")),
- mIdeal(*mRing),
- mBasis(*mRing, DivisorLookup::makeFactory(*mRing, 1)->create(true, true)) {
- }
-
- const Poly& addBasisElement(const std::string& str) {
- std::unique_ptr<Poly> p(new Poly(*mRing));
- std::istringstream in(str);
- p->parse(in);
- mBasis.insert(std::move(p));
- return mBasis.poly(mBasis.size() - 1);
- }
-
- F4MatrixBuilder& create() {
- MATHICGB_ASSERT(mBuilder.get() == 0);
- mBuilder.reset(new F4MatrixBuilder(mBasis));
- return *mBuilder;
- }
-
- const PolyRing& ring() const {return *mRing;}
-
- private:
- std::unique_ptr<PolyRing> mRing;
- Basis mIdeal;
- PolyBasis mBasis;
- std::unique_ptr<F4MatrixBuilder> mBuilder;
- };
-}
-
-TEST(F4MatrixBuilder, Empty) {
- for (int threadCount = 1; threadCount < 4; ++threadCount) {
- mgb::tbb::task_scheduler_init scheduler(threadCount);
- 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.computeColCount());
- ASSERT_EQ(0, matrix.topRight.computeColCount());
- ASSERT_EQ(0, matrix.leftColumnMonomials.size());
- ASSERT_EQ(0, matrix.rightColumnMonomials.size());
- }
-}
-
-TEST(F4MatrixBuilder, SPair) {
- for (int threadCount = 1; threadCount < 4; ++threadCount) {
- mgb::tbb::task_scheduler_init scheduler(threadCount);
- 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* const str1 =
- "Left columns: c2d\n"
- "Right columns: bd 1\n"
- "0: 0#1 | 0: 1#3 \n"
- " | \n"
- "0: 0#100 | 0: 0#100\n";
- const char* const str2 =
- "Left columns: c2d\n"
- "Right columns: bd 1\n"
- "0: 0#1 | 0: 0#1\n"
- " | \n"
- "0: 0#1 | 0: 1#3\n";
- std::string qmStr = qm.toString();
- ASSERT_TRUE(str1 == qmStr || str2 == qmStr) <<
- "\n** str1: " << str1 << "\n** qm: " << qmStr;
- }
-}
-
-TEST(F4MatrixBuilder, OneByOne) {
- for (int threadCount = 1; threadCount < 4; ++threadCount) {
- mgb::tbb::task_scheduler_init scheduler(threadCount);
- 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;
- }
-}
-
-TEST(F4MatrixBuilder, DirectReducers) {
- for (int threadCount = 1; threadCount < 4; ++threadCount) {
- 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);
- }
-
- 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";
- qm = qm.toCanonical();
- ASSERT_EQ(str, qm.toString()) << "** qm:\n" << qm;
- }
-}
-
-TEST(F4MatrixBuilder, IteratedReducer) {
- for (int threadCount = 1; threadCount < 4; ++threadCount) {
- 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: 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;
- }
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+
+#include "mathicgb/Poly.hpp"
+#include "mathicgb/PolyRing.hpp"
+#include "mathicgb/F4MatrixBuilder.hpp"
+#include "mathicgb/Basis.hpp"
+#include "mathicgb/PolyBasis.hpp"
+#include "mathicgb/io-util.hpp"
+#include "mathicgb/mtbb.hpp"
+
+#include <gtest/gtest.h>
+#include <memory>
+
+using namespace mgb;
+
+namespace {
+ // We need a struct to keep the ring and so on alive after
+ // construction - we cannot just return an object.
+ //
+ // @todo: This whole thing is fairly ridiculous - some kind of more
+ // general dependency injection mechanism might be nice here.
+ struct BuilderMaker {
+ BuilderMaker():
+ mRing(ringFromString("101 6 1\n1 1 1 1 1 1")),
+ mIdeal(*mRing),
+ mBasis(*mRing, DivisorLookup::makeFactory(*mRing, 1)->create(true, true)) {
+ }
+
+ const Poly& addBasisElement(const ::std::string& str) {
+ ::std::unique_ptr<Poly> p(new Poly(*mRing));
+ ::std::istringstream in(str);
+ p->parse(in);
+ mBasis.insert(::std::move(p));
+ return mBasis.poly(mBasis.size() - 1);
+ }
+
+ F4MatrixBuilder& create() {
+ MATHICGB_ASSERT(mBuilder.get() == 0);
+ mBuilder.reset(new F4MatrixBuilder(mBasis));
+ return *mBuilder;
+ }
+
+ const PolyRing& ring() const {return *mRing;}
+
+ private:
+ ::std::unique_ptr<PolyRing> mRing;
+ Basis mIdeal;
+ PolyBasis mBasis;
+ ::std::unique_ptr<F4MatrixBuilder> mBuilder;
+ };
+}
+
+TEST(F4MatrixBuilder, Empty) {
+ for (int threadCount = 1; threadCount < 4; ++threadCount) {
+ mgb::tbb::task_scheduler_init scheduler(threadCount);
+ 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.computeColCount());
+ ASSERT_EQ(0, matrix.topRight.computeColCount());
+ ASSERT_EQ(0, matrix.leftColumnMonomials.size());
+ ASSERT_EQ(0, matrix.rightColumnMonomials.size());
+ }
+}
+
+TEST(F4MatrixBuilder, SPair) {
+ for (int threadCount = 1; threadCount < 4; ++threadCount) {
+ mgb::tbb::task_scheduler_init scheduler(threadCount);
+ 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* const str1 =
+ "Left columns: c2d\n"
+ "Right columns: bd 1\n"
+ "0: 0#1 | 0: 1#3 \n"
+ " | \n"
+ "0: 0#100 | 0: 0#100\n";
+ const char* const str2 =
+ "Left columns: c2d\n"
+ "Right columns: bd 1\n"
+ "0: 0#1 | 0: 0#1\n"
+ " | \n"
+ "0: 0#1 | 0: 1#3\n";
+ ::std::string qmStr = qm.toString();
+ ASSERT_TRUE(str1 == qmStr || str2 == qmStr) <<
+ "\n** str1: " << str1 << "\n** qm: " << qmStr;
+ }
+}
+
+TEST(F4MatrixBuilder, OneByOne) {
+ for (int threadCount = 1; threadCount < 4; ++threadCount) {
+ mgb::tbb::task_scheduler_init scheduler(threadCount);
+ 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;
+ }
+}
+
+TEST(F4MatrixBuilder, DirectReducers) {
+ for (int threadCount = 1; threadCount < 4; ++threadCount) {
+ 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);
+ }
+
+ 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";
+ qm = qm.toCanonical();
+ ASSERT_EQ(str, qm.toString()) << "** qm:\n" << qm;
+ }
+}
+
+TEST(F4MatrixBuilder, IteratedReducer) {
+ for (int threadCount = 1; threadCount < 4; ++threadCount) {
+ 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: 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;
+ }
+}
diff --git a/src/test/F4MatrixReducer.cpp b/src/test/F4MatrixReducer.cpp
index dcf7a4d..abf27ea 100755
--- a/src/test/F4MatrixReducer.cpp
+++ b/src/test/F4MatrixReducer.cpp
@@ -1,126 +1,130 @@
-#include "mathicgb/stdinc.h"
-
-#include "mathicgb/F4MatrixReducer.hpp"
-#include "mathicgb/SparseMatrix.hpp"
-#include "mathicgb/QuadMatrix.hpp"
-#include "mathicgb/io-util.hpp"
-#include "mathicgb/Poly.hpp"
-#include <gtest/gtest.h>
-#include <sstream>
-
-TEST(F4MatrixReducer, Reduce) {
- auto ring = ringFromString("101 6 1\n10 1 1 1 1 1");
-
- QuadMatrix m;
- m.ring = ring.get();
-
- Poly p(*ring);
- std::istringstream in("a4+a3+a2+a1+b5+b4+b3+b2+b1");
- p.parse(in);
- size_t count = 0;
- for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
- monomial mono = it.getMonomial();
- if (count < 4)
- m.leftColumnMonomials.push_back(mono);
- else
- m.rightColumnMonomials.push_back(mono);
- ++count;
- }
-
- // top left
- m.topLeft.clear();
- m.topLeft.appendEntry(0, 1);
- m.topLeft.appendEntry(1, 2);
- m.topLeft.appendEntry(3, 3);
- m.topLeft.rowDone();
- m.topLeft.appendEntry(1, 1);
- m.topLeft.appendEntry(2, 3);
- m.topLeft.rowDone();
- m.topLeft.appendEntry(2, 1);
- m.topLeft.appendEntry(3, 7);
- m.topLeft.rowDone();
- m.topLeft.appendEntry(3, 1);
- m.topLeft.rowDone();
-
- // top right
- m.topRight.clear();
- m.topRight.appendEntry(2,8);
- m.topRight.rowDone();
- m.topRight.appendEntry(3,9);
- m.topRight.rowDone();
- m.topRight.appendEntry(4,10);
- m.topRight.rowDone();
- m.topRight.rowDone();
-
- // bottom left
- m.bottomLeft.clear();
- m.bottomLeft.rowDone();
- m.bottomLeft.appendEntry(1, 9);
- m.bottomLeft.rowDone();
- m.bottomLeft.appendEntry(0, 2);
- m.bottomLeft.appendEntry(1, 99); // 100 = -2 mod 101
- m.bottomLeft.appendEntry(2, 83); // 83 = -18 mod 101
- m.bottomLeft.appendEntry(3, 6);
- m.bottomLeft.rowDone();
- m.bottomLeft.appendEntry(0, 1);
- m.bottomLeft.appendEntry(1, 1);
- m.bottomLeft.appendEntry(3, 24);
- m.bottomLeft.rowDone();
- m.bottomLeft.rowDone();
- m.bottomLeft.appendEntry(3, 100);
- m.bottomLeft.rowDone();
-
- // bottom right
- m.bottomRight.clear();
- m.bottomRight.rowDone();
- m.bottomRight.appendEntry(1, 2);
- m.bottomRight.appendEntry(3, 11);
- m.bottomRight.rowDone();
- m.bottomRight.appendEntry(2, 16);
- m.bottomRight.appendEntry(3, 47);
- m.bottomRight.rowDone();
- m.bottomRight.appendEntry(0, 1);
- m.bottomRight.appendEntry(2, 12);
- m.bottomRight.appendEntry(3, 13);
- m.bottomRight.appendEntry(4, 41);
- m.bottomRight.rowDone();
- m.bottomRight.appendEntry(0, 2);
- m.bottomRight.appendEntry(1, 2);
- m.bottomRight.appendEntry(2, 8);
- m.bottomRight.appendEntry(3, 75);
- m.bottomRight.appendEntry(4, 90);
- m.bottomRight.rowDone();
- m.bottomRight.appendEntry(0, 1);
- m.bottomRight.appendEntry(1, 1);
- m.bottomRight.appendEntry(2, 4);
- m.bottomRight.appendEntry(3, 88);
- m.bottomRight.appendEntry(4, 45);
- m.bottomRight.rowDone();
-
- MATHICGB_ASSERT(m.debugAssertValid());
- const char* origStr =
- "Left columns: a4 a3 a2 a\n"
- "Right columns: b5 b4 b3 b2 b\n"
- "0: 0#1 1#2 3#3 | 0: 2#8 \n"
- "1: 1#1 2#3 | 1: 3#9 \n"
- "2: 2#1 3#7 | 2: 4#10 \n"
- "3: 3#1 | 3: \n"
- " | \n"
- "0: | 0: \n" // zero row
- "1: 1#9 | 1: 1#2 3#11 \n" // becomes second row
- "2: 0#2 1#99 2#83 3#6 | 2: 2#16 3#47 \n" // zero on left red.
- "3: 0#1 1#1 3#24 | 3: 0#1 2#12 3#13 4#41 \n" // becomes first row
- "4: | 4: 0#2 1#2 2#8 3#75 4#90\n" // zero on right red.
- "5: 3#100 | 5: 0#1 1#1 2#4 3#88 4#45\n"; // zero on right red.
-
- ASSERT_EQ(origStr, m.toString()) << "Printed m:\n" << m;
-
- SparseMatrix reduced
- (F4MatrixReducer(ring->charac()).reducedRowEchelonFormBottomRight(m));
-
- const char* redStr =
- "0: 0#1 2#4 3#22 4#11\n"
- "1: 1#1 3#66 4#34\n";
- reduced.sortRowsByIncreasingPivots();
- ASSERT_EQ(redStr, reduced.toString()) << "Printed reduced:\n" << reduced;
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+
+#include "mathicgb/F4MatrixReducer.hpp"
+#include "mathicgb/SparseMatrix.hpp"
+#include "mathicgb/QuadMatrix.hpp"
+#include "mathicgb/io-util.hpp"
+#include "mathicgb/Poly.hpp"
+#include <gtest/gtest.h>
+#include <sstream>
+
+using namespace mgb;
+
+TEST(F4MatrixReducer, Reduce) {
+ auto ring = ringFromString("101 6 1\n10 1 1 1 1 1");
+
+ QuadMatrix m;
+ m.ring = ring.get();
+
+ Poly p(*ring);
+ ::std::istringstream in("a4+a3+a2+a1+b5+b4+b3+b2+b1");
+ p.parse(in);
+ size_t count = 0;
+ for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
+ monomial mono = it.getMonomial();
+ if (count < 4)
+ m.leftColumnMonomials.push_back(mono);
+ else
+ m.rightColumnMonomials.push_back(mono);
+ ++count;
+ }
+
+ // top left
+ m.topLeft.clear();
+ m.topLeft.appendEntry(0, 1);
+ m.topLeft.appendEntry(1, 2);
+ m.topLeft.appendEntry(3, 3);
+ m.topLeft.rowDone();
+ m.topLeft.appendEntry(1, 1);
+ m.topLeft.appendEntry(2, 3);
+ m.topLeft.rowDone();
+ m.topLeft.appendEntry(2, 1);
+ m.topLeft.appendEntry(3, 7);
+ m.topLeft.rowDone();
+ m.topLeft.appendEntry(3, 1);
+ m.topLeft.rowDone();
+
+ // top right
+ m.topRight.clear();
+ m.topRight.appendEntry(2,8);
+ m.topRight.rowDone();
+ m.topRight.appendEntry(3,9);
+ m.topRight.rowDone();
+ m.topRight.appendEntry(4,10);
+ m.topRight.rowDone();
+ m.topRight.rowDone();
+
+ // bottom left
+ m.bottomLeft.clear();
+ m.bottomLeft.rowDone();
+ m.bottomLeft.appendEntry(1, 9);
+ m.bottomLeft.rowDone();
+ m.bottomLeft.appendEntry(0, 2);
+ m.bottomLeft.appendEntry(1, 99); // 100 = -2 mod 101
+ m.bottomLeft.appendEntry(2, 83); // 83 = -18 mod 101
+ m.bottomLeft.appendEntry(3, 6);
+ m.bottomLeft.rowDone();
+ m.bottomLeft.appendEntry(0, 1);
+ m.bottomLeft.appendEntry(1, 1);
+ m.bottomLeft.appendEntry(3, 24);
+ m.bottomLeft.rowDone();
+ m.bottomLeft.rowDone();
+ m.bottomLeft.appendEntry(3, 100);
+ m.bottomLeft.rowDone();
+
+ // bottom right
+ m.bottomRight.clear();
+ m.bottomRight.rowDone();
+ m.bottomRight.appendEntry(1, 2);
+ m.bottomRight.appendEntry(3, 11);
+ m.bottomRight.rowDone();
+ m.bottomRight.appendEntry(2, 16);
+ m.bottomRight.appendEntry(3, 47);
+ m.bottomRight.rowDone();
+ m.bottomRight.appendEntry(0, 1);
+ m.bottomRight.appendEntry(2, 12);
+ m.bottomRight.appendEntry(3, 13);
+ m.bottomRight.appendEntry(4, 41);
+ m.bottomRight.rowDone();
+ m.bottomRight.appendEntry(0, 2);
+ m.bottomRight.appendEntry(1, 2);
+ m.bottomRight.appendEntry(2, 8);
+ m.bottomRight.appendEntry(3, 75);
+ m.bottomRight.appendEntry(4, 90);
+ m.bottomRight.rowDone();
+ m.bottomRight.appendEntry(0, 1);
+ m.bottomRight.appendEntry(1, 1);
+ m.bottomRight.appendEntry(2, 4);
+ m.bottomRight.appendEntry(3, 88);
+ m.bottomRight.appendEntry(4, 45);
+ m.bottomRight.rowDone();
+
+ MATHICGB_ASSERT(m.debugAssertValid());
+ const char* origStr =
+ "Left columns: a4 a3 a2 a\n"
+ "Right columns: b5 b4 b3 b2 b\n"
+ "0: 0#1 1#2 3#3 | 0: 2#8 \n"
+ "1: 1#1 2#3 | 1: 3#9 \n"
+ "2: 2#1 3#7 | 2: 4#10 \n"
+ "3: 3#1 | 3: \n"
+ " | \n"
+ "0: | 0: \n" // zero row
+ "1: 1#9 | 1: 1#2 3#11 \n" // becomes second row
+ "2: 0#2 1#99 2#83 3#6 | 2: 2#16 3#47 \n" // zero on left red.
+ "3: 0#1 1#1 3#24 | 3: 0#1 2#12 3#13 4#41 \n" // becomes first row
+ "4: | 4: 0#2 1#2 2#8 3#75 4#90\n" // zero on right red.
+ "5: 3#100 | 5: 0#1 1#1 2#4 3#88 4#45\n"; // zero on right red.
+
+ ASSERT_EQ(origStr, m.toString()) << "Printed m:\n" << m;
+
+ SparseMatrix reduced
+ (F4MatrixReducer(ring->charac()).reducedRowEchelonFormBottomRight(m));
+
+ const char* redStr =
+ "0: 0#1 2#4 3#22 4#11\n"
+ "1: 1#1 3#66 4#34\n";
+ reduced.sortRowsByIncreasingPivots();
+ ASSERT_EQ(redStr, reduced.toString()) << "Printed reduced:\n" << reduced;
+}
diff --git a/src/test/MathicIO.cpp b/src/test/MathicIO.cpp
index f3663fa..7bd7f10 100755
--- a/src/test/MathicIO.cpp
+++ b/src/test/MathicIO.cpp
@@ -1,313 +1,317 @@
-#include "mathicgb/stdinc.h"
-#include "mathicgb/MathicIO.hpp"
-
-#include <gtest/gtest.h>
-
-TEST(MathicIO, Combined) {
- const char* const str =
- "32003 6\n"
- "1 1 1 1 1 1 1\n"
- "_revlex revcomponent\n"
- "3\n"
- " -bc+ad\n"
- " -b2+af\n"
- " -bc2+a2e\n";
- std::istringstream inStream(str);
- Scanner in(inStream);
- auto p = MathicIO().readRing(true, in);
- auto& ring = *p.first;
- auto basis = MathicIO().readBasis(ring, false, in);
-}
-
-TEST(MathicIO, ReadWriteRing) {
- typedef PolyRing::Monoid Monoid;
- typedef Monoid::VarIndex VarIndex;
- typedef Monoid::Exponent Exponent;
- typedef PolyRing::Field BaseField;
- typedef BaseField::RawElement RawElement;
-
- auto check = [&](
- const char* const inStr,
- const char* outStr,
- const RawElement charac,
- const VarIndex varCount,
- const VarIndex gradingCount,
- const bool withComponent
- ) {
- for (int i = 0; i < 2; ++i) {
- const char* str = i == 0 ? inStr : outStr;
- if (str == 0)
- continue;
- Scanner in(str);
- const auto p = MathicIO().readRing(withComponent, in);
- const auto& monoid = p.first->monoid();
- const auto& field = p.first->field();
- ASSERT_EQ(charac, field.charac());
- ASSERT_EQ(varCount, monoid.varCount());
- ASSERT_EQ(gradingCount, monoid.gradingCount());
- std::ostringstream out;
- MathicIO().writeRing(*p.first, p.second, withComponent, out);
- ASSERT_EQ(outStr, out.str());
- }
- };
-
- check("101 2 1 3 4", "101 2\nrevlex 1\n 3 4\n", 101, 2, 1, false);
- check(
- "101 2 schreyer lex 1 3 4 _lex revcomponent",
- "101 2\nschreyer lex 1\n 3 4\n _lex\n revcomponent\n", 101, 2, 1, true
- );
- check(
- "101 2 2 component 3 4",
- "101 2\nrevlex 2\n component\n 3 4\n", 101, 2, 2, true
- );
-}
-
-TEST(MathicIO, ReadWriteMonomial) {
- typedef PolyRing::Monoid Monoid;
- typedef Monoid::VarIndex VarIndex;
- typedef Monoid::Exponent Exponent;
- static const auto NoComponent = static_cast<Exponent>(-1);
-
- Monoid m(28);
-
- // canonicalStr is str as it should appear after being read and
- // printed. If canonicalStr is null then this is the same as str.
- auto check = [&](
- const char* const str,
- const Exponent component,
- const VarIndex var1 = -1,
- const Exponent exp1 = -1,
- const VarIndex var2 = -1,
- const Exponent exp2 = -1,
- const char* const canonicalStr = 0
- ) {
- const bool doComponent = component != NoComponent;
-
- // read monomial from string
- auto monoRead = m.alloc();
- Scanner in(str);
- MathicIO().readMonomial(m, doComponent, monoRead, in);
-
- // directly make monomial
- auto monoSet = m.alloc();
- if (var1 != -1)
- m.setExponent(var1, exp1, monoSet);
- if (var2 != -1)
- m.setExponent(var2, exp2, monoSet);
- if (doComponent)
- m.setComponent(component, monoSet);
- ASSERT_TRUE(m.equal(monoRead, monoSet)) << "Str: " << str;
-
- // print monomial
- std::ostringstream out;
- MathicIO().writeMonomial(m, doComponent, monoRead, out);
- const auto correctStr = canonicalStr == 0 ? str : canonicalStr;
- ASSERT_EQ(correctStr, out.str());
- };
-
- check("1", NoComponent);
- check("1<0>", 0);
- check("1<1>", 1);
- check("1<999>", 999);
-
- check("a1", NoComponent, 0,1, -1,-1, "a");
- check("b10<0>", 0, 1,10);
- check("A11", NoComponent, 26,11);
- check("B99<1>", 1, 27,99);
-
- check("ab", NoComponent, 0,1, 1,1);
- check("ba", NoComponent, 0,1, 1,1, "ab");
- check("a0c3b1", NoComponent, 1,1, 2,3, "bc3");
- check("ab<2>", 2, 0,1, 1,1);
-}
-
-TEST(MathicIO, ReadWriteBasis) {
- typedef PolyRing::Monoid Monoid;
- typedef PolyRing::Field Field;
- PolyRing ring(Field(101), Monoid(28));
-
- auto check = [&](
- const char* const inStr,
- const char* const outStr,
- const bool doComponent
- ) {
- for (int i = 0; i < 2; ++i) {
- const char* str = i == 0 ? inStr : outStr;
- if (str == 0)
- continue;
-
- Scanner in(str);
- const auto basis = MathicIO().readBasis(ring, doComponent, in);
- std::ostringstream out;
- MathicIO().writeBasis(basis, doComponent, out);
- const auto correctStr = outStr == 0 ? inStr : outStr;
- ASSERT_EQ(correctStr, out.str());
- }
- };
-
- check("0", "0\n", false);
- check("0", "0\n", true);
- check("1 0", "1\n 0\n", false);
- check("1 0", "1\n 0\n", true);
-
- check("1 1", "1\n 1\n", false);
- check("1 a<0>", "1\n a<0>\n", true);
- check("2 a b", "2\n a\n b\n", false);
-}
-
-TEST(MathicIO, ReadWritePoly) {
- typedef PolyRing::Monoid Monoid;
- typedef PolyRing::Field Field;
- PolyRing ring(Field(101), Monoid(28));
-
- auto check = [&](
- const char* const inStr,
- const char* const outStr,
- const bool doComponent
- ) {
- for (int i = 0; i < 2; ++i) {
- const char* str = i == 0 ? inStr : outStr;
- if (str == 0)
- continue;
-
- Scanner in(str);
- const auto poly = MathicIO().readPoly(ring, doComponent, in);
- std::ostringstream out;
- MathicIO().writePoly(poly, doComponent, out);
- const auto correctStr = outStr == 0 ? inStr : outStr;
- ASSERT_EQ(correctStr, out.str());
- }
- };
-
- check("+0", "0", false);
- check("-0", "0", false);
- check("+1", "1", false);
- check("\t a\t", "a", false);
- check("3a+1b5+2c6", "3a+b5+2c6", false);
-
- check("+0", "0", true);
- check("-0", "0", true);
- check("+1<5>", "1<5>", true);
- check("\t a<0>\t", "a<0>", true);
- check("3a<1>+1b5<2>+2c6<3>", "3a<1>+b5<2>+2c6<3>", true);
-}
-
-TEST(MathicIO, ReadWriteTerm) {
- typedef PolyRing::Monoid Monoid;
- typedef Monoid::VarIndex VarIndex;
- typedef Monoid::Exponent Exponent;
- typedef PolyRing::Field Field;
- typedef Field::Element Coefficient;
- typedef Field::RawElement RawCoefficient;
- static const auto NoComponent = static_cast<Exponent>(-1);
-
- PolyRing ring(Field(101), Monoid(28));
- auto&& m = ring.monoid();
- auto&& f = ring.field();
-
- auto check = [&](
- const char* const inStr,
- const char* const outStr,
- const bool doComponent,
- const RawCoefficient coef
- ) {
- for (int i = 0; i < 2; ++i) {
- const char* str = i == 0 ? inStr : outStr;
- if (str == 0)
- continue;
-
- // read term from string
- auto monoRead = m.alloc();
- Coefficient readCoef = f.zero();
- Scanner in(str);
- MathicIO().readTerm(ring, doComponent, readCoef, monoRead, in);
-
- ASSERT_EQ(coef, readCoef.value());
-
- // print monomial
- std::ostringstream out;
- MathicIO().writeTerm(ring, doComponent, readCoef, monoRead, out);
- const auto correctStr = outStr == 0 ? inStr : outStr;
- ASSERT_EQ(correctStr, out.str());
- }
- };
-
- check("1", 0, false, 1);
- check("-1", "100", false, f.minusOne().value());
- check("+1", "1", false, 1);
- check("2", 0, false, 2);
- check("+102", "1", false, 1);
-
- check("1<0>", 0, true, 1);
- check("+1<2>", "1<2>", true, 1);
- check("2<3>", 0, true, 2);
- check("+3<4>", "3<4>", true, 3);
- check("-3<4>", "98<4>", true, f.negative(f.toElement(3)).value());
-
- check("+1a<0>", "a<0>", true, 1);
- check("+2b", "2b", false, 2);
-}
-
-TEST(MathicIO, ReadWriteBaseField) {
- Scanner in("101");
- auto field = MathicIO().readBaseField(in);
- ASSERT_EQ(101, field.charac());
- std::ostringstream out;
- MathicIO().writeBaseField(field, out);
- ASSERT_EQ("101", out.str());
-}
-
-TEST(MathicIO, ReadWriteOrder) {
- typedef PolyRing::Monoid Monoid;
- typedef Monoid::VarIndex VarIndex;
-
- const auto check = [](
- const char* const inStr,
- const char* const outStr,
- const VarIndex varCount,
- const VarIndex gradingCount,
- const bool withComponent = false,
- const bool componentsAscendingDesired = true,
- const bool schreyering = false
- ) -> void {
- for (int i = 0; i < 2; ++i) {
- const char* str = i == 0 ? inStr : outStr;
- if (str == 0)
- continue;
-
- Scanner in(str);
- const auto order = MathicIO().readOrder(varCount, withComponent, in);
- ASSERT_EQ(varCount, order.varCount());
- ASSERT_EQ(gradingCount, order.gradingCount());
- ASSERT_EQ(componentsAscendingDesired, order.componentsAscendingDesired());
- ASSERT_EQ(schreyering, order.schreyering()) << inStr;
-
- std::ostringstream out;
- MathicIO().writeOrder(order, withComponent, out);
- ASSERT_EQ(outStr, out.str());
- }
- };
- check("0\n", "revlex 0\n", 0, 0);
- check("1\n 2\n", "revlex 1\n 2\n", 1, 1);
- check("2\n 3\n 4\n", "revlex 2\n 3\n 4\n", 1, 2);
- check("2\n 3 4\n 5 6\n", "revlex 2\n 3 4\n 5 6\n", 2, 2);
- check("1\n 1 1 1 1\n", "revlex 1\n 1 1 1 1\n", 4, 1);
-
- check("lex 0", "lex 0\n", 0, 0);
- check("lex 1 2", "lex 1\n 2\n", 1, 1);
- check("lex 2 3 4", "lex 2\n 3\n 4\n", 1, 2);
- check("lex 2 3 4 5 6", "lex 2\n 3 4\n 5 6\n", 2, 2);
- check("lex 1 1 1 1 1", "lex 1\n 1 1 1 1\n", 4, 1);
-
- check("2 component\n 5 6\n", "revlex 2\n component\n 5 6\n", 2, 2, 1, 1, 0);
- check("2 3 4\nrevcomponent\n","revlex 2\n 3 4\n revcomponent\n",2,2, 1,0,0);
- check("lex 1 component", "lex 0\n", 0, 0, 1, 1, 0);
- check("lex 1 revcomponent", "lex 1\n revcomponent\n", 1, 1, 1, 0, 0);
- check("lex 1 revcomponent", "lex 1\n revcomponent\n", 5, 1, 1, 0, 0);
-
- check(
- "schreyer lex 1 1 _revlex revcomponent",
- "schreyer revlex 1\n 1\n _revlex\n revcomponent\n",
- 1, 1, 1, 0, 1
- );
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+#include "mathicgb/MathicIO.hpp"
+
+#include <gtest/gtest.h>
+
+using namespace mgb;
+
+TEST(MathicIO, Combined) {
+ const char* const str =
+ "32003 6\n"
+ "1 1 1 1 1 1 1\n"
+ "_revlex revcomponent\n"
+ "3\n"
+ " -bc+ad\n"
+ " -b2+af\n"
+ " -bc2+a2e\n";
+ std::istringstream inStream(str);
+ Scanner in(inStream);
+ auto p = MathicIO().readRing(true, in);
+ auto& ring = *p.first;
+ auto basis = MathicIO().readBasis(ring, false, in);
+}
+
+TEST(MathicIO, ReadWriteRing) {
+ typedef PolyRing::Monoid Monoid;
+ typedef Monoid::VarIndex VarIndex;
+ typedef Monoid::Exponent Exponent;
+ typedef PolyRing::Field BaseField;
+ typedef BaseField::RawElement RawElement;
+
+ auto check = [&](
+ const char* const inStr,
+ const char* outStr,
+ const RawElement charac,
+ const VarIndex varCount,
+ const VarIndex gradingCount,
+ const bool withComponent
+ ) {
+ for (int i = 0; i < 2; ++i) {
+ const char* str = i == 0 ? inStr : outStr;
+ if (str == 0)
+ continue;
+ Scanner in(str);
+ const auto p = MathicIO().readRing(withComponent, in);
+ const auto& monoid = p.first->monoid();
+ const auto& field = p.first->field();
+ ASSERT_EQ(charac, field.charac());
+ ASSERT_EQ(varCount, monoid.varCount());
+ ASSERT_EQ(gradingCount, monoid.gradingCount());
+ std::ostringstream out;
+ MathicIO().writeRing(*p.first, p.second, withComponent, out);
+ ASSERT_EQ(outStr, out.str());
+ }
+ };
+
+ check("101 2 1 3 4", "101 2\nrevlex 1\n 3 4\n", 101, 2, 1, false);
+ check(
+ "101 2 schreyer lex 1 3 4 _lex revcomponent",
+ "101 2\nschreyer lex 1\n 3 4\n _lex\n revcomponent\n", 101, 2, 1, true
+ );
+ check(
+ "101 2 2 component 3 4",
+ "101 2\nrevlex 2\n component\n 3 4\n", 101, 2, 2, true
+ );
+}
+
+TEST(MathicIO, ReadWriteMonomial) {
+ typedef PolyRing::Monoid Monoid;
+ typedef Monoid::VarIndex VarIndex;
+ typedef Monoid::Exponent Exponent;
+ static const auto NoComponent = static_cast<Exponent>(-1);
+
+ Monoid m(28);
+
+ // canonicalStr is str as it should appear after being read and
+ // printed. If canonicalStr is null then this is the same as str.
+ auto check = [&](
+ const char* const str,
+ const Exponent component,
+ const VarIndex var1 = -1,
+ const Exponent exp1 = -1,
+ const VarIndex var2 = -1,
+ const Exponent exp2 = -1,
+ const char* const canonicalStr = 0
+ ) {
+ const bool doComponent = component != NoComponent;
+
+ // read monomial from string
+ auto monoRead = m.alloc();
+ Scanner in(str);
+ MathicIO().readMonomial(m, doComponent, monoRead, in);
+
+ // directly make monomial
+ auto monoSet = m.alloc();
+ if (var1 != -1)
+ m.setExponent(var1, exp1, monoSet);
+ if (var2 != -1)
+ m.setExponent(var2, exp2, monoSet);
+ if (doComponent)
+ m.setComponent(component, monoSet);
+ ASSERT_TRUE(m.equal(monoRead, monoSet)) << "Str: " << str;
+
+ // print monomial
+ std::ostringstream out;
+ MathicIO().writeMonomial(m, doComponent, monoRead, out);
+ const auto correctStr = canonicalStr == 0 ? str : canonicalStr;
+ ASSERT_EQ(correctStr, out.str());
+ };
+
+ check("1", NoComponent);
+ check("1<0>", 0);
+ check("1<1>", 1);
+ check("1<999>", 999);
+
+ check("a1", NoComponent, 0,1, -1,-1, "a");
+ check("b10<0>", 0, 1,10);
+ check("A11", NoComponent, 26,11);
+ check("B99<1>", 1, 27,99);
+
+ check("ab", NoComponent, 0,1, 1,1);
+ check("ba", NoComponent, 0,1, 1,1, "ab");
+ check("a0c3b1", NoComponent, 1,1, 2,3, "bc3");
+ check("ab<2>", 2, 0,1, 1,1);
+}
+
+TEST(MathicIO, ReadWriteBasis) {
+ typedef PolyRing::Monoid Monoid;
+ typedef PolyRing::Field Field;
+ PolyRing ring(Field(101), Monoid(28));
+
+ auto check = [&](
+ const char* const inStr,
+ const char* const outStr,
+ const bool doComponent
+ ) {
+ for (int i = 0; i < 2; ++i) {
+ const char* str = i == 0 ? inStr : outStr;
+ if (str == 0)
+ continue;
+
+ Scanner in(str);
+ const auto basis = MathicIO().readBasis(ring, doComponent, in);
+ std::ostringstream out;
+ MathicIO().writeBasis(basis, doComponent, out);
+ const auto correctStr = outStr == 0 ? inStr : outStr;
+ ASSERT_EQ(correctStr, out.str());
+ }
+ };
+
+ check("0", "0\n", false);
+ check("0", "0\n", true);
+ check("1 0", "1\n 0\n", false);
+ check("1 0", "1\n 0\n", true);
+
+ check("1 1", "1\n 1\n", false);
+ check("1 a<0>", "1\n a<0>\n", true);
+ check("2 a b", "2\n a\n b\n", false);
+}
+
+TEST(MathicIO, ReadWritePoly) {
+ typedef PolyRing::Monoid Monoid;
+ typedef PolyRing::Field Field;
+ PolyRing ring(Field(101), Monoid(28));
+
+ auto check = [&](
+ const char* const inStr,
+ const char* const outStr,
+ const bool doComponent
+ ) {
+ for (int i = 0; i < 2; ++i) {
+ const char* str = i == 0 ? inStr : outStr;
+ if (str == 0)
+ continue;
+
+ Scanner in(str);
+ const auto poly = MathicIO().readPoly(ring, doComponent, in);
+ std::ostringstream out;
+ MathicIO().writePoly(poly, doComponent, out);
+ const auto correctStr = outStr == 0 ? inStr : outStr;
+ ASSERT_EQ(correctStr, out.str());
+ }
+ };
+
+ check("+0", "0", false);
+ check("-0", "0", false);
+ check("+1", "1", false);
+ check("\t a\t", "a", false);
+ check("3a+1b5+2c6", "3a+b5+2c6", false);
+
+ check("+0", "0", true);
+ check("-0", "0", true);
+ check("+1<5>", "1<5>", true);
+ check("\t a<0>\t", "a<0>", true);
+ check("3a<1>+1b5<2>+2c6<3>", "3a<1>+b5<2>+2c6<3>", true);
+}
+
+TEST(MathicIO, ReadWriteTerm) {
+ typedef PolyRing::Monoid Monoid;
+ typedef Monoid::VarIndex VarIndex;
+ typedef Monoid::Exponent Exponent;
+ typedef PolyRing::Field Field;
+ typedef Field::Element Coefficient;
+ typedef Field::RawElement RawCoefficient;
+ static const auto NoComponent = static_cast<Exponent>(-1);
+
+ PolyRing ring(Field(101), Monoid(28));
+ auto&& m = ring.monoid();
+ auto&& f = ring.field();
+
+ auto check = [&](
+ const char* const inStr,
+ const char* const outStr,
+ const bool doComponent,
+ const RawCoefficient coef
+ ) {
+ for (int i = 0; i < 2; ++i) {
+ const char* str = i == 0 ? inStr : outStr;
+ if (str == 0)
+ continue;
+
+ // read term from string
+ auto monoRead = m.alloc();
+ Coefficient readCoef = f.zero();
+ Scanner in(str);
+ MathicIO().readTerm(ring, doComponent, readCoef, monoRead, in);
+
+ ASSERT_EQ(coef, readCoef.value());
+
+ // print monomial
+ std::ostringstream out;
+ MathicIO().writeTerm(ring, doComponent, readCoef, monoRead, out);
+ const auto correctStr = outStr == 0 ? inStr : outStr;
+ ASSERT_EQ(correctStr, out.str());
+ }
+ };
+
+ check("1", 0, false, 1);
+ check("-1", "100", false, f.minusOne().value());
+ check("+1", "1", false, 1);
+ check("2", 0, false, 2);
+ check("+102", "1", false, 1);
+
+ check("1<0>", 0, true, 1);
+ check("+1<2>", "1<2>", true, 1);
+ check("2<3>", 0, true, 2);
+ check("+3<4>", "3<4>", true, 3);
+ check("-3<4>", "98<4>", true, f.negative(f.toElement(3)).value());
+
+ check("+1a<0>", "a<0>", true, 1);
+ check("+2b", "2b", false, 2);
+}
+
+TEST(MathicIO, ReadWriteBaseField) {
+ Scanner in("101");
+ auto field = MathicIO().readBaseField(in);
+ ASSERT_EQ(101, field.charac());
+ std::ostringstream out;
+ MathicIO().writeBaseField(field, out);
+ ASSERT_EQ("101", out.str());
+}
+
+TEST(MathicIO, ReadWriteOrder) {
+ typedef PolyRing::Monoid Monoid;
+ typedef Monoid::VarIndex VarIndex;
+
+ const auto check = [](
+ const char* const inStr,
+ const char* const outStr,
+ const VarIndex varCount,
+ const VarIndex gradingCount,
+ const bool withComponent = false,
+ const bool componentsAscendingDesired = true,
+ const bool schreyering = false
+ ) -> void {
+ for (int i = 0; i < 2; ++i) {
+ const char* str = i == 0 ? inStr : outStr;
+ if (str == 0)
+ continue;
+
+ Scanner in(str);
+ const auto order = MathicIO().readOrder(varCount, withComponent, in);
+ ASSERT_EQ(varCount, order.varCount());
+ ASSERT_EQ(gradingCount, order.gradingCount());
+ ASSERT_EQ(componentsAscendingDesired, order.componentsAscendingDesired());
+ ASSERT_EQ(schreyering, order.schreyering()) << inStr;
+
+ std::ostringstream out;
+ MathicIO().writeOrder(order, withComponent, out);
+ ASSERT_EQ(outStr, out.str());
+ }
+ };
+ check("0\n", "revlex 0\n", 0, 0);
+ check("1\n 2\n", "revlex 1\n 2\n", 1, 1);
+ check("2\n 3\n 4\n", "revlex 2\n 3\n 4\n", 1, 2);
+ check("2\n 3 4\n 5 6\n", "revlex 2\n 3 4\n 5 6\n", 2, 2);
+ check("1\n 1 1 1 1\n", "revlex 1\n 1 1 1 1\n", 4, 1);
+
+ check("lex 0", "lex 0\n", 0, 0);
+ check("lex 1 2", "lex 1\n 2\n", 1, 1);
+ check("lex 2 3 4", "lex 2\n 3\n 4\n", 1, 2);
+ check("lex 2 3 4 5 6", "lex 2\n 3 4\n 5 6\n", 2, 2);
+ check("lex 1 1 1 1 1", "lex 1\n 1 1 1 1\n", 4, 1);
+
+ check("2 component\n 5 6\n", "revlex 2\n component\n 5 6\n", 2, 2, 1, 1, 0);
+ check("2 3 4\nrevcomponent\n","revlex 2\n 3 4\n revcomponent\n",2,2, 1,0,0);
+ check("lex 1 component", "lex 0\n", 0, 0, 1, 1, 0);
+ check("lex 1 revcomponent", "lex 1\n revcomponent\n", 1, 1, 1, 0, 0);
+ check("lex 1 revcomponent", "lex 1\n revcomponent\n", 5, 1, 1, 0, 0);
+
+ check(
+ "schreyer lex 1 1 _revlex revcomponent",
+ "schreyer revlex 1\n 1\n _revlex\n revcomponent\n",
+ 1, 1, 1, 0, 1
+ );
+}
diff --git a/src/test/MonoMonoid.cpp b/src/test/MonoMonoid.cpp
index e0ca013..20ad8c0 100755
--- a/src/test/MonoMonoid.cpp
+++ b/src/test/MonoMonoid.cpp
@@ -1,865 +1,868 @@
-#include "mathicgb/stdinc.h"
-
-#include "mathicgb/MonoMonoid.hpp"
-#include <gtest/gtest.h>
-#include <sstream>
-
-
-// Do all-pairs testing -- see monoidPict.in. Especially see that file before
-// editing this list of types.
-typedef ::testing::Types<
- MonoMonoid<int32,1,1,1>,
- MonoMonoid<int32,0,1,1>,
- MonoMonoid<int32,0,0,1>,
- MonoMonoid<int32,0,0,0>,
- MonoMonoid<int16,1,1,1>,
- MonoMonoid<int16,0,1,1>,
- MonoMonoid<int16,0,0,1>,
- MonoMonoid<int16,0,0,0>,
- MonoMonoid<int8,1,0,1>,
- MonoMonoid<int8,0,1,0>,
- MonoMonoid<int32,1,1,0>
-> MonoidTypes;
-
-template <typename T>
-class Monoid : public ::testing::Test {};
-TYPED_TEST_CASE(Monoid, MonoidTypes);
-
-// expect(i,j) encodes a matrix with interesting bit patterns that
-// are supposed to be likely to surface errors in how monomials are
-// stored inside a vector.
-uint32 expect(size_t mono, size_t var, size_t varCount) {
- const auto unique = (static_cast<uint32>(var + varCount * mono + 1) % 127);
-
- while (true) {
- // 000
- if (mono == 0)
- return 0;
- --mono;
-
- // 100
- // 010
- // 001
- if (mono < varCount)
- return var == mono ? unique : 0;
- mono -= varCount;
-
- // 000
- // 100
- // 110
- // 111
- if (mono < varCount + 1)
- return var < mono ? unique : 0;
- mono -= varCount + 1;
-
- // 111
- // 011
- // 001
- // 000
- if (mono < varCount + 1)
- return var >= mono ? unique : 0;
- mono -= varCount + 1;
-
- // 101
- // 010
- if (mono < 4)
- return (var % 2) == (mono % 2) ? unique : 0;
- mono -= 4;
-
- // 100100
- // 010010
- // 001001
- if (mono < 6)
- return (var % 3) == (mono % 3) ? unique : 0;
- mono -= 6;
-
- // mix the patterns
- mono += var % 17;
- }
-};
-
-TYPED_TEST(Monoid, VarCount) {
- typedef TypeParam Monoid;
- ASSERT_EQ(0, Monoid(0).varCount());
- ASSERT_EQ(1000 * 1000, Monoid(1000 * 1000).varCount());
- ASSERT_EQ(1, Monoid(1).varCount());
- ASSERT_EQ(2, Monoid(2).varCount());
- ASSERT_EQ(12, Monoid(12).varCount());
-}
-
-TYPED_TEST(Monoid, MonoVector) {
- typedef TypeParam Monoid;
- typedef typename Monoid::VarIndex VarIndex;
- typedef typename Monoid::MonoVector MonoVector;
-
- Monoid monoid(13);
- MonoVector v(monoid);
- MonoVector v2(monoid);
- ASSERT_EQ(v2.monoid(), monoid);
- const auto varCount = monoid.varCount();
-
- ASSERT_TRUE(v.empty());
- size_t count = 1000;
-
-
- // Not a correctness error, but empty vectors should preferably not
- // use any memory.
- ASSERT_EQ(0, v.memoryBytesUsed());
-
- for (size_t i = 0; i < count; ++i) {
- ASSERT_EQ(i, v.size());
- v.push_back(); // push_back, no param
- ASSERT_GT(v.memoryBytesUsed(), 0);
- 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) {
- const auto exponent = expect(i, var, varCount);
- if (exponent != 0) {
- allZero = false;
- monoid.setExponent(var, exponent, v.back());
- }
- }
- ASSERT_EQ(allZero, monoid.isIdentity(v.back())); // isIdentity false
- v2.push_back(v.back()); // push_back with param
- ASSERT_TRUE(monoid.equal(v.back(), v2.back()));
- }
- auto it = v.begin();
- ASSERT_EQ(it, v.cbegin());
- for (size_t i = 0; i < count; ++i, ++it) {
- typename MonoVector::const_iterator tmp;
- tmp = it;
- ASSERT_EQ(tmp, it);
- ASSERT_TRUE(v.end() != it);
-
- for (VarIndex var = 0; var < monoid.varCount(); ++var) {
- ASSERT_EQ(expect(i, var, varCount), monoid.exponent(*it, var));
- }
- }
- ASSERT_EQ(v.end(), it);
- ASSERT_EQ(v.cend(), it);
-
- ASSERT_EQ(v, v2); // operator== true
- monoid.setExponent(0, 1 + monoid.exponent(v2.back(), 0), v2.back());
- ASSERT_TRUE(v != v2); // operator!=, true, same length
-
- auto& vc = const_cast<const MonoVector&>(v);
- ASSERT_TRUE(monoid.equal(v.front(), *v2.begin())); // front, non-const
- ASSERT_TRUE(monoid.equal(vc.front(), *v2.begin())); // front, const
- ASSERT_TRUE(monoid.equal(vc.back(), v.back())); // back, non-const
-
- auto v3(v2); // copy constructor
- ASSERT_EQ(v3.monoid(), monoid);
- ASSERT_TRUE(v != v3 && v2 == v3);
- v2.swap(v); // member swap
- ASSERT_TRUE(v == v3 && v2 != v3);
- std::swap(v, v2); // std::swap
- ASSERT_TRUE(v != v3 && v2 == v3);
- using std::swap;
- swap(v, v2); // let compiler decide which swap to use
- ASSERT_TRUE(v == v3 && v2 != v3);
- swap(v, v2); // get back to original state
- ASSERT_TRUE(v != v3 && v2 == v3);
-
- ASSERT_FALSE(v3 != v2); // operator!=, false, same length
- v3.push_back();
- ASSERT_TRUE(v3 != v2); // operator!=, true, different length
-
-
- ASSERT_FALSE(v3 == v);
- v3 = v; // copy assignment
- ASSERT_EQ(v3.monoid(), monoid);
- ASSERT_EQ(v3, v);
-
- ASSERT_FALSE(v3.empty());
- v2 = std::move(v3); // move assignment
- ASSERT_EQ(v2.monoid(), monoid);
- ASSERT_EQ(v2, v);
- ASSERT_TRUE(v3.empty());
-
- ASSERT_FALSE(v2.empty());
- auto v4(std::move(v2)); // move constructor
- ASSERT_EQ(v4.monoid(), monoid);
- ASSERT_TRUE(v2.empty());
- ASSERT_EQ(v4, v);
-
- ASSERT_FALSE(v.empty());
- v.clear();
- ASSERT_TRUE(v.empty());
-}
-
-TYPED_TEST(Monoid, ReadWriteMonoid) {
- typedef TypeParam Monoid;
- typedef typename Monoid::VarIndex VarIndex;
-
- const auto check = [](
- const char* const inStr,
- const char* const outStr,
- const VarIndex varCount,
- const VarIndex gradingCount
- ) -> void {
- for (int i = 0; i < 2; ++i) {
- const char* str = i == 0 ? inStr : outStr;
- if (str == 0)
- continue;
-
- std::istringstream in(str);
- const auto p = Monoid::readMonoid(in);
- const auto& m = p.first;
-
- std::ostringstream out;
- m.printMonoid(p.second.first, out);
- ASSERT_EQ(outStr, out.str());
- ASSERT_EQ(varCount, m.varCount());
- ASSERT_EQ(gradingCount, m.gradingCount());
- }
- };
- check("0 0\n", "0\nrevlex 0\n", 0, 0);
- check("1 1\n 2\n", "1\nrevlex 1\n 2\n", 1, 1);
- check("1 2\n 3\n 4\n", "1\nrevlex 2\n 3\n 4\n", 1, 2);
- check("2 2\n 3 4\n 5 6\n", "2\nrevlex 2\n 3 4\n 5 6\n", 2, 2);
- check("4 1\n 1 1 1 1\n", "4\nrevlex 1\n 1 1 1 1\n", 4, 1);
-
- check("0 lex 0", "0\nlex 0\n", 0, 0);
- check("1 lex 1 2", "1\nlex 1\n 2\n", 1, 1);
- check("1 lex 2 3 4", "1\nlex 2\n 3\n 4\n", 1, 2);
- check("2 lex 2 3 4 5 6", "2\nlex 2\n 3 4\n 5 6\n", 2, 2);
- check("4 lex 1 1 1 1 1", "4\nlex 1\n 1 1 1 1\n", 4, 1);
-
- if (Monoid::HasComponent) {
- check("2 2\n component\n 5 6\n", "2\nrevlex 2\n component\n 5 6\n", 2, 2);
- check
- ("2 2\n 3 4\n revcomponent\n","2\nrevlex 2\n 3 4\n revcomponent\n", 2, 2);
- check("0 lex 1 component", "0\nlex 0\n", 0, 0);
- check("1 lex 1 revcomponent", "1\nlex 1\n revcomponent\n", 1, 1);
- check("5 lex 1 revcomponent", "5\nlex 1\n revcomponent\n", 5, 1);
- }
-}
-
-TYPED_TEST(Monoid, MonoPool) {
- typedef TypeParam Monoid;
- typedef typename Monoid::VarIndex VarIndex;
- typedef typename Monoid::Mono Mono;
-
- for (int q = 0; q < 2; ++q) {
- Monoid monoid(13);
- typename Monoid::MonoPool pool(monoid);
- const auto varCount = monoid.varCount();
-
- const auto count = 1000;
- std::vector<Mono> monos;
- for (int i = 0; i < count; ++i) {
- pool.alloc();
- pool.free(pool.alloc());
- auto m1 = pool.alloc();
- ASSERT_TRUE(monoid.isIdentity(m1));
- auto m2 = pool.alloc();
- ASSERT_TRUE(monoid.isIdentity(m2));
- for (VarIndex var = 0; var < varCount; ++var) {
- monoid.setExponent(var, 1, m1);
- monoid.setExponent(var, 1, m2);
- }
- if (i > 10) {
- using std::swap;
- swap(m2, monos[i - 10]);
- }
- monos.emplace_back(std::move(m1));
- }
-
- // This ensures that we get to each entry in monos exactly once.
- MATHICGB_ASSERT((count % 17) != 0);
- int i = 0;
- do {
- MATHICGB_ASSERT(!monos[i].isNull());
- ASSERT_FALSE(monoid.isIdentity(monos[i]));
- pool.free(std::move(monos[i]));
- ASSERT_TRUE(monos[i].isNull());
- pool.free(std::move(monos[i]));
- ASSERT_TRUE(monos[i].isNull());
- i = (i + 17) % count;
- } while (i != 0);
-
- // If the ordering of monomials inside the pool has anything to do with
- // allocation and deallocation order, then the monomials inside the
- // pool are at this point all jumbled around. All the entries were also
- // non-zero before, so we test that new allocations are the identity.
-
- for (int i = 0; i < count; ++i) {
- monos[i] = pool.alloc();
- ASSERT_TRUE(monoid.isIdentity(monos[i]));
- for (VarIndex var = 0; var < varCount; ++var)
- monoid.setExponent(var, expect(i, var, varCount), monos[i]);
- }
- for (int i = 0; i < count; ++i) {
- for (VarIndex var = 0; var < varCount; ++var) {
- ASSERT_EQ(expect(i, var, varCount), monoid.exponent(monos[i], var));
- }
- }
- // everything should be free'd now. Let's do all that again.
- }
-}
-
-namespace {
- template<class M>
- typename M::MonoVector parseVector(M& monoid, const char* str) {
- typename M::MonoVector v(monoid);
- std::istringstream in(str);
- v.parseM2(in);
- return v;
- }
-}
-
-TYPED_TEST(Monoid, ParsePrintM2) {
- typedef TypeParam Monoid;
- Monoid m(100);
- std::string str = "1 a z A Z ab a2 a2b ab2 a20b30";
- if (Monoid::HasComponent)
- str += " 1<1> a<2> a2<3> ab<11>\n";
- else
- str += '\n';
- auto v2 = parseVector(m, str.c_str());
- std::ostringstream v2Out;
- v2.printM2(v2Out);
- ASSERT_EQ(str, v2Out.str());
-
- decltype(v2) v(m);
- v.push_back(); // 1
-
- v.push_back(); // a
- m.setExponent(0, 1, v.back());
-
- v.push_back(); // z
- m.setExponent(25, 1, v.back());
-
- v.push_back(); // A
- m.setExponent(26, 1, v.back());
-
- v.push_back(); // Z
- m.setExponent(51, 1, v.back());
-
- v.push_back(); // ab
- m.setExponent(0, 1, v.back());
- m.setExponent(1, 1, v.back());
-
- v.push_back(); // a2
- m.setExponent(0, 2, v.back());
-
- v.push_back(); // a2b
- m.setExponent(0, 2, v.back());
- m.setExponent(1, 1, v.back());
-
- v.push_back(); // ab2
- m.setExponent(0, 1, v.back());
- m.setExponent(1, 2, v.back());
-
- v.push_back(); // a20b30
- m.setExponent(0, 20, v.back());
- m.setExponent(1, 30, v.back());
-
- if (Monoid::HasComponent) {
- v.push_back(); // 1<1>
- m.setComponent(1, v.back());
-
- v.push_back(); // a<2>
- m.setComponent(2, v.back());
- m.setExponent(0, 1, v.back());
-
- v.push_back(); // a2<3>
- m.setComponent(3, v.back());
- m.setExponent(0, 2, v.back());
-
- v.push_back(); // ab<11>
- m.setComponent(11, v.back());
- m.setExponent(0, 1, v.back());
- m.setExponent(1, 1, v.back());
- }
-
- std::ostringstream vOut;
- v.printM2(vOut);
- ASSERT_EQ(str, vOut.str());
-
- ASSERT_EQ(v, v2);
-}
-
-
-TYPED_TEST(Monoid, MultiplyDivide) {
- typedef TypeParam Monoid;
- Monoid m(49);
- typename Monoid::MonoPool pool(m);
- auto mono = pool.alloc();
- auto check = [&](const char* const str, const bool component) -> void {
- if (component && !Monoid::HasComponent)
- return;
- auto v = parseVector(m, str);
- MATHICGB_ASSERT(v.size() == 3);
- const auto& a = v.front();
- const auto& b = *++v.begin();
- const auto& c = v.back();
- ASSERT_EQ(m.hashOfProduct(a, b), m.hash(c));
- ASSERT_EQ(m.hashOfProduct(a, b), m.hashOfProduct(b, a));
-
- // isProductOf
- ASSERT_TRUE(m.isProductOf(a, b, c));
- ASSERT_TRUE(m.isProductOfHintTrue(a, b, c));
- ASSERT_TRUE(m.isTwoProductsOfHintTrue(a, a, b, c, c));
-
-
- // a*b == c using multiply
- m.multiply(a, b, mono);
- ASSERT_TRUE(m.equal(c, mono));
- ASSERT_TRUE(m.compare(c, mono) == Monoid::EqualTo);
- ASSERT_EQ(m.hash(c), m.hash(mono));
-
- // c/a == b using divide
- m.divide(a, c, mono);
- ASSERT_TRUE(m.equal(b, mono));
- ASSERT_TRUE(m.compare(b, mono) == Monoid::EqualTo);
- ASSERT_EQ(m.hash(b), m.hash(mono));
-
- // c/b == a using divideInPlace
- m.copy(c, mono);
- m.divideInPlace(b, mono);
- ASSERT_TRUE(m.equal(a, mono));
- ASSERT_TRUE(m.compare(a, mono) == Monoid::EqualTo);
- ASSERT_EQ(m.hash(a), m.hash(mono));
-
- // a*b == c using multiplyInPlace
- m.copy(a, mono);
- m.multiplyInPlace(b, mono);
- ASSERT_TRUE(m.equal(c, mono));
- ASSERT_TRUE(m.compare(c, mono) == Monoid::EqualTo);
- ASSERT_EQ(m.hash(c), m.hash(mono));
-
- // divides, check properties that mono=a*b should have
- ASSERT_TRUE(m.divides(mono, c));
- ASSERT_TRUE(m.divides(c, mono));
- ASSERT_TRUE(m.divides(a, mono));
- ASSERT_TRUE(m.divides(b, mono));
-
- // divides, general
- ASSERT_TRUE(m.divides(m, mono, c));
- ASSERT_TRUE(m.divides(m, c, mono));
- ASSERT_TRUE(m.divides(m, a, mono));
- ASSERT_TRUE(m.divides(m, b, mono));
-
- if (!m.isIdentity(a)) {
- ASSERT_TRUE(m.lessThan(b, mono));
- ASSERT_FALSE(m.lessThan(mono, b));
- ASSERT_TRUE(m.compare(mono, b) == Monoid::GreaterThan);
- ASSERT_FALSE(m.divides(mono, b));
- ASSERT_FALSE(m.divides(m, mono, b));
-
- ASSERT_FALSE(m.isProductOf(a, c, b));
- ASSERT_FALSE(m.isProductOfHintTrue(a, c, b));
- ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, c, a, b, b));
- ASSERT_FALSE(m.isTwoProductsOfHintTrue(b, c, a, c, b));
- ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, b, a, b, c));
- } else {
- ASSERT_TRUE(m.equal(b, mono));
- ASSERT_TRUE(m.compare(b, mono) == Monoid::EqualTo);
- ASSERT_TRUE(m.divides(mono, b));
- ASSERT_TRUE(m.divides(m, mono, b));
- }
-
- if (!m.isIdentity(b)) {
- ASSERT_TRUE(m.lessThan(a, mono));
- ASSERT_FALSE(m.lessThan(mono, a));
- ASSERT_TRUE(m.compare(mono, a) == Monoid::GreaterThan);
- ASSERT_FALSE(m.divides(mono, a));
- ASSERT_FALSE(m.divides(m, mono, a));
-
- ASSERT_FALSE(m.isProductOf(c, b, a));
- ASSERT_FALSE(m.isProductOfHintTrue(b, c, a));
- ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, c, b, a, a));
- ASSERT_FALSE(m.isTwoProductsOfHintTrue(a, c, b, c, a));
- ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, a, b, a, c));
- } else {
- ASSERT_TRUE(m.equal(a, mono));
- ASSERT_TRUE(m.compare(a, mono) == Monoid::EqualTo);
- ASSERT_TRUE(m.divides(m, mono, a));
- }
-
- // Check that aliased parameters work.
- m.multiply(mono, mono, mono);
- m.divide(mono, mono, mono);
- MATHICGB_ASSERT(m.isIdentity(mono));
-
- // Check that negative exponents work.
- if (Monoid::HasComponent && m.component(a) != m.component(b))
- return;
- m.divideToNegative(a, b, mono);
- m.multiply(a, mono, mono);
- ASSERT_TRUE(m.equal(mono, b));
-
- m.divideToNegative(b, a, mono);
- m.multiply(b, mono, mono);
- ASSERT_TRUE(m.equal(mono, a));
- };
- check("1 1 1", false);
- check("a<5> 1 a<5>", true);
- check("1 Vx Vx", false);
- check("aV bx abxV", false);
- check("a a2 a3", false);
- check("V<2> V2 V3<2>", true);
- check("arlgh svug arlg2hsvu", false);
- check("abcdefghiV<7> ab2c3d4e5f6g7h8i9V11 a2b3c4d5e6f7g8h9i10V12<7>", true);
-}
-
-TYPED_TEST(Monoid, LcmColon) {
- typedef TypeParam Monoid;
- Monoid mNonConst(49);
- auto& m = mNonConst;
- typename Monoid::MonoPool pool(m);
- auto mono = pool.alloc();
- auto mono2 = pool.alloc();
- auto check = [&](const char* const str, const bool component) -> void {
- if (component && !Monoid::HasComponent)
- return;
- auto v = parseVector(m, str);
- MATHICGB_ASSERT(v.size() == 3);
- const auto& a = v.front();
- const auto& b = *++v.begin();
- const auto& lcm = v.back();
-
- // isLcm (+general)
- ASSERT_TRUE(m.isLcm(a, b, lcm));
- ASSERT_TRUE(m.isLcm(m, a, m, b, lcm));
- m.copy(lcm, mono);
- m.setExponent(1, m.exponent(mono, 1) + 1, mono);
- ASSERT_FALSE(m.isLcm(a, b, mono));
- ASSERT_FALSE(m.isLcm(m, a, m, b, mono));
-
- // dividesLcm
- ASSERT_TRUE(m.dividesLcm(lcm, a, b));
- ASSERT_FALSE(m.dividesLcm(mono, a, b));
- ASSERT_TRUE(m.dividesLcm(a, a, a));
- ASSERT_TRUE(m.dividesLcm(a, a, b));
- ASSERT_TRUE(m.dividesLcm(b, b, b));
- ASSERT_TRUE(m.dividesLcm(b, b, a));
-
- // dividesLcm, general
- ASSERT_TRUE(m.dividesLcm(m, lcm, m, a, b));
- ASSERT_FALSE(m.dividesLcm(m, mono, m, a, b));
- ASSERT_TRUE(m.dividesLcm(m, a, m, a, a));
- ASSERT_TRUE(m.dividesLcm(m, a, m, a, b));
- ASSERT_TRUE(m.dividesLcm(m, b, m, b, b));
- ASSERT_TRUE(m.dividesLcm(m, b, m, b, a));
-
- // lcm(a, b)
- m.lcm(a, b, mono);
- ASSERT_TRUE(m.equal(mono, lcm));
- ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo);
- ASSERT_EQ(m.hash(lcm), m.hash(mono));
-
- // lcm(b, a), general
- m.lcm(m, b, m, a, mono);
- ASSERT_TRUE(m.equal(mono, lcm));
- ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo);
- ASSERT_EQ(m.hash(lcm), m.hash(mono));
-
- // colons
- m.colons(a, b, mono, mono2);
- m.multiply(b, mono, mono);
- m.multiply(a, mono2, mono2);
- ASSERT_TRUE(m.equal(mono, lcm));
- ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo);
- ASSERT_TRUE(m.equal(mono2, lcm));
- ASSERT_TRUE(m.compare(mono2, lcm) == Monoid::EqualTo);
- };
- check("1 1 1", false);
- check("a<2> 1<2> a<2>", true);
- check("1 Vx Vx", false);
- check("aV bx abxV", false);
- check("a a2 a2", false);
- check("V<3> V2<3> V2<3>", true);
- check("arlgh svug arlghsvu", false);
- check("a6b7c8d9efghiV ab2c3d4e5f6g7h8i9V11 a6b7c8d9e5f6g7h8i9V11", false);
-}
-
-TYPED_TEST(Monoid, Order) {
- typedef TypeParam Monoid;
- typedef typename Monoid::Order Order;
- typedef typename Monoid::Exponent Exponent;
-
- auto check = [](const Monoid& m, const char* sorted) -> void {
- auto v = parseVector(m, sorted);
- for (auto greater = v.begin(); greater != v.end(); ++greater) {
- ASSERT_EQ(m.compare(*greater, *greater), Monoid::EqualTo);
- ASSERT_TRUE(m.equal(*greater, *greater));
- ASSERT_FALSE(m.lessThan(*greater, *greater));
-
- for (auto lesser = v.begin(); lesser != greater; ++lesser) {
- ASSERT_FALSE(m.equal(*lesser, *greater));
- ASSERT_TRUE(m.lessThan(*lesser, *greater))
- << "*lesser is " << m.toString(*lesser) << '\n'
- << "*greater is " << m.toString(*greater) << '\n';
- ASSERT_FALSE(m.lessThan(*greater, *lesser));
- ASSERT_EQ(m.compare(*lesser, *greater), Monoid::LessThan);
- ASSERT_EQ(m.compare(*greater, *lesser), Monoid::GreaterThan);
- }
- }
- };
-
- const auto sortedTotalDegreeRevLex =
- "1 Z A z c b a c2 bc ac b2 ab a2 c3 abc b3 a3";
- check(Monoid(52), sortedTotalDegreeRevLex);
- check(
- Monoid(Order(52, std::vector<Exponent>(52, 1), Order::RevLexBaseOrder)),
- sortedTotalDegreeRevLex
- );
- check(
- Monoid(Order(52, std::vector<Exponent>(52, 7), Order::RevLexBaseOrder)),
- sortedTotalDegreeRevLex
- );
- std::vector<Exponent> revLexGradings(52, 1);
- for (size_t grading = 51; grading != static_cast<size_t>(-1); --grading)
- for (size_t var = 0; var < 52; ++var)
- revLexGradings.push_back(var == grading ? -1 : 0);
- check(
- Monoid(
- Order(52, std::vector<Exponent>(revLexGradings), Order::RevLexBaseOrder)
- ),
- sortedTotalDegreeRevLex
- );
- check(
- Monoid(Order(52, std::move(revLexGradings), Order::LexBaseOrder)),
- sortedTotalDegreeRevLex
- );
-
- std::vector<Exponent> dupGradings = {
- 5, 2, 3,
- 10, 4, 6, // duplicate, just multiplied by 2
- -6, 9, 4,
- -6, 9, 4,
- -6, 9, 4,
- -6, 9, 4,
- -6, 9, 4
- };
- // b: 2 9
- // c: 3 4
- // a: 5 -7
- // bc: 5 20
- // c2: 6 8
- // b3: 6 27
- // bc3: 11 21
- // ab3: 11 21
- const auto sortedDupGradingsRevLex = "1 b c a bc c2 b3 bc3 ab3";
- check(
- Monoid(Order(3, std::move(dupGradings), Order::RevLexBaseOrder)),
- sortedDupGradingsRevLex
- );
-
- std::vector<Exponent> lexGradings = {
- 0, 0, 1,
- 0, 1, 0,
- 1, 0, 0
- };
- const auto sortedLex =
- "1 a a2 a3 b ab a2b b2 ab2 b3 c ac bc abc c2 ac2 bc2 c3";
- check(
- Monoid(
- Order(3, std::vector<Exponent>(lexGradings), Order::RevLexBaseOrder)
- ),
- sortedLex
- );
- check
- (Monoid(Order(3, std::move(lexGradings), Order::LexBaseOrder)), sortedLex);
- check
- (Monoid(Order(3, std::vector<Exponent>(), Order::LexBaseOrder)), sortedLex);
-}
-
-TYPED_TEST(Monoid, RelativelyPrime) {
- typedef TypeParam Monoid;
- Monoid m(49);
- typename Monoid::MonoPool pool(m);
- auto mono = pool.alloc();
- auto mono2 = pool.alloc();
- auto check = [&](const char* str, bool relativelyPrime) -> void {
- auto v = parseVector(m, str);
- MATHICGB_ASSERT(v.size() == 2);
- ASSERT_EQ(relativelyPrime, m.relativelyPrime(v.front(), v.back()));
- ASSERT_EQ(relativelyPrime, m.relativelyPrime(v.back(), v.front()));
- };
- check("1 1", true);
- check("1 abcdefgh", true);
- check("abc defgh", true);
- check("bdfh aceg", true);
- check("bdefh aceg", false);
- check("abcdefgh abcdefgh", false);
- check("fgh abcdef", false);
-}
-
-TYPED_TEST(Monoid, SetExponents) {
- typedef TypeParam Monoid;
- Monoid m(5);
- auto v = parseVector(m, "a1b2c3d4e5");
- typename Monoid::Exponent exponents[] = {1, 2, 3, 4, 5};
- v.push_back();
- m.setExponents(exponents, v.back());
- ASSERT_TRUE(m.equal(v.front(), v.back()));
-}
-
-TYPED_TEST(Monoid, HasAmpleCapacityTotalDegree) {
- typedef TypeParam Monoid;
- typedef typename Monoid::Order Order;
- typedef typename Monoid::Exponent Exponent;
- typedef typename Monoid::VarIndex VarIndex;
-
- for (VarIndex varCount = 1; varCount < 33; ++varCount) {
- Monoid monoidTotalDegree(varCount);
-
- std::vector<Exponent> ones(varCount, 1);
- Monoid monoidTotalDegreeImplicit
- (Order(varCount, std::move(ones), Order::RevLexBaseOrder));
-
- std::vector<Exponent> mostlyOnes(varCount, 1);
- mostlyOnes[0] = 7;
- Monoid monoidGeneral
- (Order(varCount, std::move(mostlyOnes), Order::RevLexBaseOrder));
-
- Monoid* monoids[] = {
- &monoidTotalDegree,
- &monoidTotalDegreeImplicit,
- &monoidGeneral
- };
- for (int j = 0; j < 3; ++j) {
- auto& m = *monoids[j];
- const auto firstDeg = (j == 2 ? 7 : 1);
- ASSERT_EQ(varCount, m.varCount());
-
- typename Monoid::MonoPool p(m);
- auto mono = p.alloc();
- const auto last = m.varCount() - 1;
- const auto max = std::numeric_limits<Exponent>::max() / 2;
-
- // pure power, first variable
- m.setIdentity(mono);
- m.setExponent(0, max / firstDeg, mono);
- ASSERT_TRUE(m.hasAmpleCapacity(mono));
- m.setExponent(0, max / firstDeg + 1, mono);
- ASSERT_FALSE(m.hasAmpleCapacity(mono));
-
- if (varCount == 1)
- continue;
-
- // pure power, last variable
- m.setIdentity(mono);
- m.setExponent(last, max, mono);
- ASSERT_TRUE(m.hasAmpleCapacity(mono));
- m.setExponent(last, max + 1, mono);
- ASSERT_FALSE(m.hasAmpleCapacity(mono));
-
- // no exponent is too high but the degree is
- m.setIdentity(mono);
- m.setExponent(0, 12, mono);
- m.setExponent(last, max - 12 * firstDeg, mono);
- ASSERT_TRUE(m.hasAmpleCapacity(mono));
- m.setExponent(0, 13, mono);
- ASSERT_FALSE(m.hasAmpleCapacity(mono));
- }
- }
-}
-
-TYPED_TEST(Monoid, CopyEqualConversion) {
- typedef TypeParam Monoid;
- typedef typename Monoid::Order Order;
- typedef typename Monoid::Exponent Exponent;
- typedef typename Monoid::VarIndex VarIndex;
- static const bool HasComponent = Monoid::HasComponent;
- typedef MonoMonoid<Exponent, HasComponent, false, false> MonoidNone;
- typedef MonoMonoid<Exponent, HasComponent, true, true> MonoidAll;
- for (VarIndex varCount = 1; varCount < 33; ++varCount) {
- const Order order
- (varCount, std::vector<Exponent>(varCount, 1), Order::RevLexBaseOrder);
- MonoidNone none(order);
- Monoid some(Monoid::create(none));
- MonoidAll all(MonoidAll::create(some));
-
- auto none1 = none.alloc();
- auto none2 = none.alloc();
- auto none3 = none.alloc();
- auto some1 = some.alloc();
- auto some2 = some.alloc();
- auto some3 = some.alloc();
- auto all1 = all.alloc();
- auto all2 = all.alloc();
- auto all3 = all.alloc();
-
- none.setExponent(0, 1, none1);
- none.setExponent(varCount / 2, 2, none1);
- none.setExponent(varCount - 1, 3, none1);
- none.copy(none1, none2);
- none.setExponent(0, 4, none2);
-
- some.setExponent(0, 1, some1);
- some.setExponent(varCount / 2, 2, some1);
- some.setExponent(varCount - 1, 3, some1);
- some.copy(some1, some2);
- some.setExponent(0, 4, some2);
-
- all.setExponent(0, 1, all1);
- all.setExponent(varCount / 2, 2, all1);
- all.setExponent(varCount - 1, 3, all1);
- all.copy(all1, all2);
- all.setExponent(0, 4, all2);
-
- // compare on none
- ASSERT_TRUE(none.equal(none, none1, none1));
- ASSERT_TRUE(none.equal(some, some1, none1));
- ASSERT_TRUE(none.equal(all, all1, none1));
- ASSERT_FALSE(none.equal(none, none1, none2));
- ASSERT_FALSE(none.equal(some, some1, none2));
- ASSERT_FALSE(none.equal(all, all1, none2));
-
- // compare on some
- ASSERT_TRUE(some.equal(none, none1, some1));
- ASSERT_TRUE(some.equal(some, some1, some1));
- ASSERT_TRUE(some.equal(all, all1, some1));
- ASSERT_FALSE(some.equal(none, none1, some2));
- ASSERT_FALSE(some.equal(some, some1, some2));
- ASSERT_FALSE(some.equal(all, all1, some2));
-
- // compare on all
- ASSERT_TRUE(all.equal(none, none1, all1));
- ASSERT_TRUE(all.equal(some, some1, all1));
- ASSERT_TRUE(all.equal(all, all1, all1));
- ASSERT_FALSE(all.equal(none, none1, all2));
- ASSERT_FALSE(all.equal(some, some1, all2));
- ASSERT_FALSE(all.equal(all, all1, all2));
-
- // convert some->none
- none.copy(some, some1, none3);
- ASSERT_TRUE(none.equal(none1, none3));
- ASSERT_FALSE(none.equal(none2, none3));
- none.copy(some, some2, none3);
- ASSERT_FALSE(none.equal(none1, none3));
- ASSERT_TRUE(none.equal(none2, none3));
-
- /// convert some->all
- all.copy(some, some1, all3);
- ASSERT_TRUE(all.equal(all1, all3));
- ASSERT_FALSE(all.equal(all2, all3));
- all.copy(some, some2, all3);
- ASSERT_FALSE(all.equal(all1, all3));
- ASSERT_TRUE(all.equal(all2, all3));
-
- // convert none->some
- some.copy(none, none1, some3);
- ASSERT_TRUE(some.equal(some1, some3));
- ASSERT_FALSE(some.equal(some2, some3));
- some.copy(none, none2, some3);
- ASSERT_FALSE(some.equal(some1, some3));
- ASSERT_TRUE(some.equal(some2, some3));
-
- // convert Y->some
- some.copy(none, none1, some3);
- ASSERT_TRUE(some.equal(some1, some3));
- ASSERT_FALSE(some.equal(some2, some3));
- some.copy(none, none2, some3);
- ASSERT_FALSE(some.equal(some1, some3));
- ASSERT_TRUE(some.equal(some2, some3));
- }
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+#include "mathicgb/MonoMonoid.hpp"
+
+#include <gtest/gtest.h>
+#include <sstream>
+
+using namespace mgb;
+
+// Do all-pairs testing -- see monoidPict.in. Especially see that file before
+// editing this list of types.
+typedef ::testing::Types<
+ MonoMonoid<int32,1,1,1>,
+ MonoMonoid<int32,0,1,1>,
+ MonoMonoid<int32,0,0,1>,
+ MonoMonoid<int32,0,0,0>,
+ MonoMonoid<int16,1,1,1>,
+ MonoMonoid<int16,0,1,1>,
+ MonoMonoid<int16,0,0,1>,
+ MonoMonoid<int16,0,0,0>,
+ MonoMonoid<int8,1,0,1>,
+ MonoMonoid<int8,0,1,0>,
+ MonoMonoid<int32,1,1,0>
+> MonoidTypes;
+
+template <typename T>
+class Monoid : public ::testing::Test {};
+TYPED_TEST_CASE(Monoid, MonoidTypes);
+
+// expect(i,j) encodes a matrix with interesting bit patterns that
+// are supposed to be likely to surface errors in how monomials are
+// stored inside a vector.
+uint32 expect(size_t mono, size_t var, size_t varCount) {
+ const auto unique = (static_cast<uint32>(var + varCount * mono + 1) % 127);
+
+ while (true) {
+ // 000
+ if (mono == 0)
+ return 0;
+ --mono;
+
+ // 100
+ // 010
+ // 001
+ if (mono < varCount)
+ return var == mono ? unique : 0;
+ mono -= varCount;
+
+ // 000
+ // 100
+ // 110
+ // 111
+ if (mono < varCount + 1)
+ return var < mono ? unique : 0;
+ mono -= varCount + 1;
+
+ // 111
+ // 011
+ // 001
+ // 000
+ if (mono < varCount + 1)
+ return var >= mono ? unique : 0;
+ mono -= varCount + 1;
+
+ // 101
+ // 010
+ if (mono < 4)
+ return (var % 2) == (mono % 2) ? unique : 0;
+ mono -= 4;
+
+ // 100100
+ // 010010
+ // 001001
+ if (mono < 6)
+ return (var % 3) == (mono % 3) ? unique : 0;
+ mono -= 6;
+
+ // mix the patterns
+ mono += var % 17;
+ }
+};
+
+TYPED_TEST(Monoid, VarCount) {
+ typedef TypeParam Monoid;
+ ASSERT_EQ(0, Monoid(0).varCount());
+ ASSERT_EQ(1000 * 1000, Monoid(1000 * 1000).varCount());
+ ASSERT_EQ(1, Monoid(1).varCount());
+ ASSERT_EQ(2, Monoid(2).varCount());
+ ASSERT_EQ(12, Monoid(12).varCount());
+}
+
+TYPED_TEST(Monoid, MonoVector) {
+ typedef TypeParam Monoid;
+ typedef typename Monoid::VarIndex VarIndex;
+ typedef typename Monoid::MonoVector MonoVector;
+
+ Monoid monoid(13);
+ MonoVector v(monoid);
+ MonoVector v2(monoid);
+ ASSERT_EQ(v2.monoid(), monoid);
+ const auto varCount = monoid.varCount();
+
+ ASSERT_TRUE(v.empty());
+ size_t count = 1000;
+
+
+ // Not a correctness error, but empty vectors should preferably not
+ // use any memory.
+ ASSERT_EQ(0, v.memoryBytesUsed());
+
+ for (size_t i = 0; i < count; ++i) {
+ ASSERT_EQ(i, v.size());
+ v.push_back(); // push_back, no param
+ ASSERT_GT(v.memoryBytesUsed(), 0);
+ 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) {
+ const auto exponent = expect(i, var, varCount);
+ if (exponent != 0) {
+ allZero = false;
+ monoid.setExponent(var, exponent, v.back());
+ }
+ }
+ ASSERT_EQ(allZero, monoid.isIdentity(v.back())); // isIdentity false
+ v2.push_back(v.back()); // push_back with param
+ ASSERT_TRUE(monoid.equal(v.back(), v2.back()));
+ }
+ auto it = v.begin();
+ ASSERT_EQ(it, v.cbegin());
+ for (size_t i = 0; i < count; ++i, ++it) {
+ typename MonoVector::const_iterator tmp;
+ tmp = it;
+ ASSERT_EQ(tmp, it);
+ ASSERT_TRUE(v.end() != it);
+
+ for (VarIndex var = 0; var < monoid.varCount(); ++var) {
+ ASSERT_EQ(expect(i, var, varCount), monoid.exponent(*it, var));
+ }
+ }
+ ASSERT_EQ(v.end(), it);
+ ASSERT_EQ(v.cend(), it);
+
+ ASSERT_EQ(v, v2); // operator== true
+ monoid.setExponent(0, 1 + monoid.exponent(v2.back(), 0), v2.back());
+ ASSERT_TRUE(v != v2); // operator!=, true, same length
+
+ auto& vc = const_cast<const MonoVector&>(v);
+ ASSERT_TRUE(monoid.equal(v.front(), *v2.begin())); // front, non-const
+ ASSERT_TRUE(monoid.equal(vc.front(), *v2.begin())); // front, const
+ ASSERT_TRUE(monoid.equal(vc.back(), v.back())); // back, non-const
+
+ auto v3(v2); // copy constructor
+ ASSERT_EQ(v3.monoid(), monoid);
+ ASSERT_TRUE(v != v3 && v2 == v3);
+ v2.swap(v); // member swap
+ ASSERT_TRUE(v == v3 && v2 != v3);
+ std::swap(v, v2); // std::swap
+ ASSERT_TRUE(v != v3 && v2 == v3);
+ using std::swap;
+ swap(v, v2); // let compiler decide which swap to use
+ ASSERT_TRUE(v == v3 && v2 != v3);
+ swap(v, v2); // get back to original state
+ ASSERT_TRUE(v != v3 && v2 == v3);
+
+ ASSERT_FALSE(v3 != v2); // operator!=, false, same length
+ v3.push_back();
+ ASSERT_TRUE(v3 != v2); // operator!=, true, different length
+
+
+ ASSERT_FALSE(v3 == v);
+ v3 = v; // copy assignment
+ ASSERT_EQ(v3.monoid(), monoid);
+ ASSERT_EQ(v3, v);
+
+ ASSERT_FALSE(v3.empty());
+ v2 = std::move(v3); // move assignment
+ ASSERT_EQ(v2.monoid(), monoid);
+ ASSERT_EQ(v2, v);
+ ASSERT_TRUE(v3.empty());
+
+ ASSERT_FALSE(v2.empty());
+ auto v4(std::move(v2)); // move constructor
+ ASSERT_EQ(v4.monoid(), monoid);
+ ASSERT_TRUE(v2.empty());
+ ASSERT_EQ(v4, v);
+
+ ASSERT_FALSE(v.empty());
+ v.clear();
+ ASSERT_TRUE(v.empty());
+}
+
+TYPED_TEST(Monoid, ReadWriteMonoid) {
+ typedef TypeParam Monoid;
+ typedef typename Monoid::VarIndex VarIndex;
+
+ const auto check = [](
+ const char* const inStr,
+ const char* const outStr,
+ const VarIndex varCount,
+ const VarIndex gradingCount
+ ) -> void {
+ for (int i = 0; i < 2; ++i) {
+ const char* str = i == 0 ? inStr : outStr;
+ if (str == 0)
+ continue;
+
+ std::istringstream in(str);
+ const auto p = Monoid::readMonoid(in);
+ const auto& m = p.first;
+
+ std::ostringstream out;
+ m.printMonoid(p.second.first, out);
+ ASSERT_EQ(outStr, out.str());
+ ASSERT_EQ(varCount, m.varCount());
+ ASSERT_EQ(gradingCount, m.gradingCount());
+ }
+ };
+ check("0 0\n", "0\nrevlex 0\n", 0, 0);
+ check("1 1\n 2\n", "1\nrevlex 1\n 2\n", 1, 1);
+ check("1 2\n 3\n 4\n", "1\nrevlex 2\n 3\n 4\n", 1, 2);
+ check("2 2\n 3 4\n 5 6\n", "2\nrevlex 2\n 3 4\n 5 6\n", 2, 2);
+ check("4 1\n 1 1 1 1\n", "4\nrevlex 1\n 1 1 1 1\n", 4, 1);
+
+ check("0 lex 0", "0\nlex 0\n", 0, 0);
+ check("1 lex 1 2", "1\nlex 1\n 2\n", 1, 1);
+ check("1 lex 2 3 4", "1\nlex 2\n 3\n 4\n", 1, 2);
+ check("2 lex 2 3 4 5 6", "2\nlex 2\n 3 4\n 5 6\n", 2, 2);
+ check("4 lex 1 1 1 1 1", "4\nlex 1\n 1 1 1 1\n", 4, 1);
+
+ if (Monoid::HasComponent) {
+ check("2 2\n component\n 5 6\n", "2\nrevlex 2\n component\n 5 6\n", 2, 2);
+ check
+ ("2 2\n 3 4\n revcomponent\n","2\nrevlex 2\n 3 4\n revcomponent\n", 2, 2);
+ check("0 lex 1 component", "0\nlex 0\n", 0, 0);
+ check("1 lex 1 revcomponent", "1\nlex 1\n revcomponent\n", 1, 1);
+ check("5 lex 1 revcomponent", "5\nlex 1\n revcomponent\n", 5, 1);
+ }
+}
+
+TYPED_TEST(Monoid, MonoPool) {
+ typedef TypeParam Monoid;
+ typedef typename Monoid::VarIndex VarIndex;
+ typedef typename Monoid::Mono Mono;
+
+ for (int q = 0; q < 2; ++q) {
+ Monoid monoid(13);
+ typename Monoid::MonoPool pool(monoid);
+ const auto varCount = monoid.varCount();
+
+ const auto count = 1000;
+ std::vector<Mono> monos;
+ for (int i = 0; i < count; ++i) {
+ pool.alloc();
+ pool.free(pool.alloc());
+ auto m1 = pool.alloc();
+ ASSERT_TRUE(monoid.isIdentity(m1));
+ auto m2 = pool.alloc();
+ ASSERT_TRUE(monoid.isIdentity(m2));
+ for (VarIndex var = 0; var < varCount; ++var) {
+ monoid.setExponent(var, 1, m1);
+ monoid.setExponent(var, 1, m2);
+ }
+ if (i > 10) {
+ using std::swap;
+ swap(m2, monos[i - 10]);
+ }
+ monos.emplace_back(std::move(m1));
+ }
+
+ // This ensures that we get to each entry in monos exactly once.
+ MATHICGB_ASSERT((count % 17) != 0);
+ int i = 0;
+ do {
+ MATHICGB_ASSERT(!monos[i].isNull());
+ ASSERT_FALSE(monoid.isIdentity(monos[i]));
+ pool.free(std::move(monos[i]));
+ ASSERT_TRUE(monos[i].isNull());
+ pool.free(std::move(monos[i]));
+ ASSERT_TRUE(monos[i].isNull());
+ i = (i + 17) % count;
+ } while (i != 0);
+
+ // If the ordering of monomials inside the pool has anything to do with
+ // allocation and deallocation order, then the monomials inside the
+ // pool are at this point all jumbled around. All the entries were also
+ // non-zero before, so we test that new allocations are the identity.
+
+ for (int i = 0; i < count; ++i) {
+ monos[i] = pool.alloc();
+ ASSERT_TRUE(monoid.isIdentity(monos[i]));
+ for (VarIndex var = 0; var < varCount; ++var)
+ monoid.setExponent(var, expect(i, var, varCount), monos[i]);
+ }
+ for (int i = 0; i < count; ++i) {
+ for (VarIndex var = 0; var < varCount; ++var) {
+ ASSERT_EQ(expect(i, var, varCount), monoid.exponent(monos[i], var));
+ }
+ }
+ // everything should be free'd now. Let's do all that again.
+ }
+}
+
+namespace {
+ template<class M>
+ typename M::MonoVector parseVector(M& monoid, const char* str) {
+ typename M::MonoVector v(monoid);
+ std::istringstream in(str);
+ v.parseM2(in);
+ return v;
+ }
+}
+
+TYPED_TEST(Monoid, ParsePrintM2) {
+ typedef TypeParam Monoid;
+ Monoid m(100);
+ std::string str = "1 a z A Z ab a2 a2b ab2 a20b30";
+ if (Monoid::HasComponent)
+ str += " 1<1> a<2> a2<3> ab<11>\n";
+ else
+ str += '\n';
+ auto v2 = parseVector(m, str.c_str());
+ std::ostringstream v2Out;
+ v2.printM2(v2Out);
+ ASSERT_EQ(str, v2Out.str());
+
+ decltype(v2) v(m);
+ v.push_back(); // 1
+
+ v.push_back(); // a
+ m.setExponent(0, 1, v.back());
+
+ v.push_back(); // z
+ m.setExponent(25, 1, v.back());
+
+ v.push_back(); // A
+ m.setExponent(26, 1, v.back());
+
+ v.push_back(); // Z
+ m.setExponent(51, 1, v.back());
+
+ v.push_back(); // ab
+ m.setExponent(0, 1, v.back());
+ m.setExponent(1, 1, v.back());
+
+ v.push_back(); // a2
+ m.setExponent(0, 2, v.back());
+
+ v.push_back(); // a2b
+ m.setExponent(0, 2, v.back());
+ m.setExponent(1, 1, v.back());
+
+ v.push_back(); // ab2
+ m.setExponent(0, 1, v.back());
+ m.setExponent(1, 2, v.back());
+
+ v.push_back(); // a20b30
+ m.setExponent(0, 20, v.back());
+ m.setExponent(1, 30, v.back());
+
+ if (Monoid::HasComponent) {
+ v.push_back(); // 1<1>
+ m.setComponent(1, v.back());
+
+ v.push_back(); // a<2>
+ m.setComponent(2, v.back());
+ m.setExponent(0, 1, v.back());
+
+ v.push_back(); // a2<3>
+ m.setComponent(3, v.back());
+ m.setExponent(0, 2, v.back());
+
+ v.push_back(); // ab<11>
+ m.setComponent(11, v.back());
+ m.setExponent(0, 1, v.back());
+ m.setExponent(1, 1, v.back());
+ }
+
+ std::ostringstream vOut;
+ v.printM2(vOut);
+ ASSERT_EQ(str, vOut.str());
+
+ ASSERT_EQ(v, v2);
+}
+
+
+TYPED_TEST(Monoid, MultiplyDivide) {
+ typedef TypeParam Monoid;
+ Monoid m(49);
+ typename Monoid::MonoPool pool(m);
+ auto mono = pool.alloc();
+ auto check = [&](const char* const str, const bool component) -> void {
+ if (component && !Monoid::HasComponent)
+ return;
+ auto v = parseVector(m, str);
+ MATHICGB_ASSERT(v.size() == 3);
+ const auto& a = v.front();
+ const auto& b = *++v.begin();
+ const auto& c = v.back();
+ ASSERT_EQ(m.hashOfProduct(a, b), m.hash(c));
+ ASSERT_EQ(m.hashOfProduct(a, b), m.hashOfProduct(b, a));
+
+ // isProductOf
+ ASSERT_TRUE(m.isProductOf(a, b, c));
+ ASSERT_TRUE(m.isProductOfHintTrue(a, b, c));
+ ASSERT_TRUE(m.isTwoProductsOfHintTrue(a, a, b, c, c));
+
+
+ // a*b == c using multiply
+ m.multiply(a, b, mono);
+ ASSERT_TRUE(m.equal(c, mono));
+ ASSERT_TRUE(m.compare(c, mono) == Monoid::EqualTo);
+ ASSERT_EQ(m.hash(c), m.hash(mono));
+
+ // c/a == b using divide
+ m.divide(a, c, mono);
+ ASSERT_TRUE(m.equal(b, mono));
+ ASSERT_TRUE(m.compare(b, mono) == Monoid::EqualTo);
+ ASSERT_EQ(m.hash(b), m.hash(mono));
+
+ // c/b == a using divideInPlace
+ m.copy(c, mono);
+ m.divideInPlace(b, mono);
+ ASSERT_TRUE(m.equal(a, mono));
+ ASSERT_TRUE(m.compare(a, mono) == Monoid::EqualTo);
+ ASSERT_EQ(m.hash(a), m.hash(mono));
+
+ // a*b == c using multiplyInPlace
+ m.copy(a, mono);
+ m.multiplyInPlace(b, mono);
+ ASSERT_TRUE(m.equal(c, mono));
+ ASSERT_TRUE(m.compare(c, mono) == Monoid::EqualTo);
+ ASSERT_EQ(m.hash(c), m.hash(mono));
+
+ // divides, check properties that mono=a*b should have
+ ASSERT_TRUE(m.divides(mono, c));
+ ASSERT_TRUE(m.divides(c, mono));
+ ASSERT_TRUE(m.divides(a, mono));
+ ASSERT_TRUE(m.divides(b, mono));
+
+ // divides, general
+ ASSERT_TRUE(m.divides(m, mono, c));
+ ASSERT_TRUE(m.divides(m, c, mono));
+ ASSERT_TRUE(m.divides(m, a, mono));
+ ASSERT_TRUE(m.divides(m, b, mono));
+
+ if (!m.isIdentity(a)) {
+ ASSERT_TRUE(m.lessThan(b, mono));
+ ASSERT_FALSE(m.lessThan(mono, b));
+ ASSERT_TRUE(m.compare(mono, b) == Monoid::GreaterThan);
+ ASSERT_FALSE(m.divides(mono, b));
+ ASSERT_FALSE(m.divides(m, mono, b));
+
+ ASSERT_FALSE(m.isProductOf(a, c, b));
+ ASSERT_FALSE(m.isProductOfHintTrue(a, c, b));
+ ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, c, a, b, b));
+ ASSERT_FALSE(m.isTwoProductsOfHintTrue(b, c, a, c, b));
+ ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, b, a, b, c));
+ } else {
+ ASSERT_TRUE(m.equal(b, mono));
+ ASSERT_TRUE(m.compare(b, mono) == Monoid::EqualTo);
+ ASSERT_TRUE(m.divides(mono, b));
+ ASSERT_TRUE(m.divides(m, mono, b));
+ }
+
+ if (!m.isIdentity(b)) {
+ ASSERT_TRUE(m.lessThan(a, mono));
+ ASSERT_FALSE(m.lessThan(mono, a));
+ ASSERT_TRUE(m.compare(mono, a) == Monoid::GreaterThan);
+ ASSERT_FALSE(m.divides(mono, a));
+ ASSERT_FALSE(m.divides(m, mono, a));
+
+ ASSERT_FALSE(m.isProductOf(c, b, a));
+ ASSERT_FALSE(m.isProductOfHintTrue(b, c, a));
+ ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, c, b, a, a));
+ ASSERT_FALSE(m.isTwoProductsOfHintTrue(a, c, b, c, a));
+ ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, a, b, a, c));
+ } else {
+ ASSERT_TRUE(m.equal(a, mono));
+ ASSERT_TRUE(m.compare(a, mono) == Monoid::EqualTo);
+ ASSERT_TRUE(m.divides(m, mono, a));
+ }
+
+ // Check that aliased parameters work.
+ m.multiply(mono, mono, mono);
+ m.divide(mono, mono, mono);
+ MATHICGB_ASSERT(m.isIdentity(mono));
+
+ // Check that negative exponents work.
+ if (Monoid::HasComponent && m.component(a) != m.component(b))
+ return;
+ m.divideToNegative(a, b, mono);
+ m.multiply(a, mono, mono);
+ ASSERT_TRUE(m.equal(mono, b));
+
+ m.divideToNegative(b, a, mono);
+ m.multiply(b, mono, mono);
+ ASSERT_TRUE(m.equal(mono, a));
+ };
+ check("1 1 1", false);
+ check("a<5> 1 a<5>", true);
+ check("1 Vx Vx", false);
+ check("aV bx abxV", false);
+ check("a a2 a3", false);
+ check("V<2> V2 V3<2>", true);
+ check("arlgh svug arlg2hsvu", false);
+ check("abcdefghiV<7> ab2c3d4e5f6g7h8i9V11 a2b3c4d5e6f7g8h9i10V12<7>", true);
+}
+
+TYPED_TEST(Monoid, LcmColon) {
+ typedef TypeParam Monoid;
+ Monoid mNonConst(49);
+ auto& m = mNonConst;
+ typename Monoid::MonoPool pool(m);
+ auto mono = pool.alloc();
+ auto mono2 = pool.alloc();
+ auto check = [&](const char* const str, const bool component) -> void {
+ if (component && !Monoid::HasComponent)
+ return;
+ auto v = parseVector(m, str);
+ MATHICGB_ASSERT(v.size() == 3);
+ const auto& a = v.front();
+ const auto& b = *++v.begin();
+ const auto& lcm = v.back();
+
+ // isLcm (+general)
+ ASSERT_TRUE(m.isLcm(a, b, lcm));
+ ASSERT_TRUE(m.isLcm(m, a, m, b, lcm));
+ m.copy(lcm, mono);
+ m.setExponent(1, m.exponent(mono, 1) + 1, mono);
+ ASSERT_FALSE(m.isLcm(a, b, mono));
+ ASSERT_FALSE(m.isLcm(m, a, m, b, mono));
+
+ // dividesLcm
+ ASSERT_TRUE(m.dividesLcm(lcm, a, b));
+ ASSERT_FALSE(m.dividesLcm(mono, a, b));
+ ASSERT_TRUE(m.dividesLcm(a, a, a));
+ ASSERT_TRUE(m.dividesLcm(a, a, b));
+ ASSERT_TRUE(m.dividesLcm(b, b, b));
+ ASSERT_TRUE(m.dividesLcm(b, b, a));
+
+ // dividesLcm, general
+ ASSERT_TRUE(m.dividesLcm(m, lcm, m, a, b));
+ ASSERT_FALSE(m.dividesLcm(m, mono, m, a, b));
+ ASSERT_TRUE(m.dividesLcm(m, a, m, a, a));
+ ASSERT_TRUE(m.dividesLcm(m, a, m, a, b));
+ ASSERT_TRUE(m.dividesLcm(m, b, m, b, b));
+ ASSERT_TRUE(m.dividesLcm(m, b, m, b, a));
+
+ // lcm(a, b)
+ m.lcm(a, b, mono);
+ ASSERT_TRUE(m.equal(mono, lcm));
+ ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo);
+ ASSERT_EQ(m.hash(lcm), m.hash(mono));
+
+ // lcm(b, a), general
+ m.lcm(m, b, m, a, mono);
+ ASSERT_TRUE(m.equal(mono, lcm));
+ ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo);
+ ASSERT_EQ(m.hash(lcm), m.hash(mono));
+
+ // colons
+ m.colons(a, b, mono, mono2);
+ m.multiply(b, mono, mono);
+ m.multiply(a, mono2, mono2);
+ ASSERT_TRUE(m.equal(mono, lcm));
+ ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo);
+ ASSERT_TRUE(m.equal(mono2, lcm));
+ ASSERT_TRUE(m.compare(mono2, lcm) == Monoid::EqualTo);
+ };
+ check("1 1 1", false);
+ check("a<2> 1<2> a<2>", true);
+ check("1 Vx Vx", false);
+ check("aV bx abxV", false);
+ check("a a2 a2", false);
+ check("V<3> V2<3> V2<3>", true);
+ check("arlgh svug arlghsvu", false);
+ check("a6b7c8d9efghiV ab2c3d4e5f6g7h8i9V11 a6b7c8d9e5f6g7h8i9V11", false);
+}
+
+TYPED_TEST(Monoid, Order) {
+ typedef TypeParam Monoid;
+ typedef typename Monoid::Order Order;
+ typedef typename Monoid::Exponent Exponent;
+
+ auto check = [](const Monoid& m, const char* sorted) -> void {
+ auto v = parseVector(m, sorted);
+ for (auto greater = v.begin(); greater != v.end(); ++greater) {
+ ASSERT_EQ(m.compare(*greater, *greater), Monoid::EqualTo);
+ ASSERT_TRUE(m.equal(*greater, *greater));
+ ASSERT_FALSE(m.lessThan(*greater, *greater));
+
+ for (auto lesser = v.begin(); lesser != greater; ++lesser) {
+ ASSERT_FALSE(m.equal(*lesser, *greater));
+ ASSERT_TRUE(m.lessThan(*lesser, *greater))
+ << "*lesser is " << m.toString(*lesser) << '\n'
+ << "*greater is " << m.toString(*greater) << '\n';
+ ASSERT_FALSE(m.lessThan(*greater, *lesser));
+ ASSERT_EQ(m.compare(*lesser, *greater), Monoid::LessThan);
+ ASSERT_EQ(m.compare(*greater, *lesser), Monoid::GreaterThan);
+ }
+ }
+ };
+
+ const auto sortedTotalDegreeRevLex =
+ "1 Z A z c b a c2 bc ac b2 ab a2 c3 abc b3 a3";
+ check(Monoid(52), sortedTotalDegreeRevLex);
+ check(
+ Monoid(Order(52, std::vector<Exponent>(52, 1), Order::RevLexBaseOrder)),
+ sortedTotalDegreeRevLex
+ );
+ check(
+ Monoid(Order(52, std::vector<Exponent>(52, 7), Order::RevLexBaseOrder)),
+ sortedTotalDegreeRevLex
+ );
+ std::vector<Exponent> revLexGradings(52, 1);
+ for (size_t grading = 51; grading != static_cast<size_t>(-1); --grading)
+ for (size_t var = 0; var < 52; ++var)
+ revLexGradings.push_back(var == grading ? -1 : 0);
+ check(
+ Monoid(
+ Order(52, std::vector<Exponent>(revLexGradings), Order::RevLexBaseOrder)
+ ),
+ sortedTotalDegreeRevLex
+ );
+ check(
+ Monoid(Order(52, std::move(revLexGradings), Order::LexBaseOrder)),
+ sortedTotalDegreeRevLex
+ );
+
+ std::vector<Exponent> dupGradings = {
+ 5, 2, 3,
+ 10, 4, 6, // duplicate, just multiplied by 2
+ -6, 9, 4,
+ -6, 9, 4,
+ -6, 9, 4,
+ -6, 9, 4,
+ -6, 9, 4
+ };
+ // b: 2 9
+ // c: 3 4
+ // a: 5 -7
+ // bc: 5 20
+ // c2: 6 8
+ // b3: 6 27
+ // bc3: 11 21
+ // ab3: 11 21
+ const auto sortedDupGradingsRevLex = "1 b c a bc c2 b3 bc3 ab3";
+ check(
+ Monoid(Order(3, std::move(dupGradings), Order::RevLexBaseOrder)),
+ sortedDupGradingsRevLex
+ );
+
+ std::vector<Exponent> lexGradings = {
+ 0, 0, 1,
+ 0, 1, 0,
+ 1, 0, 0
+ };
+ const auto sortedLex =
+ "1 a a2 a3 b ab a2b b2 ab2 b3 c ac bc abc c2 ac2 bc2 c3";
+ check(
+ Monoid(
+ Order(3, std::vector<Exponent>(lexGradings), Order::RevLexBaseOrder)
+ ),
+ sortedLex
+ );
+ check
+ (Monoid(Order(3, std::move(lexGradings), Order::LexBaseOrder)), sortedLex);
+ check
+ (Monoid(Order(3, std::vector<Exponent>(), Order::LexBaseOrder)), sortedLex);
+}
+
+TYPED_TEST(Monoid, RelativelyPrime) {
+ typedef TypeParam Monoid;
+ Monoid m(49);
+ typename Monoid::MonoPool pool(m);
+ auto mono = pool.alloc();
+ auto mono2 = pool.alloc();
+ auto check = [&](const char* str, bool relativelyPrime) -> void {
+ auto v = parseVector(m, str);
+ MATHICGB_ASSERT(v.size() == 2);
+ ASSERT_EQ(relativelyPrime, m.relativelyPrime(v.front(), v.back()));
+ ASSERT_EQ(relativelyPrime, m.relativelyPrime(v.back(), v.front()));
+ };
+ check("1 1", true);
+ check("1 abcdefgh", true);
+ check("abc defgh", true);
+ check("bdfh aceg", true);
+ check("bdefh aceg", false);
+ check("abcdefgh abcdefgh", false);
+ check("fgh abcdef", false);
+}
+
+TYPED_TEST(Monoid, SetExponents) {
+ typedef TypeParam Monoid;
+ Monoid m(5);
+ auto v = parseVector(m, "a1b2c3d4e5");
+ typename Monoid::Exponent exponents[] = {1, 2, 3, 4, 5};
+ v.push_back();
+ m.setExponents(exponents, v.back());
+ ASSERT_TRUE(m.equal(v.front(), v.back()));
+}
+
+TYPED_TEST(Monoid, HasAmpleCapacityTotalDegree) {
+ typedef TypeParam Monoid;
+ typedef typename Monoid::Order Order;
+ typedef typename Monoid::Exponent Exponent;
+ typedef typename Monoid::VarIndex VarIndex;
+
+ for (VarIndex varCount = 1; varCount < 33; ++varCount) {
+ Monoid monoidTotalDegree(varCount);
+
+ std::vector<Exponent> ones(varCount, 1);
+ Monoid monoidTotalDegreeImplicit
+ (Order(varCount, std::move(ones), Order::RevLexBaseOrder));
+
+ std::vector<Exponent> mostlyOnes(varCount, 1);
+ mostlyOnes[0] = 7;
+ Monoid monoidGeneral
+ (Order(varCount, std::move(mostlyOnes), Order::RevLexBaseOrder));
+
+ Monoid* monoids[] = {
+ &monoidTotalDegree,
+ &monoidTotalDegreeImplicit,
+ &monoidGeneral
+ };
+ for (int j = 0; j < 3; ++j) {
+ auto& m = *monoids[j];
+ const auto firstDeg = (j == 2 ? 7 : 1);
+ ASSERT_EQ(varCount, m.varCount());
+
+ typename Monoid::MonoPool p(m);
+ auto mono = p.alloc();
+ const auto last = m.varCount() - 1;
+ const auto max = std::numeric_limits<Exponent>::max() / 2;
+
+ // pure power, first variable
+ m.setIdentity(mono);
+ m.setExponent(0, max / firstDeg, mono);
+ ASSERT_TRUE(m.hasAmpleCapacity(mono));
+ m.setExponent(0, max / firstDeg + 1, mono);
+ ASSERT_FALSE(m.hasAmpleCapacity(mono));
+
+ if (varCount == 1)
+ continue;
+
+ // pure power, last variable
+ m.setIdentity(mono);
+ m.setExponent(last, max, mono);
+ ASSERT_TRUE(m.hasAmpleCapacity(mono));
+ m.setExponent(last, max + 1, mono);
+ ASSERT_FALSE(m.hasAmpleCapacity(mono));
+
+ // no exponent is too high but the degree is
+ m.setIdentity(mono);
+ m.setExponent(0, 12, mono);
+ m.setExponent(last, max - 12 * firstDeg, mono);
+ ASSERT_TRUE(m.hasAmpleCapacity(mono));
+ m.setExponent(0, 13, mono);
+ ASSERT_FALSE(m.hasAmpleCapacity(mono));
+ }
+ }
+}
+
+TYPED_TEST(Monoid, CopyEqualConversion) {
+ typedef TypeParam Monoid;
+ typedef typename Monoid::Order Order;
+ typedef typename Monoid::Exponent Exponent;
+ typedef typename Monoid::VarIndex VarIndex;
+ static const bool HasComponent = Monoid::HasComponent;
+ typedef MonoMonoid<Exponent, HasComponent, false, false> MonoidNone;
+ typedef MonoMonoid<Exponent, HasComponent, true, true> MonoidAll;
+ for (VarIndex varCount = 1; varCount < 33; ++varCount) {
+ const Order order
+ (varCount, std::vector<Exponent>(varCount, 1), Order::RevLexBaseOrder);
+ MonoidNone none(order);
+ Monoid some(Monoid::create(none));
+ MonoidAll all(MonoidAll::create(some));
+
+ auto none1 = none.alloc();
+ auto none2 = none.alloc();
+ auto none3 = none.alloc();
+ auto some1 = some.alloc();
+ auto some2 = some.alloc();
+ auto some3 = some.alloc();
+ auto all1 = all.alloc();
+ auto all2 = all.alloc();
+ auto all3 = all.alloc();
+
+ none.setExponent(0, 1, none1);
+ none.setExponent(varCount / 2, 2, none1);
+ none.setExponent(varCount - 1, 3, none1);
+ none.copy(none1, none2);
+ none.setExponent(0, 4, none2);
+
+ some.setExponent(0, 1, some1);
+ some.setExponent(varCount / 2, 2, some1);
+ some.setExponent(varCount - 1, 3, some1);
+ some.copy(some1, some2);
+ some.setExponent(0, 4, some2);
+
+ all.setExponent(0, 1, all1);
+ all.setExponent(varCount / 2, 2, all1);
+ all.setExponent(varCount - 1, 3, all1);
+ all.copy(all1, all2);
+ all.setExponent(0, 4, all2);
+
+ // compare on none
+ ASSERT_TRUE(none.equal(none, none1, none1));
+ ASSERT_TRUE(none.equal(some, some1, none1));
+ ASSERT_TRUE(none.equal(all, all1, none1));
+ ASSERT_FALSE(none.equal(none, none1, none2));
+ ASSERT_FALSE(none.equal(some, some1, none2));
+ ASSERT_FALSE(none.equal(all, all1, none2));
+
+ // compare on some
+ ASSERT_TRUE(some.equal(none, none1, some1));
+ ASSERT_TRUE(some.equal(some, some1, some1));
+ ASSERT_TRUE(some.equal(all, all1, some1));
+ ASSERT_FALSE(some.equal(none, none1, some2));
+ ASSERT_FALSE(some.equal(some, some1, some2));
+ ASSERT_FALSE(some.equal(all, all1, some2));
+
+ // compare on all
+ ASSERT_TRUE(all.equal(none, none1, all1));
+ ASSERT_TRUE(all.equal(some, some1, all1));
+ ASSERT_TRUE(all.equal(all, all1, all1));
+ ASSERT_FALSE(all.equal(none, none1, all2));
+ ASSERT_FALSE(all.equal(some, some1, all2));
+ ASSERT_FALSE(all.equal(all, all1, all2));
+
+ // convert some->none
+ none.copy(some, some1, none3);
+ ASSERT_TRUE(none.equal(none1, none3));
+ ASSERT_FALSE(none.equal(none2, none3));
+ none.copy(some, some2, none3);
+ ASSERT_FALSE(none.equal(none1, none3));
+ ASSERT_TRUE(none.equal(none2, none3));
+
+ /// convert some->all
+ all.copy(some, some1, all3);
+ ASSERT_TRUE(all.equal(all1, all3));
+ ASSERT_FALSE(all.equal(all2, all3));
+ all.copy(some, some2, all3);
+ ASSERT_FALSE(all.equal(all1, all3));
+ ASSERT_TRUE(all.equal(all2, all3));
+
+ // convert none->some
+ some.copy(none, none1, some3);
+ ASSERT_TRUE(some.equal(some1, some3));
+ ASSERT_FALSE(some.equal(some2, some3));
+ some.copy(none, none2, some3);
+ ASSERT_FALSE(some.equal(some1, some3));
+ ASSERT_TRUE(some.equal(some2, some3));
+
+ // convert Y->some
+ some.copy(none, none1, some3);
+ ASSERT_TRUE(some.equal(some1, some3));
+ ASSERT_FALSE(some.equal(some2, some3));
+ some.copy(none, none2, some3);
+ ASSERT_FALSE(some.equal(some1, some3));
+ ASSERT_TRUE(some.equal(some2, some3));
+ }
+}
diff --git a/src/test/PrimeField.cpp b/src/test/PrimeField.cpp
index d52418b..969876f 100755
--- a/src/test/PrimeField.cpp
+++ b/src/test/PrimeField.cpp
@@ -1,9 +1,13 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
-
#include "mathicgb/PrimeField.hpp"
+
#include <gtest/gtest.h>
#include <sstream>
+using namespace mgb;
+
namespace {
template<class T>
std::string toString(T&& t) {
diff --git a/src/test/QuadMatrixBuilder.cpp b/src/test/QuadMatrixBuilder.cpp
index 5d9affa..735a489 100755
--- a/src/test/QuadMatrixBuilder.cpp
+++ b/src/test/QuadMatrixBuilder.cpp
@@ -1,244 +1,248 @@
-#include "mathicgb/stdinc.h"
-
-#include "mathicgb/Poly.hpp"
-#include "mathicgb/PolyRing.hpp"
-#include "mathicgb/QuadMatrixBuilder.hpp"
-#include "mathicgb/io-util.hpp"
-#include "mathicgb/Basis.hpp"
-#include "mathicgb/QuadMatrix.hpp"
-#include <gtest/gtest.h>
-
-namespace {
- std::string monToStr(const PolyRing& ring, ConstMonomial a) {
- std::ostringstream out;
- ring.monomialDisplay(out, a, false, true);
- return out.str();
- }
-
- void createColumns(const char* left, const char* right, QuadMatrixBuilder& b)
- {
- const PolyRing& ring = b.ring();
- {
- Poly p(b.ring());
- std::istringstream in(left);
- p.parseDoNotOrder(in);
- size_t colCount = 0;
- for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
- QuadMatrixBuilder::LeftRightColIndex lrCol =
- b.createColumnLeft(it.getMonomial()).first;
- ASSERT_TRUE(lrCol.left());
- ASSERT_FALSE(lrCol.right());
- auto col = lrCol.leftIndex();
- ASSERT_EQ(col, lrCol.index());
- ASSERT_EQ(colCount, col);
- ++colCount;
- }
- }
- {
- Poly p(b.ring());
- std::istringstream in(right);
- p.parseDoNotOrder(in);
- size_t colCount = 0;
- for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
- QuadMatrixBuilder::LeftRightColIndex lrCol =
- b.createColumnRight(it.getMonomial()).first;
- ASSERT_TRUE(lrCol.right());
- ASSERT_FALSE(lrCol.left());
- auto col = lrCol.rightIndex();
- ASSERT_EQ(col, lrCol.index());
- ASSERT_EQ(colCount, col);
- ++colCount;
- }
- }
- }
-}
-
-TEST(QuadMatrixBuilder, Empty) {
- // test a builder with no rows and no columns
- PolyRing ring(2, PolyRing::Monoid(0));
- QuadMatrixBuilder::Map map(ring);
- QuadMatrixBuilder::MonomialsType monoLeft;
- QuadMatrixBuilder::MonomialsType monoRight;
- QuadMatrixBuilder b(ring, map, monoLeft, monoRight);
- const char* matrixStr =
- "Left columns:\n"
- "Right columns:\n"
- "matrix with no rows | matrix with no rows\n"
- " | \n"
- "matrix with no rows | matrix with no rows\n";
- auto matrix = b.buildMatrixAndClear();
- matrix.leftColumnMonomials = monoLeft;
- matrix.rightColumnMonomials = monoRight;
- ASSERT_EQ(matrixStr, matrix.toString());
-}
-
-TEST(QuadMatrixBuilder, Construction) {
- std::unique_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
- QuadMatrixBuilder::Map map(*ring);
- QuadMatrixBuilder::MonomialsType monoLeft;
- QuadMatrixBuilder::MonomialsType monoRight;
- QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
- createColumns("a<1>+<0>", "bc<0>+b<0>+c<0>", b);
-
- // top row: nothing, nothing
- b.rowDoneTopLeftAndRight();
-
- // top row: 0#1 1#2, 2#3
- b.appendEntryTopLeft(0, 1);
- b.appendEntryTopLeft(1, 2);
- b.appendEntryTopRight(2, 3);
- b.rowDoneTopLeftAndRight();
-
- // bottom row: 1#4, nothing
- b.appendEntryBottomLeft(1,4);
- b.rowDoneBottomLeftAndRight();
-
- // bottom row: nothing, 0#5
- b.appendEntryBottomRight(0,5);
- b.rowDoneBottomLeftAndRight();
-
- // bottom row: nothing, nothing
- b.rowDoneBottomLeftAndRight();
-
- const char* matrixStr =
- "Left columns: a 1\n"
- "Right columns: bc b c\n"
- "0: | 0: \n"
- "1: 0#1 1#2 | 1: 2#3\n"
- " | \n"
- "0: 1#4 | 0: \n"
- "1: | 1: 0#5\n"
- "2: | 2: \n";
- auto matrix = b.buildMatrixAndClear();
- matrix.leftColumnMonomials = monoLeft;
- matrix.rightColumnMonomials = monoRight;
- ASSERT_EQ(matrixStr, matrix.toString());
-}
-
-TEST(QuadMatrixBuilder, ColumnQuery) {
- std::unique_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
- QuadMatrixBuilder::Map map(*ring);
- QuadMatrixBuilder::MonomialsType monoLeft;
- QuadMatrixBuilder::MonomialsType monoRight;
- QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
- createColumns("a<1>+<0>", "b<0>+c<0>+bc<0>", b);
-
- Poly p(b.ring());
- // coefficient 1X=left, 2X=right, 30=not there, % 10 = column index
- std::istringstream in
- ("10a<1>+11<0>+20b<0>+21c<0>+22bc<0>+30ab<0>+30e<0>+10a<1>");
- p.parseDoNotOrder(in);
- for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
- const QuadMatrixBuilder::LeftRightColIndex* col =
- MonomialMap<QuadMatrixBuilder::LeftRightColIndex>::Reader(map).find(it.getMonomial()).first;
- if (it.getCoefficient() / 10 == 3)
- ASSERT_EQ(col, static_cast<void*>(0));
- else {
- ASSERT_TRUE(col != static_cast<void*>(0));
- ASSERT_EQ(it.getCoefficient() % 10, col->index());
- if (it.getCoefficient() / 10 == 2)
- ASSERT_TRUE(col->right());
- else
- ASSERT_TRUE(col->left());
- }
- }
-}
-
-TEST(QuadMatrixBuilder, SortColumns) {
- // construct builder and reverse lex order
- std::unique_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
- Basis basis(*ring);
-
- // one row top, no rows bottom, no columns
- {
- QuadMatrixBuilder::Map map(*ring);
- QuadMatrixBuilder::MonomialsType monoLeft;
- QuadMatrixBuilder::MonomialsType monoRight;
- QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
- b.rowDoneTopLeftAndRight();
- auto matrix = b.buildMatrixAndClear();
- matrix.sortColumnsLeftRightParallel();
- const char* matrixStr =
- "Left columns:\n"
- "Right columns:\n"
- "0: | 0: \n"
- " | \n"
- "matrix with no rows | matrix with no rows\n";
- ASSERT_EQ(matrixStr, matrix.toString());
- }
-
- {
- QuadMatrixBuilder::Map map(*ring);
- QuadMatrixBuilder::MonomialsType monoLeft;
- QuadMatrixBuilder::MonomialsType monoRight;
- QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
- createColumns("<0>+a<0>", "b<0>+bcd<0>+bc<0>", b);
- b.appendEntryTopLeft(0,1);
- b.appendEntryTopLeft(1,2);
- b.appendEntryTopRight(0,3);
- b.appendEntryTopRight(1,4);
- b.appendEntryTopRight(2,5);
- b.rowDoneTopLeftAndRight();
-
- b.appendEntryBottomLeft(0,6);
- b.appendEntryBottomLeft(1,7);
- b.appendEntryBottomRight(0,8);
- b.appendEntryBottomRight(1,9);
- b.appendEntryBottomRight(2,10);
- b.rowDoneBottomLeftAndRight();
- auto matrix = b.buildMatrixAndClear();
- matrix.leftColumnMonomials = monoLeft;
- matrix.rightColumnMonomials = monoRight;
-
- const char* matrixStr1 =
- "Left columns: 1 a\n"
- "Right columns: b bcd bc\n"
- "0: 0#1 1#2 | 0: 0#3 1#4 2#5 \n"
- " | \n"
- "0: 0#6 1#7 | 0: 0#8 1#9 2#10\n";
- ASSERT_EQ(matrixStr1, matrix.toString());
-
- const char* matrixStr2 =
- "Left columns: a 1\n"
- "Right columns: bcd bc b\n"
- "0: 1#1 0#2 | 0: 2#3 0#4 1#5 \n"
- " | \n"
- "0: 1#6 0#7 | 0: 2#8 0#9 1#10\n";
- matrix.sortColumnsLeftRightParallel();
- ASSERT_EQ(matrixStr2, matrix.toString());
-
- matrix.sortColumnsLeftRightParallel();
- ASSERT_EQ(matrixStr2, matrix.toString());
- }
-}
-
-TEST(QuadMatrixBuilder, BuildAndClear) {
- std::unique_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
- QuadMatrixBuilder::Map map(*ring);
- QuadMatrixBuilder::MonomialsType monoLeft;
- QuadMatrixBuilder::MonomialsType monoRight;
- QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
- createColumns("a<1>+<0>", "b<0>+c<0>+bc<0>", b);
-
- b.appendEntryTopLeft(1, 1);
- b.appendEntryTopRight(2, 2);
- b.rowDoneTopLeftAndRight();
-
- b.appendEntryBottomLeft(1, 3);
- b.appendEntryBottomRight(2, 4);
- b.rowDoneBottomLeftAndRight();
-
- QuadMatrix qm(b.buildMatrixAndClear());
- qm.leftColumnMonomials = monoLeft;
- qm.rightColumnMonomials = monoRight;
-
- // test that the quad matrix is right
- ASSERT_EQ("0: 1#1\n", qm.topLeft.toString());
- ASSERT_EQ("0: 2#2\n", qm.topRight.toString());
- ASSERT_EQ("0: 1#3\n", qm.bottomLeft.toString());
- ASSERT_EQ("0: 2#4\n", qm.bottomRight.toString());
- ASSERT_EQ(2, qm.leftColumnMonomials.size());
- ASSERT_EQ(3, qm.rightColumnMonomials.size());
- ASSERT_EQ("a", monToStr(*ring, qm.leftColumnMonomials[0]));
- ASSERT_EQ("b", monToStr(*ring, qm.rightColumnMonomials[0]));
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+#include "mathicgb/QuadMatrixBuilder.hpp"
+
+#include "mathicgb/Poly.hpp"
+#include "mathicgb/PolyRing.hpp"
+#include "mathicgb/io-util.hpp"
+#include "mathicgb/Basis.hpp"
+#include "mathicgb/QuadMatrix.hpp"
+#include <gtest/gtest.h>
+
+using namespace mgb;
+
+namespace {
+ ::std::string monToStr(const PolyRing& ring, ConstMonomial a) {
+ ::std::ostringstream out;
+ ring.monomialDisplay(out, a, false, true);
+ return out.str();
+ }
+
+ void createColumns(const char* left, const char* right, QuadMatrixBuilder& b)
+ {
+ const PolyRing& ring = b.ring();
+ {
+ Poly p(b.ring());
+ ::std::istringstream in(left);
+ p.parseDoNotOrder(in);
+ size_t colCount = 0;
+ for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
+ QuadMatrixBuilder::LeftRightColIndex lrCol =
+ b.createColumnLeft(it.getMonomial()).first;
+ ASSERT_TRUE(lrCol.left());
+ ASSERT_FALSE(lrCol.right());
+ auto col = lrCol.leftIndex();
+ ASSERT_EQ(col, lrCol.index());
+ ASSERT_EQ(colCount, col);
+ ++colCount;
+ }
+ }
+ {
+ Poly p(b.ring());
+ ::std::istringstream in(right);
+ p.parseDoNotOrder(in);
+ size_t colCount = 0;
+ for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
+ QuadMatrixBuilder::LeftRightColIndex lrCol =
+ b.createColumnRight(it.getMonomial()).first;
+ ASSERT_TRUE(lrCol.right());
+ ASSERT_FALSE(lrCol.left());
+ auto col = lrCol.rightIndex();
+ ASSERT_EQ(col, lrCol.index());
+ ASSERT_EQ(colCount, col);
+ ++colCount;
+ }
+ }
+ }
+}
+
+TEST(QuadMatrixBuilder, Empty) {
+ // test a builder with no rows and no columns
+ PolyRing ring(2, PolyRing::Monoid(0));
+ QuadMatrixBuilder::Map map(ring);
+ QuadMatrixBuilder::MonomialsType monoLeft;
+ QuadMatrixBuilder::MonomialsType monoRight;
+ QuadMatrixBuilder b(ring, map, monoLeft, monoRight);
+ const char* matrixStr =
+ "Left columns:\n"
+ "Right columns:\n"
+ "matrix with no rows | matrix with no rows\n"
+ " | \n"
+ "matrix with no rows | matrix with no rows\n";
+ auto matrix = b.buildMatrixAndClear();
+ matrix.leftColumnMonomials = monoLeft;
+ matrix.rightColumnMonomials = monoRight;
+ ASSERT_EQ(matrixStr, matrix.toString());
+}
+
+TEST(QuadMatrixBuilder, Construction) {
+ ::std::unique_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
+ QuadMatrixBuilder::Map map(*ring);
+ QuadMatrixBuilder::MonomialsType monoLeft;
+ QuadMatrixBuilder::MonomialsType monoRight;
+ QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
+ createColumns("a<1>+<0>", "bc<0>+b<0>+c<0>", b);
+
+ // top row: nothing, nothing
+ b.rowDoneTopLeftAndRight();
+
+ // top row: 0#1 1#2, 2#3
+ b.appendEntryTopLeft(0, 1);
+ b.appendEntryTopLeft(1, 2);
+ b.appendEntryTopRight(2, 3);
+ b.rowDoneTopLeftAndRight();
+
+ // bottom row: 1#4, nothing
+ b.appendEntryBottomLeft(1,4);
+ b.rowDoneBottomLeftAndRight();
+
+ // bottom row: nothing, 0#5
+ b.appendEntryBottomRight(0,5);
+ b.rowDoneBottomLeftAndRight();
+
+ // bottom row: nothing, nothing
+ b.rowDoneBottomLeftAndRight();
+
+ const char* matrixStr =
+ "Left columns: a 1\n"
+ "Right columns: bc b c\n"
+ "0: | 0: \n"
+ "1: 0#1 1#2 | 1: 2#3\n"
+ " | \n"
+ "0: 1#4 | 0: \n"
+ "1: | 1: 0#5\n"
+ "2: | 2: \n";
+ auto matrix = b.buildMatrixAndClear();
+ matrix.leftColumnMonomials = monoLeft;
+ matrix.rightColumnMonomials = monoRight;
+ ASSERT_EQ(matrixStr, matrix.toString());
+}
+
+TEST(QuadMatrixBuilder, ColumnQuery) {
+ ::std::unique_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
+ QuadMatrixBuilder::Map map(*ring);
+ QuadMatrixBuilder::MonomialsType monoLeft;
+ QuadMatrixBuilder::MonomialsType monoRight;
+ QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
+ createColumns("a<1>+<0>", "b<0>+c<0>+bc<0>", b);
+
+ Poly p(b.ring());
+ // coefficient 1X=left, 2X=right, 30=not there, % 10 = column index
+ ::std::istringstream in
+ ("10a<1>+11<0>+20b<0>+21c<0>+22bc<0>+30ab<0>+30e<0>+10a<1>");
+ p.parseDoNotOrder(in);
+ for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
+ const QuadMatrixBuilder::LeftRightColIndex* col =
+ MonomialMap<QuadMatrixBuilder::LeftRightColIndex>::Reader(map).find(it.getMonomial()).first;
+ if (it.getCoefficient() / 10 == 3)
+ ASSERT_EQ(col, static_cast<void*>(0));
+ else {
+ ASSERT_TRUE(col != static_cast<void*>(0));
+ ASSERT_EQ(it.getCoefficient() % 10, col->index());
+ if (it.getCoefficient() / 10 == 2)
+ ASSERT_TRUE(col->right());
+ else
+ ASSERT_TRUE(col->left());
+ }
+ }
+}
+
+TEST(QuadMatrixBuilder, SortColumns) {
+ // construct builder and reverse lex order
+ ::std::unique_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
+ Basis basis(*ring);
+
+ // one row top, no rows bottom, no columns
+ {
+ QuadMatrixBuilder::Map map(*ring);
+ QuadMatrixBuilder::MonomialsType monoLeft;
+ QuadMatrixBuilder::MonomialsType monoRight;
+ QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
+ b.rowDoneTopLeftAndRight();
+ auto matrix = b.buildMatrixAndClear();
+ matrix.sortColumnsLeftRightParallel();
+ const char* matrixStr =
+ "Left columns:\n"
+ "Right columns:\n"
+ "0: | 0: \n"
+ " | \n"
+ "matrix with no rows | matrix with no rows\n";
+ ASSERT_EQ(matrixStr, matrix.toString());
+ }
+
+ {
+ QuadMatrixBuilder::Map map(*ring);
+ QuadMatrixBuilder::MonomialsType monoLeft;
+ QuadMatrixBuilder::MonomialsType monoRight;
+ QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
+ createColumns("<0>+a<0>", "b<0>+bcd<0>+bc<0>", b);
+ b.appendEntryTopLeft(0,1);
+ b.appendEntryTopLeft(1,2);
+ b.appendEntryTopRight(0,3);
+ b.appendEntryTopRight(1,4);
+ b.appendEntryTopRight(2,5);
+ b.rowDoneTopLeftAndRight();
+
+ b.appendEntryBottomLeft(0,6);
+ b.appendEntryBottomLeft(1,7);
+ b.appendEntryBottomRight(0,8);
+ b.appendEntryBottomRight(1,9);
+ b.appendEntryBottomRight(2,10);
+ b.rowDoneBottomLeftAndRight();
+ auto matrix = b.buildMatrixAndClear();
+ matrix.leftColumnMonomials = monoLeft;
+ matrix.rightColumnMonomials = monoRight;
+
+ const char* matrixStr1 =
+ "Left columns: 1 a\n"
+ "Right columns: b bcd bc\n"
+ "0: 0#1 1#2 | 0: 0#3 1#4 2#5 \n"
+ " | \n"
+ "0: 0#6 1#7 | 0: 0#8 1#9 2#10\n";
+ ASSERT_EQ(matrixStr1, matrix.toString());
+
+ const char* matrixStr2 =
+ "Left columns: a 1\n"
+ "Right columns: bcd bc b\n"
+ "0: 1#1 0#2 | 0: 2#3 0#4 1#5 \n"
+ " | \n"
+ "0: 1#6 0#7 | 0: 2#8 0#9 1#10\n";
+ matrix.sortColumnsLeftRightParallel();
+ ASSERT_EQ(matrixStr2, matrix.toString());
+
+ matrix.sortColumnsLeftRightParallel();
+ ASSERT_EQ(matrixStr2, matrix.toString());
+ }
+}
+
+TEST(QuadMatrixBuilder, BuildAndClear) {
+ ::std::unique_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
+ QuadMatrixBuilder::Map map(*ring);
+ QuadMatrixBuilder::MonomialsType monoLeft;
+ QuadMatrixBuilder::MonomialsType monoRight;
+ QuadMatrixBuilder b(*ring, map, monoLeft, monoRight);
+ createColumns("a<1>+<0>", "b<0>+c<0>+bc<0>", b);
+
+ b.appendEntryTopLeft(1, 1);
+ b.appendEntryTopRight(2, 2);
+ b.rowDoneTopLeftAndRight();
+
+ b.appendEntryBottomLeft(1, 3);
+ b.appendEntryBottomRight(2, 4);
+ b.rowDoneBottomLeftAndRight();
+
+ QuadMatrix qm(b.buildMatrixAndClear());
+ qm.leftColumnMonomials = monoLeft;
+ qm.rightColumnMonomials = monoRight;
+
+ // test that the quad matrix is right
+ ASSERT_EQ("0: 1#1\n", qm.topLeft.toString());
+ ASSERT_EQ("0: 2#2\n", qm.topRight.toString());
+ ASSERT_EQ("0: 1#3\n", qm.bottomLeft.toString());
+ ASSERT_EQ("0: 2#4\n", qm.bottomRight.toString());
+ ASSERT_EQ(2, qm.leftColumnMonomials.size());
+ ASSERT_EQ(3, qm.rightColumnMonomials.size());
+ ASSERT_EQ("a", monToStr(*ring, qm.leftColumnMonomials[0]));
+ ASSERT_EQ("b", monToStr(*ring, qm.rightColumnMonomials[0]));
+}
diff --git a/src/test/Scanner.cpp b/src/test/Scanner.cpp
index d1dcf98..d1aefd2 100755
--- a/src/test/Scanner.cpp
+++ b/src/test/Scanner.cpp
@@ -1,120 +1,124 @@
-#include "mathicgb/stdinc.h"
-#include "mathicgb/Scanner.hpp"
-
-#include <gtest/gtest.h>
-
-namespace {
- const char* const alpha = "abcdefghijkl";
- const char* const alphaSpaced = "a bc def ghij kl";
- const char* const alphas[] = {"a", "bc", "def", "ghij", "kl"};
-}
-
-TEST(Scanner, NoOp) {
- std::istringstream in;
- Scanner sc(in);
-}
-
-TEST(Scanner, PeekAndGet) {
- std::stringstream s(alphaSpaced);
- Scanner in(s);
- for (size_t i = 0; alpha[i] != '\0'; ++i) {
- ASSERT_EQ(alphaSpaced[i], in.peek());
- ASSERT_EQ(alphaSpaced[i], in.get());
- }
-}
-
-TEST(Scanner, Match) {
- std::stringstream s(alphaSpaced);
- Scanner in(s);
- for (size_t i = 0; alpha[i] != '\0'; ++i) {
- ASSERT_FALSE(in.match('!'));
- ASSERT_FALSE(in.matchEOF());
- ASSERT_TRUE(in.match(alpha[i]));
- }
- ASSERT_TRUE(in.matchEOF());
-}
-
-TEST(Scanner, ExpectChar) {
- std::stringstream s(alphaSpaced);
- Scanner in(s);
- for (size_t i = 0; alpha[i] != '\0'; ++i)
- in.expect(alpha[i]);
- in.expectEOF();
-}
-
-TEST(Scanner, ExpectTwoChars) {
- Scanner in(alphaSpaced);
- for (size_t i = 0; alpha[i] != '\0'; ++i) {
- if (i % 2 == 0)
- in.expect('!', alpha[i]);
- else
- in.expect(alpha[i], '!');
- }
- in.expectEOF();
-}
-
-TEST(Scanner, ExpectString) {
- Scanner in{std::string(alphaSpaced)};
- const auto size = sizeof(alphas) / sizeof(*alphas);
- for (size_t i = 0; i < size; ++i) {
- if (i % 2 == 0)
- in.expect(alphas[i]);
- else
- in.expect(std::string(alphas[i]));
- }
-}
-
-TEST(Scanner, MatchString) {
- Scanner in{std::string(alphaSpaced)};
- const auto size = sizeof(alphas) / sizeof(*alphas);
- for (size_t i = 0; i < size; ++i) {
- ASSERT_FALSE(in.match("ef"));
- ASSERT_FALSE(in.match("deq"));
- ASSERT_TRUE(in.match(alphas[i]));
- }
-}
-
-TEST(Scanner, readModular) {
- PrimeField<unsigned char> f(11);
- std::stringstream s("0 1 1 +0 -0 +1 -1 15 255 -255");
- Scanner in(s);
- ASSERT_EQ(f.zero(), in.readModular(f));
- ASSERT_EQ(f.one(), in.readModular(f));
- ASSERT_EQ(f.minusOne(), in.readModular(f, true));
- ASSERT_EQ(f.zero(), in.readModular(f));
- ASSERT_EQ(f.zero(), in.readModular(f));
- ASSERT_EQ(f.one(), in.readModular(f));
- ASSERT_EQ(f.minusOne(), in.readModular(f));
- ASSERT_EQ(f.toElement(4), in.readModular(f));
- ASSERT_EQ(f.toElement(2), in.readModular(f));
- ASSERT_EQ(f.toElement(9), in.readModular(f));
-}
-
-TEST(Scanner, readInteger) {
- std::stringstream s("0 1 +0 -0 +1 -1 127 -128 128");
- Scanner in(s);
- ASSERT_EQ(0, in.readInteger<signed char>());
- ASSERT_EQ(1, in.readInteger<char>());
- ASSERT_EQ(0, in.readInteger<unsigned char>());
- ASSERT_EQ(0, in.readInteger<char>());
- ASSERT_EQ(1, in.readInteger<char>());
- ASSERT_EQ(-1, in.readInteger<char>());
- ASSERT_EQ(127, in.readInteger<char>());
- ASSERT_EQ(-128, in.readInteger<char>());
- ASSERT_EQ(-128, in.readInteger<char>(true));
-}
-
-TEST(Scanner, WhiteAndLineCount) {
- std::stringstream s(" \t\n\rx\n\n\ny");
- Scanner in(s);
- ASSERT_EQ(1, in.lineCount());
- ASSERT_TRUE(in.peek() == ' ');
- ASSERT_TRUE(in.peekWhite());
- in.eatWhite();
- ASSERT_TRUE(in.peek() == 'x');
- ASSERT_TRUE(in.match('x'));
- ASSERT_EQ(2, in.lineCount());
- ASSERT_TRUE(in.match('y'));
- in.expectEOF();
- ASSERT_EQ(5, in.lineCount());
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+#include "mathicgb/Scanner.hpp"
+
+#include <gtest/gtest.h>
+
+using namespace mgb;
+
+namespace {
+ const char* const alpha = "abcdefghijkl";
+ const char* const alphaSpaced = "a bc def ghij kl";
+ const char* const alphas[] = {"a", "bc", "def", "ghij", "kl"};
+}
+
+TEST(Scanner, NoOp) {
+ std::istringstream in;
+ Scanner sc(in);
+}
+
+TEST(Scanner, PeekAndGet) {
+ std::stringstream s(alphaSpaced);
+ Scanner in(s);
+ for (size_t i = 0; alpha[i] != '\0'; ++i) {
+ ASSERT_EQ(alphaSpaced[i], in.peek());
+ ASSERT_EQ(alphaSpaced[i], in.get());
+ }
+}
+
+TEST(Scanner, Match) {
+ std::stringstream s(alphaSpaced);
+ Scanner in(s);
+ for (size_t i = 0; alpha[i] != '\0'; ++i) {
+ ASSERT_FALSE(in.match('!'));
+ ASSERT_FALSE(in.matchEOF());
+ ASSERT_TRUE(in.match(alpha[i]));
+ }
+ ASSERT_TRUE(in.matchEOF());
+}
+
+TEST(Scanner, ExpectChar) {
+ std::stringstream s(alphaSpaced);
+ Scanner in(s);
+ for (size_t i = 0; alpha[i] != '\0'; ++i)
+ in.expect(alpha[i]);
+ in.expectEOF();
+}
+
+TEST(Scanner, ExpectTwoChars) {
+ Scanner in(alphaSpaced);
+ for (size_t i = 0; alpha[i] != '\0'; ++i) {
+ if (i % 2 == 0)
+ in.expect('!', alpha[i]);
+ else
+ in.expect(alpha[i], '!');
+ }
+ in.expectEOF();
+}
+
+TEST(Scanner, ExpectString) {
+ Scanner in{std::string(alphaSpaced)};
+ const auto size = sizeof(alphas) / sizeof(*alphas);
+ for (size_t i = 0; i < size; ++i) {
+ if (i % 2 == 0)
+ in.expect(alphas[i]);
+ else
+ in.expect(std::string(alphas[i]));
+ }
+}
+
+TEST(Scanner, MatchString) {
+ Scanner in{std::string(alphaSpaced)};
+ const auto size = sizeof(alphas) / sizeof(*alphas);
+ for (size_t i = 0; i < size; ++i) {
+ ASSERT_FALSE(in.match("ef"));
+ ASSERT_FALSE(in.match("deq"));
+ ASSERT_TRUE(in.match(alphas[i]));
+ }
+}
+
+TEST(Scanner, readModular) {
+ PrimeField<unsigned char> f(11);
+ std::stringstream s("0 1 1 +0 -0 +1 -1 15 255 -255");
+ Scanner in(s);
+ ASSERT_EQ(f.zero(), in.readModular(f));
+ ASSERT_EQ(f.one(), in.readModular(f));
+ ASSERT_EQ(f.minusOne(), in.readModular(f, true));
+ ASSERT_EQ(f.zero(), in.readModular(f));
+ ASSERT_EQ(f.zero(), in.readModular(f));
+ ASSERT_EQ(f.one(), in.readModular(f));
+ ASSERT_EQ(f.minusOne(), in.readModular(f));
+ ASSERT_EQ(f.toElement(4), in.readModular(f));
+ ASSERT_EQ(f.toElement(2), in.readModular(f));
+ ASSERT_EQ(f.toElement(9), in.readModular(f));
+}
+
+TEST(Scanner, readInteger) {
+ std::stringstream s("0 1 +0 -0 +1 -1 127 -128 128");
+ Scanner in(s);
+ ASSERT_EQ(0, in.readInteger<signed char>());
+ ASSERT_EQ(1, in.readInteger<char>());
+ ASSERT_EQ(0, in.readInteger<unsigned char>());
+ ASSERT_EQ(0, in.readInteger<char>());
+ ASSERT_EQ(1, in.readInteger<char>());
+ ASSERT_EQ(-1, in.readInteger<char>());
+ ASSERT_EQ(127, in.readInteger<char>());
+ ASSERT_EQ(-128, in.readInteger<char>());
+ ASSERT_EQ(-128, in.readInteger<char>(true));
+}
+
+TEST(Scanner, WhiteAndLineCount) {
+ std::stringstream s(" \t\n\rx\n\n\ny");
+ Scanner in(s);
+ ASSERT_EQ(1, in.lineCount());
+ ASSERT_TRUE(in.peek() == ' ');
+ ASSERT_TRUE(in.peekWhite());
+ in.eatWhite();
+ ASSERT_TRUE(in.peek() == 'x');
+ ASSERT_TRUE(in.match('x'));
+ ASSERT_EQ(2, in.lineCount());
+ ASSERT_TRUE(in.match('y'));
+ in.expectEOF();
+ ASSERT_EQ(5, in.lineCount());
+}
diff --git a/src/test/SparseMatrix.cpp b/src/test/SparseMatrix.cpp
index d140553..d07eb54 100755
--- a/src/test/SparseMatrix.cpp
+++ b/src/test/SparseMatrix.cpp
@@ -1,85 +1,90 @@
-#include "mathicgb/stdinc.h"
-
-#include "mathicgb/SparseMatrix.hpp"
-#include "mathicgb/Poly.hpp"
-#include "mathicgb/PolyRing.hpp"
-#include "mathicgb/io-util.hpp"
-#include <gtest/gtest.h>
-#include <memory>
-
-namespace {
- std::unique_ptr<Poly> parsePoly(const PolyRing& ring, std::string str) {
- auto p = make_unique<Poly>(ring);
- std::istringstream in(str);
- p->parse(in);
- return p;
- }
-}
-
-TEST(SparseMatrix, NoRows) {
- SparseMatrix mat; // test a matrix with no rows
- ASSERT_EQ(0, mat.entryCount());
- ASSERT_EQ(0, mat.rowCount());
- ASSERT_EQ(0, mat.computeColCount());
- ASSERT_EQ("matrix with no rows\n", mat.toString());
-}
-
-TEST(SparseMatrix, Simple) {
- SparseMatrix mat;
-
- mat.appendEntry(5, 101);
- mat.rowDone();
- ASSERT_EQ(1, mat.entryCount());
- ASSERT_EQ(1, mat.rowCount());
- ASSERT_EQ(6, mat.computeColCount());
- ASSERT_EQ(5, mat.leadCol(0));
- ASSERT_EQ(1, mat.entryCountInRow(0));
- ASSERT_EQ("0: 5#101\n", mat.toString());
- ASSERT_FALSE(mat.emptyRow(0));
-
- mat.rowDone(); // add a row with no entries
- ASSERT_EQ(1, mat.entryCount());
- ASSERT_EQ(2, mat.rowCount());
- ASSERT_EQ(6, mat.computeColCount());
- ASSERT_EQ(5, mat.leadCol(0));
- ASSERT_EQ(0, mat.entryCountInRow(1));
- ASSERT_EQ("0: 5#101\n1:\n", mat.toString());
- ASSERT_TRUE(mat.emptyRow(1));
-
- mat.appendEntry(5, 102);
- mat.appendEntry(2001, 0); // scalar zero
- mat.rowDone(); // add a row with two entries
- ASSERT_EQ(3, mat.entryCount());
- ASSERT_EQ(3, mat.rowCount());
- ASSERT_EQ(2002, mat.computeColCount());
- ASSERT_EQ(5, mat.leadCol(2));
- ASSERT_EQ(2, mat.entryCountInRow(2));
- ASSERT_EQ("0: 5#101\n1:\n2: 5#102 2001#0\n", mat.toString());
- ASSERT_FALSE(mat.emptyRow(2));
-}
-
-TEST(SparseMatrix, toRow) {
- auto ring = ringFromString("32003 6 1\n1 1 1 1 1 1");
- auto polyForMonomials = parsePoly(*ring, "a5+a4+a3+a2+a1+a0");
- std::vector<monomial> monomials;
- for (auto it = polyForMonomials->begin(); it != polyForMonomials->end(); ++it)
- monomials.push_back(it.getMonomial());
-
- SparseMatrix mat(5);
- mat.clear();
- mat.rowDone();
- mat.appendEntry(0,10);
- mat.rowDone();
- mat.appendEntry(2,20);
- mat.appendEntry(3,0);
- mat.appendEntry(4,40);
- mat.rowDone();
-
- Poly p(*ring);
- mat.rowToPolynomial(0, monomials, p);
- ASSERT_EQ(*parsePoly(*ring, "0"), p);
- mat.rowToPolynomial(1, monomials, p);
- ASSERT_EQ(*parsePoly(*ring, "10a5"), p);
- mat.rowToPolynomial(2, monomials, p);
- ASSERT_EQ(*parsePoly(*ring, "20a3+40a1"), p);
-}
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+#include "mathicgb/SparseMatrix.hpp"
+
+#include "mathicgb/Poly.hpp"
+#include "mathicgb/PolyRing.hpp"
+#include "mathicgb/io-util.hpp"
+#include <gtest/gtest.h>
+#include <memory>
+#include <string>
+
+using namespace mgb;
+
+namespace {
+ ::std::unique_ptr<Poly> parsePoly(const PolyRing& ring, ::std::string str) {
+ auto p = make_unique<Poly>(ring);
+ ::std::istringstream in(str);
+ p->parse(in);
+ return p;
+ }
+}
+
+TEST(SparseMatrix, NoRows) {
+ SparseMatrix mat; // test a matrix with no rows
+ ASSERT_EQ(0, mat.entryCount());
+ ASSERT_EQ(0, mat.rowCount());
+ ASSERT_EQ(0, mat.computeColCount());
+ ASSERT_EQ("matrix with no rows\n", mat.toString());
+}
+
+TEST(SparseMatrix, Simple) {
+ SparseMatrix mat;
+
+ mat.appendEntry(5, 101);
+ mat.rowDone();
+ ASSERT_EQ(1, mat.entryCount());
+ ASSERT_EQ(1, mat.rowCount());
+ ASSERT_EQ(6, mat.computeColCount());
+ ASSERT_EQ(5, mat.leadCol(0));
+ ASSERT_EQ(1, mat.entryCountInRow(0));
+ ASSERT_EQ("0: 5#101\n", mat.toString());
+ ASSERT_FALSE(mat.emptyRow(0));
+
+ mat.rowDone(); // add a row with no entries
+ ASSERT_EQ(1, mat.entryCount());
+ ASSERT_EQ(2, mat.rowCount());
+ ASSERT_EQ(6, mat.computeColCount());
+ ASSERT_EQ(5, mat.leadCol(0));
+ ASSERT_EQ(0, mat.entryCountInRow(1));
+ ASSERT_EQ("0: 5#101\n1:\n", mat.toString());
+ ASSERT_TRUE(mat.emptyRow(1));
+
+ mat.appendEntry(5, 102);
+ mat.appendEntry(2001, 0); // scalar zero
+ mat.rowDone(); // add a row with two entries
+ ASSERT_EQ(3, mat.entryCount());
+ ASSERT_EQ(3, mat.rowCount());
+ ASSERT_EQ(2002, mat.computeColCount());
+ ASSERT_EQ(5, mat.leadCol(2));
+ ASSERT_EQ(2, mat.entryCountInRow(2));
+ ASSERT_EQ("0: 5#101\n1:\n2: 5#102 2001#0\n", mat.toString());
+ ASSERT_FALSE(mat.emptyRow(2));
+}
+
+TEST(SparseMatrix, toRow) {
+ auto ring = ringFromString("32003 6 1\n1 1 1 1 1 1");
+ auto polyForMonomials = parsePoly(*ring, "a5+a4+a3+a2+a1+a0");
+ ::std::vector<monomial> monomials;
+ for (auto it = polyForMonomials->begin(); it != polyForMonomials->end(); ++it)
+ monomials.push_back(it.getMonomial());
+
+ SparseMatrix mat(5);
+ mat.clear();
+ mat.rowDone();
+ mat.appendEntry(0,10);
+ mat.rowDone();
+ mat.appendEntry(2,20);
+ mat.appendEntry(3,0);
+ mat.appendEntry(4,40);
+ mat.rowDone();
+
+ Poly p(*ring);
+ mat.rowToPolynomial(0, monomials, p);
+ ASSERT_EQ(*parsePoly(*ring, "0"), p);
+ mat.rowToPolynomial(1, monomials, p);
+ ASSERT_EQ(*parsePoly(*ring, "10a5"), p);
+ mat.rowToPolynomial(2, monomials, p);
+ ASSERT_EQ(*parsePoly(*ring, "20a3+40a1"), p);
+}
diff --git a/src/test/gb-test.cpp b/src/test/gb-test.cpp
index a43eeeb..8285b4b 100755
--- a/src/test/gb-test.cpp
+++ b/src/test/gb-test.cpp
@@ -1,5 +1,5 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
#include "mathicgb/Poly.hpp"
@@ -15,7 +15,6 @@
#include "mathicgb/MathicIO.hpp"
#include "mathicgb/Scanner.hpp"
#include "test/ideals.hpp"
-
#include <cstdio>
#include <string>
#include <iostream>
@@ -23,6 +22,8 @@
#include <memory>
#include <gtest/gtest.h>
+using namespace mgb;
+
TEST(IO, ideal) {
const char* idealA_fromStr_format =
"32003 6 \
@@ -407,8 +408,3 @@ TEST(GB, gerdt93_0_7) {
testGB(gerdt93IdealComponentFirst(false), gerdt93_gb_strat0_free7,
gerdt93_syzygies_strat0_free7, gerdt93_initial_strat0_free7, 9);
}
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/test/gtestInclude.cpp b/src/test/gtestInclude.cpp
index a14f48f..3d48078 100755
--- a/src/test/gtestInclude.cpp
+++ b/src/test/gtestInclude.cpp
@@ -1,10 +1,17 @@
-// Includes a file from gtest that pulls in all of the implementation
-// of gtest. The gtest docs recommend building gtest individually for
-// each program rather than using an installed gtest and this is as
-// easy a way of doing it as any. Especially because it guarantees that
-// the compiler flags are the same, which is the whole point of the
-// recommendation to build gtest for each program.
-
-// the .. goes back from the include/ directory of gtest so we can
-// enter the src directory.
-#include <../src/gtest-all.cc>
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+
+// Includes a file from gtest that pulls in all of the implementation
+// of gtest. The gtest docs recommend building gtest individually for
+// each program rather than using an installed gtest and this is as
+// easy a way of doing it as any. Especially because it guarantees that
+// the compiler flags are the same, which is the whole point of the
+// recommendation to build gtest for each program.
+
+namespace mgb {}
+using namespace mgb;
+
+// the .. goes back from the include/ directory of gtest so we can
+// enter the src directory.
+#include <../src/gtest-all.cc>
diff --git a/src/test/ideals.cpp b/src/test/ideals.cpp
index cb87fdd..92882e7 100755
--- a/src/test/ideals.cpp
+++ b/src/test/ideals.cpp
@@ -1,340 +1,339 @@
-#include "mathicgb/stdinc.h"
-#include "test/ideals.hpp"
-
-#include <sstream>
-
-std::string smallIdealComponentLastDescending() {
- return
- "32003 6\n"
- "1 1 1 1 1 1 1\n"
- "_revlex revcomponent\n"
- "3\n"
- "-bc+ad\n"
- "-b2+af\n"
- "-bc2+a2e\n";
-}
-
-const char* idealSmallBasis = "\
-0 <0> bc-ad\n\
-1 <1> b2-af\n\
-2 <2> bc2-a2e\n\
-3 c<0> acd-a2e\n\
-4 b<0> abd-acf\n\
-5 c2<1> a2be-ac2f\n\
-6 bc<0> a2d2-ac2f\n\
-7 c3<1> a3de-ac3f\n\
-8 c4<1> a4e2-ac4f\n\
-";
-
-const char* idealSmallSyzygies =
- " 0: b2 bc2 \n 1: c2d bc2 \n";
-
-const char* idealSmallInitial =
- " bc\n b2\n acd\n abd\n a2be\n a2d2\n a3de\n a4e2\n";
-
-std::string liuIdealComponentLastDescending() {
- return
- "2 6\n"
- "1 1 1 1 1 1 1\n"
- "_revlex revcomponent\n"
- "4\n"
- "bc+bd+af+ef\n"
- "ac+cd+bf+ef\n"
- "ad+bd+cf+ef\n"
- "ab+ac+df+ef\n";
-}
-
-const char* liu_gb_strat0_free1 =
-"\
-0 <0> bc+bd+af+ef\n\
-1 <1> ac+cd+bf+ef\n\
-2 <2> ad+bd+cf+ef\n\
-3 <3> ab+ac+df+ef\n\
-4 c<2> bd2+cd2+c2f+cef+cf2+ef2\n\
-5 b<2> b2d+cd2+d2f+bef+af2+ef2\n\
-6 b<1> c2d+cd2+b2f+c2f+cdf+bef+cef+def+af2+ef2\n\
-7 a<0> a2f+b2f+c2f+d2f+aef+bef+cef+def\n\
-8 ad<0> cd2f+d3f+cdef+d2ef+b2f2+c2f2+bdf2+aef2+def2+e2f2+bf3+ef3\n\
-9 c2<2> c3f+d3f+c2ef+bdef+cdef+d2ef+b2f2+c2f2+d2f2+aef2+bef2+e2f2+af3+bf3\n\
-10 b2<1> b3f+d3f+b2ef+d2ef+b2f2+c2f2+bef2+cef2+bf3+df3\n\
-11 c2d<2> b2ef2+d2ef2+be2f2+de2f2+b2f3+d2f3+aef3+cef3+af4+bf4+cf4+df4\n\
-12 c2d2<2> bde2f2+cde2f2+c2ef3+d2ef3+ae2f3+e3f3+c2f4+bdf4+cdf4+d2f4+aef4+def4+df5+ef5\n\
-13 c2d3<2> c2e2f3+d2e2f3+ce3f3+de3f3+c2ef4+d2ef4+be2f4+ce2f4+aef5+cef5+af6+bf6+cf6+df6\n\
-14 c2d4<2> cde2f4+d2e2f4+ae3f4+be3f4+ce3f4+e4f4+ce2f5+e3f5+cdf6+d2f6+aef6+bef6+cef6+e2f6+cf7+ef7\n\
-15 c2d5<2> d2e3f4+de4f4+ae3f5+be3f5+d2ef6+be2f6+aef7+bef7+bf8+df8\n\
-";
-
-const char* liu_syzygies_strat0_free1 =
- " 0: ac ab a2d \n 1: ab b2d b2c \n 2: bc ac ab c3d \n";
-
-const char* liu_initial_strat0_free1 =
- " ad\n bc\n ac\n ab\n a2f\n bd2\n c2d\n b2d\n cd2f\n c3f\n b3f\n b2ef2\n bde2f2\n c2e2f3\n cde2f4\n d2e3f4\n";
-
-std::string weispfennig97IdealComponentLast(bool componentsAscending) {
- std::ostringstream out;
- out << "7583 4 schreyer revlex 1\n";
- if (componentsAscending)
- out << "1 1 1 1 _revlex component\n";
- else
- out << "1 1 1 1 _revlex revcomponent\n";
- out <<
- "3\n"
- "b4+ab2c+a2d2-2abd2+b2d2+c2d2 \n"
- "a2b2c-bc4+a3d2+ab2d2+ac2d2+3d5 \n"
- "a3b2-abc3+a2d3+b2d3+c2d3\n";
- return out.str();
-}
-
-
-const char* weispfennig97_gb_strat0_free4 = "\
-0 <0> b4+ab2c+a2d2-2abd2+b2d2+c2d2\n\
-1 <1> a2b2c-bc4+a3d2+ab2d2+ac2d2+3d5\n\
-2 <2> a3b2-abc3+a2d3+b2d3+c2d3\n\
-3 c<2> a4d2+a2b2d2+a2c2d2-a2cd3-b2cd3-c3d3+3ad5\n\
-4 b2<1> b3c4+abc5-2a3bcd2-ab2c2d2-abc3d2+bc4d2-2a2bd4+a2d5-2b2d5-3acd5+c2d5-3d7\n\
-5 b2<2> ab3c3+a2bc4+2a2b3d2+2a2bc2d2-a2b2d3-2a2bcd3+ab2cd3-2b3cd3-b2c2d3-2bc3d3-2a2d5+4abd5+b2d5+c2d5\n\
-6 b3<1> ab3c2d2+ab2c3d2+a2c4d2+c6d2+2a2b2d4-a2bd5+2b3d5-2a2cd5+3abcd5-2b2cd5-bc2d5-2c3d5+3bd7\n\
-7 b2c<2> a2bc3d2-abc4d2+bc5d2+ab2c2d3-b2c3d3-bc4d3+2a3bd4-a3cd4-ab2cd4-ac3d4+3ab2d5+a2cd5-2abcd5+b2cd5+c3d5+3ad7-3cd7+3d8\n\
-8 b3<2> a3c3d2+ab2c3d2+ac5d2+a2b3d3-ab3cd3+b3c2d3-2a3d5+2a2bd5-b3d5-2ac2d5-bc2d5\n\
-9 ab2<2> a3bc4+b2c6+a3bc2d2+3ab2c3d2+a2c4d2-abc4d2+c6d2-2a3bcd3-2ab3cd3-ab2c2d3-3abc3d3+bc4d3+2a2b2d4-3a3d5+a2bd5-2a2cd5+3abcd5-2b2cd5-6bc2d5-2c3d5+a2d6+b2d6+c2d6+3bd7-3d8\n\
-10 b3c<1> a2bc4d2-ab2c4d2-a2c5d2-c7d2+2a2b3d4+2a2bc2d4-2bc4d4-a2b2d5-a2bcd5+ab2cd5-4b3cd5+2a2c2d5-3abc2d5+b2c2d5-bc3d5+2c4d5+2a3d6+2ab2d6+2ac2d6-2a2d7+4abd7+b2d7-3bcd7+c2d7+6d9\n\
-11 b2c2<2> ab2c4d2+a2c5d2-abc5d2+bc6d2+c7d2+ab2c3d3-b2c4d3-bc5d3-2a2b3d4+2a3bcd4-a3c2d4-2a2bc2d4-ab2c2d4-ac4d4+2bc4d4+a2b2d5+a2bcd5+2ab2cd5+4b3cd5-a2c2d5+abc2d5+bc3d5-c4d5-2a3d6-2ab2d6-2ac2d6+2a2d7-4abd7-b2d7+3acd7+3bcd7-4c2d7+3cd8-6d9\n\
-12 ab3<1> a3c4d2+b2c5d2+ac6d2+bc6d2-a3bcd4-ab3cd4-a3c2d4-ab2c2d4+abc3d4-ac4d4-a3bd5+2ab3d5-2a3cd5+3a2bcd5-2ab2cd5-abc2d5-2ac3d5-2a2d7+3abd7-2b2d7-3bcd7-5c2d7\n\
-13 b3c<2> a2c5d2-abc5d2+b2c5d2+2bc6d2+c7d2-b3c3d3-a2c4d3-2b2c4d3-bc5d3-c6d3-2a2b3d4+a3bcd4-ab3cd4-2a3c2d4-2a2bc2d4-2ab2c2d4+abc3d4-2ac4d4+2bc4d4-a2b2d5+3ab3d5+2a2bcd5+5b3cd5-a2c2d5+abc2d5+2bc3d5-c4d5-2a3d6+a2bd6-2ab2d6-2b3d6+2a2cd6-3abcd6+2b2cd6-2ac2d6+bc2d6+2c3d6-abd7-3b2d7+3acd7-9c2d7+3cd8-6d9\n\
-14 a2b2<1> a3bc5+b2c7+2b2c5d2-2a3bc2d3-2ab2c3d3-2b3c3d3-2abc4d3+2bc5d3+4a2b3d4-6a3bcd4-2ab3cd4+4a2bc2d4+2abc3d4-4a2b2d5+6ab3d5-3a3cd5+2a2bcd5-9ab2cd5-4b3cd5-a2c2d5+4abc2d5-2b2c2d5-7bc3d5-c4d5+a2cd6+b2cd6+c3d6-9a2d7+16abd7-3b2d7-6acd7-6bcd7-3c2d7-3ad8+6bd8-6cd8\n\
-15 ab3<2> a3bd5-ac3d5-b3d6-abcd6+2ad8\n\
-16 ab2c2<2> b2c6d2-bc7d2+abc5d3+b2c5d3-a3bc2d4+3ab2c3d4+a2c4d4+abc4d4+2b2c4d4-2bc5d4+c6d4-a2b3d5-2a3bcd5-ab3cd5-6ab2c2d5-3b3c2d5-abc3d5+2b2c3d5-2bc4d5+2a2b2d6-2ab3d6+2a3cd6+2ab2cd6-2abc2d6-4ac3d6+2a3d7-a2bd7-3ab2d7-5b3d7-7a2cd7+7abcd7-4b2cd7+2ac2d7-5bc2d7-c3d7+a2d8+b2d8-3acd8+c2d8+6ad9-3bd9+6cd9\n\
-17 a2b3<1> abc6d2+bc7d2-2b2c5d3-bc6d3-ab2c3d4+b3c3d4+a2c4d4+2abc4d4-b2c4d4+c6d4+4a2b3d5+4a3bcd5+5ab3cd5+a3c2d5+2ab2c2d5+3b3c2d5-a2c3d5-abc3d5-b2c3d5-2ac4d5+3bc4d5-c5d5+2a2b2d6-ab3d6-a2bcd6+2ab2cd6-4b3cd6-abc2d6+2ac3d6-bc3d6-2a3d7-3ab2d7+5b3d7-a2cd7+2abcd7-4b2cd7-2ac2d7-7c3d7+2a2d8-b2d8+6acd8+3bcd8+5c2d8-4ad9+6bd9-3d10\n\
-18 a2b3<2> a2b3d5+a2bc2d5+a2c3d5+ab3d6-b3cd6-bc3d6-2a2d8+3abd8\n\
-19 bc5<2> a2bc6d2-ab2c6d2+b2c7d2+2abc5d4+2b2c5d4-4bc6d4-5ab2c3d5-2b3c3d5-a2c4d5+b2c4d5+4bc5d5-c6d5-4ab3cd6+3a3c2d6+a2bc2d6+6ab2c2d6+3b3c2d6-3abc3d6+b2c3d6-4ac4d6+2bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-8ab2cd7-5b3cd7-6a2c2d7+5abc2d7-4b2c2d7-3ac3d7-bc3d7-3c4d7-3a3d8+3a2bd8-ab2d8-5b3d8+6a2cd8-11abcd8+3b2cd8-3ac2d8+3c3d8+a2d9-2abd9-b2d9+8acd9-9bcd9+11c2d9+ad10-15cd10\n\
-20 b3c3<1> a2c7d2+b2c7d2+c9d2-4ab2c3d5+2b3c3d5-3a2c4d5+4abc4d5-2b2c4d5+3bc5d5-3c6d5-2ab3cd6-a3c2d6+a2bc2d6+ab2c2d6+3b3c2d6-abc3d6+2b2c3d6-2ac4d6+3bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-2ab2cd7+b3cd7-2a2c2d7+3abc2d7-3b2c2d7-5ac3d7+2bc3d7-2c4d7-3a3d8+3a2bd8-4ab2d8-7b3d8+5a2cd8-11abcd8+2b2cd8-3ac2d8+2c3d8+a2d9-2abd9-b2d9+2acd9-3bcd9-c2d9+2ad10-9cd10-3d11\n\
-21 b3c3<2> abc7d2-2bc8d2-abc5d4+2b2c5d4-3bc6d4+2a3bc2d5-7ab2c3d5-4b3c3d5-2a2c4d5+abc4d5-2b2c4d5+3bc5d5-2c6d5-3ab3cd6+3a3c2d6-a2bc2d6+12ab2c2d6+b3c2d6+2a2c3d6-2b2c3d6+3ac4d6+6ab3d7+2a3cd7-6a2bcd7-4ab2cd7+2b3cd7-4a2c2d7+9abc2d7-2b2c2d7+ac3d7+2bc3d7+5c4d7+a2bd8+2b3d8+9a2cd8-14abcd8+9b2cd8+6bc2d8+6c3d8-2a2d9-2abd9+2b2d9+3acd9-9bcd9+8c2d9-ad10+3bd10-15cd10+3d11\n\
-22 a2b3c<1> bc8d2-bc7d3-2526abc5d4-b2c5d4+2531ab2c3d5+3b3c3d5+4b2c4d5-ac5d5-bc5d5+ab3cd6+a2bc2d6-6ab2c2d6-4b3c2d6-2528a2c3d6-2529abc3d6+2b2c3d6-2bc4d6-a2b2d7-2534ab3d7+a2bcd7+2530ab2cd7-2b3cd7+2529a2c2d7-6abc2d7+2527b2c2d7-5ac3d7-2bc3d7+2524c4d7+2a3d8-2ab2d8-7b3d8-5a2cd8+5abcd8-4b2cd8+4ac2d8-3bc2d8+c3d8+a2d9+abd9+2530b2d9-3acd9+6bcd9+2530c2d9+7ad10-12bd10+7cd10\n\
-23 a3b3<1> a2c4d5+abc4d5+b2c4d5-bc5d5+ab3cd6-ab2c2d6-b3c2d6+b2c3d6-ab3d7+a3cd7+ab2cd7-abc2d7-2ac3d7-3ab2d8-3b3d8-3a2cd8+2abcd8-b2cd8-c3d8+3ad10-3bd10+3cd10-3d11\n\
-24 abc5<2> abc8d2-2bc9d2+abc5d5-11b2c5d5-3bc6d5+12ab2c3d6+7b3c3d6-8abc4d6-11b2c4d6+2ac5d6+12bc5d6+7c6d6+12ab3cd7+8a3c2d7-9a2bc2d7+21ab2c2d7+19b3c2d7-8a2c3d7+3abc3d7-17b2c3d7+9ac4d7+16bc4d7+4c5d7+10a2b2d8-6ab3d8-14a3cd8-3a2bcd8-4ab2cd8+5b3cd8+7a2c2d8+9abc2d8+9b2c2d8+29ac3d8+bc3d8+4c4d8-4a3d9-20a2bd9+29ab2d9+63b3d9+23a2cd9-8abcd9-5ac2d9-4bc2d9-3c3d9+18a2d10-20abd10-3b2d10-11acd10+27bcd10+15c2d10-50ad11+48bd11-33cd11+3d12\n\
-25 ab3c3<2> ac6d5+bc6d5+b3c3d6-b2c4d6-a3c2d7-ab2c2d7+2a2c3d7+ac4d7+3a2b2d8+2ab3d8+3ab2cd8+2b3cd8-2ac3d8-a2d10-acd10-3c2d10+3ad11\n\
-26 a3b3c<1> abc5d5+3790bc6d5+3791c7d5-ab2c3d6-3790b2c4d6+3792bc5d6-3790a3c2d7-3790ab2c2d7-a2c3d7-abc3d7+3791ac4d7-bc4d7+3791a2b2d8+3789ab3d8-a2bcd8+3790ab2cd8+3788b3cd8-a2c2d8+3791b2c2d8+a3d9+ab2d9+ac2d9+2a2d10+3789abd10-3790b2d10+acd10+3790bcd10+6c2d10+3790bd11-3cd11+3d12\n\
-27 a2bc5<2> bc10d2+2540bc7d5+2521b2c5d6-2535bc6d6-846c7d6+2511ab2c3d7+2523b3c3d7+2509abc4d7-17b2c4d7+3ac5d7+852bc5d7-2525c6d7+3ab3cd8+2534a3c2d8-2536a2bc2d8+2570ab2c2d8+2569b3c2d8+1669a2c3d8-3371abc3d8-2554b2c3d8-3372ac4d8-1668bc4d8-3c5d8-3357a2b2d9-841ab3d9-2548a3cd9+856a2bcd9+1663ab2cd9+1675b3cd9+2518a2c2d9+2566abc2d9+845b2c2d9-2473ac3d9+2538bc3d9+1688c4d9-3392a3d10-2530a2bd10-792ab2d10+85b3d10+40a2cd10+2517abcd10+2536b2cd10-3395ac2d10+2528bc2d10-2559c3d10-1654a2d11+793abd11-855b2d11- [...]
-28 a2b3c3<1> ac7d5+bc7d5-b2c5d6+3790bc6d6+3791c7d6-ab2c3d7-2abc4d7+3791b2c4d7+2ac5d7-3789bc5d7-ab3cd8-3790a3c2d8-a2bc2d8-3784ab2c2d8+5b3c2d8-2a2c3d8-2b2c3d8+3791ac4d8+bc4d8+3791a2b2d9+3790ab3d9-2a3cd9-a2bcd9+3788ab2cd9+3791b3cd9-a2c2d9+4abc2d9+3791b2c2d9+4ac3d9+bc3d9-4a3d10+4a2bd10+4ab2d10+5b3d10+5a2cd10-4abcd10+2b2cd10-5ac2d10-bc2d10-c3d10+3a2d11+3786abd11-3788b2d11+3acd11+3790bcd11+5c2d11-6ad12-3787bd12-9cd12+3d13\n\
-29 a3b3c2<1> bc7d5-3033c8d5-b2c5d6+3033bc6d6-3034ab2c3d7+3034abc4d7+3032b2c4d7+3034ac5d7+3034bc5d7-1515ab3cd8-3035a2bc2d8+1518ab2c2d8-1513b3c2d8+3031a2c3d8+1516b2c3d8+1518bc4d8-1517c5d8-ab3d9-3034a3cd9-3034ab2cd9-3031b3cd9-3032abc2d9-3032ac3d9-3031bc3d9+3031a3d10-1515a2bd10+3033ab2d10+3035b3d10+3034a2cd10+3033abcd10-b2cd10+1514ac2d10+1517bc2d10-4c3d10+1521a2d11-1522abd11+3032b2d11-1516bcd11-3032c2d11-3036ad12-1513bd12-1519cd12+1516d13\n\
-30 a3b3c3<1> c9d5-3033c8d6-b2c5d7+3030bc6d7+2528c7d7-3032ab2c3d8+3b3c3d8+3040abc4d8+3036b2c4d8+3034ac5d8+507bc5d8-c6d8-1516ab3cd9+3a3c2d9-3035a2bc2d9+1520ab2c2d9-1512b3c2d9-2025a2c3d9+2527abc3d9+1517b2c3d9+2528ac4d9-1007bc4d9-1517c5d9+2523a2b2d10+2525ab3d10-3034a3cd10-2528a2bcd10-511ab2cd10-505b3cd10-2a2c2d10-3029abc2d10-2529b2c2d10-3043ac3d10-3028bc3d10+2526c4d10-2025a3d11-1516a2bd11-2031ab2d11+3025b3d11+3033a2cd11+3024abcd11-3542ac2d11+1514bc2d11-c3d11-1006a2d12+3533abd12-2023b2d12+25 [...]
-";
-
-const char* weispfennig97_syzygies_strat0_free4 =
- " 1: b4 a4b3 \n 2: b4 a2b2c a3b3 b3c4 a3bc5 \n";
-
-const char* weispfennig97_initial_strat0_free4 =
- " b4\n a2b2c\n a3b2\n a4d2\n b3c4\n ab3c3\n a2bc3d2\n a3c3d2\n ab3c2d2\n a3bc4\n a3bd5\n a2c5d2\n ab2c4d2\n a2b3d5\n b2c6d2\n abc6d2\n a2c4d5\n bc8d2\n ac6d5\n abc5d5\n bc7d5\n c9d5\n";
-
-const char* weispfennig97_gb_strat0_free5 = "\
-0 <0> b4+ab2c+a2d2-2abd2+b2d2+c2d2\n\
-1 <1> a2b2c-bc4+a3d2+ab2d2+ac2d2+3d5\n\
-2 <2> a3b2-abc3+a2d3+b2d3+c2d3\n\
-3 a<1> a4d2+a2b2d2+a2c2d2-a2cd3-b2cd3-c3d3+3ad5\n\
-4 a2c<0> b3c4+abc5-2a3bcd2-ab2c2d2-abc3d2+bc4d2-2a2bd4+a2d5-2b2d5-3acd5+c2d5-3d7\n\
-5 a3<0> ab3c3+a2bc4+2a2b3d2+2a2bc2d2-a2b2d3-2a2bcd3+ab2cd3-2b3cd3-b2c2d3-2bc3d3-2a2d5+4abd5+b2d5+c2d5\n\
-6 a2bc<0> ab3c2d2+ab2c3d2+a2c4d2+c6d2+2a2b2d4-a2bd5+2b3d5-2a2cd5+3abcd5-2b2cd5-bc2d5-2c3d5+3bd7\n\
-7 ab2<1> a2bc3d2-abc4d2+bc5d2+ab2c2d3-b2c3d3-bc4d3+2a3bd4-a3cd4-ab2cd4-ac3d4+3ab2d5+a2cd5-2abcd5+b2cd5+c3d5+3ad7-3cd7+3d8\n\
-8 a3b<0> a3c3d2+ab2c3d2+ac5d2+a2b3d3-ab3cd3+b3c2d3-2a3d5+2a2bd5-b3d5-2ac2d5-bc2d5\n\
-9 a4<0> a3bc4+b2c6+a3bc2d2+3ab2c3d2+a2c4d2-abc4d2+c6d2-2a3bcd3-2ab3cd3-ab2c2d3-3abc3d3+bc4d3+2a2b2d4-3a3d5+a2bd5-2a2cd5+3abcd5-2b2cd5-6bc2d5-2c3d5+a2d6+b2d6+c2d6+3bd7-3d8\n\
-10 a2bc2<0> a2bc4d2-ab2c4d2-a2c5d2-c7d2+2a2b3d4+2a2bc2d4-2bc4d4-a2b2d5-a2bcd5+ab2cd5-4b3cd5+2a2c2d5-3abc2d5+b2c2d5-bc3d5+2c4d5+2a3d6+2ab2d6+2ac2d6-2a2d7+4abd7+b2d7-3bcd7+c2d7+6d9\n\
-11 ab2c<1> ab2c4d2+a2c5d2-abc5d2+bc6d2+c7d2+ab2c3d3-b2c4d3-bc5d3-2a2b3d4+2a3bcd4-a3c2d4-2a2bc2d4-ab2c2d4-ac4d4+2bc4d4+a2b2d5+a2bcd5+2ab2cd5+4b3cd5-a2c2d5+abc2d5+bc3d5-c4d5-2a3d6-2ab2d6-2ac2d6+2a2d7-4abd7-b2d7+3acd7+3bcd7-4c2d7+3cd8-6d9\n\
-12 ab3<1> a2c5d2-abc5d2+b2c5d2+2bc6d2+c7d2-b3c3d3-a2c4d3-2b2c4d3-bc5d3-c6d3-2a2b3d4+a3bcd4-ab3cd4-2a3c2d4-2a2bc2d4-2ab2c2d4+abc3d4-2ac4d4+2bc4d4-a2b2d5+3ab3d5+2a2bcd5+5b3cd5-a2c2d5+abc2d5+2bc3d5-c4d5-2a3d6+a2bd6-2ab2d6-2b3d6+2a2cd6-3abcd6+2b2cd6-2ac2d6+bc2d6+2c3d6-abd7-3b2d7+3acd7-9c2d7+3cd8-6d9\n\
-13 a4b<0> a3bd5-ac3d5-b3d6-abcd6+2ad8\n\
-14 a2b2c<1> b2c6d2-bc7d2+abc5d3+b2c5d3-a3bc2d4+3ab2c3d4+a2c4d4+abc4d4+2b2c4d4-2bc5d4+c6d4-a2b3d5-2a3bcd5-ab3cd5-6ab2c2d5-3b3c2d5-abc3d5+2b2c3d5-2bc4d5+2a2b2d6-2ab3d6+2a3cd6+2ab2cd6-2abc2d6-4ac3d6+2a3d7-a2bd7-3ab2d7-5b3d7-7a2cd7+7abcd7-4b2cd7+2ac2d7-5bc2d7-c3d7+a2d8+b2d8-3acd8+c2d8+6ad9-3bd9+6cd9\n\
-15 a2b3<1> abc6d2+bc7d2-2b2c5d3-bc6d3-ab2c3d4+b3c3d4+a2c4d4+2abc4d4-b2c4d4+c6d4+4a2b3d5+a3bcd5+5ab3cd5+a3c2d5+2ab2c2d5+3b3c2d5-a2c3d5-abc3d5-b2c3d5+ac4d5+3bc4d5-c5d5+2a2b2d6-ab3d6-a2bcd6+2ab2cd6-b3cd6+2abc2d6+2ac3d6-bc3d6-2a3d7-3ab2d7+5b3d7-a2cd7+2abcd7-4b2cd7-2ac2d7-7c3d7+2a2d8-b2d8+3bcd8+5c2d8-4ad9+6bd9-3d10\n\
-16 a5b<0> a2b3d5+a2bc2d5+a2c3d5+ab3d6-b3cd6-bc3d6-2a2d8+3abd8\n\
-17 abc4<1> a2bc6d2-ab2c6d2+b2c7d2+2abc5d4+2b2c5d4-4bc6d4-5ab2c3d5-2b3c3d5-a2c4d5+b2c4d5+4bc5d5-c6d5-4ab3cd6+3a3c2d6+a2bc2d6+6ab2c2d6+3b3c2d6-3abc3d6+b2c3d6-4ac4d6+2bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-8ab2cd7-5b3cd7-6a2c2d7+5abc2d7-4b2c2d7-3ac3d7-bc3d7-3c4d7-3a3d8+3a2bd8-ab2d8-5b3d8+6a2cd8-11abcd8+3b2cd8-3ac2d8+3c3d8+a2d9-2abd9-b2d9+8acd9-9bcd9+11c2d9+ad10-15cd10\n\
-18 a2bc4<0> a2c7d2+b2c7d2+c9d2-4ab2c3d5+2b3c3d5-3a2c4d5+4abc4d5-2b2c4d5+3bc5d5-3c6d5-2ab3cd6-a3c2d6+a2bc2d6+ab2c2d6+3b3c2d6-abc3d6+2b2c3d6-2ac4d6+3bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-2ab2cd7+b3cd7-2a2c2d7+3abc2d7-3b2c2d7-5ac3d7+2bc3d7-2c4d7-3a3d8+3a2bd8-4ab2d8-7b3d8+5a2cd8-11abcd8+2b2cd8-3ac2d8+2c3d8+a2d9-2abd9-b2d9+2acd9-3bcd9-c2d9+2ad10-9cd10-3d11\n\
-19 ab3c2<1> abc7d2-2bc8d2-abc5d4+2b2c5d4-3bc6d4+2a3bc2d5-7ab2c3d5-4b3c3d5-2a2c4d5+abc4d5-2b2c4d5+3bc5d5-2c6d5-3ab3cd6+3a3c2d6-a2bc2d6+12ab2c2d6+b3c2d6+2a2c3d6-2b2c3d6+3ac4d6+6ab3d7+2a3cd7-6a2bcd7-4ab2cd7+2b3cd7-4a2c2d7+9abc2d7-2b2c2d7+ac3d7+2bc3d7+5c4d7+a2bd8+2b3d8+9a2cd8-14abcd8+9b2cd8+6bc2d8+6c3d8-2a2d9-2abd9+2b2d9+3acd9-9bcd9+8c2d9-ad10+3bd10-15cd10+3d11\n\
-20 a2b3c<1> bc8d2-bc7d3-2526abc5d4-b2c5d4-a3bc2d5+2531ab2c3d5+3b3c3d5+4b2c4d5-bc5d5+ab3cd6+a2bc2d6-6ab2c2d6-3b3c2d6-2528a2c3d6-2528abc3d6+2b2c3d6-2bc4d6-a2b2d7-2534ab3d7+a2bcd7+2530ab2cd7-2b3cd7+2529a2c2d7-6abc2d7+2527b2c2d7-5ac3d7-2bc3d7+2524c4d7+2a3d8-2ab2d8-7b3d8-5a2cd8+5abcd8-4b2cd8+2ac2d8-3bc2d8+c3d8+a2d9+abd9+2530b2d9-3acd9+6bcd9+2530c2d9+7ad10-12bd10+7cd10\n\
-21 a5bc<0> a2c4d5+abc4d5+b2c4d5-bc5d5+ab3cd6-ab2c2d6-b3c2d6+b2c3d6-ab3d7+a3cd7+ab2cd7-abc2d7-2ac3d7-3ab2d8-3b3d8-3a2cd8+2abcd8-b2cd8-c3d8+3ad10-3bd10+3cd10-3d11\n\
-22 a2bc4<1> abc8d2-2bc9d2+abc5d5-11b2c5d5-3bc6d5+12ab2c3d6+7b3c3d6-8abc4d6-11b2c4d6+2ac5d6+12bc5d6+7c6d6+12ab3cd7+8a3c2d7-9a2bc2d7+21ab2c2d7+19b3c2d7-8a2c3d7+3abc3d7-17b2c3d7+9ac4d7+16bc4d7+4c5d7+10a2b2d8-6ab3d8-14a3cd8-3a2bcd8-4ab2cd8+5b3cd8+7a2c2d8+9abc2d8+9b2c2d8+29ac3d8+bc3d8+4c4d8-4a3d9-20a2bd9+29ab2d9+63b3d9+23a2cd9-8abcd9-5ac2d9-4bc2d9-3c3d9+18a2d10-20abd10-3b2d10-11acd10+27bcd10+15c2d10-50ad11+48bd11-33cd11+3d12\n\
-23 a4bc3<0> ac6d5+bc6d5+b3c3d6-b2c4d6-a3c2d7-ab2c2d7+2a2c3d7+ac4d7+3a2b2d8+2ab3d8+3ab2cd8+2b3cd8-2ac3d8-a2d10-acd10-3c2d10+3ad11\n\
-24 a5bc2<0> abc5d5+3790bc6d5+3791c7d5-ab2c3d6-3790b2c4d6+3792bc5d6-3790a3c2d7-3790ab2c2d7-a2c3d7-abc3d7+3791ac4d7-bc4d7+3791a2b2d8+3789ab3d8-a2bcd8+3790ab2cd8+3788b3cd8-a2c2d8+3791b2c2d8+a3d9+ab2d9+ac2d9+2a2d10+3789abd10-3790b2d10+acd10+3790bcd10+6c2d10+3790bd11-3cd11+3d12\n\
-25 a3bc4<1> bc10d2+2540bc7d5+2521b2c5d6-2535bc6d6-846c7d6+2511ab2c3d7+2523b3c3d7+2509abc4d7-17b2c4d7+3ac5d7+852bc5d7-2525c6d7+3ab3cd8+2534a3c2d8-2536a2bc2d8+2570ab2c2d8+2569b3c2d8+1669a2c3d8-3371abc3d8-2554b2c3d8-3372ac4d8-1668bc4d8-3c5d8-3357a2b2d9-841ab3d9-2548a3cd9+856a2bcd9+1663ab2cd9+1675b3cd9+2518a2c2d9+2566abc2d9+845b2c2d9-2473ac3d9+2538bc3d9+1688c4d9-3392a3d10-2530a2bd10-792ab2d10+85b3d10+40a2cd10+2517abcd10+2536b2cd10-3395ac2d10+2528bc2d10-2559c3d10-1654a2d11+793abd11-855b2d11- [...]
-26 a5bc3<0> bc7d5-3033c8d5-b2c5d6+3033bc6d6-3034ab2c3d7+3034abc4d7+3032b2c4d7+3034ac5d7+3034bc5d7-1515ab3cd8-3035a2bc2d8+1518ab2c2d8-1513b3c2d8+3031a2c3d8+1516b2c3d8+1518bc4d8-1517c5d8-ab3d9-3034a3cd9-3034ab2cd9-3031b3cd9-3032abc2d9-3032ac3d9-3031bc3d9+3031a3d10-1515a2bd10+3033ab2d10+3035b3d10+3034a2cd10+3033abcd10-b2cd10+1514ac2d10+1517bc2d10-4c3d10+1521a2d11-1522abd11+3032b2d11-1516bcd11-3032c2d11-3036ad12-1513bd12-1519cd12+1516d13\n\
-27 a5bc4<0> c9d5-3033c8d6-b2c5d7+3030bc6d7+2528c7d7-3032ab2c3d8+3b3c3d8+3040abc4d8+3036b2c4d8+3034ac5d8+507bc5d8-c6d8-1516ab3cd9+3a3c2d9-3035a2bc2d9+1520ab2c2d9-1512b3c2d9-2025a2c3d9+2527abc3d9+1517b2c3d9+2528ac4d9-1007bc4d9-1517c5d9+2523a2b2d10+2525ab3d10-3034a3cd10-2528a2bcd10-511ab2cd10-505b3cd10-2a2c2d10-3029abc2d10-2529b2c2d10-3043ac3d10-3028bc3d10+2526c4d10-2025a3d11-1516a2bd11-2031ab2d11+3025b3d11+3033a2cd11+3024abcd11-3542ac2d11+1514bc2d11-c3d11-1006a2d12+3533abd12-2023b2d12+252 [...]
-";
-
-const char* weispfennig97_syzygies_strat0_free5 =
- " 0: a2b2c a3b2 a6b \n 1: ab4 a3b2 ab3c3 a4bc4 \n";
-
-const char* weispfennig97_initial_strat0_free5 =
- " b4\n a2b2c\n a3b2\n a4d2\n b3c4\n ab3c3\n a2bc3d2\n a3c3d2\n ab3c2d2\n a3bc4\n a3bd5\n a2c5d2\n ab2c4d2\n a2b3d5\n b2c6d2\n abc6d2\n a2c4d5\n bc8d2\n ac6d5\n abc5d5\n bc7d5\n c9d5\n";
-
-const char* Gert93RawIdeal =
- "3\n"
- "ab-b2-4bc+ae\n"
- "a2c-6bc2+a2f\n"
- "a3+b2c-a2d\n";
-
-
-std::string gerdt93IdealComponentLast(bool componentsAscending, bool schreyer) {
- std::ostringstream out;
- out << "7583 6\n";
- if (schreyer)
- out << "schreyer ";
- out << "revlex 1\n";
- if (componentsAscending)
- out << " 1 1 1 1 1 1 _revlex component\n";
- else
- out << " 1 1 1 1 1 1 _revlex revcomponent\n";
- out << Gert93RawIdeal;
- return out.str();
-}
-
-std::string gerdt93IdealComponentFirst(bool componentsAscending) {
- std::ostringstream out;
- out << "7583 6 schreyer revlex 2\n";
- if (componentsAscending)
- out << " component\n 1 1 1 1 1 1\n";
- else
- out << " revcomponent\n 1 1 1 1 1 1\n";
- out << Gert93RawIdeal;
- return out.str();
-}
-
-std::string gerdt93IdealComponentMiddle(bool componentsAscending) {
- std::ostringstream out;
- out << "7583 6 schreyer revlex 2\n";
- if (componentsAscending)
- out << "1 1 1 1 1 1\n component\n";
- else
- out << "1 1 1 1 1 1\n revcomponent\n";
- out << Gert93RawIdeal;
- return out.str();
-}
-
-const char* gerdt93_gb_strat0_free1 = "\
-0 <0> ab-b2-4bc+ae\n\
-1 <1> a2c-6bc2+a2f\n\
-2 <2> a3+b2c-a2d\n\
-3 a<1> abc2+1264b2c2-bc2d+1264b2cf\n\
-4 c2<0> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
-5 ac<0> b3c+3259bc3+1085bc2d-b2ce+1081ac2e-10bc2e+ace2+b3f+1091b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
-6 a2<1> b3c2-216b2c3-12b2c2d+36bc2d2-6ab2cf+b3cf+216b2c2f-6b2cdf-36a2bf2\n\
-7 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
-8 bc2<0> bc4-563bc3d-2577bc2d2-1896ac3e-469bc3e-2229ac2de+3088bc2de+2013ac2e2-1829bc3f-3362b2cdf-2179bc2df+3088b2cef+2353ac2ef+3515bc2ef-1075ace2f-785b3f2+2930b2cf2+2606bc2f2-348a2ef2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
-9 ac2<0> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
-10 ac3<0> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
-";
-
-const char* gerdt93_syzygies_strat0_free1 = "\
- 0: a2c a3 b2c2 abc2 \n\
- 1: a3 \n\
-";
-
-const char* gerdt93_initial_strat0_free1 =
- " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
-
-const char* gerdt93_gb_strat0_free2 = "\
-0 <0> ab-b2-4bc+ae\n\
-1 <1> a2c-6bc2+a2f\n\
-2 <2> a3+b2c-a2d\n\
-3 b<1> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
-4 c<2> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
-5 b<2> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
-6 bc<2> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
-7 ac<2> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
-8 ac2<2> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
-";
-
-const char* gerdt93_syzygies_strat0_free2 = "\
- 1: ab \n\
- 2: ab b2c a2c \n\
-";
-
-const char* gerdt93_initial_strat0_free2 =
- " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
-
-const char* gerdt93_gb_strat0_free3 = "\
-0 <0> ab-b2-4bc+ae\n\
-1 <1> a2c-6bc2+a2f\n\
-2 <2> a3+b2c-a2d\n\
-3 a<1> abc2+1264b2c2-bc2d+1264b2cf\n\
-4 c2<0> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
-5 ac<0> b3c+3259bc3+1085bc2d-b2ce+1081ac2e-10bc2e+ace2+b3f+1091b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
-6 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
-7 a2<1> b3c2-216b2c3-12b2c2d+36bc2d2-6ab2cf+b3cf+216b2c2f-6b2cdf-36a2bf2\n\
-8 bc2<0> bc4-563bc3d-2577bc2d2-1896ac3e-469bc3e-2229ac2de+3088bc2de+2013ac2e2-1829bc3f-3362b2cdf-2179bc2df+3088b2cef+2353ac2ef+3515bc2ef-1075ace2f-785b3f2+2930b2cf2+2606bc2f2-348a2ef2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
-9 ac2<0> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
-10 ac3<0> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
-";
-
-const char* gerdt93_syzygies_strat0_free3 = "\
- 0: a2c a3 b2c2 abc2 \n\
- 1: a3 \n\
-";
-
-const char* gerdt93_initial_strat0_free3 =
- " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
-
-const char* gerdt93_gb_strat0_free4 = "\
-0 <0> ab-b2-4bc+ae\n\
-1 <1> a2c-6bc2+a2f\n\
-2 <2> a3+b2c-a2d\n\
-3 b<1> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
-4 c<2> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
-5 b<2> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
-6 bc<2> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
-7 ac<2> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
-8 ac2<2> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
-";
-
-const char* gerdt93_syzygies_strat0_free4 = "\
- 1: ab \n\
- 2: ab b2c a2c \n\
-";
-
-const char* gerdt93_initial_strat0_free4 =
- " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
-
-const char* gerdt93_gb_strat0_free5 = "\
-0 <0> ab-b2-4bc+ae\n\
-1 <1> a2c-6bc2+a2f\n\
-2 <2> a3+b2c-a2d\n\
-3 ac<0> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
-4 a<1> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
-5 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
-6 ab<1> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
-7 a2<1> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
-8 a2c<1> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
-";
-
-const char* gerdt93_syzygies_strat0_free5 = "\
- 0: a2c a3 \n\
- 1: ab2 a2b a3 \n\
-";
-const char* gerdt93_initial_strat0_free5 =
- " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
-
-const char* gerdt93_gb_strat0_free6 = "0 <0> ab-b2-4bc+ae\n1 <1> a2c-6bc2+a2f\n2 <2> a3+b2c-a2d\n3 b<1> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n4 c<2> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n5 b<2> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n6 bc<2> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829b [...]
-const char* gerdt93_syzygies_strat0_free6 =
- " 1: ab \n 2: ab b2c a2c \n";
-const char* gerdt93_initial_strat0_free6 =
- " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
-
-const char* gerdt93_gb_strat0_free7 = "\
-0 <0> ab-b2-4bc+ae\n\
-1 <1> a2c-6bc2+a2f\n\
-2 <2> a3+b2c-a2d\n\
-3 a<1> abc2+1264b2c2-bc2d+1264b2cf\n\
-4 a2<1> b3c2-216b2c3-12b2c2d+36bc2d2-6ab2cf+b3cf+216b2c2f-6b2cdf-36a2bf2\n\
-5 c2<0> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
-6 ac<0> b3c+3259bc3+1085bc2d-b2ce+1081ac2e-10bc2e+ace2+b3f+1091b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
-7 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
-8 bc2<0> bc4-563bc3d-2577bc2d2-1896ac3e-469bc3e-2229ac2de+3088bc2de+2013ac2e2-1829bc3f-3362b2cdf-2179bc2df+3088b2cef+2353ac2ef+3515bc2ef-1075ace2f-785b3f2+2930b2cf2+2606bc2f2-348a2ef2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
-9 ac2<0> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
-10 ac3<0> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
-";
-
-const char* gerdt93_syzygies_strat0_free7 =
- " 0: a2c a3 b2c2 abc2 \n 1: a3 \n";
-const char* gerdt93_initial_strat0_free7 =
- " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+#include "test/ideals.hpp"
+
+#include <sstream>
+
+using namespace mgb;
+
+std::string smallIdealComponentLastDescending() {
+ return
+ "32003 6\n"
+ "1 1 1 1 1 1 1\n"
+ "_revlex revcomponent\n"
+ "3\n"
+ "-bc+ad\n"
+ "-b2+af\n"
+ "-bc2+a2e\n";
+}
+
+const char* idealSmallBasis = "\
+0 <0> bc-ad\n\
+1 <1> b2-af\n\
+2 <2> bc2-a2e\n\
+3 c<0> acd-a2e\n\
+4 b<0> abd-acf\n\
+5 c2<1> a2be-ac2f\n\
+6 bc<0> a2d2-ac2f\n\
+7 c3<1> a3de-ac3f\n\
+8 c4<1> a4e2-ac4f\n\
+";
+
+const char* idealSmallSyzygies =
+ " 0: b2 bc2 \n 1: c2d bc2 \n";
+
+const char* idealSmallInitial =
+ " bc\n b2\n acd\n abd\n a2be\n a2d2\n a3de\n a4e2\n";
+
+std::string liuIdealComponentLastDescending() {
+ return
+ "2 6\n"
+ "1 1 1 1 1 1 1\n"
+ "_revlex revcomponent\n"
+ "4\n"
+ "bc+bd+af+ef\n"
+ "ac+cd+bf+ef\n"
+ "ad+bd+cf+ef\n"
+ "ab+ac+df+ef\n";
+}
+
+const char* liu_gb_strat0_free1 =
+"\
+0 <0> bc+bd+af+ef\n\
+1 <1> ac+cd+bf+ef\n\
+2 <2> ad+bd+cf+ef\n\
+3 <3> ab+ac+df+ef\n\
+4 c<2> bd2+cd2+c2f+cef+cf2+ef2\n\
+5 b<2> b2d+cd2+d2f+bef+af2+ef2\n\
+6 b<1> c2d+cd2+b2f+c2f+cdf+bef+cef+def+af2+ef2\n\
+7 a<0> a2f+b2f+c2f+d2f+aef+bef+cef+def\n\
+8 ad<0> cd2f+d3f+cdef+d2ef+b2f2+c2f2+bdf2+aef2+def2+e2f2+bf3+ef3\n\
+9 c2<2> c3f+d3f+c2ef+bdef+cdef+d2ef+b2f2+c2f2+d2f2+aef2+bef2+e2f2+af3+bf3\n\
+10 b2<1> b3f+d3f+b2ef+d2ef+b2f2+c2f2+bef2+cef2+bf3+df3\n\
+11 c2d<2> b2ef2+d2ef2+be2f2+de2f2+b2f3+d2f3+aef3+cef3+af4+bf4+cf4+df4\n\
+12 c2d2<2> bde2f2+cde2f2+c2ef3+d2ef3+ae2f3+e3f3+c2f4+bdf4+cdf4+d2f4+aef4+def4+df5+ef5\n\
+13 c2d3<2> c2e2f3+d2e2f3+ce3f3+de3f3+c2ef4+d2ef4+be2f4+ce2f4+aef5+cef5+af6+bf6+cf6+df6\n\
+14 c2d4<2> cde2f4+d2e2f4+ae3f4+be3f4+ce3f4+e4f4+ce2f5+e3f5+cdf6+d2f6+aef6+bef6+cef6+e2f6+cf7+ef7\n\
+15 c2d5<2> d2e3f4+de4f4+ae3f5+be3f5+d2ef6+be2f6+aef7+bef7+bf8+df8\n\
+";
+
+const char* liu_syzygies_strat0_free1 =
+ " 0: ac ab a2d \n 1: ab b2d b2c \n 2: bc ac ab c3d \n";
+
+const char* liu_initial_strat0_free1 =
+ " ad\n bc\n ac\n ab\n a2f\n bd2\n c2d\n b2d\n cd2f\n c3f\n b3f\n b2ef2\n bde2f2\n c2e2f3\n cde2f4\n d2e3f4\n";
+
+std::string weispfennig97IdealComponentLast(bool componentsAscending) {
+ std::ostringstream out;
+ out << "7583 4 schreyer revlex 1\n";
+ if (componentsAscending)
+ out << "1 1 1 1 _revlex component\n";
+ else
+ out << "1 1 1 1 _revlex revcomponent\n";
+ out <<
+ "3\n"
+ "b4+ab2c+a2d2-2abd2+b2d2+c2d2 \n"
+ "a2b2c-bc4+a3d2+ab2d2+ac2d2+3d5 \n"
+ "a3b2-abc3+a2d3+b2d3+c2d3\n";
+ return out.str();
+}
+
+
+const char* weispfennig97_gb_strat0_free4 = "\
+0 <0> b4+ab2c+a2d2-2abd2+b2d2+c2d2\n\
+1 <1> a2b2c-bc4+a3d2+ab2d2+ac2d2+3d5\n\
+2 <2> a3b2-abc3+a2d3+b2d3+c2d3\n\
+3 c<2> a4d2+a2b2d2+a2c2d2-a2cd3-b2cd3-c3d3+3ad5\n\
+4 b2<1> b3c4+abc5-2a3bcd2-ab2c2d2-abc3d2+bc4d2-2a2bd4+a2d5-2b2d5-3acd5+c2d5-3d7\n\
+5 b2<2> ab3c3+a2bc4+2a2b3d2+2a2bc2d2-a2b2d3-2a2bcd3+ab2cd3-2b3cd3-b2c2d3-2bc3d3-2a2d5+4abd5+b2d5+c2d5\n\
+6 b3<1> ab3c2d2+ab2c3d2+a2c4d2+c6d2+2a2b2d4-a2bd5+2b3d5-2a2cd5+3abcd5-2b2cd5-bc2d5-2c3d5+3bd7\n\
+7 b2c<2> a2bc3d2-abc4d2+bc5d2+ab2c2d3-b2c3d3-bc4d3+2a3bd4-a3cd4-ab2cd4-ac3d4+3ab2d5+a2cd5-2abcd5+b2cd5+c3d5+3ad7-3cd7+3d8\n\
+8 b3<2> a3c3d2+ab2c3d2+ac5d2+a2b3d3-ab3cd3+b3c2d3-2a3d5+2a2bd5-b3d5-2ac2d5-bc2d5\n\
+9 ab2<2> a3bc4+b2c6+a3bc2d2+3ab2c3d2+a2c4d2-abc4d2+c6d2-2a3bcd3-2ab3cd3-ab2c2d3-3abc3d3+bc4d3+2a2b2d4-3a3d5+a2bd5-2a2cd5+3abcd5-2b2cd5-6bc2d5-2c3d5+a2d6+b2d6+c2d6+3bd7-3d8\n\
+10 b3c<1> a2bc4d2-ab2c4d2-a2c5d2-c7d2+2a2b3d4+2a2bc2d4-2bc4d4-a2b2d5-a2bcd5+ab2cd5-4b3cd5+2a2c2d5-3abc2d5+b2c2d5-bc3d5+2c4d5+2a3d6+2ab2d6+2ac2d6-2a2d7+4abd7+b2d7-3bcd7+c2d7+6d9\n\
+11 b2c2<2> ab2c4d2+a2c5d2-abc5d2+bc6d2+c7d2+ab2c3d3-b2c4d3-bc5d3-2a2b3d4+2a3bcd4-a3c2d4-2a2bc2d4-ab2c2d4-ac4d4+2bc4d4+a2b2d5+a2bcd5+2ab2cd5+4b3cd5-a2c2d5+abc2d5+bc3d5-c4d5-2a3d6-2ab2d6-2ac2d6+2a2d7-4abd7-b2d7+3acd7+3bcd7-4c2d7+3cd8-6d9\n\
+12 ab3<1> a3c4d2+b2c5d2+ac6d2+bc6d2-a3bcd4-ab3cd4-a3c2d4-ab2c2d4+abc3d4-ac4d4-a3bd5+2ab3d5-2a3cd5+3a2bcd5-2ab2cd5-abc2d5-2ac3d5-2a2d7+3abd7-2b2d7-3bcd7-5c2d7\n\
+13 b3c<2> a2c5d2-abc5d2+b2c5d2+2bc6d2+c7d2-b3c3d3-a2c4d3-2b2c4d3-bc5d3-c6d3-2a2b3d4+a3bcd4-ab3cd4-2a3c2d4-2a2bc2d4-2ab2c2d4+abc3d4-2ac4d4+2bc4d4-a2b2d5+3ab3d5+2a2bcd5+5b3cd5-a2c2d5+abc2d5+2bc3d5-c4d5-2a3d6+a2bd6-2ab2d6-2b3d6+2a2cd6-3abcd6+2b2cd6-2ac2d6+bc2d6+2c3d6-abd7-3b2d7+3acd7-9c2d7+3cd8-6d9\n\
+14 a2b2<1> a3bc5+b2c7+2b2c5d2-2a3bc2d3-2ab2c3d3-2b3c3d3-2abc4d3+2bc5d3+4a2b3d4-6a3bcd4-2ab3cd4+4a2bc2d4+2abc3d4-4a2b2d5+6ab3d5-3a3cd5+2a2bcd5-9ab2cd5-4b3cd5-a2c2d5+4abc2d5-2b2c2d5-7bc3d5-c4d5+a2cd6+b2cd6+c3d6-9a2d7+16abd7-3b2d7-6acd7-6bcd7-3c2d7-3ad8+6bd8-6cd8\n\
+15 ab3<2> a3bd5-ac3d5-b3d6-abcd6+2ad8\n\
+16 ab2c2<2> b2c6d2-bc7d2+abc5d3+b2c5d3-a3bc2d4+3ab2c3d4+a2c4d4+abc4d4+2b2c4d4-2bc5d4+c6d4-a2b3d5-2a3bcd5-ab3cd5-6ab2c2d5-3b3c2d5-abc3d5+2b2c3d5-2bc4d5+2a2b2d6-2ab3d6+2a3cd6+2ab2cd6-2abc2d6-4ac3d6+2a3d7-a2bd7-3ab2d7-5b3d7-7a2cd7+7abcd7-4b2cd7+2ac2d7-5bc2d7-c3d7+a2d8+b2d8-3acd8+c2d8+6ad9-3bd9+6cd9\n\
+17 a2b3<1> abc6d2+bc7d2-2b2c5d3-bc6d3-ab2c3d4+b3c3d4+a2c4d4+2abc4d4-b2c4d4+c6d4+4a2b3d5+4a3bcd5+5ab3cd5+a3c2d5+2ab2c2d5+3b3c2d5-a2c3d5-abc3d5-b2c3d5-2ac4d5+3bc4d5-c5d5+2a2b2d6-ab3d6-a2bcd6+2ab2cd6-4b3cd6-abc2d6+2ac3d6-bc3d6-2a3d7-3ab2d7+5b3d7-a2cd7+2abcd7-4b2cd7-2ac2d7-7c3d7+2a2d8-b2d8+6acd8+3bcd8+5c2d8-4ad9+6bd9-3d10\n\
+18 a2b3<2> a2b3d5+a2bc2d5+a2c3d5+ab3d6-b3cd6-bc3d6-2a2d8+3abd8\n\
+19 bc5<2> a2bc6d2-ab2c6d2+b2c7d2+2abc5d4+2b2c5d4-4bc6d4-5ab2c3d5-2b3c3d5-a2c4d5+b2c4d5+4bc5d5-c6d5-4ab3cd6+3a3c2d6+a2bc2d6+6ab2c2d6+3b3c2d6-3abc3d6+b2c3d6-4ac4d6+2bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-8ab2cd7-5b3cd7-6a2c2d7+5abc2d7-4b2c2d7-3ac3d7-bc3d7-3c4d7-3a3d8+3a2bd8-ab2d8-5b3d8+6a2cd8-11abcd8+3b2cd8-3ac2d8+3c3d8+a2d9-2abd9-b2d9+8acd9-9bcd9+11c2d9+ad10-15cd10\n\
+20 b3c3<1> a2c7d2+b2c7d2+c9d2-4ab2c3d5+2b3c3d5-3a2c4d5+4abc4d5-2b2c4d5+3bc5d5-3c6d5-2ab3cd6-a3c2d6+a2bc2d6+ab2c2d6+3b3c2d6-abc3d6+2b2c3d6-2ac4d6+3bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-2ab2cd7+b3cd7-2a2c2d7+3abc2d7-3b2c2d7-5ac3d7+2bc3d7-2c4d7-3a3d8+3a2bd8-4ab2d8-7b3d8+5a2cd8-11abcd8+2b2cd8-3ac2d8+2c3d8+a2d9-2abd9-b2d9+2acd9-3bcd9-c2d9+2ad10-9cd10-3d11\n\
+21 b3c3<2> abc7d2-2bc8d2-abc5d4+2b2c5d4-3bc6d4+2a3bc2d5-7ab2c3d5-4b3c3d5-2a2c4d5+abc4d5-2b2c4d5+3bc5d5-2c6d5-3ab3cd6+3a3c2d6-a2bc2d6+12ab2c2d6+b3c2d6+2a2c3d6-2b2c3d6+3ac4d6+6ab3d7+2a3cd7-6a2bcd7-4ab2cd7+2b3cd7-4a2c2d7+9abc2d7-2b2c2d7+ac3d7+2bc3d7+5c4d7+a2bd8+2b3d8+9a2cd8-14abcd8+9b2cd8+6bc2d8+6c3d8-2a2d9-2abd9+2b2d9+3acd9-9bcd9+8c2d9-ad10+3bd10-15cd10+3d11\n\
+22 a2b3c<1> bc8d2-bc7d3-2526abc5d4-b2c5d4+2531ab2c3d5+3b3c3d5+4b2c4d5-ac5d5-bc5d5+ab3cd6+a2bc2d6-6ab2c2d6-4b3c2d6-2528a2c3d6-2529abc3d6+2b2c3d6-2bc4d6-a2b2d7-2534ab3d7+a2bcd7+2530ab2cd7-2b3cd7+2529a2c2d7-6abc2d7+2527b2c2d7-5ac3d7-2bc3d7+2524c4d7+2a3d8-2ab2d8-7b3d8-5a2cd8+5abcd8-4b2cd8+4ac2d8-3bc2d8+c3d8+a2d9+abd9+2530b2d9-3acd9+6bcd9+2530c2d9+7ad10-12bd10+7cd10\n\
+23 a3b3<1> a2c4d5+abc4d5+b2c4d5-bc5d5+ab3cd6-ab2c2d6-b3c2d6+b2c3d6-ab3d7+a3cd7+ab2cd7-abc2d7-2ac3d7-3ab2d8-3b3d8-3a2cd8+2abcd8-b2cd8-c3d8+3ad10-3bd10+3cd10-3d11\n\
+24 abc5<2> abc8d2-2bc9d2+abc5d5-11b2c5d5-3bc6d5+12ab2c3d6+7b3c3d6-8abc4d6-11b2c4d6+2ac5d6+12bc5d6+7c6d6+12ab3cd7+8a3c2d7-9a2bc2d7+21ab2c2d7+19b3c2d7-8a2c3d7+3abc3d7-17b2c3d7+9ac4d7+16bc4d7+4c5d7+10a2b2d8-6ab3d8-14a3cd8-3a2bcd8-4ab2cd8+5b3cd8+7a2c2d8+9abc2d8+9b2c2d8+29ac3d8+bc3d8+4c4d8-4a3d9-20a2bd9+29ab2d9+63b3d9+23a2cd9-8abcd9-5ac2d9-4bc2d9-3c3d9+18a2d10-20abd10-3b2d10-11acd10+27bcd10+15c2d10-50ad11+48bd11-33cd11+3d12\n\
+25 ab3c3<2> ac6d5+bc6d5+b3c3d6-b2c4d6-a3c2d7-ab2c2d7+2a2c3d7+ac4d7+3a2b2d8+2ab3d8+3ab2cd8+2b3cd8-2ac3d8-a2d10-acd10-3c2d10+3ad11\n\
+26 a3b3c<1> abc5d5+3790bc6d5+3791c7d5-ab2c3d6-3790b2c4d6+3792bc5d6-3790a3c2d7-3790ab2c2d7-a2c3d7-abc3d7+3791ac4d7-bc4d7+3791a2b2d8+3789ab3d8-a2bcd8+3790ab2cd8+3788b3cd8-a2c2d8+3791b2c2d8+a3d9+ab2d9+ac2d9+2a2d10+3789abd10-3790b2d10+acd10+3790bcd10+6c2d10+3790bd11-3cd11+3d12\n\
+27 a2bc5<2> bc10d2+2540bc7d5+2521b2c5d6-2535bc6d6-846c7d6+2511ab2c3d7+2523b3c3d7+2509abc4d7-17b2c4d7+3ac5d7+852bc5d7-2525c6d7+3ab3cd8+2534a3c2d8-2536a2bc2d8+2570ab2c2d8+2569b3c2d8+1669a2c3d8-3371abc3d8-2554b2c3d8-3372ac4d8-1668bc4d8-3c5d8-3357a2b2d9-841ab3d9-2548a3cd9+856a2bcd9+1663ab2cd9+1675b3cd9+2518a2c2d9+2566abc2d9+845b2c2d9-2473ac3d9+2538bc3d9+1688c4d9-3392a3d10-2530a2bd10-792ab2d10+85b3d10+40a2cd10+2517abcd10+2536b2cd10-3395ac2d10+2528bc2d10-2559c3d10-1654a2d11+793abd11-855b2d11- [...]
+28 a2b3c3<1> ac7d5+bc7d5-b2c5d6+3790bc6d6+3791c7d6-ab2c3d7-2abc4d7+3791b2c4d7+2ac5d7-3789bc5d7-ab3cd8-3790a3c2d8-a2bc2d8-3784ab2c2d8+5b3c2d8-2a2c3d8-2b2c3d8+3791ac4d8+bc4d8+3791a2b2d9+3790ab3d9-2a3cd9-a2bcd9+3788ab2cd9+3791b3cd9-a2c2d9+4abc2d9+3791b2c2d9+4ac3d9+bc3d9-4a3d10+4a2bd10+4ab2d10+5b3d10+5a2cd10-4abcd10+2b2cd10-5ac2d10-bc2d10-c3d10+3a2d11+3786abd11-3788b2d11+3acd11+3790bcd11+5c2d11-6ad12-3787bd12-9cd12+3d13\n\
+29 a3b3c2<1> bc7d5-3033c8d5-b2c5d6+3033bc6d6-3034ab2c3d7+3034abc4d7+3032b2c4d7+3034ac5d7+3034bc5d7-1515ab3cd8-3035a2bc2d8+1518ab2c2d8-1513b3c2d8+3031a2c3d8+1516b2c3d8+1518bc4d8-1517c5d8-ab3d9-3034a3cd9-3034ab2cd9-3031b3cd9-3032abc2d9-3032ac3d9-3031bc3d9+3031a3d10-1515a2bd10+3033ab2d10+3035b3d10+3034a2cd10+3033abcd10-b2cd10+1514ac2d10+1517bc2d10-4c3d10+1521a2d11-1522abd11+3032b2d11-1516bcd11-3032c2d11-3036ad12-1513bd12-1519cd12+1516d13\n\
+30 a3b3c3<1> c9d5-3033c8d6-b2c5d7+3030bc6d7+2528c7d7-3032ab2c3d8+3b3c3d8+3040abc4d8+3036b2c4d8+3034ac5d8+507bc5d8-c6d8-1516ab3cd9+3a3c2d9-3035a2bc2d9+1520ab2c2d9-1512b3c2d9-2025a2c3d9+2527abc3d9+1517b2c3d9+2528ac4d9-1007bc4d9-1517c5d9+2523a2b2d10+2525ab3d10-3034a3cd10-2528a2bcd10-511ab2cd10-505b3cd10-2a2c2d10-3029abc2d10-2529b2c2d10-3043ac3d10-3028bc3d10+2526c4d10-2025a3d11-1516a2bd11-2031ab2d11+3025b3d11+3033a2cd11+3024abcd11-3542ac2d11+1514bc2d11-c3d11-1006a2d12+3533abd12-2023b2d12+25 [...]
+";
+
+const char* weispfennig97_syzygies_strat0_free4 =
+ " 1: b4 a4b3 \n 2: b4 a2b2c a3b3 b3c4 a3bc5 \n";
+
+const char* weispfennig97_initial_strat0_free4 =
+ " b4\n a2b2c\n a3b2\n a4d2\n b3c4\n ab3c3\n a2bc3d2\n a3c3d2\n ab3c2d2\n a3bc4\n a3bd5\n a2c5d2\n ab2c4d2\n a2b3d5\n b2c6d2\n abc6d2\n a2c4d5\n bc8d2\n ac6d5\n abc5d5\n bc7d5\n c9d5\n";
+
+const char* weispfennig97_gb_strat0_free5 = "\
+0 <0> b4+ab2c+a2d2-2abd2+b2d2+c2d2\n\
+1 <1> a2b2c-bc4+a3d2+ab2d2+ac2d2+3d5\n\
+2 <2> a3b2-abc3+a2d3+b2d3+c2d3\n\
+3 a<1> a4d2+a2b2d2+a2c2d2-a2cd3-b2cd3-c3d3+3ad5\n\
+4 a2c<0> b3c4+abc5-2a3bcd2-ab2c2d2-abc3d2+bc4d2-2a2bd4+a2d5-2b2d5-3acd5+c2d5-3d7\n\
+5 a3<0> ab3c3+a2bc4+2a2b3d2+2a2bc2d2-a2b2d3-2a2bcd3+ab2cd3-2b3cd3-b2c2d3-2bc3d3-2a2d5+4abd5+b2d5+c2d5\n\
+6 a2bc<0> ab3c2d2+ab2c3d2+a2c4d2+c6d2+2a2b2d4-a2bd5+2b3d5-2a2cd5+3abcd5-2b2cd5-bc2d5-2c3d5+3bd7\n\
+7 ab2<1> a2bc3d2-abc4d2+bc5d2+ab2c2d3-b2c3d3-bc4d3+2a3bd4-a3cd4-ab2cd4-ac3d4+3ab2d5+a2cd5-2abcd5+b2cd5+c3d5+3ad7-3cd7+3d8\n\
+8 a3b<0> a3c3d2+ab2c3d2+ac5d2+a2b3d3-ab3cd3+b3c2d3-2a3d5+2a2bd5-b3d5-2ac2d5-bc2d5\n\
+9 a4<0> a3bc4+b2c6+a3bc2d2+3ab2c3d2+a2c4d2-abc4d2+c6d2-2a3bcd3-2ab3cd3-ab2c2d3-3abc3d3+bc4d3+2a2b2d4-3a3d5+a2bd5-2a2cd5+3abcd5-2b2cd5-6bc2d5-2c3d5+a2d6+b2d6+c2d6+3bd7-3d8\n\
+10 a2bc2<0> a2bc4d2-ab2c4d2-a2c5d2-c7d2+2a2b3d4+2a2bc2d4-2bc4d4-a2b2d5-a2bcd5+ab2cd5-4b3cd5+2a2c2d5-3abc2d5+b2c2d5-bc3d5+2c4d5+2a3d6+2ab2d6+2ac2d6-2a2d7+4abd7+b2d7-3bcd7+c2d7+6d9\n\
+11 ab2c<1> ab2c4d2+a2c5d2-abc5d2+bc6d2+c7d2+ab2c3d3-b2c4d3-bc5d3-2a2b3d4+2a3bcd4-a3c2d4-2a2bc2d4-ab2c2d4-ac4d4+2bc4d4+a2b2d5+a2bcd5+2ab2cd5+4b3cd5-a2c2d5+abc2d5+bc3d5-c4d5-2a3d6-2ab2d6-2ac2d6+2a2d7-4abd7-b2d7+3acd7+3bcd7-4c2d7+3cd8-6d9\n\
+12 ab3<1> a2c5d2-abc5d2+b2c5d2+2bc6d2+c7d2-b3c3d3-a2c4d3-2b2c4d3-bc5d3-c6d3-2a2b3d4+a3bcd4-ab3cd4-2a3c2d4-2a2bc2d4-2ab2c2d4+abc3d4-2ac4d4+2bc4d4-a2b2d5+3ab3d5+2a2bcd5+5b3cd5-a2c2d5+abc2d5+2bc3d5-c4d5-2a3d6+a2bd6-2ab2d6-2b3d6+2a2cd6-3abcd6+2b2cd6-2ac2d6+bc2d6+2c3d6-abd7-3b2d7+3acd7-9c2d7+3cd8-6d9\n\
+13 a4b<0> a3bd5-ac3d5-b3d6-abcd6+2ad8\n\
+14 a2b2c<1> b2c6d2-bc7d2+abc5d3+b2c5d3-a3bc2d4+3ab2c3d4+a2c4d4+abc4d4+2b2c4d4-2bc5d4+c6d4-a2b3d5-2a3bcd5-ab3cd5-6ab2c2d5-3b3c2d5-abc3d5+2b2c3d5-2bc4d5+2a2b2d6-2ab3d6+2a3cd6+2ab2cd6-2abc2d6-4ac3d6+2a3d7-a2bd7-3ab2d7-5b3d7-7a2cd7+7abcd7-4b2cd7+2ac2d7-5bc2d7-c3d7+a2d8+b2d8-3acd8+c2d8+6ad9-3bd9+6cd9\n\
+15 a2b3<1> abc6d2+bc7d2-2b2c5d3-bc6d3-ab2c3d4+b3c3d4+a2c4d4+2abc4d4-b2c4d4+c6d4+4a2b3d5+a3bcd5+5ab3cd5+a3c2d5+2ab2c2d5+3b3c2d5-a2c3d5-abc3d5-b2c3d5+ac4d5+3bc4d5-c5d5+2a2b2d6-ab3d6-a2bcd6+2ab2cd6-b3cd6+2abc2d6+2ac3d6-bc3d6-2a3d7-3ab2d7+5b3d7-a2cd7+2abcd7-4b2cd7-2ac2d7-7c3d7+2a2d8-b2d8+3bcd8+5c2d8-4ad9+6bd9-3d10\n\
+16 a5b<0> a2b3d5+a2bc2d5+a2c3d5+ab3d6-b3cd6-bc3d6-2a2d8+3abd8\n\
+17 abc4<1> a2bc6d2-ab2c6d2+b2c7d2+2abc5d4+2b2c5d4-4bc6d4-5ab2c3d5-2b3c3d5-a2c4d5+b2c4d5+4bc5d5-c6d5-4ab3cd6+3a3c2d6+a2bc2d6+6ab2c2d6+3b3c2d6-3abc3d6+b2c3d6-4ac4d6+2bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-8ab2cd7-5b3cd7-6a2c2d7+5abc2d7-4b2c2d7-3ac3d7-bc3d7-3c4d7-3a3d8+3a2bd8-ab2d8-5b3d8+6a2cd8-11abcd8+3b2cd8-3ac2d8+3c3d8+a2d9-2abd9-b2d9+8acd9-9bcd9+11c2d9+ad10-15cd10\n\
+18 a2bc4<0> a2c7d2+b2c7d2+c9d2-4ab2c3d5+2b3c3d5-3a2c4d5+4abc4d5-2b2c4d5+3bc5d5-3c6d5-2ab3cd6-a3c2d6+a2bc2d6+ab2c2d6+3b3c2d6-abc3d6+2b2c3d6-2ac4d6+3bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-2ab2cd7+b3cd7-2a2c2d7+3abc2d7-3b2c2d7-5ac3d7+2bc3d7-2c4d7-3a3d8+3a2bd8-4ab2d8-7b3d8+5a2cd8-11abcd8+2b2cd8-3ac2d8+2c3d8+a2d9-2abd9-b2d9+2acd9-3bcd9-c2d9+2ad10-9cd10-3d11\n\
+19 ab3c2<1> abc7d2-2bc8d2-abc5d4+2b2c5d4-3bc6d4+2a3bc2d5-7ab2c3d5-4b3c3d5-2a2c4d5+abc4d5-2b2c4d5+3bc5d5-2c6d5-3ab3cd6+3a3c2d6-a2bc2d6+12ab2c2d6+b3c2d6+2a2c3d6-2b2c3d6+3ac4d6+6ab3d7+2a3cd7-6a2bcd7-4ab2cd7+2b3cd7-4a2c2d7+9abc2d7-2b2c2d7+ac3d7+2bc3d7+5c4d7+a2bd8+2b3d8+9a2cd8-14abcd8+9b2cd8+6bc2d8+6c3d8-2a2d9-2abd9+2b2d9+3acd9-9bcd9+8c2d9-ad10+3bd10-15cd10+3d11\n\
+20 a2b3c<1> bc8d2-bc7d3-2526abc5d4-b2c5d4-a3bc2d5+2531ab2c3d5+3b3c3d5+4b2c4d5-bc5d5+ab3cd6+a2bc2d6-6ab2c2d6-3b3c2d6-2528a2c3d6-2528abc3d6+2b2c3d6-2bc4d6-a2b2d7-2534ab3d7+a2bcd7+2530ab2cd7-2b3cd7+2529a2c2d7-6abc2d7+2527b2c2d7-5ac3d7-2bc3d7+2524c4d7+2a3d8-2ab2d8-7b3d8-5a2cd8+5abcd8-4b2cd8+2ac2d8-3bc2d8+c3d8+a2d9+abd9+2530b2d9-3acd9+6bcd9+2530c2d9+7ad10-12bd10+7cd10\n\
+21 a5bc<0> a2c4d5+abc4d5+b2c4d5-bc5d5+ab3cd6-ab2c2d6-b3c2d6+b2c3d6-ab3d7+a3cd7+ab2cd7-abc2d7-2ac3d7-3ab2d8-3b3d8-3a2cd8+2abcd8-b2cd8-c3d8+3ad10-3bd10+3cd10-3d11\n\
+22 a2bc4<1> abc8d2-2bc9d2+abc5d5-11b2c5d5-3bc6d5+12ab2c3d6+7b3c3d6-8abc4d6-11b2c4d6+2ac5d6+12bc5d6+7c6d6+12ab3cd7+8a3c2d7-9a2bc2d7+21ab2c2d7+19b3c2d7-8a2c3d7+3abc3d7-17b2c3d7+9ac4d7+16bc4d7+4c5d7+10a2b2d8-6ab3d8-14a3cd8-3a2bcd8-4ab2cd8+5b3cd8+7a2c2d8+9abc2d8+9b2c2d8+29ac3d8+bc3d8+4c4d8-4a3d9-20a2bd9+29ab2d9+63b3d9+23a2cd9-8abcd9-5ac2d9-4bc2d9-3c3d9+18a2d10-20abd10-3b2d10-11acd10+27bcd10+15c2d10-50ad11+48bd11-33cd11+3d12\n\
+23 a4bc3<0> ac6d5+bc6d5+b3c3d6-b2c4d6-a3c2d7-ab2c2d7+2a2c3d7+ac4d7+3a2b2d8+2ab3d8+3ab2cd8+2b3cd8-2ac3d8-a2d10-acd10-3c2d10+3ad11\n\
+24 a5bc2<0> abc5d5+3790bc6d5+3791c7d5-ab2c3d6-3790b2c4d6+3792bc5d6-3790a3c2d7-3790ab2c2d7-a2c3d7-abc3d7+3791ac4d7-bc4d7+3791a2b2d8+3789ab3d8-a2bcd8+3790ab2cd8+3788b3cd8-a2c2d8+3791b2c2d8+a3d9+ab2d9+ac2d9+2a2d10+3789abd10-3790b2d10+acd10+3790bcd10+6c2d10+3790bd11-3cd11+3d12\n\
+25 a3bc4<1> bc10d2+2540bc7d5+2521b2c5d6-2535bc6d6-846c7d6+2511ab2c3d7+2523b3c3d7+2509abc4d7-17b2c4d7+3ac5d7+852bc5d7-2525c6d7+3ab3cd8+2534a3c2d8-2536a2bc2d8+2570ab2c2d8+2569b3c2d8+1669a2c3d8-3371abc3d8-2554b2c3d8-3372ac4d8-1668bc4d8-3c5d8-3357a2b2d9-841ab3d9-2548a3cd9+856a2bcd9+1663ab2cd9+1675b3cd9+2518a2c2d9+2566abc2d9+845b2c2d9-2473ac3d9+2538bc3d9+1688c4d9-3392a3d10-2530a2bd10-792ab2d10+85b3d10+40a2cd10+2517abcd10+2536b2cd10-3395ac2d10+2528bc2d10-2559c3d10-1654a2d11+793abd11-855b2d11- [...]
+26 a5bc3<0> bc7d5-3033c8d5-b2c5d6+3033bc6d6-3034ab2c3d7+3034abc4d7+3032b2c4d7+3034ac5d7+3034bc5d7-1515ab3cd8-3035a2bc2d8+1518ab2c2d8-1513b3c2d8+3031a2c3d8+1516b2c3d8+1518bc4d8-1517c5d8-ab3d9-3034a3cd9-3034ab2cd9-3031b3cd9-3032abc2d9-3032ac3d9-3031bc3d9+3031a3d10-1515a2bd10+3033ab2d10+3035b3d10+3034a2cd10+3033abcd10-b2cd10+1514ac2d10+1517bc2d10-4c3d10+1521a2d11-1522abd11+3032b2d11-1516bcd11-3032c2d11-3036ad12-1513bd12-1519cd12+1516d13\n\
+27 a5bc4<0> c9d5-3033c8d6-b2c5d7+3030bc6d7+2528c7d7-3032ab2c3d8+3b3c3d8+3040abc4d8+3036b2c4d8+3034ac5d8+507bc5d8-c6d8-1516ab3cd9+3a3c2d9-3035a2bc2d9+1520ab2c2d9-1512b3c2d9-2025a2c3d9+2527abc3d9+1517b2c3d9+2528ac4d9-1007bc4d9-1517c5d9+2523a2b2d10+2525ab3d10-3034a3cd10-2528a2bcd10-511ab2cd10-505b3cd10-2a2c2d10-3029abc2d10-2529b2c2d10-3043ac3d10-3028bc3d10+2526c4d10-2025a3d11-1516a2bd11-2031ab2d11+3025b3d11+3033a2cd11+3024abcd11-3542ac2d11+1514bc2d11-c3d11-1006a2d12+3533abd12-2023b2d12+252 [...]
+";
+
+const char* weispfennig97_syzygies_strat0_free5 =
+ " 0: a2b2c a3b2 a6b \n 1: ab4 a3b2 ab3c3 a4bc4 \n";
+
+const char* weispfennig97_initial_strat0_free5 =
+ " b4\n a2b2c\n a3b2\n a4d2\n b3c4\n ab3c3\n a2bc3d2\n a3c3d2\n ab3c2d2\n a3bc4\n a3bd5\n a2c5d2\n ab2c4d2\n a2b3d5\n b2c6d2\n abc6d2\n a2c4d5\n bc8d2\n ac6d5\n abc5d5\n bc7d5\n c9d5\n";
+
+const char* Gert93RawIdeal =
+ "3\n"
+ "ab-b2-4bc+ae\n"
+ "a2c-6bc2+a2f\n"
+ "a3+b2c-a2d\n";
+
+
+std::string gerdt93IdealComponentLast(bool componentsAscending, bool schreyer) {
+ std::ostringstream out;
+ out << "7583 6\n";
+ if (schreyer)
+ out << "schreyer ";
+ out << "revlex 1\n";
+ if (componentsAscending)
+ out << " 1 1 1 1 1 1 _revlex component\n";
+ else
+ out << " 1 1 1 1 1 1 _revlex revcomponent\n";
+ out << Gert93RawIdeal;
+ return out.str();
+}
+
+std::string gerdt93IdealComponentFirst(bool componentsAscending) {
+ std::ostringstream out;
+ out << "7583 6 schreyer revlex 2\n";
+ if (componentsAscending)
+ out << " component\n 1 1 1 1 1 1\n";
+ else
+ out << " revcomponent\n 1 1 1 1 1 1\n";
+ out << Gert93RawIdeal;
+ return out.str();
+}
+
+std::string gerdt93IdealComponentMiddle(bool componentsAscending) {
+ std::ostringstream out;
+ out << "7583 6 schreyer revlex 2\n";
+ if (componentsAscending)
+ out << "1 1 1 1 1 1\n component\n";
+ else
+ out << "1 1 1 1 1 1\n revcomponent\n";
+ out << Gert93RawIdeal;
+ return out.str();
+}
+
+const char* gerdt93_gb_strat0_free1 = "\
+0 <0> ab-b2-4bc+ae\n\
+1 <1> a2c-6bc2+a2f\n\
+2 <2> a3+b2c-a2d\n\
+3 a<1> abc2+1264b2c2-bc2d+1264b2cf\n\
+4 c2<0> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
+5 ac<0> b3c+3259bc3+1085bc2d-b2ce+1081ac2e-10bc2e+ace2+b3f+1091b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
+6 a2<1> b3c2-216b2c3-12b2c2d+36bc2d2-6ab2cf+b3cf+216b2c2f-6b2cdf-36a2bf2\n\
+7 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
+8 bc2<0> bc4-563bc3d-2577bc2d2-1896ac3e-469bc3e-2229ac2de+3088bc2de+2013ac2e2-1829bc3f-3362b2cdf-2179bc2df+3088b2cef+2353ac2ef+3515bc2ef-1075ace2f-785b3f2+2930b2cf2+2606bc2f2-348a2ef2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
+9 ac2<0> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
+10 ac3<0> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
+";
+
+const char* gerdt93_syzygies_strat0_free1 = "\
+ 0: a2c a3 b2c2 abc2 \n\
+ 1: a3 \n\
+";
+
+const char* gerdt93_initial_strat0_free1 =
+ " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
+
+const char* gerdt93_gb_strat0_free2 = "\
+0 <0> ab-b2-4bc+ae\n\
+1 <1> a2c-6bc2+a2f\n\
+2 <2> a3+b2c-a2d\n\
+3 b<1> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
+4 c<2> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
+5 b<2> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
+6 bc<2> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
+7 ac<2> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
+8 ac2<2> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
+";
+
+const char* gerdt93_syzygies_strat0_free2 = "\
+ 1: ab \n\
+ 2: ab b2c a2c \n\
+";
+
+const char* gerdt93_initial_strat0_free2 =
+ " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
+
+const char* gerdt93_gb_strat0_free3 = "\
+0 <0> ab-b2-4bc+ae\n\
+1 <1> a2c-6bc2+a2f\n\
+2 <2> a3+b2c-a2d\n\
+3 a<1> abc2+1264b2c2-bc2d+1264b2cf\n\
+4 c2<0> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
+5 ac<0> b3c+3259bc3+1085bc2d-b2ce+1081ac2e-10bc2e+ace2+b3f+1091b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
+6 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
+7 a2<1> b3c2-216b2c3-12b2c2d+36bc2d2-6ab2cf+b3cf+216b2c2f-6b2cdf-36a2bf2\n\
+8 bc2<0> bc4-563bc3d-2577bc2d2-1896ac3e-469bc3e-2229ac2de+3088bc2de+2013ac2e2-1829bc3f-3362b2cdf-2179bc2df+3088b2cef+2353ac2ef+3515bc2ef-1075ace2f-785b3f2+2930b2cf2+2606bc2f2-348a2ef2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
+9 ac2<0> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
+10 ac3<0> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
+";
+
+const char* gerdt93_syzygies_strat0_free3 = "\
+ 0: a2c a3 b2c2 abc2 \n\
+ 1: a3 \n\
+";
+
+const char* gerdt93_initial_strat0_free3 =
+ " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
+
+const char* gerdt93_gb_strat0_free4 = "\
+0 <0> ab-b2-4bc+ae\n\
+1 <1> a2c-6bc2+a2f\n\
+2 <2> a3+b2c-a2d\n\
+3 b<1> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
+4 c<2> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
+5 b<2> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
+6 bc<2> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
+7 ac<2> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
+8 ac2<2> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
+";
+
+const char* gerdt93_syzygies_strat0_free4 = "\
+ 1: ab \n\
+ 2: ab b2c a2c \n\
+";
+
+const char* gerdt93_initial_strat0_free4 =
+ " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
+
+const char* gerdt93_gb_strat0_free5 = "\
+0 <0> ab-b2-4bc+ae\n\
+1 <1> a2c-6bc2+a2f\n\
+2 <2> a3+b2c-a2d\n\
+3 ac<0> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
+4 a<1> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
+5 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
+6 ab<1> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
+7 a2<1> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
+8 a2c<1> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
+";
+
+const char* gerdt93_syzygies_strat0_free5 = "\
+ 0: a2c a3 \n\
+ 1: ab2 a2b a3 \n\
+";
+const char* gerdt93_initial_strat0_free5 =
+ " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
+
+const char* gerdt93_gb_strat0_free6 = "0 <0> ab-b2-4bc+ae\n1 <1> a2c-6bc2+a2f\n2 <2> a3+b2c-a2d\n3 b<1> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n4 c<2> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n5 b<2> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n6 bc<2> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829b [...]
+const char* gerdt93_syzygies_strat0_free6 =
+ " 1: ab \n 2: ab b2c a2c \n";
+const char* gerdt93_initial_strat0_free6 =
+ " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
+
+const char* gerdt93_gb_strat0_free7 = "\
+0 <0> ab-b2-4bc+ae\n\
+1 <1> a2c-6bc2+a2f\n\
+2 <2> a3+b2c-a2d\n\
+3 a<1> abc2+1264b2c2-bc2d+1264b2cf\n\
+4 a2<1> b3c2-216b2c3-12b2c2d+36bc2d2-6ab2cf+b3cf+216b2c2f-6b2cdf-36a2bf2\n\
+5 c2<0> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\
+6 ac<0> b3c+3259bc3+1085bc2d-b2ce+1081ac2e-10bc2e+ace2+b3f+1091b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\
+7 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\
+8 bc2<0> bc4-563bc3d-2577bc2d2-1896ac3e-469bc3e-2229ac2de+3088bc2de+2013ac2e2-1829bc3f-3362b2cdf-2179bc2df+3088b2cef+2353ac2ef+3515bc2ef-1075ace2f-785b3f2+2930b2cf2+2606bc2f2-348a2ef2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\
+9 ac2<0> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\
+10 ac3<0> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\
+";
+
+const char* gerdt93_syzygies_strat0_free7 =
+ " 0: a2c a3 b2c2 abc2 \n 1: a3 \n";
+const char* gerdt93_initial_strat0_free7 =
+ " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n";
diff --git a/src/test/ideals.hpp b/src/test/ideals.hpp
index 4b0b709..a82c12e 100755
--- a/src/test/ideals.hpp
+++ b/src/test/ideals.hpp
@@ -1,67 +1,68 @@
-#ifndef _test_ideals_h_
-#define _test_ideals_h_
-
-// small
-std::string smallIdealComponentLastDescending();
-
-extern const char* idealSmallBasis;
-extern const char* idealSmallSyzygies;
-extern const char* idealSmallInitial;
-
-// liu
-std::string liuIdealComponentLastDescending();
-
-extern const char* liu_gb_strat0_free1;
-extern const char* liu_syzygies_strat0_free1;
-extern const char* liu_initial_strat0_free1;
-
-// weispfennig97
-std::string weispfennig97IdealComponentLast(bool componentsAscending);
-
-extern const char* weispfennig97_gb_strat0_free4;
-extern const char* weispfennig97_syzygies_strat0_free4;
-extern const char* weispfennig97_initial_strat0_free4;
-
-extern const char* weispfennig97_gb_strat0_free5;
-extern const char* weispfennig97_syzygies_strat0_free5;
-extern const char* weispfennig97_initial_strat0_free5;
-
-// gerdt93
-std::string gerdt93IdealComponentFirst(bool componentsAscending);
-std::string gerdt93IdealComponentMiddle(bool componentsAscending);
-std::string gerdt93IdealComponentLast(bool componentsAscending, bool schreyer);
-
-extern const char* gerdt93_gb_strat0_free1;
-extern const char* gerdt93_syzygies_strat0_free1;
-extern const char* gerdt93_initial_strat0_free1;
-
-extern const char* gerdt93_gb_strat0_free2;
-extern const char* gerdt93_syzygies_strat0_free2;
-extern const char* gerdt93_initial_strat0_free2;
-
-extern const char* gerdt93_gb_strat0_free3;
-extern const char* gerdt93_syzygies_strat0_free3;
-extern const char* gerdt93_initial_strat0_free3;
-
-extern const char* gerdt93_gb_strat0_free4;
-extern const char* gerdt93_syzygies_strat0_free4;
-extern const char* gerdt93_initial_strat0_free4;
-
-extern const char* gerdt93_gb_strat0_free5;
-extern const char* gerdt93_syzygies_strat0_free5;
-extern const char* gerdt93_initial_strat0_free5;
-
-extern const char* gerdt93_gb_strat0_free6;
-extern const char* gerdt93_syzygies_strat0_free6;
-extern const char* gerdt93_initial_strat0_free6;
-
-extern const char* gerdt93_gb_strat0_free7;
-extern const char* gerdt93_syzygies_strat0_free7;
-extern const char* gerdt93_initial_strat0_free7;
-
-#endif
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#ifndef MATHICGB_IDEALS_GUARD
+#define MATHICGB_IDEALS_GUARD
+
+#include <string>
+
+namespace mgb {}
+
+// small
+std::string smallIdealComponentLastDescending();
+
+extern const char* idealSmallBasis;
+extern const char* idealSmallSyzygies;
+extern const char* idealSmallInitial;
+
+// liu
+std::string liuIdealComponentLastDescending();
+
+extern const char* liu_gb_strat0_free1;
+extern const char* liu_syzygies_strat0_free1;
+extern const char* liu_initial_strat0_free1;
+
+// weispfennig97
+std::string weispfennig97IdealComponentLast(bool componentsAscending);
+
+extern const char* weispfennig97_gb_strat0_free4;
+extern const char* weispfennig97_syzygies_strat0_free4;
+extern const char* weispfennig97_initial_strat0_free4;
+
+extern const char* weispfennig97_gb_strat0_free5;
+extern const char* weispfennig97_syzygies_strat0_free5;
+extern const char* weispfennig97_initial_strat0_free5;
+
+// gerdt93
+std::string gerdt93IdealComponentFirst(bool componentsAscending);
+std::string gerdt93IdealComponentMiddle(bool componentsAscending);
+std::string gerdt93IdealComponentLast(bool componentsAscending, bool schreyer);
+
+extern const char* gerdt93_gb_strat0_free1;
+extern const char* gerdt93_syzygies_strat0_free1;
+extern const char* gerdt93_initial_strat0_free1;
+
+extern const char* gerdt93_gb_strat0_free2;
+extern const char* gerdt93_syzygies_strat0_free2;
+extern const char* gerdt93_initial_strat0_free2;
+
+extern const char* gerdt93_gb_strat0_free3;
+extern const char* gerdt93_syzygies_strat0_free3;
+extern const char* gerdt93_initial_strat0_free3;
+
+extern const char* gerdt93_gb_strat0_free4;
+extern const char* gerdt93_syzygies_strat0_free4;
+extern const char* gerdt93_initial_strat0_free4;
+
+extern const char* gerdt93_gb_strat0_free5;
+extern const char* gerdt93_syzygies_strat0_free5;
+extern const char* gerdt93_initial_strat0_free5;
+
+extern const char* gerdt93_gb_strat0_free6;
+extern const char* gerdt93_syzygies_strat0_free6;
+extern const char* gerdt93_initial_strat0_free6;
+
+extern const char* gerdt93_gb_strat0_free7;
+extern const char* gerdt93_syzygies_strat0_free7;
+extern const char* gerdt93_initial_strat0_free7;
+
+#endif
diff --git a/src/test/mathicgb.cpp b/src/test/mathicgb.cpp
index 7f5ee90..f7381ed 100755
--- a/src/test/mathicgb.cpp
+++ b/src/test/mathicgb.cpp
@@ -1,557 +1,561 @@
-#include "mathicgb/stdinc.h"
-
-#include <gtest/gtest.h>
-#include "mathicgb.h"
-
-namespace {
- template<class Stream>
- void makeBasis(Stream& s) {
- s.idealBegin();
- s.appendPolynomialBegin(); // x^2 - y
- s.appendTermBegin();
- s.appendExponent(0,2);
- s.appendTermDone(1);
- s.appendTermBegin();
- s.appendExponent(1,1);
- s.appendTermDone(s.modulus() - 1);
- s.appendPolynomialDone();
- s.appendPolynomialBegin(2); // x^3-z
- s.appendTermBegin();
- s.appendExponent(0,3);
- s.appendTermDone(1);
- s.appendTermBegin();
- s.appendExponent(2,1);
- s.appendTermDone(s.modulus() - 1);
- s.appendPolynomialDone();
- s.idealDone();
- }
-
- template<class Stream>
- void makeGroebnerBasis(Stream& s) {
- s.idealBegin(3);
- s.appendPolynomialBegin(2); // x^2 - y
- s.appendTermBegin();
- s.appendExponent(0, 2);
- s.appendExponent(1, 0);
- s.appendExponent(2, 0);
- s.appendTermDone(1);
- s.appendTermBegin();
- s.appendExponent(0, 0);
- s.appendExponent(1, 1);
- s.appendExponent(2, 0);
- s.appendTermDone(s.modulus() - 1);
- s.appendPolynomialDone();
- s.appendPolynomialBegin(2); // xy - z
- s.appendTermBegin();
- s.appendExponent(0, 1);
- s.appendExponent(1, 1);
- s.appendExponent(2, 0);
- s.appendTermDone(1);
- s.appendTermBegin();
- s.appendExponent(0, 0);
- s.appendExponent(1, 0);
- s.appendExponent(2, 1);
- s.appendTermDone(s.modulus() - 1);
- s.appendPolynomialDone();
- s.appendPolynomialBegin(2); // y^2 - xy
- s.appendTermBegin();
- s.appendExponent(0, 0);
- s.appendExponent(1, 2);
- s.appendExponent(2, 0);
- s.appendTermDone(1);
- s.appendTermBegin();
- s.appendExponent(0, 1);
- s.appendExponent(1, 0);
- s.appendExponent(2, 1);
- s.appendTermDone(s.modulus() - 1);
- s.appendPolynomialDone();
- s.idealDone();
- }
-
- template<class Stream>
- void makeCyclic5Basis(Stream& s) {
- s.idealBegin(5); // polyCount
- s.appendPolynomialBegin(5);
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(1, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(2, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(3, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendPolynomialDone();
- s.appendPolynomialBegin(5);
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(1, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(3, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendPolynomialDone();
- s.appendPolynomialBegin(5);
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendPolynomialDone();
- s.appendPolynomialBegin(5);
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendPolynomialDone();
- s.appendPolynomialBegin(2);
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendExponent(4, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendTermDone(100); // coefficient
- s.appendPolynomialDone();
- s.idealDone();
- }
-
- template<class Stream>
- void makeSimpleIdeal(Stream& s) { // variables a,b,c,d. a2-bc, ab-cd.
- s.idealBegin();
- s.appendPolynomialBegin(); // a^2-b*c
- s.appendTermBegin();
- s.appendExponent(0,2);
- s.appendTermDone(1);
- s.appendTermBegin();
- s.appendExponent(1,1);
- s.appendExponent(2,1);
- s.appendTermDone(s.modulus() - 1);
- s.appendPolynomialDone();
- s.appendPolynomialBegin(2); // a*b-c*d
- s.appendTermBegin();
- s.appendExponent(0,1);
- s.appendExponent(1,1);
- s.appendTermDone(1);
- s.appendTermBegin();
- s.appendExponent(2,1);
- s.appendExponent(3,1);
- s.appendTermDone(s.modulus() - 1);
- s.appendPolynomialDone();
- s.idealDone();
- }
-
- template<class Stream>
- void makeSimpleIdealGroebnerBasis(Stream& s) { // variables a,b,c,d. a2-bc, ab-cd.
- // Groebner basis is {a^2-b*c,a*b-c*d,a*c*d-b^2*c,b^3*c-c^2*d^2}
- // (order: eliminate 1 variable: [1 0 0 0; 1 1 1 1]).
- s.idealBegin(4); // polyCount
- s.appendPolynomialBegin(2);
- s.appendTermBegin();
- s.appendExponent(0, 2); // index, exponent
- s.appendExponent(1, 0); // index, exponent
- s.appendExponent(2, 0); // index, exponent
- s.appendExponent(3, 0); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 0); // index, exponent
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 0); // index, exponent
- s.appendTermDone(100); // coefficient
- s.appendPolynomialDone();
- s.appendPolynomialBegin(2);
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(1, 1); // index, exponent
- s.appendExponent(2, 0); // index, exponent
- s.appendExponent(3, 0); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 0); // index, exponent
- s.appendExponent(1, 0); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendTermDone(100); // coefficient
- s.appendPolynomialDone();
- s.appendPolynomialBegin(2);
- s.appendTermBegin();
- s.appendExponent(0, 1); // index, exponent
- s.appendExponent(1, 0); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 1); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 0); // index, exponent
- s.appendExponent(1, 2); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 0); // index, exponent
- s.appendTermDone(100); // coefficient
- s.appendPolynomialDone();
- s.appendPolynomialBegin(2);
- s.appendTermBegin();
- s.appendExponent(0, 0); // index, exponent
- s.appendExponent(1, 3); // index, exponent
- s.appendExponent(2, 1); // index, exponent
- s.appendExponent(3, 0); // index, exponent
- s.appendTermDone(1); // coefficient
- s.appendTermBegin();
- s.appendExponent(0, 0); // index, exponent
- s.appendExponent(1, 0); // index, exponent
- s.appendExponent(2, 2); // index, exponent
- s.appendExponent(3, 2); // index, exponent
- s.appendTermDone(100); // coefficient
- s.appendPolynomialDone();
- s.idealDone();
- }
-}
-
-TEST(MathicGBLib, NullIdealStream) {
- {
- mgb::NullIdealStream stream(2, 3);
- ASSERT_EQ(2, stream.modulus());
- ASSERT_EQ(3, stream.varCount());
- makeBasis(stream);
- }
-
- {
- mgb::NullIdealStream stream(101, 0);
- ASSERT_EQ(101, stream.modulus());
- ASSERT_EQ(0, stream.varCount());
- }
-}
-
-TEST(MathicGBLib, IdealStreamLog) {
- {
- const char* const idealStr =
- "s.idealBegin();\n"
- "s.appendPolynomialBegin();\n"
- "s.appendTermBegin();\n"
- "s.appendExponent(0, 2); // index, exponent\n"
- "s.appendTermDone(1); // coefficient\n"
- "s.appendTermBegin();\n"
- "s.appendExponent(1, 1); // index, exponent\n"
- "s.appendTermDone(6); // coefficient\n"
- "s.appendPolynomialDone();\n"
- "s.appendPolynomialBegin(2);\n"
- "s.appendTermBegin();\n"
- "s.appendExponent(0, 3); // index, exponent\n"
- "s.appendTermDone(1); // coefficient\n"
- "s.appendTermBegin();\n"
- "s.appendExponent(2, 1); // index, exponent\n"
- "s.appendTermDone(6); // coefficient\n"
- "s.appendPolynomialDone();\n"
- "s.idealDone();\n";
-
- std::ostringstream out1;
- mgb::IdealStreamLog<> stream1(out1, 7, 3);
-
- mgb::IdealStreamChecker<decltype(stream1)> checker(stream1);
-
- std::ostringstream out2;
- mgb::IdealStreamLog<decltype(checker)> stream2(out2, checker);
-
- std::ostringstream out3;
- mgb::IdealStreamLog<decltype(stream2)> stream3(out3, stream2);
-
- ASSERT_EQ(7, stream1.modulus());
- ASSERT_EQ(3, stream1.varCount());
- ASSERT_EQ(7, checker.modulus());
- ASSERT_EQ(3, checker.varCount());
- ASSERT_EQ(7, stream2.modulus());
- ASSERT_EQ(3, stream2.varCount());
- ASSERT_EQ(7, stream3.modulus());
- ASSERT_EQ(3, stream3.varCount());
-
- makeBasis(stream3);
- const auto str1 = std::string(
- "IdealStreamLog s(stream, 7, 3);\n"
- ) + idealStr;
- ASSERT_EQ(str1, out1.str())
- << "Displayed expected:\n" << out1.str()
- << "Displayed actual:\n" << str1 << std::endl;
-
- const auto str2 = std::string(
- "IdealStreamLog s(stream, log); // modulus=7, varCount=3\n"
- ) + idealStr;
- ASSERT_EQ(str2, out2.str()) << "Displayed expected:\n" << out2.str();
- ASSERT_EQ(str2, out3.str()) << "Displayed expected:\n" << out3.str();
- }
-
- // The ideal <> in no variables
- {
- std::ostringstream out;
- mgb::IdealStreamLog<> stream(out, 101, 0);
- ASSERT_EQ(101, stream.modulus());
- ASSERT_EQ(0, stream.varCount());
- stream.idealBegin(0);
- stream.idealDone();
- }
-
- // The ideal <1, 0> in no variables
- {
- std::ostringstream out;
- mgb::IdealStreamLog<> stream(out, 101, 0);
- ASSERT_EQ(101, stream.modulus());
- ASSERT_EQ(0, stream.varCount());
- stream.idealBegin(2);
- stream.appendPolynomialBegin(0); // 1
- stream.appendTermBegin();
- stream.appendTermDone(1);
- stream.appendPolynomialDone();
- stream.appendPolynomialBegin(0); // 0
- stream.appendPolynomialDone();
- stream.idealDone();
- }
-}
-
-TEST(MathicGBLib, ZeroIdealGB) {
- mgb::GroebnerConfiguration configuration(2, 0);
- mgb::GroebnerInputIdealStream input(configuration);
- std::ostringstream out;
- mgb::IdealStreamLog<> logStream(out, 2, 0);
-
- input.idealBegin(0);
- input.idealDone();
- mgb::computeGroebnerBasis(input, logStream);
-
- const auto msg =
- "IdealStreamLog s(stream, 2, 0);\n"
- "s.idealBegin(0); // polyCount\n"
- "s.idealDone();\n";
- EXPECT_EQ(msg, out.str());
-}
-
-TEST(MathicGBLib, OneIdealGB) {
- mgb::GroebnerConfiguration configuration(2, 0);
- mgb::GroebnerInputIdealStream input(configuration);
- std::ostringstream out;
- mgb::IdealStreamLog<> logStream(out, 2, 0);
-
- input.idealBegin(1);
- input.appendPolynomialBegin(1);
- input.appendTermBegin();
- input.appendTermDone(1);
- input.appendPolynomialDone();
- input.idealDone();
- mgb::computeGroebnerBasis(input, logStream);
-
- const auto msg =
- "IdealStreamLog s(stream, 2, 0);\n"
- "s.idealBegin(1); // polyCount\n"
- "s.appendPolynomialBegin(1);\n"
- "s.appendTermBegin();\n"
- "s.appendTermDone(1); // coefficient\n"
- "s.appendPolynomialDone();\n"
- "s.idealDone();\n";
- EXPECT_EQ(msg, out.str());
-}
-
-TEST(MathicGBLib, EasyGB) {
- mgb::GroebnerConfiguration configuration(101, 3);
- mgb::GroebnerInputIdealStream input(configuration);
- std::ostringstream computedStr;
- mgb::IdealStreamLog<> computed(computedStr, 101, 3);
- mgb::IdealStreamChecker<decltype(computed)> checked(computed);
-
- makeBasis(input);
- mgb::computeGroebnerBasis(input, checked);
-
- std::ostringstream correctStr;
- mgb::IdealStreamLog<> correct(correctStr, 101, 3);
- mgb::IdealStreamChecker<decltype(correct)> correctChecked(correct);
- makeGroebnerBasis(correctChecked);
-
- EXPECT_EQ(correctStr.str(), computedStr.str())
- << "\nDisplayed expected:\n" << correctStr.str()
- << "\nDisplayed computed:\n" << computedStr.str();
-}
-
-TEST(MathicGBLib, EasyReGB) {
- mgb::GroebnerConfiguration configuration(101, 3);
- mgb::GroebnerInputIdealStream input(configuration);
- std::ostringstream computedStr;
- mgb::IdealStreamLog<> computed(computedStr, 101, 3);
- mgb::IdealStreamChecker<decltype(computed)> checked(computed);
-
- makeGroebnerBasis(input);
- mgb::computeGroebnerBasis(input, checked);
-
- std::ostringstream correctStr;
- mgb::IdealStreamLog<> correct(correctStr, 101, 3);
- mgb::IdealStreamChecker<decltype(correct)> correctChecked(correct);
- makeGroebnerBasis(correctChecked);
-
- EXPECT_EQ(correctStr.str(), computedStr.str())
- << "\nDisplayed expected:\n" << correctStr.str()
- << "\nDisplayed computed:\n" << computedStr.str();
-}
-
-TEST(MathicGBLib, Cyclic5) {
- for (int i = 0; i < 2; ++i) {
- mgb::GroebnerConfiguration configuration(101, 5);
- const auto reducer = i == 0 ?
- mgb::GroebnerConfiguration::ClassicReducer :
- mgb::GroebnerConfiguration::MatrixReducer;
- configuration.setReducer(reducer);
- mgb::GroebnerInputIdealStream input(configuration);
- makeCyclic5Basis(input);
-
- mgb::NullIdealStream computed(input.modulus(), input.varCount());
-
- mgb::computeGroebnerBasis(input, computed);
- }
-}
-
-namespace {
- class TestCallback : public mgb::GroebnerConfiguration::Callback {
- public:
- TestCallback(int count, Action action): mCount(count), mAction(action) {}
-
- virtual Action call() {
- --mCount;
- return mCount == 0 ? mAction : ContinueAction;
- }
-
- private:
- int mCount;
- const Action mAction;
- };
-}
-
-TEST(MathicGBLib, EarlyExit) {
- typedef mgb::GroebnerConfiguration::Callback::Action Action;
- auto check = [](bool useClassic, int count, Action action) {
- mgb::GroebnerConfiguration configuration(101, 5);
- const auto reducer = useClassic ?
- mgb::GroebnerConfiguration::ClassicReducer :
- mgb::GroebnerConfiguration::MatrixReducer;
- configuration.setReducer(reducer);
- TestCallback callback(count, action);
- configuration.setCallback(&callback);
- mgb::GroebnerInputIdealStream input(configuration);
- makeCyclic5Basis(input);
-
- std::ostringstream strOut;
- mgb::IdealStreamLog<> out(strOut, 101, 5);
- mgb::computeGroebnerBasis(input, out);
- return strOut.str().size();
- };
-
- for (int useClassic = 0; useClassic < 2; ++useClassic) {
- size_t none = check(useClassic, 5, Action::StopWithNoOutputAction);
- size_t minSize = check(useClassic, 1, Action::StopWithPartialOutputAction);
- size_t midSize = check(useClassic, 4, Action::StopWithPartialOutputAction);
- size_t maxSize = check(useClassic, 1, Action::ContinueAction);
- ASSERT_LT(none, 35); // the stream writes a header even for no output
- ASSERT_LT(none, minSize);
- ASSERT_LT(minSize, midSize);
- ASSERT_LT(midSize, maxSize);
- }
-}
-
-TEST(MathicGBLib, SimpleEliminationGB) {
- std::vector<mgb::GroebnerConfiguration::Exponent> gradings = {1,0,0,0, 1,1,1,1};
- for (int i = 0; i < 2; ++i) {
- mgb::GroebnerConfiguration configuration(101, 4);
- const auto reducer = i == 0 ?
- mgb::GroebnerConfiguration::ClassicReducer :
- mgb::GroebnerConfiguration::MatrixReducer;
- configuration.setReducer(reducer);
- configuration.setMonomialOrder(
- mgb::GroebnerConfiguration::BaseOrder::ReverseLexicographicBaseOrder,
- gradings
- );
-
- mgb::GroebnerInputIdealStream input(configuration);
- std::ostringstream computedStr;
- mgb::IdealStreamLog<> computed(computedStr, 101, 4);
- mgb::IdealStreamChecker<decltype(computed)> checked(computed);
-
- makeSimpleIdeal(input);
- mgb::computeGroebnerBasis(input, checked);
-
- std::ostringstream correctStr;
- mgb::IdealStreamLog<> correct(correctStr, 101, 4);
- mgb::IdealStreamChecker<decltype(correct)> correctChecked(correct);
- makeSimpleIdealGroebnerBasis(correctChecked);
-
- EXPECT_EQ(correctStr.str(), computedStr.str())
- << "\nDisplayed expected:\n" << correctStr.str()
- << "\nDisplayed computed:\n" << computedStr.str();
-#if 0
- mgb::GroebnerInputIdealStream input(configuration);
- makeSimpleIdeal(input);
- mgb::NullIdealStream computed(input.modulus(), input.varCount());
- mgb::computeGroebnerBasis(input, computed);
-#endif
- }
-}
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+
+#include "mathicgb.h"
+#include <gtest/gtest.h>
+
+using namespace mgb;
+
+namespace {
+ template<class Stream>
+ void makeBasis(Stream& s) {
+ s.idealBegin();
+ s.appendPolynomialBegin(); // x^2 - y
+ s.appendTermBegin();
+ s.appendExponent(0,2);
+ s.appendTermDone(1);
+ s.appendTermBegin();
+ s.appendExponent(1,1);
+ s.appendTermDone(s.modulus() - 1);
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(2); // x^3-z
+ s.appendTermBegin();
+ s.appendExponent(0,3);
+ s.appendTermDone(1);
+ s.appendTermBegin();
+ s.appendExponent(2,1);
+ s.appendTermDone(s.modulus() - 1);
+ s.appendPolynomialDone();
+ s.idealDone();
+ }
+
+ template<class Stream>
+ void makeGroebnerBasis(Stream& s) {
+ s.idealBegin(3);
+ s.appendPolynomialBegin(2); // x^2 - y
+ s.appendTermBegin();
+ s.appendExponent(0, 2);
+ s.appendExponent(1, 0);
+ s.appendExponent(2, 0);
+ s.appendTermDone(1);
+ s.appendTermBegin();
+ s.appendExponent(0, 0);
+ s.appendExponent(1, 1);
+ s.appendExponent(2, 0);
+ s.appendTermDone(s.modulus() - 1);
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(2); // xy - z
+ s.appendTermBegin();
+ s.appendExponent(0, 1);
+ s.appendExponent(1, 1);
+ s.appendExponent(2, 0);
+ s.appendTermDone(1);
+ s.appendTermBegin();
+ s.appendExponent(0, 0);
+ s.appendExponent(1, 0);
+ s.appendExponent(2, 1);
+ s.appendTermDone(s.modulus() - 1);
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(2); // y^2 - xy
+ s.appendTermBegin();
+ s.appendExponent(0, 0);
+ s.appendExponent(1, 2);
+ s.appendExponent(2, 0);
+ s.appendTermDone(1);
+ s.appendTermBegin();
+ s.appendExponent(0, 1);
+ s.appendExponent(1, 0);
+ s.appendExponent(2, 1);
+ s.appendTermDone(s.modulus() - 1);
+ s.appendPolynomialDone();
+ s.idealDone();
+ }
+
+ template<class Stream>
+ void makeCyclic5Basis(Stream& s) {
+ s.idealBegin(5); // polyCount
+ s.appendPolynomialBegin(5);
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(1, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(2, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(3, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(5);
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(1, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(3, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(5);
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(5);
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(2);
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendExponent(4, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendTermDone(100); // coefficient
+ s.appendPolynomialDone();
+ s.idealDone();
+ }
+
+ template<class Stream>
+ void makeSimpleIdeal(Stream& s) { // variables a,b,c,d. a2-bc, ab-cd.
+ s.idealBegin();
+ s.appendPolynomialBegin(); // a^2-b*c
+ s.appendTermBegin();
+ s.appendExponent(0,2);
+ s.appendTermDone(1);
+ s.appendTermBegin();
+ s.appendExponent(1,1);
+ s.appendExponent(2,1);
+ s.appendTermDone(s.modulus() - 1);
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(2); // a*b-c*d
+ s.appendTermBegin();
+ s.appendExponent(0,1);
+ s.appendExponent(1,1);
+ s.appendTermDone(1);
+ s.appendTermBegin();
+ s.appendExponent(2,1);
+ s.appendExponent(3,1);
+ s.appendTermDone(s.modulus() - 1);
+ s.appendPolynomialDone();
+ s.idealDone();
+ }
+
+ template<class Stream>
+ void makeSimpleIdealGroebnerBasis(Stream& s) { // variables a,b,c,d. a2-bc, ab-cd.
+ // Groebner basis is {a^2-b*c,a*b-c*d,a*c*d-b^2*c,b^3*c-c^2*d^2}
+ // (order: eliminate 1 variable: [1 0 0 0; 1 1 1 1]).
+ s.idealBegin(4); // polyCount
+ s.appendPolynomialBegin(2);
+ s.appendTermBegin();
+ s.appendExponent(0, 2); // index, exponent
+ s.appendExponent(1, 0); // index, exponent
+ s.appendExponent(2, 0); // index, exponent
+ s.appendExponent(3, 0); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 0); // index, exponent
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 0); // index, exponent
+ s.appendTermDone(100); // coefficient
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(2);
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(1, 1); // index, exponent
+ s.appendExponent(2, 0); // index, exponent
+ s.appendExponent(3, 0); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 0); // index, exponent
+ s.appendExponent(1, 0); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendTermDone(100); // coefficient
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(2);
+ s.appendTermBegin();
+ s.appendExponent(0, 1); // index, exponent
+ s.appendExponent(1, 0); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 1); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 0); // index, exponent
+ s.appendExponent(1, 2); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 0); // index, exponent
+ s.appendTermDone(100); // coefficient
+ s.appendPolynomialDone();
+ s.appendPolynomialBegin(2);
+ s.appendTermBegin();
+ s.appendExponent(0, 0); // index, exponent
+ s.appendExponent(1, 3); // index, exponent
+ s.appendExponent(2, 1); // index, exponent
+ s.appendExponent(3, 0); // index, exponent
+ s.appendTermDone(1); // coefficient
+ s.appendTermBegin();
+ s.appendExponent(0, 0); // index, exponent
+ s.appendExponent(1, 0); // index, exponent
+ s.appendExponent(2, 2); // index, exponent
+ s.appendExponent(3, 2); // index, exponent
+ s.appendTermDone(100); // coefficient
+ s.appendPolynomialDone();
+ s.idealDone();
+ }
+}
+
+TEST(MathicGBLib, NullIdealStream) {
+ {
+ mgb::NullIdealStream stream(2, 3);
+ ASSERT_EQ(2, stream.modulus());
+ ASSERT_EQ(3, stream.varCount());
+ makeBasis(stream);
+ }
+
+ {
+ mgb::NullIdealStream stream(101, 0);
+ ASSERT_EQ(101, stream.modulus());
+ ASSERT_EQ(0, stream.varCount());
+ }
+}
+
+TEST(MathicGBLib, IdealStreamLog) {
+ {
+ const char* const idealStr =
+ "s.idealBegin();\n"
+ "s.appendPolynomialBegin();\n"
+ "s.appendTermBegin();\n"
+ "s.appendExponent(0, 2); // index, exponent\n"
+ "s.appendTermDone(1); // coefficient\n"
+ "s.appendTermBegin();\n"
+ "s.appendExponent(1, 1); // index, exponent\n"
+ "s.appendTermDone(6); // coefficient\n"
+ "s.appendPolynomialDone();\n"
+ "s.appendPolynomialBegin(2);\n"
+ "s.appendTermBegin();\n"
+ "s.appendExponent(0, 3); // index, exponent\n"
+ "s.appendTermDone(1); // coefficient\n"
+ "s.appendTermBegin();\n"
+ "s.appendExponent(2, 1); // index, exponent\n"
+ "s.appendTermDone(6); // coefficient\n"
+ "s.appendPolynomialDone();\n"
+ "s.idealDone();\n";
+
+ std::ostringstream out1;
+ mgb::IdealStreamLog<> stream1(out1, 7, 3);
+
+ mgb::IdealStreamChecker<decltype(stream1)> checker(stream1);
+
+ std::ostringstream out2;
+ mgb::IdealStreamLog<decltype(checker)> stream2(out2, checker);
+
+ std::ostringstream out3;
+ mgb::IdealStreamLog<decltype(stream2)> stream3(out3, stream2);
+
+ ASSERT_EQ(7, stream1.modulus());
+ ASSERT_EQ(3, stream1.varCount());
+ ASSERT_EQ(7, checker.modulus());
+ ASSERT_EQ(3, checker.varCount());
+ ASSERT_EQ(7, stream2.modulus());
+ ASSERT_EQ(3, stream2.varCount());
+ ASSERT_EQ(7, stream3.modulus());
+ ASSERT_EQ(3, stream3.varCount());
+
+ makeBasis(stream3);
+ const auto str1 = std::string(
+ "IdealStreamLog s(stream, 7, 3);\n"
+ ) + idealStr;
+ ASSERT_EQ(str1, out1.str())
+ << "Displayed expected:\n" << out1.str()
+ << "Displayed actual:\n" << str1 << std::endl;
+
+ const auto str2 = std::string(
+ "IdealStreamLog s(stream, log); // modulus=7, varCount=3\n"
+ ) + idealStr;
+ ASSERT_EQ(str2, out2.str()) << "Displayed expected:\n" << out2.str();
+ ASSERT_EQ(str2, out3.str()) << "Displayed expected:\n" << out3.str();
+ }
+
+ // The ideal <> in no variables
+ {
+ std::ostringstream out;
+ mgb::IdealStreamLog<> stream(out, 101, 0);
+ ASSERT_EQ(101, stream.modulus());
+ ASSERT_EQ(0, stream.varCount());
+ stream.idealBegin(0);
+ stream.idealDone();
+ }
+
+ // The ideal <1, 0> in no variables
+ {
+ std::ostringstream out;
+ mgb::IdealStreamLog<> stream(out, 101, 0);
+ ASSERT_EQ(101, stream.modulus());
+ ASSERT_EQ(0, stream.varCount());
+ stream.idealBegin(2);
+ stream.appendPolynomialBegin(0); // 1
+ stream.appendTermBegin();
+ stream.appendTermDone(1);
+ stream.appendPolynomialDone();
+ stream.appendPolynomialBegin(0); // 0
+ stream.appendPolynomialDone();
+ stream.idealDone();
+ }
+}
+
+TEST(MathicGBLib, ZeroIdealGB) {
+ mgb::GroebnerConfiguration configuration(2, 0);
+ mgb::GroebnerInputIdealStream input(configuration);
+ std::ostringstream out;
+ mgb::IdealStreamLog<> logStream(out, 2, 0);
+
+ input.idealBegin(0);
+ input.idealDone();
+ mgb::computeGroebnerBasis(input, logStream);
+
+ const auto msg =
+ "IdealStreamLog s(stream, 2, 0);\n"
+ "s.idealBegin(0); // polyCount\n"
+ "s.idealDone();\n";
+ EXPECT_EQ(msg, out.str());
+}
+
+TEST(MathicGBLib, OneIdealGB) {
+ mgb::GroebnerConfiguration configuration(2, 0);
+ mgb::GroebnerInputIdealStream input(configuration);
+ std::ostringstream out;
+ mgb::IdealStreamLog<> logStream(out, 2, 0);
+
+ input.idealBegin(1);
+ input.appendPolynomialBegin(1);
+ input.appendTermBegin();
+ input.appendTermDone(1);
+ input.appendPolynomialDone();
+ input.idealDone();
+ mgb::computeGroebnerBasis(input, logStream);
+
+ const auto msg =
+ "IdealStreamLog s(stream, 2, 0);\n"
+ "s.idealBegin(1); // polyCount\n"
+ "s.appendPolynomialBegin(1);\n"
+ "s.appendTermBegin();\n"
+ "s.appendTermDone(1); // coefficient\n"
+ "s.appendPolynomialDone();\n"
+ "s.idealDone();\n";
+ EXPECT_EQ(msg, out.str());
+}
+
+TEST(MathicGBLib, EasyGB) {
+ mgb::GroebnerConfiguration configuration(101, 3);
+ mgb::GroebnerInputIdealStream input(configuration);
+ std::ostringstream computedStr;
+ mgb::IdealStreamLog<> computed(computedStr, 101, 3);
+ mgb::IdealStreamChecker<decltype(computed)> checked(computed);
+
+ makeBasis(input);
+ mgb::computeGroebnerBasis(input, checked);
+
+ std::ostringstream correctStr;
+ mgb::IdealStreamLog<> correct(correctStr, 101, 3);
+ mgb::IdealStreamChecker<decltype(correct)> correctChecked(correct);
+ makeGroebnerBasis(correctChecked);
+
+ EXPECT_EQ(correctStr.str(), computedStr.str())
+ << "\nDisplayed expected:\n" << correctStr.str()
+ << "\nDisplayed computed:\n" << computedStr.str();
+}
+
+TEST(MathicGBLib, EasyReGB) {
+ mgb::GroebnerConfiguration configuration(101, 3);
+ mgb::GroebnerInputIdealStream input(configuration);
+ std::ostringstream computedStr;
+ mgb::IdealStreamLog<> computed(computedStr, 101, 3);
+ mgb::IdealStreamChecker<decltype(computed)> checked(computed);
+
+ makeGroebnerBasis(input);
+ mgb::computeGroebnerBasis(input, checked);
+
+ std::ostringstream correctStr;
+ mgb::IdealStreamLog<> correct(correctStr, 101, 3);
+ mgb::IdealStreamChecker<decltype(correct)> correctChecked(correct);
+ makeGroebnerBasis(correctChecked);
+
+ EXPECT_EQ(correctStr.str(), computedStr.str())
+ << "\nDisplayed expected:\n" << correctStr.str()
+ << "\nDisplayed computed:\n" << computedStr.str();
+}
+
+TEST(MathicGBLib, Cyclic5) {
+ for (int i = 0; i < 2; ++i) {
+ mgb::GroebnerConfiguration configuration(101, 5);
+ const auto reducer = i == 0 ?
+ mgb::GroebnerConfiguration::ClassicReducer :
+ mgb::GroebnerConfiguration::MatrixReducer;
+ configuration.setReducer(reducer);
+ mgb::GroebnerInputIdealStream input(configuration);
+ makeCyclic5Basis(input);
+
+ mgb::NullIdealStream computed(input.modulus(), input.varCount());
+
+ mgb::computeGroebnerBasis(input, computed);
+ }
+}
+
+namespace {
+ class TestCallback : public mgb::GroebnerConfiguration::Callback {
+ public:
+ TestCallback(int count, Action action): mCount(count), mAction(action) {}
+
+ virtual Action call() {
+ --mCount;
+ return mCount == 0 ? mAction : ContinueAction;
+ }
+
+ private:
+ int mCount;
+ const Action mAction;
+ };
+}
+
+TEST(MathicGBLib, EarlyExit) {
+ typedef mgb::GroebnerConfiguration::Callback::Action Action;
+ auto check = [](bool useClassic, int count, Action action) {
+ mgb::GroebnerConfiguration configuration(101, 5);
+ const auto reducer = useClassic ?
+ mgb::GroebnerConfiguration::ClassicReducer :
+ mgb::GroebnerConfiguration::MatrixReducer;
+ configuration.setReducer(reducer);
+ TestCallback callback(count, action);
+ configuration.setCallback(&callback);
+ mgb::GroebnerInputIdealStream input(configuration);
+ makeCyclic5Basis(input);
+
+ std::ostringstream strOut;
+ mgb::IdealStreamLog<> out(strOut, 101, 5);
+ mgb::computeGroebnerBasis(input, out);
+ return strOut.str().size();
+ };
+
+ for (int useClassic = 0; useClassic < 2; ++useClassic) {
+ size_t none = check(useClassic, 5, Action::StopWithNoOutputAction);
+ size_t minSize = check(useClassic, 1, Action::StopWithPartialOutputAction);
+ size_t midSize = check(useClassic, 4, Action::StopWithPartialOutputAction);
+ size_t maxSize = check(useClassic, 1, Action::ContinueAction);
+ ASSERT_LT(none, 35); // the stream writes a header even for no output
+ ASSERT_LT(none, minSize);
+ ASSERT_LT(minSize, midSize);
+ ASSERT_LT(midSize, maxSize);
+ }
+}
+
+TEST(MathicGBLib, SimpleEliminationGB) {
+ std::vector<mgb::GroebnerConfiguration::Exponent> gradings = {1,0,0,0, 1,1,1,1};
+ for (int i = 0; i < 2; ++i) {
+ mgb::GroebnerConfiguration configuration(101, 4);
+ const auto reducer = i == 0 ?
+ mgb::GroebnerConfiguration::ClassicReducer :
+ mgb::GroebnerConfiguration::MatrixReducer;
+ configuration.setReducer(reducer);
+ configuration.setMonomialOrder(
+ mgb::GroebnerConfiguration::BaseOrder::ReverseLexicographicBaseOrder,
+ gradings
+ );
+
+ mgb::GroebnerInputIdealStream input(configuration);
+ std::ostringstream computedStr;
+ mgb::IdealStreamLog<> computed(computedStr, 101, 4);
+ mgb::IdealStreamChecker<decltype(computed)> checked(computed);
+
+ makeSimpleIdeal(input);
+ mgb::computeGroebnerBasis(input, checked);
+
+ std::ostringstream correctStr;
+ mgb::IdealStreamLog<> correct(correctStr, 101, 4);
+ mgb::IdealStreamChecker<decltype(correct)> correctChecked(correct);
+ makeSimpleIdealGroebnerBasis(correctChecked);
+
+ EXPECT_EQ(correctStr.str(), computedStr.str())
+ << "\nDisplayed expected:\n" << correctStr.str()
+ << "\nDisplayed computed:\n" << computedStr.str();
+#if 0
+ mgb::GroebnerInputIdealStream input(configuration);
+ makeSimpleIdeal(input);
+ mgb::NullIdealStream computed(input.modulus(), input.varCount());
+ mgb::computeGroebnerBasis(input, computed);
+#endif
+ }
+}
+
diff --git a/src/test/monoidPict.in b/src/test/monoidPict.in
index 200ee7f..5da0f2a 100755
--- a/src/test/monoidPict.in
+++ b/src/test/monoidPict.in
@@ -1,29 +1,29 @@
-# See pict.in for what pict files do.
-# This file is for getting a good set of test instantiations of MonoMonoid.
-# See the test file MonoMonoid.cpp.
-#
-# To generate a set of test configurations, do
-#
-# pict monoidPict.in /e:monoidPict.seed > monoidPict.out
-#
-# Then reformat the output and put it into MonoMonoid.cpp as the set
-# of PolyRing configurations to use.
-
-##############################################################
-# This is the PICT model specifying all parameters and their values
-#
-Exponent: int8, int16, int32
-HasComponent: 0,1
-StoreHash: 0,1
-StoreOrder: 0,1
-
-##############################################################
-# PICT submodels go here.
-#
-
-# we are not currently using PICT submodels
-
-##############################################################
-# This is the set of PICT constraints that rule out some combinations
-# of parameter values.
-#
+# See pict.in for what pict files do.
+# This file is for getting a good set of test instantiations of MonoMonoid.
+# See the test file MonoMonoid.cpp.
+#
+# To generate a set of test configurations, do
+#
+# pict monoidPict.in /e:monoidPict.seed > monoidPict.out
+#
+# Then reformat the output and put it into MonoMonoid.cpp as the set
+# of PolyRing configurations to use.
+
+##############################################################
+# This is the PICT model specifying all parameters and their values
+#
+Exponent: int8, int16, int32
+HasComponent: 0,1
+StoreHash: 0,1
+StoreOrder: 0,1
+
+##############################################################
+# PICT submodels go here.
+#
+
+# we are not currently using PICT submodels
+
+##############################################################
+# This is the set of PICT constraints that rule out some combinations
+# of parameter values.
+#
diff --git a/src/test/monoidPict.seed b/src/test/monoidPict.seed
index 44aa83c..faf9bed 100755
--- a/src/test/monoidPict.seed
+++ b/src/test/monoidPict.seed
@@ -1,9 +1,9 @@
-Exponent HasComponent StoreHash StoreOrder
-int32 1 1 1
-int32 0 1 1
-int32 0 0 1
-int32 0 0 0
-int16 1 1 1
-int16 0 1 1
-int16 0 0 1
-int16 0 0 0
+Exponent HasComponent StoreHash StoreOrder
+int32 1 1 1
+int32 0 1 1
+int32 0 0 1
+int32 0 0 0
+int16 1 1 1
+int16 0 1 1
+int16 0 0 1
+int16 0 0 0
diff --git a/src/test/pict.in b/src/test/pict.in
index 0557a0b..1d8cdb0 100755
--- a/src/test/pict.in
+++ b/src/test/pict.in
@@ -1,58 +1,58 @@
-# The purpose of this file is to generate a set of test configurations
-# where every pair of parameter values is present at least once. See
-# the Wikipedia page on all pairs testing:
-#
-# http://en.wikipedia.org/wiki/All-pairs_testing
-#
-# This file is an input file for the Microsoft testing tool PICT.
-# The tool is available at
-#
-# http://download.microsoft.com/download/f/5/5/f55484df-8494-48fa-8dbd-8c6f76cc014b/pict33.msi
-#
-# You will need to run this program on Windows. It is a closed source
-# utility. There are open sources alternatives but they are not as good.
-#
-# To update the test in gb-test.cpp, do
-#
-# pict pict.in > pict.out
-#
-# Then place the entire contents of pict.out (including newlines) into
-# the string allPairsTest in gb-test.cpp.
-
-##############################################################
-# This is the PICT model specifying all parameters and their values
-#
-spairQueue: 0,1,2,3
-reducerType: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
-divLookup: 1, 2, 3, 4
-monTable: 0, 1, 2
-buchberger: 0, 1
-postponeKoszul: 0, 1
-useBaseDivisors: 0, 1
-autoTailReduce: 0,1
-autoTopReduce: 0,1
-preferSparseReducers: 0,1
-useSingularCriterionEarly: 0, 1
-sPairGroupSize: 0, 1, 2, 10, 100
-threadCount: 1, 2, 8
-
-##############################################################
-# PICT submodels go here.
-#
-
-# we are not currently using PICT submodels
-
-##############################################################
-# This is the set of PICT constraints that rule out some combinations
-# of parameter values.
-#
-IF [buchberger] = 0 THEN
- [autoTopReduce] = 0 AND
- [autoTailReduce] = 0 AND
- [reducerType] <> 25 AND
- [reducerType] <> 26;
-
-IF [buchberger] = 1 THEN
- [postponeKoszul] = 0 AND
- [useBaseDivisors] = 0 AND
- [usesingularCriterionEarly] = 0;
+# The purpose of this file is to generate a set of test configurations
+# where every pair of parameter values is present at least once. See
+# the Wikipedia page on all pairs testing:
+#
+# http://en.wikipedia.org/wiki/All-pairs_testing
+#
+# This file is an input file for the Microsoft testing tool PICT.
+# The tool is available at
+#
+# http://download.microsoft.com/download/f/5/5/f55484df-8494-48fa-8dbd-8c6f76cc014b/pict33.msi
+#
+# You will need to run this program on Windows. It is a closed source
+# utility. There are open sources alternatives but they are not as good.
+#
+# To update the test in gb-test.cpp, do
+#
+# pict pict.in > pict.out
+#
+# Then place the entire contents of pict.out (including newlines) into
+# the string allPairsTest in gb-test.cpp.
+
+##############################################################
+# This is the PICT model specifying all parameters and their values
+#
+spairQueue: 0,1,2,3
+reducerType: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
+divLookup: 1, 2, 3, 4
+monTable: 0, 1, 2
+buchberger: 0, 1
+postponeKoszul: 0, 1
+useBaseDivisors: 0, 1
+autoTailReduce: 0,1
+autoTopReduce: 0,1
+preferSparseReducers: 0,1
+useSingularCriterionEarly: 0, 1
+sPairGroupSize: 0, 1, 2, 10, 100
+threadCount: 1, 2, 8
+
+##############################################################
+# PICT submodels go here.
+#
+
+# we are not currently using PICT submodels
+
+##############################################################
+# This is the set of PICT constraints that rule out some combinations
+# of parameter values.
+#
+IF [buchberger] = 0 THEN
+ [autoTopReduce] = 0 AND
+ [autoTailReduce] = 0 AND
+ [reducerType] <> 25 AND
+ [reducerType] <> 26;
+
+IF [buchberger] = 1 THEN
+ [postponeKoszul] = 0 AND
+ [useBaseDivisors] = 0 AND
+ [usesingularCriterionEarly] = 0;
diff --git a/src/test/poly-test.cpp b/src/test/poly-test.cpp
index 09a7f61..d00fc09 100755
--- a/src/test/poly-test.cpp
+++ b/src/test/poly-test.cpp
@@ -1,27 +1,27 @@
-// Copyright 2011 Michael E. Stillman
-
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
#include "mathicgb/stdinc.h"
-#include <cstdio>
-#include <string>
-#include <iostream>
-#include <sstream>
-
#include "mathicgb/Poly.hpp"
+
#include "mathicgb/Basis.hpp"
#include "mathicgb/MonTableNaive.hpp"
#include "mathicgb/MonTableKDTree.hpp"
#include "mathicgb/MonTableDivList.hpp"
#include "mathicgb/MTArray.hpp"
#include "mathicgb/io-util.hpp"
-
#include "mathicgb/MonomialHashTable.hpp"
#include "mathicgb/PolyHashTable.hpp"
#include "mathicgb/PolyHeap.hpp"
#include "mathicgb/PolyGeoBucket.hpp"
#include "mathicgb/SigPolyBasis.hpp"
#include "mathicgb/SignatureGB.hpp"
-
#include <gtest/gtest.h>
+#include <cstdio>
+#include <string>
+#include <iostream>
+#include <sstream>
+
+using namespace mgb;
std::string ideal1 =
"32003 4 1 1 1 1 1 \
@@ -829,8 +829,3 @@ TEST(MonomialHashTable,test1) {
H.getStats(stats);
//H.dump(1);
}
-
-// Local Variables:
-// compile-command: "make -C .. "
-// indent-tabs-mode: nil
-// End:
diff --git a/src/test/testMain.cpp b/src/test/testMain.cpp
index 4d820af..6fe8117 100755
--- a/src/test/testMain.cpp
+++ b/src/test/testMain.cpp
@@ -1,5 +1,11 @@
+// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY
+// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.
+#include "mathicgb/stdinc.h"
+
#include <gtest/gtest.h>
+using namespace mgb;
+
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
--
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