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
00033
00034
00035
00036 #include "Matrix.h"
00037 #include "Vector.h"
00038 #include "ID.h"
00039
00040 #include <stdlib.h>
00041
00042 #define MATRIX_WORK_AREA 400
00043 #define INT_WORK_AREA 20
00044
00045 double Matrix::MATRIX_NOT_VALID_ENTRY =0.0;
00046 double *Matrix::matrixWork = new double [MATRIX_WORK_AREA];
00047 int *Matrix::intWork = new int [INT_WORK_AREA];
00048
00049
00050
00051
00052
00053
00054 Matrix::Matrix()
00055 :numRows(0), numCols(0),dataSize(0),data(0),fromFree(0)
00056 {
00057
00058 }
00059
00060
00061 Matrix::Matrix(int nRows,int nCols)
00062 :numRows(nRows),numCols(nCols),fromFree(0)
00063 {
00064 #ifdef _G3DEBUG
00065 if (nRows < 0) {
00066 cerr << "WARNING: Matrix::Matrix(int,int): tried to init matrix ";
00067 cerr << "with num rows: " << nRows << " <0\n";
00068 numRows = 0; numCols =0; dataSize =0; data = 0;
00069 }
00070 if (nCols < 0) {
00071 cerr << "WARNING: Matrix::Matrix(int,int): tried to init matrix";
00072 cerr << "with num cols: " << nCols << " <0\n";
00073 numRows = 0; numCols =0; dataSize =0; data = 0;
00074 }
00075 #endif
00076 dataSize = numRows * numCols;
00077 data = 0;
00078
00079 if (dataSize > 0) {
00080 data = new double[dataSize];
00081
00082 if (data == 0) {
00083 cerr << "WARNING:Matrix::Matrix(int,int): Ran out of memory on init ";
00084 cerr << "of size " << dataSize << "\n";
00085 numRows = 0; numCols =0; dataSize =0;
00086 } else {
00087
00088 double *dataPtr = data;
00089 for (int i=0; i<dataSize; i++)
00090 *dataPtr++ = 0.0;
00091 }
00092 }
00093 }
00094
00095 Matrix::Matrix(double *theData, int row, int col)
00096 :numRows(row),numCols(col),dataSize(row*col),data(theData),fromFree(1)
00097 {
00098 #ifdef _G3DEBUG
00099 if (row < 0) {
00100 cerr << "WARNING: Matrix::Matrix(int,int): tried to init matrix with numRows: ";
00101 cerr << row << " <0\n";
00102 numRows = 0; numCols =0; dataSize =0; data = 0;
00103 }
00104 if (col < 0) {
00105 cerr << "WARNING: Matrix::Matrix(int,int): tried to init matrix with numCols: ";
00106 cerr << col << " <0\n";
00107 numRows = 0; numCols =0; dataSize =0; data = 0;
00108 }
00109 #endif
00110
00111
00112 }
00113
00114 Matrix::Matrix(const Matrix &other)
00115 :fromFree(0)
00116 {
00117 numRows = other.numRows;
00118 numCols = other.numCols;
00119 dataSize = other.dataSize;
00120 data = 0;
00121
00122 if (dataSize != 0) {
00123 data = new double[dataSize];
00124
00125 if (data == 0) {
00126 cerr << "WARNING:Matrix::Matrix(Matrix &): ";
00127 cerr << "Ran out of memory on init of size " << dataSize << "\n";
00128 numRows = 0; numCols =0; dataSize = 0;
00129 } else {
00130
00131 double *dataPtr = data;
00132 double *otherDataPtr = other.data;
00133 for (int i=0; i<dataSize; i++)
00134 *dataPtr++ = *otherDataPtr++;
00135 }
00136 }
00137 }
00138
00139
00140
00141
00142
00143
00144 Matrix::~Matrix()
00145 {
00146 if (data != 0)
00147 if (fromFree == 0)
00148 delete [] data;
00149
00150 }
00151
00152
00153
00154
00155
00156
00157 void
00158 Matrix::Zero(void)
00159 {
00160 double *dataPtr = data;
00161 for (int i=0; i<dataSize; i++)
00162 *dataPtr++ = 0;
00163 }
00164
00165
00166 int
00167 Matrix::resize(int rows, int cols) {
00168
00169 int newSize = rows*cols;
00170
00171 if (newSize <= 0) {
00172 g3ErrorHandler->warning("Matrix::resize) - rows %d or cols %d specified <= 0\n",
00173 rows, cols);
00174 return -1;
00175 }
00176
00177 else if (newSize > dataSize) {
00178
00179
00180 if (data != 0)
00181 if (fromFree == 0)
00182 delete [] data;
00183
00184
00185 fromFree = 0;
00186
00187 data = new double[newSize];
00188
00189 if (data == 0) {
00190 g3ErrorHandler->warning("Matrix::resize(%d %d) - out of memory\n",
00191 rows, cols);
00192 numRows = 0; numCols =0; dataSize = 0;
00193 return -2;
00194 }
00195 dataSize = newSize;
00196 numRows = rows;
00197 numCols = cols;
00198 }
00199
00200
00201
00202 else {
00203 numRows = rows;
00204 numCols = cols;
00205 }
00206
00207 return 0;
00208 }
00209
00210
00211
00212
00213
00214 int
00215 Matrix::Assemble(const Matrix &V, const ID &rows, const ID &cols, double fact)
00216 {
00217 int pos_Rows, pos_Cols;
00218 int res = 0;
00219
00220 for (int i=0; i<cols.Size(); i++) {
00221 pos_Cols = cols(i);
00222 for (int j=0; j<rows.Size(); j++) {
00223 pos_Rows = rows(j);
00224
00225 if ((pos_Cols >= 0) && (pos_Rows >= 0) && (pos_Rows < numRows) &&
00226 (pos_Cols < numCols) && (i < V.numCols) && (j < V.numRows))
00227 (*this)(pos_Rows,pos_Cols) += V(j,i)*fact;
00228 else {
00229 cerr << "WARNING: Matrix::Assemble(const Matrix &V, const ID &l): ";
00230 cerr << " - position (" << pos_Rows << "," << pos_Cols << ") outside bounds \n";
00231 res = -1;
00232 }
00233 }
00234 }
00235
00236 return res;
00237 }
00238
00239 #ifdef _WIN32
00240 extern "C" int _stdcall DGESV(int *N, int *NRHS, double *A, int *LDA,
00241 int *iPiv, double *B, int *LDB, int *INFO);
00242
00243 extern "C" int _stdcall DGETRS(char *TRANS, unsigned int sizeT,
00244 int *N, int *NRHS, double *A, int *LDA,
00245 int *iPiv, double *B, int *LDB, int *INFO);
00246 #else
00247 extern "C" int dgesv_(int *N, int *NRHS, double *A, int *LDA, int *iPiv,
00248 double *B, int *LDB, int *INFO);
00249
00250 extern "C" int dgetrs_(char *TRANS, int *N, int *NRHS, double *A, int *LDA,
00251 int *iPiv, double *B, int *LDB, int *INFO);
00252 #endif
00253
00254 int
00255 Matrix::Solve(const Vector &b, Vector &x) const
00256 {
00257
00258 int n = numRows;
00259
00260 #ifdef _G3DEBUG
00261 if (numRows != numCols) {
00262 g3ErrorHandler->warning("Matrix::Solve(b,x) - %s [%d %d] is not square\n",
00263 "the matrix of dimensions",
00264 numRows, numCols);
00265 return -1;
00266 }
00267
00268 if (n != x.Size()) {
00269 g3ErrorHandler->warning("Matrix::Solve(b,x) - dimension of x, %d, %s %d\n",
00270 numRows, "is not same as matrix", x.Size());
00271 return -2;
00272 }
00273
00274 if (n != b.Size()) {
00275 g3ErrorHandler->warning("Matrix::Solve(b,x) - dimension of b, %d, %s %d\n",
00276 numRows, "is not same as matrix", b.Size());
00277 return -2;
00278 }
00279 #endif
00280
00281
00282 if (dataSize > MATRIX_WORK_AREA) {
00283 g3ErrorHandler->warning("Matrix::Solve(b,x) - matrix dimension [%d %d] %s %d\n",
00284 numRows, numCols, "larger than work area",
00285 MATRIX_WORK_AREA);
00286 return -3;
00287 }
00288
00289
00290 int i;
00291 for (i=0; i<dataSize; i++)
00292 matrixWork[i] = data[i];
00293
00294
00295 x = b;
00296
00297 int nrhs = 1;
00298 int ldA = n;
00299 int ldB = n;
00300 int info;
00301 double *Aptr = matrixWork;
00302 double *Xptr = x.theData;
00303 int *iPIV = intWork;
00304
00305
00306 #ifdef _WIN32
00307 DGESV(&n,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info);
00308 #else
00309 dgesv_(&n,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info);
00310 #endif
00311
00312
00313 return 0;
00314 }
00315
00316
00317 int
00318 Matrix::Solve(const Matrix &b, Matrix &x) const
00319 {
00320
00321 int n = numRows;
00322 int nrhs = x.numCols;
00323
00324 #ifdef _G3DEBUG
00325 if (numRows != numCols) {
00326 g3ErrorHandler->warning("Matrix::Solve(B,X) - the matrix of dimensions [%d %d] is not square\n",
00327 numRows, numCols);
00328 return -1;
00329 }
00330
00331 if (n != x.numRows) {
00332 g3ErrorHandler->warning("Matrix::Solve(B,X) - #rows of X, %d, is not same as matrix %d\n",
00333 numRows, x.numRows);
00334 return -2;
00335 }
00336
00337 if (n != b.numRows) {
00338 g3ErrorHandler->warning("Matrix::Solve(B,X) - #rows of B, %d, is not same as matrix %d\n",
00339 numRows, b.numRows);
00340 return -2;
00341 }
00342
00343 if (x.numCols != b.numCols) {
00344 g3ErrorHandler->warning("Matrix::Solve(B,X) - #cols of B, %d, is not same as that of X, %d\n",
00345 b.numCols, x.numCols);
00346 return -3;
00347 }
00348 #endif
00349
00350
00351 if (dataSize > MATRIX_WORK_AREA || n > INT_WORK_AREA) {
00352 g3ErrorHandler->warning("Matrix::Solve(b,x) - matrix dimension [%d %d] larger than work area %d\n",
00353 numRows, numCols, MATRIX_WORK_AREA);
00354 return -3;
00355 }
00356
00357 x = b;
00358
00359
00360 int i;
00361 for (i=0; i<dataSize; i++)
00362 matrixWork[i] = data[i];
00363
00364
00365 int ldA = n;
00366 int ldB = n;
00367 int info;
00368 double *Aptr = matrixWork;
00369 double *Xptr = x.data;
00370
00371 int *iPIV = intWork;
00372
00373
00374 #ifdef _WIN32
00375 DGESV(&n,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info);
00376 #else
00377 dgesv_(&n,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info);
00378 #endif
00379
00380 return info;
00381 }
00382
00383
00384
00385 int
00386 Matrix::addMatrix(double factThis, const Matrix &other, double factOther)
00387 {
00388 if (factThis == 1.0 && factOther == 0.0)
00389 return 0;
00390
00391 #ifdef _G3DEBUG
00392 if ((other.numRows != numRows) || (other.numCols != numCols)) {
00393 g3ErrorHandler->warning("Matrix::addMatrix(): incompatable matrices, this[%d %d] other[%d %d]\n",
00394 numRows, numCols, other.numRows, other.numCols);
00395 return -1;
00396 }
00397 #endif
00398
00399 if (factThis == 1.0) {
00400
00401
00402 if (factOther == 1.0) {
00403 double *dataPtr = data;
00404 double *otherDataPtr = other.data;
00405 for (int i=0; i<dataSize; i++)
00406 *dataPtr++ += *otherDataPtr++;
00407 } else {
00408 double *dataPtr = data;
00409 double *otherDataPtr = other.data;
00410 for (int i=0; i<dataSize; i++)
00411 *dataPtr++ += *otherDataPtr++ * factOther;
00412 }
00413 }
00414
00415 else if (factThis == 0.0) {
00416
00417
00418 if (factOther == 1.0) {
00419 double *dataPtr = data;
00420 double *otherDataPtr = other.data;
00421 for (int i=0; i<dataSize; i++)
00422 *dataPtr++ = *otherDataPtr++;
00423 } else {
00424 double *dataPtr = data;
00425 double *otherDataPtr = other.data;
00426 for (int i=0; i<dataSize; i++)
00427 *dataPtr++ = *otherDataPtr++ * factOther;
00428 }
00429 }
00430
00431 else {
00432
00433
00434 if (factOther == 1.0) {
00435 double *dataPtr = data;
00436 double *otherDataPtr = other.data;
00437 for (int i=0; i<dataSize; i++) {
00438 double value = *dataPtr * factThis + *otherDataPtr++;
00439 *dataPtr++ = value;
00440 }
00441 } else {
00442 double *dataPtr = data;
00443 double *otherDataPtr = other.data;
00444 for (int i=0; i<dataSize; i++) {
00445 double value = *dataPtr * factThis + *otherDataPtr++ * factOther;
00446 *dataPtr++ = value;
00447 }
00448 }
00449 }
00450
00451
00452 return 0;
00453 }
00454
00455
00456
00457 int
00458 Matrix::addMatrixProduct(double thisFact,
00459 const Matrix &B,
00460 const Matrix &C,
00461 double otherFact)
00462 {
00463 if (thisFact == 1.0 && otherFact == 0.0)
00464 return 0;
00465 #ifdef _G3DEBUG
00466 if ((B.numRows != numRows) || (C.numCols != numCols) || (B.numCols != C.numRows)) {
00467 g3ErrorHandler->warning("Matrix::addMatrixProduct():%s[%d %d] A[%d &d] B{%d %d]\n",
00468 "incompatable matrices, this",
00469 numRows, numCols, B.numRows, B.numCols, C.numRows, C.numCols);
00470 return -1;
00471 }
00472 #endif
00473
00474 if (thisFact == 1.0) {
00475
00476 if (otherFact == 1.0) {
00477
00478 int numColB = B.numCols;
00479 double *ckjPtr = &(C.data)[0];
00480 for (int j=0; j<numCols; j++) {
00481 double *aijPtrA = &data[j*numRows];
00482 for (int k=0; k<numColB; k++) {
00483 double tmp = *ckjPtr++;
00484 double *aijPtr = aijPtrA;
00485 double *bikPtr = &(B.data)[k*numRows];
00486 for (int i=0; i<numRows; i++)
00487 *aijPtr++ += *bikPtr++ * tmp;
00488 }
00489 }
00490 } else {
00491
00492 int numColB = B.numCols;
00493 double *ckjPtr = &(C.data)[0];
00494 for (int j=0; j<numCols; j++) {
00495 double *aijPtrA = &data[j*numRows];
00496 for (int k=0; k<numColB; k++) {
00497 double tmp = *ckjPtr++ * otherFact;
00498 double *aijPtr = aijPtrA;
00499 double *bikPtr = &(B.data)[k*numRows];
00500 for (int i=0; i<numRows; i++)
00501 *aijPtr++ += *bikPtr++ * tmp;
00502 }
00503 }
00504 }
00505 }
00506
00507 else if (thisFact == 0.0) {
00508
00509 if (otherFact == 1.0) {
00510
00511 double *dataPtr = data;
00512 for (int i=0; i<dataSize; i++)
00513 *dataPtr++ = 0.0;
00514 int numColB = B.numCols;
00515 double *ckjPtr = &(C.data)[0];
00516 for (int j=0; j<numCols; j++) {
00517 double *aijPtrA = &data[j*numRows];
00518 for (int k=0; k<numColB; k++) {
00519 double tmp = *ckjPtr++;
00520 double *aijPtr = aijPtrA;
00521 double *bikPtr = &(B.data)[k*numRows];
00522 for (int i=0; i<numRows; i++)
00523 *aijPtr++ += *bikPtr++ * tmp;
00524 }
00525 }
00526 } else {
00527
00528 double *dataPtr = data;
00529 for (int i=0; i<dataSize; i++)
00530 *dataPtr++ = 0.0;
00531 int numColB = B.numCols;
00532 double *ckjPtr = &(C.data)[0];
00533 for (int j=0; j<numCols; j++) {
00534 double *aijPtrA = &data[j*numRows];
00535 for (int k=0; k<numColB; k++) {
00536 double tmp = *ckjPtr++ * otherFact;
00537 double *aijPtr = aijPtrA;
00538 double *bikPtr = &(B.data)[k*numRows];
00539 for (int i=0; i<numRows; i++)
00540 *aijPtr++ += *bikPtr++ * tmp;
00541 }
00542 }
00543 }
00544 }
00545
00546 else {
00547
00548 double *dataPtr = data;
00549 for (int i=0; i<dataSize; i++)
00550 *dataPtr++ *= thisFact;
00551 int numColB = B.numCols;
00552 double *ckjPtr = &(C.data)[0];
00553 for (int j=0; j<numCols; j++) {
00554 double *aijPtrA = &data[j*numRows];
00555 for (int k=0; k<numColB; k++) {
00556 double tmp = *ckjPtr++ * otherFact;
00557 double *aijPtr = aijPtrA;
00558 double *bikPtr = &(B.data)[k*numRows];
00559 for (int i=0; i<numRows; i++)
00560 *aijPtr++ += *bikPtr++ * tmp;
00561 }
00562 }
00563 }
00564
00565 return 0;
00566 }
00567
00568
00569
00570 int
00571 Matrix::addMatrixTripleProduct(double thisFact,
00572 const Matrix &T,
00573 const Matrix &B,
00574 double otherFact)
00575 {
00576 if (thisFact == 1.0 && otherFact == 0.0)
00577 return 0;
00578 #ifdef _G3DEBUG
00579 if ((numCols != numRows) || (B.numCols != B.numRows) || (T.numCols != numRows) ||
00580 (T.numRows != B.numCols)) {
00581 g3ErrorHandler->warning("Matrix::addMatrixTripleProduct():%s[%d %d] T[%d %d] B[%d %d]\n",
00582 "incompatable matrices, this",
00583 numRows, numCols, T.numRows, T.numCols, B.numRows, B.numCols);
00584 return -1;
00585 }
00586 #endif
00587
00588
00589 int dimB = B.numCols;
00590 int sizeWork = dimB * numCols;
00591
00592 if (sizeWork > MATRIX_WORK_AREA) {
00593 this->addMatrix(thisFact, T^B*T, otherFact);
00594 return 0;
00595 }
00596
00597
00598 double *matrixWorkPtr = matrixWork;
00599 for (int l=0; l<sizeWork; l++)
00600 *matrixWorkPtr++ = 0.0;
00601
00602
00603
00604
00605 double *tkjPtr = &(T.data)[0];
00606 for (int j=0; j<numCols; j++) {
00607 double *aijPtrA = &matrixWork[j*dimB];
00608 for (int k=0; k<dimB; k++) {
00609 double tmp = *tkjPtr++ * otherFact;
00610 double *aijPtr = aijPtrA;
00611 double *bikPtr = &(B.data)[k*dimB];
00612 for (int i=0; i<dimB; i++)
00613 *aijPtr++ += *bikPtr++ * tmp;
00614 }
00615 }
00616
00617
00618
00619 if (thisFact == 1.0) {
00620 double *dataPtr = &data[0];
00621 for (int j=0; j< numCols; j++) {
00622 double *workkjPtrA = &matrixWork[j*dimB];
00623 for (int i=0; i<numRows; i++) {
00624 double *ckiPtr = &(T.data)[i*dimB];
00625 double *workkjPtr = workkjPtrA;
00626 double aij = 0.0;
00627 for (int k=0; k< dimB; k++)
00628 aij += *ckiPtr++ * *workkjPtr++;
00629 *dataPtr++ += aij;
00630 }
00631 }
00632 } else if (thisFact == 0.0) {
00633 double *dataPtr = &data[0];
00634 for (int j=0; j< numCols; j++) {
00635 double *workkjPtrA = &matrixWork[j*dimB];
00636 for (int i=0; i<numRows; i++) {
00637 double *ckiPtr = &(T.data)[i*dimB];
00638 double *workkjPtr = workkjPtrA;
00639 double aij = 0.0;
00640 for (int k=0; k< dimB; k++)
00641 aij += *ckiPtr++ * *workkjPtr++;
00642 *dataPtr++ = aij;
00643 }
00644 }
00645
00646 } else {
00647 double *dataPtr = &data[0];
00648 for (int j=0; j< numCols; j++) {
00649 double *workkjPtrA = &matrixWork[j*dimB];
00650 for (int i=0; i<numRows; i++) {
00651 double *ckiPtr = &(T.data)[i*dimB];
00652 double *workkjPtr = workkjPtrA;
00653 double aij = 0.0;
00654 for (int k=0; k< dimB; k++)
00655 aij += *ckiPtr++ * *workkjPtr++;
00656 double value = *dataPtr * thisFact + aij;
00657 *dataPtr++ = value;
00658 }
00659 }
00660 }
00661
00662 return 0;
00663 }
00664
00665
00666
00667
00668
00669
00670
00671 Matrix
00672 Matrix::operator()(const ID &rows, const ID & cols) const
00673 {
00674 int nRows, nCols;
00675 nRows = rows.Size();
00676 nCols = cols.Size();
00677 Matrix result(nRows,nCols);
00678 double *dataPtr = result.data;
00679 for (int i=0; i<nCols; i++)
00680 for (int j=0; j<nRows; j++)
00681 *dataPtr++ = (*this)(rows(j),cols(i));
00682
00683 return result;
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 Matrix &
00695 Matrix::operator=(const Matrix &other)
00696 {
00697
00698 if (this == &other)
00699 return *this;
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 if ((numCols != other.numCols) || (numRows != other.numRows)) {
00711 #ifdef _G3DEBUG
00712 g3ErrorHandler->warning("Matrix::operator=() - matrix dimensions do not match: [%d %d] != [%d %d]\n",
00713 numRows, numCols, other.numRows, other.numCols);
00714 #endif
00715 if (this->data != 0)
00716 delete [] this->data;
00717
00718 int theSize = other.numCols*other.numRows;
00719
00720 data = new double[theSize];
00721
00722 this->dataSize = theSize;
00723 this->numCols = other.numCols;
00724 this->numRows = other.numRows;
00725 }
00726
00727
00728
00729 double *dataPtr = data;
00730 double *otherDataPtr = other.data;
00731 for (int i=0; i<dataSize; i++)
00732 *dataPtr++ = *otherDataPtr++;
00733
00734 return *this;
00735 }
00736
00737
00738
00739
00740
00741 Matrix &
00742 Matrix::operator=(const Tensor &V)
00743 {
00744 int rank = V.rank();
00745 if (rank != 4) {
00746 g3ErrorHandler->warning("Matrix::operator=() - tensor must be of rank 4\n");
00747 return *this;
00748 }
00749 int dim = V.dim(1);
00750 if (dim != V.dim(2) != V.dim(3) != V.dim(4)) {
00751 g3ErrorHandler->warning("Matrix::operator=() - tensor must have square dimensions\n");
00752 return *this;
00753 }
00754
00755 if (dim != 2 || dim != 3 || dim != 1) {
00756 g3ErrorHandler->warning("Matrix::operator=() - tensor must be of dimension 2 or 3\n");
00757 return *this;
00758 }
00759
00760 if (dim == 1) {
00761 if ((numCols != 1) || (numRows != 1)) {
00762 g3ErrorHandler->warning("Matrix::operator=() - matrix must be %s\n",
00763 "1x1 for tensor of dimension 3\n");
00764 return *this;
00765 }
00766 (*this)(0,0) = V.cval(1,1,1,1);
00767
00768 } else if (dim == 2) {
00769 if ((numCols != 3) || (numRows != 3)) {
00770 g3ErrorHandler->warning("Matrix::operator=() - matrix must be %s\n",
00771 "1x1 for tensor of dimension 3\n");
00772 return *this;
00773 }
00774 (*this)(0,0) = V.cval(1,1,1,1);
00775 (*this)(0,1) = V.cval(1,1,2,2);
00776 (*this)(0,2) = V.cval(1,1,1,2);
00777
00778 (*this)(1,0) = V.cval(2,2,1,1);
00779 (*this)(1,1) = V.cval(2,2,2,2);
00780 (*this)(1,2) = V.cval(2,2,1,2);
00781
00782 (*this)(2,0) = V.cval(1,2,1,1);
00783 (*this)(2,1) = V.cval(1,2,2,2);
00784 (*this)(2,2) = V.cval(1,2,1,2);
00785
00786 } else {
00787 if ((numCols != 6) || (numRows != 6)) {
00788 g3ErrorHandler->warning("Matrix::operator=() - matrix must be %s\n",
00789 "1x1 for tensor of dimension 3\n");
00790 return *this;
00791 }
00792 (*this)(0,0) = V.cval(1,1,1,1);
00793 (*this)(0,1) = V.cval(1,1,2,2);
00794 (*this)(0,2) = V.cval(1,1,3,3);
00795 (*this)(0,3) = V.cval(1,1,1,2);
00796 (*this)(0,4) = V.cval(1,1,1,3);
00797 (*this)(0,5) = V.cval(1,1,2,3);
00798
00799 (*this)(1,0) = V.cval(2,2,1,1);
00800 (*this)(1,1) = V.cval(2,2,2,2);
00801 (*this)(1,2) = V.cval(2,2,3,3);
00802 (*this)(1,3) = V.cval(2,2,1,2);
00803 (*this)(1,4) = V.cval(2,2,1,3);
00804 (*this)(1,5) = V.cval(2,2,2,3);
00805
00806 (*this)(2,0) = V.cval(3,3,1,1);
00807 (*this)(2,1) = V.cval(3,3,2,2);
00808 (*this)(2,2) = V.cval(3,3,3,3);
00809 (*this)(2,3) = V.cval(3,3,1,2);
00810 (*this)(2,4) = V.cval(3,3,1,3);
00811 (*this)(2,5) = V.cval(3,3,2,3);
00812
00813 (*this)(3,0) = V.cval(1,2,1,1);
00814 (*this)(3,1) = V.cval(1,2,2,2);
00815 (*this)(3,2) = V.cval(1,2,3,3);
00816 (*this)(3,3) = V.cval(1,2,1,2);
00817 (*this)(3,4) = V.cval(1,2,1,3);
00818 (*this)(3,5) = V.cval(1,2,2,3);
00819
00820 (*this)(4,0) = V.cval(1,3,1,1);
00821 (*this)(4,1) = V.cval(1,3,2,2);
00822 (*this)(4,2) = V.cval(1,3,3,3);
00823 (*this)(4,3) = V.cval(1,3,1,2);
00824 (*this)(4,4) = V.cval(1,3,1,3);
00825 (*this)(4,5) = V.cval(1,3,2,3);
00826
00827 (*this)(5,0) = V.cval(2,3,1,1);
00828 (*this)(5,1) = V.cval(2,3,2,2);
00829 (*this)(5,2) = V.cval(2,3,3,3);
00830 (*this)(5,3) = V.cval(2,3,1,2);
00831 (*this)(5,4) = V.cval(2,3,1,3);
00832 (*this)(5,5) = V.cval(2,3,2,3);
00833 }
00834 return *this;
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 Matrix &
00847 Matrix::operator+=(double fact)
00848 {
00849
00850 if (fact == 0.0)
00851 return *this;
00852
00853 double *dataPtr = data;
00854 for (int i=0; i<dataSize; i++)
00855 *dataPtr++ += fact;
00856
00857 return *this;
00858 }
00859
00860
00861
00862
00863 Matrix &
00864 Matrix::operator-=(double fact)
00865 {
00866
00867 if (fact == 0.0)
00868 return *this;
00869
00870 double *dataPtr = data;
00871 for (int i=0; i<dataSize; i++)
00872 *dataPtr++ -= fact;
00873
00874 return *this;
00875 }
00876
00877
00878 Matrix &
00879 Matrix::operator*=(double fact)
00880 {
00881
00882 if (fact == 1.0)
00883 return *this;
00884
00885 double *dataPtr = data;
00886 for (int i=0; i<dataSize; i++)
00887 *dataPtr++ *= fact;
00888
00889 return *this;
00890 }
00891
00892 Matrix &
00893 Matrix::operator/=(double fact)
00894 {
00895
00896 if (fact == 1.0)
00897 return *this;
00898
00899 if (fact != 0.0) {
00900 double val = 1.0/fact;
00901
00902 double *dataPtr = data;
00903 for (int i=0; i<dataSize; i++)
00904 *dataPtr++ *= val;
00905
00906 return *this;
00907 } else {
00908
00909 cerr << "WARNING:Matrix::operator/= - 0 factor specified all values in Matrix set to ";
00910 cerr << MATRIX_VERY_LARGE_VALUE << endl;
00911
00912 double *dataPtr = data;
00913 for (int i=0; i<dataSize; i++)
00914 *dataPtr++ = MATRIX_VERY_LARGE_VALUE;
00915
00916 return *this;
00917 }
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927 Matrix
00928 Matrix::operator+(double fact) const
00929 {
00930 Matrix result(*this);
00931 result += fact;
00932 return result;
00933 }
00934
00935 Matrix
00936 Matrix::operator-(double fact) const
00937 {
00938 Matrix result(*this);
00939 result -= fact;
00940 return result;
00941 }
00942
00943 Matrix
00944 Matrix::operator*(double fact) const
00945 {
00946 Matrix result(*this);
00947 result *= fact;
00948 return result;
00949 }
00950
00951 Matrix
00952 Matrix::operator/(double fact) const
00953 {
00954 if (fact == 0.0) {
00955 cerr << "Matrix::operator/(const double &fact): ERROR divide-by-zero\n";
00956 exit(0);
00957 }
00958 Matrix result(*this);
00959 result /= fact;
00960 return result;
00961 }
00962
00963
00964
00965
00966
00967
00968 Vector
00969 Matrix::operator*(const Vector &V) const
00970 {
00971 Vector result(numRows);
00972
00973 if (V.Size() != numCols) {
00974 cerr << "Matrix::operator*(Vector): incompatable sizes\n";
00975 return result;
00976 }
00977
00978 double *dataPtr = data;
00979 for (int i=0; i<numCols; i++)
00980 for (int j=0; j<numRows; j++)
00981 result(j) += *dataPtr++ * V(i);
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 return result;
00998 }
00999
01000 Vector
01001 Matrix::operator^(const Vector &V) const
01002 {
01003 Vector result(numCols);
01004
01005 if (V.Size() != numRows) {
01006 cerr << "Matrix::operator*(Vector): incompatable sizes\n";
01007 return result;
01008 }
01009
01010 double *dataPtr = data;
01011 for (int i=0; i<numCols; i++)
01012 for (int j=0; j<numRows; j++)
01013 result(i) += *dataPtr++ * V(j);
01014
01015 return result;
01016 }
01017
01018
01019
01020
01021
01022
01023
01024 Matrix
01025 Matrix::operator+(const Matrix &M) const
01026 {
01027 Matrix result(*this);
01028 result.addMatrix(1.0,M,1.0);
01029 return result;
01030 }
01031
01032 Matrix
01033 Matrix::operator-(const Matrix &M) const
01034 {
01035 Matrix result(*this);
01036 result.addMatrix(1.0,M,-1.0);
01037 return result;
01038 }
01039
01040
01041 Matrix
01042 Matrix::operator*(const Matrix &M) const
01043 {
01044 Matrix result(numRows,M.numCols);
01045
01046 if (numCols != M.numRows || result.numRows != numRows) {
01047 cerr << "Matrix::operator*(Matrix): incompatable sizes\n";
01048 return result;
01049 }
01050
01051 double *resDataPtr = result.data;
01052
01053 int innerDim = numCols;
01054 int nCols = result.numCols;
01055 for (int i=0; i<nCols; i++) {
01056 double *aStartRowDataPtr = data;
01057 double *bStartColDataPtr = &(M.data[i*innerDim]);
01058 for (int j=0; j<numRows; j++) {
01059 double *bDataPtr = bStartColDataPtr;
01060 double *aDataPtr = aStartRowDataPtr +j;
01061 double sum = 0.0;
01062 for (int k=0; k<innerDim; k++) {
01063 sum += *aDataPtr * *bDataPtr++;
01064 aDataPtr += numRows;
01065 }
01066 *resDataPtr++ = sum;
01067 }
01068 }
01069 return result;
01070 }
01071
01072
01073
01074
01075
01076
01077
01078 Matrix
01079 Matrix::operator^(const Matrix &M) const
01080 {
01081 Matrix result(numCols,M.numCols);
01082
01083 if (numRows != M.numRows || result.numRows != numCols) {
01084 cerr << "Matrix::operator*(Matrix): incompatable sizes\n";
01085 return result;
01086 }
01087
01088 double *resDataPtr = result.data;
01089
01090 int innerDim = numRows;
01091 int nCols = result.numCols;
01092 for (int i=0; i<nCols; i++) {
01093 double *aDataPtr = data;
01094 double *bStartColDataPtr = &(M.data[i*innerDim]);
01095 for (int j=0; j<numCols; j++) {
01096 double *bDataPtr = bStartColDataPtr;
01097 double sum = 0.0;
01098 for (int k=0; k<innerDim; k++) {
01099 sum += *aDataPtr++ * *bDataPtr++;
01100 }
01101 *resDataPtr++ = sum;
01102 }
01103 }
01104
01105 return result;
01106 }
01107
01108
01109
01110
01111 Matrix &
01112 Matrix::operator+=(const Matrix &M)
01113 {
01114 #ifdef _G3DEBUG
01115 if (numRows != M.numRows || numCols != M.numCols) {
01116 g3ErrorHandler->warning("Matrix::operator+=(const Matrix &M) - matrices incompatable [%d %d] [%d %d]\n",
01117 numRows, numCols, M.numRows, M.numCols);
01118 return *this;
01119 }
01120 #endif
01121
01122 double *dataPtr = data;
01123 double *otherData = M.data;
01124 for (int i=0; i<dataSize; i++)
01125 *dataPtr++ += *otherData++;
01126
01127 return *this;
01128 }
01129
01130 Matrix &
01131 Matrix::operator-=(const Matrix &M)
01132 {
01133 #ifdef _G3DEBUG
01134 if (numRows != M.numRows || numCols != M.numCols) {
01135 g3ErrorHandler->warning("Matrix::operator-=(const Matrix &M) - matrices incompatable [%d %d] [%d %d]\n",
01136 numRows, numCols, M.numRows, M.numCols);
01137 return *this;
01138 }
01139 #endif
01140
01141 double *dataPtr = data;
01142 double *otherData = M.data;
01143 for (int i=0; i<dataSize; i++)
01144 *dataPtr++ -= *otherData++;
01145
01146 return *this;
01147 }
01148
01149
01150
01151
01152
01153
01154 void
01155 Matrix::Output(ostream &s) const
01156 {
01157 for (int i=0; i<noRows(); i++) {
01158 for (int j=0; j<noCols(); j++)
01159 s << (*this)(i,j) << " ";
01160 s << "\n";
01161 }
01162 }
01163
01164
01165 void
01166 Matrix::Input(istream &s)
01167 {
01168 for (int i=0; i<noRows(); i++)
01169 for (int j=0; j<noCols(); j++)
01170 s >> (*this)(i,j);
01171 }
01172
01173
01174
01175
01176
01177
01178 ostream &operator<<(ostream &s, const Matrix &V)
01179 {
01180 s << "\n";
01181 V.Output(s);
01182 s << "\n";
01183 return s;
01184 }
01185
01186
01187
01188 istream &operator>>(istream &s, Matrix &V)
01189 {
01190 V.Input(s);
01191 return s;
01192 }
01193
01194
01195
01196
01197
01198
01199 int
01200 Matrix::Assemble(const Matrix &V, int init_row, int init_col, double fact)
01201 {
01202 int pos_Rows, pos_Cols;
01203 int res = 0;
01204
01205 int VnumRows = V.numRows;
01206 int VnumCols = V.numCols;
01207
01208 int final_row = init_row + VnumRows - 1;
01209 int final_col = init_col + VnumCols - 1;
01210
01211 if ((init_row >= 0) && (final_row < numRows) && (init_col >= 0) && (final_col < numCols))
01212 {
01213 for (int i=0; i<VnumCols; i++)
01214 {
01215 pos_Cols = init_col + i;
01216 for (int j=0; j<VnumRows; j++)
01217 {
01218 pos_Rows = init_row + j;
01219
01220 (*this)(pos_Rows,pos_Cols) += V(j,i)*fact;
01221 }
01222 }
01223 }
01224 else
01225 {
01226 cerr << "WARNING: Matrix::Assemble(const Matrix &V, int init_row, int init_col, double fact): ";
01227 cerr << "position outside bounds \n";
01228 res = -1;
01229 }
01230
01231 return res;
01232 }
01233
01234
01235
01236
01237 int
01238 Matrix::AssembleTranspose(const Matrix &V, int init_row, int init_col, double fact)
01239 {
01240 int pos_Rows, pos_Cols;
01241 int res = 0;
01242
01243 int VnumRows = V.numRows;
01244 int VnumCols = V.numCols;
01245
01246 int final_row = init_row + VnumCols - 1;
01247 int final_col = init_col + VnumRows - 1;
01248
01249 if ((init_row >= 0) && (final_row < numRows) && (init_col >= 0) && (final_col < numCols))
01250 {
01251 for (int i=0; i<VnumRows; i++)
01252 {
01253 pos_Cols = init_col + i;
01254 for (int j=0; j<VnumCols; j++)
01255 {
01256 pos_Rows = init_row + j;
01257
01258 (*this)(pos_Rows,pos_Cols) += V(i,j)*fact;
01259 }
01260 }
01261 }
01262 else
01263 {
01264 cerr << "WARNING: Matrix::AssembleTranspose(const Matrix &V, int init_row, int init_col, double fact): ";
01265 cerr << "position outside bounds \n";
01266 res = -1;
01267 }
01268
01269 return res;
01270 }
01271
01272
01273
01274
01275 int
01276 Matrix::Extract(const Matrix &V, int init_row, int init_col, double fact)
01277 {
01278 int pos_Rows, pos_Cols;
01279 int res = 0;
01280
01281 int VnumRows = V.numRows;
01282 int VnumCols = V.numCols;
01283
01284 int final_row = init_row + numRows - 1;
01285 int final_col = init_col + numCols - 1;
01286
01287 if ((init_row >= 0) && (final_row < VnumRows) && (init_col >= 0) && (final_col < VnumCols))
01288 {
01289 for (int i=0; i<numCols; i++)
01290 {
01291 pos_Cols = init_col + i;
01292 for (int j=0; j<numRows; j++)
01293 {
01294 pos_Rows = init_row + j;
01295
01296 (*this)(j,i) = V(pos_Rows,pos_Cols)*fact;
01297 }
01298 }
01299 }
01300 else
01301 {
01302 cerr << "WARNING: Matrix::Extract(const Matrix &V, int init_row, int init_col, double fact): ";
01303 cerr << "position outside bounds \n";
01304 res = -1;
01305 }
01306
01307 return res;
01308 }
01309
01310
01311 Matrix operator*(double a, const Matrix &V)
01312 {
01313 return V * a;
01314 }
01315
01316
01317
01318