公式解一元四次方程式

2012年3月1日 尚無評論

解四次式ax^4+bx^3+cx^2+dx+e=0
參考http://en.wikipedia.org/wiki/Quartic_function

#include <complex>
#include <crtdbg.h>

//ax^4+bx^3+cx^2+dx+e=0;
//使用標準函式庫complex
void solve_equation4(double a,double b,double c, double d, double e,
	std::complex<double>&s0,std::complex<double>&s1,std::complex<double>&s2,std::complex<double>&s3)
{
	// http://en.wikipedia.org/wiki/Quartic_function
	double bb=b*b;
	double aa=a*a;
	double aaa=aa*a;
	double bbb=bb*b;

	double apha=(-3.*bb)/(8*aa)+c/a;
	double beta=(bbb)/(8*aaa)-(b*c)/(2*aa)+d/a;
	double gama=(-3.*bb*bb)/(256*aa*aa)+(c*bb)/(16*aaa)-(b*d)/(4*aa)+e/a;
	
	//誤差量自行修改
	const double epsilon=1.e-8;

	if(beta>=-epsilon && beta<=epsilon)
	{
		double n1=-b/(4*a);
		std::complex<double> nx=sqrt(std::complex<double>(apha*apha-4*gama));
		std::complex<double> n2=sqrt((-apha+nx)/2.);
		std::complex<double> n2x=sqrt((-apha-nx)/2.);
		s0=n1+n2;
		s1=n1-n2;
		s2=n1+n2x;
		s3=n1-n2x;
	}else
	{
		double apha2=apha*apha;
		double beta2=beta*beta;
		double P=(-apha2)/12.-gama;
		double Q=(-apha*apha2)/108.+(apha*gama)/3.-beta2/8.;			
		std::complex<double> R=-Q/2.+sqrt(std::complex<double>(Q*Q/4.+P*P*P/27.));

		std::complex<double> U=pow(R,1/3.);
		std::complex<double> y;
		y=(-5./6.)*apha+U;

		double absU=abs(U);
		if(absU>=-epsilon && absU<=epsilon)
			y-=pow(Q,1./3.);
		else
			y-=P/(3.*U);


		std::complex<double> y2=y*2.;

		std::complex<double> W=sqrt(apha+y2);
		
		double n1=-b/(4*a);

		std::complex<double> n2=W/2.;

		std::complex<double> n3_x=3*apha+y2;
		std::complex<double> n3_x1=2*beta/W;

		std::complex<double> n31=sqrt(-(n3_x+n3_x1))/2.;
		std::complex<double> n32=sqrt(-(n3_x-n3_x1))/2.;
		
		s0=n1+n2+n31;
		s1=n1+n2-n31;
		s2=n1-n2+n32;
		s3=n1-n2-n32;
	}

	//套回四次方式,檢查等式是否成立.
#ifdef _DEBUG
	std::complex<double>* x[4]={&s0,&s1,&s2,&s3};

	for(int i=0;i<4;i++)
	{
		//誤差值跟係數大小有關。
		//當係數值很大時,可能誤差挺大...
		double value=abs(pow(*x[i],4)*a)+abs(pow(*x[i],3)*b)+abs(pow(*x[i],2)*c)+abs(*x[i]*d)+abs(e);
		if(value<1.)
			value=1.;
		double ep=value*1.0e-12;
		double dif=abs(pow(*x[i],4)*a+pow(*x[i],3)*b+pow(*x[i],2)*c+*x[i]*d+e);
		_ASSERT(dif>=-ep && dif<=ep);
	}
#endif
}
Categories: dimension1, math Tags:

公式解一元三次方程式

2012年2月22日 尚無評論

求解三次式,ax^3+bx^2+cx+d=0;

解有經過排序,實數解在前面

當a==0時傳回-1, 解內容為NaN(非浮點數值, 使用_isnan檢查)

當a!=0
s1, s2, s3為解的實部,s1i, s2i, s3i為解的虛部
當有3個實數解傳回3, s1=解1, s2=解2, s3=解3, s1i、s2i與s3i為零
當有2個實數解傳回2, s1=解1, s2=解2, s3=解1或解2, s1i、s2i與s3i為零(三實數解的特例,有兩個值相等)
當有1個實數解傳回1, s1=解1, s2=解1, s3=解1, s1i、s2i與s3i為零(三實數解,有3個值相等)
當有1個實數,2個虛數解傳回1, s1=實數, s2=解2的實部, s3=解3的實部, s1i為零, s2i=解2的虛部, s3i=解3的虛部
有錯誤傳回-1, s1, s2, s3, s2i, s3i為NaN(非浮點數值, 使用_isnan檢查)。

#include <math.h>
#include <float.h>
#include <limits>
//#include <algorithm>
#include <crtdbg.h>

