6 Ekim 2017 Cuma

multi_array Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <boost/multi_array.hpp>
Bu sınıfın boyutları çalışma esnasında belirlenebildiği için bazı avantajlar sunuyor
Tanımlama
Örnek
C++98'de kolay kullanmak için bir typedef yaparız.
typedef boost::multi_array<double, 3> array_type;
Örnek
C++11'de şöyle yaparız.
using Array = boost::multi_array<float,2>
Örnek
Şöyle yaparız.
using intArray3D = boost::multi_array<int, 3>;
Template Parametreleri
Template parametreleri farklı olan tanımlamalar aynı değildir. Yukarıdaki C++98 tanımlaması ile bu tanımlama faklıdır.
typedef boost::multi_array<double, 2> array_type;
Yani şu tiplerin hepsi birbirinden farklıdır.
typedef boost::multi_array<int, 2> Array2D;
typedef boost::multi_array<int, 3> Array3D;
typedef boost::multi_array<int, 4> Array4D;
typedef boost::multi_array<int, 5> Array5D;
multi_array_ref
Bu sınıfa benzer multi_array_ref sınıfı da var. Bu sınıf std::unique_ptr<T> şeklinde bellek ile çalışabilir.

Constructor - boost::extents
Şöyle yaparız. Template içinde kaç boyutlu olduğunu belirtiriz. Constructor içinde her boyutun büyüklüğünü belirtiriz.
array_type arr (boost::extents[2][4][5]);
C++11 ile şöyle yaparız.
array_type arr {boost::extents[2][4][5]};
Constructor - std::array
Şöyle yaparız.
using intArray3D = boost::multi_array<int, 3>;

std::array<int, 3> my_shape { 3, 4, 5 };
intArray3D xs(my_shape);
Constructor - std::vector
Şöyle yaparız.
using intArray3D = boost::multi_array<int, 3>;

std::vector<int> my_shape { 3, 4, 5 };
intArray3D xs(my_shape);
begin metodu
Şöyle yaparız.
std::fill_n (arr.begin(), arr.size(), 1);
data metodu
Açıklaması şöyle.
element* data(); This returns a pointer to the beginning of the contiguous block that contains the array's data. If all dimensions of the array are 0-indexed and stored in ascending order, this is equivalent to origin().
element* origin(); This returns the origin element of the multi_array.
Örnek
C array'den multi_array'e kopyalama için şöyle yaparız.
// First create a primitive array, which can be directly initialized
uint8_t field_primitive[4][8] = {
    { 1,1,1,1,1,1,1,1 },
    { 1,2,1,2,1,2,1,2 },
    { 1,1,2,2,2,2,2,2 },
    { 1,2,2,2,2,2,2,2 }
};
// Create the boost::multi_array I actually want to use
boost::multi_array<uint8_t, 2> arr (boost::extents[4][8]);

memcpy(arr.data(), field_primitive, arr.num_elements() * sizeof(uint8_t));
Örnek
Elimizde bir C metodu olsun
void function(float param[ROWS][COLS]);
Bu metoda parametre olarak multi_array geçmek için şöyle yaparız.
function((float (*)[COLS])array.data());
dimensionality Alanı
Template için verilen ikinci parametredir. Eğer 3 verdiysek çıktı olarak 3 alırız.
Örnek
Şöyle yaparız.
std::cout << arr.dimensionality;
Örnek
Elimizde şöyle bir kod olsun. Bu kod nesnenin tüm boyutlarının büyüklüğünü basar.
void dump_shape(intArray3D const& arr) {
  for (unsigned dim = 0; dim < arr.dimensionality; ++dim)
    std::cout << arr.shape()[dim] << " ";
  std::cout << "\n";
}
Şöyle yaparız.
using intArray3D = boost::multi_array<int, 3>;

