简体   繁体   English

如何获取 boost multi_array 的视图并将其分配回相同的 boost multi_array?

[英]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:我有一个名为 DataView 的 function 执行“切片”(创建 array_view),如下所示:


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. ...其中 _Data 是 Array2D (boost::multi_array) 类型的私有成员,其中包含 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).当我想将新获取的视图 (array_view) 分配回原始的 multi_array (my_array) 时,就会出现问题。 I have tried to do this by creating this function on the class MyArray:我试图通过在 class MyArray 上创建这个 function 来做到这一点:


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... ...并使用这行代码调用 function ...


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使用我当前的策略,从我的原始 multi_array 创建一个 array_view 并将新视图分配回原始数组,或者
  2. Slicing the original multi_array (in place).对原始的 multi_array 进行切片(就地)。 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).因此,当将子视图分配给数组时,Boost.MultiArray 将在运行时拒绝分配,仅仅是因为该库不支持从不同大小(形状)的 arrays 分配。

(see runtime error message here: https://godbolt.org/z/ffPo3e3hj ) (在此处查看运行时错误消息: https://godbolt.org/z/ffPo3e3hj

So, to start, you need to use an array library that accepts assignment of arrays of arbitrary size.因此,首先,您需要使用一个数组库来接受任意大小的 arrays 的赋值。

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.即使您可以并且更有趣的是,数组数据结构和算法也受制于称为“别名”的东西以提高效率,这意味着通常您不能使用两个在 LHS 和 RHS 上共享 memory 的东西或方程或分配。

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.这可以使用 Boost.MultiArray 来完成,但由于我上面提到的微不足道的限制,它很混乱。

Incidentally, I have a library similar to Boost.MultiArray, in which I use unary plus to break aliasing by making a copy.顺便说一句,我有一个类似于 Boost.MultiArray 的库,在其中我使用一元加号通过复制来打破别名。

    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 https://godbolt.org/z/ahExP787T

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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