[mathicgb] 331/393: Changed the way that module-component rows are stored in MonoOrder. This fixed a bug where MathicGB would get confused in the library interface when given a non-last position for the module comparison.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:30 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 a090dea427492add77ed25e43e7c41e41fe390ce
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Fri Aug 23 13:32:33 2013 +0200

    Changed the way that module-component rows are stored in MonoOrder. This fixed a bug where MathicGB would get confused in the library interface when given a non-last position for the module comparison.
---
 build/vs12/mathicgb-test/mathicgb-test.vcxproj     |   2 +
 .../mathicgb-test/mathicgb-test.vcxproj.filters    |   6 +
 src/cli/GBAction.cpp                               |   4 +-
 src/cli/SigGBAction.cpp                            |   4 +-
 src/mathicgb/MathicIO.cpp                          |  57 ++-
 src/mathicgb/MathicIO.hpp                          | 447 ++++++++++++++++++++-
 src/mathicgb/MonoMonoid.hpp                        |  60 ++-
 src/mathicgb/MonoOrder.hpp                         | 100 ++---
 src/mathicgb/io-util.cpp                           |   4 +-
 src/test/MathicIO.cpp                              | 102 ++---
 src/test/MonoMonoid.cpp                            |  52 ++-
 src/test/Scanner.cpp                               |   4 +-
 src/test/gb-test.cpp                               |   4 +-
 13 files changed, 654 insertions(+), 192 deletions(-)

diff --git a/build/vs12/mathicgb-test/mathicgb-test.vcxproj b/build/vs12/mathicgb-test/mathicgb-test.vcxproj
index 5b5d3d7..1fa51fa 100755
--- a/build/vs12/mathicgb-test/mathicgb-test.vcxproj
+++ b/build/vs12/mathicgb-test/mathicgb-test.vcxproj
@@ -402,10 +402,12 @@
     <ClCompile Include="..\..\..\src\test\gtestInclude.cpp" />
     <ClCompile Include="..\..\..\src\test\ideals.cpp" />
     <ClCompile Include="..\..\..\src\test\mathicgb.cpp" />
+    <ClCompile Include="..\..\..\src\test\MathicIO.cpp" />
     <ClCompile Include="..\..\..\src\test\MonoMonoid.cpp" />
     <ClCompile Include="..\..\..\src\test\poly-test.cpp" />
     <ClCompile Include="..\..\..\src\test\PrimeField.cpp" />
     <ClCompile Include="..\..\..\src\test\QuadMatrixBuilder.cpp" />
+    <ClCompile Include="..\..\..\src\test\Scanner.cpp" />
     <ClCompile Include="..\..\..\src\test\SparseMatrix.cpp" />
     <ClCompile Include="..\..\..\src\test\testMain.cpp" />
   </ItemGroup>
diff --git a/build/vs12/mathicgb-test/mathicgb-test.vcxproj.filters b/build/vs12/mathicgb-test/mathicgb-test.vcxproj.filters
index 82437c0..1750b4f 100755
--- a/build/vs12/mathicgb-test/mathicgb-test.vcxproj.filters
+++ b/build/vs12/mathicgb-test/mathicgb-test.vcxproj.filters
@@ -51,6 +51,12 @@
     <ClCompile Include="..\..\..\src\test\MonoMonoid.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\src\test\MathicIO.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\src\test\Scanner.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\src\test\ideals.hpp">