auto my_shape = boost::extents[3][4][5];
intArray3D xs(my_shape);
dump_shape(xs); 
Çıktı olarak şunu alırız.
3 4 5 
num_dimensions metodu
dimensionality alanı ile aynı değeri verir. Şöyle yaparız. Template için verilen ikinci parametredir. Eğer 3 verdiysek çıktı olarak 3 alırız.
arr.num_dimensions()
operator =  metodu
Boyutları aynı olduğu müddetçe bir yapı diğerine kopyalanabilir. Şöyle yaparız.
arr2= arr1;
Şöyle yaparız.
// Create a 2x4x5 array
array_type arr (boost::extents[2][4][5]);

// Create a new array
arr = array_type (boost::extents[7][6][8]);
origin metodu
Şöyle yaparız.
#include <boost/multi_array.hpp>
#include <algorithm>
#include <iostream>
#include <cstring>

int main()
{
  boost::multi_array<char, 2> a{boost::extents[2][6]};

  typedef boost::multi_array<char, 2>::array_view<1>::type array_view;
  typedef boost::multi_array_types::index_range range;
  array_view view = a[boost::indices[0][range{0, 5}]];

  std::memcpy(view.origin(), "tsooB", 6);
  std::reverse(view.begin(), view.end());

  std::cout << view.origin() << '\n';

  boost::multi_array<char, 2>::reference subarray = a[1];
  std::memcpy(subarray.origin(), "C++", 4);

  std::cout << subarray.origin() << '\n';
} 
reshape metodu - no copy
Boyutların büyüklüğünü değiştirir.
Örnek
Şöyle yaparız.
using array_type = boost::multi_array<double, 2>;

array_type::extent_gen extents;
array_type arr(extents[1][2]); // 1 x 2 array

A[0][0] = 1; A[0][1] = 2;
std::cout << A[0][0] << ' ' << A[0][1] << '\n';

boost::array<array_type::index, 2> dims = {{2,1}};
A.reshape(dims); // reshape it to 2 x 1

std::cout << A[0][0] << ' ' << A[1][0] << '\n'; // verify
Örnek
Elimizde 3 boyutlu bir dizi olsun.
typedef boost::multi_array<double, 3> array_type;
// Create a 2x4x5 array
array_type arr (boost::extents[2][4][5]);
Boyutların büyüklüğünü değiştirmek için şöyle yaparız.
// Reshape (no copy) - The total number of elements must remain the same
boost::array<array_type::index, 3> new_dims {{5, 4, 2}};
ar.reshape (new_dims);
resize metodu - copy
Boyutların büyüklüğünü değiştirmek için şöyle yaparız.
// Resize, keeping currently stored elements by copying them
arr.resize (boost::extents[8][10][5]);
boos::extents yerine std::vector kullanılabilir. Şöyle yaparız.
arr source = ...; arr dest;
vector<size_t> grid;
const size_t* shape = source.shape();
grid.assign (shape, shape+source.num_dimensions());
dest.resize (grid);
shape metodu
Nesnenin tüm boyutlarının büyüklüğünü döner. He boyutun büyüklüğünü operator [] ile alırız.

Örnek
Şöyle yaparız.
const size_t* shape = arr.shape();
2 boyutlu bir yapının tüm elemanları dolaşmak için şöyle yaparız.
for(size_t i=0; i<arr.shape()[0]; ++i) {
  for(size_t j=0; j<arr.shape()[1]; ++j) {
    ...
  }
}
Şöyle yaparız.
std::copy(arr.shape(), arr.shape() + a.dimensionality,...);
size metodu
3 boyutlu bir yapının tüm elemanları dolaşmak için şöyle yaparız. Bu işlem için shape metodu da kullanılabilir.
for(int j = 0; j < arr.size(); j++ ){
  for(int k = 0; k < arr[0].size(); k++ ){
    for(int l = 0; l < arr[0][0].size(); l++ ){
      ...
    }
  }
}
Kalıtım
Eğer bu sınıftan kalıtmak istersek şöyle yaparız.
template<typename T, size_t N>
class myMatrix : public boost::multi_array<T, N> {
  ...
}
Parametre Geçmek
Bu sınıfı bir metoda parametre olarak geçmek için şöyle yaparız.
template<std::size_t N>
void writeArrayToFile(const boost::multi_array<int, N>& array) {
  // do things with array
}



Hiç yorum yok:

Yorum Gönder