//求解三次式,ax^3+bx^2+cx+d=0;
//解有經過排序,實數解在前面,若同為實數解s1<s2<s3
//
//當a==0時傳回-1, 解內容為NaN(非浮點數值, 使用_isnan檢查)

//當a!=0
//s1, s2, s3為解的實部,s1i, s2i, s3i為解的虛部
//當有3個實數解傳回3, s1=解1, s2=解2, s3=解3, s1i、s2i與s3i為零
//當有2個實數解傳回2, s1=解1, s2=解2, s3=解1或解2, s1i、s2i與s3i為零(三實數解的特例,有兩個值相等)
//當有1個實數解傳回1, s1=解1, s2=解1, s3=解1, s1i、s2i與s3i為零(三實數解,有3個值相等)
//當有1個實數,2個虛數解傳回1, s1=實數, s2=解2的實部, s3=解3的實部, s1i為零, s2i=解2的虛部, s3i=解3的虛部
//有錯誤傳回-1, s1, s2, s3, s2i, s3i為NaN(非浮點數值, 使用_isnan檢查)。
// by wct 2012/02/23
static void sort_double3(double*p)
{
	double tmp;
	if(p[0]>p[1])
	{
		tmp=p[1];
		p[1]=p[0];
		p[0]=tmp;
	}
	if(p[1]<=p[2])
		return;

	tmp=p[2];
	p[2]=p[1];
	p[1]=tmp;

	if(p[0]>p[1])
	{
		tmp=p[1];
		p[1]=p[0];
		p[0]=tmp;
	}
}
int solve_equation_cubic(double a,double b,double c, double d,
			double* s1,double* s2, double* s3,double*s1i ,double*s2i,double* s3i)
{
	//const 強調值不再改變。
	//誤差量自行修改
	const double epsilon=1.e-8;
	//a==0
	if(a>=-epsilon && a<=epsilon)
	{
		double nan;
		nan=std::numeric_limits<double>::quiet_NaN();
		if(s3)
			*s3=nan;
		if(s3i)
			*s3i=nan;
		if(s2)
			*s2=nan;
		if(s2i)
			*s2i=nan;
		if(s1)
			*s1=nan;
		if(s1i)
			*s1i=nan;
		return -1;
	}
	//使用盛金解(Shengjin's Formulas)
	//http://www.hudong.com/wiki/%E8%A7%A3%E4%B8%80%E5%85%83%E4%B8%89%E6%AC%A1%E6%96%B9%E7%A8%8B

	const double a3=a*3.;
	const double A=b*b-a3*c;
	const double B=b*c-9.*a*d;
	const double C=c*c-3.*b*d;
	static const double sqrt3=sqrt(3.);
	static const double oneOF3=1./3.;

	const double D=B*B-4.*A*C;

	//有重根
	//在電腦上用使用離散數字,在足夠小區間內的數值近似於零。
	if(D<=epsilon && D>=-epsilon)	
	{
		//虛根為零
		if(s1i)
			*s1i=0;
		if(s2i)
			*s2i=0;
		if(s3i)
			*s3i=0;

		//三重實根
		//A==0
		if(A <= epsilon && A >= -epsilon)// B必定等於0
		{
			_ASSERT(B <= 0.0001 && B >= -0.0001);

			double s;
			//if(b==0)//若b==0, 則c==0, d==0, 解為0
			if(b <= epsilon && b >= -epsilon)
			{
				_ASSERT(c <= epsilon && c >= -epsilon);
				_ASSERT(d <= epsilon && d >= -epsilon);
				s=0;
			}
			else
				s=-c/b;
				

			if(s1)
				*s1=s;
			if(s2)
				*s2=s;
			if(s3)
				*s3=s;
			return 1;
		}
		//兩個重根
	//	if(A!=0) //不需判斷,A必定不等於零
		{
			_ASSERT(_finite(A));
			const double K=B/A;
			const double s=-b/a+K;
			const double sx=-K/2.;
			if(s>sx)
			{
				if(s1)
					*s1=sx;
				if(s2)
					*s2=s;
				if(s3)
					*s3=sx;
			}else
			{
				if(s1)
					*s1=s;
				if(s2)
					*s2=sx;
				if(s3)
					*s3=sx;
			}
			return 2;
		}
	}

	//一實根,一對共軛虛根	
	if(D>0)
	{
		const double sqrtD=sqrt(D);		

		const double a6=a*6.;		

		const double Y1=A*b+a3*(-B+sqrtD)/2.;
		const double Y2=A*b+a3*(-B-sqrtD)/2.;
		double y1,y2;
		
		if(Y1<0)
			y1=-pow(-Y1,oneOF3);
		else
			y1=pow(Y1,oneOF3);

		if(Y2<0)
			y2=-pow(-Y2,oneOF3);
		else
			y2=pow(Y2,oneOF3);
		
		if(s1)
			*s1=(-b-y1-y2)/a3;

		if(s1i)
			*s1i=0;
		
		const double real=(-2.*b + y1 + y2) / a6;
		double img=sqrt3*(y1-y2)/ a6;
		if(img<0)
			img=-img;

		if(s2)
			*s2=real;
		if(s3)
			*s3=real;
		if(s2i)
			*s2i=-img;
		if(s3i)
			*s3i=img;

		return 1;
	}


	//有三不等實根
	if(D<0)
	{
		//虛根為零
		if(s1i)
			*s1i=0;
		if(s2i)
			*s2i=0;
		if(s3i)
			*s3i=0;

		double sol[3];
//		if(A>0)//必定存在, 盛金定理8
		{
			_ASSERT(A>0);
			const double T = (2. * A * b - a3 * B) / (2. * sqrt(A * A * A));
//			if(T>-1 && T<1)//必定存在, 盛金定理9
			{
				_ASSERT(T>-1.00001 && T<1.00001);

				const double rTheta = acos(T);
				const double rTheta_3 = rTheta/3.;
				const double cos_rTheta_3=cos(rTheta_3);
				const double sin_rTheta_3=sin(rTheta_3);

				const double sqrtA=sqrt(A);
				sol[0] = (-b - 2 * sqrtA * cos_rTheta_3)/a3;
				
				const double Delta= sqrt3 * sin_rTheta_3;
				sol[1] = (-b + sqrtA * (cos_rTheta_3 +Delta))/a3;
				sol[2] = (-b + sqrtA * (cos_rTheta_3 - Delta))/a3;

				//std::sort(sol,sol+3);
				sort_double3(sol);
				if(s1)
					*s1=sol[0];
				if(s2)
					*s2=sol[1];
				if(s3)
					*s3=sol[2];
				return 3;
			}
		}
	}

	//D為NaN?
	_ASSERT(0);
	double nan;
	nan=std::numeric_limits<double>::quiet_NaN();
	if(s1)
		*s1=nan;
	if(s2)
		*s2=nan;
	if(s3)
		*s3=nan;
	if(s1i)
		*s1i=nan;
	if(s2i)
		*s2i=nan;
	if(s3i)
		*s3i=nan;

	return -1;
}
Categories: dimension1 Tags:

