You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

slaed0.f 14 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. *> \brief \b SLAED0 used by sstedc. Computes all eigenvalues and corresponding eigenvectors of an unreduced symmetric tridiagonal matrix using the divide and conquer method.
  2. *
  3. * =========== DOCUMENTATION ===========
  4. *
  5. * Online html documentation available at
  6. * http://www.netlib.org/lapack/explore-html/
  7. *
  8. *> \htmlonly
  9. *> Download SLAED0 + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slaed0.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slaed0.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slaed0.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * SUBROUTINE SLAED0( ICOMPQ, QSIZ, N, D, E, Q, LDQ, QSTORE, LDQS,
  22. * WORK, IWORK, INFO )
  23. *
  24. * .. Scalar Arguments ..
  25. * INTEGER ICOMPQ, INFO, LDQ, LDQS, N, QSIZ
  26. * ..
  27. * .. Array Arguments ..
  28. * INTEGER IWORK( * )
  29. * REAL D( * ), E( * ), Q( LDQ, * ), QSTORE( LDQS, * ),
  30. * $ WORK( * )
  31. * ..
  32. *
  33. *
  34. *> \par Purpose:
  35. * =============
  36. *>
  37. *> \verbatim
  38. *>
  39. *> SLAED0 computes all eigenvalues and corresponding eigenvectors of a
  40. *> symmetric tridiagonal matrix using the divide and conquer method.
  41. *> \endverbatim
  42. *
  43. * Arguments:
  44. * ==========
  45. *
  46. *> \param[in] ICOMPQ
  47. *> \verbatim
  48. *> ICOMPQ is INTEGER
  49. *> = 0: Compute eigenvalues only.
  50. *> = 1: Compute eigenvectors of original dense symmetric matrix
  51. *> also. On entry, Q contains the orthogonal matrix used
  52. *> to reduce the original matrix to tridiagonal form.
  53. *> = 2: Compute eigenvalues and eigenvectors of tridiagonal
  54. *> matrix.
  55. *> \endverbatim
  56. *>
  57. *> \param[in] QSIZ
  58. *> \verbatim
  59. *> QSIZ is INTEGER
  60. *> The dimension of the orthogonal matrix used to reduce
  61. *> the full matrix to tridiagonal form. QSIZ >= N if ICOMPQ = 1.
  62. *> \endverbatim
  63. *>
  64. *> \param[in] N
  65. *> \verbatim
  66. *> N is INTEGER
  67. *> The dimension of the symmetric tridiagonal matrix. N >= 0.
  68. *> \endverbatim
  69. *>
  70. *> \param[in,out] D
  71. *> \verbatim
  72. *> D is REAL array, dimension (N)
  73. *> On entry, the main diagonal of the tridiagonal matrix.
  74. *> On exit, its eigenvalues.
  75. *> \endverbatim
  76. *>
  77. *> \param[in] E
  78. *> \verbatim
  79. *> E is REAL array, dimension (N-1)
  80. *> The off-diagonal elements of the tridiagonal matrix.
  81. *> On exit, E has been destroyed.
  82. *> \endverbatim
  83. *>
  84. *> \param[in,out] Q
  85. *> \verbatim
  86. *> Q is REAL array, dimension (LDQ, N)
  87. *> On entry, Q must contain an N-by-N orthogonal matrix.
  88. *> If ICOMPQ = 0 Q is not referenced.
  89. *> If ICOMPQ = 1 On entry, Q is a subset of the columns of the
  90. *> orthogonal matrix used to reduce the full
  91. *> matrix to tridiagonal form corresponding to
  92. *> the subset of the full matrix which is being
  93. *> decomposed at this time.
  94. *> If ICOMPQ = 2 On entry, Q will be the identity matrix.
  95. *> On exit, Q contains the eigenvectors of the
  96. *> tridiagonal matrix.
  97. *> \endverbatim
  98. *>
  99. *> \param[in] LDQ
  100. *> \verbatim
  101. *> LDQ is INTEGER
  102. *> The leading dimension of the array Q. If eigenvectors are
  103. *> desired, then LDQ >= max(1,N). In any case, LDQ >= 1.
  104. *> \endverbatim
  105. *>
  106. *> \param[out] QSTORE
  107. *> \verbatim
  108. *> QSTORE is REAL array, dimension (LDQS, N)
  109. *> Referenced only when ICOMPQ = 1. Used to store parts of
  110. *> the eigenvector matrix when the updating matrix multiplies
  111. *> take place.
  112. *> \endverbatim
  113. *>
  114. *> \param[in] LDQS
  115. *> \verbatim
  116. *> LDQS is INTEGER
  117. *> The leading dimension of the array QSTORE. If ICOMPQ = 1,
  118. *> then LDQS >= max(1,N). In any case, LDQS >= 1.
  119. *> \endverbatim
  120. *>
  121. *> \param[out] WORK
  122. *> \verbatim
  123. *> WORK is REAL array,
  124. *> If ICOMPQ = 0 or 1, the dimension of WORK must be at least
  125. *> 1 + 3*N + 2*N*lg N + 3*N**2
  126. *> ( lg( N ) = smallest integer k
  127. *> such that 2^k >= N )
  128. *> If ICOMPQ = 2, the dimension of WORK must be at least
  129. *> 4*N + N**2.
  130. *> \endverbatim
  131. *>
  132. *> \param[out] IWORK
  133. *> \verbatim
  134. *> IWORK is INTEGER array,
  135. *> If ICOMPQ = 0 or 1, the dimension of IWORK must be at least
  136. *> 6 + 6*N + 5*N*lg N.
  137. *> ( lg( N ) = smallest integer k
  138. *> such that 2^k >= N )
  139. *> If ICOMPQ = 2, the dimension of IWORK must be at least
  140. *> 3 + 5*N.
  141. *> \endverbatim
  142. *>
  143. *> \param[out] INFO
  144. *> \verbatim
  145. *> INFO is INTEGER
  146. *> = 0: successful exit.
  147. *> < 0: if INFO = -i, the i-th argument had an illegal value.
  148. *> > 0: The algorithm failed to compute an eigenvalue while
  149. *> working on the submatrix lying in rows and columns
  150. *> INFO/(N+1) through mod(INFO,N+1).
  151. *> \endverbatim
  152. *
  153. * Authors:
  154. * ========
  155. *
  156. *> \author Univ. of Tennessee
  157. *> \author Univ. of California Berkeley
  158. *> \author Univ. of Colorado Denver
  159. *> \author NAG Ltd.
  160. *
  161. *> \date September 2012
  162. *
  163. *> \ingroup auxOTHERcomputational
  164. *
  165. *> \par Contributors:
  166. * ==================
  167. *>
  168. *> Jeff Rutter, Computer Science Division, University of California
  169. *> at Berkeley, USA
  170. *
  171. * =====================================================================
  172. SUBROUTINE SLAED0( ICOMPQ, QSIZ, N, D, E, Q, LDQ, QSTORE, LDQS,
  173. $ WORK, IWORK, INFO )
  174. *
  175. * -- LAPACK computational routine (version 3.4.2) --
  176. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  177. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  178. * September 2012
  179. *
  180. * .. Scalar Arguments ..
  181. INTEGER ICOMPQ, INFO, LDQ, LDQS, N, QSIZ
  182. * ..
  183. * .. Array Arguments ..
  184. INTEGER IWORK( * )
  185. REAL D( * ), E( * ), Q( LDQ, * ), QSTORE( LDQS, * ),
  186. $ WORK( * )
  187. * ..
  188. *
  189. * =====================================================================
  190. *
  191. * .. Parameters ..
  192. REAL ZERO, ONE, TWO
  193. PARAMETER ( ZERO = 0.E0, ONE = 1.E0, TWO = 2.E0 )
  194. * ..
  195. * .. Local Scalars ..
  196. INTEGER CURLVL, CURPRB, CURR, I, IGIVCL, IGIVNM,
  197. $ IGIVPT, INDXQ, IPERM, IPRMPT, IQ, IQPTR, IWREM,
  198. $ J, K, LGN, MATSIZ, MSD2, SMLSIZ, SMM1, SPM1,
  199. $ SPM2, SUBMAT, SUBPBS, TLVLS
  200. REAL TEMP
  201. * ..
  202. * .. External Subroutines ..
  203. EXTERNAL SCOPY, SGEMM, SLACPY, SLAED1, SLAED7, SSTEQR,
  204. $ XERBLA
  205. * ..
  206. * .. External Functions ..
  207. INTEGER ILAENV
  208. EXTERNAL ILAENV
  209. * ..
  210. * .. Intrinsic Functions ..
  211. INTRINSIC ABS, INT, LOG, MAX, REAL
  212. * ..
  213. * .. Executable Statements ..
  214. *
  215. * Test the input parameters.
  216. *
  217. INFO = 0
  218. *
  219. IF( ICOMPQ.LT.0 .OR. ICOMPQ.GT.2 ) THEN
  220. INFO = -1
  221. ELSE IF( ( ICOMPQ.EQ.1 ) .AND. ( QSIZ.LT.MAX( 0, N ) ) ) THEN
  222. INFO = -2
  223. ELSE IF( N.LT.0 ) THEN
  224. INFO = -3
  225. ELSE IF( LDQ.LT.MAX( 1, N ) ) THEN
  226. INFO = -7
  227. ELSE IF( LDQS.LT.MAX( 1, N ) ) THEN
  228. INFO = -9
  229. END IF
  230. IF( INFO.NE.0 ) THEN
  231. CALL XERBLA( 'SLAED0', -INFO )
  232. RETURN
  233. END IF
  234. *
  235. * Quick return if possible
  236. *
  237. IF( N.EQ.0 )
  238. $ RETURN
  239. *
  240. SMLSIZ = ILAENV( 9, 'SLAED0', ' ', 0, 0, 0, 0 )
  241. *
  242. * Determine the size and placement of the submatrices, and save in
  243. * the leading elements of IWORK.
  244. *
  245. IWORK( 1 ) = N
  246. SUBPBS = 1
  247. TLVLS = 0
  248. 10 CONTINUE
  249. IF( IWORK( SUBPBS ).GT.SMLSIZ ) THEN
  250. DO 20 J = SUBPBS, 1, -1
  251. IWORK( 2*J ) = ( IWORK( J )+1 ) / 2
  252. IWORK( 2*J-1 ) = IWORK( J ) / 2
  253. 20 CONTINUE
  254. TLVLS = TLVLS + 1
  255. SUBPBS = 2*SUBPBS
  256. GO TO 10
  257. END IF
  258. DO 30 J = 2, SUBPBS
  259. IWORK( J ) = IWORK( J ) + IWORK( J-1 )
  260. 30 CONTINUE
  261. *
  262. * Divide the matrix into SUBPBS submatrices of size at most SMLSIZ+1
  263. * using rank-1 modifications (cuts).
  264. *
  265. SPM1 = SUBPBS - 1
  266. DO 40 I = 1, SPM1
  267. SUBMAT = IWORK( I ) + 1
  268. SMM1 = SUBMAT - 1
  269. D( SMM1 ) = D( SMM1 ) - ABS( E( SMM1 ) )
  270. D( SUBMAT ) = D( SUBMAT ) - ABS( E( SMM1 ) )
  271. 40 CONTINUE
  272. *
  273. INDXQ = 4*N + 3
  274. IF( ICOMPQ.NE.2 ) THEN
  275. *
  276. * Set up workspaces for eigenvalues only/accumulate new vectors
  277. * routine
  278. *
  279. TEMP = LOG( REAL( N ) ) / LOG( TWO )
  280. LGN = INT( TEMP )
  281. IF( 2**LGN.LT.N )
  282. $ LGN = LGN + 1
  283. IF( 2**LGN.LT.N )
  284. $ LGN = LGN + 1
  285. IPRMPT = INDXQ + N + 1
  286. IPERM = IPRMPT + N*LGN
  287. IQPTR = IPERM + N*LGN
  288. IGIVPT = IQPTR + N + 2
  289. IGIVCL = IGIVPT + N*LGN
  290. *
  291. IGIVNM = 1
  292. IQ = IGIVNM + 2*N*LGN
  293. IWREM = IQ + N**2 + 1
  294. *
  295. * Initialize pointers
  296. *
  297. DO 50 I = 0, SUBPBS
  298. IWORK( IPRMPT+I ) = 1
  299. IWORK( IGIVPT+I ) = 1
  300. 50 CONTINUE
  301. IWORK( IQPTR ) = 1
  302. END IF
  303. *
  304. * Solve each submatrix eigenproblem at the bottom of the divide and
  305. * conquer tree.
  306. *
  307. CURR = 0
  308. DO 70 I = 0, SPM1
  309. IF( I.EQ.0 ) THEN
  310. SUBMAT = 1
  311. MATSIZ = IWORK( 1 )
  312. ELSE
  313. SUBMAT = IWORK( I ) + 1
  314. MATSIZ = IWORK( I+1 ) - IWORK( I )
  315. END IF
  316. IF( ICOMPQ.EQ.2 ) THEN
  317. CALL SSTEQR( 'I', MATSIZ, D( SUBMAT ), E( SUBMAT ),
  318. $ Q( SUBMAT, SUBMAT ), LDQ, WORK, INFO )
  319. IF( INFO.NE.0 )
  320. $ GO TO 130
  321. ELSE
  322. CALL SSTEQR( 'I', MATSIZ, D( SUBMAT ), E( SUBMAT ),
  323. $ WORK( IQ-1+IWORK( IQPTR+CURR ) ), MATSIZ, WORK,
  324. $ INFO )
  325. IF( INFO.NE.0 )
  326. $ GO TO 130
  327. IF( ICOMPQ.EQ.1 ) THEN
  328. CALL SGEMM( 'N', 'N', QSIZ, MATSIZ, MATSIZ, ONE,
  329. $ Q( 1, SUBMAT ), LDQ, WORK( IQ-1+IWORK( IQPTR+
  330. $ CURR ) ), MATSIZ, ZERO, QSTORE( 1, SUBMAT ),
  331. $ LDQS )
  332. END IF
  333. IWORK( IQPTR+CURR+1 ) = IWORK( IQPTR+CURR ) + MATSIZ**2
  334. CURR = CURR + 1
  335. END IF
  336. K = 1
  337. DO 60 J = SUBMAT, IWORK( I+1 )
  338. IWORK( INDXQ+J ) = K
  339. K = K + 1
  340. 60 CONTINUE
  341. 70 CONTINUE
  342. *
  343. * Successively merge eigensystems of adjacent submatrices
  344. * into eigensystem for the corresponding larger matrix.
  345. *
  346. * while ( SUBPBS > 1 )
  347. *
  348. CURLVL = 1
  349. 80 CONTINUE
  350. IF( SUBPBS.GT.1 ) THEN
  351. SPM2 = SUBPBS - 2
  352. DO 90 I = 0, SPM2, 2
  353. IF( I.EQ.0 ) THEN
  354. SUBMAT = 1
  355. MATSIZ = IWORK( 2 )
  356. MSD2 = IWORK( 1 )
  357. CURPRB = 0
  358. ELSE
  359. SUBMAT = IWORK( I ) + 1
  360. MATSIZ = IWORK( I+2 ) - IWORK( I )
  361. MSD2 = MATSIZ / 2
  362. CURPRB = CURPRB + 1
  363. END IF
  364. *
  365. * Merge lower order eigensystems (of size MSD2 and MATSIZ - MSD2)
  366. * into an eigensystem of size MATSIZ.
  367. * SLAED1 is used only for the full eigensystem of a tridiagonal
  368. * matrix.
  369. * SLAED7 handles the cases in which eigenvalues only or eigenvalues
  370. * and eigenvectors of a full symmetric matrix (which was reduced to
  371. * tridiagonal form) are desired.
  372. *
  373. IF( ICOMPQ.EQ.2 ) THEN
  374. CALL SLAED1( MATSIZ, D( SUBMAT ), Q( SUBMAT, SUBMAT ),
  375. $ LDQ, IWORK( INDXQ+SUBMAT ),
  376. $ E( SUBMAT+MSD2-1 ), MSD2, WORK,
  377. $ IWORK( SUBPBS+1 ), INFO )
  378. ELSE
  379. CALL SLAED7( ICOMPQ, MATSIZ, QSIZ, TLVLS, CURLVL, CURPRB,
  380. $ D( SUBMAT ), QSTORE( 1, SUBMAT ), LDQS,
  381. $ IWORK( INDXQ+SUBMAT ), E( SUBMAT+MSD2-1 ),
  382. $ MSD2, WORK( IQ ), IWORK( IQPTR ),
  383. $ IWORK( IPRMPT ), IWORK( IPERM ),
  384. $ IWORK( IGIVPT ), IWORK( IGIVCL ),
  385. $ WORK( IGIVNM ), WORK( IWREM ),
  386. $ IWORK( SUBPBS+1 ), INFO )
  387. END IF
  388. IF( INFO.NE.0 )
  389. $ GO TO 130
  390. IWORK( I / 2+1 ) = IWORK( I+2 )
  391. 90 CONTINUE
  392. SUBPBS = SUBPBS / 2
  393. CURLVL = CURLVL + 1
  394. GO TO 80
  395. END IF
  396. *
  397. * end while
  398. *
  399. * Re-merge the eigenvalues/vectors which were deflated at the final
  400. * merge step.
  401. *
  402. IF( ICOMPQ.EQ.1 ) THEN
  403. DO 100 I = 1, N
  404. J = IWORK( INDXQ+I )
  405. WORK( I ) = D( J )
  406. CALL SCOPY( QSIZ, QSTORE( 1, J ), 1, Q( 1, I ), 1 )
  407. 100 CONTINUE
  408. CALL SCOPY( N, WORK, 1, D, 1 )
  409. ELSE IF( ICOMPQ.EQ.2 ) THEN
  410. DO 110 I = 1, N
  411. J = IWORK( INDXQ+I )
  412. WORK( I ) = D( J )
  413. CALL SCOPY( N, Q( 1, J ), 1, WORK( N*I+1 ), 1 )
  414. 110 CONTINUE
  415. CALL SCOPY( N, WORK, 1, D, 1 )
  416. CALL SLACPY( 'A', N, N, WORK( N+1 ), N, Q, LDQ )
  417. ELSE
  418. DO 120 I = 1, N
  419. J = IWORK( INDXQ+I )
  420. WORK( I ) = D( J )
  421. 120 CONTINUE
  422. CALL SCOPY( N, WORK, 1, D, 1 )
  423. END IF
  424. GO TO 140
  425. *
  426. 130 CONTINUE
  427. INFO = SUBMAT*( N+1 ) + SUBMAT + MATSIZ - 1
  428. *
  429. 140 CONTINUE
  430. RETURN
  431. *
  432. * End of SLAED0
  433. *
  434. END