[mathicgb] 307/393: Adding new external-to-MonoMonoid IO class MathicIO along with tests.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:26 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 613868a7c2315aefadfcf81c685edee0db2a5476
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Sun May 5 14:48:27 2013 +0200

    Adding new external-to-MonoMonoid IO class MathicIO along with tests.
---
 Makefile.am                    | 114 +++++-----
 src/mathicgb/Basis.cpp         |   4 +-
 src/mathicgb/MathicIO.cpp      |   3 +
 src/mathicgb/MathicIO.hpp      | 489 +++++++++++++++++++++++++++++++++++++++++
 src/mathicgb/MonoMonoid.hpp    |  42 +++-
 src/mathicgb/MonoOrder.hpp     |  24 +-
 src/mathicgb/MonoProcessor.hpp |  13 +-
 src/mathicgb/PrimeField.hpp    |   3 +
 src/mathicgb/Scanner.cpp       |   3 +-
 src/test/MathicIO.cpp          | 171 ++++++++++++++
 10 files changed, 798 insertions(+), 68 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 46ca9be..d913337 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,59 +13,61 @@ libmathicgb_la_LIBADD= $(DEPS_LIBS)
 
 # the sources that are built to make libmathicgb. Listing the headers in
 # sources ensure that those files are included in distributions.
-libmathicgb_la_SOURCES = src/mathicgb/BjarkeGeobucket2.cpp				\
+libmathicgb_la_SOURCES = src/mathicgb/BjarkeGeobucket2.cpp		\
   src/mathicgb/BjarkeGeobucket2.hpp src/mathicgb/BjarkeGeobucket.cpp	\
-  src/mathicgb/BjarkeGeobucket.hpp src/mathicgb/BuchbergerAlg.cpp		\
-  src/mathicgb/BuchbergerAlg.hpp src/mathicgb/ChainedHashTable.cpp		\
-  src/mathicgb/ChainedHashTable.hpp src/mathicgb/DivisorLookup.hpp		\
-  src/mathicgb/DivisorLookup.cpp src/mathicgb/DivLookup.hpp				\
-  src/mathicgb/FreeModuleOrder.cpp src/mathicgb/FreeModuleOrder.hpp		\
-  src/mathicgb/GroebnerBasis.cpp src/mathicgb/GroebnerBasis.hpp			\
-  src/mathicgb/HashTourReducer.cpp src/mathicgb/HashTourReducer.hpp		\
-  src/mathicgb/Basis.cpp src/mathicgb/Basis.hpp							\
-  src/mathicgb/io-util.cpp src/mathicgb/io-util.hpp						\
-  src/mathicgb/KoszulQueue.cpp src/mathicgb/KoszulQueue.hpp				\
+  src/mathicgb/BjarkeGeobucket.hpp src/mathicgb/BuchbergerAlg.cpp	\
+  src/mathicgb/BuchbergerAlg.hpp src/mathicgb/ChainedHashTable.cpp	\
+  src/mathicgb/ChainedHashTable.hpp src/mathicgb/DivisorLookup.hpp	\
+  src/mathicgb/DivisorLookup.cpp src/mathicgb/DivLookup.hpp		\
+  src/mathicgb/FreeModuleOrder.cpp src/mathicgb/FreeModuleOrder.hpp	\
+  src/mathicgb/GroebnerBasis.cpp src/mathicgb/GroebnerBasis.hpp		\
+  src/mathicgb/HashTourReducer.cpp src/mathicgb/HashTourReducer.hpp	\
+  src/mathicgb/Basis.cpp src/mathicgb/Basis.hpp				\
+  src/mathicgb/io-util.cpp src/mathicgb/io-util.hpp			\
+  src/mathicgb/KoszulQueue.cpp src/mathicgb/KoszulQueue.hpp		\
   src/mathicgb/MonomialHashTable.hpp src/mathicgb/MonTableDivList.hpp	\
