00001 SUBROUTINE CLATBS( UPLO, TRANS, DIAG, NORMIN, N, KD, AB, LDAB, X,
00002 $ SCALE, CNORM, INFO )
00003
00004
00005
00006
00007
00008
00009
00010 CHARACTER DIAG, NORMIN, TRANS, UPLO
00011 INTEGER INFO, KD, LDAB, N
00012 REAL SCALE
00013
00014
00015 REAL CNORM( * )
00016 COMPLEX AB( LDAB, * ), X( * )
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
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 REAL ZERO, HALF, ONE, TWO
00176 PARAMETER ( ZERO = 0.0E+0, HALF = 0.5E+0, ONE = 1.0E+0,
00177 $ TWO = 2.0E+0 )
00178
00179
00180 LOGICAL NOTRAN, NOUNIT, UPPER
00181 INTEGER I, IMAX, J, JFIRST, JINC, JLAST, JLEN, MAIND
00182 REAL BIGNUM, GROW, REC, SMLNUM, TJJ, TMAX, TSCAL,
00183 $ XBND, XJ, XMAX
00184 COMPLEX CSUMJ, TJJS, USCAL, ZDUM
00185
00186
00187 LOGICAL LSAME
00188 INTEGER ICAMAX, ISAMAX
00189 REAL SCASUM, SLAMCH
00190 COMPLEX CDOTC, CDOTU, CLADIV
00191 EXTERNAL LSAME, ICAMAX, ISAMAX, SCASUM, SLAMCH, CDOTC,
00192 $ CDOTU, CLADIV
00193
00194
00195 EXTERNAL CAXPY, CSSCAL, CTBSV, SLABAD, SSCAL, XERBLA
00196
00197
00198 INTRINSIC ABS, AIMAG, CMPLX, CONJG, MAX, MIN, REAL
00199
00200
00201 REAL CABS1, CABS2
00202
00203
00204 CABS1( ZDUM ) = ABS( REAL( ZDUM ) ) + ABS( AIMAG( ZDUM ) )
00205 CABS2( ZDUM ) = ABS( REAL( ZDUM ) / 2. ) +
00206 $ ABS( AIMAG( ZDUM ) / 2. )
00207
00208
00209
00210 INFO = 0
00211 UPPER = LSAME( UPLO, 'U' )
00212 NOTRAN = LSAME( TRANS, 'N' )
00213 NOUNIT = LSAME( DIAG, 'N' )
00214
00215
00216
00217 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
00218 INFO = -1
00219 ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.
00220 $ LSAME( TRANS, 'C' ) ) THEN
00221 INFO = -2
00222 ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN
00223 INFO = -3
00224 ELSE IF( .NOT.LSAME( NORMIN, 'Y' ) .AND. .NOT.
00225 $ LSAME( NORMIN, 'N' ) ) THEN
00226 INFO = -4
00227 ELSE IF( N.LT.0 ) THEN
00228 INFO = -5
00229 ELSE IF( KD.LT.0 ) THEN
00230 INFO = -6
00231 ELSE IF( LDAB.LT.KD+1 ) THEN
00232 INFO = -8
00233 END IF
00234 IF( INFO.NE.0 ) THEN
00235 CALL XERBLA( 'CLATBS', -INFO )
00236 RETURN
00237 END IF
00238
00239
00240
00241 IF( N.EQ.0 )
00242 $ RETURN
00243
00244
00245
00246 SMLNUM = SLAMCH( 'Safe minimum' )
00247 BIGNUM = ONE / SMLNUM
00248 CALL SLABAD( SMLNUM, BIGNUM )
00249 SMLNUM = SMLNUM / SLAMCH( 'Precision' )
00250 BIGNUM = ONE / SMLNUM
00251 SCALE = ONE
00252
00253 IF( LSAME( NORMIN, 'N' ) ) THEN
00254
00255
00256
00257 IF( UPPER ) THEN
00258
00259
00260
00261 DO 10 J = 1, N
00262 JLEN = MIN( KD, J-1 )
00263 CNORM( J ) = SCASUM( JLEN, AB( KD+1-JLEN, J ), 1 )
00264 10 CONTINUE
00265 ELSE
00266
00267
00268
00269 DO 20 J = 1, N
00270 JLEN = MIN( KD, N-J )
00271 IF( JLEN.GT.0 ) THEN
00272 CNORM( J ) = SCASUM( JLEN, AB( 2, J ), 1 )
00273 ELSE
00274 CNORM( J ) = ZERO
00275 END IF
00276 20 CONTINUE
00277 END IF
00278 END IF
00279
00280
00281
00282
00283 IMAX = ISAMAX( N, CNORM, 1 )
00284 TMAX = CNORM( IMAX )
00285 IF( TMAX.LE.BIGNUM*HALF ) THEN
00286 TSCAL = ONE
00287 ELSE
00288 TSCAL = HALF / ( SMLNUM*TMAX )
00289 CALL SSCAL( N, TSCAL, CNORM, 1 )
00290 END IF
00291
00292
00293
00294
00295 XMAX = ZERO
00296 DO 30 J = 1, N
00297 XMAX = MAX( XMAX, CABS2( X( J ) ) )
00298 30 CONTINUE
00299 XBND = XMAX
00300 IF( NOTRAN ) THEN
00301
00302
00303
00304 IF( UPPER ) THEN
00305 JFIRST = N
00306 JLAST = 1
00307 JINC = -1
00308 MAIND = KD + 1
00309 ELSE
00310 JFIRST = 1
00311 JLAST = N
00312 JINC = 1
00313 MAIND = 1
00314 END IF
00315
00316 IF( TSCAL.NE.ONE ) THEN
00317 GROW = ZERO
00318 GO TO 60
00319 END IF
00320
00321 IF( NOUNIT ) THEN
00322
00323
00324
00325
00326
00327
00328 GROW = HALF / MAX( XBND, SMLNUM )
00329 XBND = GROW
00330 DO 40 J = JFIRST, JLAST, JINC
00331
00332
00333
00334 IF( GROW.LE.SMLNUM )
00335 $ GO TO 60
00336
00337 TJJS = AB( MAIND, J )
00338 TJJ = CABS1( TJJS )
00339
00340 IF( TJJ.GE.SMLNUM ) THEN
00341
00342
00343
00344 XBND = MIN( XBND, MIN( ONE, TJJ )*GROW )
00345 ELSE
00346
00347
00348
00349 XBND = ZERO
00350 END IF
00351
00352 IF( TJJ+CNORM( J ).GE.SMLNUM ) THEN
00353
00354
00355
00356 GROW = GROW*( TJJ / ( TJJ+CNORM( J ) ) )
00357 ELSE
00358
00359
00360
00361 GROW = ZERO
00362 END IF
00363 40 CONTINUE
00364 GROW = XBND
00365 ELSE
00366
00367
00368
00369
00370
00371 GROW = MIN( ONE, HALF / MAX( XBND, SMLNUM ) )
00372 DO 50 J = JFIRST, JLAST, JINC
00373
00374
00375
00376 IF( GROW.LE.SMLNUM )
00377 $ GO TO 60
00378
00379
00380
00381 GROW = GROW*( ONE / ( ONE+CNORM( J ) ) )
00382 50 CONTINUE
00383 END IF
00384 60 CONTINUE
00385
00386 ELSE
00387
00388
00389
00390 IF( UPPER ) THEN
00391 JFIRST = 1
00392 JLAST = N
00393 JINC = 1
00394 MAIND = KD + 1
00395 ELSE
00396 JFIRST = N
00397 JLAST = 1
00398 JINC = -1
00399 MAIND = 1
00400 END IF
00401
00402 IF( TSCAL.NE.ONE ) THEN
00403 GROW = ZERO
00404 GO TO 90
00405 END IF
00406
00407 IF( NOUNIT ) THEN
00408
00409
00410
00411
00412
00413
00414 GROW = HALF / MAX( XBND, SMLNUM )
00415 XBND = GROW
00416 DO 70 J = JFIRST, JLAST, JINC
00417
00418
00419
00420 IF( GROW.LE.SMLNUM )
00421 $ GO TO 90
00422
00423
00424
00425 XJ = ONE + CNORM( J )
00426 GROW = MIN( GROW, XBND / XJ )
00427
00428 TJJS = AB( MAIND, J )
00429 TJJ = CABS1( TJJS )
00430
00431 IF( TJJ.GE.SMLNUM ) THEN
00432
00433
00434
00435 IF( XJ.GT.TJJ )
00436 $ XBND = XBND*( TJJ / XJ )
00437 ELSE
00438
00439
00440
00441 XBND = ZERO
00442 END IF
00443 70 CONTINUE
00444 GROW = MIN( GROW, XBND )
00445 ELSE
00446
00447
00448
00449
00450
00451 GROW = MIN( ONE, HALF / MAX( XBND, SMLNUM ) )
00452 DO 80 J = JFIRST, JLAST, JINC
00453
00454
00455
00456 IF( GROW.LE.SMLNUM )
00457 $ GO TO 90
00458
00459
00460
00461 XJ = ONE + CNORM( J )
00462 GROW = GROW / XJ
00463 80 CONTINUE
00464 END IF
00465 90 CONTINUE
00466 END IF
00467
00468 IF( ( GROW*TSCAL ).GT.SMLNUM ) THEN
00469
00470
00471
00472
00473 CALL CTBSV( UPLO, TRANS, DIAG, N, KD, AB, LDAB, X, 1 )
00474 ELSE
00475
00476
00477
00478 IF( XMAX.GT.BIGNUM*HALF ) THEN
00479
00480
00481
00482
00483 SCALE = ( BIGNUM*HALF ) / XMAX
00484 CALL CSSCAL( N, SCALE, X, 1 )
00485 XMAX = BIGNUM
00486 ELSE
00487 XMAX = XMAX*TWO
00488 END IF
00489
00490 IF( NOTRAN ) THEN
00491
00492
00493
00494 DO 110 J = JFIRST, JLAST, JINC
00495
00496
00497
00498 XJ = CABS1( X( J ) )
00499 IF( NOUNIT ) THEN
00500 TJJS = AB( MAIND, J )*TSCAL
00501 ELSE
00502 TJJS = TSCAL
00503 IF( TSCAL.EQ.ONE )
00504 $ GO TO 105
00505 END IF
00506 TJJ = CABS1( TJJS )
00507 IF( TJJ.GT.SMLNUM ) THEN
00508
00509
00510
00511 IF( TJJ.LT.ONE ) THEN
00512 IF( XJ.GT.TJJ*BIGNUM ) THEN
00513
00514
00515
00516 REC = ONE / XJ
00517 CALL CSSCAL( N, REC, X, 1 )
00518 SCALE = SCALE*REC
00519 XMAX = XMAX*REC
00520 END IF
00521 END IF
00522 X( J ) = CLADIV( X( J ), TJJS )
00523 XJ = CABS1( X( J ) )
00524 ELSE IF( TJJ.GT.ZERO ) THEN
00525
00526
00527
00528 IF( XJ.GT.TJJ*BIGNUM ) THEN
00529
00530
00531
00532
00533 REC = ( TJJ*BIGNUM ) / XJ
00534 IF( CNORM( J ).GT.ONE ) THEN
00535
00536
00537
00538
00539 REC = REC / CNORM( J )
00540 END IF
00541 CALL CSSCAL( N, REC, X, 1 )
00542 SCALE = SCALE*REC
00543 XMAX = XMAX*REC
00544 END IF
00545 X( J ) = CLADIV( X( J ), TJJS )
00546 XJ = CABS1( X( J ) )
00547 ELSE
00548
00549
00550
00551
00552 DO 100 I = 1, N
00553 X( I ) = ZERO
00554 100 CONTINUE
00555 X( J ) = ONE
00556 XJ = ONE
00557 SCALE = ZERO
00558 XMAX = ZERO
00559 END IF
00560 105 CONTINUE
00561
00562
00563
00564
00565 IF( XJ.GT.ONE ) THEN
00566 REC = ONE / XJ
00567 IF( CNORM( J ).GT.( BIGNUM-XMAX )*REC ) THEN
00568
00569
00570
00571 REC = REC*HALF
00572 CALL CSSCAL( N, REC, X, 1 )
00573 SCALE = SCALE*REC
00574 END IF
00575 ELSE IF( XJ*CNORM( J ).GT.( BIGNUM-XMAX ) ) THEN
00576
00577
00578
00579 CALL CSSCAL( N, HALF, X, 1 )
00580 SCALE = SCALE*HALF
00581 END IF
00582
00583 IF( UPPER ) THEN
00584 IF( J.GT.1 ) THEN
00585
00586
00587
00588
00589
00590 JLEN = MIN( KD, J-1 )
00591 CALL CAXPY( JLEN, -X( J )*TSCAL,
00592 $ AB( KD+1-JLEN, J ), 1, X( J-JLEN ), 1 )
00593 I = ICAMAX( J-1, X, 1 )
00594 XMAX = CABS1( X( I ) )
00595 END IF
00596 ELSE IF( J.LT.N ) THEN
00597
00598
00599
00600
00601
00602 JLEN = MIN( KD, N-J )
00603 IF( JLEN.GT.0 )
00604 $ CALL CAXPY( JLEN, -X( J )*TSCAL, AB( 2, J ), 1,
00605 $ X( J+1 ), 1 )
00606 I = J + ICAMAX( N-J, X( J+1 ), 1 )
00607 XMAX = CABS1( X( I ) )
00608 END IF
00609 110 CONTINUE
00610
00611 ELSE IF( LSAME( TRANS, 'T' ) ) THEN
00612
00613
00614
00615 DO 150 J = JFIRST, JLAST, JINC
00616
00617
00618
00619
00620 XJ = CABS1( X( J ) )
00621 USCAL = TSCAL
00622 REC = ONE / MAX( XMAX, ONE )
00623 IF( CNORM( J ).GT.( BIGNUM-XJ )*REC ) THEN
00624
00625
00626
00627 REC = REC*HALF
00628 IF( NOUNIT ) THEN
00629 TJJS = AB( MAIND, J )*TSCAL
00630 ELSE
00631 TJJS = TSCAL
00632 END IF
00633 TJJ = CABS1( TJJS )
00634 IF( TJJ.GT.ONE ) THEN
00635
00636
00637
00638 REC = MIN( ONE, REC*TJJ )
00639 USCAL = CLADIV( USCAL, TJJS )
00640 END IF
00641 IF( REC.LT.ONE ) THEN
00642 CALL CSSCAL( N, REC, X, 1 )
00643 SCALE = SCALE*REC
00644 XMAX = XMAX*REC
00645 END IF
00646 END IF
00647
00648 CSUMJ = ZERO
00649 IF( USCAL.EQ.CMPLX( ONE ) ) THEN
00650
00651
00652
00653
00654 IF( UPPER ) THEN
00655 JLEN = MIN( KD, J-1 )
00656 CSUMJ = CDOTU( JLEN, AB( KD+1-JLEN, J ), 1,
00657 $ X( J-JLEN ), 1 )
00658 ELSE
00659 JLEN = MIN( KD, N-J )
00660 IF( JLEN.GT.1 )
00661 $ CSUMJ = CDOTU( JLEN, AB( 2, J ), 1, X( J+1 ),
00662 $ 1 )
00663 END IF
00664 ELSE
00665
00666
00667
00668 IF( UPPER ) THEN
00669 JLEN = MIN( KD, J-1 )
00670 DO 120 I = 1, JLEN
00671 CSUMJ = CSUMJ + ( AB( KD+I-JLEN, J )*USCAL )*
00672 $ X( J-JLEN-1+I )
00673 120 CONTINUE
00674 ELSE
00675 JLEN = MIN( KD, N-J )
00676 DO 130 I = 1, JLEN
00677 CSUMJ = CSUMJ + ( AB( I+1, J )*USCAL )*X( J+I )
00678 130 CONTINUE
00679 END IF
00680 END IF
00681
00682 IF( USCAL.EQ.CMPLX( TSCAL ) ) THEN
00683
00684
00685
00686
00687 X( J ) = X( J ) - CSUMJ
00688 XJ = CABS1( X( J ) )
00689 IF( NOUNIT ) THEN
00690
00691
00692
00693 TJJS = AB( MAIND, J )*TSCAL
00694 ELSE
00695 TJJS = TSCAL
00696 IF( TSCAL.EQ.ONE )
00697 $ GO TO 145
00698 END IF
00699 TJJ = CABS1( TJJS )
00700 IF( TJJ.GT.SMLNUM ) THEN
00701
00702
00703
00704 IF( TJJ.LT.ONE ) THEN
00705 IF( XJ.GT.TJJ*BIGNUM ) THEN
00706
00707
00708
00709 REC = ONE / XJ
00710 CALL CSSCAL( N, REC, X, 1 )
00711 SCALE = SCALE*REC
00712 XMAX = XMAX*REC
00713 END IF
00714 END IF
00715 X( J ) = CLADIV( X( J ), TJJS )
00716 ELSE IF( TJJ.GT.ZERO ) THEN
00717
00718
00719
00720 IF( XJ.GT.TJJ*BIGNUM ) THEN
00721
00722
00723
00724 REC = ( TJJ*BIGNUM ) / XJ
00725 CALL CSSCAL( N, REC, X, 1 )
00726 SCALE = SCALE*REC
00727 XMAX = XMAX*REC
00728 END IF
00729 X( J ) = CLADIV( X( J ), TJJS )
00730 ELSE
00731
00732
00733
00734
00735 DO 140 I = 1, N
00736 X( I ) = ZERO
00737 140 CONTINUE
00738 X( J ) = ONE
00739 SCALE = ZERO
00740 XMAX = ZERO
00741 END IF
00742 145 CONTINUE
00743 ELSE
00744
00745
00746
00747
00748 X( J ) = CLADIV( X( J ), TJJS ) - CSUMJ
00749 END IF
00750 XMAX = MAX( XMAX, CABS1( X( J ) ) )
00751 150 CONTINUE
00752
00753 ELSE
00754
00755
00756
00757 DO 190 J = JFIRST, JLAST, JINC
00758
00759
00760
00761
00762 XJ = CABS1( X( J ) )
00763 USCAL = TSCAL
00764 REC = ONE / MAX( XMAX, ONE )
00765 IF( CNORM( J ).GT.( BIGNUM-XJ )*REC ) THEN
00766
00767
00768
00769 REC = REC*HALF
00770 IF( NOUNIT ) THEN
00771 TJJS = CONJG( AB( MAIND, J ) )*TSCAL
00772 ELSE
00773 TJJS = TSCAL
00774 END IF
00775 TJJ = CABS1( TJJS )
00776 IF( TJJ.GT.ONE ) THEN
00777
00778
00779
00780 REC = MIN( ONE, REC*TJJ )
00781 USCAL = CLADIV( USCAL, TJJS )
00782 END IF
00783 IF( REC.LT.ONE ) THEN
00784 CALL CSSCAL( N, REC, X, 1 )
00785 SCALE = SCALE*REC
00786 XMAX = XMAX*REC
00787 END IF
00788 END IF
00789
00790 CSUMJ = ZERO
00791 IF( USCAL.EQ.CMPLX( ONE ) ) THEN
00792
00793
00794
00795
00796 IF( UPPER ) THEN
00797 JLEN = MIN( KD, J-1 )
00798 CSUMJ = CDOTC( JLEN, AB( KD+1-JLEN, J ), 1,
00799 $ X( J-JLEN ), 1 )
00800 ELSE
00801 JLEN = MIN( KD, N-J )
00802 IF( JLEN.GT.1 )
00803 $ CSUMJ = CDOTC( JLEN, AB( 2, J ), 1, X( J+1 ),
00804 $ 1 )
00805 END IF
00806 ELSE
00807
00808
00809
00810 IF( UPPER ) THEN
00811 JLEN = MIN( KD, J-1 )
00812 DO 160 I = 1, JLEN
00813 CSUMJ = CSUMJ + ( CONJG( AB( KD+I-JLEN, J ) )*
00814 $ USCAL )*X( J-JLEN-1+I )
00815 160 CONTINUE
00816 ELSE
00817 JLEN = MIN( KD, N-J )
00818 DO 170 I = 1, JLEN
00819 CSUMJ = CSUMJ + ( CONJG( AB( I+1, J ) )*USCAL )*
00820 $ X( J+I )
00821 170 CONTINUE
00822 END IF
00823 END IF
00824
00825 IF( USCAL.EQ.CMPLX( TSCAL ) ) THEN
00826
00827
00828
00829
00830 X( J ) = X( J ) - CSUMJ
00831 XJ = CABS1( X( J ) )
00832 IF( NOUNIT ) THEN
00833
00834
00835
00836 TJJS = CONJG( AB( MAIND, J ) )*TSCAL
00837 ELSE
00838 TJJS = TSCAL
00839 IF( TSCAL.EQ.ONE )
00840 $ GO TO 185
00841 END IF
00842 TJJ = CABS1( TJJS )
00843 IF( TJJ.GT.SMLNUM ) THEN
00844
00845
00846
00847 IF( TJJ.LT.ONE ) THEN
00848 IF( XJ.GT.TJJ*BIGNUM ) THEN
00849
00850
00851
00852 REC = ONE / XJ
00853 CALL CSSCAL( N, REC, X, 1 )
00854 SCALE = SCALE*REC
00855 XMAX = XMAX*REC
00856 END IF
00857 END IF
00858 X( J ) = CLADIV( X( J ), TJJS )
00859 ELSE IF( TJJ.GT.ZERO ) THEN
00860
00861
00862
00863 IF( XJ.GT.TJJ*BIGNUM ) THEN
00864
00865
00866
00867 REC = ( TJJ*BIGNUM ) / XJ
00868 CALL CSSCAL( N, REC, X, 1 )
00869 SCALE = SCALE*REC
00870 XMAX = XMAX*REC
00871 END IF
00872 X( J ) = CLADIV( X( J ), TJJS )
00873 ELSE
00874
00875
00876
00877
00878 DO 180 I = 1, N
00879 X( I ) = ZERO
00880 180 CONTINUE
00881 X( J ) = ONE
00882 SCALE = ZERO
00883 XMAX = ZERO
00884 END IF
00885 185 CONTINUE
00886 ELSE
00887
00888
00889
00890
00891 X( J ) = CLADIV( X( J ), TJJS ) - CSUMJ
00892 END IF
00893 XMAX = MAX( XMAX, CABS1( X( J ) ) )
00894 190 CONTINUE
00895 END IF
00896 SCALE = SCALE / TSCAL
00897 END IF
00898
00899
00900
00901 IF( TSCAL.NE.ONE ) THEN
00902 CALL SSCAL( N, ONE / TSCAL, CNORM, 1 )
00903 END IF
00904
00905 RETURN
00906
00907
00908
00909 END