[mathicgb] 313/393: Removed Basis::parse in favor of MathicIO. Added support for negative modular coefficients.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:27 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 bbb09cb9b7ed9e50758481a422bc15e80ccb8f11
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Tue May 7 01:12:09 2013 +0200

    Removed Basis::parse in favor of MathicIO. Added support for negative modular coefficients.
---
 Makefile.am                    |  11 +-
 src/cli/GBAction.cpp           |  16 +-
 src/cli/SigGBAction.cpp        |  17 +-
 src/mathicgb/Basis.cpp         |  35 +---
 src/mathicgb/Basis.hpp         |   9 -
 src/mathicgb/MathicIO.cpp      | 370 +++++++++++++++++++++++++++++++++++++++++
 src/mathicgb/MathicIO.hpp      | 367 +---------------------------------------
 src/mathicgb/MonoProcessor.hpp |  55 +++---
 src/mathicgb/Scanner.cpp       |  12 +-
 src/mathicgb/Scanner.hpp       |  34 ++++
 src/mathicgb/io-util.cpp       |  13 +-
 src/test/MathicIO.cpp          |  31 +++-
 src/test/Scanner.cpp           |  16 ++
 src/test/gb-test.cpp           |  42 +++--
 14 files changed, 546 insertions(+), 482 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index d913337..1375921 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -67,7 +67,8 @@ libmathicgb_la_SOURCES = src/mathicgb/BjarkeGeobucket2.cpp		\
   src/mathicgb/PrimeField.hpp src/mathicgb/MonoMonoid.hpp		\
   src/mathicgb/MonoProcessor.hpp src/mathicgb/MonoOrder.hpp		\
   src/mathicgb/Scanner.hpp src/mathicgb/Scanner.cpp			\
-  src/mathicgb/Unchar.hpp
+  src/mathicgb/Unchar.hpp src/mathicgb/MathicIO.hpp			\
+  src/mathicgb/MathicIO.cpp
 
 
 # The headers that libmathicgb installs.
@@ -88,11 +89,11 @@ bin_PROGRAMS = mgb
 
 # set up the console program. Listing the headers in sources ensure that
 # those files are included in distributions.
-mgb_SOURCES = src/cli/GBMain.cpp src/cli/CommonParams.hpp				\
+mgb_SOURCES = src/cli/GBMain.cpp src/cli/CommonParams.hpp		\
   src/cli/CommonParams.cpp src/cli/GBAction.hpp src/cli/GBAction.cpp	\
-  src/cli/GBCommonParams.hpp src/cli/GBCommonParams.cpp					\
-  src/cli/MatrixAction.cpp src/cli/MatrixAction.hpp						\
-  src/cli/SigGBAction.hpp src/cli/SigGBAction.cpp						\
+  src/cli/GBCommonParams.hpp src/cli/GBCommonParams.cpp			\
+  src/cli/MatrixAction.cpp src/cli/MatrixAction.hpp			\
+  src/cli/SigGBAction.hpp src/cli/SigGBAction.cpp			\
   src/cli/HelpAction.hpp src/cli/HelpAction.cpp
 mgb_LDADD = $(top_builddir)/libmathicgb.la $(DEPS_LIBS)
 
diff --git a/src/cli/GBAction.cpp b/src/cli/GBAction.cpp
index 85c3147..16b521b 100755
--- a/src/cli/GBAction.cpp
+++ b/src/cli/GBAction.cpp
@@ -5,6 +5,8 @@
 #include "mathicgb/Basis.hpp"
 #include "mathicgb/io-util.hpp"
 #include "mathicgb/F4Reducer.hpp"
+#include "mathicgb/Scanner.hpp"
+#include "mathicgb/MathicIO.hpp"
 #include <fstream>
 #include <iostream>
 
