|
Boost Users : |
From: Antonio Piccolboni (piccolbo_at_[hidden])
Date: 2006-05-17 14:46:12
As I said in a former message that I am afraid fell through the
cracks, sorry if I am repeating myself, I don't think rewriting the
whole STL algorithm lib for multi_array is a solution. for_each,
accumulate, sort, where do we stop? I recently needed to apply random
shuffle, for instance. I think the solution is to define iterators
that provide a "flat", element by element view of a multi_array. These
iterators would be regular skip iterators that just a have a fancy
increment operation that looks at the stride vector to decide by how
much to jump when incremented. Let's say that these are returned by
begin_element and end_element. Then you could do on multi array ma
things like
for_each(ma.begin_element(), ma.end_element(), do_something())
or
accumulate(ma.begin_element(), ma.end_element(), 0)
and so on for all STL algorithms, all the statstical functions that I
wrote (GPLed, maybe the beginning of a boost stats lib?, mail me if
interested) and more.
I've been using data() and data()+num_elements for the same purpose,
but that breaks for non contiguos storage (that is, not guaranteed to
work for views)
I don't think rewriting all the algorithms for multi_array is a viable
strategy, nor is in keeping with the idea that data structures and
algorithms should be made as ortogonal as reasonably possible. Just
my 2c
Antonio
You can do that right now with data() and data() + num_elements
On 5/16/06, Beth Jacobson <bethj_at_[hidden]> wrote:
> On a recent thread, Bruno Martinez provided a std::for_each-like
> function for multi_arrays which lets users apply a function to each
> element in a multi_array or view without having to know anything about
> the dimensions. I've been playing around with it (on MSVC 7.1) and it
> works perfectly. It seems like a good utility for anyone using
> boost.multi_array.
>
> Working from Bruno's code, I wrote a similar std::accumulate-like
> function, which could also be generally useful. I'm fairly new to
> template programming, so if someone could look over the code below and
> see if I've done something dangerous or stupid, it would be much
> appreciated.
>
> Also, is there some standard Boost way of making this sort of code
> generally available? It probably isn't at a level where it could be
> included in the library, but it seems like a shame to just let it
> languish in the bowels of the mailing list archive.
>
> Anyway, here are both algorithms:
>
> My accumulate-like function:
> template<class MA, class T, class F, int dim>
> struct accum_impl
> {
> F f;
> T &val;
>
> accum_impl(T &val, F f) : f(f), val(val) {}
>
> T operator()(MA& ma)
> {
> std::for_each(ma.begin(), ma.end(), accum_impl<typename
> boost::add_const<MA::const_reference>::type, T, F, dim-1>(val, f));
> return val;
> }
> };
>
> template<class Ref, class T, class F>
> struct accum_impl<Ref, T, F, 0>
> {
> F f;
> T &val;
>
> accum_impl(T &val, F &f) : f(f), val(val) {}
>
> T operator()(Ref r)
> {
> val = f(val, r);
> return val;
> }
> };
>
> template<class MA, class T, class F>
> T multi_accum(MA& ma, T init, F f)
> {
> accum_impl<MA, T, F, MA::dimensionality> impl(init, f);
> return impl(ma);
> }
>
> And a test:
> typedef boost::multi_array<int, 3> array_type;
> typedef array_type::index_range range;
> typedef array_type::index index;
> array_type B(boost::extents[4][2][3]);
>
> int values = 0;
> for(index i = 0; i != 4; ++i)
> for(index j = 0; j != 2; ++j)
> for(index k = 0; k != 3; ++k)
> B[i][j][k] = values++;
>
> array_type::array_view<2>::type myview =
> B[ boost::indices[range(1,3)][1][range(0,2)] ];
>
> cout << "Sum: " << multi_accum(myview, 0, std::plus<int>()) << endl;
> cout << "Product: " << multi_accum(myview, 1, std::multiplies<int>()) <<
> endl;
>
>
>
> Bruno Martinez's for_each-like function:
>
> template<class MA, class F, int dim>
> struct for_each_impl
> {
> F f;
> for_each_impl(F f) : f(f) {}
>
> void operator()(MA& ma)
> {
> std::for_each(ma.begin(), ma.end(), for_each_impl<typename
> MA::reference, F, dim-1>(f));
> }
> };
>
> template<class Ref, class F>
> struct for_each_impl<Ref, F, 0>
> {
> F f;
> for_each_impl(F f) : f(f) {}
>
> void operator()(Ref r)
> {
> f(r);
> }
> };
>
> template<class MA, class F>
> void multi_for_each(MA& ma, F f)
> {
> for_each_impl<MA, F, MA::dimensionality> impl(f);
> impl(ma);
> }
>
> And a test:
>
> typedef boost::multi_array<double, 3> array_type;
> typedef array_type::index index;
> array_type myarray(boost::extents[3][4][2]);
> typedef array_type::index_range range;
> array_type::array_view<3>::type myview =
> myarray[ boost::indices[range(0,2)][range(1,3)][range(0,4,2)] ];
> multi_for_each(myview, _1 = 56);
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net