00001 SUBROUTINE DGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
00002 $ WORK, LWORK, IWORK, INFO )
00003
00004
00005
00006
00007
00008
00009
00010 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
00011 DOUBLE PRECISION RCOND
00012
00013
00014 INTEGER IWORK( * )
00015 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 DOUBLE PRECISION ZERO, ONE, TWO
00140 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0 )
00141
00142
00143 LOGICAL LQUERY
00144 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
00145 $ LDWORK, LIWORK, MAXMN, MAXWRK, MINMN, MINWRK,
00146 $ MM, MNTHR, NLVL, NWORK, SMLSIZ, WLALSD
00147 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
00148
00149
00150 EXTERNAL DGEBRD, DGELQF, DGEQRF, DLABAD, DLACPY, DLALSD,
00151 $ DLASCL, DLASET, DORMBR, DORMLQ, DORMQR, XERBLA
00152
00153
00154 INTEGER ILAENV
00155 DOUBLE PRECISION DLAMCH, DLANGE
00156 EXTERNAL ILAENV, DLAMCH, DLANGE
00157
00158
00159 INTRINSIC DBLE, INT, LOG, MAX, MIN
00160
00161
00162
00163
00164
00165 INFO = 0
00166 MINMN = MIN( M, N )
00167 MAXMN = MAX( M, N )
00168 MNTHR = ILAENV( 6, 'DGELSD', ' ', M, N, NRHS, -1 )
00169 LQUERY = ( LWORK.EQ.-1 )
00170 IF( M.LT.0 ) THEN
00171 INFO = -1
00172 ELSE IF( N.LT.0 ) THEN
00173 INFO = -2
00174 ELSE IF( NRHS.LT.0 ) THEN
00175 INFO = -3
00176 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
00177 INFO = -5
00178 ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THEN
00179 INFO = -7
00180 END IF
00181
00182 SMLSIZ = ILAENV( 9, 'DGELSD', ' ', 0, 0, 0, 0 )
00183
00184
00185
00186
00187
00188
00189
00190
00191 MINWRK = 1
00192 LIWORK = 1
00193 MINMN = MAX( 1, MINMN )
00194 NLVL = MAX( INT( LOG( DBLE( MINMN ) / DBLE( SMLSIZ+1 ) ) /
00195 $ LOG( TWO ) ) + 1, 0 )
00196
00197 IF( INFO.EQ.0 ) THEN
00198 MAXWRK = 0
00199 LIWORK = 3*MINMN*NLVL + 11*MINMN
00200 MM = M
00201 IF( M.GE.N .AND. M.GE.MNTHR ) THEN
00202
00203
00204
00205 MM = N
00206 MAXWRK = MAX( MAXWRK, N+N*ILAENV( 1, 'DGEQRF', ' ', M, N,
00207 $ -1, -1 ) )
00208 MAXWRK = MAX( MAXWRK, N+NRHS*
00209 $ ILAENV( 1, 'DORMQR', 'LT', M, NRHS, N, -1 ) )
00210 END IF
00211 IF( M.GE.N ) THEN
00212
00213
00214
00215 MAXWRK = MAX( MAXWRK, 3*N+( MM+N )*
00216 $ ILAENV( 1, 'DGEBRD', ' ', MM, N, -1, -1 ) )
00217 MAXWRK = MAX( MAXWRK, 3*N+NRHS*
00218 $ ILAENV( 1, 'DORMBR', 'QLT', MM, NRHS, N, -1 ) )
00219 MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
00220 $ ILAENV( 1, 'DORMBR', 'PLN', N, NRHS, N, -1 ) )
00221 WLALSD = 9*N+2*N*SMLSIZ+8*N*NLVL+N*NRHS+(SMLSIZ+1)**2
00222 MAXWRK = MAX( MAXWRK, 3*N+WLALSD )
00223 MINWRK = MAX( 3*N+MM, 3*N+NRHS, 3*N+WLALSD )
00224 END IF
00225 IF( N.GT.M ) THEN
00226 WLALSD = 9*M+2*M*SMLSIZ+8*M*NLVL+M*NRHS+(SMLSIZ+1)**2
00227 IF( N.GE.MNTHR ) THEN
00228
00229
00230
00231
00232 MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
00233 MAXWRK = MAX( MAXWRK, M*M+4*M+2*M*
00234 $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00235 MAXWRK = MAX( MAXWRK, M*M+4*M+NRHS*
00236 $ ILAENV( 1, 'DORMBR', 'QLT', M, NRHS, M, -1 ) )
00237 MAXWRK = MAX( MAXWRK, M*M+4*M+( M-1 )*
00238 $ ILAENV( 1, 'DORMBR', 'PLN', M, NRHS, M, -1 ) )
00239 IF( NRHS.GT.1 ) THEN
00240 MAXWRK = MAX( MAXWRK, M*M+M+M*NRHS )
00241 ELSE
00242 MAXWRK = MAX( MAXWRK, M*M+2*M )
00243 END IF
00244 MAXWRK = MAX( MAXWRK, M+NRHS*
00245 $ ILAENV( 1, 'DORMLQ', 'LT', N, NRHS, M, -1 ) )
00246 MAXWRK = MAX( MAXWRK, M*M+4*M+WLALSD )
00247
00248
00249 MAXWRK = MAX( MAXWRK,
00250 $ 4*M+M*M+MAX( M, 2*M-4, NRHS, N-3*M ) )
00251 ELSE
00252
00253
00254
00255 MAXWRK = 3*M + ( N+M )*ILAENV( 1, 'DGEBRD', ' ', M, N,
00256 $ -1, -1 )
00257 MAXWRK = MAX( MAXWRK, 3*M+NRHS*
00258 $ ILAENV( 1, 'DORMBR', 'QLT', M, NRHS, N, -1 ) )
00259 MAXWRK = MAX( MAXWRK, 3*M+M*
00260 $ ILAENV( 1, 'DORMBR', 'PLN', N, NRHS, M, -1 ) )
00261 MAXWRK = MAX( MAXWRK, 3*M+WLALSD )
00262 END IF
00263 MINWRK = MAX( 3*M+NRHS, 3*M+M, 3*M+WLALSD )
00264 END IF
00265 MINWRK = MIN( MINWRK, MAXWRK )
00266 WORK( 1 ) = MAXWRK
00267 IWORK( 1 ) = LIWORK
00268
00269 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00270 INFO = -12
00271 END IF
00272 END IF
00273
00274 IF( INFO.NE.0 ) THEN
00275 CALL XERBLA( 'DGELSD', -INFO )
00276 RETURN
00277 ELSE IF( LQUERY ) THEN
00278 GO TO 10
00279 END IF
00280
00281
00282
00283 IF( M.EQ.0 .OR. N.EQ.0 ) THEN
00284 RANK = 0
00285 RETURN
00286 END IF
00287
00288
00289
00290 EPS = DLAMCH( 'P' )
00291 SFMIN = DLAMCH( 'S' )
00292 SMLNUM = SFMIN / EPS
00293 BIGNUM = ONE / SMLNUM
00294 CALL DLABAD( SMLNUM, BIGNUM )
00295
00296
00297
00298 ANRM = DLANGE( 'M', M, N, A, LDA, WORK )
00299 IASCL = 0
00300 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00301
00302
00303
00304 CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
00305 IASCL = 1
00306 ELSE IF( ANRM.GT.BIGNUM ) THEN
00307
00308
00309
00310 CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
00311 IASCL = 2
00312 ELSE IF( ANRM.EQ.ZERO ) THEN
00313
00314
00315
00316 CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )
00317 CALL DLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 )
00318 RANK = 0
00319 GO TO 10
00320 END IF
00321
00322
00323
00324 BNRM = DLANGE( 'M', M, NRHS, B, LDB, WORK )
00325 IBSCL = 0
00326 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00327
00328
00329
00330 CALL DLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
00331 IBSCL = 1
00332 ELSE IF( BNRM.GT.BIGNUM ) THEN
00333
00334
00335
00336 CALL DLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
00337 IBSCL = 2
00338 END IF
00339
00340
00341
00342 IF( M.LT.N )
00343 $ CALL DLASET( 'F', N-M, NRHS, ZERO, ZERO, B( M+1, 1 ), LDB )
00344
00345
00346
00347 IF( M.GE.N ) THEN
00348
00349
00350
00351 MM = M
00352 IF( M.GE.MNTHR ) THEN
00353
00354
00355
00356 MM = N
00357 ITAU = 1
00358 NWORK = ITAU + N
00359
00360
00361
00362
00363 CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00364 $ LWORK-NWORK+1, INFO )
00365
00366
00367
00368
00369 CALL DORMQR( 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAU ), B,
00370 $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00371
00372
00373
00374 IF( N.GT.1 ) THEN
00375 CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
00376 END IF
00377 END IF
00378
00379 IE = 1
00380 ITAUQ = IE + N
00381 ITAUP = ITAUQ + N
00382 NWORK = ITAUP + N
00383
00384
00385
00386
00387 CALL DGEBRD( MM, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
00388 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
00389 $ INFO )
00390
00391
00392
00393
00394 CALL DORMBR( 'Q', 'L', 'T', MM, NRHS, N, A, LDA, WORK( ITAUQ ),
00395 $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00396
00397
00398
00399 CALL DLALSD( 'U', SMLSIZ, N, NRHS, S, WORK( IE ), B, LDB,
00400 $ RCOND, RANK, WORK( NWORK ), IWORK, INFO )
00401 IF( INFO.NE.0 ) THEN
00402 GO TO 10
00403 END IF
00404
00405
00406
00407 CALL DORMBR( 'P', 'L', 'N', N, NRHS, N, A, LDA, WORK( ITAUP ),
00408 $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00409
00410 ELSE IF( N.GE.MNTHR .AND. LWORK.GE.4*M+M*M+
00411 $ MAX( M, 2*M-4, NRHS, N-3*M, WLALSD ) ) THEN
00412
00413
00414
00415
00416 LDWORK = M
00417 IF( LWORK.GE.MAX( 4*M+M*LDA+MAX( M, 2*M-4, NRHS, N-3*M ),
00418 $ M*LDA+M+M*NRHS, 4*M+M*LDA+WLALSD ) )LDWORK = LDA
00419 ITAU = 1
00420 NWORK = M + 1
00421
00422
00423
00424
00425 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00426 $ LWORK-NWORK+1, INFO )
00427 IL = NWORK
00428
00429
00430
00431 CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK )
00432 CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, WORK( IL+LDWORK ),
00433 $ LDWORK )
00434 IE = IL + LDWORK*M
00435 ITAUQ = IE + M
00436 ITAUP = ITAUQ + M
00437 NWORK = ITAUP + M
00438
00439
00440
00441
00442 CALL DGEBRD( M, M, WORK( IL ), LDWORK, S, WORK( IE ),
00443 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
00444 $ LWORK-NWORK+1, INFO )
00445
00446
00447
00448
00449 CALL DORMBR( 'Q', 'L', 'T', M, NRHS, M, WORK( IL ), LDWORK,
00450 $ WORK( ITAUQ ), B, LDB, WORK( NWORK ),
00451 $ LWORK-NWORK+1, INFO )
00452
00453
00454
00455 CALL DLALSD( 'U', SMLSIZ, M, NRHS, S, WORK( IE ), B, LDB,
00456 $ RCOND, RANK, WORK( NWORK ), IWORK, INFO )
00457 IF( INFO.NE.0 ) THEN
00458 GO TO 10
00459 END IF
00460
00461
00462
00463 CALL DORMBR( 'P', 'L', 'N', M, NRHS, M, WORK( IL ), LDWORK,
00464 $ WORK( ITAUP ), B, LDB, WORK( NWORK ),
00465 $ LWORK-NWORK+1, INFO )
00466
00467
00468
00469 CALL DLASET( 'F', N-M, NRHS, ZERO, ZERO, B( M+1, 1 ), LDB )
00470 NWORK = ITAU + M
00471
00472
00473
00474
00475 CALL DORMLQ( 'L', 'T', N, NRHS, M, A, LDA, WORK( ITAU ), B,
00476 $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00477
00478 ELSE
00479
00480
00481
00482 IE = 1
00483 ITAUQ = IE + M
00484 ITAUP = ITAUQ + M
00485 NWORK = ITAUP + M
00486
00487
00488
00489
00490 CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
00491 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
00492 $ INFO )
00493
00494
00495
00496
00497 CALL DORMBR( 'Q', 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAUQ ),
00498 $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00499
00500
00501
00502 CALL DLALSD( 'L', SMLSIZ, M, NRHS, S, WORK( IE ), B, LDB,
00503 $ RCOND, RANK, WORK( NWORK ), IWORK, INFO )
00504 IF( INFO.NE.0 ) THEN
00505 GO TO 10
00506 END IF
00507
00508
00509
00510 CALL DORMBR( 'P', 'L', 'N', N, NRHS, M, A, LDA, WORK( ITAUP ),
00511 $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00512
00513 END IF
00514
00515
00516
00517 IF( IASCL.EQ.1 ) THEN
00518 CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )
00519 CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
00520 $ INFO )
00521 ELSE IF( IASCL.EQ.2 ) THEN
00522 CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )
00523 CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
00524 $ INFO )
00525 END IF
00526 IF( IBSCL.EQ.1 ) THEN
00527 CALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
00528 ELSE IF( IBSCL.EQ.2 ) THEN
00529 CALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )
00530 END IF
00531
00532 10 CONTINUE
00533 WORK( 1 ) = MAXWRK
00534 IWORK( 1 ) = LIWORK
00535 RETURN
00536
00537
00538
00539 END