After seeing the example of xtensor
matrix adaptors of 1D containers, I was wondering if it is also possible to have a resizeable adaptor of STL containers like vectors.
In the process, I would like to also find out and use the type of such an adaptor, instead of using auto
.
Starting with the C-style array adaptor and compute()
function --which multiplies the 2x1 row vector with a 2x1 column and returns the xarray as a 2x2 matrix-- I got as far as
#include <cstddef>
#include <xtensor/xarray.hpp>
#include <xtensor/xadapt.hpp>
template <class A>
void compute ( A& a ) {
xt::xarray<double> b {1., 2.};
b.reshape({2, 1});
a = a * b; // size has changed, shape is now { 2, 2 }
}
int main() {
std::size_t size = 2;
////////////////////////////////////////////////////////////////
double* datavx = new double [ size ];
for ( unsigned i = 0; i < size; i++ )
datavx [ i ] = i;
std::vector<std::size_t> shapevx = { size };
std::vector<std::size_t> stridesvx = { 1 };
auto vx = xt::adapt ( datavx, size, xt::acquire_ownership(), shapevx, stridesvx );
std::cout << "\nbefore reshape\n";
for ( unsigned i = 0; i < size; i++ )
std::cout << datavx [ i ] << " ";
compute ( vx );
std::cout << "\nafter reshape\n";
for ( unsigned i = 0; i < size * size; i++ )
std::cout << datavx [ i ] << " ";
////////////////////////////////////////////////////////////////
std::vector<double> datav (size);
for (unsigned i = 0; i < size; i++)
datav[i] = i;
std::vector<std::size_t> shapev = shapevx;
std::vector<std::size_t> stridesv = stridesvx;
using shape_type = std::vector<size_t>;
using adaptor_typev = xt::xarray_adaptor<xt::xbuffer_adaptor<double*, xt::acquire_ownership>, xt::layout_type::dynamic, shape_type >;
adaptor_typev my_adaptorv = xt::adapt(datav.data(), size, xt::acquire_ownership(), shapev, stridesv);
std::cout << "\n";
std::cout << "\nbefore reshape\n";
for (unsigned i = 0; i < size; i++)
std::cout << datav[i] << " ";
compute(my_adaptorv);
std::cout << "\nafter reshape\n";
for (unsigned i = 0; i < size * size; i++)
std::cout << datav[i] << " ";
std::cout << std::endl;
// prints 0 1 0 2
}
The output that I get from the C-style xarray_adaptor (from the xtensor website) and the std:vector xarray_adaptor, respectively, is:
before reshape
0 1
after reshape
0 1 0 2
before reshape
0 1
after reshape
0 1 nan -5.11336e-311
==== Program exited with exit code: 3221226356 ====
Time elapsed: 000:00.016 (MM:SS.MS)
The last two values suggest that the resize has not happened, and the non-zero exit code shows all is not well. If I run it in the debugger, it exits with a SIGTRAP at the end of main()
. The top of the call stack says ntdll!RtllsZeroMemory
.
Does that mean that to resize an xarray
adaptor of an std::vector
, I need to resize the vector separately? Or is there a way to do it without trying to become owner of the vector's data (that does not sound right to begin with)?
The comments by @JaMit and @IgorTandetnik helped me in the right direction -- I did need an adaptor of a vector not a C-style array.
But the examples with vector adaptors all used auto
declarations and I still wanted to know the type of the adaptor.
An old answer on StackOverflow allowed me to combine the two: this bit of code shows the type of the adaptor, which I then used to do the declaration 'manually'.