-  src/mathicgb/MonTableKDTree.hpp src/mathicgb/MonTableNaive.cpp		\
-  src/mathicgb/MonTableNaive.hpp src/mathicgb/MTArray.cpp				\
-  src/mathicgb/MTArray.hpp src/mathicgb/PairTriangle.cpp				\
-  src/mathicgb/PairTriangle.hpp src/mathicgb/Poly.cpp					\
-  src/mathicgb/Poly.hpp src/mathicgb/PolyBasis.cpp						\
-  src/mathicgb/PolyBasis.hpp src/mathicgb/PolyGeoBucket.cpp				\
-  src/mathicgb/PolyGeoBucket.hpp src/mathicgb/PolyHashReducer.cpp		\
-  src/mathicgb/PolyHashReducer.hpp src/mathicgb/PolyHashTable.cpp		\
-  src/mathicgb/PolyHashTable.hpp src/mathicgb/PolyHeap.cpp				\
-  src/mathicgb/PolyHeap.hpp src/mathicgb/PolyReducer.cpp				\
-  src/mathicgb/PolyReducer.hpp src/mathicgb/PolyRing.cpp				\
-  src/mathicgb/PolyRing.hpp src/mathicgb/Reducer.cpp					\
-  src/mathicgb/Reducer.hpp src/mathicgb/ReducerDedup.hpp				\
-  src/mathicgb/ReducerHash.hpp src/mathicgb/ReducerHashPack.hpp			\
-  src/mathicgb/ReducerHelper.hpp src/mathicgb/ReducerNoDedup.hpp		\
-  src/mathicgb/ReducerPack.hpp src/mathicgb/ReducerPackDedup.hpp		\
-  src/mathicgb/SignatureGB.cpp src/mathicgb/SignatureGB.hpp				\
-  src/mathicgb/SigSPairs.cpp src/mathicgb/SigSPairs.hpp					\
-  src/mathicgb/SPairs.cpp src/mathicgb/SPairs.hpp						\
-  src/mathicgb/stdinc.h src/mathicgb/TournamentReducer.cpp				\
-  src/mathicgb/TournamentReducer.hpp src/mathicgb/SigSPairQueue.hpp		\
-  src/mathicgb/SigSPairQueue.cpp src/mathicgb/SparseMatrix.hpp			\
-  src/mathicgb/SparseMatrix.cpp src/mathicgb/QuadMatrixBuilder.hpp		\
+  src/mathicgb/MonTableKDTree.hpp src/mathicgb/MonTableNaive.cpp	\
+  src/mathicgb/MonTableNaive.hpp src/mathicgb/MTArray.cpp		\
+  src/mathicgb/MTArray.hpp src/mathicgb/PairTriangle.cpp		\
+  src/mathicgb/PairTriangle.hpp src/mathicgb/Poly.cpp			\
+  src/mathicgb/Poly.hpp src/mathicgb/PolyBasis.cpp			\
+  src/mathicgb/PolyBasis.hpp src/mathicgb/PolyGeoBucket.cpp		\
+  src/mathicgb/PolyGeoBucket.hpp src/mathicgb/PolyHashReducer.cpp	\
+  src/mathicgb/PolyHashReducer.hpp src/mathicgb/PolyHashTable.cpp	\
+  src/mathicgb/PolyHashTable.hpp src/mathicgb/PolyHeap.cpp		\
+  src/mathicgb/PolyHeap.hpp src/mathicgb/PolyReducer.cpp		\
+  src/mathicgb/PolyReducer.hpp src/mathicgb/PolyRing.cpp		\
+  src/mathicgb/PolyRing.hpp src/mathicgb/Reducer.cpp			\
+  src/mathicgb/Reducer.hpp src/mathicgb/ReducerDedup.hpp		\
+  src/mathicgb/ReducerHash.hpp src/mathicgb/ReducerHashPack.hpp		\
+  src/mathicgb/ReducerHelper.hpp src/mathicgb/ReducerNoDedup.hpp	\
+  src/mathicgb/ReducerPack.hpp src/mathicgb/ReducerPackDedup.hpp	\
+  src/mathicgb/SignatureGB.cpp src/mathicgb/SignatureGB.hpp		\
+  src/mathicgb/SigSPairs.cpp src/mathicgb/SigSPairs.hpp			\
+  src/mathicgb/SPairs.cpp src/mathicgb/SPairs.hpp			\
+  src/mathicgb/stdinc.h src/mathicgb/TournamentReducer.cpp		\
+  src/mathicgb/TournamentReducer.hpp src/mathicgb/SigSPairQueue.hpp	\
+  src/mathicgb/SigSPairQueue.cpp src/mathicgb/SparseMatrix.hpp		\
+  src/mathicgb/SparseMatrix.cpp src/mathicgb/QuadMatrixBuilder.hpp	\
   src/mathicgb/QuadMatrixBuilder.cpp src/mathicgb/TypicalReducer.cpp	\
