
On 4/14/07, Neal Becker <ndbecker2@gmail.com> 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)) + ); }