@@ -53,11 +55,11 @@ void GBAction::performAction() {
   std::ifstream inputFile(inputBasisFile.c_str());
   if (inputFile.fail())
     mic::reportError("Could not read input file \"" + inputBasisFile + '\n');
-  auto tuple = Basis::parse(inputFile);
-  auto& basis = std::get<1>(tuple);
 
-
-  std::unique_ptr<PolyRing const> ring(&(basis->ring()));
+  Scanner in(inputFile);
+  auto p = MathicIO().readRing(true, in);
+  auto& ring = *p.first;
+  auto basis = MathicIO().readBasis(ring, false, in);
 
   // run algorithm
   const auto reducerType = Reducer::reducerType(mGBParams.mReducer.value());
@@ -66,18 +68,18 @@ void GBAction::performAction() {
     reducerType != Reducer::Reducer_F4_Old &&
     reducerType != Reducer::Reducer_F4_New
   ) {
-    reducer = Reducer::makeReducer(reducerType, *ring);
+    reducer = Reducer::makeReducer(reducerType, ring);
   } else {
     const auto type = reducerType == Reducer::Reducer_F4_Old ?
       F4Reducer::OldType : F4Reducer::NewType;
-    auto f4Reducer = make_unique<F4Reducer>(*ring, type);
+    auto f4Reducer = make_unique<F4Reducer>(ring, type);
     if (mMinMatrixToStore.value() > 0)
       f4Reducer->writeMatricesTo(projectName, mMinMatrixToStore);
     reducer = std::move(f4Reducer);
   }
 
   BuchbergerAlg alg(
-    *basis,
+    basis,
     *reducer,
     mGBParams.mDivisorLookup.value(),
     mGBParams.mPreferSparseReducers.value(),
diff --git a/src/cli/SigGBAction.cpp b/src/cli/SigGBAction.cpp
index ce83dbe..f1d95a2 100755
--- a/src/cli/SigGBAction.cpp
+++ b/src/cli/SigGBAction.cpp
@@ -4,6 +4,8 @@
 #include "mathicgb/Basis.hpp"
 #include "mathicgb/SignatureGB.hpp"
 #include "mathicgb/io-util.hpp"
+#include "mathicgb/Scanner.hpp"
+#include "mathicgb/MathicIO.hpp"
 #include <fstream>
 #include <iostream>
 
@@ -44,14 +46,19 @@ void SigGBAction::performAction() {
   std::ifstream inputFile(inputBasisFile.c_str());
   if (inputFile.fail())
     mic::reportError("Could not read input file \"" + inputBasisFile + '\n');
-  auto tuple = Basis::parse(inputFile);
-  auto& basis = std::get<1>(tuple);
 
-  std::unique_ptr<PolyRing const> ring(&(basis->ring()));
+
+  Scanner in(inputFile);
+  auto p = MathicIO().readRing(true, in);
+  auto& ring = *p.first;
+  auto& processor = p.second;
+  auto basis = MathicIO().readBasis(ring, false, in);
+  if (processor.schreyering())
+    processor.setSchreyerMultipliers(basis);
 
   SignatureGB alg(
-    std::move(*basis),
-    std::move(*std::get<2>(tuple)),
+    std::move(basis),
+    std::move(processor),
     Reducer::reducerType(mGBParams.mReducer.value()),
     mGBParams.mDivisorLookup.value(),
     mGBParams.mMonomialTable.value(),
diff --git a/src/mathicgb/Basis.cpp b/src/mathicgb/Basis.cpp
index 508e16a..c381f13 100755
--- a/src/mathicgb/Basis.cpp
+++ b/src/mathicgb/Basis.cpp
@@ -4,6 +4,7 @@
 #include "PolyRing.hpp"
 #include "Poly.hpp"
 #include "FreeModuleOrder.hpp"
+#include "MathicIO.hpp"
 #include <ostream>
 #include <istream>
 #include <iostream>
@@ -37,40 +38,6 @@ void Basis::sort(FreeModuleOrder& order) {
   std::sort(mGenerators.begin(), mGenerators.end(), cmp);
 }
 
-auto Basis::parse(std::istream& in) -> Parsed
-{
-  auto r = PolyRing::read(in);
-  auto ring = make_unique<PolyRing>(std::move(*r.first));
-  delete r.first;
-
-  auto basis = make_unique<Basis>(*ring);
-  auto processor =
-    make_unique<MonoProcessor<Monoid>>(ring->monoid(), r.second.first, false);
-
-  size_t polyCount;
-  in >> polyCount;
-  for (size_t i = 0; i < polyCount; ++i) {
-    auto poly = make_unique<Poly>(*ring);
-    while (std::isspace(in.peek()))
-      in.get();
-    poly->parse(in);
-    basis->insert(std::move(poly));
-  }
-
-  if (r.second.second) {
-    Monoid::MonoVector schreyer(ring->monoid());
-    for (size_t gen = 0; gen < basis->size(); ++gen)
-      schreyer.push_back(basis->getPoly(gen)->getLeadMonomial());
-    processor->setModuleAdjustments(std::move(schreyer));
-  }
-
-  return std::make_tuple(
-    std::move(ring),
-    std::move(basis),
-    std::move(processor)
-  );
-}
-
 void Basis::display(std::ostream& out, bool printComponent, bool componentIncreasingDesired) const
 {
   mRing.write(out, componentIncreasingDesired);
diff --git a/src/mathicgb/Basis.hpp b/src/mathicgb/Basis.hpp
index 9c1b6b9..c8981b3 100755
--- a/src/mathicgb/Basis.hpp
+++ b/src/mathicgb/Basis.hpp
@@ -3,7 +3,6 @@
 
 #include "Poly.hpp"
 #include "PolyRing.hpp"
-#include "MonoProcessor.hpp"
 #include <tuple>
 #include <memory>
 #include <algorithm>
@@ -21,14 +20,6 @@ public:
 
   void insert(std::unique_ptr<Poly>&& p);
 
-  /// reads ring, #gens, each generator in turn
-  typedef std::tuple<
-    std::unique_ptr<PolyRing>,
-    std::unique_ptr<Basis>,
-    std::unique_ptr<MonoProcessor<PolyRing::Monoid>>
-  > Parsed;
-  static Parsed parse(std::istream &i);
-
   /// inverse operation to parse().
   void display(std::ostream &o, bool print_comp, bool componentIncreasingDesired) const;
 
diff --git a/src/mathicgb/MathicIO.cpp b/src/mathicgb/MathicIO.cpp
index 76b8486..2f0dd0d 100755
--- a/src/mathicgb/MathicIO.cpp
+++ b/src/mathicgb/MathicIO.cpp
@@ -1,3 +1,373 @@
 #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);
+}
diff --git a/src/mathicgb/MathicIO.hpp b/src/mathicgb/MathicIO.hpp
index 43dae37..6352ec3 100755
--- a/src/mathicgb/MathicIO.hpp
+++ b/src/mathicgb/MathicIO.hpp
@@ -41,7 +41,7 @@ public:
   BaseField readBaseField(Scanner& in);
   void writeBaseField(const BaseField& field, std::ostream& out);
 
-  std::pair<PolyRing, Processor> readRing(
+  std::pair<std::unique_ptr<PolyRing>, Processor> readRing(
     const bool withComponent,
     Scanner& in
   );
@@ -138,369 +138,4 @@ public:
   );
 };
 
-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<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();
-  PolyRing ring(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 = withComponent && in.match("component");
-    if (withComponent && (com || in.match("revcomponent"))) {
-      if (!Monoid::HasComponent)
-        in.reportError("Cannot specify component comparison for non-modules.");
-      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 = withComponent && in.match("component");
-    if (withComponent && (moreCom || in.match("revcomponent")))
-      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.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 = field.toElement(in.readInteger<RawCoefficient>(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);
-}
-
 #endif
diff --git a/src/mathicgb/MonoProcessor.hpp b/src/mathicgb/MonoProcessor.hpp
index 7f7c84e..854d8c2 100755
--- a/src/mathicgb/MonoProcessor.hpp
+++ b/src/mathicgb/MonoProcessor.hpp
@@ -1,6 +1,8 @@
 #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.
@@ -28,19 +30,29 @@ public:
     mComponentsAscendingDesired(componentsAscendingDesired),
     mComponentCount(0),
     mSchreyering(schreyering),
-    mModuleAdjustmentsMemory(monoid)
+    mSchreyerMultipliersMemory(monoid)
   {}
 
-  void setModuleAdjustments(MonoVector&& moduleAdjustments) {
+  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(mModuleAdjustmentsMemory.empty() ||
-      mModuleAdjustmentsMemory.size() == componentCount());
-    mModuleAdjustmentsMemory = std::move(moduleAdjustments);
+    MATHICGB_ASSERT(mSchreyerMultipliersMemory.empty() ||
+      mSchreyerMultipliersMemory.size() == componentCount());
+    mSchreyerMultipliersMemory = std::move(moduleAdjustments);
 
-    mModuleAdjustments.clear();
+    mSchreyerMultipliers.clear();
     for (
-      auto it = mModuleAdjustmentsMemory.begin();
-      it != mModuleAdjustmentsMemory.end();
+      auto it = mSchreyerMultipliersMemory.begin();
+      it != mSchreyerMultipliersMemory.end();
       ++it
     ) {
       // in the absence of a separate monoid for (non-module) monomials,
@@ -49,13 +61,13 @@ public:
 
       // todo: there should be a better way of indexing into a
       // MonoVector.
-      mModuleAdjustments.emplace_back((*it).ptr());
+      mSchreyerMultipliers.emplace_back((*it).ptr());
     }
   }
     
 
   void preprocess(MonoRef mono) const {
-    if (hasModuleAdjustments())
+    if (hasSchreyerMultipliers())
       monoid().multiplyInPlace(moduleAdjustment(mono), mono);
     if (needToReverseComponents())
       reverseComponent(mono);
@@ -64,14 +76,14 @@ public:
   void postprocess(MonoRef mono) const {
     if (needToReverseComponents())
       reverseComponent(mono);
-    if (hasModuleAdjustments()) {
+    if (hasSchreyerMultipliers()) {
       MATHICGB_ASSERT(monoid().divides(moduleAdjustment(mono), mono));
       monoid().divideInPlace(moduleAdjustment(mono), mono);
     }
   }
 
   bool processingNeeded() const {
-    return needToReverseComponents() || hasModuleAdjustments();
+    return needToReverseComponents() || hasSchreyerMultipliers();
   }
 
   bool needToReverseComponents() const {
@@ -84,16 +96,13 @@ public:
   }
   bool componentsAscendingDesired() const {return mComponentsAscendingDesired;}
 
-  bool hasModuleAdjustments() const {
-    return !mModuleAdjustments.empty();
+  bool hasSchreyerMultipliers() const {
+    return !mSchreyerMultipliers.empty();
   }
 
-  void setSchreyering(bool value) {mSchreyering = true;}
-  bool schreyering() const {return mSchreyering;}
-
   void setComponentCount(VarIndex count) {mComponentCount = count;}
   VarIndex componentCount() const {return mComponentCount;}
-  const Monoid& monoid() const {return mModuleAdjustmentsMemory.monoid();}
+  const Monoid& monoid() const {return mSchreyerMultipliersMemory.monoid();}
 
 private:
   void operator==(const MonoProcessor&) const; // not available
@@ -105,18 +114,18 @@ private:
   }
 
   ConstMonoRef moduleAdjustment(ConstMonoRef mono) const {
-    MATHICGB_ASSERT(hasModuleAdjustments());
+    MATHICGB_ASSERT(hasSchreyerMultipliers());
     const auto component = monoid().component(mono);
     MATHICGB_ASSERT(component < componentCount());
-    MATHICGB_ASSERT(mModuleAdjustments.size() == componentCount());
-    return *mModuleAdjustments[component];
+    MATHICGB_ASSERT(mSchreyerMultipliers.size() == componentCount());
+    return *mSchreyerMultipliers[component];
   }
 
   bool mComponentsAscendingDesired;
   VarIndex mComponentCount;
   bool mSchreyering;
-  MonoVector mModuleAdjustmentsMemory;
-  std::vector<ConstMonoPtr> mModuleAdjustments;
+  MonoVector mSchreyerMultipliersMemory;
+  std::vector<ConstMonoPtr> mSchreyerMultipliers;
 };
 
 #endif
diff --git a/src/mathicgb/Scanner.cpp b/src/mathicgb/Scanner.cpp
index caab861..cc67dff 100755
--- a/src/mathicgb/Scanner.cpp
+++ b/src/mathicgb/Scanner.cpp
@@ -15,12 +15,14 @@ static const size_t BufferSize =
 
 
 
-void reportSyntaxError(std::string s) {
-  mathic::reportError(s);
+void reportSyntaxError(std::string s, uint64 lineNumber) {
+  std::ostringstream out;
+  out << "Syntax error on line " << lineNumber << ": " << s;
+  mathic::reportError(out.str());
 }
 
 void Scanner::reportError(std::string msg) const {
-  reportSyntaxError(msg);
+  reportSyntaxError(msg, lineCount());
 }
 
 
@@ -72,7 +74,7 @@ bool Scanner::match(const char* const str) {
   eatWhite();
   MATHICGB_ASSERT(str != 0);
   const auto size = std::strlen(str);
-  if (!ensureBuffer(size - 1))
+  if (!ensureBuffer(size))
     return false;
   if (size == 0)
     return true;
@@ -157,7 +159,7 @@ void Scanner::reportErrorUnexpectedToken(
   if (got != "")
     errorMsg << ", but got " << got;
   errorMsg << '.';
-  reportSyntaxError(errorMsg.str());
+  reportError(errorMsg.str());
 }
 
 bool Scanner::readBuffer(size_t minRead) {
diff --git a/src/mathicgb/Scanner.hpp b/src/mathicgb/Scanner.hpp
index e3e7c05..fdbdc0f 100755
--- a/src/mathicgb/Scanner.hpp
+++ b/src/mathicgb/Scanner.hpp
@@ -1,10 +1,12 @@
 #ifndef MATHICGB_SCANNER_GUARD
 #define MATHICGB_SCANNER_GUARD
 
+#include "PrimeField.hpp"
 #include "Unchar.hpp"
 #include <string>
 #include <cstdio>
 #include <vector>
+#include <type_traits>
 #include <limits>
 #include <sstream>
 #include <istream>
@@ -87,6 +89,12 @@ public:
   template<class T>
   T readInteger(bool negate = false);
 
+  template<class T>
+  typename PrimeField<T>::Element readModular(
+    const PrimeField<T>& field,
+    const bool negate = false
+  );
+
   /// Reads a T if it is there. Does not recognize + or - as the start
   /// of an integer.
   template<class T>
@@ -105,6 +113,10 @@ public:
   /// whitespace. Whitespace is defined by std::isspace().
   bool peekWhite() {return isspace(peek());}
 
+  /// Returns true if the next character is + or -. Does not skip
+  /// whitespace.
+  bool peekSign() {return peek() == '+' || peek() == '-';}
+
   /// Returns the number of newlines seen plus one. Does not skip
   /// whitespace.
   uint64 lineCount() const {return mLineCount;}
@@ -185,6 +197,8 @@ inline void Scanner::ignore(size_t count) {
     get();
 }
 
+
+
 template<class T>
 T Scanner::readInteger(const bool negate) {
   static_assert(std::numeric_limits<T>::is_integer, "");
@@ -228,6 +242,26 @@ T Scanner::readInteger(const bool negate) {
 }
 
 template<class T>
+typename PrimeField<T>::Element Scanner::readModular(
+  const PrimeField<T>& field,
+  const bool negate
+) {
+  static_assert(std::numeric_limits<T>::is_integer, "");
+
+  // Otherwise we need to consider that the most negative value's
+  // negative cannot be represented as a positive number when reading.
+  static_assert(!std::is_signed<T>::value, "");
+
+  eatWhite();
+  const bool minus = !match('+') && match('-');
+  const bool positive = minus == negate;
+  if (!peekDigit())
+    reportErrorUnexpectedToken("an integer", "");
+  const auto e = field.toElement(readInteger<T>(false));
+  return positive ? e : field.negative(e);
+}
+
+template<class T>
 bool Scanner::matchReadIntegerNoSign(T& t, bool negate) {
   if (peekDigit()) {
     t = readInteger<T>(negate);
diff --git a/src/mathicgb/io-util.cpp b/src/mathicgb/io-util.cpp
index c1d5dfc..cc33a51 100755
--- a/src/mathicgb/io-util.cpp
+++ b/src/mathicgb/io-util.cpp
@@ -8,6 +8,8 @@
 #include "Poly.hpp"
 #include "MTArray.hpp"
 #include "io-util.hpp"
+#include "Scanner.hpp"
+#include "MathicIO.hpp"
 
 #include "PolyHeap.hpp"
 #include "PolyGeoBucket.hpp"
@@ -35,12 +37,11 @@ std::string toString(const Poly *g)
 
 std::unique_ptr<Basis> basisParseFromString(std::string str)
 {
-  // todo: fix the leak
-  std::istringstream in(str);
-  auto t = Basis::parse(in);
-  std::get<0>(t).release();
-  std::get<2>(t).release();
-  return std::move(std::get<1>(t));
+  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)
diff --git a/src/test/MathicIO.cpp b/src/test/MathicIO.cpp
index ca82054..f3663fa 100755
--- a/src/test/MathicIO.cpp
+++ b/src/test/MathicIO.cpp
@@ -3,6 +3,22 @@
 
 #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;
@@ -23,13 +39,14 @@ TEST(MathicIO, ReadWriteRing) {
       if (str == 0)
         continue;
       Scanner in(str);
-      auto p = MathicIO().readRing(withComponent, in);
-      auto& monoid = p.first.monoid();
-      ASSERT_EQ(charac, p.first.field().charac());
+      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());
     }
   };
@@ -216,6 +233,7 @@ TEST(MathicIO, ReadWriteTerm) {
   };
 
   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);
@@ -224,6 +242,7 @@ TEST(MathicIO, ReadWriteTerm) {
   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);
@@ -287,8 +306,8 @@ TEST(MathicIO, ReadWriteOrder) {
   check("lex 1 revcomponent", "lex 1\n revcomponent\n", 5, 1, 1, 0, 0);
 
   check(
-    "schreyer lex 1 1 _lex revcomponent",
-    "schreyer lex 1\n 1\n _lex\n revcomponent\n",
+    "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/Scanner.cpp b/src/test/Scanner.cpp
index bca051f..d1dcf98 100755
--- a/src/test/Scanner.cpp
+++ b/src/test/Scanner.cpp
@@ -74,6 +74,22 @@ TEST(Scanner, MatchString) {
   }
 }
 
+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);
diff --git a/src/test/gb-test.cpp b/src/test/gb-test.cpp
index 1a5c3a8..8384432 100755
--- a/src/test/gb-test.cpp
+++ b/src/test/gb-test.cpp
@@ -12,6 +12,8 @@
 #include "mathicgb/SignatureGB.hpp"
 #include "mathicgb/BuchbergerAlg.hpp"
 #include "mathicgb/mtbb.hpp"
+#include "mathicgb/MathicIO.hpp"
+#include "mathicgb/Scanner.hpp"
 #include "test/ideals.hpp"
 
 #include <cstdio>
@@ -287,21 +289,29 @@ spairQueue	reducerType	divLookup	monTable	buchberger	postponeKoszul	useBaseDivis
     Reducer::ReducerType red = Reducer::ReducerType(reducerType);
     MATHICGB_ASSERT(static_cast<int>(red) == reducerType);
 
+    std::istringstream inStream(idealStr);
 
-    std::istringstream in(idealStr);
-    auto tuple = Basis::parse(in);
-    auto& I = std::get<1>(tuple);
+    Scanner in(inStream);
+    auto p = MathicIO().readRing(true, in);
+    auto& ring = *p.first;
+    auto& processor = p.second;
+    auto basis = MathicIO().readBasis(ring, false, in);
+    if (processor.schreyering())
+      processor.setSchreyerMultipliers(basis);
 
-    MATHICGB_ASSERT
-      (Reducer::makeReducerNullOnUnknown(red, I->ring()).get() != 0);
+    MATHICGB_ASSERT(Reducer::makeReducerNullOnUnknown(red, ring).get() != 0);
 
     mgb::tbb::task_scheduler_init scheduler(threadCount);
     if (buchberger) {
       const auto reducer = Reducer::makeReducer
-        (Reducer::reducerType(reducerType), I->ring());
-      BuchbergerAlg alg
-        (*I, *reducer,
-         divLookup, preferSparseReducers, spairQueue);
+        (Reducer::reducerType(reducerType), ring);
+      BuchbergerAlg alg(
+        std::move(basis),
+        *reducer,
+        divLookup,
+        preferSparseReducers,
+        spairQueue
+      );
       alg.setUseAutoTopReduction(autoTopReduce);
       alg.setUseAutoTailReduction(autoTailReduce);
       alg.setSPairGroupSize(sPairGroupSize);
@@ -312,9 +322,9 @@ spairQueue	reducerType	divLookup	monTable	buchberger	postponeKoszul	useBaseDivis
         << reducerType << ' ' << divLookup << ' '
         << monTable << ' ' << postponeKoszul << ' ' << useBaseDivisors;
     } else {
-      SignatureGB basis(
-        std::move(*I),
-        std::move(*std::get<2>(tuple)),
+      SignatureGB alg(
+        std::move(basis),
+        std::move(processor),
         Reducer::reducerType(reducerType),
         divLookup,
         monTable,
@@ -324,16 +334,16 @@ spairQueue	reducerType	divLookup	monTable	buchberger	postponeKoszul	useBaseDivis
         useSingularCriterionEarly,
         spairQueue
       );
-      basis.computeGrobnerBasis();
-      EXPECT_EQ(sigBasisStr, toString(basis.getGB(), 1))
+      alg.computeGrobnerBasis();
+      EXPECT_EQ(sigBasisStr, toString(alg.getGB(), 1))
         << reducerType << ' ' << divLookup << ' '
         << monTable << ' ' << ' ' << postponeKoszul << ' '
         << useBaseDivisors;
-      EXPECT_EQ(syzygiesStr, toString(basis.getSyzTable()))
+      EXPECT_EQ(syzygiesStr, toString(alg.getSyzTable()))
         << reducerType << ' ' << divLookup << ' '
         << monTable << ' ' << ' ' << postponeKoszul << ' '
         << useBaseDivisors;
-      EXPECT_EQ(nonSingularReductions, basis.getSigReductionCount() - basis.getSingularReductionCount())
+      EXPECT_EQ(nonSingularReductions, alg.getSigReductionCount() - alg.getSingularReductionCount())
         << reducerType << ' ' << divLookup << ' '
         << monTable << ' ' << ' ' << postponeKoszul << ' '
         << useBaseDivisors;

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