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


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:11