00001 /* dlasdq.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 dlasdq_(char *uplo, integer *sqre, integer *n, integer * 00021 ncvt, integer *nru, integer *ncc, doublereal *d__, doublereal *e, 00022 doublereal *vt, integer *ldvt, doublereal *u, integer *ldu, 00023 doublereal *c__, integer *ldc, doublereal *work, integer *info) 00024 { 00025 /* System generated locals */ 00026 integer c_dim1, c_offset, u_dim1, u_offset, vt_dim1, vt_offset, i__1, 00027 i__2; 00028 00029 /* Local variables */ 00030 integer i__, j; 00031 doublereal r__, cs, sn; 00032 integer np1, isub; 00033 doublereal smin; 00034 integer sqre1; 00035 extern logical lsame_(char *, char *); 00036 extern /* Subroutine */ int dlasr_(char *, char *, char *, integer *, 00037 integer *, doublereal *, doublereal *, doublereal *, integer *), dswap_(integer *, doublereal *, integer * 00038 , doublereal *, integer *); 00039 integer iuplo; 00040 extern /* Subroutine */ int dlartg_(doublereal *, doublereal *, 00041 doublereal *, doublereal *, doublereal *), xerbla_(char *, 00042 integer *), dbdsqr_(char *, integer *, integer *, integer 00043 *, integer *, doublereal *, doublereal *, doublereal *, integer *, 00044 doublereal *, integer *, doublereal *, integer *, doublereal *, 00045 integer *); 00046 logical rotate; 00047 00048 00049 /* -- LAPACK auxiliary routine (version 3.2) -- */ 00050 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ 00051 /* November 2006 */ 00052 00053 /* .. Scalar Arguments .. */ 00054 /* .. */ 00055 /* .. Array Arguments .. */ 00056 /* .. */ 00057 00058 /* Purpose */ 00059 /* ======= */ 00060 00061 /* DLASDQ computes the singular value decomposition (SVD) of a real */ 00062 /* (upper or lower) bidiagonal matrix with diagonal D and offdiagonal */ 00063 /* E, accumulating the transformations if desired. Letting B denote */ 00064 /* the input bidiagonal matrix, the algorithm computes orthogonal */ 00065 /* matrices Q and P such that B = Q * S * P' (P' denotes the transpose */ 00066 /* of P). The singular values S are overwritten on D. */ 00067 00068 /* The input matrix U is changed to U * Q if desired. */ 00069 /* The input matrix VT is changed to P' * VT if desired. */ 00070 /* The input matrix C is changed to Q' * C if desired. */ 00071 00072 /* See "Computing Small Singular Values of Bidiagonal Matrices With */ 00073 /* Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, */ 00074 /* LAPACK Working Note #3, for a detailed description of the algorithm. */ 00075 00076 /* Arguments */ 00077 /* ========= */ 00078 00079 /* UPLO (input) CHARACTER*1 */ 00080 /* On entry, UPLO specifies whether the input bidiagonal matrix */ 00081 /* is upper or lower bidiagonal, and wether it is square are */ 00082 /* not. */ 00083 /* UPLO = 'U' or 'u' B is upper bidiagonal. */ 00084 /* UPLO = 'L' or 'l' B is lower bidiagonal. */ 00085 00086 /* SQRE (input) INTEGER */ 00087 /* = 0: then the input matrix is N-by-N. */ 00088 /* = 1: then the input matrix is N-by-(N+1) if UPLU = 'U' and */ 00089 /* (N+1)-by-N if UPLU = 'L'. */ 00090 00091 /* The bidiagonal matrix has */ 00092 /* N = NL + NR + 1 rows and */ 00093 /* M = N + SQRE >= N columns. */ 00094 00095 /* N (input) INTEGER */ 00096 /* On entry, N specifies the number of rows and columns */ 00097 /* in the matrix. N must be at least 0. */ 00098 00099 /* NCVT (input) INTEGER */ 00100 /* On entry, NCVT specifies the number of columns of */ 00101 /* the matrix VT. NCVT must be at least 0. */ 00102 00103 /* NRU (input) INTEGER */ 00104 /* On entry, NRU specifies the number of rows of */ 00105 /* the matrix U. NRU must be at least 0. */ 00106 00107 /* NCC (input) INTEGER */ 00108 /* On entry, NCC specifies the number of columns of */ 00109 /* the matrix C. NCC must be at least 0. */ 00110 00111 /* D (input/output) DOUBLE PRECISION array, dimension (N) */ 00112 /* On entry, D contains the diagonal entries of the */ 00113 /* bidiagonal matrix whose SVD is desired. On normal exit, */ 00114 /* D contains the singular values in ascending order. */ 00115 00116 /* E (input/output) DOUBLE PRECISION array. */ 00117 /* dimension is (N-1) if SQRE = 0 and N if SQRE = 1. */ 00118 /* On entry, the entries of E contain the offdiagonal entries */ 00119 /* of the bidiagonal matrix whose SVD is desired. On normal */ 00120 /* exit, E will contain 0. If the algorithm does not converge, */ 00121 /* D and E will contain the diagonal and superdiagonal entries */ 00122 /* of a bidiagonal matrix orthogonally equivalent to the one */ 00123 /* given as input. */ 00124 00125 /* VT (input/output) DOUBLE PRECISION array, dimension (LDVT, NCVT) */ 00126 /* On entry, contains a matrix which on exit has been */ 00127 /* premultiplied by P', dimension N-by-NCVT if SQRE = 0 */ 00128 /* and (N+1)-by-NCVT if SQRE = 1 (not referenced if NCVT=0). */ 00129 00130 /* LDVT (input) INTEGER */ 00131 /* On entry, LDVT specifies the leading dimension of VT as */ 00132 /* declared in the calling (sub) program. LDVT must be at */ 00133 /* least 1. If NCVT is nonzero LDVT must also be at least N. */ 00134 00135 /* U (input/output) DOUBLE PRECISION array, dimension (LDU, N) */ 00136 /* On entry, contains a matrix which on exit has been */ 00137 /* postmultiplied by Q, dimension NRU-by-N if SQRE = 0 */ 00138 /* and NRU-by-(N+1) if SQRE = 1 (not referenced if NRU=0). */ 00139 00140 /* LDU (input) INTEGER */ 00141 /* On entry, LDU specifies the leading dimension of U as */ 00142 /* declared in the calling (sub) program. LDU must be at */ 00143 /* least max( 1, NRU ) . */ 00144 00145 /* C (input/output) DOUBLE PRECISION array, dimension (LDC, NCC) */ 00146 /* On entry, contains an N-by-NCC matrix which on exit */ 00147 /* has been premultiplied by Q' dimension N-by-NCC if SQRE = 0 */ 00148 /* and (N+1)-by-NCC if SQRE = 1 (not referenced if NCC=0). */ 00149 00150 /* LDC (input) INTEGER */ 00151 /* On entry, LDC specifies the leading dimension of C as */ 00152 /* declared in the calling (sub) program. LDC must be at */ 00153 /* least 1. If NCC is nonzero, LDC must also be at least N. */ 00154 00155 /* WORK (workspace) DOUBLE PRECISION array, dimension (4*N) */ 00156 /* Workspace. Only referenced if one of NCVT, NRU, or NCC is */ 00157 /* nonzero, and if N is at least 2. */ 00158 00159 /* INFO (output) INTEGER */ 00160 /* On exit, a value of 0 indicates a successful exit. */ 00161 /* If INFO < 0, argument number -INFO is illegal. */ 00162 /* If INFO > 0, the algorithm did not converge, and INFO */ 00163 /* specifies how many superdiagonals did not converge. */ 00164 00165 /* Further Details */ 00166 /* =============== */ 00167 00168 /* Based on contributions by */ 00169 /* Ming Gu and Huan Ren, Computer Science Division, University of */ 00170 /* California at Berkeley, USA */ 00171 00172 /* ===================================================================== */ 00173 00174 /* .. Parameters .. */ 00175 /* .. */ 00176 /* .. Local Scalars .. */ 00177 /* .. */ 00178 /* .. External Subroutines .. */ 00179 /* .. */ 00180 /* .. External Functions .. */ 00181 /* .. */ 00182 /* .. Intrinsic Functions .. */ 00183 /* .. */ 00184 /* .. Executable Statements .. */ 00185 00186 /* Test the input parameters. */ 00187 00188 /* Parameter adjustments */ 00189 --d__; 00190 --e; 00191 vt_dim1 = *ldvt; 00192 vt_offset = 1 + vt_dim1; 00193 vt -= vt_offset; 00194 u_dim1 = *ldu; 00195 u_offset = 1 + u_dim1; 00196 u -= u_offset; 00197 c_dim1 = *ldc; 00198 c_offset = 1 + c_dim1; 00199 c__ -= c_offset; 00200 --work; 00201 00202 /* Function Body */ 00203 *info = 0; 00204 iuplo = 0; 00205 if (lsame_(uplo, "U")) { 00206 iuplo = 1; 00207 } 00208 if (lsame_(uplo, "L")) { 00209 iuplo = 2; 00210 } 00211 if (iuplo == 0) { 00212 *info = -1; 00213 } else if (*sqre < 0 || *sqre > 1) { 00214 *info = -2; 00215 } else if (*n < 0) { 00216 *info = -3; 00217 } else if (*ncvt < 0) { 00218 *info = -4; 00219 } else if (*nru < 0) { 00220 *info = -5; 00221 } else if (*ncc < 0) { 00222 *info = -6; 00223 } else if (*ncvt == 0 && *ldvt < 1 || *ncvt > 0 && *ldvt < max(1,*n)) { 00224 *info = -10; 00225 } else if (*ldu < max(1,*nru)) { 00226 *info = -12; 00227 } else if (*ncc == 0 && *ldc < 1 || *ncc > 0 && *ldc < max(1,*n)) { 00228 *info = -14; 00229 } 00230 if (*info != 0) { 00231 i__1 = -(*info); 00232 xerbla_("DLASDQ", &i__1); 00233 return 0; 00234 } 00235 if (*n == 0) { 00236 return 0; 00237 } 00238 00239 /* ROTATE is true if any singular vectors desired, false otherwise */ 00240 00241 rotate = *ncvt > 0 || *nru > 0 || *ncc > 0; 00242 np1 = *n + 1; 00243 sqre1 = *sqre; 00244 00245 /* If matrix non-square upper bidiagonal, rotate to be lower */ 00246 /* bidiagonal. The rotations are on the right. */ 00247 00248 if (iuplo == 1 && sqre1 == 1) { 00249 i__1 = *n - 1; 00250 for (i__ = 1; i__ <= i__1; ++i__) { 00251 dlartg_(&d__[i__], &e[i__], &cs, &sn, &r__); 00252 d__[i__] = r__; 00253 e[i__] = sn * d__[i__ + 1]; 00254 d__[i__ + 1] = cs * d__[i__ + 1]; 00255 if (rotate) { 00256 work[i__] = cs; 00257 work[*n + i__] = sn; 00258 } 00259 /* L10: */ 00260 } 00261 dlartg_(&d__[*n], &e[*n], &cs, &sn, &r__); 00262 d__[*n] = r__; 00263 e[*n] = 0.; 00264 if (rotate) { 00265 work[*n] = cs; 00266 work[*n + *n] = sn; 00267 } 00268 iuplo = 2; 00269 sqre1 = 0; 00270 00271 /* Update singular vectors if desired. */ 00272 00273 if (*ncvt > 0) { 00274 dlasr_("L", "V", "F", &np1, ncvt, &work[1], &work[np1], &vt[ 00275 vt_offset], ldvt); 00276 } 00277 } 00278 00279 /* If matrix lower bidiagonal, rotate to be upper bidiagonal */ 00280 /* by applying Givens rotations on the left. */ 00281 00282 if (iuplo == 2) { 00283 i__1 = *n - 1; 00284 for (i__ = 1; i__ <= i__1; ++i__) { 00285 dlartg_(&d__[i__], &e[i__], &cs, &sn, &r__); 00286 d__[i__] = r__; 00287 e[i__] = sn * d__[i__ + 1]; 00288 d__[i__ + 1] = cs * d__[i__ + 1]; 00289 if (rotate) { 00290 work[i__] = cs; 00291 work[*n + i__] = sn; 00292 } 00293 /* L20: */ 00294 } 00295 00296 /* If matrix (N+1)-by-N lower bidiagonal, one additional */ 00297 /* rotation is needed. */ 00298 00299 if (sqre1 == 1) { 00300 dlartg_(&d__[*n], &e[*n], &cs, &sn, &r__); 00301 d__[*n] = r__; 00302 if (rotate) { 00303 work[*n] = cs; 00304 work[*n + *n] = sn; 00305 } 00306 } 00307 00308 /* Update singular vectors if desired. */ 00309 00310 if (*nru > 0) { 00311 if (sqre1 == 0) { 00312 dlasr_("R", "V", "F", nru, n, &work[1], &work[np1], &u[ 00313 u_offset], ldu); 00314 } else { 00315 dlasr_("R", "V", "F", nru, &np1, &work[1], &work[np1], &u[ 00316 u_offset], ldu); 00317 } 00318 } 00319 if (*ncc > 0) { 00320 if (sqre1 == 0) { 00321 dlasr_("L", "V", "F", n, ncc, &work[1], &work[np1], &c__[ 00322 c_offset], ldc); 00323 } else { 00324 dlasr_("L", "V", "F", &np1, ncc, &work[1], &work[np1], &c__[ 00325 c_offset], ldc); 00326 } 00327 } 00328 } 00329 00330 /* Call DBDSQR to compute the SVD of the reduced real */ 00331 /* N-by-N upper bidiagonal matrix. */ 00332 00333 dbdsqr_("U", n, ncvt, nru, ncc, &d__[1], &e[1], &vt[vt_offset], ldvt, &u[ 00334 u_offset], ldu, &c__[c_offset], ldc, &work[1], info); 00335 00336 /* Sort the singular values into ascending order (insertion sort on */ 00337 /* singular values, but only one transposition per singular vector) */ 00338 00339 i__1 = *n; 00340 for (i__ = 1; i__ <= i__1; ++i__) { 00341 00342 /* Scan for smallest D(I). */ 00343 00344 isub = i__; 00345 smin = d__[i__]; 00346 i__2 = *n; 00347 for (j = i__ + 1; j <= i__2; ++j) { 00348 if (d__[j] < smin) { 00349 isub = j; 00350 smin = d__[j]; 00351 } 00352 /* L30: */ 00353 } 00354 if (isub != i__) { 00355 00356 /* Swap singular values and vectors. */ 00357 00358 d__[isub] = d__[i__]; 00359 d__[i__] = smin; 00360 if (*ncvt > 0) { 00361 dswap_(ncvt, &vt[isub + vt_dim1], ldvt, &vt[i__ + vt_dim1], 00362 ldvt); 00363 } 00364 if (*nru > 0) { 00365 dswap_(nru, &u[isub * u_dim1 + 1], &c__1, &u[i__ * u_dim1 + 1] 00366 , &c__1); 00367 } 00368 if (*ncc > 0) { 00369 dswap_(ncc, &c__[isub + c_dim1], ldc, &c__[i__ + c_dim1], ldc) 00370 ; 00371 } 00372 } 00373 /* L40: */ 00374 } 00375 00376 return 0; 00377 00378 /* End of DLASDQ */ 00379 00380 } /* dlasdq_ */