[mathicgb] 189/393: MathicGB no longer requires TBB. You still need TBB if you want parallel execution. Removing the requirement for TBB is achieved through an implementation of the parts of the TBB interface that MathicGB uses. This implementation does not do anything in paralle, so it was easy to write. So easy, in fact, that now I'm wondering whether it would make sense to make this implementation support OpenMP, in which case Cygwin would still have parallel execution, just not quite as fast.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:58 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 78da45ad4033dd0910ec0214fd962d8f18fa453e
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Mon Mar 18 17:03:56 2013 +0100

    MathicGB no longer requires TBB. You still need TBB if you want parallel execution. Removing the requirement for TBB is achieved through an implementation of the parts of the TBB interface that MathicGB uses. This implementation does not do anything in paralle, so it was easy to write. So easy, in fact, that now I'm wondering whether it would make sense to make this implementation support OpenMP, in which case Cygwin would still have parallel execution, just not quite as fast.
---
 Makefile.am                                        |   2 +-
 build/vs12/mathicgb-lib/mathicgb-lib.vcxproj       |   1 +
 .../vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters |   3 +
 src/cli/CommonParams.cpp                           |   4 +-
 src/cli/CommonParams.hpp                           |   8 +-
 src/mathicgb.cpp                                   | 630 ++++++++++-----------
 src/mathicgb.h                                     |   6 +-
 src/mathicgb/F4MatrixBuilder.cpp                   |  10 +-
 src/mathicgb/F4MatrixBuilder.hpp                   |   6 +-
 src/mathicgb/F4MatrixBuilder2.cpp                  |  13 +-
 src/mathicgb/F4MatrixBuilder2.hpp                  |   6 +-
 src/mathicgb/F4MatrixProjection.cpp                |   2 +-
 src/mathicgb/F4MatrixReducer.cpp                   |  34 +-
 src/mathicgb/FixedSizeMonomialMap.h                |  44 +-
 src/mathicgb/LogDomain.cpp                         |   7 +-
 src/mathicgb/LogDomain.hpp                         |   4 +-
 src/mathicgb/LogDomainSet.cpp                      |   4 +-
 src/mathicgb/LogDomainSet.hpp                      |   4 +-
 src/mathicgb/MonomialMap.hpp                       |   8 +-
 src/mathicgb/QuadMatrix.cpp                        |   6 +-
 src/mathicgb/mtbb.hpp                              | 230 ++++++++
 src/test/F4MatrixBuilder.cpp                       |   8 +-
 src/test/gb-test.cpp                               |   4 +-
 23 files changed, 639 insertions(+), 405 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 8baf096..61ac911 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -69,7 +69,7 @@ libmathicgb_la_SOURCES = src/mathicgb/BjarkeGeobucket2.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.cpp src/mathicgb.h src/mathicgb/mtbb.hpp
 
 # When making a distribution file, Automake knows to include all files
 # that are necessary to build the project. EXTRA_DIST specifies files
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
index e20404a..6a59c49 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
@@ -513,6 +513,7 @@
     <ClInclude Include="..\..\..\src\mathicgb\MonTableKDTree.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\MonTableNaive.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\MTArray.hpp" />
+    <ClInclude Include="..\..\..\src\mathicgb\mtbb.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\PairTriangle.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\Poly.hpp" />
     <ClInclude Include="..\..\..\src\mathicgb\PolyBasis.hpp" />
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
index 065c619..7b57653 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
@@ -320,5 +320,8 @@
     <ClInclude Include="..\..\..\src\mathicgb.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\src\mathicgb\mtbb.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/cli/CommonParams.cpp b/src/cli/CommonParams.cpp
