简体   繁体   中英

How do I get a view of a boost multi_array and assign it back to the same boost multi_array?

I have a function called DataView that performs the "slicing" (creation of the array_view) as follows:


template <class T>
typename Boost<T>::Array2D::template array_view<2>::type MyArray<T>::DataView(int x_start, int x_finish, int y_start, int y_finish)
{
    using range = boost::multi_array_types::index_range;

    return _Data[boost::indices[range().start(x_start).finish(x_finish).stride(1)][range().start(y_start).finish(y_finish).stride(1)]];

}

...where _Data is a private member of type Array2D (boost::multi_array) containing the data portion of MyArray. The slicing (view creation) is happening without a problem as follows:


Boost<double>::Array2D::array_view<2>::type array_view = my_array->DataView(x1, x2, y1, y2);

The problem occurs when I want to assign the newly acquired view (array_view) back to the original multi_array (my_array). I have tried to do this by creating this function on the class MyArray:


template <class T>
void MyArray<T>::Data(const typename Boost<T>::Array2D &inData)
{

    // find the dimensions of inData
    int xdim = static_cast<int>(inData.shape()[0]);
    int ydim = static_cast<int>(inData.shape()[1]);

    // resize _Data to match the size of inData
    _Data.resize(boost::extents[xdim][ydim]);

    // assign _Data to the new set of data
    _Data = inData;
}

...and calling the function with this line of code...


my_array->Data(array_view);

While the build is successful, my application is producing the following error:


base.hpp:178: Reference boost::detail::multi_array::value_accessor_one<T>::access(boost::type<Reference>, boost::detail::multi_array::value_accessor_one<T>::index, TPtr, const size_type*, const index*, const index*) const [with Reference = double&; TPtr = double*; T = double; boost::detail::multi_array::value_accessor_one<T>::index = long int; boost::detail::multi_array::multi_array_base::size_type = long unsigned int]: Assertion `size_type(idx - index_bases[0]) < extents[0]' failed.

What I really need is a simple example of how I can do one of the following:

  1. Use my current strategy of creating an array_view from my original multi_array and assigning the new view back to the original array, OR
  2. Slicing the original multi_array (in place). I've looked for an example of this solution and cannot seem to find it.

Thank you.

This turned out to be something unrelated within my program. I had other variables that were dependent on the dimensions of my array (which had changed due to the reassignment to the view) that I failed to set.

The answer to your question "assign a view back to the same array?" is simple: "don't do that".

There are two reasons for that, one trivial and the other one is more interesting.

The trivial one is that most subviews of an array are of a different size as the original array. So when a subview is assigned to an array, Boost.MultiArray will reject the assignment at runtime, simply because the library doesn't support assignment from-to arrays of different sizes (shape).

(see runtime error message here: https://godbolt.org/z/ffPo3e3hj )

So, to start, you need to use an array library that accepts assignment of arrays of arbitrary size.

And even if you could and more interestingly, array data structures and algorithms are subject to something called "aliasing" for efficiency, which means that in general you cannot use two things that share memory on the LHS and the RHS of an equation or assignment.

What you need to do is to make a copy first and then (resize and) assign back to the original array. This can be done with Boost.MultiArray but it is messy because of the trivial limitation I mention above.

Incidentally, I have a library similar to Boost.MultiArray, in which I use unary plus to break aliasing by making a copy.

    multi::array<double, 2> A({3, 3});
    A = + A({0, 2}, {0, 2}) ;  // make an independent copy of the view first, the assign to the original array

https://godbolt.org/z/ahExP787T

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM