Boost logo

Boost :

From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2007-04-15 15:50:53


On 4/14/07, Neal Becker <ndbecker2_at_[hidden]> wrote:
> Here is an example:

OK, thanks for the examples. I think I understand where you're coming
from. I didn't realize ublas' matrix doesn't extend the usual
Container concepts. No begin(), just begin1() and begin2(). That's
frustrating. Also, the concepts defined in ublas documentation are
unnecessarily intrusive; i.e. too many members.

Anyway, to solve your specific problem with ublas, you need to
generate a type that models ForwardRange, ranges across the
matrix<>::size1() rows, and who's range_value<>:: type is a ublas
matrix_row. Thankfully, this type can be generated automatically using
existing Boost libraries.

Here's how. matrix_row needs a row index in the interval [0,
matrix<>::size1()). These indices can be generated from a
counting_iterator. Then you need a sequence of calls to matrix_row's
constructor to generate each row from each index. That can be done by
using transform_iterator with a lambda bound matrix_row constructor.
matrix_row already models Container (or at least it comes close
enough) and can be used with Boost.Range directly.

You could do something similar with matrix_column.

The changes to your example file below illustrate how you can deal
with a range of rows in a ublas matrix without requiring an additional
manually defined iterator or extension to Boost.Range. As far as a
generic abstraction of multi-dimensional ranges I would prefer
something closer to Shunsuke example using oven or the
slicing/subscripting-like thingy I posted rather than adopting ublas
naming conventions like size1, size2, begin1, begin2,

Hope this helps!

Daniel

$ diff -u test_range.cc~ test_range.cc
--- test_range.cc~ 2007-04-15 14:55:11.000000000 -0400
+++ test_range.cc 2007-04-15 15:35:47.000000000 -0400
@@ -1,8 +1,14 @@
+#include <boost/function.hpp>
+#include <boost/iterator/counting_iterator.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/construct.hpp>
 #include <boost/range.hpp>
  #include <boost/numeric/ublas/vector.hpp>
  #include <boost/numeric/ublas/matrix.hpp>
  #include <boost/numeric/ublas/matrix_proxy.hpp>
 #include <iostream>
+#include <iterator>

  namespace ublas = boost::numeric::ublas;

@@ -46,11 +52,16 @@
   return typename row_iterator<ublas::matrix<T> >::type (m, m.size1());
 }

-template<typename range_2d_t>
-int F (range_2d_t & rng) {
- typename row_iterator<range_2d_t>::type ri = row_begin (rng);
- for (; ri != row_end (rng); ++ri) {
- typedef typename row_iterator<range_2d_t>::row_t row_t;
+template<typename ForwardRange>
+void F (ForwardRange const& rng) {
+ typedef typename boost::range_const_iterator<
+ ForwardRange
+ >::type row_iterator;
+ row_iterator ri = boost::begin (rng);
+ for (; ri != boost::end (rng); ++ri) {
+ typedef typename std::iterator_traits<
+ row_iterator
+ >::value_type row_t;
     row_t r = *ri;
     typename boost::range_const_iterator<row_t>::type i = boost::begin (r);
     for (; i != boost::end (r); ++i)
@@ -60,12 +71,28 @@
 }

 int main() {
- ublas::matrix<int> m (2, 2);
+ using namespace boost;
+
+ typedef ublas::matrix<int> matrix_type;
+ matrix_type m(2, 2);
   for (int r = 0; r < m.size1(); ++r) {
     for (int c = 0; c < m.size2(); ++c) {
       m (r, c) = r*m.size2()+c;
     }
   }
- F (m);
+
+ typedef ublas::matrix_row<matrix_type> row_type;
+ function<row_type(int)> row_generator
+ = lambda::bind(lambda::constructor<row_type>()
+ , lambda::var(m), lambda::_1);
+
+ F (make_iterator_range(
+ make_transform_iterator(
+ make_counting_iterator(0U)
+ , row_generator)
+ , make_transform_iterator(
+ make_counting_iterator(m.size1())
+ , row_generator))
+ );
 }


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk