00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef Array2D_H
00033 #define Array2D_H
00034
00035 #include <iostream>
00036 #include <iomanip>
00037 #include <typeinfo>
00038 #include "Complex.h"
00039 #include <assert.h>
00040 #include "Array1D.h"
00041 #include "fastfunctions.h"
00042 #include "cppblas.h"
00043
00044
00045
00046
00047
00048
00049
00050 static const bool USE_KAHAN = false;
00051
00052
00053
00054
00055
00056
00057
00058
00059 extern "C"
00060 {
00061 void FORTRAN_FUNC(dgesv)(int* N, int* NRHS,
00062 double *A, int* lda, int* ipiv,
00063 double *B, int* ldb,
00064 int* info);
00065 void FORTRAN_FUNC(sgesv)(int* N, int* NRHS,
00066 float *A, int* lda, int* ipiv,
00067 float *B, int* ldb,
00068 int* info);
00069 void FORTRAN_FUNC(dggev)(const char* jobvl, const char* jobvr, int* n,
00070 double *a, int* lda, double *b, int* ldb,
00071 double *alphar, double *alphai, double *beta,
00072 double *vl, int* ldvl,
00073 double *vr, int* ldvr,
00074 double *work, int* lwork,
00075 int *info);
00076 }
00077
00078
00079 #if defined SINGLEPRECISION || defined QMC_GPU
00080 typedef float qmcfloat;
00081 const static float REALLYTINY = 1e-35f;
00082 #else
00083 typedef double qmcfloat;
00084 const static double REALLYTINY = 1e-300;
00085 #endif
00086
00087 using namespace std;
00088
00095 template <class T> class Array2D
00096 {
00097 private:
00102 int n_1;
00103
00104
00109 int n_2;
00110
00114 T * pArray;
00115
00120 Array1D<T> diCol;
00121 Array1D<int> diINDX;
00122 Array1D<T> diVV;
00123
00124 public:
00129 T* array()
00130 {
00131 return pArray;
00132 }
00133
00139 int dim1() const
00140 {
00141 return n_1;
00142 }
00143
00149 int dim2() const
00150 {
00151 return n_2;
00152 }
00153
00159 int size() const
00160 {
00161 return n_1*n_2;
00162 }
00163
00171 void allocate(int i, int j)
00172 {
00173 #ifdef QMC_DEBUG
00174 if( i < 0 || j < 0)
00175 {
00176 cerr << "Error: invalid dimensions in Array2D::allocate\n"
00177 << " i = " << i << endl
00178 << " j = " << j << endl;
00179 assert(0);
00180 }
00181 #endif
00182 if( n_1 != i || n_2 != j )
00183 {
00184 deallocate();
00185
00186 n_1 = i;
00187 n_2 = j;
00188
00189 if(n_1 >= 1 && n_2 >= 1)
00190 {
00191 pArray = new T[ n_1*n_2 ];
00192 }
00193 else
00194 {
00195 pArray = 0;
00196 }
00197 }
00198 }
00199
00204 void deallocate()
00205 {
00206 if(pArray != 0)
00207 delete [] pArray;
00208 pArray = 0;
00209
00210 n_1 = 0;
00211 n_2 = 0;
00212
00213 diCol.deallocate();
00214 diINDX.deallocate();
00215 diVV.deallocate();
00216 }
00217
00218 void setupMatrixMultiply(const Array2D<T> & rhs, Array2D<T> & result,
00219 const bool rhsIsTransposed) const
00220 {
00221 if(rhsIsTransposed)
00222 {
00223 #ifdef QMC_DEBUG
00224 if(n_2 != rhs.n_2)
00225 {
00226 cerr << "ERROR: Transposed Matrix multiplication: " << n_1 << "x"
00227 << n_2 << " * " << rhs.n_2 << "x" << rhs.n_1 << endl;
00228 exit(1);
00229 }
00230 if(result.dim1() != n_1 || result.dim2() != rhs.n_1)
00231 {
00232 cerr << "Warning: we had to reallocate result: "
00233 << result.dim1() << "x" << result.dim2() << " to "
00234 << n_1 << "x" << rhs.n_1 << endl;
00235
00236 }
00237 #endif
00238 result.allocate(n_1,rhs.n_1);
00239 }
00240 else
00241 {
00242 #ifdef QMC_DEBUG
00243 if(n_2 != rhs.n_1)
00244 {
00245 cerr << "ERROR: Matrix multiplication: " << n_1 << "x"
00246 << n_2 << " * " << rhs.n_1 << "x" << rhs.n_2 << endl;
00247 exit(1);
00248 }
00249 if(result.dim1() != n_1 || result.dim2() != rhs.n_2)
00250 {
00251 cerr << "Warning: we had to reallocate result: "
00252 << result.dim1() << "x" << result.dim2() << " to "
00253 << n_1 << "x" << rhs.n_2 << endl;
00254 }
00255 #endif
00256 result.allocate(n_1,rhs.n_2);
00257 }
00258 }
00259
00260 #ifdef USEBLAS
00261
00262 void gemm(const Array2D<double> & rhs, Array2D<double> & result,
00263 const bool rhsIsTransposed) const
00264 {
00265 setupMatrixMultiply(rhs,result,rhsIsTransposed);
00266
00267
00268 double alpha = 1.0;
00269 double beta = 0.0;
00270
00271 #ifdef USE_CBLAS
00272 int M = result.n_1;
00273 int N = result.n_2;
00274 int K = n_2;
00275 int lda = n_2;
00276 int ldb = rhs.n_2;
00277 int ldc = result.n_2;
00278
00279 CBLAS_TRANSPOSE myTrans = rhsIsTransposed ? CblasTrans : CblasNoTrans;
00280 cblas_dgemm(CBLAS_ORDER(CblasRowMajor),
00281 CBLAS_TRANSPOSE(CblasNoTrans), myTrans,
00282 M, N, K,
00283 alpha, pArray, lda,
00284 rhs.pArray, ldb,
00285 beta, result.pArray, ldc);
00286 #else
00287
00288
00289
00290
00291
00292 int M = result.n_2;
00293 int N = result.n_1;
00294 int K = n_2;
00295 int lda = rhs.n_2;
00296 int ldb = n_2;
00297 int ldc = result.n_2;
00298
00299 char transa = rhsIsTransposed ? 'T' : 'N';
00300 char transb = 'N';
00301
00302 FORTRAN_FUNC(dgemm)(&transa, &transb,
00303 &M, &N, &K,
00304 &alpha,
00305 rhs.pArray, &lda,
00306 pArray, &ldb,
00307 &beta,
00308 result.pArray, &ldc);
00309 #endif
00310 }
00311
00312 void gemm(const Array2D<float> & rhs, Array2D<float> & result,
00313 const bool rhsIsTransposed) const
00314 {
00315 setupMatrixMultiply(rhs,result,rhsIsTransposed);
00316
00317
00318 float alpha = 1.0;
00319 float beta = 0.0;
00320
00321 #ifdef USE_CBLAS
00322 int M = result.n_1;
00323 int N = result.n_2;
00324 int K = n_2;
00325 int lda = n_2;
00326 int ldb = rhs.n_2;
00327 int ldc = result.n_2;
00328
00329 CBLAS_TRANSPOSE myTrans = rhsIsTransposed ? CblasTrans : CblasNoTrans;
00330 cblas_sgemm(CBLAS_ORDER(CblasRowMajor),
00331 CBLAS_TRANSPOSE(CblasNoTrans), myTrans,
00332 M, N, K,
00333 alpha, pArray, lda,
00334 rhs.pArray, ldb,
00335 beta, result.pArray, ldc);
00336 #else
00337
00338
00339
00340
00341
00342 int M = result.n_2;
00343 int N = result.n_1;
00344 int K = n_2;
00345 int lda = rhs.n_2;
00346 int ldb = n_2;
00347 int ldc = result.n_2;
00348
00349 char transa = rhsIsTransposed ? 'T' : 'N';
00350 char transb = 'N';
00351
00352 FORTRAN_FUNC(sgemm)(&transa, &transb,
00353 &M, &N, &K,
00354 &alpha,
00355 rhs.pArray, &lda,
00356 pArray, &ldb,
00357 &beta,
00358 result.pArray, &ldc);
00359 #endif
00360 }
00361
00366 double dotAllElectrons(const Array2D<double> & rhs)
00367 {
00368 #ifdef USE_CBLAS
00369 return cblas_ddot(n_1*n_2, pArray, 1, rhs.pArray, 1);
00370 #else
00371 int inc = 1;
00372 int num = n_1 * n_2;
00373 return FORTRAN_FUNC(ddot)(&num, pArray, &inc, rhs.pArray, &inc);
00374 #endif
00375 }
00376
00377 float dotAllElectrons(const Array2D<float> & rhs)
00378 {
00379 #ifdef USE_CBLAS
00380 return cblas_sdot(n_1*n_2, pArray, 1, rhs.pArray, 1);
00381 #else
00382 int inc = 1;
00383 int num = n_1 * n_2;
00384 return FORTRAN_FUNC(sdot)(&num, pArray, &inc, rhs.pArray, &inc);
00385 #endif
00386 }
00387
00392 double dotOneElectron(const Array2D<double> & rhs, int whichElectron)
00393 {
00394 #ifdef USE_CBLAS
00395 return cblas_ddot(n_1, pArray + whichElectron*n_2, 1, rhs.pArray + whichElectron*n_2, 1);
00396 #else
00397 int inc = 1;
00398 return FORTRAN_FUNC(ddot)(&n_1, pArray + whichElectron*n_2, &inc, rhs.pArray + whichElectron*n_2, &inc);
00399 #endif
00400 }
00401
00402 float dotOneElectron(const Array2D<float> & rhs, int whichElectron)
00403 {
00404 #ifdef USE_CBLAS
00405 return cblas_sdot(n_1, pArray + whichElectron*n_2, 1, rhs.pArray + whichElectron*n_2, 1);
00406 #else
00407 int inc = 1;
00408 return FORTRAN_FUNC(sdot)(&n_1, pArray + whichElectron*n_2, &inc, rhs.pArray + whichElectron*n_2, &inc);
00409 #endif
00410 }
00411
00412 void operator+=( const Array2D<double> & rhs)
00413 {
00414 #ifdef USE_CBLAS
00415 cblas_daxpy(n_1*n_2, 1.0, rhs.pArray,1, pArray, 1);
00416 #else
00417 int num = n_1*n_2;
00418 int inc = 1;
00419 double a = 1.0;
00420 FORTRAN_FUNC(daxpy)(&num, &a, rhs.pArray, &inc, pArray, &inc);
00421 #endif
00422 }
00423
00424 #else
00425 void gemm(const Array2D<T> & rhs, Array2D<T> & result,
00426 const bool rhsIsTransposed) const
00427 {
00428 setupMatrixMultiply(rhs,result,rhsIsTransposed);
00429
00430
00431 int M = n_1;
00432 int N = rhsIsTransposed ? rhs.n_1 : rhs.n_2;
00433 int K = n_2;
00434 T * A = pArray;
00435 T * B = rhs.pArray;
00436 T * C = result.pArray;
00437
00438 if(rhsIsTransposed)
00439 {
00440 if(USE_KAHAN)
00441 {
00442 T Cee, Why, Tee;
00443 int i, j, k;
00444
00445 for (i = 0; i < M; ++i)
00446 {
00447 const register T *Ai_ = A + i*K;
00448 for (j = 0; j < N; ++j)
00449 {
00450 const register T *B_j = B + j*K;
00451 register T cij = Ai_[0] * B_j[0];
00452 Cee = 0;
00453 for (k = 1; k < K; ++k)
00454 {
00455
00456
00457
00458
00459 Why = Ai_[k] * B_j[k] - Cee;
00460 Tee = cij + Why;
00461 Cee = (Tee - cij) - Why;
00462 cij = Tee;
00463 }
00464 C[i*N + j] = cij;
00465 }
00466 }
00467 }
00468 else
00469 {
00470 int i, j, k;
00471
00472 for (i = 0; i < M; ++i)
00473 {
00474 const register T *Ai_ = A + i*K;
00475 for (j = 0; j < N; ++j)
00476 {
00477 const register T *B_j = B + j*K;
00478 register T cij = 0;
00479 for (k = 0; k < K; ++k)
00480 {
00481 cij += Ai_[k] * B_j[k];
00482 }
00483 C[i*N + j] = cij;
00484 }
00485 }
00486 }
00487 }
00488 else
00489 {
00490 for (int i = 0; i < M; ++i)
00491 {
00492 register T *Ai_ = A + i*K;
00493 for (int j = 0; j < N; ++j)
00494 {
00495 register T cij = 0;
00496 for (int k = 0; k < K; ++k)
00497 {
00498 cij += Ai_[k] * B[k*N+j];
00499 }
00500 C[i*N + j] = cij;
00501 }
00502 }
00503 }
00504 }
00505
00510 T dotAllElectrons(const Array2D<T> & rhs)
00511 {
00512 register T temp = 0;
00513 for(int i=0; i<n_1*n_2; i++)
00514 temp += pArray[i]*rhs.pArray[i];
00515 return temp;
00516 }
00517
00522 T dotOneElectron(const Array2D<T> & rhs, int whichElectron)
00523 {
00524 register T temp = 0;
00525 T * l = pArray + whichElectron*n_2;
00526 T * r = rhs.pArray + whichElectron*n_2;
00527 for(int i=0; i<n_1; i++)
00528 temp += l[i]*r[i];
00529 return temp;
00530 }
00531
00532 void operator+=( const Array2D<T> & rhs)
00533 {
00534 for(int i=0; i<n_1*n_2; i++)
00535 pArray[i] += rhs.pArray[i];
00536 }
00537
00538 #endif
00539
00540 Array2D<T> operator*(const Array2D<T> & rhs) const
00541 {
00542 Array2D<T> TEMP(n_1,rhs.n_2);
00543 TEMP = 0;
00544 gemm(rhs,TEMP,false);
00545 return TEMP;
00546 }
00547
00548 void setToIdentity(int i)
00549 {
00550 for(int j=0; j<min(n_1,n_2); j++)
00551 {
00552 (*this)(i,j) = (T)(0.0);
00553 (*this)(j,i) = (T)(0.0);
00554 }
00555 (*this)(i,i) = (T)(1.0);
00556 }
00557
00558 void setToIdentity()
00559 {
00560 *this = (T)(0.0);
00561 for(int i=0; i<min(n_1,n_2); i++)
00562 (*this)(i,i) = (T)(1.0);
00563 }
00564
00565 bool isIdentity()
00566 {
00567 for(int i=0; i<n_1; i++)
00568 for(int j=0; j<n_2; j++)
00569 {
00570 T val = (*this)(i,j);
00571 if(i == j) val -= 1.0;
00572 if(fabs(val) > REALLYTINY) return false;
00573 }
00574 return true;
00575 }
00576
00580 void transpose()
00581 {
00582 Array2D<T> old = *this;
00583 if(n_1 != n_2)
00584 {
00585 n_1 = old.dim2();
00586 n_2 = old.dim1();
00587 }
00588 for(int i=0; i<n_1; i++)
00589 for(int j=0; j<n_2; j++)
00590 (*this)(i,j) = old(j,i);
00591 old.deallocate();
00592 }
00593
00598 double nonSymmetry()
00599 {
00600 if(n_1 != n_2)
00601 {
00602 cerr << "Array2D::symmetric just handles square matrices right now\n";
00603 return -1.0;
00604 }
00605
00606 if(n_1 < 2)
00607 return 0.0;
00608
00609 double diff = 0;
00610 for(int i=0; i<n_1; i++)
00611 for(int j=0; j<i; j++)
00612 {
00613 double term = 0;
00614 if(fabs((*this)(i,j)) > REALLYTINY)
00615 term = ((*this)(i,j) - (*this)(j,i))/(*this)(i,j);
00616 diff += term * term;
00617 }
00618
00619
00620 diff = 2.0*diff/(n_1 * n_2 - n_1);
00621
00622
00623
00624 return diff;
00625 }
00626
00633 template <class _RHS>
00634 double compare(const Array2D<_RHS> & rhs, double reallyBad, bool print, bool & same)
00635 {
00636 if(n_1 != rhs.dim1() || n_2 != rhs.dim2())
00637 {
00638 cerr << "ERROR: dims don't match for comparison: " << n_1 << "x"
00639 << n_2 << " * " << rhs.dim2() << "x" << rhs.dim1() << endl;
00640 return 0.0;
00641 }
00642
00643 same = true;
00644 int largestI = 0, largestJ = 0;
00645 double badCount = 0;
00646 double curRelErr=0, largestError = 0;
00647 double curAbsErr=0;
00648 double error = 0, error2 = 0, sample_size = 0;
00649 double abs_error = 0;
00650
00651 for(int i=0; i<n_1; i++)
00652 {
00653 for(int j=0; j<n_2; j++)
00654 {
00655 curAbsErr = fabs((double)(get(i,j)-rhs.get(i,j)));
00656 double den = 1.0;
00657 if(fabs(rhs.get(i,j)) > 1e-200)
00658 den = rhs.get(i,j);
00659 curRelErr = fabs( curAbsErr / den );
00660
00661 if(curRelErr > largestError)
00662 {
00663 largestError = curRelErr;
00664 largestI = i; largestJ = j;
00665 }
00666
00667 if(curRelErr > reallyBad)
00668 {
00669 badCount++;
00670 same = false;
00671 if(print)
00672 {
00673 cout << scientific;
00674 int prec = 8;
00675 int width = 15;
00676 cout << "Error at (" << i << "," << j << "): this "
00677 << setprecision(prec) << setw(width) << get(i,j) << " rhs "
00678 << setprecision(prec) << setw(width) << rhs.get(i,j) << " current error " << curRelErr << endl;
00679
00680 }
00681 }
00682
00683 if(curRelErr < reallyBad)
00684 {
00685 abs_error += curAbsErr;
00686 error += curRelErr;
00687 error2 += curRelErr * curRelErr;
00688 sample_size++;
00689 }
00690 }
00691 }
00692
00693 if(print)
00694 {
00695 cout << scientific;
00696 int prec = 8;
00697 int width = 15;
00698 cout << "Largest Error at (" << largestI << "," << largestJ << "): this "
00699 << setprecision(prec) << setw(width) << get(largestI,largestJ) << " rhs "
00700 << setprecision(prec) << setw(width) << rhs.get(largestI,largestJ) << " current error " << largestError << endl;
00701 }
00702
00703 error = error/sample_size;
00704 error2 = error2/sample_size;
00705 double std_dev = sqrt(error2 - error*error);
00706
00707 if(print)
00708 printf("sample_size %5.2e ave_abs_error %6.3e ave_rel_error %6.3e std_dev %6.3e (%4.2e worse_than %5.3e)\n",
00709 (double)sample_size, abs_error, error, std_dev, badCount, reallyBad);
00710
00711
00712
00713 if(fabs(error) > 1e-7) same = false;
00714
00715 return error;
00716 }
00717
00722 bool operator==(const Array2D & rhs)
00723 {
00724 bool same;
00725 compare(rhs,1e-5,false,same);
00726 return same;
00727 }
00728
00729 void operator=(const Array2D & rhs)
00730 {
00731 if(n_1 != rhs.dim1() || n_2 != rhs.dim2())
00732 allocate(rhs.dim1(),rhs.dim2());
00733
00734 memcpy(pArray, rhs.pArray, sizeof(T)*n_1*n_2);
00735 }
00736
00741 template <class _RHS>
00742 void operator=(const Array2D<_RHS> & rhs)
00743 {
00744 if(n_1 != rhs.dim1() || n_2 != rhs.dim2())
00745 allocate(rhs.dim1(),rhs.dim2());
00746
00747 for(int i=0; i<n_1; i++)
00748 for(int j=0; j<n_2; j++)
00749 pArray[map(i,j)] = (T)(rhs.get(i,j));
00750 }
00751
00757 void operator=(const T C)
00758 {
00759 #ifdef QMC_DEBUG
00760 if(n_1 < 1 || n_2 < 1)
00761 {
00762 cerr << "Warning: using Array2D::operator=(const T C)"
00763 << " with dims " << n_1 << " and " << n_2
00764 << "; C = " << C << endl;
00765
00766 }
00767 #endif
00768 if(C == 0)
00769 {
00770 memset(pArray,0,sizeof(T)*n_1*n_2);
00771 return;
00772 }
00773
00774 for(int i=0; i<n_1*n_2; i++)
00775 pArray[i] = C;
00776 }
00777
00778 double addLL()
00779 {
00780 double sum = 0;
00781 for(int i=0; i<n_1; i++)
00782 for(int j=0; j < i; j++)
00783 sum += pArray[n_2*i + j];
00784 return sum;
00785 }
00786
00790 Array2D operator*(const T C)
00791 {
00792 #ifdef QMC_DEBUG
00793 if(n_1 < 1 || n_2 < 1)
00794 {
00795 cerr << "Warning: using Array2D::operator*(const T C)"
00796 << " with dims " << n_1 << " and " << n_2
00797 << "; C = " << C << endl;
00798
00799 }
00800 #endif
00801 Array2D<T> TEMP(n_1,n_2);
00802 for(int i=0; i<n_1*n_2; i++)
00803 TEMP.pArray[i] = C*pArray[i];
00804 return TEMP;
00805 }
00806
00810 Array2D<T> operator-(const Array2D<T> & rhs) const
00811 {
00812 #ifdef QMC_DEBUG
00813 if(n_1 < 1 || n_2 < 1)
00814 {
00815 cerr << "Warning: using Array2D::operator-(const T C)"
00816 << " with dims " << n_1 << " and " << n_2 << endl;
00817
00818 }
00819 #endif
00820 Array2D<T> TEMP(n_1,n_2);
00821 for(int i=0; i<n_1*n_2; i++)
00822 TEMP.pArray[i] = pArray[i] - rhs.pArray[i];
00823 return TEMP;
00824 }
00825
00829 Array2D<T> operator+(const Array2D<T> & rhs) const
00830 {
00831 #ifdef QMC_DEBUG
00832 if(n_1 < 1 || n_2 < 1)
00833 {
00834 cerr << "Warning: using Array2D::operator+(const T C)"
00835 << " with dims " << n_1 << " and " << n_2 << endl;
00836
00837 }
00838 #endif
00839 Array2D<T> TEMP(n_1,n_2);
00840 for(int i=0; i<n_1*n_2; i++)
00841 TEMP.pArray[i] = pArray[i] + rhs.pArray[i];
00842 return TEMP;
00843 }
00844
00848 void operator*=(const T C)
00849 {
00850 #ifdef QMC_DEBUG
00851 if(n_1 < 1 || n_2 < 1)
00852 {
00853 cerr << "Warning: using Array2D::operator*=(const T C)"
00854 << " with dims " << n_1 << " and " << n_2
00855 << "; C = " << C << endl;
00856
00857 }
00858 #endif
00859 for(int i=0; i<n_1*n_2; i++)
00860 pArray[i] *= C;
00861 }
00862
00866 void operator/=(const T C)
00867 {
00868 #ifdef QMC_DEBUG
00869 if(n_1 < 1 || n_2 < 1)
00870 {
00871 cerr << "Warning: using Array2D::operator/=(const T C)"
00872 << " with dims " << n_1 << " and " << n_2
00873 << "; C = " << C << endl;
00874
00875 }
00876 if(C == 0.0)
00877 {
00878 cerr << "Error: divide by zero in Array2D::operator/=" << endl;
00879 }
00880 #endif
00881
00882 T inv = 1.0/C;
00883 operator*=(inv);
00884 }
00885
00889 Array2D()
00890 {
00891 pArray = 0; n_1 = 0; n_2 = 0;
00892 }
00893
00900 Array2D(int i, int j)
00901 {
00902 pArray = 0;
00903 n_1 = 0; n_2 = 0;
00904 allocate(i,j);
00905 }
00906
00916 Array2D(int i, int j, double shift, double range, long & iseed)
00917 {
00918 pArray = 0;
00919 n_1 = 0; n_2 = 0;
00920 allocate(i,j);
00921
00922 if(iseed > 0) srand(iseed);
00923 for(int idx=0; idx<n_1*n_2; idx++)
00924 {
00925
00926 double val = (double)(rand())/RAND_MAX;
00927 val = range * (val + shift);
00928 pArray[idx] = (T)val;
00929 }
00930 }
00931
00937 Array2D( const Array2D<T> & rhs)
00938 {
00939 n_1 = 0;
00940 n_2 = 0;
00941 pArray = 0;
00942 allocate(rhs.dim1(),rhs.dim2());
00943 operator=(rhs);
00944 }
00945
00949 void setRow(int whichRow, Array1D<T> & rhs)
00950 {
00951 #ifdef QMC_DEBUG
00952 if(whichRow >= n_1)
00953 cerr << "Error: invalid row index in Array2D::setRow\n";
00954 if(rhs.dim1() > n_2)
00955 cerr << "Error: rhs length is incorrect in Array2D::setRow\n";
00956 #endif
00957 memcpy(pArray + n_2*whichRow, rhs.array(), sizeof(T)*n_2);
00958 }
00959
00964 void setRows(int to, int from, int numRows, const Array2D<T> & rhs)
00965 {
00966 #ifdef QMC_DEBUG
00967 if(to < 0 || from < 0 || numRows < 0 ||
00968 (to+numRows) > n_1 || (from+numRows) > rhs.dim1() ||
00969 n_2 != rhs.dim2())
00970 {
00971 cerr << "Error: incompatible dimensions in setRows:\n"
00972 << " to = " << to << endl
00973 << " from = " << from << endl
00974 << " numRows = " << numRows << endl
00975 << " n_1 = " << n_1 << endl
00976 << " n_2 = " << n_2 << endl
00977 << " rhs.n_1 = " << rhs.dim1() << endl
00978 << " rhs.n_2 = " << rhs.dim2() << endl;
00979 assert(0);
00980 }
00981 assert(pArray);
00982 assert(rhs.pArray);
00983 if(numRows == 0)
00984 cout << "Warning: 0 rows in Array2D::setRows" << endl;
00985 #endif
00986 memcpy(pArray + n_2*to, rhs.pArray + n_2*from, sizeof(T)*n_2*numRows);
00987 }
00988
00989
00990
00991
00992 void swapRows(int i, int j)
00993 {
00994 Array2D<T> temp = *this;
00995 setRows(i,j,1,temp);
00996 setRows(j,i,1,temp);
00997 }
00998
01002 void setColumn(int to, int from, const Array2D<T> & rhs)
01003 {
01004 for(int i=0; i<n_1; i++)
01005 pArray[map(i,to)] = rhs.pArray[rhs.map(i,from)];
01006 }
01007
01011 ~Array2D()
01012 {
01013 deallocate();
01014 }
01015
01019 inline int map(int i, int j) const
01020 {
01021 #ifdef QMC_DEBUG
01022 if(i >= n_1 || j >= n_2 ||
01023 i < 0 || j < 0)
01024 {
01025 cerr << "Error: bad index in Array2D::map(" << i << "," << j << "); "
01026 << " allocated (" << n_1 << "," << n_2 << ")" << endl;
01027 assert(0);
01028 }
01029 if(pArray == 0)
01030 {
01031 cerr << "Error: pArray == 0 in Array2D::map" << endl;
01032 assert(0);
01033 }
01034 #endif
01035 return n_2*i + j;
01036 }
01037
01038
01039
01040
01041 T* operator[](int row)
01042 {
01043 #ifdef QMC_DEBUG
01044 if(row >= n_1 || row < 0)
01045 {
01046 cerr << "Error: bad dimension in Array2D::operator[]" << endl
01047 << " row = " << row << endl
01048 << " n_1 = " << n_1 << endl;
01049 assert(0);
01050 }
01051 #endif
01052 return & pArray[n_2 * row];
01053 }
01054
01058 T& operator()(int i,int j)
01059 {
01060 #ifdef QMC_DEBUG
01061 if(i >= n_1 || j >= n_2 ||
01062 i < 0 || j < 0)
01063 {
01064 cerr << "Error: bad index in Array2D::operator()(" << i << "," << j << "); "
01065 << " allocated (" << n_1 << "," << n_2 << ")" << endl;
01066 assert(0);
01067 }
01068 if(pArray == 0)
01069 {
01070 cerr << "Error: pArray == 0 in Array2D::operator()" << endl;
01071 assert(0);
01072 }
01073 #endif
01074 return pArray[map(i,j)];
01075 }
01076
01081 T get(int i, int j) const
01082 {
01083 #ifdef QMC_DEBUG
01084 if(i >= n_1 || j >= n_2 ||
01085 i < 0 || j < 0)
01086 {
01087 cerr << "Error: bad index in Array2D::get(" << i << "," << j << "); "
01088 << " allocated (" << n_1 << "," << n_2 << ")" << endl;
01089 assert(0);
01090 }
01091 if(pArray == 0)
01092 {
01093 cerr << "Error: pArray == 0 in Array2D::get(int,int)" << endl;
01094 assert(0);
01095 }
01096 #endif
01097 return pArray[map(i,j)];
01098 }
01099
01100 double frobeniusNorm()
01101 {
01102 double sum = 0;
01103 for(int i=0; i<n_1*n_2; i++)
01104 sum += pArray[i]*pArray[i];
01105 return sqrt(sum);
01106 }
01107
01108 double pInfNorm()
01109 {
01110 double norm = 0;
01111 double sum = 0;
01112 for(int i=0; i<n_1; i++)
01113 {
01114 for(int j=0; j<n_2; j++)
01115 {
01116 sum += fabs( get(i,j) );
01117 }
01118 norm = max(sum,norm);
01119 sum = 0;
01120 }
01121 return norm;
01122 }
01123
01124 double p1Norm()
01125 {
01126 double norm = 0;
01127 double sum = 0;
01128 for(int j=0; j<n_2; j++)
01129 {
01130 for(int i=0; i<n_1; i++)
01131 {
01132 sum += fabs( get(i,j) );
01133 }
01134 norm = max(sum,norm);
01135 sum = 0;
01136 }
01137 return norm;
01138 }
01139
01147 friend ostream& operator<<(ostream & strm, const Array2D<T> & rhs)
01148 {
01149 if(rhs.n_2 < 8)
01150 rhs.printArray2D(strm, 15, 10, -1, ',', true);
01151 else if(rhs.n_2 < 11)
01152 rhs.printArray2D(strm, 8, 10, -1, ',', true);
01153 else
01154 rhs.printArray2D(strm, 2, 7, -1, ',', false);
01155
01156 return strm;
01157 }
01158
01164 void printArray2D(ostream & strm, int numSigFig, int columnSpace, int maxJ, char sep, bool sci) const
01165 {
01166 strm.precision(4);
01167 if(maxJ < 0) maxJ = n_2;
01168 strm << "{";
01169 for(int i=0; i<n_1;i++)
01170 {
01171 if(i==0) strm << "{";
01172 else strm << " {";
01173 for(int j=0; j<n_2 && j<maxJ; j++)
01174 {
01175 if(sci) strm.setf(ios::scientific);
01176 else strm.unsetf(ios::scientific);
01177
01178 strm << setprecision(numSigFig)
01179 << setw(numSigFig+columnSpace);
01180 strm << pArray[map(i,j)];
01181
01182 if(j<n_2-1) strm << sep;
01183 }
01184 if(i<n_1-1) strm << "},";
01185 else strm << "}}";
01186
01187
01188
01189 strm << endl;
01190 }
01191 }
01192
01204 void ludcmp(double *d, bool *calcOK)
01205 {
01206 int i,j,k;
01207 int imax = -1;
01208 long double big,dum,temp;
01209 long double Why, Cee, Tee;
01210 register long double sum;
01211 long double one = (T)(1.0);
01212 long double zero = (T)(0.0);
01213
01214 *calcOK = true;
01215 *d=1.0;
01216
01217 diVV.allocate(n_1);
01218
01219
01220
01221 for (i=0;i<n_1;i++)
01222 {
01223 big=zero;
01224 for (j=0;j<n_1;j++)
01225 if ((temp=(T)(fabs((double)get(i,j)))) > big)
01226 big=temp;
01227
01228
01229 if (big == zero)
01230 {
01231
01232 *calcOK = false;
01233 return;
01234 }
01235
01236 diVV(i)= (T)(one/big);
01237 }
01238
01239
01240 for (j=0;j<n_1;j++)
01241 {
01242
01243
01244 for (i=0;i<j;i++)
01245 {
01246 sum=-1.0*get(i,j);
01247
01248 if(USE_KAHAN)
01249 {
01250 Cee = 0;
01251 for (k=0;k<i;k++)
01252 {
01253 Why = get(i,k)*get(k,j) - Cee;
01254 Tee = sum + Why;
01255 Cee = (Tee - sum) - Why;
01256 sum = Tee;
01257 }
01258 }
01259 else
01260 {
01261
01262 for (k=0;k<i;k++)
01263 sum += get(i,k)*get(k,j);
01264
01265 }
01266
01267 pArray[map(i,j)] = (T)(-1.0*sum);
01268 }
01269
01270
01271 big=zero;
01272 for (i=j;i<n_1;i++)
01273 {
01274 sum=-1.0*get(i,j);
01275
01276 if(USE_KAHAN)
01277 {
01278 Cee = 0;
01279 for (k=0;k<j;k++)
01280 {
01281 Why = get(i,k)*get(k,j) - Cee;
01282 Tee = sum + Why;
01283 Cee = (Tee - sum) - Why;
01284 sum = Tee;
01285 }
01286 }
01287 else
01288 {
01289
01290 for (k=0;k<j;k++)
01291 sum += get(i,k)*get(k,j);
01292
01293 }
01294
01295 pArray[map(i,j)] = (T)(-1.0*sum);
01296
01297
01298 if ( (dum=diVV(i)*(T)(fabs((double)sum))) >= big)
01299 {
01300 big=dum;
01301 imax=i;
01302 }
01303 }
01304
01305
01306
01307 if (j != imax)
01308 {
01309
01310
01311 for (k=0;k<n_1;k++)
01312 {
01313 dum=get(imax,k);
01314 pArray[map(imax,k)]=get(j,k);
01315 pArray[map(j,k)] = (T)(dum);
01316 }
01317
01318
01319
01320 *d = -(*d);
01321
01322
01323 diVV(imax)=diVV(j);
01324 }
01325 diINDX(j)=imax;
01326
01327
01328 if (get(j,j) == zero)
01329 pArray[map(j,j)]=(T)(REALLYTINY);
01330
01331
01332 if (j != n_1)
01333 {
01334 dum=one/(get(j,j));
01335 for (i=j+1;i<n_1;i++)
01336 pArray[map(i,j)] *= (T)(dum);
01337 }
01338
01339 }
01340 }
01341
01352 void lubksb(Array1D<T> &b)
01353 {
01354 int ii=-1, ip;
01355 long double sum;
01356 long double Cee, Why, Tee;
01357
01358 for (int i=0;i<n_1;i++)
01359 {
01360 ip=diINDX(i);
01361 sum= -1.0*b(ip);
01362 b(ip)=b(i);
01363
01364 if (ii>=0)
01365 {
01366
01367
01368 if(USE_KAHAN)
01369 {
01370 Cee = 0;
01371 for (int j=ii;j<=i-1;j++)
01372 {
01373 Why = get(i,j)*b(j) - Cee;
01374 Tee = sum + Why;
01375 Cee = (Tee - sum) - Why;
01376 sum = Tee;
01377 }
01378 }
01379 else
01380 {
01381
01382 for (int j=ii;j<=i-1;j++)
01383 sum += get(i,j)*b(j);
01384 }
01385
01386 }
01387 else if (sum)
01388 {
01389
01390 ii=i;
01391 }
01392
01393 b(i) = (T)(-1.0*sum);
01394 }
01395
01396 for (int i=n_1-1;i>=0;i--)
01397 {
01398 sum=-1.0*b(i);
01399
01400
01401 if(USE_KAHAN)
01402 {
01403 Cee = 0;
01404 for (int j=i+1;j<n_1;j++)
01405 {
01406 Why = get(i,j)*b(j) - Cee;
01407 Tee = sum + Why;
01408 Cee = (Tee - sum) - Why;
01409 sum = Tee;
01410 }
01411 }
01412 else
01413 {
01414
01415 for (int j=i+1;j<n_1;j++)
01416 sum += get(i,j)*b(j);
01417 }
01418
01419 b(i) = (T)(-1.0*sum/get(i,i));
01420 }
01421 }
01422
01428 void mprove(const Array2D<T> & A, Array2D<T> & inv)
01429 {
01430 int i,j;
01431 Array1D<T> r = Array1D<T>(n_1);
01432
01433 for(int k=0; k<n_1; k++)
01434 {
01435
01436 for(int i=0; i<n_2; i++)
01437 {
01438 long double sdp = i == k ? -1.0 : 0.0;
01439 for(int j=0; j<n_2; j++)
01440 sdp += (long double) A.get(i,j) * (long double) inv(k,j);
01441 r(i) = sdp;
01442 }
01443
01444 lubksb(r);
01445 for(int i=0; i<n_1; i++) inv(k,i) -= r(i);
01446 }
01447 }
01448
01459 #if defined USELAPACK || defined USECLPK
01460 void determinant_and_inverse(Array2D<double> &inv, double& det, bool *calcOK)
01461 {
01462 diINDX.allocate(n_1);
01463
01464 inv.setToIdentity();
01465
01466 int info = 0;
01467 int N = n_1;
01468 int NRHS = n_1;
01469 int LDA = n_1;
01470 int LDB = n_1;
01471
01472
01473 FORTRAN_FUNC(dgesv)(&N, &NRHS, pArray, &LDA, diINDX.array(), inv.array(), &LDB, &info);
01474
01475 if(info == 0) *calcOK = true;
01476 else *calcOK = false;
01477
01478 det = 1.0;
01479 for(int i=0; i<n_1; i++)
01480 {
01481 if(diINDX(i) != i+1)
01482 det *= -1;
01483 det *= get(i,i);
01484 }
01485 }
01486
01487 void determinant_and_inverse(Array2D<float> &inv, double& det, bool *calcOK)
01488 {
01489 diINDX.allocate(n_1);
01490
01491 inv.setToIdentity();
01492
01493 int info = 0;
01494 int N = n_1;
01495 int NRHS = n_1;
01496 int LDA = n_1;
01497 int LDB = n_1;
01498
01499
01500 FORTRAN_FUNC(sgesv)(&N, &NRHS, pArray, &LDA, diINDX.array(), inv.array(), &LDB, &info);
01501
01502 if(info == 0) *calcOK = true;
01503 else *calcOK = false;
01504
01505 det = 1.0;
01506 for(int i=0; i<n_1; i++)
01507 {
01508 if(diINDX(i) != i+1)
01509 det *= -1;
01510 det *= get(i,i);
01511 }
01512 }
01513 #else
01514
01521 void determinant_and_inverse(Array2D<T> &inv, double& det, bool *calcOK)
01522 {
01523 double d;
01524 T one = (T)1.0;
01525 T zero = (T)0.0;
01526
01527 diINDX.allocate(n_1);
01528 diCol.allocate(n_1);
01529 inv.allocate(n_1,n_1);
01530
01531 ludcmp(&d,calcOK);
01532
01533 if( *calcOK )
01534 {
01535 for(int j=0; j<n_1; j++)
01536 {
01537 diCol = zero;
01538 diCol(j) = one;
01539 lubksb(diCol);
01540 for(int i=0; i<n_1; i++)
01541 inv(i,j) = diCol(i);
01542 }
01543 }
01544
01545 for(int i=0; i<n_1; i++)
01546 d *= get(i,i);
01547 det = d;
01548 }
01549 #endif
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566 template <class _RHS>
01567 double inverseUpdateOneRow(int row, Array2D<_RHS> & newD, int rowInD)
01568 {
01569 int d = n_1;
01570 #ifdef QMC_DEBUG
01571 if( rowInD >= newD.dim1() || row >= n_1 ||
01572 rowInD < 0 || row < 0 ||
01573 n_2 != newD.dim2())
01574 {
01575 cout << "Error: dimensions don't match in inverse update." << endl;
01576 cout << " n_1 = " << n_1 << endl;
01577 cout << " n_2 = " << n_2 << endl;
01578 cout << " row = " << row << endl;
01579 cout << " D.n_1 = " << newD.dim1() << endl;
01580 cout << " D.n_2 = " << newD.dim2() << endl;
01581 cout << " D row = " << rowInD << endl;
01582 assert(0);
01583 }
01584 #endif
01585 double detRatio = 0;
01586 for(int r=0; r<d; r++)
01587 detRatio += (T)(newD.get(rowInD,r)) * pArray[map(r,row)];
01588 double q = 1.0/detRatio;
01589
01590 for(int c=0; c<d; c++)
01591 {
01592
01593 if(c == row)
01594 continue;
01595
01596 double val = 0.0;
01597 for(int l=0; l<d; l++)
01598 val += (T)(newD.get(rowInD,l)) * pArray[map(l,c)];
01599 val *= q;
01600
01601 for(int r=0; r<d; r++)
01602 pArray[map(r,c)] -= val * pArray[map(r,row)];
01603 }
01604
01605
01606 for(int r=0; r<d; r++)
01607 pArray[map(r,row)] *= q;
01608
01609 return detRatio;
01610 }
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627 template <class _RHS>
01628 double inverseUpdateOneColumn(int column, Array2D<_RHS> & newD, int columnInD)
01629 {
01630 int d = n_2;
01631 #ifdef QMC_DEBUG
01632 if( columnInD >= newD.dim2() || column >= n_2 ||
01633 columnInD < 0 || column < 0 ||
01634 n_1 != newD.dim1())
01635 {
01636 cout << "Error: dimensions don't match in inverse update." << endl;
01637 cout << " n_1 = " << n_1 << endl;
01638 cout << " n_2 = " << n_2 << endl;
01639 cout << " column = " << column << endl;
01640 cout << " D.n_1 = " << newD.dim1() << endl;
01641 cout << " D.n_2 = " << newD.dim2() << endl;
01642 cout << "D column = " << columnInD << endl;
01643 assert(0);
01644 }
01645 #endif
01646 double detRatio = 0;
01647 for(int c=0; c<d; c++)
01648 detRatio += (T)(newD.get(c,columnInD)) * pArray[map(column,c)];
01649 double q = 1.0/detRatio;
01650
01651 for(int r=0; r<d; r++)
01652 {
01653
01654 if(r == column)
01655 continue;
01656
01657 double val = 0.0;
01658 for(int l=0; l<d; l++)
01659 val += (T)(newD.get(l,columnInD)) * pArray[map(r,l)];
01660 val *= q;
01661
01662 for(int c=0; c<d; c++)
01663 pArray[map(r,c)] -= val * pArray[map(column,c)];
01664 }
01665
01666
01667 for(int c=0; c<d; c++)
01668 pArray[map(column,c)] *= q;
01669
01670 return detRatio;
01671 }
01672
01690 void rref()
01691 {
01692 double max_data, temp;
01693 int max_index, i, j, k, l;
01694 int order = min(n_1,n_2);
01695 Array1D<int> pivots(order);
01696 double tolerance = 1e-20;
01697 bool allowPivot = true;
01698
01699 l = 0;
01700 for (k = 0; k < order; k++)
01701 {
01702 max_data = pArray[map(l,k)];
01703 max_index = l;
01704
01705 if(allowPivot)
01706 {
01707
01708
01709 for (i = l; i < n_1; i++)
01710 {
01711 if (fabs(pArray[map(i,k)]) > fabs(max_data))
01712 {
01713 max_data = pArray[map(i,k)];
01714 max_index = i;
01715 }
01716 }
01717 }
01718
01719 pivots(k) = max_index;
01720 if (fabs(max_data) > tolerance)
01721 {
01722
01723
01724 for (j = k; j < n_2; j++)
01725 {
01726 temp = pArray[map(max_index,j)] / max_data;
01727 pArray[map(max_index,j)] = pArray[map(l,j)];
01728 pArray[map(l,j)] = temp;
01729 }
01730
01731
01732
01733
01734 for (i = l + 1; i < n_1; i++)
01735 {
01736 double scale = pArray[map(i,l)];
01737 for (j = k; j < n_2; j++)
01738 pArray[map(i,j)] -= pArray[map(l,j)] * scale;
01739 }
01740
01741 l++;
01742 }
01743 }
01744
01745
01746
01747
01748
01749
01750 for (k = 0; k < order-1; k++)
01751 {
01752 if (pArray[map(k+1,k+1)] != 0)
01753 {
01754 for (i = k; i >= 0; i--)
01755 {
01756 double scale = pArray[map(i,k+1)];
01757 for (j = k+1; j < n_2; j++)
01758 pArray[map(i,j)] -= pArray[map(k+1,j)] * scale;
01759 }
01760 }
01761 }
01762 }
01763
01780 void rref(int t)
01781 {
01782 if(isDependent(t) != -1)
01783 {
01784
01785 return;
01786 }
01787
01788
01789
01790
01791
01792 bool printWarnings = true;
01793 if(t < 0 || t >= n_2)
01794 {
01795 if(printWarnings)
01796 {
01797 cerr << "Error: invalid variable elimination. ";
01798 cerr << "Number variables = " << n_2 << " but ";
01799 cerr << "t = " << t << "." << endl;
01800 }
01801 return;
01802 }
01803
01804
01805
01806
01807
01808 static int s = -1;
01809 s++;
01810 if(s >= n_1) s=0;
01811
01812 double tolerance = 1e-10;
01813
01814
01815
01816
01817
01818 double scale = pArray[map(s,t)];
01819 int best = s;
01820 bool willUnsolve = false;
01821 for(int r=n_1-1; r>=0; r--)
01822 {
01823 scale = pArray[map(r,t)];
01824
01825 if(fabs(scale) < tolerance)
01826 continue;
01827 else
01828 best = r;
01829
01830 willUnsolve = constraintUsed(r) == -1 ? false : true;
01831 if(constraintUsed(r) == -1)
01832 {
01833 best = r;
01834 break;
01835 }
01836 }
01837
01838 if(best != s)
01839 swapRows(best,s);
01840 scale = pArray[map(s,t)];
01841
01842
01843
01844
01845
01846 if(fabs(scale) <= tolerance)
01847 {
01848 if(printWarnings)
01849 {
01850 cerr << "Warning: none of the constraints use variable t = " << t
01851 << " so we can't eliminate it!" << endl;
01852 }
01853 return;
01854 }
01855
01856
01857
01858
01859
01860
01861
01862 if(fabs(scale - 1.0) > tolerance)
01863 {
01864 for(int c = 0; c < n_2; c++)
01865 pArray[map(s,c)] = pArray[map(s,c)] / scale;
01866 }
01867
01868
01869
01870
01871 pArray[map(s,t)] = 1.0;
01872
01873
01874
01875
01876
01877
01878 for(int r = 0; r < n_1; r++)
01879 {
01880 scale = pArray[map(r,t)];
01881
01882 if(r == s || fabs(scale) < tolerance) continue;
01883
01884 for(int c = 0; c < n_2; c++)
01885 {
01886
01887
01888
01889
01890 pArray[map(r,c)] -= pArray[map(s,c)] * scale;
01891
01892
01893
01894 if(fabs(pArray[map(r,c)]) < tolerance)
01895 pArray[map(r,c)] = 0.0;
01896 }
01897
01898
01899 pArray[map(r,t)] = 0.0;
01900 }
01901 }
01902
01903
01904
01905
01906
01907
01908
01909
01910 int numDependent()
01911 {
01912 int numDep = 0;
01913 for(int j=0; j<dim2(); j++)
01914 if(isDependent(j) > -1)
01915 numDep++;
01916 return numDep;
01917 }
01918
01919
01920
01921
01922
01923
01924
01925 int isDependent(int column)
01926 {
01927 double tolerance = 1e-50;
01928 int hasOne = -1;
01929 bool zeros = true;
01930 for(int i=0; i<dim1(); i++)
01931 {
01932 if(fabs(pArray[map(i,column)] - 1.0) < tolerance && hasOne < 0)
01933 hasOne = i;
01934 else if(fabs(pArray[map(i,column)]) > tolerance)
01935 zeros = false;
01936 }
01937
01938
01939
01940
01941
01942 if(hasOne > -1 && zeros)
01943 return hasOne;
01944
01945 return -1;
01946 }
01947
01956 int constraintUsed(int r)
01957 {
01958 for(int c=0; c<n_2; c++)
01959 if(fabs(pArray[map(r,c)] - 1.0) < 1e-10)
01960 if(isDependent(c) == r)
01961 return c;
01962 return -1;
01963 }
01964
01976 void generalizedEigenvectors(Array2D<double> A,
01977 Array2D<double> B,
01978 Array1D<Complex> & eigval)
01979 {
01980 #ifdef USELAPACK
01981 allocate(A.n_1,A.n_1);
01982
01983 char vl = 'N';
01984 char vr = 'V';
01985 int n = n_1;
01986 int lda = A.n_1;
01987 int ldb = B.n_1;
01988 int ldvl = 1;
01989 int ldvr = n_1;
01990 int info = 0;
01991
01992 Array1D<double> alphar(n);
01993 Array1D<double> alphai(n);
01994 Array1D<double> beta(n);
01995
01996 Array1D<double> work(8*n);
01997 int lwork = work.dim1();
01998 FORTRAN_FUNC(dggev)(&vl,&vr,&n,
01999 A.array(), &lda, B.array(), &ldb,
02000 alphar.array(), alphai.array(), beta.array(),
02001 (double*)0,&ldvl,
02002 pArray, &ldvr,
02003 work.array(), &lwork,
02004 &info);
02005
02006 if(lwork == -1 && info == 0)
02007 {
02008 cout << "Notice: dggev recommends " << work(0) << " memory." << endl;
02009 }
02010 else if(info == 0)
02011 {
02012 eigval.allocate(n);
02013 for(int i=0; i<n; i++)
02014 {
02015
02016
02017 double real = alphar(i) / beta(i);
02018 double imag = alphai(i) / beta(i);
02019
02020 eigval(i) = Complex(real,imag);
02021 }
02022 }
02023 else
02024 {
02025 cout << "Error: dggev reported info = " << info << endl;
02026 }
02027
02028 alphar.deallocate();
02029 alphai.deallocate();
02030 beta.deallocate();
02031 work.deallocate();
02032
02033 #else
02034 cout << "Error: dggev requires you to compile with LAPACK!!" << endl;
02035 #endif
02036 }
02037
02044 Array1D<double> eigenvaluesRS()
02045 {
02046 Array1D<double> wr;
02047
02048 if(n_1 != n_2)
02049 {
02050 cout << "Error: no eigenvalues for non square matrix!" << endl
02051 << " n_1 = " << n_1 << endl
02052 << " n_2 = " << n_2 << endl
02053 << endl;
02054 return wr;
02055 }
02056
02057 double check = nonSymmetry();
02058 if(check > 1e-5)
02059 {
02060 cout << "Error: eigenvaluesRS only works with symmetric matrices" << endl
02061 << " nonSymmetry = " << check << endl;
02062 return wr;
02063 }
02064
02065 wr.allocate(n_1);
02066 wr = 0.0;
02067
02068 Array1D<double> fv1;
02069 fv1.allocate(n_1);
02070
02071 Array2D<double> A = *this;
02072
02073 int i, ii, ierr = -1, j, k, l, l1, l2;
02074 double c, c2, c3, dl1, el1, f, g, h, p, r, s, s2, scale, tst1, tst2;
02075
02076
02077 ii = n_1 - 1;
02078 for (i = 0; i < ii; i++)
02079 {
02080 wr[i] = A[ii][i];
02081 A[ii][i] = A[i][i];
02082 }
02083 wr[ii] = A[ii][ii];
02084
02085 for (i = (n_1 - 1); i >= 0; i--)
02086 {
02087
02088 l = i - 1;
02089 scale = h = 0.0;
02090
02091 if (l < 0)
02092 {
02093 fv1[i] = 0.0;
02094 continue;
02095 }
02096
02097 for (j = 0; j <= l; j++)
02098 scale += fabs(wr[j]);
02099
02100 if (scale == 0.0)
02101 {
02102 for (j = 0; j <= l; j++)
02103 {
02104 wr[j] = A[l][j];
02105 A[l][j] = A[i][j];
02106 A[i][j] = 0.0;
02107 }
02108
02109 fv1[i] = 0.0;
02110 continue;
02111 }
02112
02113 for (j = 0; j <= l; j++)
02114 {
02115 wr[j] /= scale;
02116 h += wr[j]*wr[j];
02117 }
02118
02119 f = wr[l];
02120 g = ((f >= 0) ? -sqrt(h) : sqrt(h));
02121 fv1[i] = g*scale;
02122 h -= f*g;
02123 wr[l] = f - g;
02124
02125 if (l != 0)
02126 {
02127
02128 for (j = 0; j <= l; j++)
02129 fv1[j] = 0.0;
02130
02131 for (j = 0; j <= l; j++)
02132 {
02133 f = wr[j];
02134 g = fv1[j] + f*A[j][j];
02135 for (ii = (j + 1); ii <= l; ii++)
02136 {
02137 g += wr[ii]*A[ii][j];
02138 fv1[ii] += f*A[ii][j];
02139 }
02140 fv1[j] = g;
02141 }
02142
02143
02144
02145 f = 0.0;
02146 for (j = 0; j <= l; j++)
02147 {
02148 fv1[j] /= h;
02149 f += fv1[j]*wr[j];
02150 }
02151
02152 h = f/(h*2);
02153
02154
02155
02156 for (j = 0; j <= l; j++)
02157 fv1[j] -= h*wr[j];
02158
02159
02160
02161 for (j = 0; j <= l; j++)
02162 {
02163 f = wr[j];
02164 g = fv1[j];
02165
02166 for (ii = j; ii <= l; ii++)
02167 A[ii][j] -= f*fv1[ii] + g*wr[ii];
02168
02169 }
02170
02171 }
02172
02173 for (j = 0; j <= l; j++)
02174 {
02175 f = wr[j];
02176 wr[j] = A[l][j];
02177 A[l][j] = A[i][j];
02178 A[i][j] = f*scale;
02179 }
02180
02181 }
02182
02183
02184
02185
02186
02187 for (i = 1; i < n_1; i++)
02188 fv1[i - 1] = fv1[i];
02189
02190 fv1[n_1 - 1] = tst1 = f = 0.0;
02191
02192 for (l = 0; l < n_1; l++)
02193 {
02194
02195 j = 0;
02196 h = fabs(wr[l]) + fabs(fv1[l]);
02197
02198 tst1 = ((tst1 < h) ? h : tst1);
02199
02200
02201
02202 for (k = l; k < n_1; k++)
02203 {
02204 tst2 = tst1 + fabs(fv1[k]);
02205 if (tst2 == tst1) break;
02206 }
02207
02208 if (k != l)
02209 {
02210
02211 do
02212 {
02213
02214 if (j == 30)
02215 {
02216 ierr = l;
02217 break;
02218 }
02219
02220 j++;
02221
02222
02223
02224 l1 = l + 1;
02225 l2 = l1 + 1;
02226 g = wr[l];
02227 p = (wr[l1] - g)/(2.0*fv1[l]);
02228 r = pythag(p, 1.0);
02229 scale = ((p >= 0) ? r : -r);
02230 scale += p;
02231 wr[l] = fv1[l]/scale;
02232 dl1 = wr[l1] = fv1[l]*scale;
02233 h = g - wr[l];
02234
02235 for (i = l2; i < n_1; i++)
02236 wr[i] -= h;
02237
02238 f += h;
02239
02240
02241
02242 p = wr[k];
02243 c2 = c = 1.0;
02244 el1 = fv1[l1];
02245 s = 0.0;
02246 c3 = 99.9;
02247 s2 = 99.9;
02248
02249
02250 for (i = (k - 1); i >= l; i--)
02251 {
02252 c3 = c2;
02253 c2 = c;
02254 s2 = s;
02255 g = c*fv1[i];
02256 h = c*p;
02257 r = pythag(p, fv1[i]);
02258 fv1[i + 1] = s*r;
02259 s = fv1[i]/r;
02260 c = p/r;
02261 p = c*wr[i] - s*g;
02262 wr[i + 1] = h + s*(c*g + s*wr[i]);
02263 }
02264
02265 p = -s*s2*c3*el1*fv1[l]/dl1;
02266 fv1[l] = s*p;
02267 wr[l] = c*p;
02268 tst2 = tst1 + fabs(fv1[l]);
02269 }
02270 while (tst2 > tst1);
02271
02272 }
02273
02274 if (ierr >= 0)
02275 break;
02276
02277 p = wr[l] + f;
02278
02279
02280
02281
02282 for (i = l; i >= 1; i--)
02283 {
02284 if (p >= wr[i - 1])
02285 break;
02286 wr[i] = wr[i - 1];
02287 }
02288
02289 wr[i] = p;
02290
02291 }
02292
02293
02294
02295 A.deallocate();
02296 fv1.deallocate();
02297 return wr;
02298 }
02299 };
02300
02301 #endif