OpenRadioss 2025.1.11
OpenRadioss project
Loading...
Searching...
No Matches
ssteqr2.f
Go to the documentation of this file.
1 SUBROUTINE ssteqr2( COMPZ, N, D, E, Z, LDZ, NR, WORK, INFO )
2*
3* -- LAPACK routine (version 2.0) --
4* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
5* Courant Institute, Argonne National Lab, and Rice University
6* September 30, 1994
7*
8* .. Scalar Arguments ..
9 CHARACTER COMPZ
10 INTEGER INFO, LDZ, N, NR
11* ..
12* .. Array Arguments ..
13 REAL D( * ), E( * ), WORK( * ), Z( LDZ, * )
14* ..
15*
16* Purpose
17* =======
18*
19* SSTEQR2 is a modified version of LAPACK routine SSTEQR.
20* SSTEQR2 computes all eigenvalues and, optionally, eigenvectors of a
21* symmetric tridiagonal matrix using the implicit QL or QR method.
22* running SSTEQR2 to perform updates on a distributed matrix Q.
23* Proper usage of SSTEQR2 can be gleaned from examination of ScaLAPACK's
24* PSSYEV.
25*
26* Arguments
27* =========
28*
29* COMPZ (input) CHARACTER*1
30* = 'N': Compute eigenvalues only.
31* = 'I': Compute eigenvalues and eigenvectors of the
32* tridiagonal matrix. Z must be initialized to the
33* identity matrix by PDLASET or DLASET prior to entering
34* this subroutine.
35*
36* N (input) INTEGER
37* The order of the matrix. N >= 0.
38*
39* D (input/output) REAL array, dimension (N)
40* On entry, the diagonal elements of the tridiagonal matrix.
41* On exit, if INFO = 0, the eigenvalues in ascending order.
42*
43* E (input/output) REAL array, dimension (N-1)
44* On entry, the (n-1) subdiagonal elements of the tridiagonal
45* matrix.
46* On exit, E has been destroyed.
47*
48* Z (local input/local output) REAL array, global
49* dimension (N, N), local dimension (LDZ, NR).
50* On entry, if COMPZ = 'V', then Z contains the orthogonal
51* matrix used in the reduction to tridiagonal form.
52* On exit, if INFO = 0, then if COMPZ = 'V', Z contains the
53* orthonormal eigenvectors of the original symmetric matrix,
54* and if COMPZ = 'I', Z contains the orthonormal eigenvectors
55* of the symmetric tridiagonal matrix.
56* If COMPZ = 'N', then Z is not referenced.
57*
58* LDZ (input) INTEGER
59* The leading dimension of the array Z. LDZ >= 1, and if
60* eigenvectors are desired, then LDZ >= max(1,N).
61*
62* NR (input) INTEGER
63* NR = MAX(1, NUMROC( N, NB, MYPROW, 0, NPROCS ) ).
64* If COMPZ = 'N', then NR is not referenced.
65*
66* WORK (workspace) REAL array, dimension (max(1,2*N-2))
67* If COMPZ = 'N', then WORK is not referenced.
68*
69* INFO (output) INTEGER
70* = 0: successful exit
71* < 0: if INFO = -i, the i-th argument had an illegal value
72* > 0: the algorithm has failed to find all the eigenvalues in
73* a total of 30*N iterations; if INFO = i, then i
74* elements of E have not converged to zero; on exit, D
75* and E contain the elements of a symmetric tridiagonal
76* matrix which is orthogonally similar to the original
77* matrix.
78*
79* =====================================================================
80*
81* .. Parameters ..
82 REAL ZERO, ONE, TWO, THREE
83 parameter( zero = 0.0e0, one = 1.0e0, two = 2.0e0,
84 $ three = 3.0e0 )
85 INTEGER MAXIT
86 parameter( maxit = 30 )
87* ..
88* .. Local Scalars ..
89 INTEGER I, ICOMPZ, II, ISCALE, J, JTOT, K, L, L1, LEND,
90 $ LENDM1, LENDP1, LENDSV, LM1, LSV, M, MM, MM1,
91 $ NM1, NMAXIT
92 REAL ANORM, B, C, EPS, EPS2, F, G, P, R, RT1, RT2,
93 $ S, SAFMAX, SAFMIN, SSFMAX, SSFMIN, TST
94* ..
95* .. External Functions ..
96 LOGICAL LSAME
97 REAL SLAMCH, SLANST, SLAPY2
98 EXTERNAL lsame, slamch, slanst, slapy2
99* ..
100* .. External Subroutines ..
101 EXTERNAL slae2, slaev2, slartg, slascl, slasr,
103* ..
104* .. Intrinsic Functions ..
105 INTRINSIC abs, max, sign, sqrt
106* ..
107* .. Executable Statements ..
108*
109* Test the input parameters.
110*
111 info = 0
112*
113 IF( lsame( compz, 'N' ) ) THEN
114 icompz = 0
115 ELSE IF( lsame( compz, 'I' ) ) THEN
116 icompz = 1
117 ELSE
118 icompz = -1
119 END IF
120 IF( icompz.LT.0 ) THEN
121 info = -1
122 ELSE IF( n.LT.0 ) THEN
123 info = -2
124 ELSE IF( icompz.GT.0 .AND. ldz.LT.max( 1, nr ) ) THEN
125 info = -6
126 END IF
127 IF( info.NE.0 ) THEN
128 CALL xerbla( 'SSTEQR2', -info )
129 RETURN
130 END IF
131*
132* Quick return if possible
133*
134 IF( n.EQ.0 )
135 $ RETURN
136*
137 IF( n.EQ.1 ) THEN
138 IF( icompz.EQ.1 )
139 $ z( 1, 1 ) = one
140 RETURN
141 END IF
142*
143* Determine the unit roundoff and over/underflow thresholds.
144*
145 eps = slamch( 'E' )
146 eps2 = eps**2
147 safmin = slamch( 'S' )
148 safmax = one / safmin
149 ssfmax = sqrt( safmax ) / three
150 ssfmin = sqrt( safmin ) / eps2
151*
152* Compute the eigenvalues and eigenvectors of the tridiagonal
153* matrix.
154*
155 nmaxit = n*maxit
156 jtot = 0
157*
158* Determine where the matrix splits and choose QL or QR iteration
159* for each block, according to whether top or bottom diagonal
160* element is smaller.
161*
162 l1 = 1
163 nm1 = n - 1
164*
165 10 CONTINUE
166 IF( l1.GT.n )
167 $ GO TO 160
168 IF( l1.GT.1 )
169 $ e( l1-1 ) = zero
170 IF( l1.LE.nm1 ) THEN
171 DO 20 m = l1, nm1
172 tst = abs( e( m ) )
173 IF( tst.EQ.zero )
174 $ GO TO 30
175 IF( tst.LE.( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+
176 $ 1 ) ) ) )*eps ) THEN
177 e( m ) = zero
178 GO TO 30
179 END IF
180 20 CONTINUE
181 END IF
182 m = n
183*
184 30 CONTINUE
185 l = l1
186 lsv = l
187 lend = m
188 lendsv = lend
189 l1 = m + 1
190 IF( lend.EQ.l )
191 $ GO TO 10
192*
193* Scale submatrix in rows and columns L to LEND
194*
195 anorm = slanst( 'I', lend-l+1, d( l ), e( l ) )
196 iscale = 0
197 IF( anorm.EQ.zero )
198 $ GO TO 10
199 IF( anorm.GT.ssfmax ) THEN
200 iscale = 1
201 CALL slascl( 'G', 0, 0, anorm, ssfmax, lend-l+1, 1, d( l ), n,
202 $ info )
203 CALL slascl( 'G', 0, 0, anorm, ssfmax, lend-l, 1, e( l ), n,
204 $ info )
205 ELSE IF( anorm.LT.ssfmin ) THEN
206 iscale = 2
207 CALL slascl( 'G', 0, 0, anorm, ssfmin, lend-l+1, 1, d( l ), n,
208 $ info )
209 CALL slascl( 'G', 0, 0, anorm, ssfmin, lend-l, 1, e( l ), n,
210 $ info )
211 END IF
212*
213* Choose between QL and QR iteration
214*
215 IF( abs( d( lend ) ).LT.abs( d( l ) ) ) THEN
216 lend = lsv
217 l = lendsv
218 END IF
219*
220 IF( lend.GT.l ) THEN
221*
222* QL Iteration
223*
224* Look for small subdiagonal element.
225*
226 40 CONTINUE
227 IF( l.NE.lend ) THEN
228 lendm1 = lend - 1
229 DO 50 m = l, lendm1
230 tst = abs( e( m ) )**2
231 IF( tst.LE.( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+
232 $ safmin )GO TO 60
233 50 CONTINUE
234 END IF
235*
236 m = lend
237*
238 60 CONTINUE
239 IF( m.LT.lend )
240 $ e( m ) = zero
241 p = d( l )
242 IF( m.EQ.l )
243 $ GO TO 80
244*
245* If remaining matrix is 2-by-2, use SLAE2 or SLAEV2
246* to compute its eigensystem.
247*
248 IF( m.EQ.l+1 ) THEN
249 IF( icompz.GT.0 ) THEN
250 CALL slaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s )
251 work( l ) = c
252 work( n-1+l ) = s
253 CALL slasr( 'R', 'V', 'B', nr, 2, work( l ),
254 $ work( n-1+l ), z( 1, l ), ldz )
255 ELSE
256 CALL slae2( d( l ), e( l ), d( l+1 ), rt1, rt2 )
257 END IF
258 d( l ) = rt1
259 d( l+1 ) = rt2
260 e( l ) = zero
261 l = l + 2
262 IF( l.LE.lend )
263 $ GO TO 40
264 GO TO 140
265 END IF
266*
267 IF( jtot.EQ.nmaxit )
268 $ GO TO 140
269 jtot = jtot + 1
270*
271* Form shift.
272*
273 g = ( d( l+1 )-p ) / ( two*e( l ) )
274 r = slapy2( g, one )
275 g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) )
276*
277 s = one
278 c = one
279 p = zero
280*
281* Inner loop
282*
283 mm1 = m - 1
284 DO 70 i = mm1, l, -1
285 f = s*e( i )
286 b = c*e( i )
287 CALL slartg( g, f, c, s, r )
288 IF( i.NE.m-1 )
289 $ e( i+1 ) = r
290 g = d( i+1 ) - p
291 r = ( d( i )-g )*s + two*c*b
292 p = s*r
293 d( i+1 ) = g + p
294 g = c*r - b
295*
296* If eigenvectors are desired, then save rotations.
297*
298 IF( icompz.GT.0 ) THEN
299 work( i ) = c
300 work( n-1+i ) = -s
301 END IF
302*
303 70 CONTINUE
304*
305* If eigenvectors are desired, then apply saved rotations.
306*
307 IF( icompz.GT.0 ) THEN
308 mm = m - l + 1
309 CALL slasr( 'R', 'V', 'B', nr, mm, work( l ), work( n-1+l ),
310 $ z( 1, l ), ldz )
311 END IF
312*
313 d( l ) = d( l ) - p
314 e( l ) = g
315 GO TO 40
316*
317* Eigenvalue found.
318*
319 80 CONTINUE
320 d( l ) = p
321*
322 l = l + 1
323 IF( l.LE.lend )
324 $ GO TO 40
325 GO TO 140
326*
327 ELSE
328*
329* QR Iteration
330*
331* Look for small superdiagonal element.
332*
333 90 CONTINUE
334 IF( l.NE.lend ) THEN
335 lendp1 = lend + 1
336 DO 100 m = l, lendp1, -1
337 tst = abs( e( m-1 ) )**2
338 IF( tst.LE.( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+
339 $ safmin )GO TO 110
340 100 CONTINUE
341 END IF
342*
343 m = lend
344*
345 110 CONTINUE
346 IF( m.GT.lend )
347 $ e( m-1 ) = zero
348 p = d( l )
349 IF( m.EQ.l )
350 $ GO TO 130
351*
352* If remaining matrix is 2-by-2, use SLAE2 or SLAEV2
353* to compute its eigensystem.
354*
355 IF( m.EQ.l-1 ) THEN
356 IF( icompz.GT.0 ) THEN
357 CALL slaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s )
358 work( m ) = c
359 work( n-1+m ) = s
360 CALL slasr( 'r', 'v', 'f', NR, 2, WORK( M ),
361 $ WORK( N-1+M ), Z( 1, L-1 ), LDZ )
362 ELSE
363 CALL SLAE2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2 )
364 END IF
365 D( L-1 ) = RT1
366 D( L ) = RT2
367 E( L-1 ) = ZERO
368 L = L - 2
369.GE. IF( LLEND )
370 $ GO TO 90
371 GO TO 140
372 END IF
373*
374.EQ. IF( JTOTNMAXIT )
375 $ GO TO 140
376 JTOT = JTOT + 1
377*
378* Form shift.
379*
380 G = ( D( L-1 )-P ) / ( TWO*E( L-1 ) )
381 R = SLAPY2( G, ONE )
382 G = D( M ) - P + ( E( L-1 ) / ( G+SIGN( R, G ) ) )
383*
384 S = ONE
385 C = ONE
386 P = ZERO
387*
388* Inner loop
389*
390 LM1 = L - 1
391 DO 120 I = M, LM1
392 F = S*E( I )
393 B = C*E( I )
394 CALL SLARTG( G, F, C, S, R )
395.NE. IF( IM )
396 $ E( I-1 ) = R
397 G = D( I ) - P
398 R = ( D( I+1 )-G )*S + TWO*C*B
399 P = S*R
400 D( I ) = G + P
401 G = C*R - B
402*
403* If eigenvectors are desired, then save rotations.
404*
405.GT. IF( ICOMPZ0 ) THEN
406 WORK( I ) = C
407 WORK( N-1+I ) = S
408 END IF
409*
410 120 CONTINUE
411*
412* If eigenvectors are desired, then apply saved rotations.
413*
414.GT. IF( ICOMPZ0 ) THEN
415 MM = L - M + 1
416 CALL SLASR( 'r', 'v', 'f', NR, MM, WORK( M ), WORK( N-1+M ),
417 $ Z( 1, M ), LDZ )
418 END IF
419*
420 D( L ) = D( L ) - P
421 E( LM1 ) = G
422 GO TO 90
423*
424* Eigenvalue found.
425*
426 130 CONTINUE
427 D( L ) = P
428*
429 L = L - 1
430.GE. IF( LLEND )
431 $ GO TO 90
432 GO TO 140
433*
434 END IF
435*
436* Undo scaling if necessary
437*
438 140 CONTINUE
439.EQ. IF( ISCALE1 ) THEN
440 CALL SLASCL( 'g', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1,
441 $ D( LSV ), N, INFO )
442 CALL SLASCL( 'g', 0, 0, SSFMAX, ANORM, LENDSV-LSV, 1, E( LSV ),
443 $ N, INFO )
444.EQ. ELSE IF( ISCALE2 ) THEN
445 CALL SLASCL( 'g', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1,
446 $ D( LSV ), N, INFO )
447 CALL SLASCL( 'g', 0, 0, SSFMIN, ANORM, LENDSV-LSV, 1, E( LSV ),
448 $ N, INFO )
449 END IF
450*
451* Check for no convergence to an eigenvalue after a total
452* of N*MAXIT iterations.
453*
454.LT. IF( JTOTNMAXIT )
455 $ GO TO 10
456 DO 150 I = 1, N - 1
457.NE. IF( E( I )ZERO )
458 $ INFO = INFO + 1
459 150 CONTINUE
460 GO TO 190
461*
462* Order eigenvalues and eigenvectors.
463*
464 160 CONTINUE
465.EQ. IF( ICOMPZ0 ) THEN
466*
467* Use Quick Sort
468*
469 CALL SLASRT( 'i', N, D, INFO )
470*
471 ELSE
472*
473* Use Selection Sort to minimize swaps of eigenvectors
474*
475 DO 180 II = 2, N
476 I = II - 1
477 K = I
478 P = D( I )
479 DO 170 J = II, N
480.LT. IF( D( J )P ) THEN
481 K = J
482 P = D( J )
483 END IF
484 170 CONTINUE
485.NE. IF( KI ) THEN
486 D( K ) = D( I )
487 D( I ) = P
488 CALL SSWAP( NR, Z( 1, I ), 1, Z( 1, K ), 1 )
489 END IF
490 180 CONTINUE
491 END IF
492*
493 190 CONTINUE
494 RETURN
495*
496* End of SSTEQR2
497*
498 END
subroutine slasr(side, pivot, direct, m, n, c, s, a, lda)
SLASR applies a sequence of plane rotations to a general rectangular matrix.
Definition slasr.f:199
subroutine slae2(a, b, c, rt1, rt2)
SLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix.
Definition slae2.f:102
subroutine slartg(f, g, c, s, r)
SLARTG generates a plane rotation with real cosine and real sine.
Definition slartg.f90:113
subroutine slaev2(a, b, c, rt1, rt2, cs1, sn1)
SLAEV2 computes the eigenvalues and eigenvectors of a 2-by-2 symmetric/Hermitian matrix.
Definition slaev2.f:120
subroutine slascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
SLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition slascl.f:143
subroutine slasrt(id, n, d, info)
SLASRT sorts numbers in increasing or decreasing order.
Definition slasrt.f:88
subroutine xerbla(srname, info)
XERBLA
Definition xerbla.f:60
subroutine sswap(n, sx, incx, sy, incy)
SSWAP
Definition sswap.f:82
#define max(a, b)
Definition macros.h:21
subroutine ssteqr2(compz, n, d, e, z, ldz, nr, work, info)
Definition ssteqr2.f:2