/*s*************************************************************************** * * Copyright (c), Ilya Valuev 2005 All Rights Reserved. * * Author : Ilya Valuev, MIPT, Moscow, Russia * * Project : GridMD, ivutils * *****************************************************************************/ /*s**************************************************************************** * $Log: vector_3.h,v $ * Revision 1.2 2011/06/11 16:53:55 valuev * sync with LAMMPS * * Revision 1.1 2011/06/10 17:15:07 morozov * First Windows project with the correct directory structure * * Revision 1.22 2010/11/17 02:13:32 valuev * Added analysis phase, fixed some memory leaks * * Revision 1.21 2009/09/09 14:43:35 valuev * fixed trajreader * * Revision 1.20 2009/07/24 05:08:46 valuev * Sync with FDTD, added molecule setup * * Revision 1.33 2009/06/01 13:01:42 valuev * Added ShearBox * * Revision 1.32 2009/05/28 07:49:00 valuev * updated chemosensor * * Revision 1.31 2009/05/22 08:53:52 valuev * new uiExperiment interface * * Revision 1.30 2009/02/22 10:49:56 lesha * Vector_Nt constructors are modified * * Revision 1.29 2009/02/04 14:23:31 valuev * fixed bug in maxabscoord and minabscoord functions * * Revision 1.28 2009/02/04 10:56:30 lesha * SINGLE_PRECISION is recovered * * Revision 1.27 2009/02/03 00:47:35 lesha * *** empty log message *** * * Revision 1.26 2009/01/30 13:54:05 valuev * restructured as a library * * Revision 1.16 2008/08/18 21:40:09 valuev * added Gurski-Krasko potential * * Revision 1.15 2008/05/05 17:27:43 morozov * cvector_3.h is the new header for class cVector_3. Old one is moved to cvector_3old.h * class hmatrix is added to pairhash.h * wavepackets.h contains class WavePacket * * Revision 1.14 2008/04/22 12:44:17 valuev * made gcc 4.12 compilable * * Revision 1.13 2008/04/21 23:13:44 valuev * made gcc 4.12 compilable * * Revision 1.12 2008/04/21 22:42:30 valuev * *** empty log message *** * * Revision 1.11 2008/04/15 13:11:41 valuev * Added antisymmetrized wave packets * * *******************************************************************************/ /*r @file vector_3.h @brief работа с трехмерными векторами */ # ifndef VECTOR_3_H # define VECTOR_3_H # define _USE_MATH_DEFINES # include # include # include # include // some compilers don't define PI! # ifndef M_PI # define M_PI 3.1415926535897932385 # endif # ifndef fmod //r деление по модулю чисел с плавающей точкой # define fmod(a,b) ((a)-((long)((a)/(b))*(b))) # endif using namespace std; #ifndef SINGLE_PRECISION typedef double vec_type; #else typedef float vec_type; #endif //e "infinitely" large number in Vector_3 sense //r "бесконечно большое" число в смысле Vector_3 //# ifndef SINGLE_PRECISION //# define VEC_INFTY 1.e20 //# else //# define VEC_INFTY 1.e20f //# endif #define VEC_INFTY numeric_limits::max() //e "infinitely" small number in Vector_3 sense (used for vector comparisons) //r "бесконечно малое" число в смысле Vector_3 (используется для сравнений) //# ifndef SINGLE_PRECISION //# define VEC_ZERO 1.e-20 //# else //# define VEC_ZERO 1.e-20f //# endif #define VEC_ZERO 512*numeric_limits::epsilon() //r N-мерный вектор типа T, с некоторыми полезными операциями template struct Vector_Nt { typedef T value_type; T v[N]; Vector_Nt(const T &a=0){ for (int i=0; i0)v[0]=a1; if(N>1)v[1]=a2; for(int i=2;i0)v[0]=s1; if(N>1)v[1]=s2; if(N>2)v[2]=s3; for(int i=3;i Vector_Nt(const A *beg) { for (int i=0; i Vector_Nt(const Vector_Nt& v1) { for (int i=0; i void copy_to(A *beg) const { for (int i=0; iVEC_ZERO)return false; return true; }; inline bool operator!=(const Vector_Nt &vect) const{ return (!(this->operator==(vect))); }; inline Vector_Nt operator+(const Vector_Nt& vect) const{ Vector_Nt result; for (int i=0; inorm(); if(norm>=VEC_ZERO){ T c=newnorm/norm; for (int i=0; i=VEC_INFTY){ if(result>=0) result=0.; result-=1; v[i]=v[i]>0 ? 1 : -1; } else if(result>=0) //still summing the normal components result+=v[i]*v[i]; else v[i]=0.; } if(fabs(result)cell[i]/2){ ret[i]-=cell[i]; } else if(v[i]<-cell[i]/2){ ret[i]+=cell[i]; } } } return ret; } //e @return a vector projection on a given axis Vector_Nt prj(int i) const { Vector_Nt res; res[i]=v[i]; return res; } //e @return a vector projection on a given vector (k*v)*k Vector_Nt prj(const Vector_Nt &k) const { return k*(k*(*this)); } //e @return a vector of length l parallel to this Vector_Nt unit(T l=1) const { Vector_Nt res(*this); res.normalize(l); return res; } //e reduction to elementary cell [0, cell[i]) (FOR REDUCTION TO ELEMENTARY CELL) //e flags indicate the periodicity in specific directions: 0x1 for X, 0x2 for Y, 0x4 for Z //r Почти то же, что и rcell1, но без ограничения на положение *this и с другой системой ячеек. /*r В начале координат находится не центр ячейки, а ее угол. Может работать медленнее из-за наличия операции деления по модулю с плавающей точкой */ Vector_Nt rcell(const Vector_Nt &cell, int flags=0xffff) const { Vector_Nt ret(*this); for (int i=0, flag=1; icell[i]) // printf("!"); } } return ret; } Vector_Nt rpcell(const Vector_Nt &p1, const Vector_Nt &cell, int flags=0xfff) const { Vector_Nt ret(*this); for (int i=0, flag=1; ip1[i]+cell[i]) { ret.v[i]=fmod(v[i]-p1[i],cell[i])+p1[i]; if (ret.v[i]vv){ im=i; vv=v[i]; } } if(ind)*ind=im; return vv; } //e returns the corrd having maximal absolute value T maxabscoord(int *ind=NULL) const { int im=0; T vv=fabs(v[0]); for (int i=1; ivv){ im=i; vv=fabs(v[i]); } } if(ind)*ind=im; return v[im]; } //e returns the corrd having minimal absolute value T minabscoord(int *ind=NULL) const { int im=0; T vv=fabs(v[0]); for (int i=1; i=VEC_INFTY) return true; } return false; } }; template Vector_Nt operator*(const T &coeff,const Vector_Nt &vec){ return vec*coeff; } template Vector_Nt operator*(int coeff,const Vector_Nt &vec){ return vec*coeff; } //template <> Vector_Nt operator*(const double &coeff,const Vector_Nt &vec); // old Vector_3 compatibility typedefs and functions typedef Vector_Nt Vector_3; typedef Vector_3 *Vector_3P; typedef Vector_Nt Vector_2; typedef Vector_2 *Vector_2P; template class Vector_N: public Vector_Nt{ }; //Vector_3 operator*(int coeff,const Vector_3 &vec){ // return vec*((vec_type)coeff); //} //e finds the maximum distance between vector pairs //r Находит максимальное расстояние между векторами va1[i], va2[i], i=1..n /*r @param va1 - массив Vector_3[n] @param n - длина массивов va1 и va2 */ vec_type dist_max(Vector_3 *va1,Vector_3 *va2,int n); //e finds average distance between vector pairs //r Находит среднее расстояние между векторами va1[i], va2[i], i=1..n vec_type dist_av(Vector_3 *va1,Vector_3 *va2,int n); //e finds the average difference norm between two vector sets of the same length /*e optionally gives the indexes for maximal and minimal difference va2 can be NULL, then the norm of va1 is used */ //r Находит среднее расстояние между va1[i] и va2[i], а также, по желанию, индексы, на которых достигается min и max расстояние vec_type diff_av(Vector_3 *va1,Vector_3 *va2,int n, int *minind=0, int *maxind=0); //e finds suitable perpendicular to a vector //r Находит перпендикуляр к вектору vAB Vector_3 FindPerp(const Vector_3 &vAB); //e Returns the average (center) vector of the vector array //e and cooordinates of a minimal box in which it is contained Vector_3 GetScope(const Vector_3 *varr,long n,Vector_3* box_min,Vector_3* box_max); //e the same with long index array Vector_3 GetIScope(const Vector_3 *varr,long *indarr,long n,Vector_3* box_min,Vector_3* box_max); //e the same with int index array Vector_3 GetIScopei(const Vector_3 *varr,int *indarr,int n,Vector_3* box_min,Vector_3* box_max); // neue Funktionen //e clears vector array with optional integer index //r Очистка массива векторов, с поддержкой индексирования /*r В данном Vector_3 vec[] обнуляет n координат. Если ind==NULL, то очищает первые n элементов. Если ind!=NULL, то для i=0..n-1 очищает vec[ind[i]] См. @ref indexed_calculations. */ void clear_vecarri(int n,Vector_3 *vec, int *ind=0); //e reflects the vector ini+dir*t+0.5*force*t^2 to be inside a box limited by 0 and box sizes //e changes dir according to the final state //e fills crossed dir with bit flags corresponding directions along which the walls were crossed Vector_3 Reflect(Vector_3& ini, double t,Vector_3 &dir, double *box, int flag=0x7, const Vector_3 &force=Vector_3()); inline vec_type vec_area(const Vector_2 &vect1, const Vector_2 &vect2) { return fabs(vect1[0]*vect2[1]-vect1[1]*vect2[0])/2; } inline vec_type vec_area(const Vector_3 &vect1, const Vector_3 &vect2) { return (vect1%vect2).norm()/2; } // remake for vec_type! template denum_t acccomp(const num_t x, const denum_t y, const val_t val) { num_t eps_num=numeric_limits::epsilon(); denum_t eps_denum=numeric_limits::epsilon(); return (eps_num>=eps_denum) ? acccomp(x, (num_t)y, (num_t)val) : acccomp((denum_t)x, y, (denum_t)val); } template denum_t acccomp(const num_t x, const denum_t y) { return acccomp(x, y, num_t(1)); } template bool acccomp(const T x, const T y, const T val) { T eps=numeric_limits::epsilon(); int iexp; frexp(val,&iexp); T mult=ldexp(.5, iexp+1); T err=T(256)*mult*eps; return fabs(x-y)<=err; } template bool acccomp(const T x, const T y) { return acccomp(x, y, T(1)); } template denum_t accdiv(const num_t x, const denum_t y) { num_t eps_num=numeric_limits::epsilon(); denum_t eps_denum=numeric_limits::epsilon(); return (eps_num>=eps_denum) ? accdiv1(x, (num_t)y) : accdiv1((denum_t)x, y); } template T accdiv1(T x, T y) { T result; T eps=numeric_limits::epsilon(); T fr=x/y; T ifr=floor(fr+T(.5)); // T err=64*eps*(ifr!=0 ? fabs(ifr) : 1); int mult; if (ifr<=512) mult=512; else { int iexp; frexp(ifr,&iexp); mult=int(ldexp(.5, iexp+1)); } T err=mult*eps; if (fabs(fr-ifr)<=err) result=ifr; else result=fr; return result; } template denum_t accdiv_rmd(const num_t x, const denum_t y, P *remainder) { num_t eps_num=numeric_limits::epsilon(); denum_t eps_denum=numeric_limits::epsilon(); return (eps_num>=eps_denum) ? accdiv_rmd(x, (num_t)y, remainder) : accdiv_rmd((denum_t)x, y, remainder); } template T accdiv_rmd(const T x, const T y, P *remainder) { T result=accdiv(x, y); T iresult=floor(result); if (result-iresult>0) *remainder=x-iresult*y; else *remainder=0; return result; } //e returns random unit vector uniformely distributed in space (?? check this) inline Vector_3 randdir(){ vec_type xi1=2*((vec_type)rand())/RAND_MAX-1.; vec_type xi2=((vec_type)rand())/RAND_MAX; vec_type r1=sqrt(1.-xi1*xi1); return Vector_3(r1*cos(2*M_PI*xi2),r1*sin(2*M_PI*xi2),xi1); } ///\en Calculates extent of the vector container. /// \return the center of the vector set, optionally /// (if arguments are not NULL) fills the bounding box in \a box_min, \a box_max. template Vector_3 get_extent(vec_inp_it beg,vec_inp_it end, Vector_3* box_min=NULL,Vector_3* box_max=NULL){ if(beg==end) return Vector_3(); Vector_3 center(*beg++); Vector_3 cube1(center), cube2(center); size_t n=1; for(;beg!=end;++beg){ Vector_3 vec=*beg; center+=vec; for(size_t j=0;j<3;j++){ if(cube1[j]>vec[j]) cube1[j]=vec[j]; if(cube2[j] bool much_less(const T& a, const T& b, const T &factor){ if(fabs(a)