191 implicit none
192
193
194
195
196
197
198 CHARACTER JOBVL, JOBVR
199 INTEGER INFO, LDA, LDVL, LDVR, LWORK, N
200
201
202 DOUBLE PRECISION A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ),
203 $ WI( * ), WORK( * ), WR( * )
204
205
206
207
208
209 DOUBLE PRECISION ZERO, ONE
210 parameter( zero = 0.0d0, one = 1.0d0 )
211
212
213 LOGICAL LQUERY, SCALEA, WANTVL, WANTVR
214 CHARACTER SIDE
215 INTEGER HSWORK, I, IBAL, IERR, IHI, ILO, ITAU, IWRK, K,
216 $ LWORK_TREVC, MAXWRK, MINWRK, NOUT
217 DOUBLE PRECISION ANRM, BIGNUM, CS, CSCALE, EPS, R, SCL, SMLNUM,
218 $ SN
219
220
221 LOGICAL SELECT( 1 )
222 DOUBLE PRECISION DUM( 1 )
223
224
228
229
230 LOGICAL LSAME
231 INTEGER IDAMAX, ILAENV
232 DOUBLE PRECISION DLAMCH, DLANGE, DLAPY2, DNRM2
236
237
238 INTRINSIC max, sqrt
239
240
241
242
243
244 info = 0
245 lquery = ( lwork.EQ.-1 )
246 wantvl =
lsame( jobvl,
'V' )
247 wantvr =
lsame( jobvr,
'V' )
248 IF( ( .NOT.wantvl ) .AND. ( .NOT.
lsame( jobvl,
'N' ) ) )
THEN
249 info = -1
250 ELSE IF( ( .NOT.wantvr ) .AND.
251 $ ( .NOT.
lsame( jobvr,
'N' ) ) )
THEN
252 info = -2
253 ELSE IF( n.LT.0 ) THEN
254 info = -3
255 ELSE IF( lda.LT.max( 1, n ) ) THEN
256 info = -5
257 ELSE IF( ldvl.LT.1 .OR. ( wantvl .AND. ldvl.LT.n ) ) THEN
258 info = -9
259 ELSE IF( ldvr.LT.1 .OR. ( wantvr .AND. ldvr.LT.n ) ) THEN
260 info = -11
261 END IF
262
263
264
265
266
267
268
269
270
271
272
273 IF( info.EQ.0 ) THEN
274 IF( n.EQ.0 ) THEN
275 minwrk = 1
276 maxwrk = 1
277 ELSE
278 maxwrk = 2*n + n*
ilaenv( 1,
'DGEHRD',
' ', n, 1, n, 0 )
279 IF( wantvl ) THEN
280 minwrk = 4*n
281 maxwrk = max( maxwrk, 2*n + ( n - 1 )*
ilaenv( 1,
282 $ 'DORGHR', ' ', n, 1, n, -1 ) )
283 CALL dhseqr(
'S',
'V', n, 1, n, a, lda, wr, wi, vl,
284 $ ldvl,
285 $ work, -1, info )
286 hswork = int( work(1) )
287 maxwrk = max( maxwrk, n + 1, n + hswork )
288 CALL dtrevc3(
'L',
'B',
SELECT, n, a, lda,
289 $ vl, ldvl, vr, ldvr, n, nout,
290 $ work, -1, ierr )
291 lwork_trevc = int( work(1) )
292 maxwrk = max( maxwrk, n + lwork_trevc )
293 maxwrk = max( maxwrk, 4*n )
294 ELSE IF( wantvr ) THEN
295 minwrk = 4*n
296 maxwrk = max( maxwrk, 2*n + ( n - 1 )*
ilaenv( 1,
297 $ 'DORGHR', ' ', n, 1, n, -1 ) )
298 CALL dhseqr(
'S',
'V', n, 1, n, a, lda, wr, wi, vr,
299 $ ldvr,
300 $ work, -1, info )
301 hswork = int( work(1) )
302 maxwrk = max( maxwrk, n + 1, n + hswork )
303 CALL dtrevc3(
'R',
'B',
SELECT, n, a, lda,
304 $ vl, ldvl, vr, ldvr, n, nout,
305 $ work, -1, ierr )
306 lwork_trevc = int( work(1) )
307 maxwrk = max( maxwrk, n + lwork_trevc )
308 maxwrk = max( maxwrk, 4*n )
309 ELSE
310 minwrk = 3*n
311 CALL dhseqr(
'E',
'N', n, 1, n, a, lda, wr, wi, vr,
312 $ ldvr,
313 $ work, -1, info )
314 hswork = int( work(1) )
315 maxwrk = max( maxwrk, n + 1, n + hswork )
316 END IF
317 maxwrk = max( maxwrk, minwrk )
318 END IF
319 work( 1 ) = maxwrk
320
321 IF( lwork.LT.minwrk .AND. .NOT.lquery ) THEN
322 info = -13
323 END IF
324 END IF
325
326 IF( info.NE.0 ) THEN
327 CALL xerbla(
'DGEEV ', -info )
328 RETURN
329 ELSE IF( lquery ) THEN
330 RETURN
331 END IF
332
333
334
335 IF( n.EQ.0 )
336 $ RETURN
337
338
339
342 bignum = one / smlnum
343 smlnum = sqrt( smlnum ) / eps
344 bignum = one / smlnum
345
346
347
348 anrm =
dlange(
'M', n, n, a, lda, dum )
349 scalea = .false.
350 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
351 scalea = .true.
352 cscale = smlnum
353 ELSE IF( anrm.GT.bignum ) THEN
354 scalea = .true.
355 cscale = bignum
356 END IF
357 IF( scalea )
358 $
CALL dlascl(
'G', 0, 0, anrm, cscale, n, n, a, lda, ierr )
359
360
361
362
363 ibal = 1
364 CALL dgebal(
'B', n, a, lda, ilo, ihi, work( ibal ), ierr )
365
366
367
368
369 itau = ibal + n
370 iwrk = itau + n
371 CALL dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),
372 $ lwork-iwrk+1, ierr )
373
374 IF( wantvl ) THEN
375
376
377
378
379 side = 'L'
380 CALL dlacpy(
'L', n, n, a, lda, vl, ldvl )
381
382
383
384
385 CALL dorghr( n, ilo, ihi, vl, ldvl, work( itau ),
386 $ work( iwrk ),
387 $ lwork-iwrk+1, ierr )
388
389
390
391
392 iwrk = itau
393 CALL dhseqr(
'S',
'V', n, ilo, ihi, a, lda, wr, wi, vl,
394 $ ldvl,
395 $ work( iwrk ), lwork-iwrk+1, info )
396
397 IF( wantvr ) THEN
398
399
400
401
402 side = 'B'
403 CALL dlacpy(
'F', n, n, vl, ldvl, vr, ldvr )
404 END IF
405
406 ELSE IF( wantvr ) THEN
407
408
409
410
411 side = 'R'
412 CALL dlacpy(
'L', n, n, a, lda, vr, ldvr )
413
414
415
416
417 CALL dorghr( n, ilo, ihi, vr, ldvr, work( itau ),
418 $ work( iwrk ),
419 $ lwork-iwrk+1, ierr )
420
421
422
423
424 iwrk = itau
425 CALL dhseqr(
'S',
'V', n, ilo, ihi, a, lda, wr, wi, vr,
426 $ ldvr,
427 $ work( iwrk ), lwork-iwrk+1, info )
428
429 ELSE
430
431
432
433
434 iwrk = itau
435 CALL dhseqr(
'E',
'N', n, ilo, ihi, a, lda, wr, wi, vr,
436 $ ldvr,
437 $ work( iwrk ), lwork-iwrk+1, info )
438 END IF
439
440
441
442 IF( info.NE.0 )
443 $ GO TO 50
444
445 IF( wantvl .OR. wantvr ) THEN
446
447
448
449
450 CALL dtrevc3( side,
'B',
SELECT, n, a, lda, vl, ldvl, vr,
451 $ ldvr,
452 $ n, nout, work( iwrk ), lwork-iwrk+1, ierr )
453 END IF
454
455 IF( wantvl ) THEN
456
457
458
459
460 CALL dgebak(
'B',
'L', n, ilo, ihi, work( ibal ), n, vl,
461 $ ldvl,
462 $ ierr )
463
464
465
466 DO 20 i = 1, n
467 IF( wi( i ).EQ.zero ) THEN
468 scl = one /
dnrm2( n, vl( 1, i ), 1 )
469 CALL dscal( n, scl, vl( 1, i ), 1 )
470 ELSE IF( wi( i ).GT.zero ) THEN
472 $
dnrm2( n, vl( 1, i+1 ), 1 ) )
473 CALL dscal( n, scl, vl( 1, i ), 1 )
474 CALL dscal( n, scl, vl( 1, i+1 ), 1 )
475 DO 10 k = 1, n
476 work( iwrk+k-1 ) = vl( k, i )**2 + vl( k, i+1 )**2
477 10 CONTINUE
478 k =
idamax( n, work( iwrk ), 1 )
479 CALL dlartg( vl( k, i ), vl( k, i+1 ), cs, sn, r )
480 CALL drot( n, vl( 1, i ), 1, vl( 1, i+1 ), 1, cs, sn )
481 vl( k, i+1 ) = zero
482 END IF
483 20 CONTINUE
484 END IF
485
486 IF( wantvr ) THEN
487
488
489
490
491 CALL dgebak(
'B',
'R', n, ilo, ihi, work( ibal ), n, vr,
492 $ ldvr,
493 $ ierr )
494
495
496
497 DO 40 i = 1, n
498 IF( wi( i ).EQ.zero ) THEN
499 scl = one /
dnrm2( n, vr( 1, i ), 1 )
500 CALL dscal( n, scl, vr( 1, i ), 1 )
501 ELSE IF( wi( i ).GT.zero ) THEN
503 $
dnrm2( n, vr( 1, i+1 ), 1 ) )
504 CALL dscal( n, scl, vr( 1, i ), 1 )
505 CALL dscal( n, scl, vr( 1, i+1 ), 1 )
506 DO 30 k = 1, n
507 work( iwrk+k-1 ) = vr( k, i )**2 + vr( k, i+1 )**2
508 30 CONTINUE
509 k =
idamax( n, work( iwrk ), 1 )
510 CALL dlartg( vr( k, i ), vr( k, i+1 ), cs, sn, r )
511 CALL drot( n, vr( 1, i ), 1, vr( 1, i+1 ), 1, cs, sn )
512 vr( k, i+1 ) = zero
513 END IF
514 40 CONTINUE
515 END IF
516
517
518
519 50 CONTINUE
520 IF( scalea ) THEN
521 CALL dlascl(
'G', 0, 0, cscale, anrm, n-info, 1,
522 $ wr( info+1 ),
523 $ max( n-info, 1 ), ierr )
524 CALL dlascl(
'G', 0, 0, cscale, anrm, n-info, 1,
525 $ wi( info+1 ),
526 $ max( n-info, 1 ), ierr )
527 IF( info.GT.0 ) THEN
528 CALL dlascl(
'G', 0, 0, cscale, anrm, ilo-1, 1, wr, n,
529 $ ierr )
530 CALL dlascl(
'G', 0, 0, cscale, anrm, ilo-1, 1, wi, n,
531 $ ierr )
532 END IF
533 END IF
534
535 work( 1 ) = maxwrk
536 RETURN
537
538
539
subroutine xerbla(srname, info)
subroutine dgebak(job, side, n, ilo, ihi, scale, m, v, ldv, info)
DGEBAK
subroutine dgebal(job, n, a, lda, ilo, ihi, scale, info)
DGEBAL
subroutine dgehrd(n, ilo, ihi, a, lda, tau, work, lwork, info)
DGEHRD
subroutine dhseqr(job, compz, n, ilo, ihi, h, ldh, wr, wi, z, ldz, work, lwork, info)
DHSEQR
integer function idamax(n, dx, incx)
IDAMAX
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
double precision function dlamch(cmach)
DLAMCH
double precision function dlange(norm, m, n, a, lda, work)
DLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
double precision function dlapy2(x, y)
DLAPY2 returns sqrt(x2+y2).
subroutine dlartg(f, g, c, s, r)
DLARTG generates a plane rotation with real cosine and real sine.
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
logical function lsame(ca, cb)
LSAME
real(wp) function dnrm2(n, x, incx)
DNRM2
subroutine drot(n, dx, incx, dy, incy, c, s)
DROT
subroutine dscal(n, da, dx, incx)
DSCAL
subroutine dtrevc3(side, howmny, select, n, t, ldt, vl, ldvl, vr, ldvr, mm, m, work, lwork, info)
DTREVC3
subroutine dorghr(n, ilo, ihi, a, lda, tau, work, lwork, info)
DORGHR