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
00038 #ifndef LA_USELAPACK_H
00039 #define LA_USELAPACK_H
00040
00041 #include "fastlib/la/matrix.h"
00042
00043 #include "fastlib/col/arraylist.h"
00044
00045 #define DEBUG_VECSIZE(a, b) \
00046 DEBUG_SAME_SIZE((a).length(), (b).length())
00047 #define DEBUG_MATSIZE(a, b) \
00048 DEBUG_SAME_SIZE((a).n_rows(), (b).n_rows());\
00049 DEBUG_SAME_SIZE((a).n_cols(), (b).n_cols())
00050 #define DEBUG_MATSQUARE(a) \
00051 DEBUG_SAME_SIZE((a).n_rows(), (a).n_cols())
00052
00053
00054
00055
00056
00057
00058
00059 #define SUCCESS_FROM_LAPACK(info) \
00060 (likely((info) == 0) ? SUCCESS_PASS : SUCCESS_FAIL)
00061
00062 #ifndef NO_LAPACK
00063 #define USE_LAPACK
00064 #define USE_BLAS_L1
00065 #endif
00066
00067 #if defined(DOXYGEN) && !defined(USE_LAPACK)
00068
00069 #define USE_LAPACK
00070 #endif
00071
00072 #ifdef USE_LAPACK
00073 #include "fastlib/la/blas.h"
00074 #include "fastlib/la/clapack.h"
00075
00076
00077 #endif
00078
00131 namespace la {
00136 inline void ScaleRows(index_t n_rows, index_t n_cols,
00137 const double *scales, double *matrix) {
00138 do {
00139 for (index_t i = 0; i < n_rows; i++) {
00140 matrix[i] *= scales[i];
00141 }
00142 matrix += n_rows;
00143 } while (--n_cols);
00144 }
00145
00146 #if defined(USE_LAPACK) && defined(USE_BLAS_L1)
00147
00148
00149
00150
00151
00155 inline double LengthEuclidean(index_t length, const double *x) {
00156 return F77_FUNC(dnrm2)(length, x, 1);
00157 }
00158
00163 inline double Dot(index_t length, const double *x, const double *y) {
00164 return F77_FUNC(ddot)(length, x, 1, y, 1);
00165 }
00166
00171 inline void Scale(index_t length, double alpha, double *x) {
00172 F77_FUNC(dscal)(length, alpha, x, 1);
00173 }
00178 inline void ScaleOverwrite(index_t length,
00179 double alpha, const double *x, double *y) {
00180 mem::Copy(y, x, length);
00181 Scale(length, alpha, y);
00182 }
00183
00188 inline void AddExpert(index_t length,
00189 double alpha, const double *x, double *y) {
00190 F77_FUNC(daxpy)(length, alpha, x, 1, y, 1);
00191 }
00192
00197 inline void AddTo(index_t length, const double *x, double *y) {
00198 AddExpert(length, 1.0, x, y);
00199 }
00204 inline void AddOverwrite(index_t length,
00205 const double *x, const double *y, double *z) {
00206 mem::Copy(z, y, length);
00207 AddTo(length, x, z);
00208 }
00209
00214 inline void SubFrom(index_t length, const double *x, double *y) {
00215 AddExpert(length, -1.0, x, y);
00216 }
00221 inline void SubOverwrite(index_t length,
00222 const double *x, const double *y, double *z) {
00223 mem::Copy(z, y, length);
00224 SubFrom(length, x, z);
00225 }
00226 #else
00227
00228
00229
00230 inline double LengthEuclidean(index_t length, const double *x) {
00231 double sum = 0;
00232 do {
00233 sum += *x * *x;
00234 x++;
00235 } while (--length);
00236 return sqrt(sum);
00237 }
00238
00239 inline double Dot(index_t length, const double *x, const double *y) {
00240 double sum = 0;
00241 const double *end = x + length;
00242 while (x != end) {
00243 sum += *x++ * *y++;
00244 }
00245 return sum;
00246 }
00247
00248 inline void Scale(index_t length, double alpha, double *x) {
00249 const double *end = x + length;
00250 while (x != end) {
00251 *x++ *= alpha;
00252 }
00253 }
00254
00255 inline void ScaleOverwrite(index_t length,
00256 double alpha, const double *x, double *y) {
00257 const double *end = x + length;
00258 while (x != end) {
00259 *y++ = alpha * *x++;
00260 }
00261 }
00262
00263 inline void AddExpert(index_t length,
00264 double alpha, const double *x, double *y) {
00265 const double *end = x + length;
00266 while (x != end) {
00267 *y++ += alpha * *x++;
00268 }
00269 }
00270
00271 inline void AddTo(index_t length, const double *x, double *y) {
00272 const double *end = x + length;
00273 while (x != end) {
00274 *y++ += *x++;
00275 }
00276 }
00277
00278 inline void AddOverwrite(index_t length,
00279 const double *x, const double *y, double *z) {
00280 for (index_t i = 0; i < length; i++) {
00281 z[i] = y[i] + x[i];
00282 }
00283 }
00284
00285 inline void SubFrom(index_t length, const double *x, double *y) {
00286 const double *end = x + length;
00287 while (x != end) {
00288 *y++ -= *x++;
00289 }
00290 }
00291
00292 inline void SubOverwrite(index_t length,
00293 const double *x, const double *y, double *z) {
00294 for (index_t i = 0; i < length; i++) {
00295 z[i] = y[i] - x[i];
00296 }
00297 }
00298 #endif
00299
00304 inline double LengthEuclidean(const Vector &x) {
00305 return LengthEuclidean(x.length(), x.ptr());
00306 }
00307
00312 inline double Dot(const Vector &x, const Vector &y) {
00313 DEBUG_SAME_SIZE(x.length(), y.length());
00314 return Dot(x.length(), x.ptr(), y.ptr());
00315 }
00322 inline double Dot(const Matrix &x, const Matrix &y) {
00323 DEBUG_SAME_SIZE(x.n_rows(), y.n_rows());
00324 DEBUG_SAME_SIZE(x.n_cols(), y.n_cols());
00325 return Dot(x.n_elements(), x.ptr(), y.ptr());
00326 }
00327
00328
00329
00334 inline void Scale(double alpha, Vector *x) {
00335 Scale(x->length(), alpha, x->ptr());
00336 }
00341 inline void Scale(double alpha, Matrix *X) {
00342 Scale(X->n_elements(), alpha, X->ptr());
00343 }
00352 inline void ScaleRows(const Vector& d, Matrix *X) {
00353 DEBUG_SAME_SIZE(d.length(), X->n_rows());
00354 ScaleRows(d.length(), X->n_cols(), d.ptr(), X->ptr());
00355 }
00364 inline void ScaleRows(const Matrix& d, Matrix *X) {
00365 DEBUG_SAME_SIZE(min(d.n_cols(), d.n_rows()), 1);
00366 DEBUG_SAME_SIZE(max(d.n_cols(), d.n_rows()), X->n_rows());
00367 ScaleRows(X->n_rows(), X->n_cols(), d.ptr(), X->ptr());
00368 }
00373 inline void ScaleOverwrite(double alpha, const Vector &x, Vector *y) {
00374 DEBUG_SAME_SIZE(x.length(), y->length());
00375 ScaleOverwrite(x.length(), alpha, x.ptr(), y->ptr());
00376 }
00381 inline void ScaleOverwrite(double alpha, const Matrix &X, Matrix *Y) {
00382 DEBUG_SAME_SIZE(X.n_rows(), Y->n_rows());
00383 DEBUG_SAME_SIZE(X.n_cols(), Y->n_cols());
00384 ScaleOverwrite(X.n_elements(), alpha, X.ptr(), Y->ptr());
00385 }
00386
00391 inline void ScaleInit(double alpha, const Vector &x, Vector *y) {
00392 y->Init(x.length());
00393 ScaleOverwrite(alpha, x, y);
00394 }
00399 inline void ScaleInit(double alpha, const Matrix &X, Matrix *Y) {
00400 Y->Init(X.n_rows(), X.n_cols());
00401 ScaleOverwrite(alpha, X, Y);
00402 }
00403
00404
00405
00410 inline void AddExpert(double alpha, const Vector &x, Vector *y) {
00411 DEBUG_SAME_SIZE(x.length(), y->length());
00412 AddExpert(x.length(), alpha, x.ptr(), y->ptr());
00413 }
00418 inline void AddExpert(double alpha, const Matrix &X, Matrix *Y) {
00419 DEBUG_SAME_SIZE(X.n_rows(), Y->n_rows());
00420 DEBUG_SAME_SIZE(X.n_cols(), Y->n_cols());
00421 AddExpert(X.n_elements(), alpha, X.ptr(), Y->ptr());
00422 }
00423
00424
00425
00430 inline void AddTo(const Vector &x, Vector *y) {
00431 DEBUG_SAME_SIZE(x.length(), y->length());
00432 AddTo(x.length(), x.ptr(), y->ptr());
00433 }
00438 inline void AddTo(const Matrix &X, Matrix *Y) {
00439 DEBUG_SAME_SIZE(X.n_rows(), Y->n_rows());
00440 DEBUG_SAME_SIZE(X.n_cols(), Y->n_cols());
00441 AddTo(X.n_elements(), X.ptr(), Y->ptr());
00442 }
00443
00448 inline void AddOverwrite(const Vector &x, const Vector &y, Vector *z) {
00449 DEBUG_SAME_SIZE(x.length(), y.length());
00450 DEBUG_SAME_SIZE(z->length(), y.length());
00451 AddOverwrite(x.length(), x.ptr(), y.ptr(), z->ptr());
00452 }
00457 inline void AddOverwrite(const Matrix &X, const Matrix &Y, Matrix *Z) {
00458 DEBUG_SAME_SIZE(X.n_rows(), Y.n_rows());
00459 DEBUG_SAME_SIZE(X.n_cols(), Y.n_cols());
00460 DEBUG_SAME_SIZE(Z->n_rows(), Y.n_rows());
00461 DEBUG_SAME_SIZE(Z->n_cols(), Y.n_cols());
00462 AddOverwrite(X.n_elements(), X.ptr(), Y.ptr(), Z->ptr());
00463 }
00464
00469 inline void AddInit(const Vector &x, const Vector &y, Vector *z) {
00470 z->Init(x.length());
00471 AddOverwrite(x, y, z);
00472 }
00477 inline void AddInit(const Matrix &X, const Matrix &Y, Matrix *Z) {
00478 Z->Init(X.n_rows(), X.n_cols());
00479 AddOverwrite(X, Y, Z);
00480 }
00481
00482
00483
00488 inline void SubFrom(const Vector &x, Vector *y) {
00489 DEBUG_SAME_SIZE(x.length(), y->length());
00490 SubFrom(x.length(), x.ptr(), y->ptr());
00491 }
00496 inline void SubFrom(const Matrix &X, Matrix *Y) {
00497 DEBUG_SAME_SIZE(X.n_rows(), Y->n_rows());
00498 DEBUG_SAME_SIZE(X.n_cols(), Y->n_cols());
00499 SubFrom(X.n_elements(), X.ptr(), Y->ptr());
00500 }
00501
00506 inline void SubOverwrite(const Vector &x, const Vector &y, Vector *z) {
00507 DEBUG_SAME_SIZE(x.length(), y.length());
00508 DEBUG_SAME_SIZE(z->length(), y.length());
00509 SubOverwrite(x.length(), x.ptr(), y.ptr(), z->ptr());
00510 }
00515 inline void SubOverwrite(const Matrix &X, const Matrix &Y, Matrix *Z) {
00516 DEBUG_SAME_SIZE(X.n_rows(), Y.n_rows());
00517 DEBUG_SAME_SIZE(X.n_cols(), Y.n_cols());
00518 DEBUG_SAME_SIZE(Z->n_rows(), Y.n_rows());
00519 DEBUG_SAME_SIZE(Z->n_cols(), Y.n_cols());
00520 SubOverwrite(X.n_elements(), X.ptr(), Y.ptr(), Z->ptr());
00521 }
00522
00527 inline void SubInit(const Vector &x, const Vector &y, Vector *z) {
00528 z->Init(x.length());
00529 SubOverwrite(x, y, z);
00530 }
00535 inline void SubInit(const Matrix &X, const Matrix &Y, Matrix *Z) {
00536 Z->Init(X.n_rows(), X.n_cols());
00537 SubOverwrite(X, Y, Z);
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00551 inline void TransposeSquare(Matrix *X) {
00552 DEBUG_MATSQUARE(*X);
00553 index_t nr = X->n_rows();
00554 for (index_t r = 1; r < nr; r++) {
00555 for (index_t c = 0; c < r; c++) {
00556 double temp = X->get(r, c);
00557 X->set(r, c, X->get(c, r));
00558 X->set(c, r, temp);
00559 }
00560 }
00561 }
00562
00567 inline void TransposeOverwrite(const Matrix &X, Matrix *Y) {
00568 DEBUG_SAME_SIZE(X.n_rows(), Y->n_cols());
00569 DEBUG_SAME_SIZE(X.n_cols(), Y->n_rows());
00570 index_t nr = X.n_rows();
00571 index_t nc = X.n_cols();
00572 for (index_t r = 0; r < nr; r++) {
00573 for (index_t c = 0; c < nc; c++) {
00574 Y->set(c, r, X.get(r, c));
00575 }
00576 }
00577 }
00582 inline void TransposeInit(const Matrix &X, Matrix *Y) {
00583 Y->Init(X.n_cols(), X.n_rows());
00584 TransposeOverwrite(X, Y);
00585 }
00586
00587
00588
00589 #ifdef USE_LAPACK
00590
00591
00602 inline void MulExpert(
00603 double alpha, const Matrix &A, const Vector &x,
00604 double beta, Vector *y) {
00605 DEBUG_ASSERT(x.ptr() != y->ptr());
00606 DEBUG_SAME_SIZE(A.n_cols(), x.length());
00607 DEBUG_SAME_SIZE(A.n_rows(), y->length());
00608 F77_FUNC(dgemv)("N", A.n_rows(), A.n_cols(),
00609 alpha, A.ptr(), A.n_rows(), x.ptr(), 1,
00610 beta, y->ptr(), 1);
00611 }
00612
00632 inline void MulOverwrite(const Matrix &A, const Vector &x, Vector *y) {
00633 MulExpert(1.0, A, x, 0.0, y);
00634 }
00644 inline void MulInit(const Matrix &A, const Vector &x, Vector *y) {
00645 y->Init(A.n_rows());
00646 MulOverwrite(A, x, y);
00647 }
00648
00661 inline void MulExpert(
00662 double alpha, const Vector &x, const Matrix &A,
00663 double beta, Vector *y) {
00664 DEBUG_ASSERT(x.ptr() != y->ptr());
00665 DEBUG_SAME_SIZE(A.n_rows(), x.length());
00666 DEBUG_SAME_SIZE(A.n_cols(), y->length());
00667 F77_FUNC(dgemv)("T", A.n_rows(), A.n_cols(),
00668 alpha, A.ptr(), A.n_rows(), x.ptr(), 1,
00669 beta, y->ptr(), 1);
00670 }
00671
00680 inline void MulOverwrite(const Vector &x, const Matrix &A, Vector *y) {
00681 MulExpert(1.0, x, A, 0.0, y);
00682 }
00692 inline void MulInit(const Vector &x, const Matrix &A, Vector *y) {
00693 y->Init(A.n_cols());
00694 MulOverwrite(x, A, y);
00695 }
00696
00697
00698
00699
00700
00713 inline void MulExpert(
00714 double alpha,
00715 bool trans_A, const Matrix &A,
00716 bool trans_B, const Matrix &B,
00717 double beta, Matrix *C) {
00718 DEBUG_ASSERT(A.ptr() != C->ptr());
00719 DEBUG_ASSERT(B.ptr() != C->ptr());
00720 DEBUG_SAME_SIZE(trans_A ? A.n_rows() : A.n_cols(),
00721 trans_B ? B.n_cols() : B.n_rows());
00722 DEBUG_SAME_SIZE(trans_A ? A.n_cols() : A.n_rows(), C->n_rows());
00723 DEBUG_SAME_SIZE(trans_B ? B.n_rows() : B.n_cols(), C->n_cols());
00724 F77_FUNC(dgemm)(trans_A ? "T" : "N", trans_B ? "T" : "N",
00725 C->n_rows(), C->n_cols(), trans_A ? A.n_rows() : A.n_cols(),
00726 alpha, A.ptr(), A.n_rows(), B.ptr(), B.n_rows(),
00727 beta, C->ptr(), C->n_rows());
00728 }
00739 inline void MulExpert(
00740 double alpha, const Matrix &A, const Matrix &B,
00741 double beta, Matrix *C) {
00742 MulExpert(alpha, false, A, false, B, beta, C);
00743 }
00744
00764 inline void MulOverwrite(const Matrix &A, const Matrix &B, Matrix *C) {
00765 MulExpert(1.0, A, B, 0.0, C);
00766 }
00776 inline void MulInit(const Matrix &A, const Matrix &B, Matrix *C) {
00777 C->Init(A.n_rows(), B.n_cols());
00778 MulOverwrite(A, B, C);
00779 }
00780
00789 inline void MulTransAOverwrite(
00790 const Matrix &A, const Matrix &B, Matrix *C) {
00791 MulExpert(1.0, true, A, false, B, 0.0, C);
00792 }
00802 inline void MulTransAInit(
00803 const Matrix &A, const Matrix &B, Matrix *C) {
00804 C->Init(A.n_cols(), B.n_cols());
00805 MulTransAOverwrite(A, B, C);
00806 }
00807
00816 inline void MulTransBOverwrite(
00817 const Matrix &A, const Matrix &B, Matrix *C) {
00818 MulExpert(1.0, false, A, true, B, 0.0, C);
00819 }
00829 inline void MulTransBInit(
00830 const Matrix &A, const Matrix &B, Matrix *C) {
00831 C->Init(A.n_rows(), B.n_rows());
00832 MulTransBOverwrite(A, B, C);
00833 }
00834
00835
00836
00837
00838
00839 extern int dgetri_block_size;
00840 extern int dgeqrf_block_size;
00841 extern int dorgqr_block_size;
00842 extern int dgeqrf_dorgqr_block_size;
00843
00854 inline success_t PLUExpert(f77_integer *pivots, Matrix *A_in_LU_out) {
00855 f77_integer info;
00856 F77_FUNC(dgetrf)(A_in_LU_out->n_rows(), A_in_LU_out->n_cols(),
00857 A_in_LU_out->ptr(), A_in_LU_out->n_rows(), pivots, &info);
00858 return SUCCESS_FROM_LAPACK(info);
00859 }
00872 success_t PLUInit(const Matrix &A,
00873 ArrayList<f77_integer> *pivots, Matrix *L, Matrix *U);
00874
00882 inline success_t InverseExpert(f77_integer *pivots, Matrix *LU_in_B_out) {
00883 f77_integer info;
00884 f77_integer n = LU_in_B_out->n_rows();
00885 f77_integer lwork = dgetri_block_size * n;
00886 double work[lwork];
00887 DEBUG_MATSQUARE(*LU_in_B_out);
00888 F77_FUNC(dgetri)(n, LU_in_B_out->ptr(), n, pivots, work, lwork, &info);
00889 return SUCCESS_FROM_LAPACK(info);
00890 }
00905 success_t Inverse(Matrix *A);
00923 success_t InverseOverwrite(const Matrix &A, Matrix *B);
00933 inline success_t InverseInit(const Matrix &A, Matrix *B) {
00934 B->Init(A.n_rows(), A.n_cols());
00935 return InverseOverwrite(A, B);
00936 }
00937
00952 long double Determinant(const Matrix &A);
00964 double DeterminantLog(const Matrix &A, int *sign_out);
00965
00980 inline success_t SolveExpert(
00981 f77_integer *pivots, Matrix *A_in_LU_out,
00982 index_t k, double *B_in_X_out) {
00983 DEBUG_MATSQUARE(*A_in_LU_out);
00984 f77_integer info;
00985 f77_integer n = A_in_LU_out->n_rows();
00986 F77_FUNC(dgesv)(n, k, A_in_LU_out->ptr(), n, pivots,
00987 B_in_X_out, n, &info);
00988 return SUCCESS_FROM_LAPACK(info);
00989 }
01013 inline success_t SolveInit(const Matrix &A, const Matrix &B, Matrix *X) {
01014 DEBUG_MATSQUARE(A);
01015 DEBUG_SAME_SIZE(A.n_rows(), B.n_rows());
01016 Matrix tmp;
01017 index_t n = B.n_rows();
01018 f77_integer pivots[n];
01019 tmp.Copy(A);
01020 X->Copy(B);
01021 return SolveExpert(pivots, &tmp, B.n_cols(), X->ptr());
01022 }
01046 inline success_t SolveInit(const Matrix &A, const Vector &b, Vector *x) {
01047 DEBUG_MATSQUARE(A);
01048 DEBUG_SAME_SIZE(A.n_rows(), b.length());
01049 Matrix tmp;
01050 index_t n = b.length();
01051 f77_integer pivots[n];
01052 tmp.Copy(A);
01053 x->Copy(b);
01054 return SolveExpert(pivots, &tmp, 1, x->ptr());
01055 }
01056
01070 success_t QRExpert(Matrix *A_in_Q_out, Matrix *R);
01097 success_t QRInit(const Matrix &A, Matrix *Q, Matrix *R);
01098
01112 success_t SchurExpert(Matrix *A_in_T_out,
01113 double *w_real, double *w_imag, double *Z);
01128 inline success_t SchurInit(const Matrix &A,
01129 Vector *w_real, Vector *w_imag, Matrix *T, Matrix *Z) {
01130 index_t n = A.n_rows();
01131 T->Copy(A);
01132 w_real->Init(n);
01133 w_imag->Init(n);
01134 Z->Init(n, n);
01135 return SchurExpert(T, w_real->ptr(), w_imag->ptr(), Z->ptr());
01136 }
01137
01152 success_t EigenExpert(Matrix *A_garbage,
01153 double *w_real, double *w_imag, double *V_raw);
01154
01165 inline success_t EigenvaluesInit(const Matrix &A,
01166 Vector *w_real, Vector *w_imag) {
01167 DEBUG_MATSQUARE(A);
01168 int n = A.n_rows();
01169 w_real->Init(n);
01170 w_imag->Init(n);
01171 Matrix tmp;
01172 tmp.Copy(A);
01173 return SchurExpert(&tmp, w_real->ptr(), w_imag->ptr(), NULL);
01174 }
01193 success_t EigenvaluesInit(const Matrix &A, Vector *w);
01194
01222 success_t EigenvectorsInit(const Matrix &A,
01223 Vector *w_real, Vector *w_imag, Matrix *V_real, Matrix *V_imag);
01224
01238 success_t EigenvectorsInit(const Matrix &A, Vector *w, Matrix *V);
01239
01260 success_t GenEigenSymmetric(int itype, Matrix *A_eigenvec, Matrix *B_chol, double *w);
01261
01293 success_t GenEigenNonSymmetric(Matrix *A_garbage, Matrix *B_garbage,
01294 double *alpha_real, double *alpha_imag, double *beta, double *V_raw);
01295
01311 success_t SVDExpert(Matrix* A_garbage, double *s, double *U, double *VT);
01312
01321 inline success_t SVDInit(const Matrix &A, Vector *s) {
01322 s->Init(std::min(A.n_rows(), A.n_cols()));
01323 Matrix tmp;
01324 tmp.Copy(A);
01325 return SVDExpert(&tmp, s->ptr(), NULL, NULL);
01326 }
01327
01359 inline success_t SVDInit(const Matrix &A, Vector *s, Matrix *U, Matrix *VT) {
01360 index_t k = std::min(A.n_rows(), A.n_cols());
01361 s->Init(k);
01362 U->Init(A.n_rows(), k);
01363 VT->Init(k, A.n_cols());
01364 Matrix tmp;
01365 tmp.Copy(A);
01366 return SVDExpert(&tmp, s->ptr(), U->ptr(), VT->ptr());
01367 }
01368
01377 success_t Cholesky(Matrix *A_in_U_out);
01378
01399 inline success_t CholeskyInit(const Matrix &A, Matrix *U) {
01400 U->Copy(A);
01401 return Cholesky(U);
01402 }
01403 #endif
01404
01405
01406
01407
01408
01409
01410
01411
01412 };
01413
01414 #endif