~ubuntu-branches/ubuntu/karmic/scilab/karmic

« back to all changes in this revision

Viewing changes to routines/control/bdiag.f

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2002-03-21 16:57:43 UTC
  • Revision ID: james.westby@ubuntu.com-20020321165743-e9mv12c1tb1plztg
Tags: upstream-2.6
ImportĀ upstreamĀ versionĀ 2.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
      subroutine bdiag(lda,n,a,epsshr,rmax,er,ei,bs,x,xi,scale,
 
2
     1                 job,fail)
 
3
c
 
4
c!purpose
 
5
c   dbdiag reduces a matrix a to block diagonal form by first
 
6
c   reducing it to quasi-triangular form by hqror2 and then by
 
7
c   solving the matrix equation -a11*p+p*a22=a12 to introduce zeros
 
8
c   above the diagonal.
 
9
c   right transformation is factored : p*d*u*y ;where:
 
10
c     p is a permutation matrix and d positive diagonal matrix
 
11
c     u is orthogonal and y block upper triangular with identity
 
12
c     blocks on the diagonal
 
13
c
 
14
c!calling sequence
 
15
c
 
16
c     subroutine bdiag(lda,n,a,epsshr,rmax,er,ei,bs,x,xi,scale,
 
17
c    * job,fail)
 
18
c
 
19
c     integer lda, n,  bs, job
 
20
c     double precision a,er,ei,x,xi,rmax,epsshr,scale
 
21
c     dimension a(lda,n),x(lda,n),xi(lda,n),er(n),ei(n),bs(n)
 
22
c     dimension scale(n)
 
23
c     logical fail
 
24
c
 
25
c   starred parameters are altered by the subroutine
 
26
c
 
27
c
 
28
c  *a        an array that initially contains the m x n matrix
 
29
c            to be reduced. on return,  see job
 
30
c
 
31
c   lda      the leading dimension of array a. and array x,xi.
 
32
c
 
33
c   n        the order of the matrices a,x,xi
 
34
c
 
35
c   epsshr   the minimal conditionnement allowed for linear sytems
 
36
c
 
37
c   rmax     the maximum size allowed for any element of the
 
38
c            transformations.
 
39
c
 
40
c  *er       a singly subscripted real array containing the real
 
41
c            parts of the eigenvalues.
 
42
c
 
43
c  *ei       a singly subscripted real array containg the imaginary
 
44
c            parts of the eigenvalues.
 
45
c
 
46
c  *bs       a singly subscripted integer array that contains block
 
47
c            structure information.  if there is a block of order
 
48
c            k starting at a(l,l) in the output matrix a, then
 
49
c            bs(l) contains the positive integer k, bs(l+1) contains
 
50
c            -(k-1), bs(la+2) = -(k-2), ..., bs(l+k-1) = -1.
 
51
c            thus a positive integer in the l-th entry of bs
 
52
c            indicates a new block of order bs(l) starting at a(l,l).
 
53
c
 
54
c  *x        contains,  either right reducing transformation u*y,
 
55
c            either orthogonal tranformation u (see job)
 
56
c
 
57
c  *xi       xi contains the inverse reducing matrix transformation
 
58
c               or y matrix (see job)
 
59
c
 
60
c  *scale    contains the scale factor and definitions of p size(n)
 
61
c
 
62
c   job      integer parametre specifying outputed transformations
 
63
c            job=0 : a contains block diagonal form
 
64
c                    x right transformation
 
65
c                    xi dummy variable
 
66
c            job=1:like job=0 and xi contain x**-1
 
67
c            job=2 a contains block diagonal form
 
68
c                  x contains u and xi contain y
 
69
c            job=3: a contains:
 
70
c                      -block diagonal form in the diagonal blocks
 
71
c                      -a factorisation of y in the upper triangular
 
72
c                   x contains u
 
73
c                   xi dummy
 
74
c  *fail     a logical variable which is false on normal return and
 
75
c            true if there is any error in bdiag.
 
76
c
 
77
c
 
78
c!auxiliary routines
 
79
c     orthes ortran (eispack)
 
80
c     hqror2 exch split (eispack.extensions)
 
