slalsa.c
Go to the documentation of this file.
00001 /* slalsa.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 real c_b7 = 1.f;
00019 static real c_b8 = 0.f;
00020 static integer c__2 = 2;
00021 
00022 /* Subroutine */ int slalsa_(integer *icompq, integer *smlsiz, integer *n, 
00023         integer *nrhs, real *b, integer *ldb, real *bx, integer *ldbx, real *
00024         u, integer *ldu, real *vt, integer *k, real *difl, real *difr, real *
00025         z__, real *poles, integer *givptr, integer *givcol, integer *ldgcol, 
00026         integer *perm, real *givnum, real *c__, real *s, real *work, integer *
00027         iwork, integer *info)
00028 {
00029     /* System generated locals */
00030     integer givcol_dim1, givcol_offset, perm_dim1, perm_offset, b_dim1, 
00031             b_offset, bx_dim1, bx_offset, difl_dim1, difl_offset, difr_dim1, 
00032             difr_offset, givnum_dim1, givnum_offset, poles_dim1, poles_offset,
00033              u_dim1, u_offset, vt_dim1, vt_offset, z_dim1, z_offset, i__1, 
00034             i__2;
00035 
00036     /* Builtin functions */
00037     integer pow_ii(integer *, integer *);
00038 
00039     /* Local variables */
00040     integer i__, j, i1, ic, lf, nd, ll, nl, nr, im1, nlf, nrf, lvl, ndb1, 
00041             nlp1, lvl2, nrp1, nlvl, sqre, inode, ndiml;
00042     extern /* Subroutine */ int sgemm_(char *, char *, integer *, integer *, 
00043             integer *, real *, real *, integer *, real *, integer *, real *, 
00044             real *, integer *);
00045     integer ndimr;
00046     extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, 
00047             integer *), slals0_(integer *, integer *, integer *, integer *, 
00048             integer *, real *, integer *, real *, integer *, integer *, 
00049             integer *, integer *, integer *, real *, integer *, real *, real *
00050 , real *, real *, integer *, real *, real *, real *, integer *), 
00051             xerbla_(char *, integer *), slasdt_(integer *, integer *, 
00052             integer *, integer *, integer *, integer *, integer *);
00053 
00054 
00055 /*  -- LAPACK routine (version 3.2) -- */
00056 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00057 /*     November 2006 */
00058 
00059 /*     .. Scalar Arguments .. */
00060 /*     .. */
00061 /*     .. Array Arguments .. */
00062 /*     .. */
00063 
00064 /*  Purpose */
00065 /*  ======= */
00066 
00067 /*  SLALSA is an itermediate step in solving the least squares problem */
00068 /*  by computing the SVD of the coefficient matrix in compact form (The */
00069 /*  singular vectors are computed as products of simple orthorgonal */
00070 /*  matrices.). */
00071 
00072 /*  If ICOMPQ = 0, SLALSA applies the inverse of the left singular vector */
00073 /*  matrix of an upper bidiagonal matrix to the right hand side; and if */
00074 /*  ICOMPQ = 1, SLALSA applies the right singular vector matrix to the */
00075 /*  right hand side. The singular vector matrices were generated in */
00076 /*  compact form by SLALSA. */
00077 
00078 /*  Arguments */
00079 /*  ========= */
00080 
00081 
00082 /*  ICOMPQ (input) INTEGER */
00083 /*         Specifies whether the left or the right singular vector */
00084 /*         matrix is involved. */
00085 /*         = 0: Left singular vector matrix */
00086 /*         = 1: Right singular vector matrix */
00087 
00088 /*  SMLSIZ (input) INTEGER */
00089 /*         The maximum size of the subproblems at the bottom of the */
00090 /*         computation tree. */
00091 
00092 /*  N      (input) INTEGER */
00093 /*         The row and column dimensions of the upper bidiagonal matrix. */
00094 
00095 /*  NRHS   (input) INTEGER */
00096 /*         The number of columns of B and BX. NRHS must be at least 1. */
00097 
00098 /*  B      (input/output) REAL array, dimension ( LDB, NRHS ) */
00099 /*         On input, B contains the right hand sides of the least */
00100 /*         squares problem in rows 1 through M. */
00101 /*         On output, B contains the solution X in rows 1 through N. */
00102 
00103 /*  LDB    (input) INTEGER */
00104 /*         The leading dimension of B in the calling subprogram. */
00105 /*         LDB must be at least max(1,MAX( M, N ) ). */
00106 
00107 /*  BX     (output) REAL array, dimension ( LDBX, NRHS ) */
00108 /*         On exit, the result of applying the left or right singular */
00109 /*         vector matrix to B. */
00110 
00111 /*  LDBX   (input) INTEGER */
00112 /*         The leading dimension of BX. */
00113 
00114 /*  U      (input) REAL array, dimension ( LDU, SMLSIZ ). */
00115 /*         On entry, U contains the left singular vector matrices of all */
00116 /*         subproblems at the bottom level. */
00117 
00118 /*  LDU    (input) INTEGER, LDU = > N. */
00119 /*         The leading dimension of arrays U, VT, DIFL, DIFR, */
00120 /*         POLES, GIVNUM, and Z. */
00121 
00122 /*  VT     (input) REAL array, dimension ( LDU, SMLSIZ+1 ). */
00123 /*         On entry, VT' contains the right singular vector matrices of */
00124 /*         all subproblems at the bottom level. */
00125 
00126 /*  K      (input) INTEGER array, dimension ( N ). */
00127 
00128 /*  DIFL   (input) REAL array, dimension ( LDU, NLVL ). */
00129 /*         where NLVL = INT(log_2 (N/(SMLSIZ+1))) + 1. */
00130 
00131 /*  DIFR   (input) REAL array, dimension ( LDU, 2 * NLVL ). */
00132 /*         On entry, DIFL(*, I) and DIFR(*, 2 * I -1) record */
00133 /*         distances between singular values on the I-th level and */
00134 /*         singular values on the (I -1)-th level, and DIFR(*, 2 * I) */
00135 /*         record the normalizing factors of the right singular vectors */
00136 /*         matrices of subproblems on I-th level. */
00137 
00138 /*  Z      (input) REAL array, dimension ( LDU, NLVL ). */
00139 /*         On entry, Z(1, I) contains the components of the deflation- */
00140 /*         adjusted updating row vector for subproblems on the I-th */
00141 /*         level. */
00142 
00143 /*  POLES  (input) REAL array, dimension ( LDU, 2 * NLVL ). */
00144 /*         On entry, POLES(*, 2 * I -1: 2 * I) contains the new and old */
00145 /*         singular values involved in the secular equations on the I-th */
00146 /*         level. */
00147 
00148 /*  GIVPTR (input) INTEGER array, dimension ( N ). */
00149 /*         On entry, GIVPTR( I ) records the number of Givens */
00150 /*         rotations performed on the I-th problem on the computation */
00151 /*         tree. */
00152 
00153 /*  GIVCOL (input) INTEGER array, dimension ( LDGCOL, 2 * NLVL ). */
00154 /*         On entry, for each I, GIVCOL(*, 2 * I - 1: 2 * I) records the */
00155 /*         locations of Givens rotations performed on the I-th level on */
00156 /*         the computation tree. */
00157 
00158 /*  LDGCOL (input) INTEGER, LDGCOL = > N. */
00159 /*         The leading dimension of arrays GIVCOL and PERM. */
00160 
00161 /*  PERM   (input) INTEGER array, dimension ( LDGCOL, NLVL ). */
00162 /*         On entry, PERM(*, I) records permutations done on the I-th */
00163 /*         level of the computation tree. */
00164 
00165 /*  GIVNUM (input) REAL array, dimension ( LDU, 2 * NLVL ). */
00166 /*         On entry, GIVNUM(*, 2 *I -1 : 2 * I) records the C- and S- */
00167 /*         values of Givens rotations performed on the I-th level on the */
00168 /*         computation tree. */
00169 
00170 /*  C      (input) REAL array, dimension ( N ). */
00171 /*         On entry, if the I-th subproblem is not square, */
00172 /*         C( I ) contains the C-value of a Givens rotation related to */
00173 /*         the right null space of the I-th subproblem. */
00174 
00175 /*  S      (input) REAL array, dimension ( N ). */
00176 /*         On entry, if the I-th subproblem is not square, */
00177 /*         S( I ) contains the S-value of a Givens rotation related to */
00178 /*         the right null space of the I-th subproblem. */
00179 
00180 /*  WORK   (workspace) REAL array. */
00181 /*         The dimension must be at least N. */
00182 
00183 /*  IWORK  (workspace) INTEGER array. */
00184 /*         The dimension must be at least 3 * N */
00185 
00186 /*  INFO   (output) INTEGER */
00187 /*          = 0:  successful exit. */
00188 /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
00189 
00190 /*  Further Details */
00191 /*  =============== */
00192 
00193 /*  Based on contributions by */
00194 /*     Ming Gu and Ren-Cang Li, Computer Science Division, University of */
00195 /*       California at Berkeley, USA */
00196 /*     Osni Marques, LBNL/NERSC, USA */
00197 
00198 /*  ===================================================================== */
00199 
00200 /*     .. Parameters .. */
00201 /*     .. */
00202 /*     .. Local Scalars .. */
00203 /*     .. */
00204 /*     .. External Subroutines .. */
00205 /*     .. */
00206 /*     .. Executable Statements .. */
00207 
00208 /*     Test the input parameters. */
00209 
00210     /* Parameter adjustments */
00211     b_dim1 = *ldb;
00212     b_offset = 1 + b_dim1;
00213     b -= b_offset;
00214     bx_dim1 = *ldbx;
00215     bx_offset = 1 + bx_dim1;
00216     bx -= bx_offset;
00217     givnum_dim1 = *ldu;
00218     givnum_offset = 1 + givnum_dim1;
00219     givnum -= givnum_offset;
00220     poles_dim1 = *ldu;
00221     poles_offset = 1 + poles_dim1;
00222     poles -= poles_offset;
00223     z_dim1 = *ldu;
00224     z_offset = 1 + z_dim1;
00225     z__ -= z_offset;
00226     difr_dim1 = *ldu;
00227     difr_offset = 1 + difr_dim1;
00228     difr -= difr_offset;
00229     difl_dim1 = *ldu;
00230     difl_offset = 1 + difl_dim1;
00231     difl -= difl_offset;
00232     vt_dim1 = *ldu;
00233     vt_offset = 1 + vt_dim1;
00234     vt -= vt_offset;
00235     u_dim1 = *ldu;
00236     u_offset = 1 + u_dim1;
00237     u -= u_offset;
00238     --k;
00239     --givptr;
00240     perm_dim1 = *ldgcol;
00241     perm_offset = 1 + perm_dim1;
00242     perm -= perm_offset;
00243     givcol_dim1 = *ldgcol;
00244     givcol_offset = 1 + givcol_dim1;
00245     givcol -= givcol_offset;
00246     --c__;
00247     --s;
00248     --work;
00249     --iwork;
00250 
00251     /* Function Body */
00252     *info = 0;
00253 
00254     if (*icompq < 0 || *icompq > 1) {
00255         *info = -1;
00256     } else if (*smlsiz < 3) {
00257         *info = -2;
00258     } else if (*n < *smlsiz) {
00259         *info = -3;
00260     } else if (*nrhs < 1) {
00261         *info = -4;
00262     } else if (*ldb < *n) {
00263         *info = -6;
00264     } else if (*ldbx < *n) {
00265         *info = -8;
00266     } else if (*ldu < *n) {
00267         *info = -10;
00268     } else if (*ldgcol < *n) {
00269         *info = -19;
00270     }
00271     if (*info != 0) {
00272         i__1 = -(*info);
00273         xerbla_("SLALSA", &i__1);
00274         return 0;
00275     }
00276 
00277 /*     Book-keeping and  setting up the computation tree. */
00278 
00279     inode = 1;
00280     ndiml = inode + *n;
00281     ndimr = ndiml + *n;
00282 
00283     slasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr], 
00284             smlsiz);
00285 
00286 /*     The following code applies back the left singular vector factors. */
00287 /*     For applying back the right singular vector factors, go to 50. */
00288 
00289     if (*icompq == 1) {
00290         goto L50;
00291     }
00292 
00293 /*     The nodes on the bottom level of the tree were solved */
00294 /*     by SLASDQ. The corresponding left and right singular vector */
00295 /*     matrices are in explicit form. First apply back the left */
00296 /*     singular vector matrices. */
00297 
00298     ndb1 = (nd + 1) / 2;
00299     i__1 = nd;
00300     for (i__ = ndb1; i__ <= i__1; ++i__) {
00301 
00302 /*        IC : center row of each node */
00303 /*        NL : number of rows of left  subproblem */
00304 /*        NR : number of rows of right subproblem */
00305 /*        NLF: starting row of the left   subproblem */
00306 /*        NRF: starting row of the right  subproblem */
00307 
00308         i1 = i__ - 1;
00309         ic = iwork[inode + i1];
00310         nl = iwork[ndiml + i1];
00311         nr = iwork[ndimr + i1];
00312         nlf = ic - nl;
00313         nrf = ic + 1;
00314         sgemm_("T", "N", &nl, nrhs, &nl, &c_b7, &u[nlf + u_dim1], ldu, &b[nlf 
00315                 + b_dim1], ldb, &c_b8, &bx[nlf + bx_dim1], ldbx);
00316         sgemm_("T", "N", &nr, nrhs, &nr, &c_b7, &u[nrf + u_dim1], ldu, &b[nrf 
00317                 + b_dim1], ldb, &c_b8, &bx[nrf + bx_dim1], ldbx);
00318 /* L10: */
00319     }
00320 
00321 /*     Next copy the rows of B that correspond to unchanged rows */
00322 /*     in the bidiagonal matrix to BX. */
00323 
00324     i__1 = nd;
00325     for (i__ = 1; i__ <= i__1; ++i__) {
00326         ic = iwork[inode + i__ - 1];
00327         scopy_(nrhs, &b[ic + b_dim1], ldb, &bx[ic + bx_dim1], ldbx);
00328 /* L20: */
00329     }
00330 
00331 /*     Finally go through the left singular vector matrices of all */
00332 /*     the other subproblems bottom-up on the tree. */
00333 
00334     j = pow_ii(&c__2, &nlvl);
00335     sqre = 0;
00336 
00337     for (lvl = nlvl; lvl >= 1; --lvl) {
00338         lvl2 = (lvl << 1) - 1;
00339 
00340 /*        find the first node LF and last node LL on */
00341 /*        the current level LVL */
00342 
00343         if (lvl == 1) {
00344             lf = 1;
00345             ll = 1;
00346         } else {
00347             i__1 = lvl - 1;
00348             lf = pow_ii(&c__2, &i__1);
00349             ll = (lf << 1) - 1;
00350         }
00351         i__1 = ll;
00352         for (i__ = lf; i__ <= i__1; ++i__) {
00353             im1 = i__ - 1;
00354             ic = iwork[inode + im1];
00355             nl = iwork[ndiml + im1];
00356             nr = iwork[ndimr + im1];
00357             nlf = ic - nl;
00358             nrf = ic + 1;
00359             --j;
00360             slals0_(icompq, &nl, &nr, &sqre, nrhs, &bx[nlf + bx_dim1], ldbx, &
00361                     b[nlf + b_dim1], ldb, &perm[nlf + lvl * perm_dim1], &
00362                     givptr[j], &givcol[nlf + lvl2 * givcol_dim1], ldgcol, &
00363                     givnum[nlf + lvl2 * givnum_dim1], ldu, &poles[nlf + lvl2 *
00364                      poles_dim1], &difl[nlf + lvl * difl_dim1], &difr[nlf + 
00365                     lvl2 * difr_dim1], &z__[nlf + lvl * z_dim1], &k[j], &c__[
00366                     j], &s[j], &work[1], info);
00367 /* L30: */
00368         }
00369 /* L40: */
00370     }
00371     goto L90;
00372 
00373 /*     ICOMPQ = 1: applying back the right singular vector factors. */
00374 
00375 L50:
00376 
00377 /*     First now go through the right singular vector matrices of all */
00378 /*     the tree nodes top-down. */
00379 
00380     j = 0;
00381     i__1 = nlvl;
00382     for (lvl = 1; lvl <= i__1; ++lvl) {
00383         lvl2 = (lvl << 1) - 1;
00384 
00385 /*        Find the first node LF and last node LL on */
00386 /*        the current level LVL. */
00387 
00388         if (lvl == 1) {
00389             lf = 1;
00390             ll = 1;
00391         } else {
00392             i__2 = lvl - 1;
00393             lf = pow_ii(&c__2, &i__2);
00394             ll = (lf << 1) - 1;
00395         }
00396         i__2 = lf;
00397         for (i__ = ll; i__ >= i__2; --i__) {
00398             im1 = i__ - 1;
00399             ic = iwork[inode + im1];
00400             nl = iwork[ndiml + im1];
00401             nr = iwork[ndimr + im1];
00402             nlf = ic - nl;
00403             nrf = ic + 1;
00404             if (i__ == ll) {
00405                 sqre = 0;
00406             } else {
00407                 sqre = 1;
00408             }
00409             ++j;
00410             slals0_(icompq, &nl, &nr, &sqre, nrhs, &b[nlf + b_dim1], ldb, &bx[
00411                     nlf + bx_dim1], ldbx, &perm[nlf + lvl * perm_dim1], &
00412                     givptr[j], &givcol[nlf + lvl2 * givcol_dim1], ldgcol, &
00413                     givnum[nlf + lvl2 * givnum_dim1], ldu, &poles[nlf + lvl2 *
00414                      poles_dim1], &difl[nlf + lvl * difl_dim1], &difr[nlf + 
00415                     lvl2 * difr_dim1], &z__[nlf + lvl * z_dim1], &k[j], &c__[
00416                     j], &s[j], &work[1], info);
00417 /* L60: */
00418         }
00419 /* L70: */
00420     }
00421 
00422 /*     The nodes on the bottom level of the tree were solved */
00423 /*     by SLASDQ. The corresponding right singular vector */
00424 /*     matrices are in explicit form. Apply them back. */
00425 
00426     ndb1 = (nd + 1) / 2;
00427     i__1 = nd;
00428     for (i__ = ndb1; i__ <= i__1; ++i__) {
00429         i1 = i__ - 1;
00430         ic = iwork[inode + i1];
00431         nl = iwork[ndiml + i1];
00432         nr = iwork[ndimr + i1];
00433         nlp1 = nl + 1;
00434         if (i__ == nd) {
00435             nrp1 = nr;
00436         } else {
00437             nrp1 = nr + 1;
00438         }
00439         nlf = ic - nl;
00440         nrf = ic + 1;
00441         sgemm_("T", "N", &nlp1, nrhs, &nlp1, &c_b7, &vt[nlf + vt_dim1], ldu, &
00442                 b[nlf + b_dim1], ldb, &c_b8, &bx[nlf + bx_dim1], ldbx);
00443         sgemm_("T", "N", &nrp1, nrhs, &nrp1, &c_b7, &vt[nrf + vt_dim1], ldu, &
00444                 b[nrf + b_dim1], ldb, &c_b8, &bx[nrf + bx_dim1], ldbx);
00445 /* L80: */
00446     }
00447 
00448 L90:
00449 
00450     return 0;
00451 
00452 /*     End of SLALSA */
00453 
00454 } /* slalsa_ */


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