公式解一元二次方程式,

2012年2月22日 尚無評論

求解二次式,ax^2+bx+c=0;
解有經過排序,實數解在前面

當a!=0
s1, s2為解的實部,s1i, s2i為解的虛部
當有2個實數解傳回2, s1=解1, s2=解2, s1i與s2i為零
當有1個實數解傳回1, s1=s2=解, s1i與s2i為零
當虛數解傳回0, s1=s2=為根的實數部分,s1i與s2i為根的虛數部分。

當a==0或有錯誤傳回-1, s1, s2, s1i, s2i為Nan(非浮點數值, 使用_isnan檢查)。

#include <limits>
#include <float.h>
#include <math.h>

//求解二次式,ax^2+bx+c=0;
//解有經過排序,實數解在前面,若同為實數解s1<s2
//
//當a!=0	
//s1, s2為解的實部,s1i, s2i為解的虛部
//當有2個實數解傳回2, s1=解1, s2=解2, s1i與s2i為零
//當有1個實數解傳回1, s1=s2=解, s1i與s2i為零
//當虛數解傳回0, s1=s2=為根的實數部分,s1i與s2i為根的虛數部分。
//
//當a==0或有錯誤傳回-1, s1, s2, s1i, s2i為Nan(非浮點數值, 使用_isnan檢查)。
// by wct 2012/02/23
int solve_equation_quadratic(double a,double b,double c, double* s1,double* s2,double *s1i,double*s2i)
{
	//const 強調值不再改變
	//誤差量自行修改
	const double epsilon=1.e-8;
	if(a>=-epsilon && a<=epsilon)
	{
		double nan;
		nan=std::numeric_limits<double>::quiet_NaN();
		if(s1)
			*s1=nan;
		if(s2)
			*s2=nan;
		if(s1i)
			*s1i=nan;
		if(s2i)
			*s2i=nan;
		return -1;
	}
	
	//D=b^2-4ac;
	const double D=b*b-4*a*c;
	//solution1=(-b+sqrt(D))/(2*a)
	//solution2=(-b-sqrt(D))/(2*a)
	
	const double a2=a*2;	
	const double b_=-b;

	//D==0
	//有重根
	if(D <= epsilon && D >= -epsilon)
	{
		if(s1i)
			*s1i=0;
		if(s2i)
			*s2i=0;	

		const double sol=b_/a2;
		if(s1)
			*s1=sol;
		if(s2)
			*s2=sol;

		return 1;
	}


	//虛根	
	if(D<0)
	{
		const double d=sqrt(-D);	
		const double real=b_/a2;

		if(s1)
			*s1=real;
		if(s2)
			*s2=real;

		double img=d/a2;
		if(img<0)
			img=-img;

		if(s1i)
			*s1i=-img;
		if(s2i)
			*s2i=img;

		return 0;
	}
	
	//兩不等實根
	if(D>0)
	{
		const double d=sqrt(D);

		if(s1)
			*s1=(b_-d)/a2;
		if(s2)
			*s2=(b_+d)/a2;

		if(s1i)
			*s1i=0;
		if(s2i)
			*s2i=0;	
		return 2;
	}

	//D為NaN?
	_ASSERT(0);
	double nan;
	nan=std::numeric_limits<double>::quiet_NaN();
	if(s1)
		*s1=nan;
	if(s2)
		*s2=nan;
	if(s1i)
		*s1i=nan;
	if(s2i)
		*s2i=nan;

	return -1;
}
//使用範例:
//求解2x^2+3x+4=0;