81
c     dset ddot (blas)
 
82
c     real dble abs (fortran)
 
83
c     shrslv dad
 
84
c
 
85
c!
 
86
c
 
87
      integer lda, n,  bs, job
 
88
      double precision a,er,ei,x,xi,rmax,epsshr,scale(n)
 
89
      dimension a(lda,n),x(lda,n),xi(lda,n),er(n),ei(n),bs(n)
 
90
      logical fail,fails
 
91
c
 
92
      double precision c,cav,d,e1,e2,rav,temp,zero,one,mone,ddot,eps
 
93
      double precision dlamch
 
94
      integer da11,da22,i,j,k,km1,km2,l11,l22,l22m1,nk,ino
 
95
      integer low,igh
 
96
      data zero, one, mone /0.0d+0,1.0d+0,-1.0d+0/
 
97
c
 
98
c
 
99
      fail = .false.
 
100
      fails= .true.
 
101
      ino  =  -1
 
102
c
 
103
c     compute eps the l1 norm of the a matrix
 
104
c
 
105
      eps=0.0d0
 
106
      do 11 j=1,n
 
107
         temp=0.0d0
 
108
         do 10 i=1,n
 
109
            temp=temp+abs(a(i,j))
 
110
 10      continue
 
111
         eps=max(eps,temp)
 
112
 11   continue
 
113
      if (eps.eq.0.0d0) eps=1.0d0
 
114
      eps=dlamch('p')*eps
 
115
 
 
116
 
 
117
c
 
118
c     convert a to upper hessenberg form.
 
119
c
 
120
      call balanc(lda, n,   a, low, igh, scale)
 
121
      call orthes(lda, n, low, igh,   a, er)
 
122
      call ortran(lda, n, low, igh,   a, er, x)
 
123
c
 
124
c     convert a to quasi-upper triangular form by qr method.
 
125
c
 
126
      call hqror2(lda,n,1,n,a,er,ei,x,ierr,21)
 
127
c
 
128
c     check to see if hqror2 failed in computing any eigenvalue
 
129
c
 
130
c
 
131
      if(ierr.gt.1) goto 600
 
132
c
 
133
c     reduce a to block diagonal form
 
134
c
 
135
c
 
136
c     segment a into 4 matrices: a11, a da11 x da11 block
 
137
c     whose (1,1)-element is at a(l11,l11))  a22, a da22 x da22
 
138
c     block whose (1,1)-element is at a(l22,l22)) a12,
 
139
c     a da11 x da22 block whose (1,1)-element is at a(l11,l22))
 
140
c     and a21, a da22 x da11 block = 0 whose (1,1)-
 
141
c     element is at a(l22,l11).
 
142
c
 
143
c
 
144
c
 
145
c     this loop uses l11 as loop index and splits off a block
 
146
c     starting at a(l11,l11).
 
147
c
 
148
c
 
149
      l11 = 1
 
150
   40 continue
 
151
      if (l11.gt.n) go to 350
 
152
      l22 = l11
 
153
c
 
154
c       this loop uses da11 as loop variable and attempts to split
 
155
c       off a block of size da11 starting at a(l11,l11)
 
156
c
 
157
   50 continue
 
158
      if (l22.ne.l11) go to 60
 
159
      da11 = 1
 
160
      if(l11 .eq. n) go to 51
 
161
      if(abs(a(l11+1,l11)) .gt.eps ) then
 
162
         da11 = 2
 
163
      endif
 
164
   51 continue
 
165
      l22 = l11 + da11
 
166
      l22m1 = l22 - 1
 
167
      go to 240
 
168
   60 continue
 
169
c
 
170
c
 
171
c           compute the average of the eigenvalues in a11
 
172
c
 
173
      rav = zero
 
174
      cav = zero
 
175
      do 70 i=l11,l22m1
 
176
         rav = rav + er(i)
 
177
         cav = cav + abs(ei(i))
 
178
   70 continue
 
179
      rav = rav/dble(real(da11)   )
 
180
      cav = cav/dble(real(da11)   )
 
181
c
 
182
c           loop on eigenvalues of a22 to find the one closest to the av
 
