Télécharger dstqrb.eso

Retour à la liste

Numérotation des lignes :

dstqrb
  1. C DSTQRB SOURCE FANDEUR 22/05/02 21:15:16 11359
  2. c-----------------------------------------------------------------------
  3. c\BeginDoc
  4. c
  5. c\Name: dstqrb
  6. c
  7. c\Description:
  8. c Computes all eigenvalues and the last component of the eigenvectors
  9. c of a symmetric tridiagonal matrix using the implicit QL or QR method.
  10. c
  11. c This is mostly a modification of the LAPACK routine dsteqr.
  12. c See Remarks.
  13. c
  14. c\Usage:
  15. c call dstqrb
  16. c ( N, D, E, Z, WORK, INFO )
  17. c
  18. c\Arguments
  19. c N Integer. (INPUT)
  20. c The number of rows and columns in the matrix. N >= 0.
  21. c
  22. c D REAL*8 array, dimension (N). (INPUT/OUTPUT)
  23. c On entry, D contains the diagonal elements of the
  24. c tridiagonal matrix.
  25. c On exit, D contains the eigenvalues, in ascending order.
  26. c If an error exit is made, the eigenvalues are correct
  27. c for indices 1,2,...,INFO-1, but they are unordered and
  28. c may not be the smallest eigenvalues of the matrix.
  29. c
  30. c E REAL*8 array, dimension (N-1). (INPUT/OUTPUT)
  31. c On entry, E contains the subdiagonal elements of the
  32. c tridiagonal matrix in positions 1 through N-1.
  33. c On exit, E has been destroyed.
  34. c
  35. c Z REAL*8 array, dimension (N). (OUTPUT)
  36. c On exit, Z contains the last row of the orthonormal
  37. c eigenvector matrix of the symmetric tridiagonal matrix.
  38. c If an error exit is made, Z contains the last row of the
  39. c eigenvector matrix associated with the stored eigenvalues.
  40. c
  41. c WORK Double precision array, dimension (max(1,2*N-2)). (WORKSPACE)
  42. c Workspace used in accumulating the transformation for
  43. c computing the last components of the eigenvectors.
  44. c
  45. c INFO Integer. (OUTPUT)
  46. c = 0: normal return.
  47. c < 0: if INFO = -i, the i-th argument had an illegal value.
  48. c > 0: if INFO = +i, the i-th eigenvalue has not converged
  49. c after a total of 30*N iterations.
  50. c
  51. c\Remarks
  52. c 1. None.
  53. c
  54. c-----------------------------------------------------------------------
  55. c
  56. c\BeginLib
  57. c
  58. c\Local variables:
  59. c xxxxxx real
  60. c
  61. c\Routines called:
  62. c daxpy Level 1 BLAS that computes a vector triad.
  63. c dcopy Level 1 BLAS that copies one vector to another.
  64. c dswap Level 1 BLAS that swaps the contents of two vectors.
  65. c lsame LAPACK character comparison routine.
  66. c dlae2 LAPACK routine that computes the eigenvalues of a 2-by-2
  67. c symmetric matrix.
  68. c dlaev2 LAPACK routine that eigendecomposition of a 2-by-2 symmetric
  69. c matrix.
  70. c dlamch LAPACK routine that determines machine constants.
  71. c dlanst LAPACK routine that computes the norm of a matrix.
  72. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
  73. c dlartg LAPACK Givens rotation construction routine.
  74. c dlascl LAPACK routine for careful scaling of a matrix.
  75. c dlaset LAPACK matrix initialization routine.
  76. c dlasr LAPACK routine that applies an orthogonal transformation to
  77. c a matrix.
  78. c dlasrt LAPACK sorting routine.
  79. c dsteqr LAPACK routine that computes eigenvalues and eigenvectors
  80. c of a symmetric tridiagonal matrix.
  81. c xerbla LAPACK error handler routine.
  82. c
  83. c\Authors
  84. c Danny Sorensen Phuong Vu
  85. c Richard Lehoucq CRPC / Rice University
  86. c Dept. of Computational & Houston, Texas
  87. c Applied Mathematics
  88. c Rice University
  89. c Houston, Texas
  90. c
  91. c\SCCS Information: @(#)
  92. c FILE: stqrb.F SID: 2.5 DATE OF SID: 8/27/96 RELEASE: 2
  93. c
  94. c\Remarks
  95. c 1. Starting with version 2.5, this routine is a modified version
  96. c of LAPACK version 2.0 subroutine SSTEQR. No lines are deleted,
  97. c only commeted out and new lines inserted.
  98. c All lines commented out have "c$$$" at the beginning.
  99. c Note that the LAPACK version 1.0 subroutine SSTEQR contained
  100. c bugs.
  101. c
  102. c\EndLib
  103. c
  104. c-----------------------------------------------------------------------
  105. c
  106. subroutine dstqrb ( n, d, e, z, work, info )
  107. c
  108. c %------------------%
  109. c | Scalar Arguments |
  110. c %------------------%
  111. c
  112. integer info, n
  113. c
  114. c %-----------------%
  115. c | Array Arguments |
  116. c %-----------------%
  117. c
  118. REAL*8
  119. & d( n ), e( n-1 ), z( n ), work( 2*n-2 )
  120. c
  121. c .. parameters ..
  122. REAL*8
  123. & zero, one, two, three
  124. parameter ( zero = 0.0D+0, one = 1.0D+0,
  125. & two = 2.0D+0, three = 3.0D+0 )
  126. integer maxit
  127. parameter ( maxit = 30 )
  128. c ..
  129. c .. local scalars ..
  130. integer i, icompz, ii, iscale, j, jtot, k, l, l1, lend,
  131. & lendm1, lendp1, lendsv, lm1, lsv, m, mm, mm1,
  132. & nm1, nmaxit
  133. REAL*8
  134. & anorm, b, c, eps, eps2, f, g, p, r, rt1, rt2,
  135. & s, safmax, safmin, ssfmax, ssfmin, tst
  136. c ..
  137. c .. external functions ..
  138. logical lsame
  139. REAL*8
  140. external lsame, dlamch, dlanst, dlapy2
  141. c ..
  142. c .. external subroutines ..
  143. external dlae2, dlaev2, dlartg,
  144. c ..
  145. *c .. intrinsic functions ..
  146. * intrinsic abs, max, sign, sqrt
  147. *c ..
  148. *c .. executable statements ..
  149. c
  150. c test the input parameters.
  151. c
  152. info = 0
  153. c
  154. c$$$ IF( LSAME( COMPZ, 'N' ) ) THEN
  155. c$$$ ICOMPZ = 0
  156. c$$$ ELSE IF( LSAME( COMPZ, 'V' ) ) THEN
  157. c$$$ ICOMPZ = 1
  158. c$$$ ELSE IF( LSAME( COMPZ, 'I' ) ) THEN
  159. c$$$ ICOMPZ = 2
  160. c$$$ ELSE
  161. c$$$ ICOMPZ = -1
  162. c$$$ END IF
  163. c$$$ IF( ICOMPZ.LT.0 ) THEN
  164. c$$$ INFO = -1
  165. c$$$ ELSE IF( N.LT.0 ) THEN
  166. c$$$ INFO = -2
  167. c$$$ ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,
  168. c$$$ $ N ) ) ) THEN
  169. c$$$ INFO = -6
  170. c$$$ END IF
  171. c$$$ IF( INFO.NE.0 ) THEN
  172. c$$$ CALL XERBLA( 'SSTEQR', -INFO )
  173. c$$$ RETURN
  174. c$$$ END IF
  175. c
  176. c *** New starting with version 2.5 ***
  177. c
  178. icompz = 2
  179. c *************************************
  180. c
  181. c quick return if possible
  182. c
  183. if( n.eq.0 )
  184. $ return
  185. c
  186. if( n.eq.1 ) then
  187. if( icompz.eq.2 ) z( 1 ) = one
  188. return
  189. end if
  190. c
  191. c determine the unit roundoff and over/underflow thresholds.
  192. c
  193. eps = dlamch( 'e' )
  194. eps2 = eps**2
  195. safmin = dlamch( 's' )
  196. safmax = one / safmin
  197. ssfmax = sqrt( safmax ) / three
  198. ssfmin = sqrt( safmin ) / eps2
  199. c
  200. c compute the eigenvalues and eigenvectors of the tridiagonal
  201. c matrix.
  202. c
  203. c$$ if( icompz.eq.2 )
  204. c$$$ $ call dlaset( 'full', n, n, zero, one, z, ldz )
  205. c
  206. c *** New starting with version 2.5 ***
  207. c
  208. if ( icompz .eq. 2 ) then
  209. do 5 j = 1, n-1
  210. z(j) = zero
  211. 5 continue
  212. z( n ) = one
  213. end if
  214. c *************************************
  215. c
  216. nmaxit = n*maxit
  217. jtot = 0
  218. c
  219. c determine where the matrix splits and choose ql or qr iteration
  220. c for each block, according to whether top or bottom diagonal
  221. c element is smaller.
  222. c
  223. l1 = 1
  224. nm1 = n - 1
  225. c
  226. 10 continue
  227. if( l1.gt.n )
  228. $ go to 160
  229. if( l1.gt.1 )
  230. $ e( l1-1 ) = zero
  231. if( l1.le.nm1 ) then
  232. do 20 m = l1, nm1
  233. tst = abs( e( m ) )
  234. if( tst.eq.zero )
  235. $ go to 30
  236. if( tst.le.( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+
  237. $ 1 ) ) ) )*eps ) then
  238. e( m ) = zero
  239. go to 30
  240. end if
  241. 20 continue
  242. end if
  243. m = n
  244. c
  245. 30 continue
  246. l = l1
  247. lsv = l
  248. lend = m
  249. lendsv = lend
  250. l1 = m + 1
  251. if( lend.eq.l )
  252. $ go to 10
  253. c
  254. c scale submatrix in rows and columns l to lend
  255. c
  256. anorm = dlanst( 'i', lend-l+1, d( l ), e( l ) )
  257. iscale = 0
  258. if( anorm.eq.zero )
  259. $ go to 10
  260. if( anorm.gt.ssfmax ) then
  261. iscale = 1
  262. call dlascl( 'g', 0, 0, anorm, ssfmax, lend-l+1, 1, d( l ), n,
  263. $ info )
  264. call dlascl( 'g', 0, 0, anorm, ssfmax, lend-l, 1, e( l ), n,
  265. $ info )
  266. else if( anorm.lt.ssfmin ) then
  267. iscale = 2
  268. call dlascl( 'g', 0, 0, anorm, ssfmin, lend-l+1, 1, d( l ), n,
  269. $ info )
  270. call dlascl( 'g', 0, 0, anorm, ssfmin, lend-l, 1, e( l ), n,
  271. $ info )
  272. end if
  273. c
  274. c choose between ql and qr iteration
  275. c
  276. if( abs( d( lend ) ).lt.abs( d( l ) ) ) then
  277. lend = lsv
  278. l = lendsv
  279. end if
  280. c
  281. if( lend.gt.l ) then
  282. c
  283. c ql iteration
  284. c
  285. c look for small subdiagonal element.
  286. c
  287. 40 continue
  288. if( l.ne.lend ) then
  289. lendm1 = lend - 1
  290. do 50 m = l, lendm1
  291. tst = abs( e( m ) )**2
  292. if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+
  293. $ safmin )go to 60
  294. 50 continue
  295. end if
  296. c
  297. m = lend
  298. c
  299. 60 continue
  300. if( m.lt.lend )
  301. $ e( m ) = zero
  302. p = d( l )
  303. if( m.eq.l )
  304. $ go to 80
  305. c
  306. c if remaining matrix is 2-by-2, use dlae2 or dlaev2
  307. c to compute its eigensystem.
  308. c
  309. if( m.eq.l+1 ) then
  310. if( icompz.gt.0 ) then
  311. call dlaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s )
  312. work( l ) = c
  313. work( n-1+l ) = s
  314. c$$$ call dlasr( 'r', 'v', 'b', n, 2, work( l ),
  315. c$$$ $ work( n-1+l ), z( 1, l ), ldz )
  316. c
  317. c *** New starting with version 2.5 ***
  318. c
  319. tst = z(l+1)
  320. z(l+1) = c*tst - s*z(l)
  321. z(l) = s*tst + c*z(l)
  322. c *************************************
  323. else
  324. call dlae2( d( l ), e( l ), d( l+1 ), rt1, rt2 )
  325. end if
  326. d( l ) = rt1
  327. d( l+1 ) = rt2
  328. e( l ) = zero
  329. l = l + 2
  330. if( l.le.lend )
  331. $ go to 40
  332. go to 140
  333. end if
  334. c
  335. if( jtot.eq.nmaxit )
  336. $ go to 140
  337. jtot = jtot + 1
  338. c
  339. c form shift.
  340. c
  341. g = ( d( l+1 )-p ) / ( two*e( l ) )
  342. r = dlapy2( g, one )
  343. g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) )
  344. c
  345. s = one
  346. c = one
  347. p = zero
  348. c
  349. c inner loop
  350. c
  351. mm1 = m - 1
  352. do 70 i = mm1, l, -1
  353. f = s*e( i )
  354. b = c*e( i )
  355. call dlartg( g, f, c, s, r )
  356. if( i.ne.m-1 )
  357. $ e( i+1 ) = r
  358. g = d( i+1 ) - p
  359. r = ( d( i )-g )*s + two*c*b
  360. p = s*r
  361. d( i+1 ) = g + p
  362. g = c*r - b
  363. c
  364. c if eigenvectors are desired, then save rotations.
  365. c
  366. if( icompz.gt.0 ) then
  367. work( i ) = c
  368. work( n-1+i ) = -s
  369. end if
  370. c
  371. 70 continue
  372. c
  373. c if eigenvectors are desired, then apply saved rotations.
  374. c
  375. if( icompz.gt.0 ) then
  376. mm = m - l + 1
  377. c$$$ call dlasr( 'r', 'v', 'b', n, mm, work( l ), work( n-1+l ),
  378. c$$$ $ z( 1, l ), ldz )
  379. c
  380. c *** New starting with version 2.5 ***
  381. c
  382. call dlasr( 'r', 'v', 'b', 1, mm, work( l ),
  383. & work( n-1+l ), z( l ), 1 )
  384. c *************************************
  385. end if
  386. c
  387. d( l ) = d( l ) - p
  388. e( l ) = g
  389. go to 40
  390. c
  391. c eigenvalue found.
  392. c
  393. 80 continue
  394. d( l ) = p
  395. c
  396. l = l + 1
  397. if( l.le.lend )
  398. $ go to 40
  399. go to 140
  400. c
  401. else
  402. c
  403. c qr iteration
  404. c
  405. c look for small superdiagonal element.
  406. c
  407. 90 continue
  408. if( l.ne.lend ) then
  409. lendp1 = lend + 1
  410. do 100 m = l, lendp1, -1
  411. tst = abs( e( m-1 ) )**2
  412. if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+
  413. $ safmin )go to 110
  414. 100 continue
  415. end if
  416. c
  417. m = lend
  418. c
  419. 110 continue
  420. if( m.gt.lend )
  421. $ e( m-1 ) = zero
  422. p = d( l )
  423. if( m.eq.l )
  424. $ go to 130
  425. c
  426. c if remaining matrix is 2-by-2, use dlae2 or dlaev2
  427. c to compute its eigensystem.
  428. c
  429. if( m.eq.l-1 ) then
  430. if( icompz.gt.0 ) then
  431. call dlaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s )
  432. c$$$ work( m ) = c
  433. c$$$ work( n-1+m ) = s
  434. c$$$ call dlasr( 'r', 'v', 'f', n, 2, work( m ),
  435. c$$$ $ work( n-1+m ), z( 1, l-1 ), ldz )
  436. c
  437. c *** New starting with version 2.5 ***
  438. c
  439. tst = z(l)
  440. z(l) = c*tst - s*z(l-1)
  441. z(l-1) = s*tst + c*z(l-1)
  442. c *************************************
  443. else
  444. call dlae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 )
  445. end if
  446. d( l-1 ) = rt1
  447. d( l ) = rt2
  448. e( l-1 ) = zero
  449. l = l - 2
  450. if( l.ge.lend )
  451. $ go to 90
  452. go to 140
  453. end if
  454. c
  455. if( jtot.eq.nmaxit )
  456. $ go to 140
  457. jtot = jtot + 1
  458. c
  459. c form shift.
  460. c
  461. g = ( d( l-1 )-p ) / ( two*e( l-1 ) )
  462. r = dlapy2( g, one )
  463. g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) )
  464. c
  465. s = one
  466. c = one
  467. p = zero
  468. c
  469. c inner loop
  470. c
  471. lm1 = l - 1
  472. do 120 i = m, lm1
  473. f = s*e( i )
  474. b = c*e( i )
  475. call dlartg( g, f, c, s, r )
  476. if( i.ne.m )
  477. $ e( i-1 ) = r
  478. g = d( i ) - p
  479. r = ( d( i+1 )-g )*s + two*c*b
  480. p = s*r
  481. d( i ) = g + p
  482. g = c*r - b
  483. c
  484. c if eigenvectors are desired, then save rotations.
  485. c
  486. if( icompz.gt.0 ) then
  487. work( i ) = c
  488. work( n-1+i ) = s
  489. end if
  490. c
  491. 120 continue
  492. c
  493. c if eigenvectors are desired, then apply saved rotations.
  494. c
  495. if( icompz.gt.0 ) then
  496. mm = l - m + 1
  497. c$$$ call dlasr( 'r', 'v', 'f', n, mm, work( m ), work( n-1+m ),
  498. c$$$ $ z( 1, m ), ldz )
  499. c
  500. c *** New starting with version 2.5 ***
  501. c
  502. call dlasr( 'r', 'v', 'f', 1, mm, work( m ), work( n-1+m ),
  503. & z( m ), 1 )
  504. c *************************************
  505. end if
  506. c
  507. d( l ) = d( l ) - p
  508. e( lm1 ) = g
  509. go to 90
  510. c
  511. c eigenvalue found.
  512. c
  513. 130 continue
  514. d( l ) = p
  515. c
  516. l = l - 1
  517. if( l.ge.lend )
  518. $ go to 90
  519. go to 140
  520. c
  521. end if
  522. c
  523. c undo scaling if necessary
  524. c
  525. 140 continue
  526. if( iscale.eq.1 ) then
  527. call dlascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv+1, 1,
  528. $ d( lsv ), n, info )
  529. call dlascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv, 1, e( lsv ),
  530. $ n, info )
  531. else if( iscale.eq.2 ) then
  532. call dlascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv+1, 1,
  533. $ d( lsv ), n, info )
  534. call dlascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv, 1, e( lsv ),
  535. $ n, info )
  536. end if
  537. c
  538. c check for no convergence to an eigenvalue after a total
  539. c of n*maxit iterations.
  540. c
  541. if( jtot.lt.nmaxit )
  542. $ go to 10
  543. do 150 i = 1, n - 1
  544. if( e( i ).ne.zero )
  545. $ info = info + 1
  546. 150 continue
  547. go to 190
  548. c
  549. c order eigenvalues and eigenvectors.
  550. c
  551. 160 continue
  552. if( icompz.eq.0 ) then
  553. c
  554. c use quick sort
  555. c
  556. call dlasrt( 'i', n, d, info )
  557. c
  558. else
  559. c
  560. c use selection sort to minimize swaps of eigenvectors
  561. c
  562. do 180 ii = 2, n
  563. i = ii - 1
  564. k = i
  565. p = d( i )
  566. do 170 j = ii, n
  567. if( d( j ).lt.p ) then
  568. k = j
  569. p = d( j )
  570. end if
  571. 170 continue
  572. if( k.ne.i ) then
  573. d( k ) = d( i )
  574. d( i ) = p
  575. c$$$ call dswap( n, z( 1, i ), 1, z( 1, k ), 1 )
  576. c *** New starting with version 2.5 ***
  577. c
  578. p = z(k)
  579. z(k) = z(i)
  580. z(i) = p
  581. c *************************************
  582. end if
  583. 180 continue
  584. end if
  585. c
  586. 190 continue
  587. return
  588. c
  589. c %---------------%
  590. c | End of dstqrb |
  591. c %---------------%
  592. c
  593. end
  594.  
  595.  
  596.  

© Cast3M 2003 - Tous droits réservés.
Mentions légales