double a,b,c;
a=2;
b=3;
c=4;
double s1,s1i,s2,s2i;
int ret=solve_equation_quadratic(a,b,c,&s1,&s2,&s1i,&s2i);
if(ret==2)
{//有2個實數解
//....
}else if(ret==1)
{//有1個實數解
//....
}else if(ret==0)
{//虛數解
//....
}else
{//有錯誤
//....
}

如果不要那麼多資訊,用標準函式庫complex

#include <complex>

//求解二次式,ax^2+bx+c=0;
void solve_equation_quadratic(const std::complex<double>&a,const std::complex<double>&b,const std::complex<double>&c,
			  std::complex<double>&s1,std::complex<double>&s2)
{
	//(-b+root(d))/(2a)==>-b/(2a)+root(d)/(2a)
	//(-b-root(d))/(2a)==>-b/(2a)-root(d)/(2a)
	std::complex<double> a2=a*2.;
	std::complex<double> n1=(b*-1.)/a2;
	std::complex<double> n2=sqrt( (b*b) - (a*c*4.) )/a2;

	s1=n1+n2;
	s2=n1-n2;
}
//使用範例:
//求解 2x^2+3x+4=0;
std::complex<double> a,b,c,s1,s2;
a=2;
b=3;
c=4;

solve_equation_quadratic(a,b,c,s1,s2);
Categories: dimension1, math Tags:

怪腳女

2011年7月15日 尚無評論

 

她用左腳還是右腳支地?

偶而左腳,偶而右腳?

Categories: 遊戲 Tags:

簡化型vector

2011年4月18日 1 則評論

為什麼使用data_array:

 1. data_array是用於物件為資料型態,不需建構與解構式。

 2. data_array資料移動使用記憶體複製,比標準函式庫的個別物件複製快。

3. 檔案相依性與複雜性比標準函式庫少,有特殊需求,容易修改。

4. 直接改變陣列大小:set_size

5. 指定物件的記憶體位址:set_memory

6. 當非排序陣列,刪除元素,將最後一個移到要刪除的位置,可以減少物件移動數量:move_last_and_erase

7. 加入物件不需要複製;加入空物件,針對目標記憶體內容修改,減少複製物件動作:add_one

8. 將物件移動到特定位置,減少物件總移動數量:move_position

#ifndef _data_array_h_
#define _data_array_h_

#include <crtdbg.h>

template <class T>
class data_array
{
public:
	data_array(const data_array&,int max_item_count=0);
	data_array(const T*,int count,int max_item_count=0);
	explicit data_array(int max_item_count=0);//explicit: 數字不要自動轉成data_array!
	~data_array();

	//有多少物件
	int size()const;
	//改變物件數量
	void set_size(int new_size,int max_item_count=0);

	//存取物件
	T* ptr();
	T* begin();
	T* end();

	T& operator[](int index);
	T& at(int index);
	T& front();
	T& back();

	//const 物件
	const T* ptr()const;
	const T* begin()const;
	const T* end()const;

	const T& operator[](int index) const;
	const T& at(int index) const;
	const T& front()const;
	const T& back()const;	