183
c
 
184
      d = (rav-er(l22))**2 + (cav-ei(l22))**2
 
185
      k = l22
 
186
      l = l22 + 1
 
187
      if(l22 .eq. n) go to 71
 
188
      if(abs(a(l22+1,l22)) .gt. eps) l = l22 + 2
 
189
   71 continue
 
190
   80 continue
 
191
      if (l.gt.n) go to 100
 
192
      c = (rav-er(l))**2 + (cav-ei(l))**2
 
193
      if (c.ge.d) go to 90
 
194
      k = l
 
195
      d = c
 
196
   90 continue
 
197
      l = l + 1
 
198
      if(l.gt.n) go to 100
 
199
      if (abs(a(l,l-1)).gt.eps) l=l+1
 
200
      go to 80
 
201
  100 continue
 
202
c
 
203
c
 
204
c           loop to move the eigenvalue just located
 
205
c           into first position of block a22.
 
206
c
 
207
      if (k.eq.n) goto 105
 
208
      if (abs(a(k+1,k)).gt.eps) go to 150
 
209
c
 
210
c             the block we're moving to add to a11 is a 1 x 1
 
211
c
 
212
  105 nk = 1
 
213
  110 continue
 
214
      if (k.eq.l22) go to 230
 
215
      km1 = k - 1
 
216
      if (abs(a(km1,k-2)).lt.eps) go to 140
 
217
c
 
218
c             we're swapping the closest block with a 2 x 2
 
219
c
 
220
      km2 = k - 2
 
221
      call exch(lda,n,a, x, km2, 2, 1)
 
222
c
 
223
c             try to split this block into 2 real eigenvalues
 
224
c
 
225
      call split(a, x, n, km1, e1, e2, lda, lda)
 
226
      if (a(k,km1).eq.zero) go to 120
 
227
c
 
228
c             block is still complex.
 
229
c
 
230
      er(km2) = er(k)
 
231
      ei(km2) = zero
 
232
      er(k) = e1
 
233
      er(km1) = e1
 
234
      ei(km1) = e2
 
235
      ei(k) = -e2
 
236
      go to 130
 
237
c
 
238
c             complex block split into two real eigenvalues.
 
239
c
 
240
  120 continue
 
241
      er(km2) = er(k)
 
242
      er(km1) = e1
 
243
      er(k) = e2
 
244
      ei(km2) = zero
 
245
      ei(km1) = zero
 
246
  130 k = km2
 
247
      if (k.le.l22) go to 230
 
248
      go to 110
 
249
c
 
250
c
 
251
c             we're swapping the closest block with a 1 x 1.
 
252
c
 
253
  140 continue
 
254
      call exch(lda,n,a, x, km1, 1, 1)
 
255
      temp = er(k)
 
256
      er(k) = er(km1)
 
257
      er(km1) = temp
 
258
      k = km1
 
259
      if (k.le.l22) go to 230
 
260
      go to 110
 
261
c
 
262
c             the block we're moving to add to a11 is a 2 x 2.
 
263
c
 
264
  150 continue
 
265
      nk = 2
 
266
  160 continue
 
267
      if (k.eq.l22) go to 230
 
268
      km1 = k - 1
 
269
      if (abs(a(km1,k-2)).lt.eps) goto 190
 
270
c
 
271
c             we're swapping the closest block with a 2 x 2 block.
 
272
c
 
273
      km2 = k - 2
 
274
      call exch(lda,n,a, x, km2, 2, 2)
 
275
c
 
276
c             try to split swapped block into two reals.
 
277
c
 
278
      call split(a, x, n, k, e1, e2, lda, lda)
 
279
      er(km2) = er(k)
 
280
      er(km1) = er(k+1)
 
281
      ei(km2) = ei(k)
 
282
      ei(km1) = ei(k+1)
 
283
      if (a(k+1,k).eq.zero) go to 170
 
284
c
 
285
c             still complex block.
 
286
c
 
287
      er(k) = e1
 
288
      er(k+1) = e1
 
289
      ei(k) = e2
 
290
      ei(k+1) = -e2
 
291
      go to 180
 
