I have a two-dimensional native C array which was read as shorts, and I wish to map a boost::multi_array_ref
onto part of it, but express this as floats. Is there a way to set the stride in bytes (rather than multiples of the data size)?
Asked
Active
Viewed 161 times
2
-
1What do you want to achieve? Type punning like that is undefined behaviour unless you employ unions and adhere to the laws governing them. I suppose you really want to just convert the data from short to floats? – sehe May 01 '12 at 20:48
-
Indeed - the data is stored on disk as shorts, but we are deprecating that and operating on floats, so we have a conversion from short to float. The data is not even homogenous, and it would have been nice to start with a byte array, then create a reference to part of it as a view ref of floats, and another part as a view ref of shorts. – DAmann May 10 '12 at 20:12
1 Answers
0
It is really too much to ask for an array library to support strides in bytes. Even if the alignment problems are somehow solved, there are still a lot of problems with manipulating subviews and pointer arithmetic.
If you really need to manipulate byte strides, I recommend having an array of char
s (or std::byte
) and only leaving the reinterpretation of the bytes for the end.
This can be done with Boost.MultiArray, but it is easier if you use a library that does the reinterpret dirty work for you. For example Multi
#include <multi/array.hpp> // from https://gitlab.com/correaa/boost-multi/-/blob/master/test/element_transformed.cpp
namespace multi = boost::multi;
int main() {
auto n = 4, m = 3;
std::vector<float> fake_data(n*m);
fake_data[0] = 1.0F;
fake_data[1] = 2.0F;
auto custom_stride = sizeof(float); // can be different for disk-encoded data
multi::array_ref<char, 2> A({n, m*custom_stride}, reinterpret_cast<char*>(fake_data.data()));
auto const& B = A.rotated().strided(custom_stride).unrotated(); // create a strided by on CHAR!
auto [Bn, Bm] = sizes(B);
assert( Bn == 4 and Bm == 3 );
{ // you can do this with any library. Boost.MultiArray for example
assert( reinterpret_cast<float const&>(B[0][1]) == fake_data[1] );
assert( &reinterpret_cast<float const&>(B[0][1]) == &fake_data[1] );
}
{ // with this library you can make it a bit more automatic
auto const& C = B.element_transformed([](auto const& c) -> decltype(auto) {return reinterpret_cast<float const&>(c);});
auto [Cn, Cm] = sizes(C);
assert( Cn == 4 and Cm == 3 );
assert( C[0][1] == fake_data[1] );
assert( &C[0][1] == &fake_data[1] );
}
}

alfC
- 14,261
- 4
- 67
- 118