-  src/mathicgb/TypicalReducer.hpp src/mathicgb/F4Reducer.hpp			\
-  src/mathicgb/F4Reducer.cpp src/mathicgb/F4MatrixBuilder.hpp			\
-  src/mathicgb/F4MatrixBuilder.cpp src/mathicgb/QuadMatrix.hpp			\
-  src/mathicgb/QuadMatrix.cpp src/mathicgb/F4MatrixReducer.cpp			\
-  src/mathicgb/F4MatrixReducer.hpp src/mathicgb/MonomialMap.hpp			\
-  src/mathicgb/RawVector.hpp src/mathicgb/Atomic.hpp					\
-  src/mathicgb/FixedSizeMonomialMap.hpp src/mathicgb/CFile.hpp			\
-  src/mathicgb/CFile.cpp src/mathicgb/LogDomain.hpp						\
-  src/mathicgb/LogDomain.cpp src/mathicgb/LogDomainSet.hpp				\
+  src/mathicgb/TypicalReducer.hpp src/mathicgb/F4Reducer.hpp		\
+  src/mathicgb/F4Reducer.cpp src/mathicgb/F4MatrixBuilder.hpp		\
+  src/mathicgb/F4MatrixBuilder.cpp src/mathicgb/QuadMatrix.hpp		\
+  src/mathicgb/QuadMatrix.cpp src/mathicgb/F4MatrixReducer.cpp		\
+  src/mathicgb/F4MatrixReducer.hpp src/mathicgb/MonomialMap.hpp		\
+  src/mathicgb/RawVector.hpp src/mathicgb/Atomic.hpp			\
+  src/mathicgb/FixedSizeMonomialMap.hpp src/mathicgb/CFile.hpp		\
+  src/mathicgb/CFile.cpp src/mathicgb/LogDomain.hpp			\
+  src/mathicgb/LogDomain.cpp src/mathicgb/LogDomainSet.hpp		\
   src/mathicgb/F4MatrixBuilder2.hpp src/mathicgb/F4MatrixBuilder2.cpp	\
-  src/mathicgb/LogDomainSet.cpp src/mathicgb/F4ProtoMatrix.hpp			\
-  src/mathicgb/F4ProtoMatrix.cpp src/mathicgb/F4MatrixProject.hpp		\
-  src/mathicgb/F4MatrixProjection.cpp src/mathicgb/ScopeExit.hpp		\
-  src/mathicgb.cpp src/mathicgb.h src/mathicgb/mtbb.hpp					\
-  src/mathicgb/PrimeField.hpp src/mathicgb/MonoMonoid.hpp				\
-  src/mathicgb/MonoProcessor.hpp src/mathicgb/MonoOrder.hpp
+  src/mathicgb/LogDomainSet.cpp src/mathicgb/F4ProtoMatrix.hpp		\
+  src/mathicgb/F4ProtoMatrix.cpp src/mathicgb/F4MatrixProject.hpp	\
+  src/mathicgb/F4MatrixProjection.cpp src/mathicgb/ScopeExit.hpp	\
+  src/mathicgb.cpp src/mathicgb.h src/mathicgb/mtbb.hpp			\
+  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
 
 
 # The headers that libmathicgb installs.
@@ -103,12 +105,14 @@ check_PROGRAMS=$(TESTS)
 unittest_LDADD = $(DEPS_LIBS) $(top_builddir)/libmathicgb.la
 
 test_LIBS=
-unittest_SOURCES=src/test/FreeModuleOrderTest.cpp						\
-  src/test/gtestInclude.cpp src/test/testMain.cpp src/test/gb-test.cpp	\
-  src/test/ideals.cpp src/test/poly-test.cpp src/test/ideals.hpp		\
-  src/test/SparseMatrix.cpp src/test/QuadMatrixBuilder.cpp				\
-  src/test/F4MatrixBuilder.cpp src/test/F4MatrixReducer.cpp             \
-  src/test/mathicgb.cpp src/test/PrimeField.cpp src/test/MonoMonoid.cpp
+unittest_SOURCES=src/test/FreeModuleOrderTest.cpp			\
+  src/test/gtestInclude.cpp src/test/testMain.cpp			\
+  src/test/gb-test.cpp src/test/ideals.cpp src/test/poly-test.cpp	\
+  src/test/ideals.hpp src/test/SparseMatrix.cpp				\
+  src/test/QuadMatrixBuilder.cpp src/test/F4MatrixBuilder.cpp		\
+  src/test/F4MatrixReducer.cpp src/test/mathicgb.cpp			\
+  src/test/PrimeField.cpp src/test/MonoMonoid.cpp			\
+  src/test/Scanner.cpp src/test/MathicIO.cpp
 
 else
 
diff --git a/src/mathicgb/Basis.cpp b/src/mathicgb/Basis.cpp
index 0e3665c..7b1048e 100755
--- a/src/mathicgb/Basis.cpp
+++ b/src/mathicgb/Basis.cpp
@@ -48,8 +48,8 @@ auto Basis::parse(std::istream& in) -> Parsed
   delete r.first;
 
   auto basis = make_unique<Basis>(*ring);
-  auto processor = make_unique<MonoProcessor<Monoid>>(ring->monoid());
-  processor->setComponentsAscendingDesired(r.second.first);
+  auto processor =
+    make_unique<MonoProcessor<Monoid>>(ring->monoid(), r.second.first, false);
 
   size_t polyCount;
   in >> polyCount;
diff --git a/src/mathicgb/MathicIO.cpp b/src/mathicgb/MathicIO.cpp
new file mode 100755
index 0000000..76b8486
--- /dev/null
+++ b/src/mathicgb/MathicIO.cpp
@@ -0,0 +1,3 @@
+#include "stdinc.h"
+#include "MathicIO.hpp"
+
diff --git a/src/mathicgb/MathicIO.hpp b/src/mathicgb/MathicIO.hpp
new file mode 100755
index 0000000..ba57efd
--- /dev/null
+++ b/src/mathicgb/MathicIO.hpp
@@ -0,0 +1,489 @@
+#ifndef MATHICGB_MATHIC_IO_GUARD
+#define MATHICGB_MATHIC_IO_GUARD
+
+#include "Scanner.hpp"
+#include "PolyRing.hpp"
+#include "MonoProcessor.hpp"
+#include <ostream>
+#include <string>
+
+/// Class for input and output in Mathic's format.
+class MathicIO {
+public:
+  typedef PolyRing::Field BaseField;
+  typedef BaseField::Element Coefficient;
+  typedef BaseField::RawElement RawCoefficient;
+
+  typedef PolyRing::Monoid Monoid;
+  typedef Monoid::MonoRef MonoRef;
+  typedef Monoid::Exponent Exponent;
+  typedef Monoid::VarIndex VarIndex;
+  typedef Monoid::ConstMonoRef ConstMonoRef;
+  typedef Monoid::Order Order;
+  typedef MonoProcessor<Monoid> Processor;
+
+  typedef Order::Gradings Gradings;
+
+/*
+  /// reads ring, #gens, each generator in turn
+  typedef std::tuple<
+    std::unique_ptr<PolyRing>,
+    std::unique_ptr<Basis>,
+    std::unique_ptr<MonoProcessor<PolyRing::Monoid>>
+  > BasisData;
+  BasisData readBasis();
+
+
+
+*/
+  BaseField readBaseField(Scanner& in);
+  void writeBaseField(const BaseField& field, std::ostream& out);
+
+  std::pair<PolyRing, Processor> readRing(
+    const bool withComponent,
+    Scanner& in
+  );
+  void writeRing(
+    const PolyRing& ring,
+    const Processor& processor,
+    const bool withComponent,
+    std::ostream& out
+  );
+
+  Order readOrder(
+    const VarIndex varCount,
+    const bool withComponent,
+    Scanner& in
+  );
+
+  void writeOrder(
+    const Order& order,
+    const bool withComponent,
+    std::ostream& out
+  );
+
+  void readTerm(
+    const PolyRing& ring,
+    const bool readComponent,
+    Coefficient& coef,
+    MonoRef mono,
+    Scanner& in
+  );
+
+  /// Read a monomial with no coefficient. A 1 on its own is not
+  /// considered a coefficient here - it is the monomial with all
+  /// exponents zero and no coefficient.
+  ///
+  /// @todo: Eventually, pick up readComponent from Monoid::HasComponent.
+  void readMonomial(
+    const Monoid& monoid,
+    const bool readComponent,
+    MonoRef mono,
+    Scanner& in
+  );
+
+  /// Read the trailing indicator of the component of a module monomial.
+  void readComponent(
+    const Monoid& monoid,
+    MonoRef mono,
+    Scanner& in
+  );
+
+  /// Print a monomial with no coefficient.
+  void writeMonomial(
+    const Monoid& monoid,
+    const bool writeComponent,
+    ConstMonoRef mono,
+    std::ostream& out
+  );
+};
+
+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';
+  }
+}
+
+/*
+auto MathicIO::readBasis() -> BasisData {
+  typedef PolyRing::Monoid Monoid;
+  typedef Monoid::VarIndex VarIndex;
+  typedef Monoid::Gradings Gradings;
+
+  // ** Read prime field
+  const auto charac = mIn.readInteger<coefficient>();
+
+  // ** Read 
+  const auto varCount = mIn.readInteger<VarIndex>();
+  const bool doSchreyer = mIn.match("schreyer");
+
+  bool lexBaseOrder = false;
+  if (mIn.match("lex"))
+    lexBaseOrder = true;
+  else if (mIn.match("revlex"))
+    lexBaseOrder = false;
+
+  const auto gradingCount = mIn.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 = mIn.match("component");
+    const bool revcom = !com && mIn.match("revcomponent");
+    if (com || revcom) {
+      if (!HasComponent)
+        mIn.reportError("Cannot specify component comparison for non-modules.");
+      componentsAscendingDesired = com;
+      if (componentCompareIndex != Order::ComponentAfterBaseOrder)
+        mIn.reportError("Component comparison must be specified at most once.");
+      componentCompareIndex = grading;
+      index += varCount;
+    } else {
+      for (VarIndex i = 0; i < varCount; ++i, ++index)
+        gradings[index] = mIn.readInteger<Exponent>();
+    }
+  }
+  MATHICGB_ASSERT(index == gradings.size());
+
+  const bool moreRevlex = mIn.match("revlex");
+  const bool moreLex = !moreRevlex && mIn.match("lex");
+  if (moreRevlex || moreLex) {
+    lexBaseOrder = moreLex;
+
+    const bool moreCom = mIn.match("component");
+    const bool moreRevcom = !moreCom && mIn.match("revcomponent");
+    if (com || revcom)
+      componentsAscendingDesired = moreCom;
+  }
+
+  auto ring = make_unique<PolyRing>(
+    charac,
+    Order(
+      varCount,
+      std::move(gradings),
+      lexBaseOrder ? Order::LexBaseOrder : Order::RevLexBaseOrder,
+      componentCompareIndex
+    )
+  );
+  auto basis = make_unique<Basis>(*ring);
+  auto processor = make_unique<MonoProcessor<Monoid>>(ring->monoid());
+  processor->setComponentsAscendingDesired(componentsAscendingDesired);
+
+  // ** Read polynomials
+  const auto polyCount = mIn.readInteger<size_t>();
+  for (size_t i = 0; i < polyCount; ++i) {
+    auto p = readPolynomial();
+    p->sortTermsDescending();
+    basis->insert(std::move(p));
+  }
+
+  if (doSchreyer) {
+    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)
+  );
+}
+
+std::unique_ptr<Poly> MathicIO::readPolynomial(const PolyRing& ring) {
+  Poly p(ring);
+  if (mIn.match('0'))
+    return;
+
+  auto mono = ring.monoid().alloc();
+  while (true) {
+    if (!isdigit(next) && !isalpha(next) && next != '<')
+      break;
+
+
+    // read coefficient
+    const bool negate = !mIn.match('+') && mIn.match('-');
+    coefficient coef = negate ? -1 : 1;
+    mIn.matchReadInteger(coef, negate);
+
+    // read monomial
+    read
+    
+    ring.monoid().setToIdentity(mono);
+    
+
+    const size_t firstLocation = monoms.size();
+    monoms.resize(firstLocation + R->maxMonomialSize());
+    monomial m = &monoms[firstLocation];
+    if (isalpha(next) || next == '<')
+      R->monomialParse(i, m);
+    else
+      R->monomialSetIdentity(m); // have to do this to set hash value
+    next = i.peek();
+    if (next == '>')
+      i.get();
+  }
+}
+*/
+
+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 bool negate = !in.match('+') && in.match('-');
+  if (in.peekDigit())
+    coef = field.toElement(in.readInteger<RawCoefficient>(negate));
+  else if (negate)
+    coef = field.minusOne();
+  else
+    coef = field.one();
+
+  // ** Read monomial
+  auto& monoid = ring.monoid();
+  if (field.isOne(coef) && !in.peekAlpha()) {
+    // Detect the monomial 1.
+    monoid.setIdentity(mono);
+    if (readComponent)
+      this->readComponent(monoid, mono, in);
+  } else
+    readMonomial(monoid, readComponent, mono, in);
+}
+
+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('>');
+}
+
+/// 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) {
+    MATHICGB_ASSERT(Monoid::HasComponent);
+    out << '<' << unchar(monoid.component(mono)) << '>';
+  }
+}
+
+#endif
diff --git a/src/mathicgb/MonoMonoid.hpp b/src/mathicgb/MonoMonoid.hpp
index baaf447..21f6024 100755
--- a/src/mathicgb/MonoMonoid.hpp
+++ b/src/mathicgb/MonoMonoid.hpp
@@ -65,9 +65,8 @@ namespace MonoMonoidInternal {
       mLexBaseOrder(order.baseOrder() == Order::LexBaseOrder),
       mGradings(makeGradings(order)),
       mComponentGradingIndex(
-        order.componentGradingIndex() == Order::ComponentAfterBaseOrder ?
-          Order::ComponentAfterBaseOrder :
-          order.gradingCount() - 1 - order.componentGradingIndex()
+        reverseComponentGradingIndex
+          (order.gradingCount(), order.componentGradingIndex())
       )
     {
     }
@@ -119,6 +118,19 @@ namespace MonoMonoidInternal {
         gradings[i] = -gradings[i];
     }
 
+    /// Since comparisons go opposite direction, we need to reverse
+    /// the component grading index, unless it's the special value
+    /// indicating that it goes last.
+    static VarIndex reverseComponentGradingIndex(
+      const VarIndex gradingCount,
+      const VarIndex componentGradingIndex
+    ) {
+      if (componentGradingIndex == Order::ComponentAfterBaseOrder)
+        return Order::ComponentAfterBaseOrder;
+      else
+        return gradingCount - 1 - componentGradingIndex;
+    }
+
     const HashCoefficients& hashCoefficients() const {return mHashCoefficients;}
     bool orderIsTotalDegreeRevLex() const {return mOrderIsTotalDegreeRevLex;}
     Gradings& gradings() {return mGradings;} // todo: remove this overload
@@ -340,6 +352,30 @@ public:
   void printMonoid
     (const bool componentsAscendingDesired, std::ostream& out) const;
 
+  /// Returns an Order object that is equivalent to the order that
+  /// this monoid was constructed with. The settings not handled by
+  /// the monoid, and therefore not known by the monoid, are passed in
+  /// as parameters. The purpose of that is to make it clear that this
+  /// information must be supplied separately.
+  Order makeOrder(
+    const bool componentsAscendingDesired,
+    const bool schreyering
+  ) const {
+    std::vector<Exponent> orderGradings(gradings());
+    reverseGradings(varCount(), orderGradings);
+    if (!isLexBaseOrder())
+      negateGradings(orderGradings);
+    return Order(
+      varCount(),
+      std::move(orderGradings),
+      isLexBaseOrder() ? Order::LexBaseOrder : Order::RevLexBaseOrder,
+      Base::reverseComponentGradingIndex
+        (gradingCount(), componentGradingIndex()),
+      componentsAscendingDesired,
+      schreyering
+    );
+  }
+
   bool operator==(const MonoMonoid& monoid) const {
     return this == &monoid;
   }
diff --git a/src/mathicgb/MonoOrder.hpp b/src/mathicgb/MonoOrder.hpp
index 7045110..e6770ba 100755
--- a/src/mathicgb/MonoOrder.hpp
+++ b/src/mathicgb/MonoOrder.hpp
@@ -4,7 +4,7 @@
 #include <vector>
 #include <algorithm>
 
-/// Class used to describe an monomial order or a module monomial
+/// Class used to describe an monomial order and/or a module monomial
 /// order. Use this class to construct a monoid. The monoid does the
 /// actual comparisons.
 ///
@@ -36,13 +36,17 @@ public:
   MonoOrder(
     const VarIndex varCount,
     const BaseOrder baseOrder = RevLexBaseOrder,
-    const size_t componentBefore = ComponentAfterBaseOrder
+    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)
+    mComponentGradingIndex(componentBefore),
+    mComponentsAscendingDesired(componentsAscendingDesired),
+    mSchreyering(schreyering)
   {}
 
   /// The specified base order is graded by the gradings matrix.
@@ -81,12 +85,16 @@ public:
     const VarIndex varCount,
     Gradings&& gradings,
     const BaseOrder baseOrder = RevLexBaseOrder,
-    const size_t componentBefore = ComponentAfterBaseOrder
+    const size_t componentBefore = ComponentAfterBaseOrder,
+    const bool componentsAscendingDesired = true,
+    const bool schreyering = true
   ):
     mVarCount(varCount),
     mGradings(std::move(gradings)),
     mBaseOrder(baseOrder),
