dlasd0.c
Go to the documentation of this file.
00001 /* dlasd0.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__0 = 0;
00019 static integer c__2 = 2;
00020 
00021 /* Subroutine */ int dlasd0_(integer *n, integer *sqre, doublereal *d__, 
00022         doublereal *e, doublereal *u, integer *ldu, doublereal *vt, integer *
00023         ldvt, integer *smlsiz, integer *iwork, doublereal *work, integer *
00024         info)
00025 {
00026     /* System generated locals */
00027     integer u_dim1, u_offset, vt_dim1, vt_offset, i__1, i__2;
00028 
00029     /* Builtin functions */
00030     integer pow_ii(integer *, integer *);
00031 
00032     /* Local variables */
00033     integer i__, j, m, i1, ic, lf, nd, ll, nl, nr, im1, ncc, nlf, nrf, iwk, 
00034             lvl, ndb1, nlp1, nrp1;
00035     doublereal beta;
00036     integer idxq, nlvl;
00037     doublereal alpha;
00038     integer inode, ndiml, idxqc, ndimr, itemp, sqrei;
00039     extern /* Subroutine */ int dlasd1_(integer *, integer *, integer *, 
00040             doublereal *, doublereal *, doublereal *, doublereal *, integer *, 
00041              doublereal *, integer *, integer *, integer *, doublereal *, 
00042             integer *), dlasdq_(char *, integer *, integer *, integer *, 
00043             integer *, integer *, doublereal *, doublereal *, doublereal *, 
00044             integer *, doublereal *, integer *, doublereal *, integer *, 
00045             doublereal *, integer *), dlasdt_(integer *, integer *, 
00046             integer *, integer *, integer *, integer *, integer *), xerbla_(
00047             char *, integer *);
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 /*  Using a divide and conquer approach, DLASD0 computes the singular */
00063 /*  value decomposition (SVD) of a real upper bidiagonal N-by-M */
00064 /*  matrix B with diagonal D and offdiagonal E, where M = N + SQRE. */
00065 /*  The algorithm computes orthogonal matrices U and VT such that */
00066 /*  B = U * S * VT. The singular values S are overwritten on D. */
00067 
00068 /*  A related subroutine, DLASDA, computes only the singular values, */
00069 /*  and optionally, the singular vectors in compact form. */
00070 
00071 /*  Arguments */
00072 /*  ========= */
00073 
00074 /*  N      (input) INTEGER */
00075 /*         On entry, the row dimension of the upper bidiagonal matrix. */
00076 /*         This is also the dimension of the main diagonal array D. */
00077 
00078 /*  SQRE   (input) INTEGER */
00079 /*         Specifies the column dimension of the bidiagonal matrix. */
00080 /*         = 0: The bidiagonal matrix has column dimension M = N; */
00081 /*         = 1: The bidiagonal matrix has column dimension M = N+1; */
00082 
00083 /*  D      (input/output) DOUBLE PRECISION array, dimension (N) */
00084 /*         On entry D contains the main diagonal of the bidiagonal */
00085 /*         matrix. */
00086 /*         On exit D, if INFO = 0, contains its singular values. */
00087 
00088 /*  E      (input) DOUBLE PRECISION array, dimension (M-1) */
00089 /*         Contains the subdiagonal entries of the bidiagonal matrix. */
00090 /*         On exit, E has been destroyed. */
00091 
00092 /*  U      (output) DOUBLE PRECISION array, dimension at least (LDQ, N) */
00093 /*         On exit, U contains the left singular vectors. */
00094 
00095 /*  LDU    (input) INTEGER */
00096 /*         On entry, leading dimension of U. */
00097 
00098 /*  VT     (output) DOUBLE PRECISION array, dimension at least (LDVT, M) */
00099 /*         On exit, VT' contains the right singular vectors. */
00100 
00101 /*  LDVT   (input) INTEGER */
00102 /*         On entry, leading dimension of VT. */
00103 
00104 /*  SMLSIZ (input) INTEGER */
00105 /*         On entry, maximum size of the subproblems at the */
00106 /*         bottom of the computation tree. */
00107 
00108 /*  IWORK  (workspace) INTEGER work array. */
00109 /*         Dimension must be at least (8 * N) */
00110 
00111 /*  WORK   (workspace) DOUBLE PRECISION work array. */
00112 /*         Dimension must be at least (3 * M**2 + 2 * M) */
00113 
00114 /*  INFO   (output) INTEGER */
00115 /*          = 0:  successful exit. */
00116 /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
00117 /*          > 0:  if INFO = 1, an singular value did not converge */
00118 
00119 /*  Further Details */
00120 /*  =============== */
00121 
00122 /*  Based on contributions by */
00123 /*     Ming Gu and Huan Ren, Computer Science Division, University of */
00124 /*     California at Berkeley, USA */
00125 
00126 /*  ===================================================================== */
00127 
00128 /*     .. Local Scalars .. */
00129 /*     .. */
00130 /*     .. External Subroutines .. */
00131 /*     .. */
00132 /*     .. Executable Statements .. */
00133 
00134 /*     Test the input parameters. */
00135 
00136     /* Parameter adjustments */
00137     --d__;
00138     --e;
00139     u_dim1 = *ldu;
00140     u_offset = 1 + u_dim1;
00141     u -= u_offset;
00142     vt_dim1 = *ldvt;
00143     vt_offset = 1 + vt_dim1;
00144     vt -= vt_offset;
00145     --iwork;
00146     --work;
00147 
00148     /* Function Body */
00149     *info = 0;
00150 
00151     if (*n < 0) {
00152         *info = -1;
00153     } else if (*sqre < 0 || *sqre > 1) {
00154         *info = -2;
00155     }
00156 
00157     m = *n + *sqre;
00158 
00159     if (*ldu < *n) {
00160         *info = -6;
00161     } else if (*ldvt < m) {
00162         *info = -8;
00163     } else if (*smlsiz < 3) {
00164         *info = -9;
00165     }
00166     if (*info != 0) {
00167         i__1 = -(*info);
00168         xerbla_("DLASD0", &i__1);
00169         return 0;
00170     }
00171 
00172 /*     If the input matrix is too small, call DLASDQ to find the SVD. */
00173 
00174     if (*n <= *smlsiz) {
00175         dlasdq_("U", sqre, n, &m, n, &c__0, &d__[1], &e[1], &vt[vt_offset], 
00176                 ldvt, &u[u_offset], ldu, &u[u_offset], ldu, &work[1], info);
00177         return 0;
00178     }
00179 
00180 /*     Set up the computation tree. */
00181 
00182     inode = 1;
00183     ndiml = inode + *n;
00184     ndimr = ndiml + *n;
00185     idxq = ndimr + *n;
00186     iwk = idxq + *n;
00187     dlasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr], 
00188             smlsiz);
00189 
00190 /*     For the nodes on bottom level of the tree, solve */
00191 /*     their subproblems by DLASDQ. */
00192 
00193     ndb1 = (nd + 1) / 2;
00194     ncc = 0;
00195     i__1 = nd;
00196     for (i__ = ndb1; i__ <= i__1; ++i__) {
00197 
00198 /*     IC : center row of each node */
00199 /*     NL : number of rows of left  subproblem */
00200 /*     NR : number of rows of right subproblem */
00201 /*     NLF: starting row of the left   subproblem */
00202 /*     NRF: starting row of the right  subproblem */
00203 
00204         i1 = i__ - 1;
00205         ic = iwork[inode + i1];
00206         nl = iwork[ndiml + i1];
00207         nlp1 = nl + 1;
00208         nr = iwork[ndimr + i1];
00209         nrp1 = nr + 1;
00210         nlf = ic - nl;
00211         nrf = ic + 1;
00212         sqrei = 1;
00213         dlasdq_("U", &sqrei, &nl, &nlp1, &nl, &ncc, &d__[nlf], &e[nlf], &vt[
00214                 nlf + nlf * vt_dim1], ldvt, &u[nlf + nlf * u_dim1], ldu, &u[
00215                 nlf + nlf * u_dim1], ldu, &work[1], info);
00216         if (*info != 0) {
00217             return 0;
00218         }
00219         itemp = idxq + nlf - 2;
00220         i__2 = nl;
00221         for (j = 1; j <= i__2; ++j) {
00222             iwork[itemp + j] = j;
00223 /* L10: */
00224         }
00225         if (i__ == nd) {
00226             sqrei = *sqre;
00227         } else {
00228             sqrei = 1;
00229         }
00230         nrp1 = nr + sqrei;
00231         dlasdq_("U", &sqrei, &nr, &nrp1, &nr, &ncc, &d__[nrf], &e[nrf], &vt[
00232                 nrf + nrf * vt_dim1], ldvt, &u[nrf + nrf * u_dim1], ldu, &u[
00233                 nrf + nrf * u_dim1], ldu, &work[1], info);
00234         if (*info != 0) {
00235             return 0;
00236         }
00237         itemp = idxq + ic;
00238         i__2 = nr;
00239         for (j = 1; j <= i__2; ++j) {
00240             iwork[itemp + j - 1] = j;
00241 /* L20: */
00242         }
00243 /* L30: */
00244     }
00245 
00246 /*     Now conquer each subproblem bottom-up. */
00247 
00248     for (lvl = nlvl; lvl >= 1; --lvl) {
00249 
00250 /*        Find the first node LF and last node LL on the */
00251 /*        current level LVL. */
00252 
00253         if (lvl == 1) {
00254             lf = 1;
00255             ll = 1;
00256         } else {
00257             i__1 = lvl - 1;
00258             lf = pow_ii(&c__2, &i__1);
00259             ll = (lf << 1) - 1;
00260         }
00261         i__1 = ll;
00262         for (i__ = lf; i__ <= i__1; ++i__) {
00263             im1 = i__ - 1;
00264             ic = iwork[inode + im1];
00265             nl = iwork[ndiml + im1];
00266             nr = iwork[ndimr + im1];
00267             nlf = ic - nl;
00268             if (*sqre == 0 && i__ == ll) {
00269                 sqrei = *sqre;
00270             } else {
00271                 sqrei = 1;
00272             }
00273             idxqc = idxq + nlf - 1;
00274             alpha = d__[ic];
00275             beta = e[ic];
00276             dlasd1_(&nl, &nr, &sqrei, &d__[nlf], &alpha, &beta, &u[nlf + nlf *
00277                      u_dim1], ldu, &vt[nlf + nlf * vt_dim1], ldvt, &iwork[
00278                     idxqc], &iwork[iwk], &work[1], info);
00279             if (*info != 0) {
00280                 return 0;
00281             }
00282 /* L40: */
00283         }
00284 /* L50: */
00285     }
00286 
00287     return 0;
00288 
00289 /*     End of DLASD0 */
00290 
00291 } /* dlasd0_ */


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