00001
00016 #include <dlrCommon/exception.h>
00017 #include <dlrLinearAlgebra/linearAlgebra.h>
00018 #include <dlrLinearAlgebra/clapack.h>
00019 #include <dlrNumeric/utilities.h>
00020
00021
00022 namespace dlr {
00023
00028 namespace linearAlgebra {
00029
00030 Float64
00031 determinant(const Array2D<Float64>& A)
00032 {
00033
00034 if(A.columns() != A.rows()) {
00035 DLR_THROW3(ValueException,
00036 "determinant(const Array2D<Float64>&)",
00037 "Input array is not square.");
00038 }
00039
00040
00041
00042
00043
00044
00045 Array2D<Float64> AColumnMajor = A.transpose();
00046 Int32 M = static_cast<Int32>(A.rows());
00047 Int32 N = static_cast<Int32>(A.columns());
00048 Int32 LDA = static_cast<Int32>(A.rows());
00049 Array1D<Int32> IPIV(M);
00050 Int32 info;
00051 dgetrf_(&M, &N, AColumnMajor.data(), &LDA, IPIV.data(), &info);
00052
00053
00054 if(info != 0L) {
00055 std::ostringstream message;
00056 message << "Call to dgetrf_ returns " << info
00057 << ". Something is wrong.";
00058 DLR_THROW3(ValueException,
00059 "determinant(const Array2D<Float64>&)",
00060 message.str().c_str());
00061 }
00062
00063
00064
00065
00066
00067 Float64 determinant = 1.0;
00068 size_t swapCount = 0;
00069 for(size_t index = 0; index < AColumnMajor.rows(); ++index) {
00070 determinant *= AColumnMajor(index, index);
00071 if(IPIV[index] != static_cast<Int32>(index + 1)) {
00072
00073 ++swapCount;
00074 }
00075 }
00076
00077
00078 if((swapCount % 2) == 1) {
00079 determinant *= -1.0;
00080 }
00081 return determinant;
00082 }
00083
00084
00085 Array1D<Float64>
00086 eigenvaluesSymmetric(const Array2D<Float64>& inputArray)
00087 {
00088
00089 if(inputArray.size() == 0) {
00090 DLR_THROW3(ValueException,
00091 "eigenvectorsSymmetric()",
00092 "Argument inputArray cannot have zero size.");
00093 }
00094 if(inputArray.rows() != inputArray.columns()) {
00095 DLR_THROW3(ValueException,
00096 "eigenvectorsSymmetric()",
00097 "Argument inputArray must be square.");
00098 }
00099
00100
00101
00102
00103 size_t dimension = inputArray.rows();
00104 Array2D<Float64> aColumnMajor(dimension, dimension);
00105 {
00106 Array2D<Float64>::const_iterator inPtr = inputArray.begin();
00107 Array2D<Float64>::iterator outPtr = aColumnMajor.begin();
00108 for(size_t index0 = 0; index0 < dimension; ++index0) {
00109 inPtr += index0;
00110 outPtr += index0;
00111 for(size_t index1 = index0; index1 < dimension; ++index1) {
00112 *(outPtr++) = *(inPtr++);
00113 }
00114 }
00115 }
00116
00117
00118 Array1D<Float64> eigenvalues(dimension);
00119
00120
00121 char JOBZ = 'N';
00122 char UPLO = 'L';
00123 Int32 N = static_cast<Int32>(inputArray.rows());
00124 Int32 LDA = N;
00125 Float64 WORK;
00126 Int32 LWORK = -1;
00127 Int32 INFO;
00128
00129
00130 dsyev_(&JOBZ, &UPLO, &N, aColumnMajor.data(), &LDA,
00131 eigenvalues.data(), &WORK, &LWORK, &INFO);
00132
00133
00134 if(INFO != 0L) {
00135 std::ostringstream message;
00136 message << "First call to dsyev_ returns " << INFO
00137 << ". Something is wrong.";
00138 DLR_THROW3(ValueException,
00139 "eigenvectorsSymmetric()",
00140 message.str().c_str());
00141 }
00142
00143
00144 LWORK = static_cast<Int32>(WORK);
00145 Array1D<Float64> doubleWorkSpace(static_cast<size_t>(LWORK));
00146
00147
00148 dsyev_(&JOBZ, &UPLO, &N, aColumnMajor.data(), &LDA,
00149 eigenvalues.data(), doubleWorkSpace.data(), &LWORK, &INFO);
00150
00151
00152 if(INFO != 0L) {
00153 std::ostringstream message;
00154 message << "First call to dsyev_ returns " << INFO
00155 << ". Something is wrong.";
00156 DLR_THROW3(ValueException,
00157 "eigenvectorsSymmetric()",
00158 message.str().c_str());
00159 }
00160
00161
00162 std::reverse(eigenvalues.begin(), eigenvalues.end());
00163 return eigenvalues;
00164 }
00165
00166
00167 void
00168 eigenvectorsSymmetric(const Array2D<Float64>& inputArray,
00169 Array1D<Float64>& eigenvalues,
00170 Array2D<Float64>& eigenvectors)
00171 {
00172
00173 if(inputArray.size() == 0) {
00174 DLR_THROW3(ValueException,
00175 "eigenvectorsSymmetric()",
00176 "Argument inputArray cannot have zero size.");
00177 }
00178 if(inputArray.rows() != inputArray.columns()) {
00179 DLR_THROW3(ValueException,
00180 "eigenvectorsSymmetric()",
00181 "Argument inputArray must be square.");
00182 }
00183
00184
00185
00186
00187 size_t dimension = inputArray.rows();
00188 Array2D<Float64> aColumnMajor(dimension, dimension);
00189 {
00190 Array2D<Float64>::const_iterator inPtr = inputArray.begin();
00191 Array2D<Float64>::iterator outPtr = aColumnMajor.begin();
00192 for(size_t index0 = 0; index0 < dimension; ++index0) {
00193 inPtr += index0;
00194 outPtr += index0;
00195 for(size_t index1 = index0; index1 < dimension; ++index1) {
00196 *(outPtr++) = *(inPtr++);
00197 }
00198 }
00199 }
00200
00201
00202 Array1D<Float64> eigenvaluesTmp(dimension);
00203
00204
00205 char JOBZ = 'V';
00206 char UPLO = 'L';
00207 Int32 N = static_cast<Int32>(dimension);
00208 Int32 LDA = static_cast<Int32>(dimension);
00209 Float64 WORK;
00210 Int32 LWORK = -1;
00211 Int32 INFO;
00212
00213
00214 dsyev_(&JOBZ, &UPLO, &N, aColumnMajor.data(), &LDA,
00215 eigenvaluesTmp.data(), &WORK, &LWORK, &INFO);
00216
00217
00218 if(INFO != 0L) {
00219 std::ostringstream message;
00220 message << "First call to dsyev_ returns " << INFO
00221 << ". Something is wrong.";
00222 DLR_THROW3(ValueException,
00223 "eigenvectorsSymmetric()",
00224 message.str().c_str());
00225 }
00226
00227
00228 LWORK = static_cast<Int32>(WORK);
00229 Array1D<Float64> doubleWorkSpace(static_cast<size_t>(LWORK));
00230
00231
00232 dsyev_(&JOBZ, &UPLO, &N, aColumnMajor.data(), &LDA,
00233 eigenvaluesTmp.data(), doubleWorkSpace.data(), &LWORK, &INFO);
00234
00235
00236 if(INFO != 0L) {
00237 std::ostringstream message;
00238 message << "First call to dsyev_ returns " << INFO
00239 << ". Something is wrong.";
00240 DLR_THROW3(ValueException,
00241 "eigenvectorsSymmetric()",
00242 message.str().c_str());
00243 }
00244
00245
00246
00247
00248
00249
00250 if(eigenvalues.size() != dimension) {
00251 eigenvalues.reinit(dimension);
00252 }
00253 if(eigenvectors.rows() != dimension
00254 || eigenvectors.columns() != dimension) {
00255 eigenvectors.reinit(dimension, dimension);
00256 }
00257
00258
00259 {
00260 Array1D<Float64>::iterator outPtr = eigenvalues.end() - 1;
00261 Array1D<Float64>::iterator inPtr0 = eigenvaluesTmp.begin();
00262 Array1D<Float64>::iterator inPtr1 = eigenvaluesTmp.end();
00263 while(inPtr0 != inPtr1) {
00264 *outPtr = *inPtr0;
00265 ++inPtr0;
00266 --outPtr;
00267 }
00268 }
00269
00270
00271 for(size_t index0 = 0; index0 < dimension; ++index0) {
00272 Float64* outPtr = eigenvectors.data(index0);
00273 Float64* inPtr = aColumnMajor.data((dimension - index0 - 1) * dimension);
00274 for(size_t index1 = 0; index1 < dimension; ++index1) {
00275 *outPtr = *inPtr;
00276 ++inPtr;
00277 outPtr += dimension;
00278 }
00279 }
00280 }
00281
00282
00283 Array2D<Float64>
00284 inverse(const Array2D<Float64>& A)
00285 {
00286
00287 if(A.columns() != A.rows()) {
00288 DLR_THROW3(ValueException,
00289 "inverse(const Array2D<Float64>&)",
00290 "Input array is not square.");
00291 }
00292
00293 Array2D<Float64> AInverse =
00294 identity(A.rows(), A.rows(), type_tag<Float64>());
00295 Array2D<Float64> AA = A.transpose();
00296
00297 linearSolveInPlace(AA, AInverse);
00298 return AInverse;
00299 }
00300
00301
00302
00303
00304 std::pair<Float64, Float64>
00305 linearFit(const Array1D<Float64>& array0,
00306 const Array1D<Float64>& array1)
00307 {
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 if(array0.size() != array1.size()) {
00328 std::ostringstream message;
00329 message << "Arguments array0 and array1 must have the same size, "
00330 << "but are of size " << array0.size()
00331 << " and " << array1.size() << " respectively." << std::endl;
00332 DLR_THROW3(ValueException,
00333 "linearFit(const Array1D<Float64>&, const Array1D<Float64>&)",
00334 message.str().c_str());
00335 }
00336 if(array0.size() == 0) {
00337 DLR_THROW3(ValueException,
00338 "linearFit(const Array1D<Float64>&, const Array1D<Float64>&)",
00339 "Arguments cannot have zero size.");
00340 }
00341
00342
00343 Array2D<Float64> AMatrix(2, 2);
00344 AMatrix(0, 0) = dot(array0, array0);
00345 AMatrix(0, 1) = sum(array0);
00346 AMatrix(1, 0) = sum(array0);
00347 AMatrix(1, 1) = array0.size();
00348
00349 Array1D<Float64> bVector(2);
00350 bVector(0) = dot(array0, array1);
00351 bVector(1) = sum(array1);
00352
00353 Array2D<Float64> AInverse = inverse(AMatrix);
00354
00355 Array1D<Float64> result = matrixMultiply(AInverse, bVector);
00356 return std::make_pair(result(0), result(1));
00357 }
00358
00359
00360
00361
00362 Array1D<Float64>
00363 linearLeastSquares(const Array2D<Float64>& A, const Array1D<Float64>& b)
00364 {
00365
00366 if(A.size() == 0) {
00367 DLR_THROW3(
00368 ValueException,
00369 "linearLeastSquares(const Array2D<Float64>&, const Array1D<Float64>&)",
00370 "Input array A must have nonzero size.");
00371 }
00372 if(A.rows() != b.size()) {
00373 DLR_THROW3(
00374 ValueException,
00375 "linearLeastSquares(const Array2D<Float64>&, const Array1D<Float64>&)",
00376 "The number of rows in input array A must be the same as the number "
00377 "of elements in b.");
00378 }
00379
00380
00381
00382
00383
00384
00385 char trans = 'N';
00386 Int32 rows = static_cast<Int32>(A.rows());
00387 Int32 columns = static_cast<Int32>(A.columns());
00388 Int32 nrhs = static_cast<Int32>(1);
00389 Int32 ldb = static_cast<Int32>(std::max(rows, columns));
00390 Float64 temporaryWorkspace;
00391 Int32 lwork = -1;
00392 Int32 info;
00393
00394
00395 Array2D<Float64> AColumnMajor = A.transpose();
00396 Array1D<Float64> bCopy(ldb);
00397 std::copy(b.begin(), b.end(), bCopy.begin());
00398
00399
00400
00401 dgels_(&trans, &rows, &columns, &nrhs, AColumnMajor.data(), &rows,
00402 bCopy.data(), &ldb, &temporaryWorkspace, &lwork, &info);
00403
00404
00405 if(info != 0L) {
00406 std::ostringstream message;
00407 message << "First call to dgels_ returns " << info
00408 << ". Something is wrong.";
00409 DLR_THROW3(ValueException,
00410 "linearLeastSquares()",
00411 message.str().c_str());
00412 }
00413
00414
00415 lwork = static_cast<Int32>(temporaryWorkspace);
00416 Array1D<Float64> doubleWorkspace(static_cast<size_t>(lwork));
00417
00418
00419 dgels_(&trans, &rows, &columns, &nrhs, AColumnMajor.data(), &rows,
00420 bCopy.data(), &ldb, doubleWorkspace.data(), &lwork, &info);
00421
00422
00423 if(info != 0L) {
00424 std::ostringstream message;
00425 message << "Second call to dgels_ returns " << info
00426 << ". Something is wrong.";
00427 DLR_THROW3(ValueException,
00428 "linearLeastSquares()",
00429 message.str().c_str());
00430 }
00431
00432 if(bCopy.size() == A.columns()) {
00433 return bCopy;
00434 } else {
00435 Array1D<Float64> returnValue(A.columns());
00436 std::copy(bCopy.begin(), bCopy.begin() + A.columns(),
00437 returnValue.begin());
00438 return returnValue;
00439 }
00440 }
00441
00442
00443
00444
00445
00446
00447
00448 void
00449 linearSolveInPlace(Array2D<Float64>& A, Array1D<Float64>& b)
00450 {
00451 Array2D<Float64> bMatrix(b.size(), 1, b.data());
00452 linearSolveInPlace(A, bMatrix);
00453 }
00454
00455
00456
00457
00458
00459 void
00460 linearSolveInPlace(Array2D<Float64> &A, Array2D<Float64> &b)
00461 {
00462
00463 if(A.rows() != b.rows()) {
00464 DLR_THROW3(ValueException,
00465 "linearSolveInPlace(Array2D<Float64>&, Array2D<Float64>&)",
00466 "Input arrays A and b must have the same number of rows.");
00467 }
00468 if(A.rows() != A.columns()) {
00469 DLR_THROW3(ValueException,
00470 "linearSolveInPlace(Array2D<Float64>&, Array2D<Float64>&)",
00471 "Input array A must be square.");
00472 }
00473
00474
00475 Array2D<Float64> AColumnMajor = A.transpose();
00476
00477
00478 Int32 rows = static_cast<Int32>(A.rows());
00479 Int32 xColumns = static_cast<Int32>(b.columns());
00480 Int32 *iPiv = new Int32[rows];
00481 Int32 info;
00482 dgesv_(&rows, &xColumns, AColumnMajor.data(), &rows, iPiv, b.data(), &rows,
00483 &info );
00484
00485 delete[] iPiv;
00486
00487 if(info != 0L) {
00488 std::ostringstream message;
00489 message << "Call to dgesv_ returns " << info << ". Something is wrong."
00490 << " Perhaps the the input equations are poorly conditioned "
00491 << "or perhaps there is no solution.";
00492 DLR_THROW3(ValueException,
00493 "linearSolveInPlace(Array2D<Float64>&, Array2D<Float64>&)",
00494 message.str().c_str());
00495 }
00496 }
00497
00498
00499
00500
00501 Array1D<Float64>
00502 linearSolveTridiagonal(const Array1D<Float64>& subDiagonal,
00503 const Array1D<Float64>& centerDiagonal,
00504 const Array1D<Float64>& superDiagonal,
00505 const Array1D<Float64>& bVector)
00506 {
00507
00508 if(subDiagonal.size() != superDiagonal.size()) {
00509 DLR_THROW3(ValueException,
00510 "linearSolveTridiagonal()",
00511 "Input arguments subDiagonal and superDiagonal "
00512 "must have the same size.");
00513 }
00514 if(centerDiagonal.size() != bVector.size()) {
00515 DLR_THROW3(ValueException,
00516 "linearSolveTridiagonal()",
00517 "Input arguments centerDiagonal and bVector "
00518 "must have the same size.");
00519 }
00520 if(centerDiagonal.size() != subDiagonal.size() + 1) {
00521 DLR_THROW3(ValueException,
00522 "linearSolveTridiagonal()",
00523 "Input argument centerDiagonal must have one more element "
00524 "than input argument subDiagonal.");
00525 }
00526
00527
00528
00529 Int32 N = static_cast<Int32>(centerDiagonal.size());
00530 Int32 NRHS = 1;
00531 Array1D<Float64> subDiagonalCopy = subDiagonal.copy();
00532 Array1D<Float64> centerDiagonalCopy = centerDiagonal.copy();
00533 Array1D<Float64> superDiagonalCopy = superDiagonal.copy();
00534 Array1D<Float64> xVector = bVector.copy();
00535 Int32 INFO;
00536
00537 dgtsv_(&N, &NRHS, subDiagonalCopy.data(), centerDiagonalCopy.data(),
00538 superDiagonalCopy.data(), xVector.data(), &N, &INFO);
00539
00540
00541 if(INFO != 0L) {
00542 std::ostringstream message;
00543 message << "Call to dgtsv_ returns " << INFO << ". Something is wrong."
00544 << " Perhaps the the input equations are poorly conditioned "
00545 << "or perhaps there is no solution.";
00546 DLR_THROW3(ValueException,
00547 "linearSolveTridiagonal()",
00548 message.str().c_str());
00549 }
00550
00551 return xVector;
00552 }
00553
00554
00555
00556
00557
00558 Array2D<Float64>
00559 pseudoinverse(const Array2D<Float64>& A)
00560 {
00561 Array2D<Float64> ATranspose = A.transpose();
00562 Array2D<Float64> ATA = matrixMultiply(ATranspose, A);
00563 return matrixMultiply(inverse(ATA), ATranspose);
00564 }
00565
00566
00567
00568
00569 void
00570 singularValueDecomposition(const Array2D<Float64>& inputArray,
00571 Array2D<Float64>& uArray,
00572 Array1D<Float64>& sigmaArray,
00573 Array2D<Float64>& vTransposeArray)
00574 {
00575
00576 if(inputArray.size() == 0) {
00577 DLR_THROW3(ValueException,
00578 "singularValueDecomposition()",
00579 "Argument inputArray cannot have zero size.");
00580 }
00581
00582
00583
00584
00585
00586 Array2D<Float64> aColumnMajor = inputArray.copy();
00587
00588
00589 size_t numberOfSingularValues =
00590 std::min(inputArray.rows(), inputArray.columns());
00591
00592 if((vTransposeArray.rows() != numberOfSingularValues)
00593 || (vTransposeArray.columns() != inputArray.columns())) {
00594 vTransposeArray.reinit(numberOfSingularValues, inputArray.columns());
00595 }
00596
00597 Array2D<Float64> uColumnMajor = vTransposeArray;
00598
00599 if((uArray.rows() != inputArray.rows())
00600 || (uArray.columns() != numberOfSingularValues)) {
00601 uArray.reinit(inputArray.rows(), numberOfSingularValues);
00602 }
00603
00604 Array2D<Float64> vTColumnMajor = uArray;
00605
00606 if(sigmaArray.size() != numberOfSingularValues) {
00607 sigmaArray.reinit(numberOfSingularValues);
00608 }
00609 Array1D<Int32> integerWorkSpace(8 * numberOfSingularValues);
00610
00611
00612 char JOBZ = 'S';
00613 Int32 M = static_cast<Int32>(inputArray.columns());
00614 Int32 N = static_cast<Int32>(inputArray.rows());
00615 Int32 LDA = M;
00616 Int32 LDU = M;
00617 Int32 LDVT = static_cast<Int32>(numberOfSingularValues);
00618 Float64 WORK;
00619 Int32 LWORK = -1;
00620 Int32 INFO;
00621
00622
00623 dgesdd_(&JOBZ, &M, &N, aColumnMajor.data(), &LDA,
00624 sigmaArray.data(), uColumnMajor.data(), &LDU,
00625 vTColumnMajor.data(), &LDVT,
00626 &WORK, &LWORK,
00627 integerWorkSpace.data(), &INFO);
00628
00629
00630 if(INFO != 0L) {
00631 std::ostringstream message;
00632 message << "First call to dgesdd_ returns " << INFO
00633 << ". Something is wrong.";
00634 DLR_THROW3(ValueException,
00635 "singularValueDecomposition()",
00636 message.str().c_str());
00637 }
00638
00639
00640 LWORK = static_cast<Int32>(WORK);
00641 Array1D<Float64> doubleWorkSpace(static_cast<size_t>(LWORK));
00642
00643
00644 dgesdd_(&JOBZ, &M, &N, aColumnMajor.data(), &LDA,
00645 sigmaArray.data(), uColumnMajor.data(), &LDU,
00646 vTColumnMajor.data(), &LDVT,
00647 doubleWorkSpace.data(), &LWORK,
00648 integerWorkSpace.data(), &INFO);
00649
00650
00651 if(INFO != 0L) {
00652 std::ostringstream message;
00653 message << "Second call to dgesdd_ returns " << INFO
00654 << ". Something is wrong.";
00655 DLR_THROW3(ValueException,
00656 "singularValueDecomposition()",
00657 message.str().c_str());
00658 }
00659 }
00660
00661
00662
00663 void
00664 singularValueDecompositionSimple(const Array2D<Float64>& inputArray,
00665 Array2D<Float64>& uArray,
00666 Array1D<Float64>& sigmaArray,
00667 Array2D<Float64>& vTransposeArray)
00668 {
00669
00670 if(inputArray.size() == 0) {
00671 DLR_THROW3(ValueException,
00672 "singularValueDecomposition()",
00673 "Argument inputArray cannot have zero size.");
00674 }
00675
00676
00677
00678
00679
00680 Array2D<Float64> aColumnMajor = inputArray.copy();
00681
00682
00683 size_t numberOfSingularValues =
00684 std::min(inputArray.rows(), inputArray.columns());
00685
00686
00687 if((vTransposeArray.rows() != numberOfSingularValues)
00688 || (vTransposeArray.columns() != inputArray.columns())) {
00689 vTransposeArray.reinit(numberOfSingularValues, inputArray.columns());
00690 }
00691
00692
00693 Array2D<Float64> uColumnMajor = vTransposeArray;
00694
00695
00696 if((uArray.rows() != inputArray.rows())
00697 || (uArray.columns() != numberOfSingularValues)) {
00698 uArray.reinit(inputArray.rows(), numberOfSingularValues);
00699 }
00700
00701
00702 Array2D<Float64> vTColumnMajor = uArray;
00703
00704 if(sigmaArray.size() != numberOfSingularValues) {
00705 sigmaArray.reinit(numberOfSingularValues);
00706 }
00707
00708
00709 Array1D<Int32> integerWorkspace(8 * numberOfSingularValues);
00710
00711
00712 char JOBZ = 'S';
00713 Int32 M = static_cast<Int32>(inputArray.columns());
00714 Int32 N = static_cast<Int32>(inputArray.rows());
00715 Int32 LDA = M;
00716 Int32 LDU = M;
00717 Int32 LDVT = static_cast<Int32>(numberOfSingularValues);
00718 Float64 WORK;
00719 Int32 LWORK = -1;
00720 Int32 INFO;
00721
00722
00723 dgesdd_(&JOBZ, &M, &N, aColumnMajor.data(), &LDA,
00724 sigmaArray.data(), uColumnMajor.data(), &LDU,
00725 vTColumnMajor.data(), &LDVT,
00726 &WORK, &LWORK, integerWorkspace.data(), &INFO);
00727
00728
00729 if(INFO != 0L) {
00730 std::ostringstream message;
00731 message << "First call to dgesdd_ returns " << INFO
00732 << ". Something is wrong.";
00733 DLR_THROW3(ValueException,
00734 "singularValueDecomposition()",
00735 message.str().c_str());
00736 }
00737
00738
00739 LWORK = static_cast<Int32>(WORK);
00740 Array1D<Float64> doubleWorkSpace(static_cast<size_t>(LWORK));
00741
00742
00743 dgesdd_(&JOBZ, &M, &N, aColumnMajor.data(), &LDA,
00744 sigmaArray.data(), uColumnMajor.data(), &LDU,
00745 vTColumnMajor.data(), &LDVT,
00746 doubleWorkSpace.data(), &LWORK, integerWorkspace.data(), &INFO);
00747
00748
00749 if(INFO != 0L) {
00750 std::ostringstream message;
00751 message << "Second call to dgesdd_ returns " << INFO
00752 << ". Something is wrong.";
00753 DLR_THROW3(ValueException,
00754 "singularValueDecomposition()",
00755 message.str().c_str());
00756 }
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 Array1D<Float64>
00849 singularValues(const Array2D<Float64>& inputArray)
00850 {
00851
00852 if(inputArray.size() == 0) {
00853 DLR_THROW3(ValueException,
00854 "singularValues()",
00855 "Argument inputArray cannot have zero size.");
00856 }
00857
00858
00859
00860
00861
00862
00863
00864 Array2D<Float64> aColumnMajor = inputArray.copy();
00865
00866
00867 size_t numberOfSingularValues =
00868 std::min(inputArray.rows(), inputArray.columns());
00869 Array1D<Float64> sigmaArray(numberOfSingularValues);
00870 Array1D<Int32> integerWorkSpace(8 * numberOfSingularValues);
00871
00872
00873 char JOBZ = 'N';
00874
00875
00876
00877 Int32 M = static_cast<Int32>(inputArray.columns());
00878 Int32 N = static_cast<Int32>(inputArray.rows());
00879 Int32 LDA = M;
00880 Float64 U;
00881 Int32 LDU = 1;
00882 Float64 VT;
00883 Int32 LDVT = 1;
00884 Float64 WORK;
00885 Int32 LWORK = -1;
00886 Int32 INFO;
00887
00888
00889 dgesdd_(&JOBZ, &M, &N, aColumnMajor.data(), &LDA,
00890 sigmaArray.data(), &U, &LDU, &VT, &LDVT,
00891 &WORK, &LWORK,
00892 integerWorkSpace.data(), &INFO);
00893
00894
00895 if(INFO != 0L) {
00896 std::ostringstream message;
00897 message << "First call to dgesdd_ returns " << INFO
00898 << ". Something is wrong.";
00899 DLR_THROW3(ValueException,
00900 "singularValues()",
00901 message.str().c_str());
00902 }
00903
00904
00905 LWORK = static_cast<Int32>(WORK);
00906
00907
00908 Int32 minimumLWORK =
00909 3 * std::min(M,N) + std::max(std::max(M, N), 6 * std::min(M, N));
00910 if(LWORK < minimumLWORK) {
00911
00912
00913 LWORK = minimumLWORK;
00914 }
00915 Array1D<Float64> doubleWorkSpace(static_cast<size_t>(LWORK));
00916
00917
00918 dgesdd_(&JOBZ, &M, &N, aColumnMajor.data(), &LDA,
00919 sigmaArray.data(), &U, &LDU, &VT, &LDVT,
00920 doubleWorkSpace.data(), &LWORK,
00921 integerWorkSpace.data(), &INFO);
00922
00923
00924 if(INFO != 0L) {
00925 std::ostringstream message;
00926 message << "First call to dgesdd_ returns " << INFO
00927 << ". Something is wrong.";
00928 DLR_THROW3(ValueException,
00929 "singularValues()",
00930 message.str().c_str());
00931 }
00932
00933
00934 return sigmaArray;
00935 }
00936
00937 }
00938
00939 }