292
c
 
293
c             two real roots.
 
294
c
 
295
  170 continue
 
296
      er(k) = e1
 
297
      er(k+1) = e2
 
298
      ei(k) = zero
 
299
      ei(k+1) = zero
 
300
  180 continue
 
301
      k = km2
 
302
      if (k.eq.l22) go to 210
 
303
      go to 160
 
304
c
 
305
c             we're swapping the closest block with a 1 x 1.
 
306
c
 
307
  190 continue
 
308
      call exch(lda,n,a, x, km1, 1, 2)
 
309
      er(k+1) = er(km1)
 
310
      er(km1) = er(k)
 
311
      ei(km1) = ei(k)
 
312
      ei(k) = ei(k+1)
 
313
      ei(k+1) = zero
 
314
      go to 200
 
315
c
 
316
  200 continue
 
317
      k = km1
 
318
      if (k.eq.l22) go to 210
 
319
      go to 160
 
320
c
 
321
c             try to split relocated complex block.
 
322
c
 
323
  210 continue
 
324
      call split(a, x, n, k, e1, e2, lda, lda)
 
325
      if (a(k+1,k).eq.zero) go to 220
 
326
c
 
327
c             still complex.
 
328
c
 
329
      er(k) = e1
 
330
      er(k+1) = e1
 
331
      ei(k) = e2
 
332
      ei(k+1) = -e2
 
333
      go to 230
 
334
c
 
335
c             split into two real eigenvalues.
 
336
c
 
337
  220 continue
 
338
      er(k) = e1
 
339
      er(k+1) = e2
 
340
      ei(k) = zero
 
341
      ei(k+1) = zero
 
342
c
 
343
  230 continue
 
344
      da11 = da11 + nk
 
345
      l22 = l11 + da11
 
346
      l22m1 = l22 - 1
 
347
  240 continue
 
348
      if (l22.gt.n) go to 290
 
349
c
 
350
c       attempt to split off a block of size da11.
 
351
c
 
352
      da22 = n - l22 + 1
 
353
c
 
354
c       save a12 in its transpose form in block a21.
 
355
c
 
356
      do 260 j=l11,l22m1
 
357
         do 250 i=l22,n
 
358
            a(i,j) = a(j,i)
 
359
  250    continue
 
360
  260 continue
 
361
c
 
362
c
 
363
c       convert a11 to lower quasi-triangular and multiply it by -1 and
 
364
c       a12 appropriately (for solving -a11*p+p*a22=a12).
 
365
c
 
366
      call dad(a, lda, l11, l22m1, l11, n, one, 0)
 
367
      call dad(a, lda, l11, l22m1, l11, l22m1, mone, 1)
 
368
c
 
369
c       solve -a11*p + p*a22 = a12.
 
370
c
 
371
      call shrslv(a(l11,l11), a(l22,l22), a(l11,l22), da11,
 
372
     * da22, lda, lda, lda, eps,epsshr,rmax, fails)
 
373
      if (.not.fails) go to 290
 
374
c
 
375
c       change a11 back to upper quasi-triangular.
 
376
c
 
377
      call dad(a, lda, l11, l22m1, l11, l22m1, one, 1)
 
378
      call dad(a, lda, l11, l22m1, l11, l22m1, mone, 0)
 
379
c
 
380
c       was unable to solve for p - try again
 
381
c
 
382
c
 
383
c       move saved a12 back into its correct position.
 
384
c
 
385
      do 280 j=l11,l22m1
 
386
         do 270 i=l22,n
 
387
            a(j,i) = a(i,j)
 
388
            a(i,j) = zero
 
389
  270    continue
 
390
  280 continue
 
391
c
 
392
c
 
393
      go to 50
 
394
  290 continue
 
395
c
 
396
c     change solution to p to proper form.
 
397
c
 
398
      if (l22.gt.n) go to 300
 
399
      call dad(a, lda, l11, l22m1, l11, n, one, 0)
 
400
      call dad(a, lda, l11, l22m1, l11, l22m1, mone, 1)
 
401
 
 
402
c
 
403
c     store block size in array bs.
 
404
c
 
