00001
00005 #include <bpm/bpm_messages.h>
00006 #include <bpm/bpm_nr.h>
00007
00008 int gsl_linalg_householder_hm (double tau, const gsl_vector * v, gsl_matrix * A)
00009 {
00032 if (tau == 0.0)
00033 {
00034 return BPM_SUCCESS;
00035 }
00036
00037 #ifdef USE_BLAS
00038 {
00039 gsl_vector_const_view v1 = gsl_vector_const_subvector (v, 1, v->size - 1);
00040 gsl_matrix_view A1 = gsl_matrix_submatrix (A, 1, 0, A->size1 - 1, A->size2);
00041 size_t j;
00042
00043 for (j = 0; j < A->size2; j++)
00044 {
00045 double wj = 0.0;
00046 gsl_vector_view A1j = gsl_matrix_column(&A1.matrix, j);
00047 gsl_blas_ddot (&A1j.vector, &v1.vector, &wj);
00048 wj += gsl_matrix_get(A,0,j);
00049
00050 {
00051 double A0j = gsl_matrix_get (A, 0, j);
00052 gsl_matrix_set (A, 0, j, A0j - tau * wj);
00053 }
00054
00055 gsl_blas_daxpy (-tau * wj, &v1.vector, &A1j.vector);
00056 }
00057 }
00058 #else
00059 {
00060 size_t i, j;
00061
00062 for (j = 0; j < A->size2; j++)
00063 {
00064
00065
00066 double wj = gsl_matrix_get(A,0,j);
00067
00068 for (i = 1; i < A->size1; i++)
00069 {
00070 wj += gsl_matrix_get(A,i,j) * gsl_vector_get(v,i);
00071 }
00072
00073
00074
00075
00076 {
00077 double A0j = gsl_matrix_get (A, 0, j);
00078 gsl_matrix_set (A, 0, j, A0j - tau * wj);
00079 }
00080
00081
00082
00083 for (i = 1; i < A->size1; i++)
00084 {
00085 double Aij = gsl_matrix_get (A, i, j);
00086 double vi = gsl_vector_get (v, i);
00087 gsl_matrix_set (A, i, j, Aij - tau * vi * wj);
00088 }
00089 }
00090 }
00091 #endif
00092
00093 return BPM_SUCCESS;
00094 }
00095
00096 int gsl_linalg_householder_hm1 (double tau, gsl_matrix * A)
00097 {
00104 if (tau == 0)
00105 {
00106 size_t i,j;
00107
00108 gsl_matrix_set (A, 0, 0, 1.0);
00109
00110 for (j = 1; j < A->size2; j++)
00111 {
00112 gsl_matrix_set (A, 0, j, 0.0);
00113 }
00114
00115 for (i = 1; i < A->size1; i++)
00116 {
00117 gsl_matrix_set (A, i, 0, 0.0);
00118 }
00119
00120 return BPM_SUCCESS;
00121 }
00122
00123
00124
00125 #ifdef USE_BLAS
00126 {
00127 gsl_matrix_view A1 = gsl_matrix_submatrix (A, 1, 0, A->size1 - 1, A->size2);
00128 gsl_vector_view v1 = gsl_matrix_column (&A1.matrix, 0);
00129 size_t j;
00130
00131 for (j = 1; j < A->size2; j++)
00132 {
00133 double wj = 0.0;
00134
00135 gsl_vector_view A1j = gsl_matrix_column(&A1.matrix, j);
00136 gsl_blas_ddot (&A1j.vector, &v1.vector, &wj);
00137
00138
00139
00140 gsl_matrix_set (A, 0, j, - tau * wj);
00141
00142 gsl_blas_daxpy(-tau*wj, &v1.vector, &A1j.vector);
00143 }
00144
00145 gsl_blas_dscal(-tau, &v1.vector);
00146
00147 gsl_matrix_set (A, 0, 0, 1.0 - tau);
00148 }
00149 #else
00150 {
00151 size_t i, j;
00152
00153 for (j = 1; j < A->size2; j++)
00154 {
00155 double wj = 0.0;
00156
00157 for (i = 1; i < A->size1; i++)
00158 {
00159 double vi = gsl_matrix_get(A, i, 0);
00160 wj += gsl_matrix_get(A,i,j) * vi;
00161 }
00162
00163
00164
00165 gsl_matrix_set (A, 0, j, - tau * wj);
00166
00167 for (i = 1; i < A->size1; i++)
00168 {
00169 double vi = gsl_matrix_get (A, i, 0);
00170 double Aij = gsl_matrix_get (A, i, j);
00171 gsl_matrix_set (A, i, j, Aij - tau * vi * wj);
00172 }
00173 }
00174
00175 for (i = 1; i < A->size1; i++)
00176 {
00177 double vi = gsl_matrix_get(A, i, 0);
00178 gsl_matrix_set(A, i, 0, -tau * vi);
00179 }
00180
00181 gsl_matrix_set (A, 0, 0, 1.0 - tau);
00182 }
00183 #endif
00184
00185 return BPM_SUCCESS;
00186 }
00187
00188 void create_givens (const double a, const double b, double *c, double *s)
00189 {
00190 if (b == 0)
00191 {
00192 *c = 1;
00193 *s = 0;
00194 }
00195 else if (fabs (b) > fabs (a))
00196 {
00197 double t = -a / b;
00198 double s1 = 1.0 / sqrt (1 + t * t);
00199 *s = s1;
00200 *c = s1 * t;
00201 }
00202 else
00203 {
00204 double t = -b / a;
00205 double c1 = 1.0 / sqrt (1 + t * t);
00206 *c = c1;
00207 *s = c1 * t;
00208 }
00209 }
00210
00211
00212 int gsl_linalg_bidiag_decomp (gsl_matrix * A, gsl_vector * tau_U, gsl_vector * tau_V)
00213 {
00214 if (A->size1 < A->size2)
00215 {
00216 bpm_error("bidiagonal decomposition requires M>=N in gsl_linalg_bidag_decomp(...)",
00217 __FILE__, __LINE__);
00218 return BPM_SUCCESS;
00219 }
00220 else if (tau_U->size != A->size2)
00221 {
00222 bpm_error("size of tau_U must be N in gsl_linalg_bidag_decomp(...)",
00223 __FILE__, __LINE__);
00224 return BPM_SUCCESS;
00225 }
00226 else if (tau_V->size + 1 != A->size2)
00227 {
00228 bpm_error("size of tau_V must be (N - 1) in gsl_linalg_bidag_decomp(...)",
00229 __FILE__, __LINE__);
00230 return BPM_SUCCESS;
00231 }
00232 else
00233 {
00234 const size_t M = A->size1;
00235 const size_t N = A->size2;
00236 size_t i;
00237
00238 for (i = 0 ; i < N; i++)
00239 {
00240
00241
00242 {
00243 gsl_vector_view c = gsl_matrix_column (A, i);
00244 gsl_vector_view v = gsl_vector_subvector (&c.vector, i, M - i);
00245 double tau_i = gsl_linalg_householder_transform (&v.vector);
00246
00247
00248
00249 if (i + 1 < N)
00250 {
00251 gsl_matrix_view m =
00252 gsl_matrix_submatrix (A, i, i + 1, M - i, N - (i + 1));
00253 gsl_linalg_householder_hm (tau_i, &v.vector, &m.matrix);
00254 }
00255
00256 gsl_vector_set (tau_U, i, tau_i);
00257
00258 }
00259
00260
00261
00262 if (i + 1 < N)
00263 {
00264 gsl_vector_view r = gsl_matrix_row (A, i);
00265 gsl_vector_view v = gsl_vector_subvector (&r.vector, i + 1, N - (i + 1));
00266 double tau_i = gsl_linalg_householder_transform (&v.vector);
00267
00268
00269
00270 if (i + 1 < M)
00271 {
00272 gsl_matrix_view m =
00273 gsl_matrix_submatrix (A, i+1, i+1, M - (i+1), N - (i+1));
00274 gsl_linalg_householder_mh (tau_i, &v.vector, &m.matrix);
00275 }
00276
00277 gsl_vector_set (tau_V, i, tau_i);
00278 }
00279 }
00280 }
00281
00282 return BPM_SUCCESS;
00283 }
00284
00285 double gsl_linalg_householder_transform (gsl_vector * v)
00286 {
00292 const size_t n = v->size ;
00293
00294 if (n == 1)
00295 {
00296 return 0.0;
00297 }
00298 else
00299 {
00300 double alpha, beta, tau ;
00301
00302 gsl_vector_view x = gsl_vector_subvector (v, 1, n - 1) ;
00303
00304 double xnorm = gsl_blas_dnrm2 (&x.vector);
00305
00306 if (xnorm == 0)
00307 {
00308 return 0.0;
00309 }
00310
00311 alpha = gsl_vector_get (v, 0) ;
00312 beta = - (alpha >= 0.0 ? +1.0 : -1.0) * hypot(alpha, xnorm) ;
00313 tau = (beta - alpha) / beta ;
00314
00315 gsl_blas_dscal (1.0 / (alpha - beta), &x.vector);
00316 gsl_vector_set (v, 0, beta) ;
00317
00318 return tau;
00319 }
00320 }
00321
00322 int gsl_linalg_householder_mh (double tau, const gsl_vector * v, gsl_matrix * A)
00323 {
00329 if (tau == 0)
00330 return BPM_SUCCESS;
00331
00332
00333
00334 #ifdef USE_BLAS
00335 {
00336 gsl_vector_const_view v1 = gsl_vector_const_subvector (v, 1, v->size - 1);
00337 gsl_matrix_view A1 = gsl_matrix_submatrix (A, 0, 1, A->size1, A->size2-1);
00338 size_t i;
00339
00340 for (i = 0; i < A->size1; i++)
00341 {
00342 double wi = 0.0;
00343 gsl_vector_view A1i = gsl_matrix_row(&A1.matrix, i);
00344 gsl_blas_ddot (&A1i.vector, &v1.vector, &wi);
00345 wi += gsl_matrix_get(A,i,0);
00346
00347 {
00348 double Ai0 = gsl_matrix_get (A, i, 0);
00349 gsl_matrix_set (A, i, 0, Ai0 - tau * wi);
00350 }
00351
00352 gsl_blas_daxpy(-tau * wi, &v1.vector, &A1i.vector);
00353 }
00354 }
00355 #else
00356 {
00357 size_t i, j;
00358
00359 for (i = 0; i < A->size1; i++)
00360 {
00361 double wi = gsl_matrix_get(A,i,0);
00362
00363 for (j = 1; j < A->size2; j++)
00364 {
00365 wi += gsl_matrix_get(A,i,j) * gsl_vector_get(v,j);
00366 }
00367
00368
00369
00370 {
00371 double Ai0 = gsl_matrix_get (A, i, 0);
00372 gsl_matrix_set (A, i, 0, Ai0 - tau * wi);
00373 }
00374
00375
00376
00377 for (j = 1; j < A->size2; j++)
00378 {
00379 double vj = gsl_vector_get (v, j);
00380 double Aij = gsl_matrix_get (A, i, j);
00381 gsl_matrix_set (A, i, j, Aij - tau * wi * vj);
00382 }
00383 }
00384 }
00385 #endif
00386
00387 return BPM_SUCCESS;
00388 }
00389
00390 int gsl_linalg_SV_solve (const gsl_matrix * U,
00391 const gsl_matrix * V,
00392 const gsl_vector * S,
00393 const gsl_vector * b, gsl_vector * x)
00394 {
00395 if (U->size1 != b->size)
00396 {
00397 bpm_error("first dimension of matrix U must size of vector b in gsl_linalg_SV_solve(..)",
00398 __FILE__, __LINE__);
00399 return BPM_SUCCESS;
00400 }
00401 else if (U->size2 != S->size)
00402 {
00403 bpm_error("length of vector S must match second dimension of matrix U in gsl_linalg_SV_solve(..)",
00404 __FILE__, __LINE__);
00405 return BPM_SUCCESS;
00406 }
00407 else if (V->size1 != V->size2)
00408 {
00409 bpm_error("matrix V must be square in gsl_linalg_SV_solve(..)",
00410 __FILE__, __LINE__);
00411 return BPM_SUCCESS;
00412 }
00413 else if (S->size != V->size1)
00414 {
00415 bpm_error("length of vector S must match size of matrix V in gsl_linalg_SV_solve(..)",
00416 __FILE__, __LINE__);
00417 return BPM_SUCCESS;
00418 }
00419 else if (V->size2 != x->size)
00420 {
00421 bpm_error("size of matrix V must match size of vector x in gsl_linalg_SV_solve(..)",
00422 __FILE__, __LINE__);
00423 return BPM_SUCCESS;
00424 }
00425 else
00426 {
00427 const size_t N = U->size2;
00428 size_t i;
00429
00430 gsl_vector *w = gsl_vector_calloc (N);
00431
00432 gsl_blas_dgemv (CblasTrans, 1.0, U, b, 0.0, w);
00433
00434 for (i = 0; i < N; i++)
00435 {
00436 double wi = gsl_vector_get (w, i);
00437 double alpha = gsl_vector_get (S, i);
00438 if (alpha != 0)
00439 alpha = 1.0 / alpha;
00440 gsl_vector_set (w, i, alpha * wi);
00441 }
00442
00443 gsl_blas_dgemv (CblasNoTrans, 1.0, V, w, 0.0, x);
00444
00445 gsl_vector_free (w);
00446
00447 return BPM_SUCCESS;
00448 }
00449 }
00450
00451 int gsl_isnan (const double x)
00452 {
00453 int status = (x != x);
00454 return status;
00455 }
00456
00457 void chop_small_elements (gsl_vector * d, gsl_vector * f)
00458 {
00459 const size_t N = d->size;
00460 double d_i = gsl_vector_get (d, 0);
00461
00462 size_t i;
00463
00464 for (i = 0; i < N - 1; i++)
00465 {
00466 double f_i = gsl_vector_get (f, i);
00467 double d_ip1 = gsl_vector_get (d, i + 1);
00468
00469 if (fabs (f_i) < GSL_DBL_EPSILON * (fabs (d_i) + fabs (d_ip1)))
00470 {
00471 gsl_vector_set (f, i, 0.0);
00472 }
00473 d_i = d_ip1;
00474 }
00475
00476 }
00477
00478 void qrstep (gsl_vector * d, gsl_vector * f, gsl_matrix * U, gsl_matrix * V)
00479 {
00480 #if !USE_BLAS
00481 const size_t M = U->size1;
00482 const size_t N = V->size1;
00483 #endif
00484 const size_t n = d->size;
00485 double y, z;
00486 double ak, bk, zk, ap, bp, aq, bq;
00487 size_t i, k;
00488
00489 if (n == 1)
00490 return;
00491
00492
00493
00494 if (n == 2)
00495 {
00496 svd2 (d, f, U, V);
00497 return;
00498 }
00499
00500
00501
00502 for (i = 0; i < n - 1; i++)
00503 {
00504 double d_i = gsl_vector_get (d, i);
00505
00506 if (d_i == 0.0)
00507 {
00508 chase_out_intermediate_zero (d, f, U, i);
00509 return;
00510 }
00511 }
00512
00513
00514
00515 {
00516 double d_nm1 = gsl_vector_get (d, n - 1);
00517
00518 if (d_nm1 == 0.0)
00519 {
00520 chase_out_trailing_zero (d, f, V);
00521 return;
00522 }
00523 }
00524
00525
00526
00527
00528 {
00529 double d0 = gsl_vector_get (d, 0);
00530 double f0 = gsl_vector_get (f, 0);
00531
00532 double d1 = gsl_vector_get (d, 1);
00533 double f1 = gsl_vector_get (f, 1);
00534
00535 {
00536 double mu = trailing_eigenvalue (d, f);
00537
00538 y = d0 * d0 - mu;
00539 z = d0 * f0;
00540 }
00541
00542
00543
00544 ak = 0;
00545 bk = 0;
00546
00547 ap = d0;
00548 bp = f0;
00549
00550 aq = d1;
00551 bq = f1;
00552 }
00553
00554 for (k = 0; k < n - 1; k++)
00555 {
00556 double c, s;
00557 create_givens (y, z, &c, &s);
00558
00559
00560
00561 #ifdef USE_BLAS
00562 {
00563 gsl_vector_view Vk = gsl_matrix_column(V,k);
00564 gsl_vector_view Vkp1 = gsl_matrix_column(V,k+1);
00565 gsl_blas_drot(&Vk.vector, &Vkp1.vector, c, -s);
00566 }
00567 #else
00568 for (i = 0; i < N; i++)
00569 {
00570 double Vip = gsl_matrix_get (V, i, k);
00571 double Viq = gsl_matrix_get (V, i, k + 1);
00572 gsl_matrix_set (V, i, k, c * Vip - s * Viq);
00573 gsl_matrix_set (V, i, k + 1, s * Vip + c * Viq);
00574 }
00575 #endif
00576
00577
00578
00579 {
00580 double bk1 = c * bk - s * z;
00581
00582 double ap1 = c * ap - s * bp;
00583 double bp1 = s * ap + c * bp;
00584 double zp1 = -s * aq;
00585
00586 double aq1 = c * aq;
00587
00588 if (k > 0)
00589 {
00590 gsl_vector_set (f, k - 1, bk1);
00591 }
00592
00593 ak = ap1;
00594 bk = bp1;
00595 zk = zp1;
00596
00597 ap = aq1;
00598
00599 if (k < n - 2)
00600 {
00601 bp = gsl_vector_get (f, k + 1);
00602 }
00603 else
00604 {
00605 bp = 0.0;
00606 }
00607
00608 y = ak;
00609 z = zk;
00610 }
00611
00612 create_givens (y, z, &c, &s);
00613
00614
00615
00616 #ifdef USE_BLAS
00617 {
00618 gsl_vector_view Uk = gsl_matrix_column(U,k);
00619 gsl_vector_view Ukp1 = gsl_matrix_column(U,k+1);
00620 gsl_blas_drot(&Uk.vector, &Ukp1.vector, c, -s);
00621 }
00622 #else
00623 for (i = 0; i < M; i++)
00624 {
00625 double Uip = gsl_matrix_get (U, i, k);
00626 double Uiq = gsl_matrix_get (U, i, k + 1);
00627 gsl_matrix_set (U, i, k, c * Uip - s * Uiq);
00628 gsl_matrix_set (U, i, k + 1, s * Uip + c * Uiq);
00629 }
00630 #endif
00631
00632
00633
00634 {
00635 double ak1 = c * ak - s * zk;
00636 double bk1 = c * bk - s * ap;
00637 double zk1 = -s * bp;
00638
00639 double ap1 = s * bk + c * ap;
00640 double bp1 = c * bp;
00641
00642 gsl_vector_set (d, k, ak1);
00643
00644 ak = ak1;
00645 bk = bk1;
00646 zk = zk1;
00647
00648 ap = ap1;
00649 bp = bp1;
00650
00651 if (k < n - 2)
00652 {
00653 aq = gsl_vector_get (d, k + 2);
00654 }
00655 else
00656 {
00657 aq = 0.0;
00658 }
00659
00660 y = bk;
00661 z = zk;
00662 }
00663 }
00664
00665 gsl_vector_set (f, n - 2, bk);
00666 gsl_vector_set (d, n - 1, ap);
00667 }
00668
00669 double trailing_eigenvalue (const gsl_vector * d, const gsl_vector * f)
00670 {
00671
00672 const size_t n = d->size;
00673
00674 double da = gsl_vector_get (d, n - 2);
00675 double db = gsl_vector_get (d, n - 1);
00676 double fa = (n > 2) ? gsl_vector_get (f, n - 3) : 0.0;
00677 double fb = gsl_vector_get (f, n - 2);
00678
00679 double ta = da * da + fa * fa;
00680 double tb = db * db + fb * fb;
00681 double tab = da * fb;
00682
00683 double dt = (ta - tb) / 2.0;
00684
00685 double mu;
00686
00687 if (dt >= 0)
00688 {
00689 mu = tb - (tab * tab) / (dt + hypot (dt, tab));
00690 }
00691 else
00692 {
00693 mu = tb + (tab * tab) / ((-dt) + hypot (dt, tab));
00694 }
00695
00696 return mu;
00697 }
00698
00699 void create_schur (double d0, double f0, double d1, double * c, double * s)
00700 {
00701
00702 double apq = 2.0 * d0 * f0;
00703
00704 if (apq != 0.0)
00705 {
00706 double t;
00707 double tau = (f0*f0 + (d1 + d0)*(d1 - d0)) / apq;
00708
00709 if (tau >= 0.0)
00710 {
00711 t = 1.0/(tau + hypot(1.0, tau));
00712 }
00713 else
00714 {
00715 t = -1.0/(-tau + hypot(1.0, tau));
00716 }
00717
00718 *c = 1.0 / hypot(1.0, t);
00719 *s = t * (*c);
00720 }
00721 else
00722 {
00723 *c = 1.0;
00724 *s = 0.0;
00725 }
00726 }
00727
00728 void svd2 (gsl_vector * d, gsl_vector * f, gsl_matrix * U, gsl_matrix * V)
00729 {
00730
00731 size_t i;
00732 double c, s, a11, a12, a21, a22;
00733
00734 const size_t M = U->size1;
00735 const size_t N = V->size1;
00736
00737 double d0 = gsl_vector_get (d, 0);
00738 double f0 = gsl_vector_get (f, 0);
00739
00740 double d1 = gsl_vector_get (d, 1);
00741
00742 if (d0 == 0.0)
00743 {
00744
00745
00746 create_givens (f0, d1, &c, &s);
00747
00748
00749
00750 gsl_vector_set (d, 0, c * f0 - s * d1);
00751 gsl_vector_set (f, 0, s * f0 + c * d1);
00752 gsl_vector_set (d, 1, 0.0);
00753
00754
00755
00756 for (i = 0; i < M; i++)
00757 {
00758 double Uip = gsl_matrix_get (U, i, 0);
00759 double Uiq = gsl_matrix_get (U, i, 1);
00760 gsl_matrix_set (U, i, 0, c * Uip - s * Uiq);
00761 gsl_matrix_set (U, i, 1, s * Uip + c * Uiq);
00762 }
00763
00764
00765
00766 gsl_matrix_swap_columns (V, 0, 1);
00767
00768 return;
00769 }
00770 else if (d1 == 0.0)
00771 {
00772
00773
00774 create_givens (d0, f0, &c, &s);
00775
00776
00777
00778 gsl_vector_set (d, 0, d0 * c - f0 * s);
00779 gsl_vector_set (f, 0, 0.0);
00780
00781
00782
00783 for (i = 0; i < N; i++)
00784 {
00785 double Vip = gsl_matrix_get (V, i, 0);
00786 double Viq = gsl_matrix_get (V, i, 1);
00787 gsl_matrix_set (V, i, 0, c * Vip - s * Viq);
00788 gsl_matrix_set (V, i, 1, s * Vip + c * Viq);
00789 }
00790
00791 return;
00792 }
00793 else
00794 {
00795
00796
00797 create_schur (d0, f0, d1, &c, &s);
00798
00799
00800
00801 a11 = c * d0 - s * f0;
00802 a21 = - s * d1;
00803
00804 a12 = s * d0 + c * f0;
00805 a22 = c * d1;
00806
00807
00808
00809 for (i = 0; i < N; i++)
00810 {
00811 double Vip = gsl_matrix_get (V, i, 0);
00812 double Viq = gsl_matrix_get (V, i, 1);
00813 gsl_matrix_set (V, i, 0, c * Vip - s * Viq);
00814 gsl_matrix_set (V, i, 1, s * Vip + c * Viq);
00815 }
00816
00817
00818
00819
00820 if (hypot(a11, a21) < hypot(a12,a22))
00821 {
00822 double t1, t2;
00823
00824
00825
00826 t1 = a11; a11 = a12; a12 = t1;
00827 t2 = a21; a21 = a22; a22 = t2;
00828
00829
00830
00831 gsl_matrix_swap_columns(V, 0, 1);
00832 }
00833
00834 create_givens (a11, a21, &c, &s);
00835
00836
00837
00838 gsl_vector_set (d, 0, c * a11 - s * a21);
00839 gsl_vector_set (f, 0, c * a12 - s * a22);
00840 gsl_vector_set (d, 1, s * a12 + c * a22);
00841
00842
00843
00844 for (i = 0; i < M; i++)
00845 {
00846 double Uip = gsl_matrix_get (U, i, 0);
00847 double Uiq = gsl_matrix_get (U, i, 1);
00848 gsl_matrix_set (U, i, 0, c * Uip - s * Uiq);
00849 gsl_matrix_set (U, i, 1, s * Uip + c * Uiq);
00850 }
00851
00852 return;
00853 }
00854 }
00855
00856
00857 void chase_out_intermediate_zero (gsl_vector * d, gsl_vector * f, gsl_matrix * U, size_t k0)
00858 {
00859
00860 #if !USE_BLAS
00861 const size_t M = U->size1;
00862 #endif
00863 const size_t n = d->size;
00864 double c, s;
00865 double x, y;
00866 size_t k;
00867
00868 x = gsl_vector_get (f, k0);
00869 y = gsl_vector_get (d, k0+1);
00870
00871 for (k = k0; k < n - 1; k++)
00872 {
00873 create_givens (y, -x, &c, &s);
00874
00875
00876
00877 #ifdef USE_BLAS
00878 {
00879 gsl_vector_view Uk0 = gsl_matrix_column(U,k0);
00880 gsl_vector_view Ukp1 = gsl_matrix_column(U,k+1);
00881 gsl_blas_drot(&Uk0.vector, &Ukp1.vector, c, -s);
00882 }
00883 #else
00884 {
00885 size_t i;
00886
00887 for (i = 0; i < M; i++)
00888 {
00889 double Uip = gsl_matrix_get (U, i, k0);
00890 double Uiq = gsl_matrix_get (U, i, k + 1);
00891 gsl_matrix_set (U, i, k0, c * Uip - s * Uiq);
00892 gsl_matrix_set (U, i, k + 1, s * Uip + c * Uiq);
00893 }
00894 }
00895 #endif
00896
00897
00898
00899 gsl_vector_set (d, k + 1, s * x + c * y);
00900
00901 if (k == k0)
00902 gsl_vector_set (f, k, c * x - s * y );
00903
00904 if (k < n - 2)
00905 {
00906 double z = gsl_vector_get (f, k + 1);
00907 gsl_vector_set (f, k + 1, c * z);
00908
00909 x = -s * z ;
00910 y = gsl_vector_get (d, k + 2);
00911 }
00912 }
00913 }
00914
00915 void chase_out_trailing_zero (gsl_vector * d, gsl_vector * f, gsl_matrix * V)
00916 {
00917 #if !USE_BLAS
00918 const size_t N = V->size1;
00919 #endif
00920 const size_t n = d->size;
00921 double c, s;
00922 double x, y;
00923 size_t k;
00924
00925 x = gsl_vector_get (d, n - 2);
00926 y = gsl_vector_get (f, n - 2);
00927
00928 for (k = n - 1; k > 0 && k--;)
00929 {
00930 create_givens (x, y, &c, &s);
00931
00932
00933
00934 #ifdef USE_BLAS
00935 {
00936 gsl_vector_view Vp = gsl_matrix_column(V,k);
00937 gsl_vector_view Vq = gsl_matrix_column(V,n-1);
00938 gsl_blas_drot(&Vp.vector, &Vq.vector, c, -s);
00939 }
00940 #else
00941 {
00942 size_t i;
00943
00944 for (i = 0; i < N; i++)
00945 {
00946 double Vip = gsl_matrix_get (V, i, k);
00947 double Viq = gsl_matrix_get (V, i, n - 1);
00948 gsl_matrix_set (V, i, k, c * Vip - s * Viq);
00949 gsl_matrix_set (V, i, n - 1, s * Vip + c * Viq);
00950 }
00951 }
00952 #endif
00953
00954
00955
00956 gsl_vector_set (d, k, c * x - s * y);
00957
00958 if (k == n - 2)
00959 gsl_vector_set (f, k, s * x + c * y );
00960
00961 if (k > 0)
00962 {
00963 double z = gsl_vector_get (f, k - 1);
00964 gsl_vector_set (f, k - 1, c * z);
00965
00966 x = gsl_vector_get (d, k - 1);
00967 y = s * z ;
00968 }
00969 }
00970 }
00971
00972 int gsl_linalg_bidiag_unpack (const gsl_matrix * A, const gsl_vector * tau_U,
00973 gsl_matrix * U, const gsl_vector * tau_V,
00974 gsl_matrix * V, gsl_vector * diag,
00975 gsl_vector * superdiag) {
00976 const size_t M = A->size1;
00977 const size_t N = A->size2;
00978
00979 const size_t K = GSL_MIN(M, N);
00980
00981 if (M < N)
00982 {
00983 bpm_error("matrix A must have M >= N in gsl_linalg_bidiag_unpack(...)",
00984 __FILE__, __LINE__);
00985 return BPM_FAILURE;
00986 }
00987 else if (tau_U->size != K)
00988 {
00989 bpm_error("size of tau must be MIN(M,N) in gsl_linalg_bidiag_unpack(...)",
00990 __FILE__, __LINE__);
00991 return BPM_FAILURE;
00992 }
00993 else if (tau_V->size + 1 != K)
00994 {
00995 bpm_error("size of tau must be MIN(M,N) - 1 in gsl_linalg_bidiag_unpack(...)",
00996 __FILE__, __LINE__);
00997 return BPM_FAILURE;
00998 }
00999 else if (U->size1 != M || U->size2 != N)
01000 {
01001 bpm_error("size of U must be M x N in gsl_linalg_bidiag_unpack(...)",
01002 __FILE__, __LINE__);
01003 return BPM_FAILURE;
01004 }
01005 else if (V->size1 != N || V->size2 != N)
01006 {
01007 bpm_error("size of V must be N x N in gsl_linalg_bidiag_unpack(...)",
01008 __FILE__, __LINE__);
01009 return BPM_FAILURE;
01010 }
01011 else if (diag->size != K)
01012 {
01013 bpm_error("size of diagonal must match size of A in gsl_linalg_bidiag_unpack(...)",
01014 __FILE__, __LINE__);
01015 return BPM_FAILURE;
01016 }
01017 else if (superdiag->size + 1 != K)
01018 {
01019 bpm_error("size of subdiagonal must be (diagonal size - 1) in gsl_linalg_bidiag_unpack(...)",
01020 __FILE__, __LINE__);
01021 return BPM_FAILURE;
01022 }
01023 else
01024 {
01025 size_t i, j;
01026
01027
01028
01029 for (i = 0; i < N; i++)
01030 {
01031 double Aii = gsl_matrix_get (A, i, i);
01032 gsl_vector_set (diag, i, Aii);
01033 }
01034
01035
01036
01037 for (i = 0; i < N - 1; i++)
01038 {
01039 double Aij = gsl_matrix_get (A, i, i+1);
01040 gsl_vector_set (superdiag, i, Aij);
01041 }
01042
01043
01044
01045 gsl_matrix_set_identity (V);
01046
01047 for (i = N - 1; i > 0 && i--;)
01048 {
01049
01050 gsl_vector_const_view r = gsl_matrix_const_row (A, i);
01051 gsl_vector_const_view h =
01052 gsl_vector_const_subvector (&r.vector, i + 1, N - (i+1));
01053
01054 double ti = gsl_vector_get (tau_V, i);
01055
01056 gsl_matrix_view m =
01057 gsl_matrix_submatrix (V, i + 1, i + 1, N-(i+1), N-(i+1));
01058
01059 gsl_linalg_householder_hm (ti, &h.vector, &m.matrix);
01060 }
01061
01062
01063
01064 gsl_matrix_set_identity (U);
01065
01066 for (j = N; j > 0 && j--;)
01067 {
01068
01069 gsl_vector_const_view c = gsl_matrix_const_column (A, j);
01070 gsl_vector_const_view h = gsl_vector_const_subvector (&c.vector, j, M - j);
01071 double tj = gsl_vector_get (tau_U, j);
01072
01073 gsl_matrix_view m =
01074 gsl_matrix_submatrix (U, j, j, M-j, N-j);
01075
01076 gsl_linalg_householder_hm (tj, &h.vector, &m.matrix);
01077 }
01078
01079 return BPM_SUCCESS;
01080 }
01081 }
01082
01083 int gsl_linalg_bidiag_unpack2 (gsl_matrix * A, gsl_vector * tau_U, gsl_vector * tau_V, gsl_matrix * V)
01084 {
01085
01086 const size_t M = A->size1;
01087 const size_t N = A->size2;
01088
01089 const size_t K = GSL_MIN(M, N);
01090
01091 if (M < N)
01092 {
01093 bpm_error("matrix A must have M >= N in gsl_linalg_bidiag_unpack2(...)",
01094 __FILE__, __LINE__);
01095 return BPM_FAILURE;
01096 }
01097 else if (tau_U->size != K)
01098 {
01099 bpm_error("size of tau must be MIN(M,N) in gsl_linalg_bidiag_unpack2(...)",
01100 __FILE__, __LINE__);
01101 return BPM_FAILURE;
01102 }
01103 else if (tau_V->size + 1 != K)
01104 {
01105 bpm_error("size of tau must be MIN(M,N) - 1 in gsl_linalg_bidiag_unpack2(...)",
01106 __FILE__, __LINE__);
01107 return BPM_FAILURE;
01108 }
01109 else if (V->size1 != N || V->size2 != N)
01110 {
01111 bpm_error("size of V must be N x N in gsl_linalg_bidiag_unpack2(...)",
01112 __FILE__, __LINE__);
01113 return BPM_FAILURE;
01114 }
01115 else
01116 {
01117 size_t i, j;
01118
01119
01120
01121 gsl_matrix_set_identity (V);
01122
01123 for (i = N - 1; i > 0 && i--;)
01124 {
01125
01126 gsl_vector_const_view r = gsl_matrix_const_row (A, i);
01127 gsl_vector_const_view h =
01128 gsl_vector_const_subvector (&r.vector, i + 1, N - (i+1));
01129
01130 double ti = gsl_vector_get (tau_V, i);
01131
01132 gsl_matrix_view m =
01133 gsl_matrix_submatrix (V, i + 1, i + 1, N-(i+1), N-(i+1));
01134
01135 gsl_linalg_householder_hm (ti, &h.vector, &m.matrix);
01136 }
01137
01138
01139
01140 for (i = 0; i < N - 1; i++)
01141 {
01142 double Aij = gsl_matrix_get (A, i, i+1);
01143 gsl_vector_set (tau_V, i, Aij);
01144 }
01145
01146
01147
01148
01149 for (j = N; j > 0 && j--;)
01150 {
01151
01152 double tj = gsl_vector_get (tau_U, j);
01153 double Ajj = gsl_matrix_get (A, j, j);
01154 gsl_matrix_view m = gsl_matrix_submatrix (A, j, j, M-j, N-j);
01155
01156 gsl_vector_set (tau_U, j, Ajj);
01157 gsl_linalg_householder_hm1 (tj, &m.matrix);
01158 }
01159
01160 return BPM_SUCCESS;
01161 }
01162 }
01163
01164 int gsl_linalg_SV_decomp (gsl_matrix * A, gsl_matrix * V, gsl_vector * S,
01165 gsl_vector * work) {
01166
01167 size_t a, b, i, j;
01168
01169 const size_t M = A->size1;
01170 const size_t N = A->size2;
01171 const size_t K = GSL_MIN (M, N);
01172
01173 if (M < N)
01174 {
01175 bpm_error( "svd of MxN matrix, M<N, is not implemented in gsl_linalg_SV_solve(...)",
01176 __FILE__, __LINE__);
01177 }
01178 else if (V->size1 != N)
01179 {
01180 bpm_error( "square matrix V must match second dimension of matrix A in gsl_linalg_SV_solve(...)",
01181 __FILE__, __LINE__);
01182 }
01183 else if (V->size1 != V->size2)
01184 {
01185 bpm_error( "matrix V must be square in gsl_linalg_SV_solve(...)",
01186 __FILE__, __LINE__);
01187 }
01188 else if (S->size != N)
01189 {
01190 bpm_error( "length of vector S must match second dimension of matrix A in gsl_linalg_SV_solve(...)",
01191 __FILE__, __LINE__);
01192 }
01193 else if (work->size != N)
01194 {
01195 bpm_error( "length of workspace must match second dimension of matrix A in gsl_linalg_SV_solve(...)",
01196 __FILE__, __LINE__);
01197 }
01198
01199
01200
01201 if (N == 1)
01202 {
01203 gsl_vector_view column = gsl_matrix_column (A, 0);
01204 double norm = gsl_blas_dnrm2 (&column.vector);
01205
01206 gsl_vector_set (S, 0, norm);
01207 gsl_matrix_set (V, 0, 0, 1.0);
01208
01209 if (norm != 0.0)
01210 {
01211 gsl_blas_dscal (1.0/norm, &column.vector);
01212 }
01213
01214 return BPM_SUCCESS;
01215 }
01216
01217 {
01218 gsl_vector_view f = gsl_vector_subvector (work, 0, K - 1);
01219
01220
01221
01222 gsl_linalg_bidiag_decomp (A, S, &f.vector);
01223 gsl_linalg_bidiag_unpack2 (A, S, &f.vector, V);
01224
01225
01226 chop_small_elements (S, &f.vector);
01227
01228
01229
01230 b = N - 1;
01231
01232 while (b > 0)
01233 {
01234 double fbm1 = gsl_vector_get (&f.vector, b - 1);
01235
01236 if (fbm1 == 0.0 || gsl_isnan (fbm1))
01237 {
01238 b--;
01239 continue;
01240 }
01241
01242
01243
01244
01245 a = b - 1;
01246
01247 while (a > 0)
01248 {
01249 double fam1 = gsl_vector_get (&f.vector, a - 1);
01250
01251 if (fam1 == 0.0 || gsl_isnan (fam1))
01252 {
01253 break;
01254 }
01255
01256 a--;
01257
01258 }
01259
01260 {
01261 const size_t n_block = b - a + 1;
01262
01263 gsl_vector_view S_block = gsl_vector_subvector (S, a, n_block);
01264 gsl_vector_view f_block = gsl_vector_subvector (&f.vector, a, n_block - 1);
01265
01266 gsl_matrix_view U_block =
01267 gsl_matrix_submatrix (A, 0, a, A->size1, n_block);
01268 gsl_matrix_view V_block =
01269 gsl_matrix_submatrix (V, 0, a, V->size1, n_block);
01270
01271 qrstep (&S_block.vector, &f_block.vector, &U_block.matrix, &V_block.matrix);
01272
01273
01274 chop_small_elements (&S_block.vector, &f_block.vector);
01275 }
01276 }
01277 }
01278
01279
01280 for (j = 0; j < K; j++)
01281 {
01282 double Sj = gsl_vector_get (S, j);
01283
01284 if (Sj < 0.0)
01285 {
01286 for (i = 0; i < N; i++)
01287 {
01288 double Vij = gsl_matrix_get (V, i, j);
01289
01290 gsl_matrix_set (V, i, j, -Vij);
01291 }
01292
01293 gsl_vector_set (S, j, -Sj);
01294 }
01295 }
01296
01297
01298
01299 for (i = 0; i < K; i++)
01300 {
01301 double S_max = gsl_vector_get (S, i);
01302 size_t i_max = i;
01303
01304 for (j = i + 1; j < K; j++)
01305 {
01306 double Sj = gsl_vector_get (S, j);
01307
01308 if (Sj > S_max)
01309 {
01310 S_max = Sj;
01311 i_max = j;
01312 }
01313 }
01314
01315 if (i_max != i)
01316 {
01317
01318 gsl_vector_swap_elements (S, i, i_max);
01319
01320
01321 gsl_matrix_swap_columns (A, i, i_max);
01322 gsl_matrix_swap_columns (V, i, i_max);
01323 }
01324 }
01325
01326 return BPM_SUCCESS;
01327 }
01328