[multi_array] Useful algorithms (from Re: Multi_array: A "proper" iterator over a N>1 Multi_array?)
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
"Beth Jacobson" wrote [...]
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.
The usual method is to put it in the Boost Vault : http://boost-consulting.com/vault/ in a zip file. You will need to register. (The login link also takes you to a register link.) regards Andy Little
Andy Little wrote:
"Beth Jacobson" wrote
[...]
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.
The usual method is to put it in the Boost Vault :
http://boost-consulting.com/vault/
in a zip file.
You will need to register. (The login link also takes you to a register link.)
I'll also point out that there have been Wiki pages devoted to this sort of contribution for quite some time. These have the advantage that they make their way into Google. See http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?STLAlgorithmE... Although if this is limited to multi-array it might be a bit more specialized. I look at these Wiki contributions more like ideas than finished products, certainly not up to the usual Boost standards, but useful non-the-less. Jeff
Jeff Garland wrote:
Andy Little wrote:
"Beth Jacobson" wrote
[...]
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. The usual method is to put it in the Boost Vault :
My impression was that the Boost Vault is intended for libraries on the Boost candidate track, that is they're put there with an eye to eventually submitting them for inclusion the the Boost libraries. If that's true, it's not really appropriate for this stuff.
I'll also point out that there have been Wiki pages devoted to this sort of contribution for quite some time. These have the advantage that they make their way into Google. See
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?STLAlgorithmE...
Although if this is limited to multi-array it might be a bit more specialized. I look at these Wiki contributions more like ideas than finished products, certainly not up to the usual Boost standards, but useful non-the-less.
That sounds just right for these functions. They are specific to multi-arrays so they don't belong on the AlgorithmExtensions page, but I'd like to create a Boost.MultiArray/Algorithms page which could be added to as people adapt more algorithms for use with multi_arrays. Do I need to get somebody's ok for this, or can I just dive right in? (While we're at it, a "jeff's cool date time extensions" Wiki page might be nice too. ;-)) Regards, Beth
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
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
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
MA::const_reference::type, T, F, dim-1>(val, f)); return val; } }; template
struct accum_impl { 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
T multi_accum(MA& ma, T init, F f) { accum_impl impl(init, f); return impl(ma); } And a test: typedef boost::multi_array
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
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
(f)); } }; template
struct for_each_impl { F f; for_each_impl(F f) : f(f) {} void operator()(Ref r) { f(r); } };
template
void multi_for_each(MA& ma, F f) { for_each_impl impl(f); impl(ma); } And a test:
typedef boost::multi_array
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@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
I'm going to second Antonio's comments. A globally applicable iterator across a multi-array's data elements would provide a /very/ useful tool, and doesn't seem all that impossible to program, requiring all the magic be done behind the scenes in operator+ etc. In addition, I'd love to see a Boost statistical package, but am unfamiliar with the process of getting support for a new boost library, nor what the early stages of development look like. - Greg Link On May 17, 2006, at 2:46 PM, Antonio Piccolboni wrote:
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
Antonio Piccolboni wrote:
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.
I agree that would be the ideal solution, but the multi_array-specific algorithms have one big advantage that kind of iterator: they already exist.
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)
That's exactly the issue that these algorithms address. They accept regular multi_arrays, subarrays, and views and handle them all correctly.
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
I agree in theory, but I'm not familiar enough either with the multi_array library or template programming in general to tackle the job of writing the iterator myself. If you or someone else has definite plans to do it, I won't bother with a Wiki page for the algorithms, but if the iterator is likely to remain theoretical for the foreseeable future, it still seems worthwhile to offer a working, though imperfect solution for general use. Jeff Garland described Wiki contributions as "certainly not up to the usual Boost standards, but useful none-the-less." The algorithms don't meet Boost standards for the reasons you described, but I think they conform well to the "useful none-the-less" standard required for the Wiki. Regards, Beth
participants (5)
-
Andy Little
-
Antonio Piccolboni
-
Beth Jacobson
-
Greg Link
-
Jeff Garland