[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