-    mComponentGradingIndex(componentBefore)
+    mComponentGradingIndex(componentBefore),
+    mComponentsAscendingDesired(componentsAscendingDesired),
+    mSchreyering(schreyering)
   {
 #ifdef MATHCGB_DEBUG
     if (componentBefore != ComponentAfterBaseOrder) {
@@ -152,6 +160,9 @@ public:
     return true;
   }
 
+  bool componentsAscendingDesired() const {return mComponentsAscendingDesired;}
+  bool schreyering() const {return mSchreyering;}
+
 private:
   static Gradings addComponentGrading(
     Gradings&& gradings,
@@ -189,9 +200,12 @@ private:
   }
 
   const VarIndex mVarCount;
+
   const Gradings mGradings;
   const BaseOrder mBaseOrder;
   const size_t mComponentGradingIndex;
+  const bool mSchreyering;
+  const bool mComponentsAscendingDesired;
 };
 
 #endif
diff --git a/src/mathicgb/MonoProcessor.hpp b/src/mathicgb/MonoProcessor.hpp
index 2457ec7..7f7c84e 100755
--- a/src/mathicgb/MonoProcessor.hpp
+++ b/src/mathicgb/MonoProcessor.hpp
@@ -20,9 +20,14 @@ public:
   typedef typename Monoid::ConstMonoRef ConstMonoRef;
   typedef typename Monoid::ConstMonoPtr ConstMonoPtr;
 
