boost.multi_array学习-子视图用法(3)

//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

boost.multi_array学习-子视图用法(3)的相关文章

boost.multi_array 的基本用法(2)

//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/poo

c++ boost库学习三:实用工具

noncopyable 大家都知道定义一个空类的时候,它实际包含了构造函数,拷贝构造函数,赋值操作符和析构函数等. 这样就很容易产生一个问题,就是当用户调用A a(“^_^") 或者A c="^_^" 时会发生一些意想不到的行为,所以很多时候我们需要禁用这样的用法. 一种方法就是把拷贝构造函数和赋值操作符显式的定义为private,但是这样需要很多代码. 于是boost库为大家提供了一个简单的方法:只需要将类继承于noncopyable就可以了. #include "

ASP.NET MVC学习之视图篇(2)

继ASP.NET MVC学习之视图(1)学习 4.HTML辅助器 虽然在ASP.NET MVC中我们已经摆脱了ASP.NET的控件,但是对于页面中需要循环标签的情况依然还是存在,可能很多人认为用foreach就可以完成,但是这个仅仅只是针对单个循环,如果多个循环中都要使用到同样的标签呢?下面笔者就介绍两种方式让我们事半功倍. 首先是针对单个页面的内联辅助器,如果我们遇到只要在单个页面中不断使用的标签的时候,这个方式非常的轻便,比如下面的代码根据文本内容和样式类生成li标签的辅助器(Views/H

MySQL学习笔记—视图

MySQL学习笔记-视图 视图是查看基础表数据的一种方式,其作用有 - 简化开发难度,可以运用视图执行多表操作 - 数据安全,开发人员不能直接对表操作,也不能进行删除,修改操作 - 数据重构,在有限的表中,以不同的角度生成所需的视图,简化业务 CREATE VIEW语法 CREATE VIEW语法: CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name [(column_list)] AS

c++ boost库学习一:时间和日期

timer类 #include <boost\timer.hpp> #include "iostream" using namespace std; int _tmain(int argc, _TCHAR* argv[]) { boost::timer t; cout<<"max time span: "<<t.elapsed_max()/3600<<"h"<<endl; //596.5

精通IOS-在表单元中添加子视图

#import <UIKit/UIKit.h> @interface NameAndColorCellTableViewCell : UITableViewCell @property(copy,nonatomic) NSString *name; @property(copy,nonatomic) NSString *color; @end NameAndColorCellTableViewCell.h // // NameAndColorCellTableViewCell.m // Tab

IOS子视图超过父视图frame后,无法交互响应

确定第一响应者 当用户触发某一事件(触摸事件或运动事件)后,UIKit会创建一个事件对象(UIEvent),该对象包含一些处理事件所需要的信息.然后事件对象被放到一个事件队列中.这些事件按照先进先出的顺序来处理.当处理事件时,程序的UIApplication对象会从队列头部取出一个事件对象,将其分发出去.通常首先是将事件分发给程序的主window对象,对于触摸事件来讲,window对象会首先尝试将事件分发给触摸事件发生的那个视图上.这一视图通常被称为hit-test视图,而查找这一视图的过程就叫

Java EE学习--Quartz基本用法

新浪博客完全不适合写技术类文章.本来是想找一个技术性的博客发发自己最近学的东西,发现博客园起源于咱江苏,一个非常质朴的网站,行,咱要养成好习惯,以后没事多总结总结经验吧.很多时候都在网上搜索别人的总结,我自己也总结些东西,或许多多少少能帮得上别人. 首先提到的是Quartz,一个开源的定期执行计划任务的框架.其实我内心好奇这个框架很久了,像那些能定时修改数据库数据,定时分配任务的功能一直觉得很神奇.心动不如行动,今天我就小小的学习了一下用法,力求言简意赅,大家都懂的我就不说了. 第一步:下载Qu

父视图与子视图

1,子视图在父视图上显示及响应触摸时间, 1,子视图的frame需与父视图关连 2,在父视图必须声明[self.subView superview]; - (UIImageView *)imageTom {     if (_imageTom == nil) {         UIImageView *imageTom = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];         _imageTom = im