Boost logo

Boost Users :

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


On Thu, Aug 13, 2009 at 7:14 AM, OvermindDL1<overminddl1_at_[hidden]> wrote:
> 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.

Er, do not use the recursive_variant parts, I just looked at the
multi-array library and it is fully dynamic already, so yea, take out
the recursive_variant parts and use it without those:
        typedef boost::variant
                <multi_array<int, 2>
                ,multi_array<int, 3>
                ,multi_array<int, 4>
                ,multi_array<int, 5>
                ,multi_array<int, 6>
                ,multi_array<int, 7>
                ,multi_array<int, 8>
> multi_array_variant_t;


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