-  MonoProcessor(const Monoid& monoid):
-    mComponentsAscendingDesired(true),
+  MonoProcessor(
+    const Monoid& monoid,
+    const bool componentsAscendingDesired,
+    const bool schreyering
+  ):
+    mComponentsAscendingDesired(componentsAscendingDesired),
     mComponentCount(0),
+    mSchreyering(schreyering),
     mModuleAdjustmentsMemory(monoid)
   {}
 
@@ -83,6 +88,9 @@ public:
     return !mModuleAdjustments.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();}
@@ -106,6 +114,7 @@ private:
 
   bool mComponentsAscendingDesired;
   VarIndex mComponentCount;
+  bool mSchreyering;
   MonoVector mModuleAdjustmentsMemory;
   std::vector<ConstMonoPtr> mModuleAdjustments;
 };
diff --git a/src/mathicgb/PrimeField.hpp b/src/mathicgb/PrimeField.hpp
index 009c8ad..4dcf4f3 100755
--- a/src/mathicgb/PrimeField.hpp
+++ b/src/mathicgb/PrimeField.hpp
@@ -11,6 +11,8 @@
 template<class T>
 class PrimeField {
 public:
+  typedef T RawElement;
+
   class Element {
   public:
     static_assert(!std::numeric_limits<T>::is_signed, "");
@@ -39,6 +41,7 @@ public:
 
   Element zero() const {return Element(0);}
   Element one() const {return Element(1);}
+  Element minusOne() const {return Element(charac() - 1);}
 
   bool isZero(const Element a) const {return a == zero();}
   bool isOne(const Element a) const {return a == one();}
diff --git a/src/mathicgb/Scanner.cpp b/src/mathicgb/Scanner.cpp
index 6fb10dd..caab861 100755
--- a/src/mathicgb/Scanner.cpp
+++ b/src/mathicgb/Scanner.cpp
@@ -175,7 +175,8 @@ bool Scanner::readBuffer(size_t minRead) {
     mStream->read(readInto, readCount);
     didReadCount = mStream->gcount();
   }
-  mBuffer.resize(didReadCount);
+  mBuffer.resize(saveCount + didReadCount);
   mBufferPos = mBuffer.begin();
+
   return didReadCount >= minRead;
 }
diff --git a/src/test/MathicIO.cpp b/src/test/MathicIO.cpp
new file mode 100755
index 0000000..8d17fd5
--- /dev/null
+++ b/src/test/MathicIO.cpp
@@ -0,0 +1,171 @@
+#include "mathicgb/stdinc.h"
+#include "mathicgb/MathicIO.hpp"
+
+#include <gtest/gtest.h>
+
+TEST(MathicIO, ReadWriteRing) {
+  typedef PolyRing::Monoid Monoid;
+  typedef Monoid::VarIndex VarIndex;
+  typedef Monoid::Exponent Exponent;
+  typedef PolyRing::Field BaseField;
+  typedef BaseField::RawElement RawElement;
+
+  auto check = [&](
+    const char* const inStr,
+    const char* outStr,
+    const RawElement charac,
+    const VarIndex varCount,
+    const VarIndex gradingCount,
+    const bool withComponent
+  ) {
+    for (int i = 0; i < 2; ++i) {
+      const char* str = i == 0 ? inStr : outStr;
+      if (str == 0)
+        continue;
+      Scanner in(str);
+      auto p = MathicIO().readRing(withComponent, in);
+      auto& monoid = p.first.monoid();
+      ASSERT_EQ(charac, p.first.field().charac());
+      ASSERT_EQ(varCount, monoid.varCount());
+      ASSERT_EQ(gradingCount, monoid.gradingCount());
+      std::ostringstream out;
+      MathicIO().writeRing(p.first, p.second, withComponent, out);
+      ASSERT_EQ(outStr, out.str());
+    }
+  };
+
+  check("101 2 1 3 4", "101 2\nrevlex 1\n 3 4\n", 101, 2, 1, false);
+  check(
+    "101 2 schreyer lex 1 3 4 _lex revcomponent",
+    "101 2\nschreyer lex 1\n 3 4\n _lex\n revcomponent\n", 101, 2, 1, true
+  );
+  check(
+    "101 2 2 component 3 4",
+    "101 2\nrevlex 2\n component\n 3 4\n", 101, 2, 2, true
+  );
+}
+
+TEST(MathicIO, ReadWriteMonomial) {
+  typedef PolyRing::Monoid Monoid;
+  typedef Monoid::VarIndex VarIndex;
+  typedef Monoid::Exponent Exponent;
+  static const auto NoComponent = static_cast<Exponent>(-1);
+
+  Monoid m(28);
+
+  // canonicalStr is str as it should appear after being read and
+  // printed. If canonicalStr is null then this is the same as str.
+  auto check = [&](
+    const char* const str,
+    const Exponent component,
+    const VarIndex var1 = -1,
+    const Exponent exp1 = -1,
+    const VarIndex var2 = -1,
+    const Exponent exp2 = -1,
+    const char* const canonicalStr = 0
+  ) {
+    const bool doComponent = component != NoComponent;
+
+    // read monomial from string
+    auto monoRead = m.alloc();
+    Scanner in(str);
+    MathicIO().readMonomial(m, doComponent, monoRead, in);
+
+    // directly make monomial
+    auto monoSet = m.alloc();
+    if (var1 != -1)
+      m.setExponent(var1, exp1, monoSet);
+    if (var2 != -1)
+      m.setExponent(var2, exp2, monoSet);
+    if (doComponent)
+      m.setComponent(component, monoSet);
+    ASSERT_TRUE(m.equal(monoRead, monoSet)) << "Str: " << str;
+
+    // print monomial
+    std::ostringstream out;
+    MathicIO().writeMonomial(m, doComponent, monoRead, out);
+    const auto correctStr = canonicalStr == 0 ? str : canonicalStr;
+    ASSERT_EQ(correctStr, out.str());
+  };
+
+  check("1", NoComponent);
+  check("1<0>", 0);
+  check("1<1>", 1);
+  check("1<999>", 999);
+
+  check("a1", NoComponent,  0,1,  -1,-1,  "a");
+  check("b10<0>", 0,   1,10);
+  check("A11", NoComponent,  26,11);
+  check("B99<1>", 1,   27,99);
+
+  check("ab", NoComponent,  0,1,  1,1);
+  check("ba", NoComponent,  0,1,  1,1,  "ab");
+  check("a0c3b1", NoComponent,  1,1,  2,3,  "bc3");
+  check("ab<2>", 2,  0,1,  1,1);
+}
+
+// TODO: check readTerm
+
+TEST(MathicIO, ReadWriteBaseField) {
+  Scanner in("101");
+  auto field = MathicIO().readBaseField(in);
+  ASSERT_EQ(101, field.charac());
+  std::ostringstream out;
+  MathicIO().writeBaseField(field, out);
+  ASSERT_EQ("101", out.str());
+}
+
+TEST(MathicIO, ReadWriteOrder) {
+  typedef PolyRing::Monoid Monoid;
+  typedef Monoid::VarIndex VarIndex;
+
+  const auto check = [](
+    const char* const inStr,
+    const char* const outStr,
+    const VarIndex varCount,
+    const VarIndex gradingCount,
+    const bool withComponent = false,
+    const bool componentsAscendingDesired = true,
+    const bool schreyering = false
+  ) -> void {
+    for (int i = 0; i < 2; ++i) {
+      const char* str = i == 0 ? inStr : outStr;
+      if (str == 0)
+        continue;
+
+      Scanner in(str);
+      const auto order = MathicIO().readOrder(varCount, withComponent, in);
+      ASSERT_EQ(varCount, order.varCount());
+      ASSERT_EQ(gradingCount, order.gradingCount());
+      ASSERT_EQ(componentsAscendingDesired, order.componentsAscendingDesired());
+      ASSERT_EQ(schreyering, order.schreyering()) << inStr;
+
+      std::ostringstream out;
+      MathicIO().writeOrder(order, withComponent, out);
+      ASSERT_EQ(outStr, out.str());
+    }
+  };
+  check("0\n", "revlex 0\n", 0, 0);
+  check("1\n 2\n", "revlex 1\n 2\n", 1, 1);
+  check("2\n 3\n 4\n", "revlex 2\n 3\n 4\n", 1, 2);
+  check("2\n 3 4\n 5 6\n", "revlex 2\n 3 4\n 5 6\n", 2, 2);
+  check("1\n 1 1 1 1\n", "revlex 1\n 1 1 1 1\n", 4, 1);
+
+  check("lex 0", "lex 0\n", 0, 0);
+  check("lex 1 2", "lex 1\n 2\n", 1, 1);
+  check("lex 2 3 4", "lex 2\n 3\n 4\n", 1, 2);
+  check("lex 2 3 4 5 6", "lex 2\n 3 4\n 5 6\n", 2, 2);
+  check("lex 1 1 1 1 1", "lex 1\n 1 1 1 1\n", 4, 1);
+
+  check("2 component\n 5 6\n", "revlex 2\n component\n 5 6\n", 2, 2, 1, 1, 0);
+  check("2 3 4\nrevcomponent\n","revlex 2\n 3 4\n revcomponent\n",2,2, 1,0,0);
+  check("lex 1 component", "lex 0\n", 0, 0,  1, 1, 0);
+  check("lex 1 revcomponent", "lex 1\n revcomponent\n", 1, 1, 1, 0, 0);
+  check("lex 1 revcomponent", "lex 1\n revcomponent\n", 5, 1, 1, 0, 0);
+
+  check(
+    "schreyer lex 1 1 _lex revcomponent",
+    "schreyer lex 1\n 1\n _lex\n revcomponent\n",
+    1, 1, 1, 0, 1
+  );
+}

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