index 841bb6e..d0eb366 100644
--- a/src/cli/CommonParams.cpp
+++ b/src/cli/CommonParams.cpp
@@ -53,9 +53,9 @@ void CommonParams::perform() {
 
   // delete the old init object first to make the new one take control.
   mTbbInit.reset();
-  mTbbInit = make_unique<tbb::task_scheduler_init>(
+  mTbbInit = make_unique<mgb::tbb::task_scheduler_init>(
     mThreadCount.value() == 0 ?
-      tbb::task_scheduler_init::automatic :
+      mgb::tbb::task_scheduler_init::automatic :
       mThreadCount.value()
   );
 }
diff --git a/src/cli/CommonParams.hpp b/src/cli/CommonParams.hpp
index 108a151..9843706 100644
--- a/src/cli/CommonParams.hpp
+++ b/src/cli/CommonParams.hpp
@@ -1,8 +1,8 @@
 #ifndef MATHICGB_COMMON_PARAMS_GUARD
 #define MATHICGB_COMMON_PARAMS_GUARD
 
+#include "mathicgb/mtbb.hpp"
 #include <mathic.h>
-#include <tbb/tbb.h>
 #include <vector>
 
 class CommonParams {
@@ -41,8 +41,10 @@ private:
   mathic::IntegerParameter mThreadCount;
   mathic::StringParameter mLogs;
 
-  std::vector<std::string> mExtensions; // to recognize file type
-  std::unique_ptr<tbb::task_scheduler_init> mTbbInit; // to set thread count
+  std::vector<std::string> mExtensions; /// to recognize file type
+
+  /// to set thread count
+  std::unique_ptr<mgb::tbb::task_scheduler_init> mTbbInit;
   std::size_t mMinDirectParams;
   std::size_t mMaxDirectParams;
   std::vector<std::string> mDirectParameters;
diff --git a/src/mathicgb.cpp b/src/mathicgb.cpp
index f5e03ad..f11fa5b 100644
--- a/src/mathicgb.cpp
+++ b/src/mathicgb.cpp
@@ -1,277 +1,277 @@
-#include "mathicgb/stdinc.h"
-#include "mathicgb.h"
-
+#include "mathicgb/stdinc.h"
+#include "mathicgb.h"
+
 #include "mathicgb/Ideal.hpp"
 #include "mathicgb/PolyRing.hpp"
 #include "mathicgb/Poly.hpp"
 #include "mathicgb/Reducer.hpp"
 #include "mathicgb/BuchbergerAlg.hpp"
 #include <mathic.h>
-
-namespace {
-  bool isPrime(unsigned int n) {
-    if (n == 0 || n == 1)
-      return false;
-    if (n == 2 || n == 3)
-      return true;
-    return true; // todo: make better test
-  }
-};
-
-#ifndef MATHICGB_ASSERT
-#ifdef MATHICGB_DEBUG
-#include <cassert>
-#define MATHICGB_ASSERT(X) assert(X)
-#else
-#define MATHICGB_ASSERT(X)
-#endif
-#endif
-
-#define MATHICGB_STREAM_CHECK(X, MSG) \
-  do { \
-    const bool value = (X); \
-    if (!value) { \
-      const bool ignoreMe = false; \
-      MATHICGB_ASSERT(( \
-        "MathicGB stream protocol error: "#MSG \
-        "\nAssert expression: "#X"\n", \
-        false \
-      )); \
-      throw std::invalid_argument( \
-        "MathicGB stream protocol error: "#MSG \
-        "\nAssert expression: "#X"\n" \
-      ); \
-    } \
-  } while (false)
-
-namespace mgbi {
-  struct StreamStateChecker::Pimpl {
-    Pimpl(Coefficient modulus, VarIndex varCount):
-      modulus(modulus),
-      varCount(varCount),
-      state(Initial),
-      claimedPolyCount(0),
-      seenPolyCount(0),
-      claimedTermCount(0),
-      seenTermCount(0)
-    {}
-
-    bool debugAssertValid() const;
-
-    enum State {
-      Initial,
-      MakingIdeal,
-      MakingPoly,
-      MakingTerm,
-      HasIdeal
-    };
-
-    const Coefficient modulus;
-    const VarIndex varCount;
-
-    State state;
-    size_t claimedPolyCount;
-    size_t seenPolyCount;
-    size_t claimedTermCount;
-    size_t seenTermCount;
-    VarIndex lastVar;
-  };
-
-  bool StreamStateChecker::Pimpl::debugAssertValid() const {
-#ifdef MATHICGB_DEBUG
-    MATHICGB_ASSERT(this != 0);
-    switch (state) {
-    case Initial:
-    case MakingIdeal:
-    case MakingPoly:
-    case MakingTerm:
-    case HasIdeal:
-      break;
-
-    default:
-      MATHICGB_ASSERT(false);
-      return false;
-    }
-#endif
-    return true;
-  };
-
-  StreamStateChecker::StreamStateChecker(const Coefficient modulus, const VarIndex varCount):
-    mPimpl(new Pimpl(modulus, varCount))
-  {
-    try {
-      MATHICGB_STREAM_CHECK(isPrime(modulus), "The modulus must be prime");
-      MATHICGB_ASSERT(mPimpl->debugAssertValid());
-    } catch (...) {
-      delete mPimpl;
-    }
-  }
-
-  StreamStateChecker::~StreamStateChecker() {
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-    delete mPimpl;
-  }
-
-  void StreamStateChecker::idealBegin(size_t polyCount) {
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-
-    MATHICGB_STREAM_CHECK(
-      mPimpl->state == Pimpl::Initial || mPimpl->state == Pimpl::HasIdeal,
-      "idealBegin() must not be called twice "
-      "without an intervening call to idealDone()."
-    );
-    mPimpl->state = Pimpl::MakingIdeal;
-    mPimpl->claimedPolyCount = polyCount;
-    mPimpl->seenPolyCount = 0;
-
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-  }
-
-  void StreamStateChecker::appendPolynomialBegin(size_t termCount) {
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-
-    MATHICGB_STREAM_CHECK(
-      mPimpl->state != Pimpl::Initial && mPimpl->state != Pimpl::HasIdeal,
-      "appendPolynomialBegin() must only be called after idealBegin() and "
-      "before idealEnd()."
-    );
-    MATHICGB_STREAM_CHECK(
-      mPimpl->state == Pimpl::MakingIdeal,
-     "appendPolynomialBegin() must not be called twice without "
-     "an intervening call to appendPolynomialDone()."
-    );
-    MATHICGB_STREAM_CHECK(
-      mPimpl->seenPolyCount < mPimpl->claimedPolyCount,
-      "The number of polynomials in an ideal must not exceed the amount "
-      "passed to idealBegin()."
-    );
-    mPimpl->state = Pimpl::MakingPoly;
-    mPimpl->seenPolyCount += 1;
-    mPimpl->claimedTermCount = termCount;
-    mPimpl->seenTermCount = 0;
-
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-  }
-
-  void StreamStateChecker::appendTermBegin() {
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-
-    MATHICGB_STREAM_CHECK(
-      mPimpl->state != Pimpl::Initial &&
-        mPimpl->state != Pimpl::HasIdeal &&
-        mPimpl->state != Pimpl::MakingIdeal,
-      "appendTermBegin() must only be called after appendPolynomialBegin() "
-      "and before appendPolynomialDone()."
-    );
-    MATHICGB_STREAM_CHECK(
-      mPimpl->state == Pimpl::MakingPoly,
-      "appendTermBegin() must not be called twice without an intervening "
-      "call to appendTermDone()."
-    );
-    MATHICGB_STREAM_CHECK(
-      mPimpl->seenTermCount < mPimpl->claimedTermCount,
-      "The number of terms in a polynomial must not exceed the amount "
-      "passed to appendPolynomialBegin()."
-    );
-     
-    mPimpl->state = Pimpl::MakingTerm;
-    mPimpl->seenTermCount += 1;
-    mPimpl->lastVar = std::numeric_limits<decltype(mPimpl->lastVar)>::max();
-
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-  }
-
-  void StreamStateChecker::appendExponent(VarIndex index, Exponent exponent) {
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-
-    MATHICGB_STREAM_CHECK(
-      mPimpl->state == Pimpl::MakingTerm,
-      "appendExponent must only be called after appendTermBegin() and before "
-      "appendTermDone()."
-    );
-    MATHICGB_STREAM_CHECK(
-      index < mPimpl->varCount,
-      "The index passed to appendExponent must be strictly less than "
-      "the number of variables."
-    );
-    MATHICGB_STREAM_CHECK(
-      mPimpl->lastVar ==
-        std::numeric_limits<decltype(mPimpl->lastVar)>::max() ||
-      mPimpl->lastVar < index,
-      "The variable indices passed to appendExponent must be in strictly "
-      "increasing order within each monomial."
-    );
-
-    mPimpl->lastVar = index;
-    
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-  }
-
-  void StreamStateChecker::appendTermDone(Coefficient coefficient) {
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-
-    MATHICGB_STREAM_CHECK(
-      coefficient > 0,
-      "The coefficient passed to appendTermDone() must be strictly positive."
-    );
-    MATHICGB_STREAM_CHECK(
-      coefficient < mPimpl->modulus,
-      "The coefficient passed to appendTermDone() must be strictly less "
-      "then the modulus."
-    );
-    MATHICGB_STREAM_CHECK(
-      mPimpl->state == Pimpl::MakingTerm,
-      "appendTermDone() must only be called after appendTermBegin()."
-    );
-    mPimpl->state = Pimpl::MakingPoly;
-    
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-  }
-
-  void StreamStateChecker::appendPolynomialDone() {
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-
-    MATHICGB_STREAM_CHECK(
-      mPimpl->state == Pimpl::MakingPoly,
-      "appendPolynomialDone() must only be called after appendPolynomialBegin()."
-    );
-    MATHICGB_STREAM_CHECK(
-      mPimpl->seenTermCount == mPimpl->claimedTermCount,
-      "The number of terms in a polynomial must match the amount "
-      "passed to appendPolynomialBegin()."
-    );
-    mPimpl->state = Pimpl::MakingIdeal;
-
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-  }
-
-  void StreamStateChecker::idealDone() {
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-
-    MATHICGB_STREAM_CHECK(
-      mPimpl->state == Pimpl::MakingIdeal,
-      "idealDone() must only be called after idealBegin()."
-    );
-    MATHICGB_STREAM_CHECK(
-      mPimpl->seenPolyCount == mPimpl->claimedPolyCount,
-      "The number of polynomials in an ideal must match the amount "
-      "passed to idealBegin()."
-    );
-
-    mPimpl->state = Pimpl::HasIdeal;
-
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-  }
-
-  bool StreamStateChecker::hasIdeal() const {
-    MATHICGB_ASSERT(mPimpl->debugAssertValid());
-    return mPimpl->state == Pimpl::HasIdeal;
-  }
-}
-
-namespace mgb {
-  // ** Implementation of the class GroebnerConfiguration
-
+
+namespace {
+  bool isPrime(unsigned int n) {
+    if (n == 0 || n == 1)
+      return false;
+    if (n == 2 || n == 3)
+      return true;
+    return true; // todo: make better test
+  }
+};
+
+#ifndef MATHICGB_ASSERT
+#ifdef MATHICGB_DEBUG
+#include <cassert>
+#define MATHICGB_ASSERT(X) assert(X)
+#else
+#define MATHICGB_ASSERT(X)
+#endif
+#endif
+
+#define MATHICGB_STREAM_CHECK(X, MSG) \
+  do { \
+    const bool value = (X); \
+    if (!value) { \
+      const bool ignoreMe = false; \
+      MATHICGB_ASSERT(( \
+        "MathicGB stream protocol error: "#MSG \
+        "\nAssert expression: "#X"\n", \
+        false \
+      )); \
+      throw std::invalid_argument( \
+        "MathicGB stream protocol error: "#MSG \
+        "\nAssert expression: "#X"\n" \
+      ); \
+    } \
+  } while (false)
+
+namespace mgbi {
+  struct StreamStateChecker::Pimpl {
+    Pimpl(Coefficient modulus, VarIndex varCount):
+      modulus(modulus),
+      varCount(varCount),
+      state(Initial),
+      claimedPolyCount(0),
+      seenPolyCount(0),
+      claimedTermCount(0),
+      seenTermCount(0)
+    {}
+
+    bool debugAssertValid() const;
+
+    enum State {
+      Initial,
+      MakingIdeal,
+      MakingPoly,
+      MakingTerm,
+      HasIdeal
+    };
+
+    const Coefficient modulus;
+    const VarIndex varCount;
+
+    State state;
+    size_t claimedPolyCount;
+    size_t seenPolyCount;
+    size_t claimedTermCount;
+    size_t seenTermCount;
+    VarIndex lastVar;
+  };
+
+  bool StreamStateChecker::Pimpl::debugAssertValid() const {
+#ifdef MATHICGB_DEBUG
+    MATHICGB_ASSERT(this != 0);
+    switch (state) {
+    case Initial:
+    case MakingIdeal:
+    case MakingPoly:
+    case MakingTerm:
+    case HasIdeal:
+      break;
+
+    default:
+      MATHICGB_ASSERT(false);
+      return false;
+    }
+#endif
+    return true;
+  };
+
+  StreamStateChecker::StreamStateChecker(const Coefficient modulus, const VarIndex varCount):
+    mPimpl(new Pimpl(modulus, varCount))
+  {
+    try {
+      MATHICGB_STREAM_CHECK(isPrime(modulus), "The modulus must be prime");
+      MATHICGB_ASSERT(mPimpl->debugAssertValid());
+    } catch (...) {
+      delete mPimpl;
+    }
+  }
+
+  StreamStateChecker::~StreamStateChecker() {
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+    delete mPimpl;
+  }
+
+  void StreamStateChecker::idealBegin(size_t polyCount) {
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+
+    MATHICGB_STREAM_CHECK(
+      mPimpl->state == Pimpl::Initial || mPimpl->state == Pimpl::HasIdeal,
+      "idealBegin() must not be called twice "
+      "without an intervening call to idealDone()."
+    );
+    mPimpl->state = Pimpl::MakingIdeal;
+    mPimpl->claimedPolyCount = polyCount;
+    mPimpl->seenPolyCount = 0;
+
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+  }
+
+  void StreamStateChecker::appendPolynomialBegin(size_t termCount) {
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+
+    MATHICGB_STREAM_CHECK(
+      mPimpl->state != Pimpl::Initial && mPimpl->state != Pimpl::HasIdeal,
+      "appendPolynomialBegin() must only be called after idealBegin() and "
+      "before idealEnd()."
+    );
+    MATHICGB_STREAM_CHECK(
+      mPimpl->state == Pimpl::MakingIdeal,
+     "appendPolynomialBegin() must not be called twice without "
+     "an intervening call to appendPolynomialDone()."
+    );
+    MATHICGB_STREAM_CHECK(
+      mPimpl->seenPolyCount < mPimpl->claimedPolyCount,
+      "The number of polynomials in an ideal must not exceed the amount "
+      "passed to idealBegin()."
+    );
+    mPimpl->state = Pimpl::MakingPoly;
+    mPimpl->seenPolyCount += 1;
+    mPimpl->claimedTermCount = termCount;
+    mPimpl->seenTermCount = 0;
+
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+  }
+
+  void StreamStateChecker::appendTermBegin() {
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+
+    MATHICGB_STREAM_CHECK(
+      mPimpl->state != Pimpl::Initial &&
+        mPimpl->state != Pimpl::HasIdeal &&
+        mPimpl->state != Pimpl::MakingIdeal,
+      "appendTermBegin() must only be called after appendPolynomialBegin() "
+      "and before appendPolynomialDone()."
+    );
+    MATHICGB_STREAM_CHECK(
+      mPimpl->state == Pimpl::MakingPoly,
+      "appendTermBegin() must not be called twice without an intervening "
+      "call to appendTermDone()."
+    );
+    MATHICGB_STREAM_CHECK(
+      mPimpl->seenTermCount < mPimpl->claimedTermCount,
+      "The number of terms in a polynomial must not exceed the amount "
+      "passed to appendPolynomialBegin()."
+    );
+     
+    mPimpl->state = Pimpl::MakingTerm;
+    mPimpl->seenTermCount += 1;
+    mPimpl->lastVar = std::numeric_limits<decltype(mPimpl->lastVar)>::max();
+
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+  }
+
+  void StreamStateChecker::appendExponent(VarIndex index, Exponent exponent) {
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+
+    MATHICGB_STREAM_CHECK(
+      mPimpl->state == Pimpl::MakingTerm,
+      "appendExponent must only be called after appendTermBegin() and before "
+      "appendTermDone()."
+    );
+    MATHICGB_STREAM_CHECK(
+      index < mPimpl->varCount,
+      "The index passed to appendExponent must be strictly less than "
+      "the number of variables."
+    );
+    MATHICGB_STREAM_CHECK(
+      mPimpl->lastVar ==
+        std::numeric_limits<decltype(mPimpl->lastVar)>::max() ||
+      mPimpl->lastVar < index,
+      "The variable indices passed to appendExponent must be in strictly "
+      "increasing order within each monomial."
+    );
+
+    mPimpl->lastVar = index;
+    
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+  }
+
+  void StreamStateChecker::appendTermDone(Coefficient coefficient) {
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+
+    MATHICGB_STREAM_CHECK(
+      coefficient > 0,
+      "The coefficient passed to appendTermDone() must be strictly positive."
+    );
+    MATHICGB_STREAM_CHECK(
+      coefficient < mPimpl->modulus,
+      "The coefficient passed to appendTermDone() must be strictly less "
+      "then the modulus."
+    );
+    MATHICGB_STREAM_CHECK(
+      mPimpl->state == Pimpl::MakingTerm,
+      "appendTermDone() must only be called after appendTermBegin()."
+    );
+    mPimpl->state = Pimpl::MakingPoly;
+    
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+  }
+
+  void StreamStateChecker::appendPolynomialDone() {
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+
+    MATHICGB_STREAM_CHECK(
+      mPimpl->state == Pimpl::MakingPoly,
+      "appendPolynomialDone() must only be called after appendPolynomialBegin()."
+    );
+    MATHICGB_STREAM_CHECK(
+      mPimpl->seenTermCount == mPimpl->claimedTermCount,
+      "The number of terms in a polynomial must match the amount "
+      "passed to appendPolynomialBegin()."
+    );
+    mPimpl->state = Pimpl::MakingIdeal;
+
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+  }
+
+  void StreamStateChecker::idealDone() {
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+
+    MATHICGB_STREAM_CHECK(
+      mPimpl->state == Pimpl::MakingIdeal,
+      "idealDone() must only be called after idealBegin()."
+    );
+    MATHICGB_STREAM_CHECK(
+      mPimpl->seenPolyCount == mPimpl->claimedPolyCount,
+      "The number of polynomials in an ideal must match the amount "
+      "passed to idealBegin()."
+    );
+
+    mPimpl->state = Pimpl::HasIdeal;
+
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+  }
+
+  bool StreamStateChecker::hasIdeal() const {
+    MATHICGB_ASSERT(mPimpl->debugAssertValid());
+    return mPimpl->state == Pimpl::HasIdeal;
+  }
+}
+
+namespace mgb {
+  // ** Implementation of the class GroebnerConfiguration
+
   struct GroebnerConfiguration::Pimpl {
     Pimpl(Coefficient modulus, VarIndex varCount):
 #ifdef MATHICGB_DEBUG
@@ -378,7 +378,7 @@ namespace mgb {
     MATHICGB_ASSERT(debugAssertValid());
     MATHICGB_ASSERT(mExponents != 0);
     MATHICGB_ASSERT(mPimpl != 0);
-    MATHICGB_ASSERT(!mPimpl->hasBeenDestroyed);
+    MATHICGB_ASSERT_NO_ASSUME(!mPimpl->hasBeenDestroyed);
     MATHICGB_IF_DEBUG(mPimpl->hasBeenDestroyed = true);
     delete mPimpl;
     delete[] mExponents;
@@ -463,7 +463,7 @@ namespace mgb {
     MATHICGB_ASSERT(this != 0);
     MATHICGB_ASSERT(mExponents != 0);
     MATHICGB_ASSERT(mPimpl != 0);
-    MATHICGB_ASSERT(!mPimpl->hasBeenDestroyed);
+    MATHICGB_ASSERT_NO_ASSUME(!mPimpl->hasBeenDestroyed);
     MATHICGB_ASSERT(!mPimpl->monomial.isNull());
     MATHICGB_ASSERT(&mPimpl->ideal.ring() == &mPimpl->ring);
     MATHICGB_ASSERT(&mPimpl->poly.ring() == &mPimpl->ring);
@@ -491,45 +491,45 @@ namespace mgbi {
     std::unique_ptr<Ideal> ideal;
   };
 
-  IdealAdapter::IdealAdapter():
-    mPimpl(new Pimpl()) {
-  }
-
-  IdealAdapter::~IdealAdapter() {
-    MATHICGB_ASSERT(mPimpl != 0);
-    delete mPimpl;
-  }
+  IdealAdapter::IdealAdapter():
+    mPimpl(new Pimpl()) {
+  }
+
+  IdealAdapter::~IdealAdapter() {
+    MATHICGB_ASSERT(mPimpl != 0);
+    delete mPimpl;
+  }
 
   auto IdealAdapter::varCount() const -> VarIndex {
-    MATHICGB_ASSERT(mPimpl->ideal.get() != 0);
+    MATHICGB_ASSERT(mPimpl->ideal.get() != 0);
     return mPimpl->ideal->ring().getNumVars();
   }
 
-  size_t IdealAdapter::polyCount() const {
-    MATHICGB_ASSERT(mPimpl->ideal.get() != 0);
-    return mPimpl->ideal->size();
-  }
-
-  size_t IdealAdapter::termCount(PolyIndex poly) const {
-    MATHICGB_ASSERT(mPimpl->ideal.get() != 0);
-    MATHICGB_ASSERT(poly < mPimpl->ideal->size());
-    return mPimpl->ideal->getPoly(poly)->nTerms();
-  }
-
-  auto IdealAdapter::term(
-    PolyIndex poly,
-    TermIndex term
-  ) const -> std::pair<Coefficient, const Exponent*> {
-    MATHICGB_ASSERT(mPimpl->ideal.get() != 0);
-    MATHICGB_ASSERT(poly < mPimpl->ideal->size());
-    const auto& p = *mPimpl->ideal->getPoly(poly);
-
-    MATHICGB_ASSERT(term < p.nTerms());
-    return std::make_pair(
-      p.coefficientAt(term),
-      p.monomialAt(term).unsafeGetRepresentation() + 1
-    );
-  }
+  size_t IdealAdapter::polyCount() const {
+    MATHICGB_ASSERT(mPimpl->ideal.get() != 0);
+    return mPimpl->ideal->size();
+  }
+
+  size_t IdealAdapter::termCount(PolyIndex poly) const {
+    MATHICGB_ASSERT(mPimpl->ideal.get() != 0);
+    MATHICGB_ASSERT(poly < mPimpl->ideal->size());
+    return mPimpl->ideal->getPoly(poly)->nTerms();
+  }
+
+  auto IdealAdapter::term(
+    PolyIndex poly,
+    TermIndex term
+  ) const -> std::pair<Coefficient, const Exponent*> {
+    MATHICGB_ASSERT(mPimpl->ideal.get() != 0);
+    MATHICGB_ASSERT(poly < mPimpl->ideal->size());
+    const auto& p = *mPimpl->ideal->getPoly(poly);
+
+    MATHICGB_ASSERT(term < p.nTerms());
+    return std::make_pair(
+      p.coefficientAt(term),
+      p.monomialAt(term).unsafeGetRepresentation() + 1
+    );
+  }
 }
 
 // ** Implementation of function mgbi::internalComputeGreobnerBasis
@@ -547,14 +547,14 @@ namespace mgbi {
     const auto varCount = ring.getNumVars();
 
     // Compute Groebner basis
-    const auto reducer = Reducer::makeReducer(Reducer::Reducer_F4_New, ring);
-    BuchbergerAlg alg(ideal, 4, *reducer, 2, true, 0);
-    alg.setSPairGroupSize(10000);
-    alg.setReducerMemoryQuantum(100 * 1024);
-    alg.setUseAutoTopReduction(true);
-    alg.setUseAutoTailReduction(false);
-    alg.computeGrobnerBasis();
-
-    PimplOf()(output).ideal = alg.basis().toIdealAndRetireAll();
-  }
-}
+    const auto reducer = Reducer::makeReducer(Reducer::Reducer_F4_New, ring);
+    BuchbergerAlg alg(ideal, 4, *reducer, 2, true, 0);
+    alg.setSPairGroupSize(10000);
+    alg.setReducerMemoryQuantum(100 * 1024);
+    alg.setUseAutoTopReduction(true);
+    alg.setUseAutoTailReduction(false);
+    alg.computeGrobnerBasis();
+
+    PimplOf()(output).ideal = alg.basis().toIdealAndRetireAll();
+  }
+}
diff --git a/src/mathicgb.h b/src/mathicgb.h
index e12f9ec..6367be1 100644
--- a/src/mathicgb.h
+++ b/src/mathicgb.h
@@ -486,9 +486,9 @@ namespace mgbi {
     Pimpl* mPimpl;
   };
 
-  void internalComputeGroebnerBasis(
-    GroebnerInputIdealStream& inputWhichWillBeCleared,
-    IdealAdapter& output
+  void internalComputeGroebnerBasis(
+    GroebnerInputIdealStream& inputWhichWillBeCleared,
+    IdealAdapter& output
   );
 }
 
diff --git a/src/mathicgb/F4MatrixBuilder.cpp b/src/mathicgb/F4MatrixBuilder.cpp
index 4aeaa19..793a40a 100755
--- a/src/mathicgb/F4MatrixBuilder.cpp
+++ b/src/mathicgb/F4MatrixBuilder.cpp
@@ -2,7 +2,7 @@
 #include "F4MatrixBuilder.hpp"
 
 #include "LogDomain.hpp"
-#include <tbb/tbb.h>
+#include "mtbb.hpp"
 
 MATHICGB_DEFINE_LOG_DOMAIN(
   F4MatrixBuild,
@@ -136,19 +136,19 @@ void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) {
     monomial tmp2;
   };
 
-  tbb::enumerable_thread_specific<ThreadData> threadData([&](){  
+  mgb::tbb::enumerable_thread_specific<ThreadData> threadData([&](){  
     ThreadData data = {QuadMatrixBuilder(
       ring(), mMap, mMonomialsLeft, mMonomialsRight, mBuilder.memoryQuantum()
     )};
     {
-      tbb::mutex::scoped_lock guard(mCreateColumnLock);
+      mgb::tbb::mutex::scoped_lock guard(mCreateColumnLock);
       data.tmp1 = ring().allocMonomial();
       data.tmp2 = ring().allocMonomial();
     }
     return std::move(data);
   });
 
-  tbb::parallel_do(mTodo.begin(), mTodo.end(),
+  mgb::tbb::parallel_do(mTodo.begin(), mTodo.end(),
     [&](const RowTask& task, TaskFeeder& feeder)
   {
     auto& data = threadData.local();
@@ -238,7 +238,7 @@ F4MatrixBuilder::createColumn(
   MATHICGB_ASSERT(!monoA.isNull());
   MATHICGB_ASSERT(!monoB.isNull());
 
-  tbb::mutex::scoped_lock lock(mCreateColumnLock);
+  mgb::tbb::mutex::scoped_lock lock(mCreateColumnLock);
   // see if the column exists now after we have synchronized
   {
     const auto found(ColReader(mMap).findProduct(monoA, monoB));
diff --git a/src/mathicgb/F4MatrixBuilder.hpp b/src/mathicgb/F4MatrixBuilder.hpp
index f2db0eb..9e3f267 100755
--- a/src/mathicgb/F4MatrixBuilder.hpp
+++ b/src/mathicgb/F4MatrixBuilder.hpp
@@ -6,7 +6,7 @@
 #include "PolyRing.hpp"
 #include "PolyBasis.hpp"
 #include "QuadMatrix.hpp"
-#include <tbb/mutex.h>
+#include "mtbb.hpp"
 #include <vector>
 
 /** Class for constructing an F4 matrix. This class is reponsible for
@@ -81,7 +81,7 @@ private:
     const Poly* sPairPoly;
     monomial sPairMultiply;
   };
-  typedef tbb::parallel_do_feeder<RowTask> TaskFeeder;
+  typedef ::mgb::tbb::parallel_do_feeder<RowTask> TaskFeeder;
 
   /// Creates a column with monomial label x and schedules a new row to
   /// reduce that column if possible. Here x is monoA if monoB is
@@ -142,7 +142,7 @@ private:
     TaskFeeder& feeder
   );
 
-  tbb::mutex mCreateColumnLock;
+  mgb::tbb::mutex mCreateColumnLock;
   ColIndex mLeftColCount;
   ColIndex mRightColCount;
   monomial mTmp;
diff --git a/src/mathicgb/F4MatrixBuilder2.cpp b/src/mathicgb/F4MatrixBuilder2.cpp
index 11f7317..a222e2a 100755
--- a/src/mathicgb/F4MatrixBuilder2.cpp
+++ b/src/mathicgb/F4MatrixBuilder2.cpp
@@ -3,7 +3,6 @@
 
 #include "LogDomain.hpp"
 #include "F4MatrixProjection.hpp"
-#include <tbb/tbb.h>
 
 MATHICGB_DEFINE_LOG_DOMAIN(
   F4MatrixBuild2,
@@ -126,7 +125,7 @@ void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) {
 
   // Use halves of S-pairs as reducers to decrease the number of entries that
   // need to be looked up.
-  tbb::parallel_sort(mTodo.begin(), mTodo.end(),
+  mgb::tbb::parallel_sort(mTodo.begin(), mTodo.end(),
     [&](const RowTask& a, const RowTask& b)
   {
     if (a.sPairPoly == 0)
@@ -195,10 +194,10 @@ void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) {
     monomial tmp2;
   };
 
-  tbb::enumerable_thread_specific<ThreadData> threadData([&](){  
+  mgb::tbb::enumerable_thread_specific<ThreadData> threadData([&](){  
     ThreadData data;
     {
-      tbb::mutex::scoped_lock guard(mCreateColumnLock);
+      mgb::tbb::mutex::scoped_lock guard(mCreateColumnLock);
       data.tmp1 = ring().allocMonomial();
       data.tmp2 = ring().allocMonomial();
     }
@@ -206,7 +205,7 @@ void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) {
   });
 
   // Construct the matrix as pre-blocks
-  tbb::parallel_do(mTodo.begin(), mTodo.end(),
+  mgb::tbb::parallel_do(mTodo.begin(), mTodo.end(),
     [&](const RowTask& task, TaskFeeder& feeder)
   {
     auto& data = threadData.local();
@@ -267,7 +266,7 @@ void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) {
   const auto cmp = [&](const IndexMono& a, const IndexMono b) {
     return ring().monomialLT(b.second, a.second);
   };
-  tbb::parallel_sort(columns.begin(), columns.end(), cmp);
+  mgb::tbb::parallel_sort(columns.begin(), columns.end(), cmp);
 
   const auto colEnd = columns.end();
   for (auto it = columns.begin(); it != colEnd; ++it) {
@@ -303,7 +302,7 @@ F4MatrixBuilder2::createColumn(
   MATHICGB_ASSERT(!monoA.isNull());
   MATHICGB_ASSERT(!monoB.isNull());
 
-  tbb::mutex::scoped_lock lock(mCreateColumnLock);
+  mgb::tbb::mutex::scoped_lock lock(mCreateColumnLock);
   // see if the column exists now after we have synchronized
   {
     const auto found(ColReader(mMap).findProduct(monoA, monoB));
diff --git a/src/mathicgb/F4MatrixBuilder2.hpp b/src/mathicgb/F4MatrixBuilder2.hpp
index 0828505..f11328e 100755
--- a/src/mathicgb/F4MatrixBuilder2.hpp
+++ b/src/mathicgb/F4MatrixBuilder2.hpp
@@ -8,7 +8,7 @@
 #include "QuadMatrix.hpp"
 #include "MonomialMap.hpp"
 #include "F4ProtoMatrix.hpp"
-#include <tbb/mutex.h>
+#include "mtbb.hpp"
 #include <vector>
 
 /** Class for constructing an F4 matrix.
@@ -80,7 +80,7 @@ private:
     const Poly* poly;
     const Poly* sPairPoly;
   };
-  typedef tbb::parallel_do_feeder<RowTask> TaskFeeder;
+  typedef mgb::tbb::parallel_do_feeder<RowTask> TaskFeeder;
 
   /// Creates a column with monomial label x and schedules a new row to
   /// reduce that column if possible. Here x is monoA if monoB is
@@ -132,7 +132,7 @@ private:
 
   std::vector<char> mIsColumnToLeft;
   const size_t mMemoryQuantum;
-  tbb::mutex mCreateColumnLock;
+  mgb::tbb::mutex mCreateColumnLock;
   monomial mTmp;
   const PolyBasis& mBasis;
   Map mMap;
diff --git a/src/mathicgb/F4MatrixProjection.cpp b/src/mathicgb/F4MatrixProjection.cpp
index f5b45ea..4eb1377 100644
--- a/src/mathicgb/F4MatrixProjection.cpp
+++ b/src/mathicgb/F4MatrixProjection.cpp
@@ -227,7 +227,7 @@ QuadMatrix F4MatrixProjection::makeAndClear(const size_t quantum) {
 
 QuadMatrix F4MatrixProjection::makeAndClearOneStep(const size_t quantum) {
   // Construct top/bottom row permutation
-  TopBottom<F4ProtoMatrix::Row> tb(mLeftMonomials.size(), ring());
+   TopBottom<F4ProtoMatrix::Row> tb(mLeftMonomials.size(), ring());
   const auto end = mMatrices.end();
   for (auto it = mMatrices.begin(); it != end; ++it) {
     const auto& matrix = **it;
diff --git a/src/mathicgb/F4MatrixReducer.cpp b/src/mathicgb/F4MatrixReducer.cpp
index 6240fe4..f11a54d 100644
--- a/src/mathicgb/F4MatrixReducer.cpp
+++ b/src/mathicgb/F4MatrixReducer.cpp
@@ -5,8 +5,8 @@
 #include "SparseMatrix.hpp"
 #include "PolyRing.hpp"
 #include "LogDomain.hpp"
+#include "mtbb.hpp"
 
-#include <tbb/tbb.h>
 #include <algorithm>
 #include <vector>
 #include <stdexcept>
@@ -220,7 +220,7 @@ namespace {
 
     SparseMatrix reduced(qm.topRight.memoryQuantum());
 
-    tbb::enumerable_thread_specific<DenseRow> denseRowPerThread([&](){
+    mgb::tbb::enumerable_thread_specific<DenseRow> denseRowPerThread([&](){
       return DenseRow();
     }); 
 
@@ -228,9 +228,9 @@ namespace {
 
     std::vector<SparseMatrix::RowIndex> rowOrder(rowCount);
 
-    tbb::mutex lock;
-    tbb::parallel_for(tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount, 2),
-      [&](const tbb::blocked_range<SparseMatrix::RowIndex>& range)
+    mgb::tbb::mutex lock;
+    mgb::tbb::parallel_for(mgb::tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount, 2),
+      [&](const mgb::tbb::blocked_range<SparseMatrix::RowIndex>& range)
     {
       auto& denseRow = denseRowPerThread.local();
       for (auto it = range.begin(); it != range.end(); ++it) {
@@ -261,7 +261,7 @@ namespace {
             }
           }
         }
-        tbb::mutex::scoped_lock lockGuard(lock);
+        mgb::tbb::mutex::scoped_lock lockGuard(lock);
         for (size_t pivot = 0; pivot < pivotCount; ++pivot) {
 		  MATHICGB_ASSERT(denseRow[pivot] < std::numeric_limits<SparseMatrix::Scalar>::max());
           if (denseRow[pivot] != 0)
@@ -272,8 +272,8 @@ namespace {
       }
     });
 
-    tbb::parallel_for(tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount),
-      [&](const tbb::blocked_range<SparseMatrix::RowIndex>& range)
+    mgb::tbb::parallel_for(mgb::tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount),
+      [&](const mgb::tbb::blocked_range<SparseMatrix::RowIndex>& range)
       {for (auto iter = range.begin(); iter != range.end(); ++iter)
     {
       const auto i = iter;
@@ -290,7 +290,7 @@ namespace {
         denseRow.addRowMultiple(it.scalar(), begin, end);
       }
 
-      tbb::mutex::scoped_lock lockGuard(lock);
+      mgb::tbb::mutex::scoped_lock lockGuard(lock);
       bool zero = true;
 	  for (SparseMatrix::ColIndex col = 0; col < rightColCount; ++col) {
         const auto entry =
@@ -315,8 +315,8 @@ namespace {
 
     // convert to dense representation 
     std::vector<DenseRow> dense(rowCount);
-    tbb::parallel_for(tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount),
-      [&](const tbb::blocked_range<SparseMatrix::RowIndex>& range)
+    mgb::tbb::parallel_for(mgb::tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount),
+      [&](const mgb::tbb::blocked_range<SparseMatrix::RowIndex>& range)
       {for (auto it = range.begin(); it != range.end(); ++it)
     {
       const auto row = it;
@@ -349,9 +349,9 @@ namespace {
       size_t const reducerCount = reduced.rowCount();
 
       //std::cout << "reducing " << reduced.rowCount() << " out of " << toReduce.rowCount() << std::endl;
-      tbb::mutex lock;
-      tbb::parallel_for(tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount),
-        [&](const tbb::blocked_range<SparseMatrix::RowIndex>& range)
+      mgb::tbb::mutex lock;
+      mgb::tbb::parallel_for(mgb::tbb::blocked_range<SparseMatrix::RowIndex>(0, rowCount),
+        [&](const mgb::tbb::blocked_range<SparseMatrix::RowIndex>& range)
         {for (auto it = range.begin(); it != range.end(); ++it)
       {
         const auto row = it;
@@ -386,7 +386,7 @@ namespace {
           MATHICGB_ASSERT(col < colCount);
           bool isNewReducer = false;
           {
-            tbb::mutex::scoped_lock lockGuard(lock);
+            mgb::tbb::mutex::scoped_lock lockGuard(lock);
             if (!columnHasPivot[col]) {
               columnHasPivot[col] = true;
               isNewReducer = true;
@@ -417,8 +417,8 @@ namespace {
       nextReducers.clear();
     }
 
-    tbb::parallel_for(tbb::blocked_range<size_t>(0, rowCount),
-      [&](const tbb::blocked_range<size_t>& range)
+    mgb::tbb::parallel_for(mgb::tbb::blocked_range<size_t>(0, rowCount),
+      [&](const mgb::tbb::blocked_range<size_t>& range)
       {for (auto it = range.begin(); it != range.end(); ++it)
     {
       const size_t row = it;
diff --git a/src/mathicgb/FixedSizeMonomialMap.h b/src/mathicgb/FixedSizeMonomialMap.h
index cef61f5..fa7a60f 100755
--- a/src/mathicgb/FixedSizeMonomialMap.h
+++ b/src/mathicgb/FixedSizeMonomialMap.h
@@ -1,24 +1,24 @@
-#ifndef MATHICGB_FIXED_SIZE_MONOMIAL_MAP_GUARD
-#define MATHICGB_FIXED_SIZE_MONOMIAL_MAP_GUARD
-
+#ifndef MATHICGB_FIXED_SIZE_MONOMIAL_MAP_GUARD
+#define MATHICGB_FIXED_SIZE_MONOMIAL_MAP_GUARD
+
 #include "Atomic.hpp"
 #include "PolyRing.hpp"
+#include "mtbb.hpp"
 #include <memtailor.h>
-#include <tbb/tbb.h>
 #include <limits>
 #include <vector>
 #include <algorithm>
-
-/// Concurrent hashtable mapping from monomials to T with a fixed number of
-/// buckets. Lookups are lockless while insertions grab a lock.
-///
-/// There is no limitation on the number of entries that can be inserted,
-/// but performance will suffer if the ratio of elements to buckets gets
-/// high.
-///
-/// You can insert new values but you cannot change the value that an
-/// already-inserted value maps to. It is possible to clear the table
-/// but this operation is not safe for concurrency.
+
+/// Concurrent hashtable mapping from monomials to T with a fixed number of
+/// buckets. Lookups are lockless while insertions grab a lock.
+///
+/// There is no limitation on the number of entries that can be inserted,
+/// but performance will suffer if the ratio of elements to buckets gets
+/// high.
+///
+/// You can insert new values but you cannot change the value that an
+/// already-inserted value maps to. It is possible to clear the table
+/// but this operation is not safe for concurrency.
 template<class T>
 class FixedSizeMonomialMap {
 public:
@@ -174,7 +174,7 @@ public:
   /// p.first.second is a internal monomial that equals value.first.
   std::pair<std::pair<const mapped_type*, ConstMonomial>, bool>
   insert(const value_type& value) {
-    const tbb::mutex::scoped_lock lockGuard(mInsertionMutex);
+    const mgb::tbb::mutex::scoped_lock lockGuard(mInsertionMutex);
     // find() loads buckets with memory_order_consume, so it may seem like
     // we need some extra synchronization to make sure that we have the
     // most up to date view of the bucket that value.first goes in -
@@ -289,16 +289,16 @@ private:
   std::unique_ptr<Atomic<Node*>[]> const mBuckets;
   const PolyRing& mRing;
   memt::BufferPool mNodeAlloc; // nodes are allocated from here.
-  tbb::mutex mInsertionMutex;
+  mgb::tbb::mutex mInsertionMutex;
 
 public:
   class const_iterator {
   public:
     typedef std::forward_iterator_tag iterator_category;
     typedef std::pair<mapped_type, ConstMonomial> value_type;
-    typedef ptrdiff_t difference_type;
-	typedef size_t distance_type;
-	typedef value_type* pointer;
+    typedef ptrdiff_t difference_type;
+	typedef size_t distance_type;
+	typedef value_type* pointer;
 	typedef value_type& reference;
 
     const_iterator(): mNode(0), mBucket(0), mBucketsEnd(0) {}
@@ -373,5 +373,5 @@ public:
     const Atomic<Node*>* mBucketsEnd;
   };
 };
-
-#endif
+
+#endif
diff --git a/src/mathicgb/LogDomain.cpp b/src/mathicgb/LogDomain.cpp
index ce6e5e2..c3f0eaf 100755
--- a/src/mathicgb/LogDomain.cpp
+++ b/src/mathicgb/LogDomain.cpp
@@ -3,10 +3,9 @@
 
 #include "LogDomainSet.hpp"
 #include <mathic.h>
-#include <tbb/tbb.h>
 #include <iostream>
 
-static const auto logDomainGlobalStartTime= tbb::tick_count::now();
+static const auto logDomainGlobalStartTime = mgb::tbb::tick_count::now();
 
 LogDomain<true>::LogDomain(
   const char* const name,
@@ -79,7 +78,7 @@ void LogDomain<true>::Timer::stop() {
   if (!mLogger.enabled())
     return;
   TimeInterval interval;
-  interval.realSeconds = (tbb::tick_count::now() - mRealTicks).seconds();
+  interval.realSeconds = (mgb::tbb::tick_count::now() - mRealTicks).seconds();
   mLogger.recordTime(interval);
   return;
 }
@@ -88,7 +87,7 @@ void LogDomain<true>::Timer::start() {
   if (!mLogger.enabled() || mTimerRunning)
     return;
   mTimerRunning = true;
-  mRealTicks = tbb::tick_count::now();
+  mRealTicks = mgb::tbb::tick_count::now();
 }
 
 LogDomainInternal::LogAliasRegisterer::LogAliasRegisterer(const char* alias, const char* of) {
diff --git a/src/mathicgb/LogDomain.hpp b/src/mathicgb/LogDomain.hpp
index a77abec..7894db2 100755
--- a/src/mathicgb/LogDomain.hpp
+++ b/src/mathicgb/LogDomain.hpp
@@ -1,7 +1,7 @@
 #ifndef MATHICGB_LOG_DOMAIN_GUARD
 #define MATHICGB_LOG_DOMAIN_GUARD
 
-#include <tbb/tbb.h>
+#include "mtbb.hpp"
 #include <ostream>
 #include <ctime>
 #include <sstream>
@@ -125,7 +125,7 @@ public:
 private:
   LogDomain<true>& mLogger;
   bool mTimerRunning;
-  tbb::tick_count mRealTicks; // high precision
+  mgb::tbb::tick_count mRealTicks; // high precision
 };
 
 /// This is a compile-time disabled logger. You are not supposed to dynamically
diff --git a/src/mathicgb/LogDomainSet.cpp b/src/mathicgb/LogDomainSet.cpp
index 5a4941d..53f2ed2 100644
--- a/src/mathicgb/LogDomainSet.cpp
+++ b/src/mathicgb/LogDomainSet.cpp
@@ -4,7 +4,7 @@
 #include <mathic.h>
 
 LogDomainSet::LogDomainSet():
-  mStartTime(tbb::tick_count::now()) {
+  mStartTime(mgb::tbb::tick_count::now()) {
 }
 
 void LogDomainSet::registerLogDomain(LogDomain<true>& domain) {
@@ -144,7 +144,7 @@ void LogDomainSet::printCountReport(std::ostream& out) const {
 }
 
 void LogDomainSet::printTimeReport(std::ostream& out) const {
-  const auto allTime = (tbb::tick_count::now() - mStartTime).seconds();
+  const auto allTime = (mgb::tbb::tick_count::now() - mStartTime).seconds();
 
   mathic::ColumnPrinter pr;
   auto& names = pr.addColumn(true);
diff --git a/src/mathicgb/LogDomainSet.hpp b/src/mathicgb/LogDomainSet.hpp
index 4edf81c..efa84a7 100755
--- a/src/mathicgb/LogDomainSet.hpp
+++ b/src/mathicgb/LogDomainSet.hpp
@@ -2,12 +2,12 @@
 #define MATHICGB_LOG_DOMAIN_SET_GUARD
 
 #include "LogDomain.hpp"
+#include "mtbb.hpp"
 #include <string>
 #include <vector>
 #include <algorithm>
 #include <cstring>
 #include <ostream>
-#include <tbb/tbb.h>
 
 class LogDomainSet {
 public:
@@ -79,7 +79,7 @@ private:
 
   std::vector<LogDomain<true>*> mLogDomains;
   std::vector<std::pair<const char*, const char*>> mAliases;
-  tbb::tick_count mStartTime;
+  mgb::tbb::tick_count mStartTime;
 };
 
 #endif
diff --git a/src/mathicgb/MonomialMap.hpp b/src/mathicgb/MonomialMap.hpp
index 9b0c535..6975c43 100755
--- a/src/mathicgb/MonomialMap.hpp
+++ b/src/mathicgb/MonomialMap.hpp
@@ -4,8 +4,8 @@
 #include "FixedSizeMonomialMap.h"
 #include "Atomic.hpp"
 #include "PolyRing.hpp"
+#include "mtbb.hpp"
 #include <memtailor.h>
-#include <tbb/tbb.h>
 #include <limits>
 #include <vector>
 #include <algorithm>
@@ -139,7 +139,7 @@ public:
   /// internal monomial that equals value.first.
   std::pair<std::pair<const mapped_type*, ConstMonomial>, bool>
   insert(const value_type& value) {
-    const tbb::mutex::scoped_lock lockGuard(mInsertionMutex);
+    const mgb::tbb::mutex::scoped_lock lockGuard(mInsertionMutex);
 
     // We can load mMap as std::memory_order_relaxed because we have already
     // synchronized with all other mutators by locking mInsertionMutex;
@@ -179,7 +179,7 @@ public:
   /// Return the number of entries. This method requires locking so do not
   /// call too much. The count may have 
   size_t entryCount() const {
-    const tbb::mutex::scoped_lock lockGuard(mInsertionMutex);
+    const mgb::tbb::mutex::scoped_lock lockGuard(mInsertionMutex);
     // We can load with std::memory_order_relaxed because we are holding the
     // lock.
     auto& map = *mMap.load(std::memory_order_relaxed);
@@ -197,7 +197,7 @@ private:
 
   Atomic<FixedSizeMap*> mMap;
   const PolyRing& mRing;
-  mutable tbb::mutex mInsertionMutex;
+  mutable mgb::tbb::mutex mInsertionMutex;
 
   /// Only access this field while holding the mInsertionMutex lock.
   size_t mCapacityUntilGrowth;
diff --git a/src/mathicgb/QuadMatrix.cpp b/src/mathicgb/QuadMatrix.cpp
index 45b9e3e..d1a4944 100755
--- a/src/mathicgb/QuadMatrix.cpp
+++ b/src/mathicgb/QuadMatrix.cpp
@@ -1,8 +1,8 @@
 #include "stdinc.h"
 #include "QuadMatrix.hpp"
 
+#include "mtbb.hpp"
 #include <mathic.h>
-#include <tbb/tbb.h>
 #include <ostream>
 #include <sstream>
 
@@ -311,7 +311,7 @@ void QuadMatrix::sortColumnsLeftRightParallel() {
   std::vector<ColIndex> leftPermutation;
   std::vector<ColIndex> rightPermutation;
   
-  tbb::parallel_for(0, 2, 1, [&](int i) {
+  mgb::tbb::parallel_for(0, 2, 1, [&](int i) {
     if (i == 0)
       leftPermutation =
         sortColumnMonomialsAndMakePermutation(leftColumnMonomials, *ring);
@@ -320,7 +320,7 @@ void QuadMatrix::sortColumnsLeftRightParallel() {
         sortColumnMonomialsAndMakePermutation(rightColumnMonomials, *ring);
   });
 
-  tbb::parallel_for(0, 4, 1, [&](int i) {
+  mgb::tbb::parallel_for(0, 4, 1, [&](int i) {
     if (i == 0)
       topRight.applyColumnMap(rightPermutation);
     else if (i == 1)
diff --git a/src/mathicgb/mtbb.hpp b/src/mathicgb/mtbb.hpp
new file mode 100644
index 0000000..5cacdd1
--- /dev/null
+++ b/src/mathicgb/mtbb.hpp
@@ -0,0 +1,230 @@
+#ifndef MATHICGB_TBB_GUARD
+#define MATHICGB_TBB_GUARD
+
+//#define MATHICGB_NO_TBB
+
+#ifndef MATHICGB_NO_TBB
+#include <tbb/tbb.h>
+
+namespace mgb {
+  namespace tbb {
+    using ::tbb::task_scheduler_init;
+    using ::tbb::mutex;
+    using ::tbb::parallel_do_feeder;
+    using ::tbb::enumerable_thread_specific;
+    using ::tbb::parallel_do;
+    using ::tbb::parallel_for;
+    using ::tbb::parallel_sort;
+    using ::tbb::blocked_range;
+    using ::tbb::tick_count;
+  }
+}
+
+#else
+#include <functional>
+#include <vector>
+#include <ctime>
+
+namespace mgb {
+  namespace tbb {
+    class task_scheduler_init {
+    public:
+      task_scheduler_init(int) {}
+      static const int automatic = 1;
+    };
+
+    class mutex {
+    public:
+      mutex(): mLocked(false) {}
+
+      class scoped_lock {
+      public:
+        scoped_lock(): mMutex(0) {}
+        scoped_lock(mutex& m): mMutex(&m) {mMutex->lock();}
+        ~scoped_lock() {
+          if (mMutex != 0)
+            release();
+        }
+
+        void acquire(mutex& m) {
+          MATHICGB_ASSERT(mMutex == 0);
+          mMutex = &m;
+        }
+
+        bool try_acquire(mutex& m) {
+          MATHICGB_ASSERT(mMutex == 0);
+          if (!m.try_lock())
+            return false;
+          mMutex = &m;
+          return true;
+        }
+
+        void release() {
+          MATHICGB_ASSERT(mMutex != 0);
+          mMutex->unlock();
+          mMutex = 0;
+        }
+
+      private:
+        mutex* mMutex;
+      };
+
+      void lock() {
+        MATHICGB_ASSERT(!mLocked); // deadlock
+        mLocked = true;
+      }
+
+      bool try_lock() {
+        if (mLocked)
+          return false;
+        lock();
+        return true;
+      }
+
+      void unlock() {
+        MATHICGB_ASSERT(mLocked);
+        mLocked = false;
+      }
+
+    private:
+      bool mLocked;
+    };
+
+    template<class T>
+    class enumerable_thread_specific {
+    public:
+      template<class Op>
+      enumerable_thread_specific(Op&& creater): mCreater(creater) {}
+
+      bool empty() const {return mObj.get() == 0;}
+
+      T& local() {
+        if (empty())
+          mObj = make_unique<T>(mCreater());
+        MATHICGB_ASSERT(!empty());
+        return *mObj;
+      }
+
+      T* begin() {
+        if (empty())
+          return 0;
+        else
+          return mObj.get();
+      }
+
+      T* end() {
+        if (empty())
+          return  0;
+        else
+          return begin() + 1;
+      }
+
+      void clear() {
+        mObj.reset(0);
+      }
+
+    private:
+      std::function<T()> mCreater;
+      std::unique_ptr<T> mObj;
+    };
+
+    template<class Value>
+    class blocked_range {
+    public:
+      typedef size_t size_type;
+      typedef Value const_iterator;
+
+      blocked_range(Value begin, Value end, size_t grainSize = 1):
+        mBegin(begin), mEnd(end), mGrainSize(grainSize) {}
+
+      size_type size() const {return end() - begin();}
+      bool empty() const {return mBegin == mEnd;}
+      size_type grainsize() const {return grainSize;}
+      bool is_divisible() const {return false;}
+
+      const_iterator begin() const {return mBegin;}
+      const_iterator end() const {return mEnd;}
+
+    private:
+      const_iterator mBegin;
+      const_iterator mEnd;
+      size_type mGrainSize;
+    };
+    
+    template<class Range, class Func>
+    void parallel_for(Range&& range, Func&& f) {
+      f(range);
+    }
+
+    template<class Index, class Func>
+    void parallel_for(Index begin, Index end, Index step, Func&& f) {
+      for (auto i = begin; i < end; i += step)
+        f(i);
+    }
+
+    template<class T>
+    class parallel_do_feeder {
+    public:
+      parallel_do_feeder(std::vector<T>& tasks): mTasks(tasks) {}
+
+      template<class TT>
+      void add(TT&& t) {mTasks.push_back(std::forward<TT>(t));}
+
+    private:
+      std::vector<T>& mTasks;
+    };
+
+    template<class InputIterator, class Body>
+    void parallel_do(InputIterator begin, InputIterator end, Body body) {
+      typedef std::remove_reference<decltype(*begin)>::type Task;
+      std::vector<Task> tasks;
+      parallel_do_feeder<Task> feeder(tasks);
+      for (; begin != end; ++begin) {
+        tasks.push_back(*begin);
+        while (!tasks.empty()) {
+          auto task = std::move(tasks.back());
+          tasks.pop_back();
+          body(task, feeder);
+        }
+      }
+    }
+
+    template<class It, class Pred>
+    void parallel_sort(It begin, It end, Pred&& pred) {
+      std::sort(begin, end, pred);
+    }
+
+    class tick_count {
+    public:
+      tick_count(): mTime(0) {}
+
+      static tick_count now() {
+        tick_count t;
+        t.mTime = std::time(0);
+        return t;
+      }
+
+      class interval_t {
+      public:
+        interval_t(double seconds): mSeconds(seconds) {}
+
+        double seconds() const {return mSeconds;}
+
+      private:
+        const double mSeconds;
+      };
+
+      interval_t operator-(tick_count t) const {
+        return interval_t(std::difftime(mTime, t.mTime));
+      }
+
+    private:
+      std::time_t mTime;
+    };
+  }
+}
+
+#endif
+
+
+#endif
diff --git a/src/test/F4MatrixBuilder.cpp b/src/test/F4MatrixBuilder.cpp
index 4b4d27f..d41acb6 100755
--- a/src/test/F4MatrixBuilder.cpp
+++ b/src/test/F4MatrixBuilder.cpp
@@ -7,9 +7,9 @@
 #include "mathicgb/Ideal.hpp"
 #include "mathicgb/PolyBasis.hpp"
 #include "mathicgb/io-util.hpp"
+#include "mathicgb/mtbb.hpp"
 
 #include <gtest/gtest.h>
-#include <tbb/tbb.h>
 #include <memory>
 
 namespace {
@@ -53,7 +53,7 @@ namespace {
 
 TEST(F4MatrixBuilder, Empty) {
   for (int threadCount = 1; threadCount < 4; ++threadCount) {
-    tbb::task_scheduler_init scheduler(threadCount);
+    mgb::tbb::task_scheduler_init scheduler(threadCount);
     BuilderMaker maker;
     F4MatrixBuilder& builder = maker.create();
 
@@ -70,7 +70,7 @@ TEST(F4MatrixBuilder, Empty) {
 
 TEST(F4MatrixBuilder, SPair) {
   for (int threadCount = 1; threadCount < 4; ++threadCount) {
-    tbb::task_scheduler_init scheduler(threadCount);
+    mgb::tbb::task_scheduler_init scheduler(threadCount);
     BuilderMaker maker;
     const Poly& p1 = maker.addBasisElement("a4c2-d");
     const Poly& p2 = maker.addBasisElement("a4b+d");
@@ -100,7 +100,7 @@ TEST(F4MatrixBuilder, SPair) {
 
 TEST(F4MatrixBuilder, OneByOne) {
   for (int threadCount = 1; threadCount < 4; ++threadCount) {
-    tbb::task_scheduler_init scheduler(threadCount);
+    mgb::tbb::task_scheduler_init scheduler(threadCount);
     BuilderMaker maker;
     const Poly& p = maker.addBasisElement("a");
     F4MatrixBuilder& builder = maker.create();
diff --git a/src/test/gb-test.cpp b/src/test/gb-test.cpp
index 31de756..1322585 100755
--- a/src/test/gb-test.cpp
+++ b/src/test/gb-test.cpp
@@ -11,6 +11,7 @@
 #include "mathicgb/GroebnerBasis.hpp"
 #include "mathicgb/SignatureGB.hpp"
 #include "mathicgb/BuchbergerAlg.hpp"
+#include "mathicgb/mtbb.hpp"
 #include "test/ideals.hpp"
 
 #include <cstdio>
@@ -19,7 +20,6 @@
 #include <sstream>
 #include <memory>
 #include <gtest/gtest.h>
-#include <tbb/tbb.h>
 
 TEST(IO, ideal) {
   const char* idealA_fromStr_format = 
@@ -290,7 +290,7 @@ spairQueue	reducerType	divLookup	monTable	buchberger	postponeKoszul	useBaseDivis
     MATHICGB_ASSERT
       (Reducer::makeReducerNullOnUnknown(red, I->ring()).get() != 0);
 
-    tbb::task_scheduler_init scheduler(threadCount);
+    mgb::tbb::task_scheduler_init scheduler(threadCount);
     if (buchberger) {
       const auto reducer = Reducer::makeReducer
         (Reducer::reducerType(reducerType), I->ring());

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