//made by davidsu33
//2014-9-14 11:51
#include "stdafx.h"
#include <boost/config.hpp>
#include <boost/multi_array/extent_gen.hpp>
#include <boost/multi_array.hpp>
#include <boost/pool/pool.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/array.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <iostream>
#include <cassert>
#include <vector>
#include <algorithm>
using namespace std;
typedef boost::fast_pool_allocator<double> FastPoolAllocator;
typedef boost::multi_array<double, 3, FastPoolAllocator> Multi3Array;
void mult_array_access(Multi3Array &mult3);
void show_dims(Multi3Array& mult3);
void sub_view(Multi3Array &mult3);
template<class T>
bool check_ptr(T& v1, T& v2);
void test_multi_array()
{
//using namespace boost;
//还可以设置维度的存储顺序
//Multi3Array mult3Array(boost::multi_array_types::extent_gen::extents()[3][4][5]);
//Multi3Array mult3Array(boost::extents[3][4][5]); //Right Usage
//为什么不能直接写
boost::detail::multi_array::extent_gen<3> extentgen3 = boost::detail::multi_array::extent_gen<0>()[3][4][5];
//Multi3Array mult3Array(extentgen3); //Right Usage
//???
//因为操作符顺序的关系不能写成,因为()的操作符顺序高,所以导致
//boost::detail::multi_array::extent_gen<0>()[..],[..]没有先解析
//Multi3Array mult3Array(boost::detail::multi_array::extent_gen<0>()[3][4][5]); //Error Usage
Multi3Array mult3Array((boost::detail::multi_array::extent_gen<0>()[3][4][5])); //Right Usage
int nDims = mult3Array.num_dimensions();
assert((mult3Array.num_dimensions() == 3));
assert((mult3Array.num_elements() == 3*4*5));
int sz = mult3Array.size();
//可以通过ListExtend来扩展
boost::array<unsigned,3> dimArray = {3, 4, 5};
Multi3Array mutl3Array2(dimArray);
assert(mutl3Array2.num_elements() == mult3Array.num_elements());
mult_array_access(mult3Array);
show_dims(mult3Array);
sub_view(mult3Array);
}
void mult_array_access(Multi3Array &mult3)
{
boost::array<long, 3> idx = {0, 0, 0};
assert(mult3[0][0][0] == mult3(idx));
mult3[0][0][0] = 100;
assert(mult3(idx) == 100);
int i=0;
double *pData = mult3.data();
std::for_each(pData, pData+mult3.num_elements(), boost::lambda::_1 = boost::lambda::var(i)++);
i=0; //reset i=0;
boost::array<int,3> idx3;
assert(mult3[0][0][0] == 0);
for (int x=0; x<3; ++x)
{
for (int y=0; y<4; ++y)
{
for(int z=0; z<5; ++z)
{
idx3 = boost::assign::list_of(x)(y)(z);
assert(mult3(idx3) == i++);
}
}
}
cout<<"test passed"<<endl;
}
void show_dims(Multi3Array& mult3)
{
typedef Multi3Array::size_type MSizeType;
for (int i=0; i<mult3.num_dimensions(); ++i)
{
std::cout<<"Dims["<<i<<"]"<<"="<<mult3.shape()[i]<<endl;
}
const MSizeType*oldShape = mult3.shape();
vector<MSizeType> v3(3, 0);
std::copy(oldShape, oldShape+mult3.num_dimensions(), v3.begin());
boost::array<int,3> arr3 = {1,1,4};
//mult3.reshape(arr3);//shape must keep size constant, if size is same, use this;
mult3.resize(arr3); //if multi_array 's num_numbers() is not same use this;
for (int i=0; i<mult3.num_dimensions(); ++i)
{
assert(mult3.shape()[i] == arr3[i]);
}
//BOOST_AUTO(shapeList, mult3.shape());
const MSizeType *shapeList = mult3.shape();
cout<<*mult3.shape()<<endl;
//reset to old for testing
mult3.resize(v3); //right usage
//mult3.resize(oldShape); //error usage
//在这里不能直接这么赋值,否则会报错如下
//原因是resize传入的值会进行容器的检查
//h:\boost\boost_1_56_0\boost\concept_check.hpp(1061): error C2825: 'C': must be a class or namespace when followed by '::'
// 1> h:\boost\boost_1_56_0\boost\concept_check.hpp(1040) : see reference to class template instantiation 'boost::Collection<C>' being compiled
// 1> with
// 1> [
// 1> C=const unsigned int *
// 1> ]
// 1> h:\boost\boost_1_56_0\boost\concept\detail\has_constraints.hpp(42) : see reference to class template instantiation 'boost::CollectionConcept<C>' being compiled
// 1> with
// 1> [
// 1> C=const unsigned int *
// 1> ]
// 1> h:\boost\boost_1_56_0\boost\concept\detail\msvc.hpp(58) : see reference to class template instantiation 'boost::concepts::not_satisfied<Model>' being compiled
// 1> with
// 1> [
// 1> Model=boost::CollectionConcept<const unsigned int *>
// 1> ]
// 1> h:\boost\boost_1_56_0\boost\concept_check.hpp(51) : see reference to class template instantiation 'boost::concepts::require<Model>' being compiled
// 1> with
// 1> [
// 1> Model=boost::CollectionConcept<const unsigned int *>
// 1> ]
// 1> h:\boost\boost_1_56_0\boost\multi_array.hpp(386) : see reference to function template instantiation 'void boost::function_requires<boost::CollectionConcept<C>>(Model *)' being compiled
// 1> with
// 1> [
// 1> C=const unsigned int *,
// 1> Model=boost::CollectionConcept<const unsigned int *>
// 1> ]
// 1> h:\boost_dev_spaces\boost\boost1\boost1.cpp(116) : see reference to function template instantiation 'boost::multi_array<T,NumDims,Allocator> &boost::multi_array<T,NumDims,Allocator>::resize<const unsigned int*>(const ExtentList &)' being compiled
// 1> with
// 1> [
// 1> T=double,
// 1> NumDims=3,
// 1> Allocator=FastPoolAllocator,
// 1> ExtentList=const unsigned int *
// 1> ]
// 1>h:\boost\boost_1_56_0\boost\concept_check.hpp(1061): error C2039: 'value_type' : is not a member of '`global namespace''
// 1>h:\boost\boost_1_56_0\boost\concept_check.hpp(1061): error C2146: syntax error : missing ';' before identifier 'value_type'
// 1>h:\boost\boost_1_56_0\boost\concept_check.hpp(1061): error C2602: 'boost::Collection<C>::value_type' is not a member of a base class of 'boost::Collection<C>'
// 1> with
// 1> [
// 1> C=const unsigned int *
// 1> ]
// 1> h:\boost\boost_1_56_0\boost\concept_check.hpp(1061) : see declaration of 'boost::Collection<C>::value_type'
// 1> with
// 1> [
// 1> C=const unsigned int *
// 1> ]
// 1>h:\boost\boost_1_56_0\boost\concept_check.hpp(1061): error C2868: 'boost::Collection<C>::value_type' : illegal syntax for using-declaration; expected qualified-name
// 1> with
// 1> [
// 1> C=const unsigned int *
// 1> ]
}
//=======IsSame============
template<class T, class U>
struct MIsSame;
template<class T, class U>
struct MIsSame
{
BOOST_STATIC_CONSTANT(bool, value=false);
};
template<class T>
struct MIsSame<T,T>
{
BOOST_STATIC_CONSTANT(bool, value=true);
};
//========StaticAssert========
template<bool>
struct MStaticAssert;
template<>
struct MStaticAssert<true>
{
};
//=====StaticAssertMarco=====
#define MSTATIC_ASSERT_MARCO(Cond)\
do{\
MStaticAssert<Cond> sa;\
sa = sa; \
}while(0)
//宏在定义的时候,分割成多行的时候,\后面必须不能带分隔符和注释
//for disable warning 4101, unreferenced local variable
//do{}while(0) for user to add last ';'
//#define SUB_ARRAYVIEW
void sub_view(Multi3Array &mult3)
{
//#if defined(_MSC_VER)
//#pragma message("XXX") 控制信息输出显示
//#if defined(SUB_ARRAYVIEW)
//#pragma message("SUB_ARRAYVIEW is Defined!")
//#endif
#define SUB_ARRAYVIEW(x)\
typedef Multi3Array::array_view<x>::type ArrayView##x;
SUB_ARRAYVIEW(3);
SUB_ARRAYVIEW(2);
SUB_ARRAYVIEW(1);
//IndexRange的三种写法
typedef Multi3Array::index_range IndexRange;
typedef boost::multi_array_types::index_range IndexRangeType;
typedef boost::detail::multi_array::index_range<ptrdiff_t, unsigned> IndexRangeType2;
//bool isOK = MIsSame<IndexRange, IndexRangeType>::value;
MSTATIC_ASSERT_MARCO((MIsSame<IndexRange, IndexRangeType>::value));
//MSTATIC_ASSERT_MARCO((MIsSame<int, double>::value)); //编译不过
MSTATIC_ASSERT_MARCO((MIsSame<IndexRangeType, IndexRangeType2>::value));
//MSTATIC_ASSERT_MARCO((MIsSame<int, IndexRangeType2>::value)); //编译不过
typedef Multi3Array::size_type MSizeType;
vector<MSizeType> v(mult3.num_dimensions(), 0);
copy(mult3.shape(), mult3.shape()+mult3.num_dimensions(), v.begin());
copy(v.begin(), v.end(), std::ostream_iterator<MSizeType>(cout, ";"));
cout<<endl;
//得到的子视图是原来的引用访问
ArrayView3 aview3 = mult3[boost::indices[IndexRange(0,1)][IndexRange(1, 2)][IndexRange(3, 5)]];
const MSizeType *theShape = aview3.shape();
cout<<"mult3-shape:";
copy(mult3.shape(), mult3.shape()+mult3.num_dimensions(), std::ostream_iterator<int>(std::cout));
cout<<endl;
cout<<"aview3-shape:";
copy(aview3.shape(), aview3.shape()+mult3.num_dimensions(), std::ostream_iterator<int>(std::cout));
cout<<endl;
//ArrayView不能修改shape的大小
//这个位置需要索引
//不应该写成aview3[0][1][3],需要减去起始偏移{0,1,3}
aview3[0][0][0] = 10;
assert(mult3[0][1][3] == 10);
mult3[0][1][3] = 1000;
assert(aview3[0][0][0] == 1000);
//另外一种写法
boost::array<MSizeType,3> idx3 = {0, 0, 0};
boost::array<MSizeType,3> idx32 = {0, 1, 3};
aview3(idx3) = 10;
assert(mult3(idx32) == 10);
mult3(idx32) = 1000;
assert(aview3(idx3) == 1000);
//获取2D视图,相当于第一位的索引始终是0
ArrayView2 aview21 = mult3[boost::indices[0][IndexRange(1,2)][IndexRange(3, 5)]];
ArrayView2 aview22 = mult3[boost::indices[1][IndexRange(1,2)][IndexRange(3, 5)]];
ArrayView2 aview23 = mult3[boost::indices[2][IndexRange(1,2)][IndexRange(3, 5)]];
assert(2 == aview21.num_dimensions());
assert(2 == aview22.num_dimensions());
assert(2 == aview23.num_dimensions());
//2 == 2 is bool
//2 == (true/false)导致错误
//assert(2 == 2 == 2 == 2); //must be false
int xoffset = 1, yoffset = 3;
boost::array<MSizeType,2> idx2 = {0, 0};
boost::array<MSizeType,3> idx21 = {0, 0+xoffset, 0+yoffset};
boost::array<MSizeType,3> idx22 = {1, 0+xoffset, 0+yoffset};
boost::array<MSizeType,3> idx23 = {2, 0+xoffset, 0+yoffset};
check_ptr(aview21(idx2), mult3(idx21));
check_ptr(aview22(idx2), mult3(idx22));
check_ptr(aview23(idx2), mult3(idx23));
cout<<"sub-view test all passed"<<endl;
#undef SUB_ARRAYVIEW
}
template<class T>
bool check_ptr(T& v1, T& v2)
{
assert(v1 == v2);
return (&v1 == &v2);
}
int _tmain(int argc, _TCHAR* argv[])
{
test_multi_array();
getchar();
return 0;
}
boost.multi_array 的基本用法(2)
最新推荐文章于 2023-08-22 11:12:49 发布