405
  300 bs(l11) = da11
 
406
      j = da11 - 1
 
407
      if (j.eq.0) go to 320
 
408
      do 310 i=1,j
 
409
         l11pi = l11 + i
 
410
         bs(l11pi) = -(da11-i)
 
411
  310 continue
 
412
  320 continue
 
413
      l11 = l22
 
414
      go to 40
 
415
  350 continue
 
416
      fail=.false.
 
417
c
 
418
c     set transformations matrices as required
 
419
c
 
420
      if(job.eq.3) return
 
421
c
 
422
c compute inverse transformation
 
423
      if(job.ne.1) goto 450
 
424
      do 410 i=1,n
 
425
      do 410 j=1,n
 
426
      xi(i,j)=x(j,i)
 
427
  410 continue
 
428
      l22=1
 
429
  420 l11=l22
 
430
      l22=l11+bs(l11)
 
431
      if(l22.gt.n) goto 431
 
432
      l22m1=l22-1
 
433
      do 430 i=l11,l22m1
 
434
      do 430 j=1,n
 
435
      xi(i,j)=xi(i,j)-ddot(n-l22m1,a(i,l22),lda,xi(l22,j),1)
 
436
  430 continue
 
437
      goto 420
 
438
c in-lines back-tranfc in-lines right transformations of xi
 
439
  431 continue
 
440
      if (igh .ne. low) then
 
441
         do 435 j=low,igh
 
442
            temp=1.0d+00/scale(j)
 
443
            do 434 i=1,n
 
444
               xi(i,j)=xi(i,j)*temp
 
445
  434       continue
 
446
  435    continue
 
447
      endif
 
448
      do 445 ii=1,n
 
449
         i=ii
 
450
         if (i.ge.low .and. i.le.igh) goto 445
 
451
         if (i.lt.low) i=low-ii
 
452
         k=scale(i)
 
453
         if (k.eq.i) goto 445
 
454
         do 444 j=1,n
 
455
            temp=xi(j,i)
 
456
            xi(j,i)=xi(j,k)
 
457
            xi(j,k)=temp
 
458
  444    continue
 
459
  445 continue
 
460
c
 
461
  450 continue
 
462
      if(job.eq.2) goto 500
 
463
c compute right transformation
 
464
      l22=1
 
465
  460 l11=l22
 
466
      l22=l11+bs(l11)
 
467
      if(l22.gt.n) goto 480
 
468
      do 470 j=l22,n
 
469
      do 470 i=1,n
 
470
      x(i,j)=x(i,j)+ddot(l22-l11,x(i,l11),lda,a(l11,j),1)
 
471
  470 continue
 
472
      goto 460
 
473
c
 
474
  480 continue
 
475
      call balbak( lda, n, low, igh, scale, n, x)
 
476
      goto 550
 
477
c
 
478
c extract non orthogonal tranformation from a
 
479
  500 continue
 
480
      do 510 j=1,n
 
481
      call dset(n,zero,xi(1,j),1)
 
482
  510 continue
 
483
      call dset(n,one,xi(1,1),lda+1)
 
484
      l22=1
 
485
  520 l11=l22
 
486
      if(l11.gt.n) goto 550
 
487
      l22=l11+bs(l11)
 
488
      do 530 j=l22,n
 
489
      do 530 i=1,n
 
490
      xi(i,j)=xi(i,j)+ddot(l22-l11,xi(i,l11),lda,a(l11,j),1)
 
491
  530 continue
 
492
      goto 520
 
493
c
 
494
c set zeros in the matrix a
 
495
  550 l11=1
 
496
  560 l22=l11+bs(l11)
 
497
      if(l22.gt.n) return
 
498
      l22m1=l22-1
 
499
      do 570 j=l11,l22m1
 
500
      call dset(n-l22m1,zero,a(j,l22),lda)
 
501
      call dset(n-l22m1,zero,a(l22,j),1)
 
502
  570 continue
 
503
      l11=l22
 
504
      goto 560
 
505
c
 
506
c     error return.
 
507
c
 
508
  600 continue
 
509
      fail = .true.
 
510
c
 
511
      end