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.
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download SLAED0 + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slaed0.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slaed0.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slaed0.f">
21 * SUBROUTINE SLAED0( ICOMPQ, QSIZ, N, D, E, Q, LDQ, QSTORE, LDQS,
24 * .. Scalar Arguments ..
25 * INTEGER ICOMPQ, INFO, LDQ, LDQS, N, QSIZ
27 * .. Array Arguments ..
29 * REAL D( * ), E( * ), Q( LDQ, * ), QSTORE( LDQS, * ),
39 *> SLAED0 computes all eigenvalues and corresponding eigenvectors of a
40 *> symmetric tridiagonal matrix using the divide and conquer method.
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
60 *> The dimension of the orthogonal matrix used to reduce
61 *> the full matrix to tridiagonal form. QSIZ >= N if ICOMPQ = 1.
67 *> The dimension of the symmetric tridiagonal matrix. N >= 0.
72 *> D is REAL array, dimension (N)
73 *> On entry, the main diagonal of the tridiagonal matrix.
74 *> On exit, its eigenvalues.
79 *> E is REAL array, dimension (N-1)
80 *> The off-diagonal elements of the tridiagonal matrix.
81 *> On exit, E has been destroyed.
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.
102 *> The leading dimension of the array Q. If eigenvectors are
103 *> desired, then LDQ >= max(1,N). In any case, LDQ >= 1.
106 *> \param[out] QSTORE
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
117 *> The leading dimension of the array QSTORE. If ICOMPQ = 1,
118 *> then LDQS >= max(1,N). In any case, LDQS >= 1.
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
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
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).
156 *> \author Univ. of Tennessee
157 *> \author Univ. of California Berkeley
158 *> \author Univ. of Colorado Denver
161 *> \date September 2012
163 *> \ingroup auxOTHERcomputational
165 *> \par Contributors:
168 *> Jeff Rutter, Computer Science Division, University of California
171 * =====================================================================
172 SUBROUTINE SLAED0( ICOMPQ, QSIZ, N, D, E, Q, LDQ, QSTORE, LDQS,
173 $ WORK, IWORK, INFO )
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..--
180 * .. Scalar Arguments ..
181 INTEGER ICOMPQ, INFO, LDQ, LDQS, N, QSIZ
183 * .. Array Arguments ..
185 REAL D( * ), E( * ), Q( LDQ, * ), QSTORE( LDQS, * ),
189 * =====================================================================
193 PARAMETER ( ZERO = 0.E0, ONE = 1.E0, TWO = 2.E0 )
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
202 * .. External Subroutines ..
203 EXTERNAL SCOPY, SGEMM, SLACPY, SLAED1, SLAED7, SSTEQR,
206 * .. External Functions ..
210 * .. Intrinsic Functions ..
211 INTRINSIC ABS, INT, LOG, MAX, REAL
213 * .. Executable Statements ..
215 * Test the input parameters.
219 IF( ICOMPQ.LT.0 .OR. ICOMPQ.GT.2 ) THEN
221 ELSE IF( ( ICOMPQ.EQ.1 ) .AND. ( QSIZ.LT.MAX( 0, N ) ) ) THEN
223 ELSE IF( N.LT.0 ) THEN
225 ELSE IF( LDQ.LT.MAX( 1, N ) ) THEN
227 ELSE IF( LDQS.LT.MAX( 1, N ) ) THEN
231 CALL XERBLA( 'SLAED0', -INFO )
235 * Quick return if possible
240 SMLSIZ = ILAENV( 9, 'SLAED0', ' ', 0, 0, 0, 0 )
242 * Determine the size and placement of the submatrices, and save in
243 * the leading elements of IWORK.
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
259 IWORK( J ) = IWORK( J ) + IWORK( J-1 )
262 * Divide the matrix into SUBPBS submatrices of size at most SMLSIZ+1
263 * using rank-1 modifications (cuts).
267 SUBMAT = IWORK( I ) + 1
269 D( SMM1 ) = D( SMM1 ) - ABS( E( SMM1 ) )
270 D( SUBMAT ) = D( SUBMAT ) - ABS( E( SMM1 ) )
274 IF( ICOMPQ.NE.2 ) THEN
276 * Set up workspaces for eigenvalues only/accumulate new vectors
279 TEMP = LOG( REAL( N ) ) / LOG( TWO )
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
292 IQ = IGIVNM + 2*N*LGN
293 IWREM = IQ + N**2 + 1
295 * Initialize pointers
298 IWORK( IPRMPT+I ) = 1
299 IWORK( IGIVPT+I ) = 1
304 * Solve each submatrix eigenproblem at the bottom of the divide and
313 SUBMAT = IWORK( I ) + 1
314 MATSIZ = IWORK( I+1 ) - IWORK( I )
316 IF( ICOMPQ.EQ.2 ) THEN
317 CALL SSTEQR( 'I', MATSIZ, D( SUBMAT ), E( SUBMAT ),
318 $ Q( SUBMAT, SUBMAT ), LDQ, WORK, INFO )
322 CALL SSTEQR( 'I', MATSIZ, D( SUBMAT ), E( SUBMAT ),
323 $ WORK( IQ-1+IWORK( IQPTR+CURR ) ), MATSIZ, WORK,
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 ),
333 IWORK( IQPTR+CURR+1 ) = IWORK( IQPTR+CURR ) + MATSIZ**2
337 DO 60 J = SUBMAT, IWORK( I+1 )
343 * Successively merge eigensystems of adjacent submatrices
344 * into eigensystem for the corresponding larger matrix.
346 * while ( SUBPBS > 1 )
350 IF( SUBPBS.GT.1 ) THEN
359 SUBMAT = IWORK( I ) + 1
360 MATSIZ = IWORK( I+2 ) - IWORK( I )
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
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.
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 )
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 )
390 IWORK( I / 2+1 ) = IWORK( I+2 )
399 * Re-merge the eigenvalues/vectors which were deflated at the final
402 IF( ICOMPQ.EQ.1 ) THEN
406 CALL SCOPY( QSIZ, QSTORE( 1, J ), 1, Q( 1, I ), 1 )
408 CALL SCOPY( N, WORK, 1, D, 1 )
409 ELSE IF( ICOMPQ.EQ.2 ) THEN
413 CALL SCOPY( N, Q( 1, J ), 1, WORK( N*I+1 ), 1 )
415 CALL SCOPY( N, WORK, 1, D, 1 )
416 CALL SLACPY( 'A', N, N, WORK( N+1 ), N, Q, LDQ )
422 CALL SCOPY( N, WORK, 1, D, 1 )
427 INFO = SUBMAT*( N+1 ) + SUBMAT + MATSIZ - 1