C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

Boost.MultiArray メモ

std::valarrayだと基本的には1次元のデータ構造に対してスライスを考えて多次元要素集合としてアクセスする事になる。Boost.MultiArrayなら基本的には多次元のデータ構造に対して必要ならば1次元のRAWなデータ構造も用いる事ができる。多くの場合は後者の方が扱い易くて助かる。

多次元のBoost.MultiArrayは内部構造としては連続領域が確保されているので、1次元のRAWなデータ構造に直接触れたい場合は、origin()メンバー関数により先頭要素のポインターを取得すれば良い。

目的

Boost.MultiArrayを用いて多次元の要素集合に対しランダムなインデックス値を放り込みたい。

コード

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

int main(){
  using value_type = size_t;
  const size_t dimension = 3;
  using c = boost::multi_array<value_type, dimension>;

  const size_t scaling = 2;
  auto a = c(boost::extents[scaling][scaling][scaling]);

  auto origin_begin = a.origin();
  auto origin_end   = origin_begin + a.num_elements();
  const value_type index_initial = 0;
  std::iota(origin_begin, origin_end, index_initial);

  std::random_device rd;
  std::mt19937_64 rng(rd());
  std::shuffle(origin_begin, origin_end, rng);

  for(const auto& a0: a)
    for(const auto& a1: a0)
      for(const auto& v: a1)
        std::cout << v << " ";
  std::cout << std::endl;
}

実行結果

% g++ -std=c++11 sample.cxx
% ./a.out     
4 7 6 0 3 2 5 1 
% ./a.out 
2 0 1 3 4 6 5 7 
% ./a.out 
4 0 5 7 1 2 6 3
環境
% uname -a && g++ --version | head -n1  
Linux LH-MAIN 3.4.11-2.16-desktop #1 SMP PREEMPT Wed Sep 26 17:05:00 UTC 2012 (259fc87) x86_64 x86_64 x86_64 GNU/Linux
g++ (SUSE Linux) 4.7.1 20120723 [gcc-4_7-branch revision 189773]

蛇足

  • Boost.MultiArrayは.size()メンバー関数ではコンテナー全体の要素数は得られない。
    • .size() は .shape()[0] を得るもの。
      • .shapre() は次元毎の要素数の配列を得るもの。つまり概形が得られるのでshape。
    • コンテナー全体の要素数は .num_elements() で得られる。
    • .begin()/.end()/.cbegin()/.cend() も概形に基づく1次元内側の要素群を得るもの。
      • N次元の Boost.MultiArray は N 重 for で逐次各次元を辿れる。
    • 全要素を辿るなら .origin() から .origin() + .num_elements() で辿れる。