diff --git a/src/cli/GBAction.cpp b/src/cli/GBAction.cpp
index feaef86..5eebe0e 100755
--- a/src/cli/GBAction.cpp
+++ b/src/cli/GBAction.cpp
@@ -61,9 +61,9 @@ void GBAction::performAction() {
     mic::reportError("Could not read input file \"" + inputBasisFile + '\n');
 
   Scanner in(inputFile);
-  auto p = MathicIO().readRing(true, in);
+  auto p = MathicIO<>().readRing(true, in);
   auto& ring = *p.first;
-  auto basis = MathicIO().readBasis(ring, false, in);
+  auto basis = MathicIO<>().readBasis(ring, false, in);
 
   // run algorithm
   const auto reducerType = Reducer::reducerType(mGBParams.mReducer.value());
diff --git a/src/cli/SigGBAction.cpp b/src/cli/SigGBAction.cpp
index a3646ee..01f6cc6 100755
--- a/src/cli/SigGBAction.cpp
+++ b/src/cli/SigGBAction.cpp
@@ -52,10 +52,10 @@ void SigGBAction::performAction() {
 
 
   Scanner in(inputFile);
-  auto p = MathicIO().readRing(true, in);
+  auto p = MathicIO<>().readRing(true, in);
   auto& ring = *p.first;
   auto& processor = p.second;
-  auto basis = MathicIO().readBasis(ring, false, in);
+  auto basis = MathicIO<>().readBasis(ring, false, in);
   if (processor.schreyering())
     processor.setSchreyerMultipliers(basis);
 
diff --git a/src/mathicgb/MathicIO.cpp b/src/mathicgb/MathicIO.cpp
index 26d01fa..6e0f23e 100755
--- a/src/mathicgb/MathicIO.cpp
+++ b/src/mathicgb/MathicIO.cpp
@@ -4,16 +4,22 @@
 #include "MathicIO.hpp"
 
 MATHICGB_NAMESPACE_BEGIN
-
-auto MathicIO::readBaseField(Scanner& in) -> BaseField {
+  /*
+template<class M, class BF>
+auto MathicIO<M, BF>::readBaseField(Scanner& in) -> BaseField {
   return BaseField(in.readInteger<RawCoefficient>());
 }
 
-void MathicIO::writeBaseField(const BaseField& field, std::ostream& out) {
+template<class M, class BF>
+void MathicIO<M, BF>::writeBaseField(
+  const BaseField& field,
+  std::ostream& out
+) {
   out << field.charac();
 }
 
-auto MathicIO::readRing(
+template<class M, class BF>
+auto MathicIO<M, BF>::readRing(
   const bool withComponent,
   Scanner& in
 ) -> std::pair<std::unique_ptr<PolyRing>, Processor> {
@@ -34,7 +40,8 @@ auto MathicIO::readRing(
   return std::make_pair(std::move(ring), std::move(processor));
 }
 
-void MathicIO::writeRing(
+template<class M, class BF>
+void MathicIO<M, BF>::writeRing(
   const PolyRing& ring,
   const Processor& processor,
   const bool withComponent,
@@ -50,7 +57,8 @@ void MathicIO::writeRing(
   writeOrder(order, withComponent, out);
 }
 
-auto MathicIO::readOrder(
+template<class M, class BF>
+auto MathicIO<M, BF>::readOrder(
   const VarIndex varCount,
   const bool withComponent,
   Scanner& in
@@ -58,7 +66,7 @@ auto MathicIO::readOrder(
   const bool schreyering = in.match("schreyer");
   bool lexBaseOrder = !in.match("revlex") && in.match("lex");
 
-  const auto gradingCount = in.readInteger<VarIndex>();
+  auto gradingCount = in.readInteger<VarIndex>();
   bool componentsAscendingDesired = true;
   auto componentCompareIndex = Order::ComponentAfterBaseOrder;
   Gradings gradings(static_cast<size_t>(varCount) * gradingCount);
@@ -105,7 +113,8 @@ auto MathicIO::readOrder(
   return std::move(order);
 }
 
-void MathicIO::writeOrder(
+template<class M, class BF>
+void MathicIO<M, BF>::writeOrder(
   const Order& order,
   const bool withComponent,
   std::ostream& out
@@ -140,7 +149,8 @@ void MathicIO::writeOrder(
   }
 }
 
-Basis MathicIO::readBasis(
+template<class M, class BF>
+Basis MathicIO<M, BF>::readBasis(
   const PolyRing& ring,
   const bool readComponent,
   Scanner& in
@@ -155,7 +165,8 @@ Basis MathicIO::readBasis(
   return std::move(basis);
 }
 
-void MathicIO::writeBasis(
+template<class M, class BF>
+void MathicIO<M, BF>::writeBasis(
   const Basis& basis,
   const bool writeComponent,
   std::ostream& out
@@ -168,7 +179,8 @@ void MathicIO::writeBasis(
   }
 }
 
-Poly MathicIO::readPoly(
+template<class M, class BF>
+Poly MathicIO<M, BF>::readPoly(
   const PolyRing& ring,
   const bool readComponent,
   Scanner& in
@@ -191,7 +203,8 @@ Poly MathicIO::readPoly(
   return std::move(p);
 }
 
-void MathicIO::writePoly(
+template<class M, class BF>
+void MathicIO<M, BF>::writePoly(
   const Poly& poly,
   const bool writeComponent,
   std::ostream& out
@@ -215,7 +228,8 @@ void MathicIO::writePoly(
   }
 }
 
-void MathicIO::readTerm(
+template<class M, class BF>
+void MathicIO<M, BF>::readTerm(
   const PolyRing& ring,
   const bool readComponent,
   Coefficient& coef,
@@ -244,7 +258,8 @@ void MathicIO::readTerm(
   readMonomial(monoid, readComponent, mono, in);
 }
 
-void MathicIO::writeTerm(
+template<class M, class BF>
+void MathicIO<M, BF>::writeTerm(
   const PolyRing& ring,
   const bool writeComponent,
   const Coefficient coef,
@@ -262,7 +277,8 @@ void MathicIO::writeTerm(
   writeMonomial(ring.monoid(), writeComponent, mono, out);
 }
 
-void MathicIO::readMonomial(
+template<class M, class BF>
+void MathicIO<M, BF>::readMonomial(
   const Monoid& monoid,
   const bool readComponent,
   MonoRef mono,
@@ -328,7 +344,8 @@ void MathicIO::readMonomial(
     this->readComponent(monoid, mono, in);
 }
 
-void MathicIO::readComponent(
+template<class M, class BF>
+void MathicIO<M, BF>::readComponent(
   const Monoid& monoid,
   MonoRef mono,
   Scanner& in
@@ -339,7 +356,8 @@ void MathicIO::readComponent(
   in.expect('>');
 }
 
-void MathicIO::writeComponent(
+template<class M, class BF>
+void MathicIO<M, BF>::writeComponent(
   const Monoid& monoid,
   ConstMonoRef mono,
   std::ostream& out
@@ -349,7 +367,8 @@ void MathicIO::writeComponent(
 }
 
 /// Print a monomial with no coefficient.
-void MathicIO::writeMonomial(
+template<class M, class BF>
+void MathicIO<M, BF>::writeMonomial(
   const Monoid& monoid,
   const bool writeComponent,
   ConstMonoRef mono,
@@ -380,5 +399,5 @@ void MathicIO::writeMonomial(
   if (writeComponent)
     this->writeComponent(monoid, mono, out);
 }
-
+*/
 MATHICGB_NAMESPACE_END
diff --git a/src/mathicgb/MathicIO.hpp b/src/mathicgb/MathicIO.hpp
index 9a3a75b..68f04f4 100755
--- a/src/mathicgb/MathicIO.hpp
+++ b/src/mathicgb/MathicIO.hpp
@@ -14,21 +14,28 @@
 MATHICGB_NAMESPACE_BEGIN
 
 /// Class for input and output in Mathic's format.
+template<
+  class Monoid = PolyRing::Monoid,
+  class BaseField = PolyRing::Field
+>
+class MathicIO;
+
+template<class M, class BF>
 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 BF BaseField;
+  typedef typename BaseField::Element Coefficient;
+  typedef typename BaseField::RawElement RawCoefficient;
+
+  typedef M Monoid;
+  typedef typename Monoid::MonoRef MonoRef;
+  typedef typename Monoid::Exponent Exponent;
+  typedef typename Monoid::VarIndex VarIndex;
+  typedef typename Monoid::ConstMonoRef ConstMonoRef;
+  typedef typename Monoid::Order Order;
   typedef MonoProcessor<Monoid> Processor;
 
-  typedef Order::Gradings Gradings;
+  typedef typename  Order::Gradings Gradings;
 
 /*
   /// reads ring, #gens, each generator in turn
@@ -56,6 +63,10 @@ public:
     std::ostream& out
   );
 
+  Order readOrderWithVarCount(bool withComponent, Scanner& in);
+  void writeOrderWithVarCount
+    (const Order& monoid, const bool withComponent, std::ostream& out);
+
   Order readOrder(
     const VarIndex varCount,
     const bool withComponent,
@@ -142,5 +153,419 @@ public:
   );
 };
 
+template<class M, class BF>
+auto MathicIO<M, BF>::readBaseField(Scanner& in) -> BaseField {
+  return BaseField(in.readInteger<RawCoefficient>());
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::writeBaseField(
+  const BaseField& field,
+  std::ostream& out
+) {
+  out << field.charac();
+}
+
+template<class M, class BF>
+auto MathicIO<M, BF>::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));
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::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);
+}
+
+template<class M, class BF>
+auto MathicIO<M, BF>::readOrderWithVarCount(bool withComponent, Scanner& in)
+  -> Order
+{
+  const auto varCount = in.readInteger<VarIndex>();
+  return readOrder(varCount, withComponent, in);
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::writeOrderWithVarCount(
+  const Order& order,
+  const bool withComponent,
+  std::ostream& out
+) {
+  out << order.varCount() << '\n';
+  writeOrder(order, withComponent, out);
+}
+
+template<class M, class BF>
+auto MathicIO<M, BF>::readOrder(
+  const VarIndex varCount,
+  const bool withComponent,
+  Scanner& in
+) -> Order {
+  const bool schreyering = in.match("schreyer");
+  bool lexBaseOrder = !in.match("revlex") && in.match("lex");
+
+  auto gradingCount = in.readInteger<VarIndex>();
+  bool componentsAscendingDesired = true;
+  auto componentCompareIndex = Order::ComponentAfterBaseOrder;
+  Gradings gradings;
+  gradings.reserve(static_cast<size_t>(varCount) * gradingCount);
+  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;
+    } else {
+      for (VarIndex i = 0; i < varCount; ++i)
+        gradings.emplace_back(in.readInteger<Exponent>());
+    }
+  }
+
+  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::LexBaseOrderFromRight : Order::RevLexBaseOrderFromRight,
+    componentCompareIndex,
+    componentsAscendingDesired,
+    schreyering
+  );
+  return std::move(order);
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::writeOrder(
+  const Order& order,
+  const bool withComponent,
+  std::ostream& out
+) {
+  MATHICGB_ASSERT(Monoid::HasComponent || !withComponent);
+
+  const auto baseOrder =
+    order.baseOrder() == Order::LexBaseOrderFromRight ? "lex" : "revlex";
+  const auto componentOrder =
+    order.componentsAscendingDesired() ? "component" : "revcomponent";
+
+  if (order.schreyering())
+    out << "schreyer ";
+  const bool componentLast =
+    order.componentBefore() == Order::ComponentAfterBaseOrder;
+  out << baseOrder << ' ' << order.gradingCount() + !componentLast << '\n';
+  for (VarIndex grading = 0; grading < order.gradingCount(); ++grading) {
+    if (withComponent && grading == order.componentBefore())
+      out << ' ' << componentOrder << '\n';
+    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.componentBefore() == order.gradingCount())
+    out << ' ' << componentOrder << '\n';
+
+  if (
+    withComponent &&
+    !order.componentsAscendingDesired() &&
+    order.componentBefore() == Order::ComponentAfterBaseOrder
+  ) {
+    out << " _" << baseOrder << "\n " << componentOrder << '\n';
+  }
+}
+
+template<class M, class BF>
+Basis MathicIO<M, BF>::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);
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::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';
+  }
+}
+
+template<class M, class BF>
+Poly MathicIO<M, BF>::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);
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::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
+    );
+  }
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::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);
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::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);
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::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);
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::readComponent(
+  const Monoid& monoid,
+  MonoRef mono,
+  Scanner& in
+) {
+  MATHICGB_ASSERT(Monoid::HasComponent);
+  in.expect('<');
+  monoid.setComponent(in.readInteger<Exponent>(), mono);
+  in.expect('>');
+}
+
+template<class M, class BF>
+void MathicIO<M, BF>::writeComponent(
+  const Monoid& monoid,
+  ConstMonoRef mono,
+  std::ostream& out
+) {
+  MATHICGB_ASSERT(Monoid::HasComponent);
+  out << '<' << unchar(monoid.component(mono)) << '>';
+}
+
+/// Print a monomial with no coefficient.
+template<class M, class BF>
+void MathicIO<M, BF>::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
 #endif
diff --git a/src/mathicgb/MonoMonoid.hpp b/src/mathicgb/MonoMonoid.hpp
index 54ebbf4..2471272 100755
--- a/src/mathicgb/MonoMonoid.hpp
+++ b/src/mathicgb/MonoMonoid.hpp
@@ -47,21 +47,29 @@ namespace MonoMonoidInternal {
 
     Base(const Order& order):
       mVarCount(order.varCount()),
-      mGradingCount(order.gradingCount()),
+      mGradingCount(
+        order.gradingCount() +
+          (order.componentBefore() != Order::ComponentAfterBaseOrder)
+      ),
       mOrderIndexBegin(HasComponent + order.varCount()),
-      mOrderIndexEnd(mOrderIndexBegin + StoreOrder * order.gradingCount()),
+      mOrderIndexEnd(mOrderIndexBegin + StoreOrder * mGradingCount),
       mEntryCount(std::max<VarIndex>(mOrderIndexEnd + StoreHash, 1)),
       mHashCoefficients(makeHashCoefficients(order.varCount())),
-      mOrderIsTotalDegreeRevLex
-        (!order.hasLexBaseOrder() && order.isTotalDegree()),
+      mOrderIsTotalDegreeRevLex(
+        !order.hasLexBaseOrder() &&
+        order.isTotalDegree() &&
+        order.componentBefore() == Order::ComponentAfterBaseOrder
+      ),
       mLexBaseOrder(order.hasLexBaseOrder()),
       mGradings(makeGradings(order)),
       mComponentGradingIndex(
-        reverseComponentGradingIndex
-          (order.gradingCount(), order.componentGradingIndex())
+        reverseComponentGradingIndex(mGradingCount, order.componentBefore())
       ),
       mVarsReversed(order.hasFromLeftBaseOrder())
-    {}
+    {
+      MATHICGB_ASSERT(order.isMonomialOrder());
+      MATHICGB_ASSERT(mGradings.size() == gradingCount() * varCount());
+    }
 
     VarIndex varCount() const {return mVarCount;}
     VarIndex gradingCount() const {return mGradingCount;}
@@ -79,6 +87,8 @@ namespace MonoMonoidInternal {
 
     static Gradings makeGradings(const Order& order) {
       auto gradings = order.gradings();
+      if (order.componentBefore() != Order::ComponentAfterBaseOrder)
+        insertZeroRow(order.varCount(), order.componentBefore(), gradings);
       reverseGradings(order.varCount(), gradings);
       if (order.hasFromLeftBaseOrder())
         reverseVarsInGradings(order.varCount(), gradings);
@@ -113,6 +123,35 @@ namespace MonoMonoidInternal {
         gradings[i] = -gradings[i];
     }
 
+    static void insertZeroRow(
+      const VarIndex varCount,
+      const size_t insertBeforeRow,
+      Gradings& gradings
+    ) {
+      if (varCount == 0)
+        return;
+      MATHICGB_ASSERT(gradings.size() % varCount == 0);
+      MATHICGB_ASSERT(insertBeforeRow <= gradings.size() / varCount);
+      gradings.resize(gradings.size() + varCount);
+      const auto rowBegin = gradings.begin() + insertBeforeRow * varCount;
+      std::copy_backward(rowBegin, gradings.end() - varCount, gradings.end());
+      std::fill_n(rowBegin, varCount, 0);
+    }
+
+    static void removeZeroRow(
+      const VarIndex varCount,
+      const size_t row,
+      Gradings& gradings
+    ) {
+      if (varCount == 0)
+        return;
+      MATHICGB_ASSERT(gradings.size() % varCount == 0);
+      MATHICGB_ASSERT(row < gradings.size() / varCount);
+      const auto rowBegin = gradings.begin() + row * varCount;
+      std::copy(rowBegin + varCount, gradings.end(), rowBegin);
+      gradings.resize(gradings.size() - varCount);
+    }
+
     /// Replace each row (e_0, e_1, ..., e_n) with (e_n, ..., e_1, e_0).
     static void reverseVarsInGradings(
       const size_t varCount,
@@ -377,13 +416,16 @@ public:
     reverseGradings(varCount(), orderGradings);
     if (!isLexBaseOrder())
       negateGradings(orderGradings);
+    const auto componentIndex = Base::reverseComponentGradingIndex
+      (gradingCount(), componentGradingIndex());
+    if (componentIndex != Order::ComponentAfterBaseOrder)
+      removeZeroRow(varCount(), componentIndex, orderGradings);
     return Order(
       varCount(),
       std::move(orderGradings),
       isLexBaseOrder() ?
         Order::LexBaseOrderFromRight : Order::RevLexBaseOrderFromRight,
-      Base::reverseComponentGradingIndex
-        (gradingCount(), componentGradingIndex()),
+      componentIndex,
       componentsAscendingDesired,
       schreyering
     );
diff --git a/src/mathicgb/MonoOrder.hpp b/src/mathicgb/MonoOrder.hpp
index 699a397..b15409c 100755
--- a/src/mathicgb/MonoOrder.hpp
+++ b/src/mathicgb/MonoOrder.hpp
@@ -39,24 +39,6 @@ public:
     RevLexBaseOrderFromLeft = 3
   };
 
-  /// Same as MonoOrder(varCount, varOrder, gradings, componentBefore)
-  /// where gradings has a single row of varCount 1's.
-  MonoOrder(
-    const VarIndex varCount,
-    const BaseOrder baseOrder = RevLexBaseOrderFromRight,
-    const size_t componentBefore = ComponentAfterBaseOrder,
-    const bool componentsAscendingDesired = true,
-    const bool schreyering = true
-  ):
-    mVarCount(varCount),
-    mGradings
-      (addComponentGrading(Gradings(varCount, 1), varCount, componentBefore)),
-    mBaseOrder(baseOrder),
-    mComponentGradingIndex(componentBefore),
-    mComponentsAscendingDesired(componentsAscendingDesired),
-    mSchreyering(schreyering)
-  {}
-
   /// The specified base order is graded by the gradings matrix.
   ///
   /// The layout of the gradings matrix is row-major. For comparisons,
@@ -75,20 +57,7 @@ public:
   /// - 1. If componentBefore == gradingCount(), then the component is
   /// considered after all gradings and before the base order. If
   /// componentBefore = ComponentAfterBaseOrder then the component is
-  /// considered after everything else.
-  ///
-  /// The ordering represented by this object will be equivalent to
-  /// the specified order, but it may be encoded differently. For
-  /// example, if varCount == 0, then all orders are equivalent so all
-  /// the other parameters are ignored and the encoding will be chosen
-  /// to be the minimal-overhead one: ungraded lex with component
-  /// considered last (do not depend on this particular choice - it
-  /// may change). Therefore, you cannot count on any setting of this
-  /// order to match what you passed in as a parameter.
-  ///
-  /// If the ordering you hav specified is not a monomial order, then
-  /// the only guarantee in terms of encoding is that isMonomialOrder
-  /// will return false.
+  /// considered after everything else, including afte the base order.
   MonoOrder(
     const VarIndex varCount,
     Gradings&& gradings,
@@ -100,23 +69,35 @@ public:
     mVarCount(varCount),
     mGradings(std::move(gradings)),
     mBaseOrder(baseOrder),
-    mComponentGradingIndex(componentBefore),
+    mComponentBefore(componentBefore),
     mComponentsAscendingDesired(componentsAscendingDesired),
     mSchreyering(schreyering)
   {
-#ifdef MATHCGB_DEBUG
-    // todo: fix this, it isn't checking the right row of the matrix
-    if (componentBefore != ComponentAfterBaseOrder) {
-      for (VarIndex var = 0; var < varCount(); ++var) {
-        MATHICGB_ASSERT(mGradings[var] == 0);
-      }
-    }
-#endif
+    MATHICGB_ASSERT(debugAssertValid());
+  }
+
+  /// Same as MonoOrder(varCount, varOrder, gradings, componentBefore)
+  /// where gradings has a single row of varCount 1's.
+  MonoOrder(
+    const VarIndex varCount,
+    const BaseOrder baseOrder = RevLexBaseOrderFromRight,
+    const size_t componentBefore = ComponentAfterBaseOrder,
+    const bool componentsAscendingDesired = true,
+    const bool schreyering = true
+  ):
+    mVarCount(varCount),
+    mGradings(varCount, 1),
+    mBaseOrder(baseOrder),
+    mComponentBefore(componentBefore),
+    mComponentsAscendingDesired(componentsAscendingDesired),
+    mSchreyering(schreyering)
+  {
+    MATHICGB_ASSERT(debugAssertValid());
   }
 
   VarIndex varCount() const {return mVarCount;}
 
-  VarIndex componentGradingIndex() const {return mComponentGradingIndex;}
+  VarIndex componentBefore() const {return mComponentBefore;}
 
   /// Returns the number of rows in the grading vector.
   size_t gradingCount() const {
@@ -159,20 +140,19 @@ public:
     for (VarIndex var = 0; var < varCount(); ++var) {
       // Check that x_var > 1.
       for (size_t grading = 0; ; ++grading) {
-        if (grading == gradingCount) {
+        if (grading == gradingCount()) {
           // The column was entirely zero, so x_var > 1 if and only if the
           // base ordering is lex.
           if (!hasLexBaseOrder())
             return false;
           break;
         }
-        const auto index = grading * gradingCount() + var;
+        const auto index = grading * varCount() + var;
         MATHICGB_ASSERT(index < mGradings.size());
-        const auto weight = mGradings[index];
-        if (weight != 0) {
+        if (mGradings[index] != 0) {
           // We have found the first non-zero weight in this column,
           // so x_var > 1 if and only if this weight is positive.
-          if (weight < 0)
+          if (mGradings[index] < 0)
             return false;
           break;
         }
@@ -185,27 +165,12 @@ public:
   bool schreyering() const {return mSchreyering;}
 
 private:
-  static Gradings addComponentGrading(
-    Gradings&& gradings,
-    const VarIndex varCount,
-    const VarIndex componentBefore
-  ) {
-    if (componentBefore == ComponentAfterBaseOrder)
-      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);
-  }
-
   bool debugAssertValid() {
 #ifdef MATHICGB_DEBUG
     MATHICGB_ASSERT(mGradings.size() == gradingCount() * varCount());
     MATHICGB_ASSERT(
-      mComponentGradingIndex == ComponentAfterBaseOrder ||
-      mComponentGradingIndex < gradingCount()
+      mComponentBefore == ComponentAfterBaseOrder ||
+      mComponentBefore <= gradingCount()
     );
     MATHICGB_ASSERT(
       mBaseOrder == LexBaseOrderFromLeft ||
@@ -213,11 +178,6 @@ private:
       mBaseOrder == LexBaseOrderFromRight ||
       mBaseOrder == RevLexBaseOrderFromRight 
     );
-    if (varCount() == 0) {
-      MATHICGB_ASSERT(mGradings.empty());
-      MATHICGB_ASSERT(baseOrder() == RevLexBaseOrderFromRight());
-      MATHICGB_ASSERT(mComponentGradingIndex == ComponentAfterBaseOrder);
-    }
 #endif
     return true;
   }
@@ -226,7 +186,7 @@ private:
 
   const Gradings mGradings;
   const BaseOrder mBaseOrder;
-  const size_t mComponentGradingIndex;
+  const size_t mComponentBefore;
   const bool mSchreyering;
   const bool mComponentsAscendingDesired;
 };
diff --git a/src/mathicgb/io-util.cpp b/src/mathicgb/io-util.cpp
index 053bd49..0475618 100755
--- a/src/mathicgb/io-util.cpp
+++ b/src/mathicgb/io-util.cpp
@@ -41,9 +41,9 @@ std::unique_ptr<Basis> basisParseFromString(std::string str)
 {
   std::istringstream inStream(str);
   Scanner in(inStream);
-  auto p = MathicIO().readRing(true, in);
+  auto p = MathicIO<>().readRing(true, in);
   auto& ring = *p.first.release(); // todo: fix leak
-  return make_unique<Basis>(MathicIO().readBasis(ring, false, in));
+  return make_unique<Basis>(MathicIO<>().readBasis(ring, false, in));
 }
 
 std::unique_ptr<PolyRing> ringFromString(std::string ringinfo)
diff --git a/src/test/MathicIO.cpp b/src/test/MathicIO.cpp
index 7bd7f10..5159497 100755
--- a/src/test/MathicIO.cpp
+++ b/src/test/MathicIO.cpp
@@ -18,9 +18,9 @@ TEST(MathicIO, Combined) {
     " -bc2+a2e\n";
   std::istringstream inStream(str);
   Scanner in(inStream);
-  auto p = MathicIO().readRing(true, in);
+  auto p = MathicIO<>().readRing(true, in);
   auto& ring = *p.first;
-  auto basis = MathicIO().readBasis(ring, false, in);
+  auto basis = MathicIO<>().readBasis(ring, false, in);
 }
 
 TEST(MathicIO, ReadWriteRing) {
@@ -43,14 +43,14 @@ TEST(MathicIO, ReadWriteRing) {
       if (str == 0)
         continue;
       Scanner in(str);
-      const auto p = MathicIO().readRing(withComponent, in);
+      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);
+      MathicIO<>().writeRing(*p.first, p.second, withComponent, out);
       ASSERT_EQ(outStr, out.str());
     }
   };
@@ -79,18 +79,18 @@ TEST(MathicIO, ReadWriteMonomial) {
   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 VarIndex var1,
+    const Exponent exp1,
+    const VarIndex var2,
+    const Exponent exp2,
+    const char* const canonicalStr
   ) {
     const bool doComponent = component != NoComponent;
 
     // read monomial from string
     auto monoRead = m.alloc();
     Scanner in(str);
-    MathicIO().readMonomial(m, doComponent, monoRead, in);
+    MathicIO<>().readMonomial(m, doComponent, monoRead, in);
 
     // directly make monomial
     auto monoSet = m.alloc();
@@ -104,25 +104,25 @@ TEST(MathicIO, ReadWriteMonomial) {
 
     // print monomial
     std::ostringstream out;
-    MathicIO().writeMonomial(m, doComponent, monoRead, 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("1", NoComponent,  -1,-1,  -1,-1,  0);
+  check("1<0>", 0,  -1,-1,  -1,-1,  0);
+  check("1<1>", 1,  -1,-1,  -1,-1,  0);
+  check("1<999>", 999,  -1,-1,  -1,-1,  0);
 
   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("b10<0>", 0,  1,10,  -1,-1,  0);
+  check("A11", NoComponent,  26,11, -1,-1,  0);
+  check("B99<1>", 1,   27,99,  -1,-1,  0);
 
-  check("ab", NoComponent,  0,1,  1,1);
+  check("ab", NoComponent,  0,1,  1,1,  0);
   check("ba", NoComponent,  0,1,  1,1,  "ab");
   check("a0c3b1", NoComponent,  1,1,  2,3,  "bc3");
-  check("ab<2>", 2,  0,1,  1,1);
+  check("ab<2>", 2,  0,1,  1,1,  0);
 }
 
 TEST(MathicIO, ReadWriteBasis) {
@@ -141,9 +141,9 @@ TEST(MathicIO, ReadWriteBasis) {
         continue;
 
       Scanner in(str);
-      const auto basis = MathicIO().readBasis(ring, doComponent, in);
+      const auto basis = MathicIO<>().readBasis(ring, doComponent, in);
       std::ostringstream out;
-      MathicIO().writeBasis(basis, doComponent, out);
+      MathicIO<>().writeBasis(basis, doComponent, out);
       const auto correctStr = outStr == 0 ? inStr : outStr;
       ASSERT_EQ(correctStr, out.str());
     }
@@ -175,9 +175,9 @@ TEST(MathicIO, ReadWritePoly) {
         continue;
 
       Scanner in(str);
-      const auto poly = MathicIO().readPoly(ring, doComponent, in);
+      const auto poly = MathicIO<>().readPoly(ring, doComponent, in);
       std::ostringstream out;
-      MathicIO().writePoly(poly, doComponent, out);
+      MathicIO<>().writePoly(poly, doComponent, out);
       const auto correctStr = outStr == 0 ? inStr : outStr;
       ASSERT_EQ(correctStr, out.str());
     }
@@ -224,13 +224,13 @@ TEST(MathicIO, ReadWriteTerm) {
       auto monoRead = m.alloc();
       Coefficient readCoef = f.zero();
       Scanner in(str);
-      MathicIO().readTerm(ring, doComponent, readCoef, monoRead, in);
+      MathicIO<>().readTerm(ring, doComponent, readCoef, monoRead, in);
       
       ASSERT_EQ(coef, readCoef.value());
 
       // print monomial
       std::ostringstream out;
-      MathicIO().writeTerm(ring, doComponent, readCoef, monoRead, out);
+      MathicIO<>().writeTerm(ring, doComponent, readCoef, monoRead, out);
       const auto correctStr = outStr == 0 ? inStr : outStr;
       ASSERT_EQ(correctStr, out.str());
     }
@@ -254,10 +254,10 @@ TEST(MathicIO, ReadWriteTerm) {
 
 TEST(MathicIO, ReadWriteBaseField) {
   Scanner in("101");
-  auto field = MathicIO().readBaseField(in);
+  auto field = MathicIO<>().readBaseField(in);
   ASSERT_EQ(101, field.charac());
   std::ostringstream out;
-  MathicIO().writeBaseField(field, out);
+  MathicIO<>().writeBaseField(field, out);
   ASSERT_EQ("101", out.str());
 }
 
@@ -270,9 +270,9 @@ TEST(MathicIO, ReadWriteOrder) {
     const char* const outStr,
     const VarIndex varCount,
     const VarIndex gradingCount,
-    const bool withComponent = false,
-    const bool componentsAscendingDesired = true,
-    const bool schreyering = false
+    const bool withComponent,
+    const bool componentsAscendingDesired,
+    const bool schreyering
   ) -> void {
     for (int i = 0; i < 2; ++i) {
       const char* str = i == 0 ? inStr : outStr;
@@ -280,34 +280,34 @@ TEST(MathicIO, ReadWriteOrder) {
         continue;
 
       Scanner in(str);
-      const auto order = MathicIO().readOrder(varCount, withComponent, in);
+      const auto order = MathicIO<>().readOrder(varCount, withComponent, in);
       ASSERT_EQ(varCount, order.varCount());
-      ASSERT_EQ(gradingCount, order.gradingCount());
+      ASSERT_EQ(gradingCount, order.gradingCount()) << inStr;
       ASSERT_EQ(componentsAscendingDesired, order.componentsAscendingDesired());
       ASSERT_EQ(schreyering, order.schreyering()) << inStr;
 
       std::ostringstream out;
-      MathicIO().writeOrder(order, withComponent, 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("0\n", "revlex 0\n", 0, 0,  0,1,0);
+  check("1\n 2\n", "revlex 1\n 2\n", 1, 1,  0,1,0);
+  check("2\n 3\n 4\n", "revlex 2\n 3\n 4\n", 1, 2,  0,1,0);
+  check("2\n 3 4\n 5 6\n", "revlex 2\n 3 4\n 5 6\n", 2, 2,  0,1,0);
+  check("1\n 1 1 1 1\n", "revlex 1\n 1 1 1 1\n", 4, 1,  0,1,0);
+
+  check("lex 0", "lex 0\n", 0, 0,  0,1,0);
+  check("lex 1 2", "lex 1\n 2\n", 1, 1,  0,1,0);
+  check("lex 2 3 4", "lex 2\n 3\n 4\n", 1, 2,  0,1,0);
+  check("lex 2 3 4 5 6", "lex 2\n 3 4\n 5 6\n", 2, 2,  0,1,0);
+  check("lex 1 1 1 1 1", "lex 1\n 1 1 1 1\n", 4, 1,  0,1,0);
+
+  check("2 component\n 5 6\n", "revlex 2\n component\n 5 6\n", 2, 1, 1, 1, 0);
+  check("2 3 4\nrevcomponent\n","revlex 2\n 3 4\n revcomponent\n",2, 1, 1,0,0);
+  check("lex 1 component", "lex 1\n component\n", 0, 0,  1, 1, 0);
+  check("lex 1 revcomponent", "lex 1\n revcomponent\n", 1, 0, 1, 0, 0);
+  check("lex 1 revcomponent", "lex 1\n revcomponent\n", 5, 0, 1, 0, 0);
 
   check(
     "schreyer lex 1 1 _revlex revcomponent",
diff --git a/src/test/MonoMonoid.cpp b/src/test/MonoMonoid.cpp
index f19c918..6576a4f 100755
--- a/src/test/MonoMonoid.cpp
+++ b/src/test/MonoMonoid.cpp
@@ -3,6 +3,7 @@
 #include "mathicgb/stdinc.h"
 #include "mathicgb/MonoMonoid.hpp"
 
+#include "mathicgb/MathicIO.hpp"
 #include <gtest/gtest.h>
 #include <sstream>
 
@@ -25,8 +26,8 @@ typedef ::testing::Types<
 > MonoidTypes;
 
 template <typename T>
-class Monoid : public ::testing::Test {};
-TYPED_TEST_CASE(Monoid, MonoidTypes);
+class Monoids : public ::testing::Test {};
+TYPED_TEST_CASE(Monoids, MonoidTypes);
 
 // expect(i,j) encodes a matrix with interesting bit patterns that
 // are supposed to be likely to surface errors in how monomials are
@@ -81,7 +82,7 @@ uint32 expect(size_t mono, size_t var, size_t varCount) {
   }
 };
 
-TYPED_TEST(Monoid, VarCount) {
+TYPED_TEST(Monoids, VarCount) {
   typedef TypeParam Monoid;
   ASSERT_EQ(0, Monoid(0).varCount());
   ASSERT_EQ(1000 * 1000, Monoid(1000 * 1000).varCount());
@@ -90,7 +91,7 @@ TYPED_TEST(Monoid, VarCount) {
   ASSERT_EQ(12, Monoid(12).varCount());
 }
 
-TYPED_TEST(Monoid, MonoVector) {
+TYPED_TEST(Monoids, MonoVector) {
   typedef TypeParam Monoid;
   typedef typename Monoid::VarIndex VarIndex;
   typedef typename Monoid::MonoVector MonoVector;
@@ -194,7 +195,7 @@ TYPED_TEST(Monoid, MonoVector) {
   ASSERT_TRUE(v.empty());
 }
 
-TYPED_TEST(Monoid, ReadWriteMonoid) {
+TYPED_TEST(Monoids, ReadWriteMonoid) {
   typedef TypeParam Monoid;
   typedef typename Monoid::VarIndex VarIndex;
 
@@ -209,15 +210,22 @@ TYPED_TEST(Monoid, ReadWriteMonoid) {
       if (str == 0)
         continue;
 
-      std::istringstream in(str);
-      const auto p = Monoid::readMonoid(in);
-      const auto& m = p.first;
-
+      std::istringstream inStream(str);
+      Scanner in(inStream);
+      const auto order = MathicIO<Monoid>().
+        readOrderWithVarCount(Monoid::HasComponent, in);
+      const Monoid monoid(order);
+      const auto constructedOrder =
+        monoid.makeOrder
+          (order.componentsAscendingDesired(), order.schreyering());
       std::ostringstream out;
-      m.printMonoid(p.second.first, out);
+      MathicIO<Monoid>().writeOrderWithVarCount
+        (constructedOrder, Monoid::HasComponent, out);
       ASSERT_EQ(outStr, out.str());
-      ASSERT_EQ(varCount, m.varCount());
-      ASSERT_EQ(gradingCount, m.gradingCount());
+      ASSERT_EQ(varCount, order.varCount());
+      ASSERT_EQ(varCount, monoid.varCount());
+      ASSERT_EQ(varCount, constructedOrder.varCount());
+      ASSERT_EQ(gradingCount, monoid.gradingCount());
     }
   };
   check("0 0\n", "0\nrevlex 0\n", 0, 0);
@@ -236,13 +244,13 @@ TYPED_TEST(Monoid, ReadWriteMonoid) {
     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("0 lex 1 component", "0\nlex 1\n component\n", 0, 1);
     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) {
+TYPED_TEST(Monoids, MonoPool) {
   typedef TypeParam Monoid;
   typedef typename Monoid::VarIndex VarIndex;
   typedef typename Monoid::Mono Mono;
@@ -315,7 +323,7 @@ namespace {
   }
 }
 
-TYPED_TEST(Monoid, ParsePrintM2) {
+TYPED_TEST(Monoids, ParsePrintM2) {
   typedef TypeParam Monoid;
   Monoid m(100);
   std::string str = "1 a z A Z ab a2 a2b ab2 a20b30";
@@ -388,7 +396,7 @@ TYPED_TEST(Monoid, ParsePrintM2) {
 }
 
 
-TYPED_TEST(Monoid, MultiplyDivide) {
+TYPED_TEST(Monoids, MultiplyDivide) {
   typedef TypeParam Monoid;
   Monoid m(49);
   typename Monoid::MonoPool pool(m);
@@ -511,7 +519,7 @@ TYPED_TEST(Monoid, MultiplyDivide) {
   check("abcdefghiV<7> ab2c3d4e5f6g7h8i9V11 a2b3c4d5e6f7g8h9i10V12<7>", true);
 }
 
-TYPED_TEST(Monoid, LcmColon) {
+TYPED_TEST(Monoids, LcmColon) {
   typedef TypeParam Monoid;
   Monoid mNonConst(49);
   auto& m = mNonConst;
@@ -582,7 +590,7 @@ TYPED_TEST(Monoid, LcmColon) {
   check("a6b7c8d9efghiV ab2c3d4e5f6g7h8i9V11 a6b7c8d9e5f6g7h8i9V11", false);
 }
 
-TYPED_TEST(Monoid, Order) {
+TYPED_TEST(Monoids, Order) {
   typedef TypeParam Monoid;
   typedef typename Monoid::Order Order;
   typedef typename Monoid::Exponent Exponent;
@@ -706,7 +714,7 @@ TYPED_TEST(Monoid, Order) {
   );
 }
 
-TYPED_TEST(Monoid, RelativelyPrime) {
+TYPED_TEST(Monoids, RelativelyPrime) {
   typedef TypeParam Monoid;
   Monoid m(49);
   typename Monoid::MonoPool pool(m);
@@ -727,7 +735,7 @@ TYPED_TEST(Monoid, RelativelyPrime) {
   check("fgh abcdef", false);
 }
 
-TYPED_TEST(Monoid, SetExponents) {
+TYPED_TEST(Monoids, SetExponents) {
   typedef TypeParam Monoid;
   typedef typename Monoid::VarIndex VarIndex;
   typedef typename Monoid::MonoVector MonoVector;
@@ -741,7 +749,7 @@ TYPED_TEST(Monoid, SetExponents) {
   }
 }
 
-TYPED_TEST(Monoid, HasAmpleCapacityTotalDegree) {
+TYPED_TEST(Monoids, HasAmpleCapacityTotalDegree) {
   typedef TypeParam Monoid;
   typedef typename Monoid::Order Order;
   typedef typename Monoid::Exponent Exponent;
@@ -804,7 +812,7 @@ TYPED_TEST(Monoid, HasAmpleCapacityTotalDegree) {
   }
 }
 
-TYPED_TEST(Monoid, CopyEqualConversion) {
+TYPED_TEST(Monoids, CopyEqualConversion) {
   typedef TypeParam Monoid;
   typedef typename Monoid::Order Order;
   typedef typename Monoid::Exponent Exponent;
diff --git a/src/test/Scanner.cpp b/src/test/Scanner.cpp
index d1aefd2..f689665 100755
--- a/src/test/Scanner.cpp
+++ b/src/test/Scanner.cpp
@@ -58,7 +58,7 @@ TEST(Scanner, ExpectTwoChars) {
 }
 
 TEST(Scanner, ExpectString) {
-  Scanner in{std::string(alphaSpaced)};
+  Scanner in(alphaSpaced);
   const auto size = sizeof(alphas) / sizeof(*alphas);
   for (size_t i = 0; i < size; ++i) {
     if (i % 2 == 0)
@@ -69,7 +69,7 @@ TEST(Scanner, ExpectString) {
 }
 
 TEST(Scanner, MatchString) {
-  Scanner in{std::string(alphaSpaced)};
+  Scanner in(alphaSpaced);
   const auto size = sizeof(alphas) / sizeof(*alphas);
   for (size_t i = 0; i < size; ++i) {
     ASSERT_FALSE(in.match("ef"));
diff --git a/src/test/gb-test.cpp b/src/test/gb-test.cpp
index cd5ce93..e3dbc2a 100755
--- a/src/test/gb-test.cpp
+++ b/src/test/gb-test.cpp
@@ -293,10 +293,10 @@ spairQueue	reducerType	divLookup	monTable	buchberger	postponeKoszul	useBaseDivis
     std::istringstream inStream(idealStr);
 
     Scanner in(inStream);
-    auto p = MathicIO().readRing(true, in);
+    auto p = MathicIO<>().readRing(true, in);
     auto& ring = *p.first;
     auto& processor = p.second;
-    auto basis = MathicIO().readBasis(ring, false, in);
+    auto basis = MathicIO<>().readBasis(ring, false, in);
     if (processor.schreyering())
       processor.setSchreyerMultipliers(basis);
 

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