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


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