180 implicit none
181
182
183
184
185
186
187 CHARACTER JOBVL, JOBVR
188 INTEGER INFO, LDA, LDVL, LDVR, LWORK, N
189
190
191 REAL RWORK( * )
192 COMPLEX A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ),
193 $ W( * ), WORK( * )
194
195
196
197
198
199 REAL ZERO, ONE
200 parameter( zero = 0.0e0, one = 1.0e0 )
201
202
203 LOGICAL LQUERY, SCALEA, WANTVL, WANTVR
204 CHARACTER SIDE
205 INTEGER HSWORK, I, IBAL, IERR, IHI, ILO, IRWORK, ITAU,
206 $ IWRK, K, LWORK_TREVC, MAXWRK, MINWRK, NOUT
207 REAL ANRM, BIGNUM, CSCALE, EPS, SCL, SMLNUM
208 COMPLEX TMP
209
210
211 LOGICAL SELECT( 1 )
212 REAL DUM( 1 )
213
214
217
218
219 LOGICAL LSAME
220 INTEGER ISAMAX, ILAENV
221 REAL SLAMCH, SCNRM2, CLANGE, SROUNDUP_LWORK
224
225
226 INTRINSIC real, cmplx, conjg, aimag, max, sqrt
227
228
229
230
231
232 info = 0
233 lquery = ( lwork.EQ.-1 )
234 wantvl =
lsame( jobvl,
'V' )
235 wantvr =
lsame( jobvr,
'V' )
236 IF( ( .NOT.wantvl ) .AND. ( .NOT.
lsame( jobvl,
'N' ) ) )
THEN
237 info = -1
238 ELSE IF( ( .NOT.wantvr ) .AND. ( .NOT.
lsame( jobvr,
'N' ) ) )
THEN
239 info = -2
240 ELSE IF( n.LT.0 ) THEN
241 info = -3
242 ELSE IF( lda.LT.max( 1, n ) ) THEN
243 info = -5
244 ELSE IF( ldvl.LT.1 .OR. ( wantvl .AND. ldvl.LT.n ) ) THEN
245 info = -8
246 ELSE IF( ldvr.LT.1 .OR. ( wantvr .AND. ldvr.LT.n ) ) THEN
247 info = -10
248 END IF
249
250
251
252
253
254
255
256
257
258
259
260
261 IF( info.EQ.0 ) THEN
262 IF( n.EQ.0 ) THEN
263 minwrk = 1
264 maxwrk = 1
265 ELSE
266 maxwrk = n + n*
ilaenv( 1,
'CGEHRD',
' ', n, 1, n, 0 )
267 minwrk = 2*n
268 IF( wantvl ) THEN
269 maxwrk = max( maxwrk, n + ( n - 1 )*
ilaenv( 1,
'CUNGHR',
270 $ ' ', n, 1, n, -1 ) )
271 CALL ctrevc3(
'L',
'B',
SELECT, n, a, lda,
272 $ vl, ldvl, vr, ldvr,
273 $ n, nout, work, -1, rwork, -1, ierr )
274 lwork_trevc = int( work(1) )
275 maxwrk = max( maxwrk, n + lwork_trevc )
276 CALL chseqr(
'S',
'V', n, 1, n, a, lda, w, vl, ldvl,
277 $ work, -1, info )
278 ELSE IF( wantvr ) THEN
279 maxwrk = max( maxwrk, n + ( n - 1 )*
ilaenv( 1,
'CUNGHR',
280 $ ' ', n, 1, n, -1 ) )
281 CALL ctrevc3(
'R',
'B',
SELECT, n, a, lda,
282 $ vl, ldvl, vr, ldvr,
283 $ n, nout, work, -1, rwork, -1, ierr )
284 lwork_trevc = int( work(1) )
285 maxwrk = max( maxwrk, n + lwork_trevc )
286 CALL chseqr(
'S',
'V', n, 1, n, a, lda, w, vr, ldvr,
287 $ work, -1, info )
288 ELSE
289 CALL chseqr(
'E',
'N', n, 1, n, a, lda, w, vr, ldvr,
290 $ work, -1, info )
291 END IF
292 hswork = int( work(1) )
293 maxwrk = max( maxwrk, hswork, minwrk )
294 END IF
296
297 IF( lwork.LT.minwrk .AND. .NOT.lquery ) THEN
298 info = -12
299 END IF
300 END IF
301
302 IF( info.NE.0 ) THEN
303 CALL xerbla(
'CGEEV ', -info )
304 RETURN
305 ELSE IF( lquery ) THEN
306 RETURN
307 END IF
308
309
310
311 IF( n.EQ.0 )
312 $ RETURN
313
314
315
318 bignum = one / smlnum
319 smlnum = sqrt( smlnum ) / eps
320 bignum = one / smlnum
321
322
323
324 anrm =
clange(
'M', n, n, a, lda, dum )
325 scalea = .false.
326 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
327 scalea = .true.
328 cscale = smlnum
329 ELSE IF( anrm.GT.bignum ) THEN
330 scalea = .true.
331 cscale = bignum
332 END IF
333 IF( scalea )
334 $
CALL clascl(
'G', 0, 0, anrm, cscale, n, n, a, lda, ierr )
335
336
337
338
339
340 ibal = 1
341 CALL cgebal(
'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
342
343
344
345
346
347 itau = 1
348 iwrk = itau + n
349 CALL cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),
350 $ lwork-iwrk+1, ierr )
351
352 IF( wantvl ) THEN
353
354
355
356
357 side = 'L'
358 CALL clacpy(
'L', n, n, a, lda, vl, ldvl )
359
360
361
362
363
364 CALL cunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),
365 $ lwork-iwrk+1, ierr )
366
367
368
369
370
371 iwrk = itau
372 CALL chseqr(
'S',
'V', n, ilo, ihi, a, lda, w, vl, ldvl,
373 $ work( iwrk ), lwork-iwrk+1, info )
374
375 IF( wantvr ) THEN
376
377
378
379
380 side = 'B'
381 CALL clacpy(
'F', n, n, vl, ldvl, vr, ldvr )
382 END IF
383
384 ELSE IF( wantvr ) THEN
385
386
387
388
389 side = 'R'
390 CALL clacpy(
'L', n, n, a, lda, vr, ldvr )
391
392
393
394
395
396 CALL cunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),
397 $ lwork-iwrk+1, ierr )
398
399
400
401
402
403 iwrk = itau
404 CALL chseqr(
'S',
'V', n, ilo, ihi, a, lda, w, vr, ldvr,
405 $ work( iwrk ), lwork-iwrk+1, info )
406
407 ELSE
408
409
410
411
412
413 iwrk = itau
414 CALL chseqr(
'E',
'N', n, ilo, ihi, a, lda, w, vr, ldvr,
415 $ work( iwrk ), lwork-iwrk+1, info )
416 END IF
417
418
419
420 IF( info.NE.0 )
421 $ GO TO 50
422
423 IF( wantvl .OR. wantvr ) THEN
424
425
426
427
428
429 irwork = ibal + n
430 CALL ctrevc3( side,
'B',
SELECT, n, a, lda, vl, ldvl, vr, ldvr,
431 $ n, nout, work( iwrk ), lwork-iwrk+1,
432 $ rwork( irwork ), n, ierr )
433 END IF
434
435 IF( wantvl ) THEN
436
437
438
439
440
441 CALL cgebak(
'B',
'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,
442 $ ierr )
443
444
445
446 DO 20 i = 1, n
447 scl = one /
scnrm2( n, vl( 1, i ), 1 )
448 CALL csscal( n, scl, vl( 1, i ), 1 )
449 DO 10 k = 1, n
450 rwork( irwork+k-1 ) = real( vl( k, i ) )**2 +
451 $ aimag( vl( k, i ) )**2
452 10 CONTINUE
453 k =
isamax( n, rwork( irwork ), 1 )
454 tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) )
455 CALL cscal( n, tmp, vl( 1, i ), 1 )
456 vl( k, i ) = cmplx( real( vl( k, i ) ), zero )
457 20 CONTINUE
458 END IF
459
460 IF( wantvr ) THEN
461
462
463
464
465
466 CALL cgebak(
'B',
'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,
467 $ ierr )
468
469
470
471 DO 40 i = 1, n
472 scl = one /
scnrm2( n, vr( 1, i ), 1 )
473 CALL csscal( n, scl, vr( 1, i ), 1 )
474 DO 30 k = 1, n
475 rwork( irwork+k-1 ) = real( vr( k, i ) )**2 +
476 $ aimag( vr( k, i ) )**2
477 30 CONTINUE
478 k =
isamax( n, rwork( irwork ), 1 )
479 tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) )
480 CALL cscal( n, tmp, vr( 1, i ), 1 )
481 vr( k, i ) = cmplx( real( vr( k, i ) ), zero )
482 40 CONTINUE
483 END IF
484
485
486
487 50 CONTINUE
488 IF( scalea ) THEN
489 CALL clascl(
'G', 0, 0, cscale, anrm, n-info, 1, w( info+1 ),
490 $ max( n-info, 1 ), ierr )
491 IF( info.GT.0 ) THEN
492 CALL clascl(
'G', 0, 0, cscale, anrm, ilo-1, 1, w, n, ierr )
493 END IF
494 END IF
495
497 RETURN
498
499
500
subroutine xerbla(srname, info)
subroutine cgebak(job, side, n, ilo, ihi, scale, m, v, ldv, info)
CGEBAK
subroutine cgebal(job, n, a, lda, ilo, ihi, scale, info)
CGEBAL
subroutine cgehrd(n, ilo, ihi, a, lda, tau, work, lwork, info)
CGEHRD
subroutine chseqr(job, compz, n, ilo, ihi, h, ldh, w, z, ldz, work, lwork, info)
CHSEQR
integer function isamax(n, sx, incx)
ISAMAX
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
subroutine clacpy(uplo, m, n, a, lda, b, ldb)
CLACPY copies all or part of one two-dimensional array to another.
real function slamch(cmach)
SLAMCH
real function clange(norm, m, n, a, lda, work)
CLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
subroutine clascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
CLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
logical function lsame(ca, cb)
LSAME
real(wp) function scnrm2(n, x, incx)
SCNRM2
real function sroundup_lwork(lwork)
SROUNDUP_LWORK
subroutine csscal(n, sa, cx, incx)
CSSCAL
subroutine cscal(n, ca, cx, incx)
CSCAL
subroutine ctrevc3(side, howmny, select, n, t, ldt, vl, ldvl, vr, ldvr, mm, m, work, lwork, rwork, lrwork, info)
CTREVC3
subroutine cunghr(n, ilo, ihi, a, lda, tau, work, lwork, info)
CUNGHR