	//指定
	void set_memory(T* item_ptr,int item_size);
	void assign(const T*,int count,int max_item_count=0);
	void assign(const data_array&,int max_item_count=0);
	void assign(int count,const T&x)
	{
		_size=0;
		reserve(count);
		_size=count;
		T*from=_ptr;
		T*end=_ptr+_size;
		while(from&operator =(const data_array&);
	bool operator ==(const data_array&)const;
	bool operator !=(const data_array&x)const
	{
		return !(x==*this);
	}

	//加入物件
	void push_back(const T&);
	void push_back(const T*,int count);
	void push_back(const T*pfrom,const T* pend)
	{
		push_back(pfrom,pend-pfrom);
	}
	void insert(int index,const T&);
	void insert(int index,const T*,int count);
	void insert(T*pat,const T*pfrom, const T* pend)
	{
		//pat 是array的指標
		_ASSERT(pat>=_ptr && pat<=_ptr+_size);  		insert(pat-_ptr,pfrom,pend-pfrom); 	}  	void insert(T*pat,const T&x)  	{  		//pat 是array的指標  		_ASSERT(pat>=_ptr && pat<=_ptr+_size);  		insert(pat-_ptr,x);  	}  	//加入未初始化的項目,傳回新加入的指標  	//如果要加入的物件已經存在,使用push_back,   	//如果要加入的物件不存在,用add_one再去改變內部的資料,這樣少1次複製動作。  	T&add_one();  	//移動位置  	//動作等同:但可能必較快  	//T tmp=vec[from_index];  	//vec.insert(to_index,tmp);  	//vec.erase(from_index);  	void move_position(int from_index,int to_index);  	//刪除物件  	void erase(int index,int count=1);  	void erase(T*pat,T*pend)  	{  		//pat 是array的指標  		_ASSERT(pat>=_ptr && pat<=_ptr+_size);  		erase(pat-_ptr,pend-pat);  	}  	void erase(T*pat)  	{  		//pat 是array的指標  		_ASSERT(pat>=_ptr && pat<=_ptr+_size);
		erase(pat-_ptr);
	}
	void move_last_and_erase(int index);//將最後一個移到index位置,刪除最後一個
	void pop_back();
	void clear();//物件數量設為0

	void swap(data_array&);
	void swap_item(int index1,int index2);

	//配置記憶體大小
	int capacity()const;
	void reserve(int);
	static int granule_size(int t)
	{
		//allocate_granule, 當使用push_back或insert已配置的記憶體不足,記憶體以allocate_granule的整數增加
		const int allocate_granule=128;
		int scale=t/allocate_granule;
		int value=scale*allocate_granule;
		int extra=t-value;
		if(extra)
			return value+allocate_granule;
		return value;
	}

	//刪除配置的記憶體
	void reset();
protected:
	int _size;
	T* _ptr;
	int _memory_item_size;
	BOOL _need_free;
	//記憶體已配置完成,複製到後面
	void memory_copy_to_back(const T*ptr,int item_count);
	//記憶體已配置完成,將ptr往後gap_count複製item_count個
	void memory_copy_items_back(int gap_count,T*ptr,int item_count);
	//記憶體已配置完成,將ptr往前gap_count複製item_count個
	void memory_copy_items_front(int gap_count,T*ptr,int item_count);
};

#include <malloc.h>
//note memcpy:編譯器最佳化會使用rep movs錯誤!
//使用MoveMemory,拒絕編譯器最佳化
template <class T>
inline bool data_array<T>::operator ==(const data_array<T>&x)const
{
	if(&x==this)
		return true;
	if(x._size!=_size)
		return false;
	if(_size<=0)
		return true;
//當物件有內部有空間,不能用memcmp
//例如如下xx, 內部記憶體可能有未用到的空間,使用memcmp會比較未初始化的空間!
//	struct xx
//	{
//		int x;
//		BYTE t;
//		int g;
//	};

	const T*e=end();
	const T*at=begin();
	const T*c=x.begin();
	while(at<e)
	{
		if(*c!=*at)
			return false;
		c++;
		at++;
	}
	return true;
}
template <class T>
inline void data_array<T>::swap_item(int index1,int index2)
{
	_ASSERT(index1>=0 && index1<_size && index2>=0 && index2<_size);
	T tmp=_ptr[index1];
	_ptr[index1]=_ptr[index2];
	_ptr[index2]=tmp;
}
//記憶體已配置完成,複製到後面
template <class T>
inline void data_array<T>::memory_copy_to_back(const T*ptr,int item_count)
{
	_ASSERT(_memory_item_size>=item_count+_size);
	int len=sizeof(T)*item_count;
	MoveMemory(_ptr+_size,ptr,len);
}
//記憶體已配置完成,將ptr往後gap_count複製item_count個
template <class T>
inline void data_array<T>::memory_copy_items_back(int gap_count,T*ptr,int item_count)
{
	_ASSERT(ptr>=_ptr && ptr<=_ptr+_memory_item_size);
	int len=sizeof(T)*item_count;
	T* dst=ptr+gap_count;

	//end position in memory range.
	_ASSERT((dst+gap_count)<=_ptr+_memory_item_size);
	MoveMemory(dst,ptr,len);
}
//記憶體已配置完成,將ptr往前gap_count複製item_count個
template <class T>
inline void data_array<T>::memory_copy_items_front(int gap_count,T*ptr,int item_count)
{
	_ASSERT(ptr>=_ptr && (ptr+item_count)<=_ptr+_memory_item_size);
	int len=sizeof(T)*item_count;
	T* dst=ptr-gap_count;

	//dst in memory range.
	_ASSERT(dst>=_ptr);
	MoveMemory(dst,ptr,len);
}

template <class T>
inline void data_array<T>::move_position(int from_index,int to_index)
{
	_ASSERT(from_index>=0 && from_index<_size);
	_ASSERT(to_index>=0 && to_index<_size);
	if(from_index==to_index)
		return;

	T tmp=_ptr[from_index];
	if(from_index<to_index)
	{
		//copy from front
		MoveMemory(_ptr+from_index,_ptr+from_index+1,(to_index-from_index)*sizeof(T));
	}else
	{
		//copy from back
		MoveMemory(_ptr+to_index+1,_ptr+to_index,(from_index-to_index)*sizeof(T));
	}
	_ptr[to_index]=tmp;
}
template <class T>
inline T& data_array<T>::at(int index)
{
	_ASSERT(index>=0 && index<_size);
	return _ptr[index];
}

template <class T>
inline const T& data_array<T>::at(int index)const
{
	_ASSERT(index>=0 && index<_size);
	return _ptr[index];
}

template <class T>
inline T& data_array<T>::front()
{
	_ASSERT(_size);
	return _ptr[0];
}

template <class T>
inline const T& data_array<T>::front()const
{
	_ASSERT(_size);
	return _ptr[0];
}

template <class T>
inline T& data_array<T>::back()
{
	_ASSERT(_size);
	return _ptr[_size-1];
}

template <class T>
inline const T& data_array<T>::back()const
{
	_ASSERT(_size);
	return _ptr[_size-1];
}

template <class T>
inline void data_array<T>::pop_back()
{
	_ASSERT(_size>0);
	_size--;
}
template <class T>
inline const T* data_array<T>::begin()const
{
	return _ptr;
}
template <class T>
inline T* data_array<T>::begin()
{
	return _ptr;
}
template <class T>
inline const T* data_array<T>::end()const
{
	return _ptr+_size;
}
template <class T>
inline T* data_array<T>::end()
{
	return _ptr+_size;
}
template <class T>
inline const T* data_array<T>::ptr()const
{
	return _ptr;
}
template <class T>
inline T* data_array<T>::ptr()
{
	return _ptr;
}

template <class T>
inline const T& data_array<T>::operator[](int index) const
{
	_ASSERT(index>=0 && index<_size);
	return _ptr[index];
}
template <class T>
inline T& data_array<T>::operator[](int index)
{
	_ASSERT(index>=0 && index<_size);
	return _ptr[index];
}

template <class T>
inline void data_array<T>::clear()
{
	_size=0;
}
template <class T>
inline void data_array<T>::reset()
{
	if(_memory_item_size)
	{
		if(_need_free)
		{
			free(_ptr);
			_need_free=0;
		}
		_ptr=0;
		_size=0;
		_memory_item_size=0;
	}
}

template <class T>
inline int data_array<T>::capacity()const
{
	return _memory_item_size;
}
template <class T>
inline void data_array<T>::reserve(int t)
{
	_ASSERT(t>=_size);
	//只配置更多
	if(_memory_item_size<t)
	{
		data_array<T> tmp(*this,t);
		tmp.swap(*this);
		return;
	}
}
template <class T>
inline void data_array<T>::move_last_and_erase(int index)//將最後一個移到index位置,刪除最後一個
{
	//請保證index正確
	_ASSERT(index>=0 && index<_size);
	int last=_size-1;
	if(index!=last)
		_ptr[index]=_ptr[last];
	_size--;
}

template <class T>
inline void data_array<T>::erase(int index,int count)
{
	//請保證index正確
	_ASSERT(index>=0 && index<_size);
	_ASSERT(count>=1);
	//刪過頭了, count太多!
	_ASSERT(index+count<=_size);	

	int back_count=_size-(index+count);
	_size=index+back_count;
	if(back_count<=0)//刪到尾巴
	{
		return;
	}

	_ASSERT(_size>0);//當為0, 在上一個if判斷裡面處理了
	memory_copy_items_front(count,_ptr+index+count,back_count);
}

template <class T>
inline T& data_array<T>::add_one()
{
	if(_size+1>_memory_item_size)
	{
		int new_size=granule_size(_size+1);
		reserve(new_size);
	}
	_size++;
	_ASSERT(_memory_item_size>=_size);
	return _ptr[_size-1];
}
template <class T>
inline void data_array<T>::push_back(const T&x)
{
	if(_size+1>_memory_item_size)
	{
		int new_size=granule_size(_size+1);
		reserve(new_size);
	}
	_ptr[_size]=x;
	_size++;
	_ASSERT(_memory_item_size>=_size);
}
template <class T>
inline void data_array<T>::push_back(const T*p,int count)
{
	if(count<=0)
		return;

	if(_size+count>_memory_item_size)
	{
		int new_size=granule_size(_size+count);
		data_array<T> tmp(*this,new_size);
		tmp.memory_copy_to_back(p,count);
		tmp._size+=count;
		tmp.swap(*this);
	}else
	{
		memory_copy_to_back(p,count);
		_size+=count;
	}
	_ASSERT(_memory_item_size>=_size);
}
template <class T>
void data_array<T>::insert(int index,const T&x)
{
	if(_size+1>_memory_item_size)
	{
		int new_size=granule_size(_size+1);
		if(index>=_size)
		{//add back.
			data_array<T> tmp(*this,new_size);
			tmp.swap(*this);
			_ptr[_size]=x;
			_size++;
			_ASSERT(_memory_item_size>=_size);
			return;
		}

		data_array<T> tmp(new_size);
		if(index>0)//copy datas before index
		{
			tmp.memory_copy_to_back(_ptr,index);
			tmp._size=index;
		}
		tmp._ptr[tmp._size]=x;
		tmp._size++;

		int remain_count=_size-index;
		tmp.memory_copy_to_back(_ptr+index,remain_count);
		tmp._size+=remain_count;
		tmp.swap(*this);
		_ASSERT(_memory_item_size>=_size);
		return;
	}

	int remain_count=_size-index;
	if(remain_count<=0)
	{//add back.
		_ptr[_size]=x;
		_size++;
		return;
	}

	//move back 1 items.
	memory_copy_items_back(1,_ptr+index,remain_count);

	_ptr[index]=x;
	_size++;
	_ASSERT(_memory_item_size>=_size);
}
template <class T>
void data_array<T>::insert(int index,const T*p,int count)
{
	if(count<=0)
		return;

	//加入的不應該是data_array的內容
	_ASSERT(!(p>=_ptr && p<(_ptr+_size)));

	if(_size+count>_memory_item_size)
	{
		int new_size=granule_size(_size+count);
		if(index>=_size)
		{//add back.
			data_array<T> tmp(*this,new_size);
			tmp.swap(*this);
			memory_copy_to_back(p,count);
			_size+=count;
			_ASSERT(_memory_item_size>=_size);
			return;
		}

		data_array<T> tmp(new_size);
		if(index>0)//copy datas before index
		{
			tmp.memory_copy_to_back(_ptr,index);
			tmp._size=index;
		}			

		//copy data
		tmp.memory_copy_to_back(p,count);
		tmp._size+=count;

		//copy data at and after index.
		int remain_count=_size-index;
		tmp.memory_copy_to_back(_ptr+index,remain_count);
		tmp._size+=remain_count;
		tmp.swap(*this);
		_ASSERT(_memory_item_size>=_size);
		return;
	}

	int remain_count=_size-index;
	if(remain_count<=0)
	{//add back.
		memory_copy_to_back(p,count);
		_size+=count;
		return;
	}

	//move back.
	memory_copy_items_back(count,_ptr+index,remain_count);

	//add data to index.
	int len=sizeof(T)*count;
	MoveMemory(_ptr+index,p,len);
	_size+=count;

	_ASSERT(_memory_item_size>=_size);
}
template <class T>
inline void data_array<T>::assign(const T*p,int count,int max_item_count)
{
	//不應該是data_array的內容
	_ASSERT(!(p>=_ptr && p<(_ptr+_size)));

	if(max_item_count<count)
		max_item_count=count;

	if(_memory_item_size<max_item_count)
	{
		data_array<T> tmp(p,count,max_item_count);
		tmp.swap(*this);
		return;
	}

	if(count>0)
	{
		int len=count*sizeof(T);
		MoveMemory(_ptr,p,len);
		_size=count;
		return;
	}
	_size=0;
}
template <class T>
inline void data_array<T>::assign(const data_array&x,int max_item_count)
{
	if(this==&x)
		return;
	assign(x._ptr,x._size,max_item_count);
}
template <class T>
inline data_array<T>& data_array<T>::operator =(const data_array<T>&x)
{
	if(this==&x)
		return *this;
	assign(x._ptr,x._size,x._memory_item_size);
	return *this;
}

template <class T>
inline int data_array<T>::size()const
{
	return _size;
}
template <class T>
inline void data_array<T>::set_size(int new_size,int max_item_count)
{
	if(max_item_count<new_size)
		max_item_count=new_size;

	if(max_item_count<=_memory_item_size)
	{
		_size=new_size;
		return;
	}

	if(new_size<_size)//比較小的值複製數量較少
		_size=new_size;

	data_array<T> tmp(*this,max_item_count);
	tmp.swap(*this);
	_size=new_size;
}

template <class T>
inline void data_array<T>::set_memory(T* item_ptr,int item_size)
{
	_ASSERT(item_size>0);
	//memory ptr can read?
	_ASSERT(_CrtIsValidPointer( item_ptr, item_size*sizeof(T), TRUE ) );
	reset();
	//reset will set _need_free, _size to zero
	_ASSERT(_need_free==0);
	_ASSERT(_size==0);
	_ptr=item_ptr;
	_memory_item_size=item_size;
}
template <class T>
data_array<T>::data_array(const data_array<T>&x,int max_item_count)
{
	if(max_item_count<x._size)
		max_item_count=x._size;

	if(max_item_count==0)
	{
		_need_free=0;
		_ptr=0;
		_size=0;
		_memory_item_size=0;
		return;
	}

	int len=max_item_count*sizeof(T);
	_ptr=(T*)malloc(len);
	_need_free=1;
	_memory_item_size=max_item_count;

	len=x._size*sizeof(T);
	if(len)
		MoveMemory(_ptr,x._ptr,len);
	_size=x._size;
}
template <class T>
data_array<T>::data_array(const T*p,int count,int max_item_count)
{
	if(max_item_count<count)
		max_item_count=count;

	if(max_item_count==0)
	{
		_need_free=0;
		_ptr=0;
		_size=0;
		_memory_item_size=0;
		return;
	}
	int len=max_item_count*sizeof(T);
	_ptr=(T*)malloc(len);
	_need_free=1;
	_memory_item_size=max_item_count;

	len=count*sizeof(T);
	if(len)
		MoveMemory(_ptr,p,len);
	_size=count;
}
template <class T>
inline data_array<T>::data_array(int max_item_count)
{
	if(max_item_count==0)
	{
		_need_free=0;
		_ptr=0;
		_size=0;
		_memory_item_size=0;
		return;
	}
	int len=max_item_count*sizeof(T);
	_ptr=(T*)malloc(len);
	_need_free=1;
	_size=0;
	_memory_item_size=max_item_count;
}
template <class T>
inline void data_array<T>::swap(data_array<T>&x)
{
	int tmp;

	tmp=_need_free;
	_need_free=x._need_free;
	x._need_free=tmp;

	tmp=_size;
	_size=x._size;
	x._size=tmp;

	tmp=_memory_item_size;
	_memory_item_size=x._memory_item_size;
	x._memory_item_size=tmp;

	T* t;
	t=_ptr;
	_ptr=x._ptr;
	x._ptr=t;
}
template <class T>
inline data_array<T>::~data_array()
{
	reset();
}

#endif
Categories: 小段程式 Tags:

trac與subversion

2011年3月11日 尚無評論

在幾年前尋找版本控制軟體,沒有很好用又便宜的。

感謝,自由軟體。
版本控制伺服器端subversion
版本控制用戶端TortoiseSVN
軟體的專案管理trac
linux安裝也相當方便,整體使用起來相當不錯。

Categories: programming Tags:

真理難明

2011年2月28日 尚無評論

活的人居住在陽世間,相對於死人居住在陰間。
多1分陽氣則多1分活力;
體內陰霾四佈,體能精力喪失;
信心崩潰,最易引發憂鬱!
甚至自殺!

http://www.kunwujian.com/?p=111

真心難尋,真理難明,能如此腳踏實地作研究的世間少有!

至理名言:
"你可能難以相信你那破敗枯槁的肉身竟是由於你所相信的知識所致而非無知"!

Categories: 感言 Tags:

檔案與資料夾複製

2010年10月13日 1 則評論

以前硬碟經常損壞留下的後遺症,我會另外買一顆硬碟備份資料。

經常要做一些檔案複製動作,從這裡到那裡。修改或做一些變動,過了幾天,再複製回去…

檔案往往好幾萬個,全部複製太慢;慢慢查看哪些檔案要備份,也很慢。

使用windows的備份工具,設定選項太多,複雜;windows的公事包太、太慢了。

我喜歡簡單的複製(備份)功能,有相同需要的可以使用看看。

BackUpFiles

提示

免安裝,解壓縮之後直接可執行

判斷新檔案採用檔案大小與最後修改日期。

檔案複製之後,目的檔案的屬性、建立日期、最後修改日期與來源檔案一致。

新建立路徑的最後修改日期與來源路徑一致。

檔案在NTFS與FAT檔案系統間複製,最後修改日期可能會有1、2秒的誤差,這是FAT檔案時間解析度的關係,不是BUG。

開始執行前請小心確認設定,檔案刪除或覆蓋之後將無法復原。

不要顯示訊息,將NtyMsg.exe改名或刪除。

Categories: programming, vc60 Tags:

fatal error LNK1202

2010年9月3日 10 則評論

程式使用多個靜態連結函式庫,要編譯debug版本,出現 ..... fatal error LNK1202: "....\UDebug\vc60.pdb" is missing debugging information for referencing module 唉! 什麼錯誤! VC static link library 的project option 預設:/Fd"Debug/" ==&gt;輸出vc6.pdb 使用的程式在連結的時候要找多個叫做vc6.pdb, 唯一的可能是放在不同目錄.... 一般的習慣,將*.lib放在lib資料夾。vc6.pdb 不能放在lib資料夾了,這真是爛主意。 修改/Fd"Debug/"指定特定名稱的pdb檔案/Fd"Debug/????.pdb",然後就可以複製到lib資料夾。 ????.pdb ==>自定的檔案名稱。

Categories: debug Tags:

線上雜誌

2010年5月11日 1 則評論
Categories: resources Tags: