00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef Array1D_H
00014 #define Array1D_H
00015
00016 #include <iostream>
00017 #include <iomanip>
00018 #include <math.h>
00019 #include "cppblas.h"
00020 #include <assert.h>
00021
00022 using namespace std;
00023
00032 template <class T> class Array1D
00033 {
00034 private:
00035
00040 int n_1;
00041
00046 T* pArray;
00047
00048 public:
00049
00055 int dim1() const
00056 {
00057 return n_1;
00058 }
00059
00065 int size() const
00066 {
00067 return n_1;
00068 }
00069
00075 T* array()
00076 {
00077 return pArray;
00078 }
00079
00085 void allocate(int i)
00086 {
00087 #ifdef QMC_DEBUG
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 #endif
00100 if ( n_1 != i )
00101 {
00102 deallocate();
00103 n_1 = i;
00104 if (n_1 >= 1)
00105 {
00106 pArray = new T[n_1];
00107 }
00108 else
00109 {
00110 n_1 = 0;
00111 pArray = 0;
00112 }
00113 }
00114 }
00115
00120 void resize(int i)
00121 {
00122 allocate(i);
00123 }
00124
00129 void clear()
00130 {
00131 deallocate();
00132 }
00133
00138 void deallocate()
00139 {
00140 if ( n_1 > 0 )
00141 {
00142 delete [] pArray;
00143 pArray = 0;
00144 n_1 = 0;
00145 }
00146 }
00147
00148 #ifdef USEBLAS
00149 T operator*( const Array1D<double> & rhs)
00150 {
00151 #ifdef QMC_DEBUG
00152 assert(n_1 > 0);
00153 assert(pArray);
00154 assert(rhs.pArray);
00155 #endif
00156 #ifdef USE_CBLAS
00157 return cblas_ddot(n_1, pArray, 1,rhs.pArray, 1);
00158 #else
00159 int inc = 1;
00160 return FORTRAN_FUNC(ddot)(&n_1, pArray, &inc, rhs.pArray, &inc);
00161 #endif
00162 }
00163
00164 T operator*( const Array1D<float> & rhs)
00165 {
00166 #ifdef QMC_DEBUG
00167 assert(n_1 > 0);
00168 assert(pArray);
00169 assert(rhs.pArray);
00170 #endif
00171 #ifdef USE_CBLAS
00172 return cblas_sdot(n_1, pArray, 1,rhs.pArray, 1);
00173 #else
00174 int inc = 1;
00175 return FORTRAN_FUNC(sdot)(&n_1, pArray, &inc, rhs.pArray, &inc);
00176 #endif
00177 }
00178
00179
00180 Array1D operator+( const Array1D & rhs)
00181 {
00182 Array1D <T> A(rhs);
00183 #ifdef USE_CBLAS
00184 cblas_daxpy(n_1, 1.0, pArray,1, A.pArray, 1);
00185 #else
00186 int inc = 1;
00187 double a = 1.0;
00188 FORTRAN_FUNC(daxpy)(&n_1, &a, pArray, &inc, A.pArray, &inc);
00189 #endif
00190 return A;
00191 }
00192
00193
00194 void operator+=( const Array1D & rhs)
00195 {
00196 #ifdef USE_CBLAS
00197 cblas_daxpy(n_1, 1.0, rhs.pArray,1, pArray, 1);
00198 #else
00199 int inc = 1;
00200 double a = 1.0;
00201 FORTRAN_FUNC(daxpy)(&n_1, &a, rhs.pArray, &inc, pArray, &inc);
00202 #endif
00203 }
00204
00205 #else
00206
00210 T operator*( const Array1D & rhs)
00211 {
00212 #ifdef QMC_DEBUG
00213 if ( n_1 != rhs.n_1 )
00214 {
00215 cerr << "ERROR: incorrect sizes for two Array1D's in Array1D*"
00216 << "Array1D" << endl;
00217 assert(0);
00218 }
00219 if ( n_1 <= 0 )
00220 {
00221 cerr << "ERROR: Array1D of size 0 used in Array1D*Array1D" << endl;
00222 assert(0);
00223 }
00224 assert(pArray);
00225 assert(rhs.pArray);
00226 #endif
00227 T temp = 0.0;
00228 for ( int i=0; i<n_1; i++ )
00229 {
00230 temp += pArray[i] * rhs.pArray[i];
00231 }
00232 return temp;
00233 }
00234
00239 Array1D operator+( const Array1D & rhs)
00240 {
00241 #ifdef QMC_DEBUG
00242 if ( n_1 != rhs.n_1 )
00243 {
00244 cerr << "ERROR: incorrect sizes for two Array1D's in Array1D+"
00245 << "Array1D" << endl;
00246 exit(1);
00247 }
00248 if ( n_1 <= 0 )
00249 {
00250 cerr << "ERROR: Array1D of size 0 used in Array1D+Array1D" << endl;
00251 exit(1);
00252 }
00253 assert(pArray);
00254 assert(rhs.pArray);
00255 #endif
00256 Array1D <T> A(n_1);
00257
00258 for ( int i=0; i<n_1; i++ )
00259 {
00260 A.pArray[i] = pArray[i] + rhs.pArray[i];
00261 }
00262 return A;
00263 }
00264
00265 void operator+=( const Array1D<T> & rhs)
00266 {
00267 for(int i=0; i<n_1; i++)
00268 pArray[i] += rhs.pArray[i];
00269 }
00270
00271 #endif
00272
00276 void operator=(const Array1D & rhs)
00277 {
00278 if (n_1 != rhs.n_1) allocate(rhs.n_1);
00279
00280 for (int i=0; i<n_1;i++) pArray[i] = rhs.pArray[i];
00281
00282 }
00283
00288 void operator=(const T C)
00289 {
00290 if (C == 0)
00291 {
00292 memset(pArray,0,sizeof(T)*n_1);
00293 return;
00294 }
00295 for (int i=0; i<n_1; i++)
00296 pArray[i] = C;
00297 }
00298
00303 Array1D operator*( const double rhs)
00304 {
00305 Array1D <T> A(n_1);
00306 for ( int i=0; i<n_1; i++ )
00307 {
00308 A.pArray[i] = rhs*pArray[i];
00309 }
00310 return A;
00311 }
00312
00317 void operator*=(const T C)
00318 {
00319 for (int i=0;i<n_1;i++)
00320 {
00321 pArray[i] *= C;
00322 }
00323 }
00324
00329 void operator/=(const T C)
00330 {
00331 T inv = 1.0/C;
00332 operator*=(inv);
00333 }
00334
00339 Array1D operator-( const Array1D & rhs)
00340 {
00341 if ( n_1 != rhs.n_1 )
00342 {
00343 cerr << "ERROR: incorrect sizes for two Array1D's in Array1D-"
00344 << "Array1D" << endl;
00345 exit(1);
00346 }
00347 if ( n_1 <= 0 )
00348 {
00349 cerr << "ERROR: Array1D of size 0 used in Array1D-Array1D" << endl;
00350 exit(1);
00351 }
00352 Array1D <T> A(n_1);
00353
00354 for ( int i=0; i<n_1; i++ )
00355 {
00356 A.pArray[i] = pArray[i] - rhs.pArray[i];
00357 }
00358 return A;
00359 }
00360
00365 void quaternion_conjugate()
00366 {
00367 if ( n_1 != 4 )
00368 {
00369 cerr << "ERROR: incorrect size for quaternion conjugate." << endl;
00370 exit(1);
00371 }
00372 for (int i=1; i<4; i++)
00373 {
00374 pArray[i] *= -1;
00375 }
00376 }
00377
00384 Array1D quaternion_product( const Array1D & rhs )
00385 {
00386 if ( n_1 != 4 || rhs.n_1 != 4 )
00387 {
00388 cerr << "ERROR: incorrect size for quaternion product." << endl;
00389 exit(1);
00390 }
00391 Array1D<T> product(4);
00392 product.pArray[0] = pArray[0]*rhs.pArray[0] - pArray[1]*rhs.pArray[1] -
00393 pArray[2]*rhs.pArray[2] - pArray[3]*rhs.pArray[3];
00394 product.pArray[1] = pArray[0]*rhs.pArray[1] + pArray[1]*rhs.pArray[0] +
00395 pArray[2]*rhs.pArray[3] - pArray[3]*rhs.pArray[2];
00396 product.pArray[2] = pArray[0]*rhs.pArray[2] - pArray[1]*rhs.pArray[3] +
00397 pArray[2]*rhs.pArray[0] + pArray[3]*rhs.pArray[1];
00398 product.pArray[3] = pArray[0]*rhs.pArray[3] + pArray[1]*rhs.pArray[2] -
00399 pArray[2]*rhs.pArray[1] + pArray[3]*rhs.pArray[0];
00400 return product;
00401 }
00402
00413 void rotate(Array1D axis, double angle)
00414 {
00415 #ifdef QMC_DEBUG
00416 if (n_1 != 3)
00417 {
00418 cerr << "ERROR: incorrect size for rotating point." << endl;
00419 exit(1);
00420 }
00421 #endif
00422 double x = axis(0);
00423 double y = axis(1);
00424 double z = axis(2);
00425 double s = sin(angle);
00426 double c = cos(angle);
00427 double v = 1.0 - c;
00428 double xs = x*s;
00429 double ys = y*s;
00430 double zs = z*s;
00431 double xv = x*v;
00432 double yv = y*v;
00433 double zv = z*v;
00434 double xyv = x*yv;
00435 double yzv = y*zv;
00436 double zxv = z*xv;
00437
00438 double i = (x*xv+c)*pArray[0] + (xyv-zs)*pArray[1] + (zxv+ys)*pArray[2];
00439 double j = (xyv+zs)*pArray[0] + (y*yv+c)*pArray[1] + (yzv-xs)*pArray[2];
00440 double k = (zxv-ys)*pArray[0] + (yzv+xs)*pArray[1] + (z*zv+c)*pArray[2];
00441
00442 pArray[0] = i;
00443 pArray[1] = j;
00444 pArray[2] = k;
00445 }
00446
00453 void rotateQ(Array1D axis, double angle)
00454 {
00455 if (n_1 != 3)
00456 {
00457 cerr << "ERROR: incorrect size for rotating point." << endl;
00458 exit(1);
00459 }
00460 Array1D<T> q_point(4), q_axis(4), q1(4), q2(4);
00461 q_point.pArray[0] = 0.0;
00462 q_axis.pArray[0] = cos(angle/2);
00463 for (int i=1; i<4; i++)
00464 {
00465 q_point.pArray[i] = pArray[i-1];
00466 q_axis.pArray[i] = axis.pArray[i-1]*sin(angle/2);
00467 }
00468 q1 = q_axis.quaternion_product(q_point);
00469 q_axis.quaternion_conjugate();
00470 q2 = q1.quaternion_product(q_axis);
00471 for (int i=1; i<4; i++)
00472 {
00473 pArray[i-1] = q2.pArray[i];
00474 }
00475 }
00476
00480 Array1D<T> cross(Array1D<T> & rhs)
00481 {
00482 #ifdef QMC_DEBUG
00483 if(n_1 != 3 || rhs.dim1() != 3)
00484 {
00485 cout << "Error: cross product vectors are " << n_1 << "x" << rhs.dim1() << endl;
00486 }
00487 #endif
00488 Array1D<T> crossed(3);
00489 crossed[0] = pArray[1]*rhs[2] - pArray[2]*rhs[1];
00490 crossed[1] = pArray[2]*rhs[0] - pArray[0]*rhs[2];
00491 crossed[2] = pArray[0]*rhs[1] - pArray[1]*rhs[0];
00492 return crossed;
00493 }
00494
00495
00496
00497
00498 T mag(){
00499 double sum = 0.0;
00500 for(int i=0; i<n_1; i++)
00501 sum += pArray[i]*pArray[i];
00502 return sqrt(sum);
00503 }
00504
00509 Array1D()
00510 {
00511 pArray = 0; n_1 = 0;
00512 }
00513
00519 Array1D(int i)
00520 {
00521 pArray = 0; n_1 = 0; allocate(i);
00522 }
00523
00533 Array1D(int i, double shift, double range, long & iseed)
00534 {
00535 pArray = 0;
00536 n_1 = 0;
00537 allocate(i);
00538
00539 if(iseed > 0) srand(iseed);
00540 for(int idx=0; idx<n_1; idx++)
00541 {
00542
00543 double val = (double)(rand())/RAND_MAX;
00544 val = range * (val + shift);
00545 pArray[idx] = (T)val;
00546 }
00547 }
00548
00554 Array1D(const Array1D & rhs)
00555 {
00556 n_1 = 0;
00557 pArray = 0;
00558 allocate(rhs.n_1);
00559 for (int i=0; i<n_1; i++) pArray[i] = rhs.pArray[i];
00560 }
00561
00566 ~Array1D()
00567 {
00568 deallocate();
00569 }
00570
00575 T& operator()(int i)
00576 {
00577 #ifdef QMC_DEBUG
00578 if( i < 0 || i >= n_1 )
00579 {
00580 cerr << "Error: Array1D::operator() has i = " << i
00581 << " where n_1 = " << n_1 << endl;
00582 assert( i >= 0 && i < n_1 );
00583 }
00584 assert(pArray);
00585 #endif
00586 return pArray[i];
00587 }
00588
00592 T get(int i) const
00593 {
00594 #ifdef QMC_DEBUG
00595 assert( i >= 0 && i < n_1 );
00596 assert(pArray);
00597 #endif
00598 return pArray[i];
00599 }
00600
00601 T& operator[](int i)
00602 {
00603 #ifdef QMC_DEBUG
00604 assert( i >= 0 && i < n_1 );
00605 assert(pArray);
00606 #endif
00607 return pArray[i];
00608 }
00609
00614 friend ostream& operator<<(ostream & strm, const Array1D<T> & rhs)
00615 {
00616 rhs.printArray1D(strm, 15, 5, 8, ',', false);
00617 return strm;
00618 }
00619
00625 void printArray1D(ostream & strm, int numSigFig, int columnSpace, int maxI, char sep, bool sci) const
00626 {
00627 strm.precision(4);
00628 if(maxI < 0) maxI = n_1;
00629 strm << "{";
00630 for(int i=0; i<n_1;i++)
00631 {
00632 if(i % maxI == 0 && i != 0)
00633 strm << endl << " ";
00634
00635 if(sci) strm.setf(ios::scientific);
00636 else strm.unsetf(ios::scientific);
00637
00638 strm << setprecision(numSigFig)
00639 << setw(numSigFig+columnSpace)
00640 << pArray[i];
00641 if(i<n_1-1) strm << sep;
00642 }
00643 strm << " }";
00644 }
00645
00664 int read(istream & strm, T initialization, string label)
00665 {
00666 int pi = 0;
00667 strm >> ws;
00668 string temp;
00669 while(isdigit(strm.peek()) ||
00670 strm.peek() == '+' ||
00671 strm.peek() == '-' ||
00672 strm.peek() == '.')
00673 {
00674 strm >> temp;
00675 if(pi < n_1)
00676 pArray[pi] = (T)(atof(temp.c_str()));
00677 pi++;
00678 strm >> ws;
00679 }
00680
00681 if(pi > n_1)
00682 clog << "Warning: you entered " << pi << " parameters, when only "
00683 << n_1 << " were expected for " << label << endl;
00684
00685 for (int i=pi; i < n_1; i++)
00686 pArray[i] = initialization;
00687
00688 return pi;
00689 }
00690 };
00691
00692 #endif