[mathicgb] 390/393: Added flatten() to the Range.hpp. It flattens a range of ranges into a single range.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:38 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 c48c1c1321f47b4305dff8e6beddad58b9906666
Author: Bjarke Hammersholt Roune <www.broune.com>
Date:   Tue Oct 1 19:42:03 2013 -0700

    Added flatten() to the Range.hpp. It flattens a range of ranges into a single range.
---
 src/mathicgb/MonoMonoid.hpp |   4 +-
 src/mathicgb/Range.hpp      | 139 ++++++++++++++++++++++++++++++++++++++++++++
 src/test/Range.cpp          |  43 ++++++++++++++
 3 files changed, 185 insertions(+), 1 deletion(-)

diff --git a/src/mathicgb/MonoMonoid.hpp b/src/mathicgb/MonoMonoid.hpp
index 8d7ba55..4052597 100755
--- a/src/mathicgb/MonoMonoid.hpp
+++ b/src/mathicgb/MonoMonoid.hpp
@@ -1621,6 +1621,7 @@ public:
       mMonos.resize(offset + monoid().entryCount());
       monoid().copy(mono, *MonoPtr(mMonos.data() + offset));
       MATHICGB_ASSERT(monoid().debugValid(back()));
+      MATHICGB_ASSERT(monoid().equal(back(), mono));
     }
 
     template<class Monoid>
@@ -1633,10 +1634,11 @@ public:
       mMonos.resize(offset + monoid().entryCount());
       monoid().copy(monoidMono, mono, *MonoPtr(mMonos.data() + offset));
       MATHICGB_ASSERT(monoid().debugValid(back()));
+      MATHICGB_ASSERT(monoid().equal(monoidMono, mono, back()));
     }
 
     void swap(MonoVector& v) {
-      MATHICGB_ASSERT(&monoid() == &v.monoid());
+      MATHICGB_ASSERT(monoid() == v.monoid());
       mMonos.swap(v.mMonos);
     }
 
diff --git a/src/mathicgb/Range.hpp b/src/mathicgb/Range.hpp
old mode 100644
new mode 100755
index 35b95c3..d598532
--- a/src/mathicgb/Range.hpp
+++ b/src/mathicgb/Range.hpp
@@ -387,5 +387,144 @@ auto adjPairRange(
   return adjPairRange(std::begin(r), std::end(r));
 }
 
