home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / fractal / kaos.lha / eigenlib / balanc.c next >
Encoding:
C/C++ Source or Header  |  1989-11-18  |  5.1 KB  |  178 lines

  1. balanc(nm,n,a,low,igh,scale)
  2.  
  3. int n,nm,*igh,*low;
  4. double **a,*scale;
  5.  
  6. {
  7. int i,j,k,l,m,jj,iexc;
  8. double c,f,g,r,s,b2,radix;
  9. double fabs();
  10. char noconv,skip,cntl; 
  11.  
  12. /*    this subroutine is a translation of the algol procedure balance,
  13.       num. math. 13, 293-304(1969) by parlett and reinsch.
  14.       handbook for auto. comp., vol.ii-linear algebra, 315-326(1971).
  15.  
  16.       this subroutine balances a real matrix and isolates
  17.       eigenvalues whenever possible.
  18.  
  19.       on input
  20.  
  21.          nm must be set to the row dimension of two-dimensional
  22.            array parameters as declared in the calling program
  23.            dimension statement.
  24.  
  25.          n is the order of the matrix.
  26.  
  27.          a contains the input matrix to be balanced.
  28.  
  29.       on output
  30.  
  31.          a contains the balanced matrix.
  32.  
  33.          low and igh are two integers such that a(i,j)
  34.            is equal to zero if
  35.             (1) i is greater than j and
  36.             (2) j=1,...,low-1 or i=igh+1,...,n.
  37.  
  38.          scale contains information determining the
  39.             permutations and scaling factors used.
  40.  
  41.       suppose that the principal submatrix in rows low through igh
  42.       has been balanced, that p(j) denotes the index interchanged
  43.       with j during the permutation step, and that the elements
  44.       of the diagonal matrix used are denoted by d(i,j).  then
  45.          scale(j) = p(j),    for j = 1,...,low-1
  46.                   = d(j,j),      j = low,...,igh
  47.                   = p(j)         j = igh+1,...,n.
  48.       the order in which the interchanges are made is n to igh+1,
  49.       then 1 to low-1.
  50.  
  51.       note that 1 is returned for igh if igh is zero formally.
  52.  
  53.       the algol procedure exc contained in balance appears in
  54.       balanc  in line.  (note that the algol roles of identifiers
  55.       k,l have been reversed.)
  56.  
  57.  
  58.       this routine is a C-translation of the FORTRAN 77 source code
  59.       written by the mathematics and computer science division,
  60.       argonne national laboratory
  61.       last change :   september 1989.
  62.  
  63.       mark myers
  64.       Center for Applied Mathematics 
  65.       Cornell University    (607) 255-4195
  66.       ------------------------------------------------------------------    */
  67.  
  68.  
  69.       radix = 16.e0;
  70.       b2 = radix * radix;
  71.       k = 1;
  72.       l = n;
  73.       cntl = 's';
  74.  
  75. exch: ;
  76.       if (cntl == 's' | cntl == 'r')
  77.     {if (cntl == 'r')
  78.           {if (l == 1)          /* search for rows isolating an eigenvalue */
  79.              {*low = k;          /* and push them down */
  80.           *igh = l;
  81.           return;}
  82.            l = l - 1;}
  83.          for (jj=1;jj<=l;jj++)     /* for j=1 step -1 until 1 do ... */
  84.            {j = l + 1 - jj;
  85.         skip = 'f';
  86.             for (i=1;i<=l;i++)
  87.               {if (i == j) 
  88.             continue ;
  89.                if (a[j][i] != 0.e0)
  90.          {skip = 't';
  91.               break;}}}
  92.          if (skip == 'f')
  93.            {m = l;
  94.         scale[m] = j;
  95.             cntl = 'r';
  96.             if (j != m)
  97.               {for (i=1;i<=l;i++)  
  98.                 {f = a[i][j];
  99.                  a[i][j]=a[i][m];
  100.                  a[i][m] = f;}
  101.                for (i=k;i<=n;i++)
  102.                 {f=a[j][i];
  103.                  a[j][i]=a[m][i];
  104.                  a[m][i]=f;} 
  105.               }
  106.             goto exch;
  107.            }
  108.         }
  109.       else 
  110.         k = k + 1;   /* search for columns isolating an eigenvalue */
  111.                      /* and push them left */
  112.  
  113.       skip = 'f';
  114.       for (j=k;j<=l;j++) 
  115.         {for (i=k;i<=l;i++)
  116.            {if (i == j) 
  117.               continue;
  118.             if (a[i][j] != 0.e0) 
  119.          {skip = 't';
  120.           break;}}
  121.          if (skip == 'f')
  122.            {m = k;
  123.         scale[m] = j;
  124.             cntl = 'c';
  125.             if (j != m)
  126.               {for (i=1;i<=l;i++)  
  127.                  {f = a[i][j];
  128.                   a[i][j]=a[i][m];
  129.                   a[i][m] = f;}
  130.                for (i=k;i<=n;i++)
  131.                  {f=a[j][i];
  132.                   a[j][i]=a[m][i];
  133.                   a[m][i]=f;} }
  134.             goto exch;
  135.            }
  136.         }
  137.       for (i=k;i<=l;i++)                 /* balance submatrix in rows k to l  */
  138.         scale[i] = 1.e0;
  139.       noconv = 't';
  140.       while (noconv == 't')           /* iterative loop for norm reduction */
  141.         {for (i=k;i<=l;i++)
  142.            {c = 0.e0;
  143.             r = 0.e0;
  144.  
  145.             for(j=k;j<=l;j++)
  146.           {if (j != i) 
  147.                  {c = c + fabs(a[j][i]);
  148.                   r = r + fabs(a[i][j]);}  }
  149.  
  150.             if ( c == 0.e0 | r == 0.e0 )        /* guard against zero c or */
  151.           {noconv = 'f';
  152.            continue;}
  153.             g = r / radix;                     /* or due to underflow */ 
  154.             f = 1.e0;
  155.             s = c + r;
  156.             while (c < g) 
  157.               {f = f * radix;
  158.                c = c * b2;}
  159.             g = r * radix;
  160.             while (c>=g) 
  161.               {f = f / radix;
  162.                c = c / b2; }
  163.             if ((c + r) / f >= 0.95e0 * s)         /* now balance */
  164.               {noconv = 'f';
  165.            continue;}
  166.             g = 1.e0 / f;
  167.             scale[i] = scale[i] * f;
  168.           
  169.             for (j=k;j<=n;j++)
  170.                a[i][j] = a[i][j] * g;
  171.           
  172.             for (j=1;j<=l;j++)
  173.                a[j][i]= a[j][i]* f;  
  174.         } }
  175.  *low = k;
  176.  *igh = l;
  177. }
  178.