Erwin411
Erwin411

Reputation: 764

Nesting boost::multi_array?

I have a template class which does some computation and returns multi_array, a bit oversimplified like this:

template <typename T>
class C
{
public:
    typedef boost::multi_array<T, 2> result_type;

    void do_something(T const& data, unsigned i, unsigned j); // add result to R[i][j]

    result_type R;
};

Instantiating the class with a simple type T=double works fine. Now, I want to instantiate with "T=boost::multi_array<double, 1>", but such that the result type is boost::multi_array<double, 3>.

The definition multi_array<multi_array<T, N>, M>> does clearly not result in multi_array<T, N+M>, it is just a N-dimensional multi_array with elements being M-dimensional multi_arrays ...

The idea to generate such a type is motivated by the Boost manual saying

MultiArray is recursively defined; the containers at each level of the container hierarchy model MultiArray as well. Actually, it turns out that the "elements" of the intermediate multi_array levels are of type subarray.

Can one use subarray to generate a multi_array type with an effective dimensionality N+M? Maybe somehow along the following lines:

typedef typename boost::multi_array<double, 3>::subarray<1>::type value_type;
boost::multi_array<value_type, 2> a;

I'm looking for a relatively clean solution (not a lengthy hack), if this is not possible with the multi_array interface I will better rethink the design of what I'm going to implement.

Upvotes: 2

Views: 147

Answers (2)

alfC
alfC

Reputation: 16242

Of course, it makes sense to instantiate a nested Boost.MA, multi_array<multi_array<T, N>, M>>. However you are mistaken to think that this is equivalent to multi_array<T, N + M>, it is not.

Conceptually, this is because in the former case the nested arrays of dimensions M can have all different sizes.

In practice, even if all have the same sizes, the nested array will not be a contiguous (or regularly strided) memory.

Another glitch is that multi_arrays do not have value semantic because the assignment fails (throws) for incompatible sizes, which is a bummer. So, some reasonable manipulation of nested arrays could fail.

You can try my Multi array library for to workaround that glitch: https://godbolt.org/z/ec9K7Wzc4.

Upvotes: 0

Erwin411
Erwin411

Reputation: 764

I think it makes no sense to instantiate multi_array with elements of type multi_array (although it might compile). For example, it would not lead to a contiguous memory layout since the elements manage memory themselves.

To solve the problem that motivated my question, I came up with the following solution:

template <typename T>
class C
{
    enum { extra_rank = get_rank<T>() };
public:
    typedef boost::multi_array<T, 2 + extra_rank> result_type;
}

The class defines a multi_array with extra dimensions depending on the type of T. The helper function get_rank checks whether T is multi_array and returns its dimensionality, otherwise it returns 0.

Upvotes: 0

Related Questions