[mathicgb] 128/393: Improved logging, now with timing support

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:46 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 e597ebaa1598e50423b918325c67601a287c1d61
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Thu Dec 13 19:09:47 2012 +0100

    Improved logging, now with timing support
---
 src/cli/CommonParams.cpp         |   2 -
 src/mathicgb/F4MatrixReducer.cpp |  17 +-
 src/mathicgb/F4Reducer.cpp       | 416 +++++++++++++++++++--------------------
 src/mathicgb/LogDomain.cpp       |  70 ++++++-
 src/mathicgb/LogDomain.hpp       | 163 +++++++++++++--
 src/mathicgb/QuadMatrix.cpp      |  18 +-
 src/mathicgb/SparseMatrix.cpp    |   4 +-
 7 files changed, 457 insertions(+), 233 deletions(-)

diff --git a/src/cli/CommonParams.cpp b/src/cli/CommonParams.cpp
index d3cf0b0..f5a9044 100644
--- a/src/cli/CommonParams.cpp
+++ b/src/cli/CommonParams.cpp
@@ -68,8 +68,6 @@ void CommonParams::perform() {
 
   // delete the old init object first to make the new one take control.
   mTbbInit.reset();
-  std::unique_ptr<tbb::task_scheduler_init> mTbbInit;
-
   mTbbInit = make_unique<tbb::task_scheduler_init>(
     mThreadCount.value() == 0 ?
       tbb::task_scheduler_init::automatic :
diff --git a/src/mathicgb/F4MatrixReducer.cpp b/src/mathicgb/F4MatrixReducer.cpp
index 41c33a9..829377c 100755
--- a/src/mathicgb/F4MatrixReducer.cpp
+++ b/src/mathicgb/F4MatrixReducer.cpp
@@ -10,7 +10,7 @@
 #include <algorithm>
 #include <vector>
 #include <stdexcept>
-#include <map>
+#include <map>  
 #include <string>
 #include <cstdio>
 #include <iostream>
@@ -141,7 +141,8 @@ namespace {
 
     const auto leftColCount = qm.computeLeftColCount();
 //      static_cast<SparseMatrix::ColIndex>(qm.leftColumnMonomials.size());
-    const auto rightColCount = static_cast<SparseMatrix::ColIndex>(qm.computeRightColCount());
+    const auto rightColCount =
+      static_cast<SparseMatrix::ColIndex>(qm.computeRightColCount());
 //      static_cast<SparseMatrix::ColIndex>(qm.rightColumnMonomials.size());
     MATHICGB_ASSERT(leftColCount == reduceByLeft.rowCount());
     const auto pivotCount = leftColCount;
@@ -252,6 +253,11 @@ namespace {
     const SparseMatrix& toReduce,
     const SparseMatrix::Scalar modulus
   ) {
+      const char* p = STR(MATHICGB_IF_LOG(F4MatrixReduce));
+
+    MATHICGB_LOG_TIME(F4MatrixReduce) <<
+      "Reducing matrix to row echelon form\n";
+
     const auto colCount = toReduce.computeColCount();
     const auto rowCount = toReduce.rowCount();
 
@@ -375,10 +381,13 @@ namespace {
   }
 }
 
+#define STR(X) #X
 SparseMatrix F4MatrixReducer::reduceToBottomRight(const QuadMatrix& matrix) {
   MATHICGB_ASSERT(matrix.debugAssertValid());
-  if (::logs::F4MatrixReduce.enabled())
-    matrix.printSizes(::logs::F4MatrixReduce.stream());
+  const char* p = STR(MATHICGB_IF_LOG(F4MatrixReduce));
+  /*MATHICGB_IF_LOG(F4MatrixReduce) {
+    matrix.printSizes(log.stream();
+  };*/
   return reduce(matrix, mModulus);
 }
 
diff --git a/src/mathicgb/F4Reducer.cpp b/src/mathicgb/F4Reducer.cpp
index 8688d70..52b7e09 100755
--- a/src/mathicgb/F4Reducer.cpp
+++ b/src/mathicgb/F4Reducer.cpp
@@ -1,215 +1,215 @@
-#include "stdinc.h"
-#include "F4Reducer.hpp"
-
-#include "F4MatrixBuilder.hpp"
-#include "F4MatrixReducer.hpp"
-#include "QuadMatrix.hpp"
-#include <iostream>
-#include <limits>
-
-F4Reducer::F4Reducer(const PolyRing& ring):
-  mFallback(Reducer::makeReducer(Reducer::Reducer_BjarkeGeo, ring)),
-  mRing(ring),
-  mMemoryQuantum(0),
+#include "stdinc.h"
+#include "F4Reducer.hpp"
+
+#include "F4MatrixBuilder.hpp"
+#include "F4MatrixReducer.hpp"
+#include "QuadMatrix.hpp"
+#include <iostream>
+#include <limits>
+
+F4Reducer::F4Reducer(const PolyRing& ring):
+  mFallback(Reducer::makeReducer(Reducer::Reducer_BjarkeGeo, ring)),
+  mRing(ring),
+  mMemoryQuantum(0),
   mStoreToFile(""),
-  mMinEntryCountForStore(0),
-  mMatrixSaveCount(0) {
-}
+  mMinEntryCountForStore(0),
+  mMatrixSaveCount(0) {
+}
 
 void F4Reducer::writeMatricesTo(std::string file, size_t minEntries) {
   mStoreToFile = std::move(file);
   mMinEntryCountForStore = minEntries;
   mMatrixSaveCount = 0;
 }
-
-std::unique_ptr<Poly> F4Reducer::classicReduce
-(const Poly& poly, const PolyBasis& basis) {
-  if (tracingLevel >= 2)
-    std::cerr <<
-      "F4Reducer: Using fall-back reducer for single classic reduction\n";
-
-  std::unique_ptr<Poly> p;
-  p = mFallback->classicReduce(poly, basis);
-  mSigStats = mFallback->sigStats();
-  mClassicStats = mFallback->classicStats();
-  return p;
-}
-
-std::unique_ptr<Poly> F4Reducer::classicTailReduce
-(const Poly& poly, const PolyBasis& basis) {
-  std::unique_ptr<Poly> p;
-  if (tracingLevel >= 2)
-    std::cerr <<
-      "F4Reducer: Using fall-back reducer for single classic tail reduction\n";
-
-  p = mFallback->classicTailReduce(poly, basis);
-  mSigStats = mFallback->sigStats();
-  mClassicStats = mFallback->classicStats();
-  return p;
-}
-
-std::unique_ptr<Poly> F4Reducer::classicReduceSPoly(
-  const Poly& a,
-  const Poly& b,
-  const PolyBasis& basis
-) {
-  if (tracingLevel >= 2)
-    std::cerr << "F4Reducer: "
-      "Using fall-back reducer for single classic S-pair reduction\n";
-  return mFallback->classicReduceSPoly(a, b, basis);
-}
-
-void F4Reducer::classicReduceSPolySet(
-  std::vector<std::pair<size_t, size_t> >& spairs,
-  const PolyBasis& basis,
-  std::vector<std::unique_ptr<Poly> >& reducedOut
-) {
-  if (spairs.size() <= 1) {
-    if (tracingLevel >= 2)
-      std::cerr << "F4Reducer: Using fall-back reducer for "
-        << spairs.size() << " S-pairs.\n";
-    mFallback->classicReduceSPolySet(spairs, basis, reducedOut);
-    return;
-  }
-  reducedOut.clear();
-
-  MATHICGB_ASSERT(!spairs.empty());
-  if (tracingLevel >= 2)
-    std::cerr << "F4Reducer: Reducing " << spairs.size() << " S-polynomials.\n";
-
-  SparseMatrix reduced;
-  std::vector<monomial> monomials;
-  {
-    QuadMatrix qm;
-    {
-      F4MatrixBuilder builder(basis, mMemoryQuantum);
-      for (auto it = spairs.begin(); it != spairs.end(); ++it) {
-        builder.addSPolynomialToMatrix
-          (basis.poly(it->first), basis.poly(it->second));
-      }
-      builder.buildMatrixAndClear(qm);
-
-      // there has to be something to reduce
-      MATHICGB_ASSERT(qm.bottomLeft.rowCount() > 0);
-    }
-    saveMatrix(qm);
-    reduced = F4MatrixReducer(basis.ring().charac()).
-      reducedRowEchelonFormBottomRight(qm);
-    monomials = std::move(qm.rightColumnMonomials);
-    const auto end = qm.leftColumnMonomials.end();
-    for (auto it = qm.leftColumnMonomials.begin(); it != end; ++it)
-      mRing.freeMonomial(*it);
-  }
-
-  if (tracingLevel >= 2)
-    std::cerr << "F4Reducer: Extracted " << reduced.rowCount()
-              << " non-zero rows\n";
-
-  for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) {
-    auto p = make_unique<Poly>(basis.ring());
-    reduced.rowToPolynomial(row, monomials, *p);
-    reducedOut.push_back(std::move(p));
-  }
-  const auto end = monomials.end();
-  for (auto it = monomials.begin(); it != end; ++it)
-    mRing.freeMonomial(*it);
-}
-
-void F4Reducer::classicReducePolySet
-(const std::vector<std::unique_ptr<Poly> >& polys,
- const PolyBasis& basis,
- std::vector<std::unique_ptr<Poly> >& reducedOut)
-{
-  if (polys.size() <= 1) {
-    if (tracingLevel >= 2)
-      std::cerr << "F4Reducer: Using fall-back reducer for "
-                << polys.size() << " polynomials.\n";
-    mFallback->classicReducePolySet(polys, basis, reducedOut);
-    return;
-  }
-
-  reducedOut.clear();
-
-  MATHICGB_ASSERT(!polys.empty());
-  if (tracingLevel >= 2)
-    std::cerr << "F4Reducer: Reducing " << polys.size() << " polynomials.\n";
-
-  SparseMatrix reduced;
-  std::vector<monomial> monomials;
-  {
-    QuadMatrix qm;
-    {
-      F4MatrixBuilder builder(basis, mMemoryQuantum);
-      for (auto it = polys.begin(); it != polys.end(); ++it)
-        builder.addPolynomialToMatrix(**it);
-      builder.buildMatrixAndClear(qm);
-
-      // there has to be something to reduce
-      MATHICGB_ASSERT(qm.bottomLeft.rowCount() > 0);
-    }
-    saveMatrix(qm);
-    reduced = F4MatrixReducer(basis.ring().charac()).
-      reducedRowEchelonFormBottomRight(qm);
-    monomials = std::move(qm.rightColumnMonomials);
-    for (auto it = qm.leftColumnMonomials.begin();
-      it != qm.leftColumnMonomials.end(); ++it)
-      mRing.freeMonomial(*it);
-  }
-
-  if (tracingLevel >= 2)
-    std::cerr << "F4Reducer: Extracted " << reduced.rowCount()
-              << " non-zero rows\n";
-
-  for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) {
-    auto p = make_unique<Poly>(basis.ring());
-    reduced.rowToPolynomial(row, monomials, *p);
-    reducedOut.push_back(std::move(p));
-  }
-  const auto end = monomials.end();
-  for (auto it = monomials.begin(); it != end; ++it)
-    mRing.freeMonomial(*it);
-}
-
-Poly* F4Reducer::regularReduce(
-  const_monomial sig,
-  const_monomial multiple,
-  size_t basisElement,
-  const GroebnerBasis& basis
-) {
-  if (tracingLevel >= 2)
-    std::cerr <<
-      "F4Reducer: Using fall-back reducer for single regular reduction\n";
-  Poly* p = mFallback->regularReduce(sig, multiple, basisElement, basis);
-  mSigStats = mFallback->sigStats();
-  mClassicStats = mFallback->classicStats();
-  return p;
-}
-
-void F4Reducer::setMemoryQuantum(size_t quantum) {
-  mMemoryQuantum = quantum;
-}
-
-std::string F4Reducer::description() const {
-  return "F4 reducer";
-}
-
-size_t F4Reducer::getMemoryUse() const {
-  return 0; // @todo: implement
-}
-
-void F4Reducer::saveMatrix(const QuadMatrix& matrix) {
-  if (mStoreToFile.empty())
-    return;
-  const auto entryCount = matrix.entryCount();
-  if (mMinEntryCountForStore > entryCount)
-    return;
-  ++mMatrixSaveCount;
-  std::ostringstream fileName;
-  fileName << mStoreToFile << '-' << mMatrixSaveCount << ".qmat";
-  if (tracingLevel > 2)
-    std::cerr << "F4Reducer: Saving matrix to " << fileName.str() << '\n';
-  FILE* file = fopen(fileName.str().c_str(), "wb");
-  // @todo: fix leak of file on exception
-  matrix.write(static_cast<SparseMatrix::Scalar>(mRing.charac()), file);
-  fclose(file);
-}
+
+std::unique_ptr<Poly> F4Reducer::classicReduce
+(const Poly& poly, const PolyBasis& basis) {
+  if (tracingLevel >= 2)
+    std::cerr <<
+      "F4Reducer: Using fall-back reducer for single classic reduction\n";
+
+  std::unique_ptr<Poly> p;
+  p = mFallback->classicReduce(poly, basis);
+  mSigStats = mFallback->sigStats();
+  mClassicStats = mFallback->classicStats();
+  return p;
+}
+
+std::unique_ptr<Poly> F4Reducer::classicTailReduce
+(const Poly& poly, const PolyBasis& basis) {
+  std::unique_ptr<Poly> p;
+  if (tracingLevel >= 2)
+    std::cerr <<
+      "F4Reducer: Using fall-back reducer for single classic tail reduction\n";
+
+  p = mFallback->classicTailReduce(poly, basis);
+  mSigStats = mFallback->sigStats();
+  mClassicStats = mFallback->classicStats();
+  return p;
+}
+
+std::unique_ptr<Poly> F4Reducer::classicReduceSPoly(
+  const Poly& a,
+  const Poly& b,
+  const PolyBasis& basis
+) {
+  if (tracingLevel >= 2)
+    std::cerr << "F4Reducer: "
+      "Using fall-back reducer for single classic S-pair reduction\n";
+  return mFallback->classicReduceSPoly(a, b, basis);
+}
+
+void F4Reducer::classicReduceSPolySet(
+  std::vector<std::pair<size_t, size_t> >& spairs,
+  const PolyBasis& basis,
+  std::vector<std::unique_ptr<Poly> >& reducedOut
+) {
+  if (spairs.size() <= 1) {
+    if (tracingLevel >= 2)
+      std::cerr << "F4Reducer: Using fall-back reducer for "
+        << spairs.size() << " S-pairs.\n";
+    mFallback->classicReduceSPolySet(spairs, basis, reducedOut);
+    return;
+  }
+  reducedOut.clear();
+
+  MATHICGB_ASSERT(!spairs.empty());
+  if (tracingLevel >= 2)
+    std::cerr << "F4Reducer: Reducing " << spairs.size() << " S-polynomials.\n";
+
+  SparseMatrix reduced;
+  std::vector<monomial> monomials;
+  {
+    QuadMatrix qm;
+    {
+      F4MatrixBuilder builder(basis, mMemoryQuantum);
+      for (auto it = spairs.begin(); it != spairs.end(); ++it) {
+        builder.addSPolynomialToMatrix
+          (basis.poly(it->first), basis.poly(it->second));
+      }
+      builder.buildMatrixAndClear(qm);
+
+      // there has to be something to reduce
+      MATHICGB_ASSERT(qm.bottomLeft.rowCount() > 0);
+    }
+    saveMatrix(qm);
+    reduced = F4MatrixReducer(basis.ring().charac()).
+      reducedRowEchelonFormBottomRight(qm);
+    monomials = std::move(qm.rightColumnMonomials);
+    const auto end = qm.leftColumnMonomials.end();
+    for (auto it = qm.leftColumnMonomials.begin(); it != end; ++it)
+      mRing.freeMonomial(*it);
+  }
+
+  if (tracingLevel >= 2)
+    std::cerr << "F4Reducer: Extracted " << reduced.rowCount()
+              << " non-zero rows\n";
+
+  for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) {
+    auto p = make_unique<Poly>(basis.ring());
+    reduced.rowToPolynomial(row, monomials, *p);
+    reducedOut.push_back(std::move(p));
+  }
+  const auto end = monomials.end();
+  for (auto it = monomials.begin(); it != end; ++it)
+    mRing.freeMonomial(*it);
+}
+
+void F4Reducer::classicReducePolySet
+(const std::vector<std::unique_ptr<Poly> >& polys,
+ const PolyBasis& basis,
+ std::vector<std::unique_ptr<Poly> >& reducedOut)
+{
+  if (polys.size() <= 1) {
+    if (tracingLevel >= 2)
+      std::cerr << "F4Reducer: Using fall-back reducer for "
+                << polys.size() << " polynomials.\n";
+    mFallback->classicReducePolySet(polys, basis, reducedOut);
+    return;
+  }
+
+  reducedOut.clear();
+
+  MATHICGB_ASSERT(!polys.empty());
+  if (tracingLevel >= 2)
+    std::cerr << "F4Reducer: Reducing " << polys.size() << " polynomials.\n";
+
+  SparseMatrix reduced;
+  std::vector<monomial> monomials;
+  {
+    QuadMatrix qm;
+    {
+      F4MatrixBuilder builder(basis, mMemoryQuantum);
+      for (auto it = polys.begin(); it != polys.end(); ++it)
+        builder.addPolynomialToMatrix(**it);
+      builder.buildMatrixAndClear(qm);
+
+      // there has to be something to reduce
+      MATHICGB_ASSERT(qm.bottomLeft.rowCount() > 0);
+    }
+    saveMatrix(qm);
+    reduced = F4MatrixReducer(basis.ring().charac()).
+      reducedRowEchelonFormBottomRight(qm);
+    monomials = std::move(qm.rightColumnMonomials);
+    for (auto it = qm.leftColumnMonomials.begin();
+      it != qm.leftColumnMonomials.end(); ++it)
+      mRing.freeMonomial(*it);
+  }
+
+  if (tracingLevel >= 2)
+    std::cerr << "F4Reducer: Extracted " << reduced.rowCount()
+              << " non-zero rows\n";
+
+  for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) {
+    auto p = make_unique<Poly>(basis.ring());
+    reduced.rowToPolynomial(row, monomials, *p);
+    reducedOut.push_back(std::move(p));
+  }
+  const auto end = monomials.end();
+  for (auto it = monomials.begin(); it != end; ++it)
+    mRing.freeMonomial(*it);
+}
+
+Poly* F4Reducer::regularReduce(
+  const_monomial sig,
+  const_monomial multiple,
+  size_t basisElement,
+  const GroebnerBasis& basis
+) {
+  if (tracingLevel >= 2)
+    std::cerr <<
+      "F4Reducer: Using fall-back reducer for single regular reduction\n";
+  Poly* p = mFallback->regularReduce(sig, multiple, basisElement, basis);
+  mSigStats = mFallback->sigStats();
+  mClassicStats = mFallback->classicStats();
+  return p;
+}
+
+void F4Reducer::setMemoryQuantum(size_t quantum) {
+  mMemoryQuantum = quantum;
+}
+
+std::string F4Reducer::description() const {
+  return "F4 reducer";
+}
+
+size_t F4Reducer::getMemoryUse() const {
+  return 0; // @todo: implement
+}
+
+void F4Reducer::saveMatrix(const QuadMatrix& matrix) {
+  if (mStoreToFile.empty())
+    return;
+  const auto entryCount = matrix.entryCount();
+  if (mMinEntryCountForStore > entryCount)
+    return;
+  ++mMatrixSaveCount;
+  std::ostringstream fileName;
+  fileName << mStoreToFile << '-' << mMatrixSaveCount << ".qmat";
+  if (tracingLevel > 2)
+    std::cerr << "F4Reducer: Saving matrix to " << fileName.str() << '\n';
+  FILE* file = fopen(fileName.str().c_str(), "wb");
+  // @todo: fix leak of file on exception
+  matrix.write(static_cast<SparseMatrix::Scalar>(mRing.charac()), file);
+  fclose(file);
+}
diff --git a/src/mathicgb/LogDomain.cpp b/src/mathicgb/LogDomain.cpp
index 235623a..fcf6007 100755
--- a/src/mathicgb/LogDomain.cpp
+++ b/src/mathicgb/LogDomain.cpp
@@ -9,13 +9,81 @@ LogDomain<true>::LogDomain(
   const char* const description,
   const bool enabled
 ):
+  mEnabled(enabled),
   mName(name),
   mDescription(description),
-  mEnabled(enabled)
+  mInterval()
 {
   LogDomainSet::singleton().registerLogDomain(*this);
 }
 
+LogDomain<true>::~LogDomain() {
+  if (enabled() && mHasTime) {
+    stream() << mName << " total time:           ";
+    mInterval.print(stream());
+    stream() << '\n';
+  }
+}
+
 std::ostream& LogDomain<true>::stream() {
   return std::cerr;
 }
+
+LogDomain<true>::Timer LogDomain<true>::timer() {
+  return Timer(*this);
+}
+
+void LogDomain<true>::TimeInterval::print(std::ostream& out) const {
+  const auto oldFlags = out.flags();
+  const auto oldPrecision = out.precision();
+  out.precision(3);
+  out << std::fixed << realSeconds << "s (real)";
+  // todo: restore the stream state using RAII, since the above code might
+  // throw an exception.
+  out.precision(oldPrecision);
+  out.flags(oldFlags);
+}
+
+void LogDomain<true>::recordTime(TimeInterval interval) {
+  if (!enabled())
+    return;
+  mInterval.realSeconds += interval.realSeconds;
+  mHasTime = true;
+
+  MATHICGB_ASSERT(mName != 0);
+  stream() << mName << " time recorded:        ";
+  interval.print(stream());
+  stream() << std::endl;
+}
+
+LogDomain<true>::Timer::Timer(LogDomain<true>& logger):
+  mLogger(logger),
+  mTimerRunning(false),
+  mRealTicks()
+{
+  start();
+}
+
+LogDomain<true>::Timer::~Timer() {
+  stop();
+}
+
+void LogDomain<true>::Timer::stop() {
+  if (!running())
+    return;
+  mTimerRunning = false;
+  if (!mLogger.enabled())
+    return;
+  mTimerRunning = false;
+  TimeInterval interval;
+  interval.realSeconds = (tbb::tick_count::now() - mRealTicks).seconds();
+  mLogger.recordTime(interval);
+  return;
+}
+
+void LogDomain<true>::Timer::start() {
+  if (!mLogger.enabled() || mTimerRunning)
+    return;
+  mTimerRunning = true;
+  mRealTicks = tbb::tick_count::now();
+}
diff --git a/src/mathicgb/LogDomain.hpp b/src/mathicgb/LogDomain.hpp
index a47fd71..f3de139 100755
--- a/src/mathicgb/LogDomain.hpp
+++ b/src/mathicgb/LogDomain.hpp
@@ -1,9 +1,28 @@
 #ifndef MATHICGB_LOG_DOMAIN_GUARD
 #define MATHICGB_LOG_DOMAIN_GUARD
 
+#include <tbb/tbb.h>
 #include <ostream>
-
-template<bool Enabled>
+#include <ctime>
+#include <sstream>
+
+/// A named area of logging that can be turned on or off at runtime and at
+/// compile time.
+///
+/// A logger that is turned off at compile time emits no code
+/// into the executable and all the code that writes to that logger is also
+/// removed by the optimizer if it is written in the correct way. Use the
+/// logging macroes to ensure proper use so that compile-time disabled
+/// LogDomains properly have zero overhead. LogDomains can be turned on
+/// and off at compile time and at runtime individually.
+///
+/// Compile-time enabled loggers automatically register themselves with
+/// LogDomainSet::singleton().
+///
+/// @todo: support turning all loggers off globally with a macro, regardless
+/// of their individual compile-time on/off setting.
+
+template<bool CompileTimeEnabled>
 class LogDomain {};
 
 template<>
@@ -16,6 +35,7 @@ public:
     const char* const description,
     const bool enabled
   );
+  ~LogDomain();
 
   const char* name() const {return mName;}
   const char* description() const {return mDescription;}
@@ -25,12 +45,64 @@ public:
 
   std::ostream& stream();
 
+  /// Class for recording time that is logged.
+  class Timer;
+
+  /// Returns a started timer that you can move from.
+  Timer timer();
+
 private:
