00001 SUBROUTINE SSTEDC( COMPZ, N, D, E, Z, LDZ, WORK, LWORK, IWORK,
00002 $ LIWORK, INFO )
00003
00004
00005
00006
00007
00008
00009
00010 CHARACTER COMPZ
00011 INTEGER INFO, LDZ, LIWORK, LWORK, N
00012
00013
00014 INTEGER IWORK( * )
00015 REAL D( * ), E( * ), WORK( * ), Z( LDZ, * )
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 REAL ZERO, ONE, TWO
00128 PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0, TWO = 2.0E0 )
00129
00130
00131 LOGICAL LQUERY
00132 INTEGER FINISH, I, ICOMPZ, II, J, K, LGN, LIWMIN,
00133 $ LWMIN, M, SMLSIZ, START, STOREZ, STRTRW
00134 REAL EPS, ORGNRM, P, TINY
00135
00136
00137 LOGICAL LSAME
00138 INTEGER ILAENV
00139 REAL SLAMCH, SLANST
00140 EXTERNAL ILAENV, LSAME, SLAMCH, SLANST
00141
00142
00143 EXTERNAL SGEMM, SLACPY, SLAED0, SLASCL, SLASET, SLASRT,
00144 $ SSTEQR, SSTERF, SSWAP, XERBLA
00145
00146
00147 INTRINSIC ABS, INT, LOG, MAX, MOD, REAL, SQRT
00148
00149
00150
00151
00152
00153 INFO = 0
00154 LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )
00155
00156 IF( LSAME( COMPZ, 'N' ) ) THEN
00157 ICOMPZ = 0
00158 ELSE IF( LSAME( COMPZ, 'V' ) ) THEN
00159 ICOMPZ = 1
00160 ELSE IF( LSAME( COMPZ, 'I' ) ) THEN
00161 ICOMPZ = 2
00162 ELSE
00163 ICOMPZ = -1
00164 END IF
00165 IF( ICOMPZ.LT.0 ) THEN
00166 INFO = -1
00167 ELSE IF( N.LT.0 ) THEN
00168 INFO = -2
00169 ELSE IF( ( LDZ.LT.1 ) .OR.
00170 $ ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1, N ) ) ) THEN
00171 INFO = -6
00172 END IF
00173
00174 IF( INFO.EQ.0 ) THEN
00175
00176
00177
00178 SMLSIZ = ILAENV( 9, 'SSTEDC', ' ', 0, 0, 0, 0 )
00179 IF( N.LE.1 .OR. ICOMPZ.EQ.0 ) THEN
00180 LIWMIN = 1
00181 LWMIN = 1
00182 ELSE IF( N.LE.SMLSIZ ) THEN
00183 LIWMIN = 1
00184 LWMIN = 2*( N - 1 )
00185 ELSE
00186 LGN = INT( LOG( REAL( N ) )/LOG( TWO ) )
00187 IF( 2**LGN.LT.N )
00188 $ LGN = LGN + 1
00189 IF( 2**LGN.LT.N )
00190 $ LGN = LGN + 1
00191 IF( ICOMPZ.EQ.1 ) THEN
00192 LWMIN = 1 + 3*N + 2*N*LGN + 3*N**2
00193 LIWMIN = 6 + 6*N + 5*N*LGN
00194 ELSE IF( ICOMPZ.EQ.2 ) THEN
00195 LWMIN = 1 + 4*N + N**2
00196 LIWMIN = 3 + 5*N
00197 END IF
00198 END IF
00199 WORK( 1 ) = LWMIN
00200 IWORK( 1 ) = LIWMIN
00201
00202 IF( LWORK.LT.LWMIN .AND. .NOT. LQUERY ) THEN
00203 INFO = -8
00204 ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT. LQUERY ) THEN
00205 INFO = -10
00206 END IF
00207 END IF
00208
00209 IF( INFO.NE.0 ) THEN
00210 CALL XERBLA( 'SSTEDC', -INFO )
00211 RETURN
00212 ELSE IF (LQUERY) THEN
00213 RETURN
00214 END IF
00215
00216
00217
00218 IF( N.EQ.0 )
00219 $ RETURN
00220 IF( N.EQ.1 ) THEN
00221 IF( ICOMPZ.NE.0 )
00222 $ Z( 1, 1 ) = ONE
00223 RETURN
00224 END IF
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 IF( ICOMPZ.EQ.0 ) THEN
00238 CALL SSTERF( N, D, E, INFO )
00239 GO TO 50
00240 END IF
00241
00242
00243
00244
00245 IF( N.LE.SMLSIZ ) THEN
00246
00247 CALL SSTEQR( COMPZ, N, D, E, Z, LDZ, WORK, INFO )
00248
00249 ELSE
00250
00251
00252
00253
00254 IF( ICOMPZ.EQ.1 ) THEN
00255 STOREZ = 1 + N*N
00256 ELSE
00257 STOREZ = 1
00258 END IF
00259
00260 IF( ICOMPZ.EQ.2 ) THEN
00261 CALL SLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )
00262 END IF
00263
00264
00265
00266 ORGNRM = SLANST( 'M', N, D, E )
00267 IF( ORGNRM.EQ.ZERO )
00268 $ GO TO 50
00269
00270 EPS = SLAMCH( 'Epsilon' )
00271
00272 START = 1
00273
00274
00275
00276 10 CONTINUE
00277 IF( START.LE.N ) THEN
00278
00279
00280
00281
00282
00283
00284
00285 FINISH = START
00286 20 CONTINUE
00287 IF( FINISH.LT.N ) THEN
00288 TINY = EPS*SQRT( ABS( D( FINISH ) ) )*
00289 $ SQRT( ABS( D( FINISH+1 ) ) )
00290 IF( ABS( E( FINISH ) ).GT.TINY ) THEN
00291 FINISH = FINISH + 1
00292 GO TO 20
00293 END IF
00294 END IF
00295
00296
00297
00298 M = FINISH - START + 1
00299 IF( M.EQ.1 ) THEN
00300 START = FINISH + 1
00301 GO TO 10
00302 END IF
00303 IF( M.GT.SMLSIZ ) THEN
00304
00305
00306
00307 ORGNRM = SLANST( 'M', M, D( START ), E( START ) )
00308 CALL SLASCL( 'G', 0, 0, ORGNRM, ONE, M, 1, D( START ), M,
00309 $ INFO )
00310 CALL SLASCL( 'G', 0, 0, ORGNRM, ONE, M-1, 1, E( START ),
00311 $ M-1, INFO )
00312
00313 IF( ICOMPZ.EQ.1 ) THEN
00314 STRTRW = 1
00315 ELSE
00316 STRTRW = START
00317 END IF
00318 CALL SLAED0( ICOMPZ, N, M, D( START ), E( START ),
00319 $ Z( STRTRW, START ), LDZ, WORK( 1 ), N,
00320 $ WORK( STOREZ ), IWORK, INFO )
00321 IF( INFO.NE.0 ) THEN
00322 INFO = ( INFO / ( M+1 )+START-1 )*( N+1 ) +
00323 $ MOD( INFO, ( M+1 ) ) + START - 1
00324 GO TO 50
00325 END IF
00326
00327
00328
00329 CALL SLASCL( 'G', 0, 0, ONE, ORGNRM, M, 1, D( START ), M,
00330 $ INFO )
00331
00332 ELSE
00333 IF( ICOMPZ.EQ.1 ) THEN
00334
00335
00336
00337
00338
00339 CALL SSTEQR( 'I', M, D( START ), E( START ), WORK, M,
00340 $ WORK( M*M+1 ), INFO )
00341 CALL SLACPY( 'A', N, M, Z( 1, START ), LDZ,
00342 $ WORK( STOREZ ), N )
00343 CALL SGEMM( 'N', 'N', N, M, M, ONE,
00344 $ WORK( STOREZ ), N, WORK, M, ZERO,
00345 $ Z( 1, START ), LDZ )
00346 ELSE IF( ICOMPZ.EQ.2 ) THEN
00347 CALL SSTEQR( 'I', M, D( START ), E( START ),
00348 $ Z( START, START ), LDZ, WORK, INFO )
00349 ELSE
00350 CALL SSTERF( M, D( START ), E( START ), INFO )
00351 END IF
00352 IF( INFO.NE.0 ) THEN
00353 INFO = START*( N+1 ) + FINISH
00354 GO TO 50
00355 END IF
00356 END IF
00357
00358 START = FINISH + 1
00359 GO TO 10
00360 END IF
00361
00362
00363
00364
00365
00366
00367
00368 IF( M.NE.N ) THEN
00369 IF( ICOMPZ.EQ.0 ) THEN
00370
00371
00372
00373 CALL SLASRT( 'I', N, D, INFO )
00374
00375 ELSE
00376
00377
00378
00379 DO 40 II = 2, N
00380 I = II - 1
00381 K = I
00382 P = D( I )
00383 DO 30 J = II, N
00384 IF( D( J ).LT.P ) THEN
00385 K = J
00386 P = D( J )
00387 END IF
00388 30 CONTINUE
00389 IF( K.NE.I ) THEN
00390 D( K ) = D( I )
00391 D( I ) = P
00392 CALL SSWAP( N, Z( 1, I ), 1, Z( 1, K ), 1 )
00393 END IF
00394 40 CONTINUE
00395 END IF
00396 END IF
00397 END IF
00398
00399 50 CONTINUE
00400 WORK( 1 ) = LWMIN
00401 IWORK( 1 ) = LIWMIN
00402
00403 RETURN
00404
00405
00406
00407 END