1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
subroutine inva(nmax,n,a,z,ftest,eps,ndim,fail,ind)
integer nmax,n,ftest,ndim,ind(n)
logical fail
double precision a(nmax,n),z(nmax,n),eps
c!purpose
c given the upper real schur matrix a
c with 1x1 or 2x2 diagonal blocks, this routine reorders the diagonal
c blocks along with their generalized eigenvalues by constructing equi-
c valence transformation. the transformation is also
c performed on the given (initial) transformation z (resulting from a
c possible previous step or initialized with the identity matrix).
c after reordering, the eigenvalues inside the region specified by the
c function ftest appear at the top. if ndim is their number then the
c ndim first columns of z span the requested subspace.
c!calling sequence
c
c subroutine inva (nmax,n,a,z,ftest,eps,ndim,fail,ind)
c integer nmax,n,ftest,ndim,ind(n)
c logical fail
c double precision a(nmax,n),z(nmax,n),eps
c
c nmax the first dimension of a and z
c n the order of a and z
c *a the matrix whose blocks are to be reordered.
c *z upon return this array is multiplied by the column
c transformation z.
c ftest(ls,alpha,beta,s,p) an integer function describing the
c spectrum of the invariant subspace to be computed:
c when ls=1 ftest checks if alpha/beta is in that spectrum
c when ls=2 ftest checks if the two complex conjugate
c roots with sum s and product p are in that spectrum
c if the answer is positive, ftest=1, otherwise ftest=-1
c eps the required absolute accuracy of the result
c *ndim an integer giving the dimension of the computed
c invariant subspace
c *fail a logical variable which is false on a normal return,
c true otherwise (when exchng fails)
c *ind an integer working array of dimension at least n
c
c!auxiliary routines
c exchng
c ftest (user defined)
c!
c Copyright SLICOT
external ftest
integer l,ls,ls1,ls2,l1,ll,num,is,l2i,l2k,i,k,ii,istep,ifirst
double precision s,p,alpha,beta
integer iero
common /ierinv/ iero
iero=0
fail=.false.
ndim=0
num=0
l=0
ls=1
c ** construct array ind(i) where :
c ** abs(ind(i)) is the size of the block i
c ** sign(ind(i)) indicates the location of its eigenvalues
c ** (as determined by ftest).
c ** num is the number of elements in this array
do 40 ll=1,n
l=l+ls
if(l.gt.n) go to 50
l1=l+1
if(l1.gt.n) go to 20
if(a(l1,l).eq.0.0d+0) go to 20
c here a 2x2 block is checked *
ls=2
s=a(l,l)+a(l1,l1)
p=a(l,l)*a(l1,l1)-a(l,l1)*a(l1,l)
is=ftest(ls,alpha,beta,s,p)
if(iero.gt.0) return
go to 30
c here a 1x1 block is checked *
20 ls=1
is=ftest(ls,a(l,l),1.0d+0,s,p)
if(iero.gt.0) return
30 num=num+1
if(is.eq.1) ndim=ndim+ls
40 ind(num)=ls*is
c ** reorder blocks such that those with positive value
c ** of ind(.) appear first.
50 l2i=1
do 90 i=1,num
if(ind(i).gt.0) go to 90
c if a negative ind(i) is encountered, then search for the first
c positive ind(k) following on it
l2k=l2i
do 60 k=i,num
if(ind(k).lt.0) go to 60
go to 70
60 l2k=l2k-ind(k)
c if there are no positive indices following on a negative one
c then stop
go to 100
c if a positive ind(k) follows on a negative ind(i) then
c interchange block k before block i by performing k-i swaps
70 istep=k-i
ls2=ind(k)
l=l2k
do 80 ii=1,istep
ifirst=k-ii
ls1=-ind(ifirst)
l=l-ls1
c call exchng(a,z,n,l,ls1,ls2,eps,fail,nmax,nmax)
call exch(nmax,n,a,z,l,ls1,ls2)
if (fail) return
80 ind(ifirst+1)=ind(ifirst)
ind(i)=ls2
90 l2i=l2i+ind(i)
100 fail=.false.
return
end
|