//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); } //multi_array_ref的用法 //可以和一维数组进行相互转换使用 //具备multi_array的大部分功能,除了resize //multi_array是从multi_array_ref派生过来 void multi_array_ref_usage() { boost::array<double, 24> dArray; for (unsigned i=0; i<dArray.size(); ++i) { dArray[i] = i+1; } //convert to multi_array_ref const int nDim = 3; typedef boost::multi_array_ref<double, nDim> MultiArray3DimsRef; typedef MultiArray3DimsRef::size_type MDimRefSizeType; typedef boost::array<MDimRefSizeType,nDim> BArray3; MultiArray3DimsRef ref(&dArray[0], boost::multi_array_types::extent_gen()[2][3][4]); MultiArray3DimsRef ref2(&dArray[0], boost::extents[2][3][4]); BArray3 bArray3 = {2, 3, 4}; MultiArray3DimsRef ref3(&dArray[0], bArray3); assert(ref[0][0][0] == 1); assert(ref2[0][0][0] == 1); assert(ref3[0][0][0] == 1); typedef boost::array<MDimRefSizeType, 2> BArray2; BArray3 idx = {0, 0, 0}; ref(idx) = 100; assert(ref2(idx) == 100); assert(ref3(idx) == 100); //sub-view typedef boost::multi_array_types::index_range IndexRange; BOOST_AUTO(subview1 ,ref[boost::indices[0][IndexRange(2,3)][IndexRange(2,4)]]); MultiArray3DimsRef::array_view<2>::type subview2 = ref[boost::indices[0][IndexRange(2,3)][IndexRange(2,4)]]; assert(subview2 == subview1); assert(subview1[0][0] == ref[0][2][2]); cout<<"multi_array_ref test all passed!"<<endl; } //变索引基址 void reIndex_multi_array() { const unsigned nDim = 3; typedef boost::multi_array<double, nDim, boost::fast_pool_allocator<double>> MultiArrayFastAlloc; typedef MultiArrayFastAlloc::extent_range Range; typedef boost::multi_array_types::extent_range MRange; typedef MultiArrayFastAlloc::size_type MArraySizeType; //extents[extent_range | const_int] //extent_range可以设置变基址 //const_int可以指定索引范围大小,索引从0开始 MultiArrayFastAlloc mafa(boost::extents[MRange(1,5)][4][MRange(-3, 6)]); mafa[1][0][-3] = 100; //变索引 boost::array<MArraySizeType, 3> idx = {1, 0, -3}; assert(mafa(idx) == 100); const MArraySizeType *shapeList = mafa.shape(); const MArraySizeType extens[3] = {(5-1), 4, (6-(-3))}; assert(std::equal(shapeList, shapeList+nDim, extens)); typedef boost::multi_array_types::index Index; const Index*bases = mafa.index_bases(); boost::array<Index, 3> aindex = {1, 0, -3}; assert(std::equal(bases, bases+mafa.num_dimensions(), &aindex[0])); } //灵活的子视图,可以通过逻辑表达式来控制范围 void flexible_sub_view() { const unsigned nDims = 3; typedef boost::multi_array<double,nDims> MultiArray3Dims; MultiArray3Dims ma(boost::multi_array_types::extent_gen::extents()[7][8][9]); typedef boost::multi_array_types::index_range IndexRange; BOOST_AUTO(indice, boost::indices[IndexRange()<4][2<=IndexRange()<=6][3<IndexRange()<=5]); BOOST_AUTO(subview, ma[indice]); MultiArray3Dims::array_view<3>::type sb2 = ma[indice]; assert(sb2 == subview); const boost::multi_array_types::index * bases = sb2.index_bases(); boost::array<unsigned, 3> a3 = {0, 2, 4}; std::equal(bases, bases+sb2.num_dimensions(), &a3[0]); } int _tmain(int argc, _TCHAR* argv[]) { test_multi_array(); multi_array_ref_usage(); reIndex_multi_array(); flexible_sub_view(); getchar(); return 0; }
时间: 2024-10-14 03:19:09