dlasd7.c
Go to the documentation of this file.
00001 /* dlasd7.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Table of constant values */
00017 
00018 static integer c__1 = 1;
00019 
00020 /* Subroutine */ int dlasd7_(integer *icompq, integer *nl, integer *nr, 
00021         integer *sqre, integer *k, doublereal *d__, doublereal *z__, 
00022         doublereal *zw, doublereal *vf, doublereal *vfw, doublereal *vl, 
00023         doublereal *vlw, doublereal *alpha, doublereal *beta, doublereal *
00024         dsigma, integer *idx, integer *idxp, integer *idxq, integer *perm, 
00025         integer *givptr, integer *givcol, integer *ldgcol, doublereal *givnum, 
00026          integer *ldgnum, doublereal *c__, doublereal *s, integer *info)
00027 {
00028     /* System generated locals */
00029     integer givcol_dim1, givcol_offset, givnum_dim1, givnum_offset, i__1;
00030     doublereal d__1, d__2;
00031 
00032     /* Local variables */
00033     integer i__, j, m, n, k2;
00034     doublereal z1;
00035     integer jp;
00036     doublereal eps, tau, tol;
00037     integer nlp1, nlp2, idxi, idxj;
00038     extern /* Subroutine */ int drot_(integer *, doublereal *, integer *, 
00039             doublereal *, integer *, doublereal *, doublereal *);
00040     integer idxjp;
00041     extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, 
00042             doublereal *, integer *);
00043     integer jprev;
00044     extern doublereal dlapy2_(doublereal *, doublereal *), dlamch_(char *);
00045     extern /* Subroutine */ int dlamrg_(integer *, integer *, doublereal *, 
00046             integer *, integer *, integer *), xerbla_(char *, integer *);
00047     doublereal hlftol;
00048 
00049 
00050 /*  -- LAPACK auxiliary routine (version 3.2) -- */
00051 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00052 /*     November 2006 */
00053 
00054 /*     .. Scalar Arguments .. */
00055 /*     .. */
00056 /*     .. Array Arguments .. */
00057 /*     .. */
00058 
00059 /*  Purpose */
00060 /*  ======= */
00061 
00062 /*  DLASD7 merges the two sets of singular values together into a single */
00063 /*  sorted set. Then it tries to deflate the size of the problem. There */
00064 /*  are two ways in which deflation can occur:  when two or more singular */
00065 /*  values are close together or if there is a tiny entry in the Z */
00066 /*  vector. For each such occurrence the order of the related */
00067 /*  secular equation problem is reduced by one. */
00068 
00069 /*  DLASD7 is called from DLASD6. */
00070 
00071 /*  Arguments */
00072 /*  ========= */
00073 
00074 /*  ICOMPQ  (input) INTEGER */
00075 /*          Specifies whether singular vectors are to be computed */
00076 /*          in compact form, as follows: */
00077 /*          = 0: Compute singular values only. */
00078 /*          = 1: Compute singular vectors of upper */
00079 /*               bidiagonal matrix in compact form. */
00080 
00081 /*  NL     (input) INTEGER */
00082 /*         The row dimension of the upper block. NL >= 1. */
00083 
00084 /*  NR     (input) INTEGER */
00085 /*         The row dimension of the lower block. NR >= 1. */
00086 
00087 /*  SQRE   (input) INTEGER */
00088 /*         = 0: the lower block is an NR-by-NR square matrix. */
00089 /*         = 1: the lower block is an NR-by-(NR+1) rectangular matrix. */
00090 
00091 /*         The bidiagonal matrix has */
00092 /*         N = NL + NR + 1 rows and */
00093 /*         M = N + SQRE >= N columns. */
00094 
00095 /*  K      (output) INTEGER */
00096 /*         Contains the dimension of the non-deflated matrix, this is */
00097 /*         the order of the related secular equation. 1 <= K <=N. */
00098 
00099 /*  D      (input/output) DOUBLE PRECISION array, dimension ( N ) */
00100 /*         On entry D contains the singular values of the two submatrices */
00101 /*         to be combined. On exit D contains the trailing (N-K) updated */
00102 /*         singular values (those which were deflated) sorted into */
00103 /*         increasing order. */
00104 
00105 /*  Z      (output) DOUBLE PRECISION array, dimension ( M ) */
00106 /*         On exit Z contains the updating row vector in the secular */
00107 /*         equation. */
00108 
00109 /*  ZW     (workspace) DOUBLE PRECISION array, dimension ( M ) */
00110 /*         Workspace for Z. */
00111 
00112 /*  VF     (input/output) DOUBLE PRECISION array, dimension ( M ) */
00113 /*         On entry, VF(1:NL+1) contains the first components of all */
00114 /*         right singular vectors of the upper block; and VF(NL+2:M) */
00115 /*         contains the first components of all right singular vectors */
00116 /*         of the lower block. On exit, VF contains the first components */
00117 /*         of all right singular vectors of the bidiagonal matrix. */
00118 
00119 /*  VFW    (workspace) DOUBLE PRECISION array, dimension ( M ) */
00120 /*         Workspace for VF. */
00121 
00122 /*  VL     (input/output) DOUBLE PRECISION array, dimension ( M ) */
00123 /*         On entry, VL(1:NL+1) contains the  last components of all */
00124 /*         right singular vectors of the upper block; and VL(NL+2:M) */
00125 /*         contains the last components of all right singular vectors */
00126 /*         of the lower block. On exit, VL contains the last components */
00127 /*         of all right singular vectors of the bidiagonal matrix. */
00128 
00129 /*  VLW    (workspace) DOUBLE PRECISION array, dimension ( M ) */
00130 /*         Workspace for VL. */
00131 
00132 /*  ALPHA  (input) DOUBLE PRECISION */
00133 /*         Contains the diagonal element associated with the added row. */
00134 
00135 /*  BETA   (input) DOUBLE PRECISION */
00136 /*         Contains the off-diagonal element associated with the added */
00137 /*         row. */
00138 
00139 /*  DSIGMA (output) DOUBLE PRECISION array, dimension ( N ) */
00140 /*         Contains a copy of the diagonal elements (K-1 singular values */
00141 /*         and one zero) in the secular equation. */
00142 
00143 /*  IDX    (workspace) INTEGER array, dimension ( N ) */
00144 /*         This will contain the permutation used to sort the contents of */
00145 /*         D into ascending order. */
00146 
00147 /*  IDXP   (workspace) INTEGER array, dimension ( N ) */
00148 /*         This will contain the permutation used to place deflated */
00149 /*         values of D at the end of the array. On output IDXP(2:K) */
00150 /*         points to the nondeflated D-values and IDXP(K+1:N) */
00151 /*         points to the deflated singular values. */
00152 
00153 /*  IDXQ   (input) INTEGER array, dimension ( N ) */
00154 /*         This contains the permutation which separately sorts the two */
00155 /*         sub-problems in D into ascending order.  Note that entries in */
00156 /*         the first half of this permutation must first be moved one */
00157 /*         position backward; and entries in the second half */
00158 /*         must first have NL+1 added to their values. */
00159 
00160 /*  PERM   (output) INTEGER array, dimension ( N ) */
00161 /*         The permutations (from deflation and sorting) to be applied */
00162 /*         to each singular block. Not referenced if ICOMPQ = 0. */
00163 
00164 /*  GIVPTR (output) INTEGER */
00165 /*         The number of Givens rotations which took place in this */
00166 /*         subproblem. Not referenced if ICOMPQ = 0. */
00167 
00168 /*  GIVCOL (output) INTEGER array, dimension ( LDGCOL, 2 ) */
00169 /*         Each pair of numbers indicates a pair of columns to take place */
00170 /*         in a Givens rotation. Not referenced if ICOMPQ = 0. */
00171 
00172 /*  LDGCOL (input) INTEGER */
00173 /*         The leading dimension of GIVCOL, must be at least N. */
00174 
00175 /*  GIVNUM (output) DOUBLE PRECISION array, dimension ( LDGNUM, 2 ) */
00176 /*         Each number indicates the C or S value to be used in the */
00177 /*         corresponding Givens rotation. Not referenced if ICOMPQ = 0. */
00178 
00179 /*  LDGNUM (input) INTEGER */
00180 /*         The leading dimension of GIVNUM, must be at least N. */
00181 
00182 /*  C      (output) DOUBLE PRECISION */
00183 /*         C contains garbage if SQRE =0 and the C-value of a Givens */
00184 /*         rotation related to the right null space if SQRE = 1. */
00185 
00186 /*  S      (output) DOUBLE PRECISION */
00187 /*         S contains garbage if SQRE =0 and the S-value of a Givens */
00188 /*         rotation related to the right null space if SQRE = 1. */
00189 
00190 /*  INFO   (output) INTEGER */
00191 /*         = 0:  successful exit. */
00192 /*         < 0:  if INFO = -i, the i-th argument had an illegal value. */
00193 
00194 /*  Further Details */
00195 /*  =============== */
00196 
00197 /*  Based on contributions by */
00198 /*     Ming Gu and Huan Ren, Computer Science Division, University of */
00199 /*     California at Berkeley, USA */
00200 
00201 /*  ===================================================================== */
00202 
00203 /*     .. Parameters .. */
00204 /*     .. */
00205 /*     .. Local Scalars .. */
00206 
00207 /*     .. */
00208 /*     .. External Subroutines .. */
00209 /*     .. */
00210 /*     .. External Functions .. */
00211 /*     .. */
00212 /*     .. Intrinsic Functions .. */
00213 /*     .. */
00214 /*     .. Executable Statements .. */
00215 
00216 /*     Test the input parameters. */
00217 
00218     /* Parameter adjustments */
00219     --d__;
00220     --z__;
00221     --zw;
00222     --vf;
00223     --vfw;
00224     --vl;
00225     --vlw;
00226     --dsigma;
00227     --idx;
00228     --idxp;
00229     --idxq;
00230     --perm;
00231     givcol_dim1 = *ldgcol;
00232     givcol_offset = 1 + givcol_dim1;
00233     givcol -= givcol_offset;
00234     givnum_dim1 = *ldgnum;
00235     givnum_offset = 1 + givnum_dim1;
00236     givnum -= givnum_offset;
00237 
00238     /* Function Body */
00239     *info = 0;
00240     n = *nl + *nr + 1;
00241     m = n + *sqre;
00242 
00243     if (*icompq < 0 || *icompq > 1) {
00244         *info = -1;
00245     } else if (*nl < 1) {
00246         *info = -2;
00247     } else if (*nr < 1) {
00248         *info = -3;
00249     } else if (*sqre < 0 || *sqre > 1) {
00250         *info = -4;
00251     } else if (*ldgcol < n) {
00252         *info = -22;
00253     } else if (*ldgnum < n) {
00254         *info = -24;
00255     }
00256     if (*info != 0) {
00257         i__1 = -(*info);
00258         xerbla_("DLASD7", &i__1);
00259         return 0;
00260     }
00261 
00262     nlp1 = *nl + 1;
00263     nlp2 = *nl + 2;
00264     if (*icompq == 1) {
00265         *givptr = 0;
00266     }
00267 
00268 /*     Generate the first part of the vector Z and move the singular */
00269 /*     values in the first part of D one position backward. */
00270 
00271     z1 = *alpha * vl[nlp1];
00272     vl[nlp1] = 0.;
00273     tau = vf[nlp1];
00274     for (i__ = *nl; i__ >= 1; --i__) {
00275         z__[i__ + 1] = *alpha * vl[i__];
00276         vl[i__] = 0.;
00277         vf[i__ + 1] = vf[i__];
00278         d__[i__ + 1] = d__[i__];
00279         idxq[i__ + 1] = idxq[i__] + 1;
00280 /* L10: */
00281     }
00282     vf[1] = tau;
00283 
00284 /*     Generate the second part of the vector Z. */
00285 
00286     i__1 = m;
00287     for (i__ = nlp2; i__ <= i__1; ++i__) {
00288         z__[i__] = *beta * vf[i__];
00289         vf[i__] = 0.;
00290 /* L20: */
00291     }
00292 
00293 /*     Sort the singular values into increasing order */
00294 
00295     i__1 = n;
00296     for (i__ = nlp2; i__ <= i__1; ++i__) {
00297         idxq[i__] += nlp1;
00298 /* L30: */
00299     }
00300 
00301 /*     DSIGMA, IDXC, IDXC, and ZW are used as storage space. */
00302 
00303     i__1 = n;
00304     for (i__ = 2; i__ <= i__1; ++i__) {
00305         dsigma[i__] = d__[idxq[i__]];
00306         zw[i__] = z__[idxq[i__]];
00307         vfw[i__] = vf[idxq[i__]];
00308         vlw[i__] = vl[idxq[i__]];
00309 /* L40: */
00310     }
00311 
00312     dlamrg_(nl, nr, &dsigma[2], &c__1, &c__1, &idx[2]);
00313 
00314     i__1 = n;
00315     for (i__ = 2; i__ <= i__1; ++i__) {
00316         idxi = idx[i__] + 1;
00317         d__[i__] = dsigma[idxi];
00318         z__[i__] = zw[idxi];
00319         vf[i__] = vfw[idxi];
00320         vl[i__] = vlw[idxi];
00321 /* L50: */
00322     }
00323 
00324 /*     Calculate the allowable deflation tolerence */
00325 
00326     eps = dlamch_("Epsilon");
00327 /* Computing MAX */
00328     d__1 = abs(*alpha), d__2 = abs(*beta);
00329     tol = max(d__1,d__2);
00330 /* Computing MAX */
00331     d__2 = (d__1 = d__[n], abs(d__1));
00332     tol = eps * 64. * max(d__2,tol);
00333 
00334 /*     There are 2 kinds of deflation -- first a value in the z-vector */
00335 /*     is small, second two (or more) singular values are very close */
00336 /*     together (their difference is small). */
00337 
00338 /*     If the value in the z-vector is small, we simply permute the */
00339 /*     array so that the corresponding singular value is moved to the */
00340 /*     end. */
00341 
00342 /*     If two values in the D-vector are close, we perform a two-sided */
00343 /*     rotation designed to make one of the corresponding z-vector */
00344 /*     entries zero, and then permute the array so that the deflated */
00345 /*     singular value is moved to the end. */
00346 
00347 /*     If there are multiple singular values then the problem deflates. */
00348 /*     Here the number of equal singular values are found.  As each equal */
00349 /*     singular value is found, an elementary reflector is computed to */
00350 /*     rotate the corresponding singular subspace so that the */
00351 /*     corresponding components of Z are zero in this new basis. */
00352 
00353     *k = 1;
00354     k2 = n + 1;
00355     i__1 = n;
00356     for (j = 2; j <= i__1; ++j) {
00357         if ((d__1 = z__[j], abs(d__1)) <= tol) {
00358 
00359 /*           Deflate due to small z component. */
00360 
00361             --k2;
00362             idxp[k2] = j;
00363             if (j == n) {
00364                 goto L100;
00365             }
00366         } else {
00367             jprev = j;
00368             goto L70;
00369         }
00370 /* L60: */
00371     }
00372 L70:
00373     j = jprev;
00374 L80:
00375     ++j;
00376     if (j > n) {
00377         goto L90;
00378     }
00379     if ((d__1 = z__[j], abs(d__1)) <= tol) {
00380 
00381 /*        Deflate due to small z component. */
00382 
00383         --k2;
00384         idxp[k2] = j;
00385     } else {
00386 
00387 /*        Check if singular values are close enough to allow deflation. */
00388 
00389         if ((d__1 = d__[j] - d__[jprev], abs(d__1)) <= tol) {
00390 
00391 /*           Deflation is possible. */
00392 
00393             *s = z__[jprev];
00394             *c__ = z__[j];
00395 
00396 /*           Find sqrt(a**2+b**2) without overflow or */
00397 /*           destructive underflow. */
00398 
00399             tau = dlapy2_(c__, s);
00400             z__[j] = tau;
00401             z__[jprev] = 0.;
00402             *c__ /= tau;
00403             *s = -(*s) / tau;
00404 
00405 /*           Record the appropriate Givens rotation */
00406 
00407             if (*icompq == 1) {
00408                 ++(*givptr);
00409                 idxjp = idxq[idx[jprev] + 1];
00410                 idxj = idxq[idx[j] + 1];
00411                 if (idxjp <= nlp1) {
00412                     --idxjp;
00413                 }
00414                 if (idxj <= nlp1) {
00415                     --idxj;
00416                 }
00417                 givcol[*givptr + (givcol_dim1 << 1)] = idxjp;
00418                 givcol[*givptr + givcol_dim1] = idxj;
00419                 givnum[*givptr + (givnum_dim1 << 1)] = *c__;
00420                 givnum[*givptr + givnum_dim1] = *s;
00421             }
00422             drot_(&c__1, &vf[jprev], &c__1, &vf[j], &c__1, c__, s);
00423             drot_(&c__1, &vl[jprev], &c__1, &vl[j], &c__1, c__, s);
00424             --k2;
00425             idxp[k2] = jprev;
00426             jprev = j;
00427         } else {
00428             ++(*k);
00429             zw[*k] = z__[jprev];
00430             dsigma[*k] = d__[jprev];
00431             idxp[*k] = jprev;
00432             jprev = j;
00433         }
00434     }
00435     goto L80;
00436 L90:
00437 
00438 /*     Record the last singular value. */
00439 
00440     ++(*k);
00441     zw[*k] = z__[jprev];
00442     dsigma[*k] = d__[jprev];
00443     idxp[*k] = jprev;
00444 
00445 L100:
00446 
00447 /*     Sort the singular values into DSIGMA. The singular values which */
00448 /*     were not deflated go into the first K slots of DSIGMA, except */
00449 /*     that DSIGMA(1) is treated separately. */
00450 
00451     i__1 = n;
00452     for (j = 2; j <= i__1; ++j) {
00453         jp = idxp[j];
00454         dsigma[j] = d__[jp];
00455         vfw[j] = vf[jp];
00456         vlw[j] = vl[jp];
00457 /* L110: */
00458     }
00459     if (*icompq == 1) {
00460         i__1 = n;
00461         for (j = 2; j <= i__1; ++j) {
00462             jp = idxp[j];
00463             perm[j] = idxq[idx[jp] + 1];
00464             if (perm[j] <= nlp1) {
00465                 --perm[j];
00466             }
00467 /* L120: */
00468         }
00469     }
00470 
00471 /*     The deflated singular values go back into the last N - K slots of */
00472 /*     D. */
00473 
00474     i__1 = n - *k;
00475     dcopy_(&i__1, &dsigma[*k + 1], &c__1, &d__[*k + 1], &c__1);
00476 
00477 /*     Determine DSIGMA(1), DSIGMA(2), Z(1), VF(1), VL(1), VF(M), and */
00478 /*     VL(M). */
00479 
00480     dsigma[1] = 0.;
00481     hlftol = tol / 2.;
00482     if (abs(dsigma[2]) <= hlftol) {
00483         dsigma[2] = hlftol;
00484     }
00485     if (m > n) {
00486         z__[1] = dlapy2_(&z1, &z__[m]);
00487         if (z__[1] <= tol) {
00488             *c__ = 1.;
00489             *s = 0.;
00490             z__[1] = tol;
00491         } else {
00492             *c__ = z1 / z__[1];
00493             *s = -z__[m] / z__[1];
00494         }
00495         drot_(&c__1, &vf[m], &c__1, &vf[1], &c__1, c__, s);
00496         drot_(&c__1, &vl[m], &c__1, &vl[1], &c__1, c__, s);
00497     } else {
00498         if (abs(z1) <= tol) {
00499             z__[1] = tol;
00500         } else {
00501             z__[1] = z1;
00502         }
00503     }
00504 
00505 /*     Restore Z, VF, and VL. */
00506 
00507     i__1 = *k - 1;
00508     dcopy_(&i__1, &zw[2], &c__1, &z__[2], &c__1);
00509     i__1 = n - 1;
00510     dcopy_(&i__1, &vfw[2], &c__1, &vf[2], &c__1);
00511     i__1 = n - 1;
00512     dcopy_(&i__1, &vlw[2], &c__1, &vl[2], &c__1);
00513 
00514     return 0;
00515 
00516 /*     End of DLASD7 */
00517 
00518 } /* dlasd7_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:46