+// *** Flatten range of ranges into a single range
+
+/// Flatten is an iterator that iterates through each range in a range
+/// of ranges. The point is to enable the flatten() function defined
+/// further down in this header. This iterator is invalidated whenever
+/// the outer range or any of the inner ranges invalidate any iterator
+/// or change their number of elements.
+template<class OuterIterator>
+class Flatten {
+public:
+  typedef decltype(std::begin(*std::declval<OuterIterator>())) InnerIteratorRaw;
+  typedef typename std::decay<InnerIteratorRaw>::type InnerIterator;
+
+  typedef typename std::iterator_traits<InnerIterator>::difference_type
+    difference_type;
+  typedef typename std::iterator_traits<InnerIterator>::value_type value_type;
+  typedef typename std::iterator_traits<InnerIterator>::pointer pointer;
+  typedef typename std::iterator_traits<InnerIterator>::reference reference;
+
+  // It would be possible to do something fancy here to identify the exact
+  // most general iterator category. I have not done that since I have not
+  // needed it so far.
+  typedef std::forward_iterator_tag iterator_category;
+
+  Flatten() {}
+  Flatten(const OuterIterator outerBegin, const OuterIterator outerEnd):
+    mOuter(outerBegin),
+    mOuterEnd(outerEnd)
+  {
+    adjustOuter();
+    MATHICGB_ASSERT(debugAssertValid());
+  }
+
+  Flatten& operator++() {
+    MATHICGB_ASSERT(debugAssertValid());
+    MATHICGB_ASSERT(!atEnd());
+    MATHICGB_ASSERT(mInner != std::end(*mOuter));
+
+    ++mInner;
+    if (mInner == std::end(*mOuter)) {
+      ++mOuter;
+      adjustOuter();
+    }
+
+    MATHICGB_ASSERT(debugAssertValid());
+    return *this;
+  }
+
+  decltype(*std::declval<InnerIterator>()) operator*() const {
+    MATHICGB_ASSERT(!atEnd());
+    return *mInner;
+  }
+
+  bool equal(const Flatten& f) const {
+    MATHICGB_ASSERT(debugAssertValid());
+    MATHICGB_ASSERT(f.debugAssertValid());
+
+    if (atEnd())
+      return f.atEnd();
+    else
+      return mInner == f.mInner;
+  }
+
+  bool debugAssertValid() const {
+    MATHICGB_ASSERT(atEnd() || mInner != std::end(*mOuter));
+    return true;
+  }
+
+private:
+  bool atEnd() const {return mOuter == mOuterEnd;}
+
+  void adjustOuter() {
+    for (; !atEnd(); ++mOuter) {
+      if (std::begin(*mOuter) != std::end(*mOuter)) {
+        mInner = std::begin(*mOuter);
+        return;
+      }
+    }
+  }
+
+  InnerIterator mInner;
+  OuterIterator mOuter;
+  OuterIterator mOuterEnd;
+};
+
+template<class OuterIterator>
+bool operator==(
+  const Flatten<OuterIterator>& a,
+  const Flatten<OuterIterator>& b
+) {
+  return a.equal(b);
+}
+
+template<class OuterIterator>
+bool operator!=(
+  const Flatten<OuterIterator>& a,
+  const Flatten<OuterIterator>& b
+) {
+  return !(a == b);
+}
+
+template<class OuterIterator>
+Flatten<OuterIterator> makeFlatten(
+  OuterIterator outerIterator, 
+  OuterIterator outerEnd
+) {
+  return Flatten<OuterIterator>(outerIterator, outerEnd);
+}
+
+/// As flatten(range(begin, end)).
+template<class OuterIterator>
+Range<Flatten<OuterIterator>> flattenRange(
+  OuterIterator outerBegin,
+  OuterIterator outerEnd
+) {
+  return range(
+    makeFlatten(outerBegin, outerEnd),
+    makeFlatten(outerEnd, outerEnd)
+  );
+}
+
+/// Constructs a range of the union of all (inner) ranges in outerRange.
+///
+/// Example:
+///   std::vector<std::list<int>> v(3);
+///   v[0].push_back(1);
+///   v[2].push_back(2);
+///   v[2].push_back(3);
+///   for (const auto& i : flattenRange(v))
+///     std::cout << i << ' ';
+///
+/// The output is "1 2 3 ";
+template<class OuterRange>
+auto flattenRange(
+  OuterRange&& outerRange
+) -> decltype(flattenRange(std::begin(outerRange), std::end(outerRange))) {
+  return flattenRange(std::begin(outerRange), std::end(outerRange));
+}
+
 MATHICGB_NAMESPACE_END
 #endif
diff --git a/src/test/Range.cpp b/src/test/Range.cpp
old mode 100644
new mode 100755
index 49a43b7..593368b
--- a/src/test/Range.cpp
+++ b/src/test/Range.cpp
@@ -11,6 +11,7 @@
 #include <iterator>
 #include <vector>
 #include <list>
+#include <map>
 
 using namespace mgb;
 
@@ -164,3 +165,45 @@ TEST(Range, adjPairRange) {
   Pair adj4[] = {Pair(0, 1), Pair(1, 2), Pair(2, 3)};
   ASSERT_EQ(rangeToVector(adj4), rangeToVector(adjPairRange(intRange(4))));
 }
+
+TEST(Range, flatten) {
+  std::vector<std::list<int>> v(3);
+  v[0].push_back(1);
+  v[2].push_back(2);
+  v[2].push_back(3);
+
+  std::ostringstream out;
+  for (const auto& i : flattenRange(v))
+    out << i << ' ';
+  ASSERT_EQ("1 2 3 ", out.str());
+}
+
+TEST(Range, flattenRecursive) {
+  std::list<std::vector<std::set<int>>> outer;
+
+  outer.emplace_back();
+
+  outer.emplace_back();
+  outer.back().emplace_back();
+  outer.back().emplace_back();
+  outer.back().back().insert(1);
+  outer.back().emplace_back();
+  outer.back().back().insert(2);
+  outer.back().emplace_back();
+
+  outer.back().emplace_back();
+  outer.back().back().insert(3);
+  outer.back().back().insert(4);
+  outer.back().back().insert(5);
+  outer.back().back().insert(6);
+  outer.back().emplace_back();
+  outer.back().back().insert(7);
+
+  outer.back().emplace_back();
+  outer.back().emplace_back();
+
+  std::ostringstream out;
+  for (const auto& i : flattenRange(flattenRange(outer)))
+    out << i << ' ';
+  ASSERT_EQ("1 2 3 4 5 6 7 ", out.str());
+}

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