Boost logo

Boost Users :

Subject: Re: [Boost-users] question about multi_array use
From: OvermindDL1 (overminddl1_at_[hidden])
Date: 2009-08-13 09:14:07


On Thu, Aug 13, 2009 at 6:36 AM, Alle Meije Wink<a.m.wink_at_[hidden]> wrote:
> Dear OverMind
>
> Hope I'm not making this thread too long, I've tried to search the archives
> but did not get further than browsing.
>
> After looking at different options, your idea of wrapping the different
> dimensions/dimensionalities in a struct sounds like the best idea, and
> closest to the type of data and problems I'm dealing with.
>
> Would you have a few more clues (maybe code, maybe URLs) as to how to shape
> this? I had a look at
> http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern but that
> is a very broad description. As I understand it, the struct that
> encapsulates the possible dimensionalities and the CRTP class refer to the
> same solution? Or are they different things?
>
> Thanks!
> Alle Meije
>
>> Date: Fri, 7 Aug 2009 18:09:11 -0600
>> From: OvermindDL1 <overminddl1_at_[hidden]>
>> Subject: Re: [Boost-users] question about multi_array use
>>
>> You could always just wrap up each of the possible dimensions in a
>> struct that can handle the (de)serialization and everything too,
>> perhaps use crtp to put identical functionality in a non-virtual base
>> class.
>>
>>> On Fri, Aug 7, 2009 at 2:04 PM, Anton Daneyko<self_at_[hidden]> wrote:
>>> Hello,
>>>
>>> I might be wrong, but it seems the answer is "no you can't do that",
>>> because
>>> the dimensionality is a template parameter multi_array<int, 2> and
>>> multi_array<int, 3> are different types. However I would like to hear
>>> some
>>> else' opinion as well.
>>>
>>> Regards,
>>> Anton Daneyko.
>>>
>>> On Fri, Aug 7, 2009 at 3:48 PM, Alle Meije Wink <a.m.wink_at_[hidden]>
>>> wrote:
>>>>
>>>> Hello,
>>>>
>>>> I would like to use the multi_array container to handle imaging data.
>>>> The
>>>> image data can be anything up to 8-dimensional (usually up to 4) and
>>>> dimension information is found in records that accompany the binary
>>>> data.
>>>>
>>>> Would it be possible to create an image class that takes the
>>>> dimensionality and extents list as parameters, so that images of all
>>>> dimensionalities can be treated as one class?
>>>>
>>>> For example, could the dimensionality be passed as a size_t argument?
>>>>
>>>> What I understand from the multi_array paper is that the extents list
>>>> would only be required whan the array is initialised.

Bit busy currently so no real-code to test with, but I might have pseudo-code.

Hmm, I just (saved out first and) cut a large paragraph I was writing
because I just came up with another idea.

Why not use Boost.Variant stuffed with all possible types of matrices?
 A simple templated visitor could handle them all for any operations
you want, and it optimizes out quite well. If you are worried about
memory use you could wrap each matrix in the variant in a
boost::recursive_variant so that it is dynamically allocated as
necessary as well. Perhaps something like this:

typedef boost::variant
        <boost::recursive_variant< multi_array<int, 2> >
        ,boost::recursive_variant< multi_array<int, 3> >
        ,boost::recursive_variant< multi_array<int, 4> >
        ,boost::recursive_variant< multi_array<int, 5> >
        ,boost::recursive_variant< multi_array<int, 6> >
        ,boost::recursive_variant< multi_array<int, 7> >
        ,boost::recursive_variant< multi_array<int, 8> >
> multi_array_variant_2_to_8_t;
And of course you could template it so you could specify the int type
in a template parameter as well.

Then make a variant for each of your operations, something along the
lines of this for an equal test for example:
class multi_array_variant_dotproduct_compare_equality
        : public boost::static_visitor<bool>
{
public:
        template <typename T, typename U>
        bool operator()( const T &, const U & ) const
        {
                return false; // different dimensions will always test unequal
        }

        template <typename T>
        bool operator()( const T & lhs, const T & rhs ) const
        {
                return lhs==rhs;
        }
}

And you could probably template it all (maybe using fusion) so most of
of your tests could be generated for simple things like == and so
forth.

Then probably wrap it all up in a pretty class for ease of use, like
this for a beginning shell:
class multi_array_2to8
{
protected:
        typedef boost::variant
                <multi_array<int, 2>
                ,boost::recursive_variant< multi_array<int, 3> >
                ,boost::recursive_variant< multi_array<int, 4> >
                ,boost::recursive_variant< multi_array<int, 5> >
                ,boost::recursive_variant< multi_array<int, 6> >
                ,boost::recursive_variant< multi_array<int, 7> >
                ,boost::recursive_variant< multi_array<int, 8> >
> multi_array_variant_t;

        multi_array_variant_t _multi_array_variant;

        /* snip stuff */

protected: // visitors
        class multi_array_variant_dotproduct_compare_equality
                : public boost::static_visitor<bool>
        {
        public:
                template <typename T, typename U>
                bool operator()( const T &, const U & ) const
                {
                        return false; // different dimensions will always be unequal
                }

                template <typename T>
                bool operator()( const T & lhs, const T & rhs ) const
                {
                        return lhs==rhs;
                }
        }

        /* snip more stuff */

public: // op tests
        bool operator==(multi_array_2to8 const &rhs) const
        {
                return boost::apply_visitor
                        (multi_array_variant_dotproduct_compare_equality()
                        ,_multi_array_variant
                        ,rhs._multi_array_variant
                        );
        }

        /* snip the rest of the stuff */
}

For initially filling a vector would probably require a visitor using
fusion, or 7 visitors, fusion's invoke sounds a lot easier though, and
could simplify a few other visitors too, and use using fusion (and
maybe crtp, depending on how you build it) would reduce the necessary
code a lot as well.

If you are still interested in my other way, I can try to remember
what I was thinking and finish the paragraph I was doing, but that
above seems better overall...

For now though, sleep, and since I am tired enough that the screen is
blurry, I make no remarks on my above coding quality, hopefully it
works as-is, but consider it pseudo-code otherwise.


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