+  struct TimeInterval {
+    // todo: support user time too. clock() doesn't seem to sum the time
+    // for all threads, so that didn't work.
+    double realSeconds;
+
+    void print(std::ostream& out) const;
+  };
+  void recordTime(TimeInterval interval);
+
+  bool mEnabled;
   const char* mName;
   const char* mDescription;
-  bool mEnabled;
+
+  TimeInterval mInterval; /// Total amount of time recorded on this log.
+
+  /// Indicates if any period of time has been recorded, even if that period
+  /// of time was recorded as 0 seconds.
+  bool mHasTime;
 };
 
+class LogDomain<true>::Timer {
+public:
+  /// Start the timer running. The elapsed time will be logged to the logger
+  /// once the timer is stopped or destructed.
+  Timer(LogDomain<true>& logger);
+
+  /// Stops the timer.
+  ~Timer();
+
+  /// Returns true if the timer is currently recording time.
+  bool running() const {return mTimerRunning;}
+
+  /// Stops recording time and logs the elapsed time to the logger.
+  ///
+  /// This is a no-op if the timer is not running. If the logger
+  /// is disabled then no time is logged.
+  void stop();
+
+  /// Start recording time on a stopped timer.
+  ///
+  /// This is a no-op is the timer is already running or if the logger is
+  /// disabled.
+  void start();
+
+private:
+  LogDomain<true>& mLogger;
+  bool mTimerRunning;
+  tbb::tick_count mRealTicks; // high precision
+};
+
+/// This is a compile-time disabled logger.
 template<>
 class LogDomain<false> {
 public:
@@ -40,6 +112,15 @@ public:
 
   bool enabled() const {return false;}
 
+  class Timer {
+  public:
+    Timer(LogDomain<false>&) {}
+    bool running() const {return false;}
+    void stop() {}
+    void start() {}
+  };
+  Timer timer() {return Timer(*this);}
+
   std::ostream& stream() {
     MATHICGB_ASSERT(false);
     return *static_cast<std::ostream*>(0);
@@ -47,6 +128,9 @@ public:
 };
 
 namespace LogDomainInternal {
+  // Support code for the logging macroes
+
+
   template<class Tag, bool Default>
   struct SelectValue {static const bool value = Default;};
 
@@ -59,6 +143,13 @@ namespace LogDomainInternal {
 
   template<bool Default>
   struct SelectValue<Tag_1<int>, Default> {static const bool value = true;};
+
+  template<class L>
+  struct LambdaRunner {L& log;};
+  template<class L>
+  LambdaRunner<L> lambdaRunner(L& log) {return LambdaRunner{log};}
+  template<class L, class T>
+  void operator+(LambdaRunner<L> runner, T& lambda) {lambda(runner.log);}
 }
 
 /// Defines LogDomainInternal::value_##NAME to be equal to the value of
@@ -73,10 +164,11 @@ namespace LogDomainInternal {
       SelectValue<SelectedTag_##NAME, DEFAULT_VALUE>::value; \
   }
 
-/// Defines logs::obj##NAME to be a LogDomain that is compile-time
-/// enabled depending on MATHICGB_LOG_##NAME (see MATHICGB_CAPTURE_LOG_ENABLED)
-/// and that is initially runtime enabled depending on the value of
-/// DEFAULT_RUNTIME_ENABLED.
+/// Defines a LogDomain with the given name and description.
+///
+/// The logger is default compile-time enabled depending on MATHICGB_LOG_##NAME
+/// (see MATHICGB_CAPTURE_LOG_ENABLED) and it is initially runtime
+/// enabled depending on the value of DEFAULT_RUNTIME_ENABLED.
 #define MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS(NAME, DESCRIPTION, DEFAULT_RUNTIME_ENABLED, DEFAULT_COMPILE_TIME_ENABLED) \
   MATHICGB_CAPTURE_LOG_ENABLED(NAME, DEFAULT_COMPILE_TIME_ENABLED); \
   namespace logs { \
@@ -84,16 +176,59 @@ namespace LogDomainInternal {
     Type##NAME NAME(#NAME, DESCRIPTION, DEFAULT_RUNTIME_ENABLED); \
   }
 
-/// Defines logs::##NAME to be a LogDomain. It is compile-time enabled
-/// by default and runtime disabled by default.
+/// Defines a LogDomain with the given name and description.
+///
+/// By default, the logger is compile-time enabled and runtime disabled.
 #define MATHICGB_DEFINE_LOG_DOMAIN(NAME, DESCRIPTION) \
   MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS(NAME, DESCRIPTION, 0, 1);
 
-/// Have the code X in the program if and only if logging is not globally
-/// compile-time disabled.
-#define MATHICGB_IF_LOG(X) X
-
+/// This expression yields an l-value reference to the indicated logger.
+///
+/// Example:
+///   auto timer = MATHICGB_LOGGER(MyDomain).timer();
+#define MATHICGB_LOGGER(DOMAIN) ::logs::##DOMAIN
+
+/// This expression yields the type of the indicated logger.
+///
+/// Example:
+///   if (MATHICGB_LOGGER_TYPE(MyDomain)::compileTimeEnabled)
+///     std::ostream << "MyDomain is compiled time enabled";
+#define MATHICGB_LOGGER_TYPE(DOMAIN) ::logs::Type##DOMAIN
+
+/// Runs the code in the following scope delimited by braces {} if the indicated
+/// logger is enabled - otherwise does nothing. Within the following scope
+/// there is a local reference variable log that refers to the indicated
+/// logger.
+///
+/// Example:
+///   MATHICGB_IF_LOG(MyDomain) {
+///     std::string msg;
+///     expensiveFunction(msg);
+///     log << msg;
+///   }
+#define MATHICGB_IF_LOG(DOMAIN) \
+  if (MATHICGB_LOGGER(DOMAIN).enabled()) \
+    LogDomainInternal::lambdaRunner(MATHICGB_LOGGER(DOMAIN)) + \
+      [&](MATHICGB_LOGGER_TYPE(DOMAIN)& log)
+
+/// Display information to the log using <<.
+/// If domain is not enabled then the log message is not displayed and the
+/// code after << is not executed.
+///
+/// Example: (f() only called if logger is enabled)
+///   MATHICGB_LOG(domain) << "f() = " << f();
 #define MATHICGB_LOG(DOMAIN) \
-  if (::logs::##NAME.enabled()) ::logs::##NAME.stream()
+  if (MATHICGB_LOGGER(DOMAIN).enabled()) MATHICGB_LOGGER(DOMAIN).stream()
+
+/// Will log the time to execute the remaining code in the current scope
+/// to the indicated domain. Also supports printing a message using <<.
+/// The message is printed right away while the time is printed when
+/// the scope ends.
+///
+/// Example:
+///   MATHICGB_LOG_SCOPE_TIME(MyDomain) << "Starting timed task";
+#define MATHICGB_LOG_TIME(DOMAIN) \
+  auto MATHICGB_timer##DOMAIN##_##__LINE__##(MATHICGB_LOGGER(DOMAIN).timer()); \
+  MATHICGB_LOG(DOMAIN)
 
 #endif
diff --git a/src/mathicgb/QuadMatrix.cpp b/src/mathicgb/QuadMatrix.cpp
index 3ec8bd7..68c3a19 100755
--- a/src/mathicgb/QuadMatrix.cpp
+++ b/src/mathicgb/QuadMatrix.cpp
@@ -67,10 +67,24 @@ size_t QuadMatrix::rowCount() const {
 }
 
 SparseMatrix::ColIndex QuadMatrix::computeLeftColCount() const {
+  if (!leftColumnMonomials.empty()) {
+    MATHICGB_ASSERT(
+      leftColumnMonomials.size() <=
+      std::numeric_limits<SparseMatrix::ColIndex>::max()
+    );
+    return static_cast<SparseMatrix::ColIndex>(leftColumnMonomials.size());
+  }
   return std::max(topLeft.computeColCount(), bottomLeft.computeColCount());
 }
 
 SparseMatrix::ColIndex QuadMatrix::computeRightColCount() const {
+  if (!rightColumnMonomials.empty()) {
+    MATHICGB_ASSERT(
+      rightColumnMonomials.size() <=
+      std::numeric_limits<SparseMatrix::ColIndex>::max()
+    );
+    return static_cast<SparseMatrix::ColIndex>(rightColumnMonomials.size());
+  }
   return std::max(topRight.computeColCount(), bottomRight.computeColCount());
 }
 
@@ -106,8 +120,8 @@ void QuadMatrix::printSizes(std::ostream& out) const {
   const char* const line = "----------";
 
   pr[0] << '\n';
-  pr[1] << ColPr::commafy(leftColumnMonomials.size()) << "  \n";
-  pr[2] << ColPr::commafy(rightColumnMonomials.size()) << "  \n";
+  pr[1] << ColPr::commafy(computeLeftColCount()) << "  \n";
+  pr[2] << ColPr::commafy(computeRightColCount()) << "  \n";
 
   pr[0] << "/\n";
   pr[1] << line << "|\n";
diff --git a/src/mathicgb/SparseMatrix.cpp b/src/mathicgb/SparseMatrix.cpp
index 87f0e59..895247c 100755
--- a/src/mathicgb/SparseMatrix.cpp
+++ b/src/mathicgb/SparseMatrix.cpp
@@ -395,14 +395,14 @@ namespace {
   void writeMany(const std::vector<T>& v, FILE* file) {
     if (v.empty())
       return;
-    fwrite(&v[0], sizeof(T), v.size(), file);
+    fwrite(v.data(), sizeof(T), v.size(), file);
   }
 
   template<class T>
   void readMany(FILE* file, size_t count, std::vector<T>& v) {
     size_t const originalSize = v.size();
     v.resize(originalSize + count);
-    fread(&v[originalSize], sizeof(T), count, file);
+    fread(v.data() + originalSize, sizeof(T), count, file);
   }
 
 }

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