00001 SUBROUTINE DBDSQR( UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U,
00002 $ LDU, C, LDC, WORK, INFO )
00003
00004
00005
00006
00007
00008
00009
00010 CHARACTER UPLO
00011 INTEGER INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU
00012
00013
00014 DOUBLE PRECISION C( LDC, * ), D( * ), E( * ), U( LDU, * ),
00015 $ VT( LDVT, * ), 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
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 DOUBLE PRECISION ZERO
00155 PARAMETER ( ZERO = 0.0D0 )
00156 DOUBLE PRECISION ONE
00157 PARAMETER ( ONE = 1.0D0 )
00158 DOUBLE PRECISION NEGONE
00159 PARAMETER ( NEGONE = -1.0D0 )
00160 DOUBLE PRECISION HNDRTH
00161 PARAMETER ( HNDRTH = 0.01D0 )
00162 DOUBLE PRECISION TEN
00163 PARAMETER ( TEN = 10.0D0 )
00164 DOUBLE PRECISION HNDRD
00165 PARAMETER ( HNDRD = 100.0D0 )
00166 DOUBLE PRECISION MEIGTH
00167 PARAMETER ( MEIGTH = -0.125D0 )
00168 INTEGER MAXITR
00169 PARAMETER ( MAXITR = 6 )
00170
00171
00172 LOGICAL LOWER, ROTATE
00173 INTEGER I, IDIR, ISUB, ITER, J, LL, LLL, M, MAXIT, NM1,
00174 $ NM12, NM13, OLDLL, OLDM
00175 DOUBLE PRECISION ABSE, ABSS, COSL, COSR, CS, EPS, F, G, H, MU,
00176 $ OLDCS, OLDSN, R, SHIFT, SIGMN, SIGMX, SINL,
00177 $ SINR, SLL, SMAX, SMIN, SMINL, SMINOA,
00178 $ SN, THRESH, TOL, TOLMUL, UNFL
00179
00180
00181 LOGICAL LSAME
00182 DOUBLE PRECISION DLAMCH
00183 EXTERNAL LSAME, DLAMCH
00184
00185
00186 EXTERNAL DLARTG, DLAS2, DLASQ1, DLASR, DLASV2, DROT,
00187 $ DSCAL, DSWAP, XERBLA
00188
00189
00190 INTRINSIC ABS, DBLE, MAX, MIN, SIGN, SQRT
00191
00192
00193
00194
00195
00196 INFO = 0
00197 LOWER = LSAME( UPLO, 'L' )
00198 IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LOWER ) THEN
00199 INFO = -1
00200 ELSE IF( N.LT.0 ) THEN
00201 INFO = -2
00202 ELSE IF( NCVT.LT.0 ) THEN
00203 INFO = -3
00204 ELSE IF( NRU.LT.0 ) THEN
00205 INFO = -4
00206 ELSE IF( NCC.LT.0 ) THEN
00207 INFO = -5
00208 ELSE IF( ( NCVT.EQ.0 .AND. LDVT.LT.1 ) .OR.
00209 $ ( NCVT.GT.0 .AND. LDVT.LT.MAX( 1, N ) ) ) THEN
00210 INFO = -9
00211 ELSE IF( LDU.LT.MAX( 1, NRU ) ) THEN
00212 INFO = -11
00213 ELSE IF( ( NCC.EQ.0 .AND. LDC.LT.1 ) .OR.
00214 $ ( NCC.GT.0 .AND. LDC.LT.MAX( 1, N ) ) ) THEN
00215 INFO = -13
00216 END IF
00217 IF( INFO.NE.0 ) THEN
00218 CALL XERBLA( 'DBDSQR', -INFO )
00219 RETURN
00220 END IF
00221 IF( N.EQ.0 )
00222 $ RETURN
00223 IF( N.EQ.1 )
00224 $ GO TO 160
00225
00226
00227
00228 ROTATE = ( NCVT.GT.0 ) .OR. ( NRU.GT.0 ) .OR. ( NCC.GT.0 )
00229
00230
00231
00232 IF( .NOT.ROTATE ) THEN
00233 CALL DLASQ1( N, D, E, WORK, INFO )
00234 RETURN
00235 END IF
00236
00237 NM1 = N - 1
00238 NM12 = NM1 + NM1
00239 NM13 = NM12 + NM1
00240 IDIR = 0
00241
00242
00243
00244 EPS = DLAMCH( 'Epsilon' )
00245 UNFL = DLAMCH( 'Safe minimum' )
00246
00247
00248
00249
00250 IF( LOWER ) THEN
00251 DO 10 I = 1, N - 1
00252 CALL DLARTG( D( I ), E( I ), CS, SN, R )
00253 D( I ) = R
00254 E( I ) = SN*D( I+1 )
00255 D( I+1 ) = CS*D( I+1 )
00256 WORK( I ) = CS
00257 WORK( NM1+I ) = SN
00258 10 CONTINUE
00259
00260
00261
00262 IF( NRU.GT.0 )
00263 $ CALL DLASR( 'R', 'V', 'F', NRU, N, WORK( 1 ), WORK( N ), U,
00264 $ LDU )
00265 IF( NCC.GT.0 )
00266 $ CALL DLASR( 'L', 'V', 'F', N, NCC, WORK( 1 ), WORK( N ), C,
00267 $ LDC )
00268 END IF
00269
00270
00271
00272
00273
00274 TOLMUL = MAX( TEN, MIN( HNDRD, EPS**MEIGTH ) )
00275 TOL = TOLMUL*EPS
00276
00277
00278
00279 SMAX = ZERO
00280 DO 20 I = 1, N
00281 SMAX = MAX( SMAX, ABS( D( I ) ) )
00282 20 CONTINUE
00283 DO 30 I = 1, N - 1
00284 SMAX = MAX( SMAX, ABS( E( I ) ) )
00285 30 CONTINUE
00286 SMINL = ZERO
00287 IF( TOL.GE.ZERO ) THEN
00288
00289
00290
00291 SMINOA = ABS( D( 1 ) )
00292 IF( SMINOA.EQ.ZERO )
00293 $ GO TO 50
00294 MU = SMINOA
00295 DO 40 I = 2, N
00296 MU = ABS( D( I ) )*( MU / ( MU+ABS( E( I-1 ) ) ) )
00297 SMINOA = MIN( SMINOA, MU )
00298 IF( SMINOA.EQ.ZERO )
00299 $ GO TO 50
00300 40 CONTINUE
00301 50 CONTINUE
00302 SMINOA = SMINOA / SQRT( DBLE( N ) )
00303 THRESH = MAX( TOL*SMINOA, MAXITR*N*N*UNFL )
00304 ELSE
00305
00306
00307
00308 THRESH = MAX( ABS( TOL )*SMAX, MAXITR*N*N*UNFL )
00309 END IF
00310
00311
00312
00313
00314
00315 MAXIT = MAXITR*N*N
00316 ITER = 0
00317 OLDLL = -1
00318 OLDM = -1
00319
00320
00321
00322 M = N
00323
00324
00325
00326 60 CONTINUE
00327
00328
00329
00330 IF( M.LE.1 )
00331 $ GO TO 160
00332 IF( ITER.GT.MAXIT )
00333 $ GO TO 200
00334
00335
00336
00337 IF( TOL.LT.ZERO .AND. ABS( D( M ) ).LE.THRESH )
00338 $ D( M ) = ZERO
00339 SMAX = ABS( D( M ) )
00340 SMIN = SMAX
00341 DO 70 LLL = 1, M - 1
00342 LL = M - LLL
00343 ABSS = ABS( D( LL ) )
00344 ABSE = ABS( E( LL ) )
00345 IF( TOL.LT.ZERO .AND. ABSS.LE.THRESH )
00346 $ D( LL ) = ZERO
00347 IF( ABSE.LE.THRESH )
00348 $ GO TO 80
00349 SMIN = MIN( SMIN, ABSS )
00350 SMAX = MAX( SMAX, ABSS, ABSE )
00351 70 CONTINUE
00352 LL = 0
00353 GO TO 90
00354 80 CONTINUE
00355 E( LL ) = ZERO
00356
00357
00358
00359 IF( LL.EQ.M-1 ) THEN
00360
00361
00362
00363 M = M - 1
00364 GO TO 60
00365 END IF
00366 90 CONTINUE
00367 LL = LL + 1
00368
00369
00370
00371 IF( LL.EQ.M-1 ) THEN
00372
00373
00374
00375 CALL DLASV2( D( M-1 ), E( M-1 ), D( M ), SIGMN, SIGMX, SINR,
00376 $ COSR, SINL, COSL )
00377 D( M-1 ) = SIGMX
00378 E( M-1 ) = ZERO
00379 D( M ) = SIGMN
00380
00381
00382
00383 IF( NCVT.GT.0 )
00384 $ CALL DROT( NCVT, VT( M-1, 1 ), LDVT, VT( M, 1 ), LDVT, COSR,
00385 $ SINR )
00386 IF( NRU.GT.0 )
00387 $ CALL DROT( NRU, U( 1, M-1 ), 1, U( 1, M ), 1, COSL, SINL )
00388 IF( NCC.GT.0 )
00389 $ CALL DROT( NCC, C( M-1, 1 ), LDC, C( M, 1 ), LDC, COSL,
00390 $ SINL )
00391 M = M - 2
00392 GO TO 60
00393 END IF
00394
00395
00396
00397
00398 IF( LL.GT.OLDM .OR. M.LT.OLDLL ) THEN
00399 IF( ABS( D( LL ) ).GE.ABS( D( M ) ) ) THEN
00400
00401
00402
00403 IDIR = 1
00404 ELSE
00405
00406
00407
00408 IDIR = 2
00409 END IF
00410 END IF
00411
00412
00413
00414 IF( IDIR.EQ.1 ) THEN
00415
00416
00417
00418
00419 IF( ABS( E( M-1 ) ).LE.ABS( TOL )*ABS( D( M ) ) .OR.
00420 $ ( TOL.LT.ZERO .AND. ABS( E( M-1 ) ).LE.THRESH ) ) THEN
00421 E( M-1 ) = ZERO
00422 GO TO 60
00423 END IF
00424
00425 IF( TOL.GE.ZERO ) THEN
00426
00427
00428
00429
00430 MU = ABS( D( LL ) )
00431 SMINL = MU
00432 DO 100 LLL = LL, M - 1
00433 IF( ABS( E( LLL ) ).LE.TOL*MU ) THEN
00434 E( LLL ) = ZERO
00435 GO TO 60
00436 END IF
00437 MU = ABS( D( LLL+1 ) )*( MU / ( MU+ABS( E( LLL ) ) ) )
00438 SMINL = MIN( SMINL, MU )
00439 100 CONTINUE
00440 END IF
00441
00442 ELSE
00443
00444
00445
00446
00447 IF( ABS( E( LL ) ).LE.ABS( TOL )*ABS( D( LL ) ) .OR.
00448 $ ( TOL.LT.ZERO .AND. ABS( E( LL ) ).LE.THRESH ) ) THEN
00449 E( LL ) = ZERO
00450 GO TO 60
00451 END IF
00452
00453 IF( TOL.GE.ZERO ) THEN
00454
00455
00456
00457
00458 MU = ABS( D( M ) )
00459 SMINL = MU
00460 DO 110 LLL = M - 1, LL, -1
00461 IF( ABS( E( LLL ) ).LE.TOL*MU ) THEN
00462 E( LLL ) = ZERO
00463 GO TO 60
00464 END IF
00465 MU = ABS( D( LLL ) )*( MU / ( MU+ABS( E( LLL ) ) ) )
00466 SMINL = MIN( SMINL, MU )
00467 110 CONTINUE
00468 END IF
00469 END IF
00470 OLDLL = LL
00471 OLDM = M
00472
00473
00474
00475
00476 IF( TOL.GE.ZERO .AND. N*TOL*( SMINL / SMAX ).LE.
00477 $ MAX( EPS, HNDRTH*TOL ) ) THEN
00478
00479
00480
00481 SHIFT = ZERO
00482 ELSE
00483
00484
00485
00486 IF( IDIR.EQ.1 ) THEN
00487 SLL = ABS( D( LL ) )
00488 CALL DLAS2( D( M-1 ), E( M-1 ), D( M ), SHIFT, R )
00489 ELSE
00490 SLL = ABS( D( M ) )
00491 CALL DLAS2( D( LL ), E( LL ), D( LL+1 ), SHIFT, R )
00492 END IF
00493
00494
00495
00496 IF( SLL.GT.ZERO ) THEN
00497 IF( ( SHIFT / SLL )**2.LT.EPS )
00498 $ SHIFT = ZERO
00499 END IF
00500 END IF
00501
00502
00503
00504 ITER = ITER + M - LL
00505
00506
00507
00508 IF( SHIFT.EQ.ZERO ) THEN
00509 IF( IDIR.EQ.1 ) THEN
00510
00511
00512
00513
00514 CS = ONE
00515 OLDCS = ONE
00516 DO 120 I = LL, M - 1
00517 CALL DLARTG( D( I )*CS, E( I ), CS, SN, R )
00518 IF( I.GT.LL )
00519 $ E( I-1 ) = OLDSN*R
00520 CALL DLARTG( OLDCS*R, D( I+1 )*SN, OLDCS, OLDSN, D( I ) )
00521 WORK( I-LL+1 ) = CS
00522 WORK( I-LL+1+NM1 ) = SN
00523 WORK( I-LL+1+NM12 ) = OLDCS
00524 WORK( I-LL+1+NM13 ) = OLDSN
00525 120 CONTINUE
00526 H = D( M )*CS
00527 D( M ) = H*OLDCS
00528 E( M-1 ) = H*OLDSN
00529
00530
00531
00532 IF( NCVT.GT.0 )
00533 $ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCVT, WORK( 1 ),
00534 $ WORK( N ), VT( LL, 1 ), LDVT )
00535 IF( NRU.GT.0 )
00536 $ CALL DLASR( 'R', 'V', 'F', NRU, M-LL+1, WORK( NM12+1 ),
00537 $ WORK( NM13+1 ), U( 1, LL ), LDU )
00538 IF( NCC.GT.0 )
00539 $ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCC, WORK( NM12+1 ),
00540 $ WORK( NM13+1 ), C( LL, 1 ), LDC )
00541
00542
00543
00544 IF( ABS( E( M-1 ) ).LE.THRESH )
00545 $ E( M-1 ) = ZERO
00546
00547 ELSE
00548
00549
00550
00551
00552 CS = ONE
00553 OLDCS = ONE
00554 DO 130 I = M, LL + 1, -1
00555 CALL DLARTG( D( I )*CS, E( I-1 ), CS, SN, R )
00556 IF( I.LT.M )
00557 $ E( I ) = OLDSN*R
00558 CALL DLARTG( OLDCS*R, D( I-1 )*SN, OLDCS, OLDSN, D( I ) )
00559 WORK( I-LL ) = CS
00560 WORK( I-LL+NM1 ) = -SN
00561 WORK( I-LL+NM12 ) = OLDCS
00562 WORK( I-LL+NM13 ) = -OLDSN
00563 130 CONTINUE
00564 H = D( LL )*CS
00565 D( LL ) = H*OLDCS
00566 E( LL ) = H*OLDSN
00567
00568
00569
00570 IF( NCVT.GT.0 )
00571 $ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCVT, WORK( NM12+1 ),
00572 $ WORK( NM13+1 ), VT( LL, 1 ), LDVT )
00573 IF( NRU.GT.0 )
00574 $ CALL DLASR( 'R', 'V', 'B', NRU, M-LL+1, WORK( 1 ),
00575 $ WORK( N ), U( 1, LL ), LDU )
00576 IF( NCC.GT.0 )
00577 $ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCC, WORK( 1 ),
00578 $ WORK( N ), C( LL, 1 ), LDC )
00579
00580
00581
00582 IF( ABS( E( LL ) ).LE.THRESH )
00583 $ E( LL ) = ZERO
00584 END IF
00585 ELSE
00586
00587
00588
00589 IF( IDIR.EQ.1 ) THEN
00590
00591
00592
00593
00594 F = ( ABS( D( LL ) )-SHIFT )*
00595 $ ( SIGN( ONE, D( LL ) )+SHIFT / D( LL ) )
00596 G = E( LL )
00597 DO 140 I = LL, M - 1
00598 CALL DLARTG( F, G, COSR, SINR, R )
00599 IF( I.GT.LL )
00600 $ E( I-1 ) = R
00601 F = COSR*D( I ) + SINR*E( I )
00602 E( I ) = COSR*E( I ) - SINR*D( I )
00603 G = SINR*D( I+1 )
00604 D( I+1 ) = COSR*D( I+1 )
00605 CALL DLARTG( F, G, COSL, SINL, R )
00606 D( I ) = R
00607 F = COSL*E( I ) + SINL*D( I+1 )
00608 D( I+1 ) = COSL*D( I+1 ) - SINL*E( I )
00609 IF( I.LT.M-1 ) THEN
00610 G = SINL*E( I+1 )
00611 E( I+1 ) = COSL*E( I+1 )
00612 END IF
00613 WORK( I-LL+1 ) = COSR
00614 WORK( I-LL+1+NM1 ) = SINR
00615 WORK( I-LL+1+NM12 ) = COSL
00616 WORK( I-LL+1+NM13 ) = SINL
00617 140 CONTINUE
00618 E( M-1 ) = F
00619
00620
00621
00622 IF( NCVT.GT.0 )
00623 $ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCVT, WORK( 1 ),
00624 $ WORK( N ), VT( LL, 1 ), LDVT )
00625 IF( NRU.GT.0 )
00626 $ CALL DLASR( 'R', 'V', 'F', NRU, M-LL+1, WORK( NM12+1 ),
00627 $ WORK( NM13+1 ), U( 1, LL ), LDU )
00628 IF( NCC.GT.0 )
00629 $ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCC, WORK( NM12+1 ),
00630 $ WORK( NM13+1 ), C( LL, 1 ), LDC )
00631
00632
00633
00634 IF( ABS( E( M-1 ) ).LE.THRESH )
00635 $ E( M-1 ) = ZERO
00636
00637 ELSE
00638
00639
00640
00641
00642 F = ( ABS( D( M ) )-SHIFT )*( SIGN( ONE, D( M ) )+SHIFT /
00643 $ D( M ) )
00644 G = E( M-1 )
00645 DO 150 I = M, LL + 1, -1
00646 CALL DLARTG( F, G, COSR, SINR, R )
00647 IF( I.LT.M )
00648 $ E( I ) = R
00649 F = COSR*D( I ) + SINR*E( I-1 )
00650 E( I-1 ) = COSR*E( I-1 ) - SINR*D( I )
00651 G = SINR*D( I-1 )
00652 D( I-1 ) = COSR*D( I-1 )
00653 CALL DLARTG( F, G, COSL, SINL, R )
00654 D( I ) = R
00655 F = COSL*E( I-1 ) + SINL*D( I-1 )
00656 D( I-1 ) = COSL*D( I-1 ) - SINL*E( I-1 )
00657 IF( I.GT.LL+1 ) THEN
00658 G = SINL*E( I-2 )
00659 E( I-2 ) = COSL*E( I-2 )
00660 END IF
00661 WORK( I-LL ) = COSR
00662 WORK( I-LL+NM1 ) = -SINR
00663 WORK( I-LL+NM12 ) = COSL
00664 WORK( I-LL+NM13 ) = -SINL
00665 150 CONTINUE
00666 E( LL ) = F
00667
00668
00669
00670 IF( ABS( E( LL ) ).LE.THRESH )
00671 $ E( LL ) = ZERO
00672
00673
00674
00675 IF( NCVT.GT.0 )
00676 $ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCVT, WORK( NM12+1 ),
00677 $ WORK( NM13+1 ), VT( LL, 1 ), LDVT )
00678 IF( NRU.GT.0 )
00679 $ CALL DLASR( 'R', 'V', 'B', NRU, M-LL+1, WORK( 1 ),
00680 $ WORK( N ), U( 1, LL ), LDU )
00681 IF( NCC.GT.0 )
00682 $ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCC, WORK( 1 ),
00683 $ WORK( N ), C( LL, 1 ), LDC )
00684 END IF
00685 END IF
00686
00687
00688
00689 GO TO 60
00690
00691
00692
00693 160 CONTINUE
00694 DO 170 I = 1, N
00695 IF( D( I ).LT.ZERO ) THEN
00696 D( I ) = -D( I )
00697
00698
00699
00700 IF( NCVT.GT.0 )
00701 $ CALL DSCAL( NCVT, NEGONE, VT( I, 1 ), LDVT )
00702 END IF
00703 170 CONTINUE
00704
00705
00706
00707
00708 DO 190 I = 1, N - 1
00709
00710
00711
00712 ISUB = 1
00713 SMIN = D( 1 )
00714 DO 180 J = 2, N + 1 - I
00715 IF( D( J ).LE.SMIN ) THEN
00716 ISUB = J
00717 SMIN = D( J )
00718 END IF
00719 180 CONTINUE
00720 IF( ISUB.NE.N+1-I ) THEN
00721
00722
00723
00724 D( ISUB ) = D( N+1-I )
00725 D( N+1-I ) = SMIN
00726 IF( NCVT.GT.0 )
00727 $ CALL DSWAP( NCVT, VT( ISUB, 1 ), LDVT, VT( N+1-I, 1 ),
00728 $ LDVT )
00729 IF( NRU.GT.0 )
00730 $ CALL DSWAP( NRU, U( 1, ISUB ), 1, U( 1, N+1-I ), 1 )
00731 IF( NCC.GT.0 )
00732 $ CALL DSWAP( NCC, C( ISUB, 1 ), LDC, C( N+1-I, 1 ), LDC )
00733 END IF
00734 190 CONTINUE
00735 GO TO 220
00736
00737
00738
00739 200 CONTINUE
00740 INFO = 0
00741 DO 210 I = 1, N - 1
00742 IF( E( I ).NE.ZERO )
00743 $ INFO = INFO + 1
00744 210 CONTINUE
00745 220 CONTINUE
00746 RETURN
00747
00748
00749
00750 END