2

I need to resize one multi_array to the size of another.

In Blitz++ I could just do

arr1.resize(arr2.shape());

Is there a multi_array solution of similar length? Because

arr1.resize(boost::extents[arr2.shape()[0]][arr2.shape()[1]]);

seems a little long and arduous.

Cory
  • 151
  • 12

2 Answers2

1

You can use the shape() member. Sadly it cannot directly serve as an ExtentList (it doesn't model the Collection concept) but it's easy to make it into one:

using MA = multi_array<double, 2>;
MA ma(extents[12][34]);
auto& ma_shape = reinterpret_cast<boost::array<size_t, MA::dimensionality> const&>(*ma.shape());

So that

// demo
std::cout << "[" << ma_shape[0] << "][" << ma_shape[1] << "]\n";

Prints [12][34].

Now, ma_shape can directly be used to reshape/resize another array:

Live On Coliru

#include <boost/multi_array.hpp>
#include <iostream>

int main() {
    using namespace boost;
    using MA = multi_array<double, 2>;

    MA ma(extents[12][34]);
    auto& ma_shape = reinterpret_cast<boost::array<size_t, MA::dimensionality> const&>(*ma.shape());

    // demo
    std::cout << "[" << ma_shape[0] << "][" << ma_shape[1] << "]\n";

    // resize
    MA other;
    assert(!std::equal(ma_shape.begin(), ma_shape.end(), other.shape()));

    other.resize(ma_shape);
    assert(std::equal(ma_shape.begin(), ma_shape.end(), other.shape()));

    // reshape
    other.resize(extents[1][12*34]);
    assert(!std::equal(ma_shape.begin(), ma_shape.end(), other.shape()));

    other.reshape(ma_shape);
    assert(std::equal(ma_shape.begin(), ma_shape.end(), other.shape()));
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • That looks like it will work. I am wrapping the multi_array, so I can just hide that stuff and keep all outside code the same. Thanks. – Cory May 07 '15 at 23:57
0

I think this is another oversight of Boost.MultiArray. I have written a bunch of "utility" functions that allows to take the shape (dimension sizes), base indices (e.g. 0 or 1 for each dimension) and extensions (base indices and sizes in each dimension).

namespace boost{
template<class MultiArray>
detail::multi_array::extent_gen<MultiArray::dimensionality>
extension(MultiArray const& ma){ //this function is adapted from 
    typedef detail::multi_array::extent_gen<MultiArray::dimensionality> gen_type;
    gen_type ret;
    typedef typename gen_type::range range_type;
    for(int i=0; i != MultiArray::dimensionality; ++i)
        ret.ranges_[i] = range_type(ma.index_bases()[i], ma.index_bases()[i]+ma.shape()[i]);
    return ret;
}
}

Which is later used as:

boost::multi::array<double, 3> m(boost::multi::extents[3][4][5]);
boost::multi::array<double, 3> n(extension(m)); // n takes the extension (and shape) of m

(If the base indexes are not zero it also works. It works also for view and other multi_array-type classes.)

alfC
  • 14,261
  • 4
  • 67
  • 118