% FIGURE 3.5.2
      function [EIG,V] = DPOWER(A,N,EIG,V,IUPDAT)
%
%  FUNCTION DPOWER FINDS ONE EIGENVALUE OF A, AND A CORRESPONDING
%    EIGENVECTOR, USING THE SHIFTED INVERSE POWER METHOD.
%
%  ARGUMENTS
%
%             ON INPUT                          ON OUTPUT
%             --------                          ---------
%
%    A      - THE N BY N MATRIX.
%
%    N      - THE SIZE OF MATRIX A.
%
%    EIG    - A (COMPLEX) INITIAL GUESS AT      AN EIGENVALUE OF A,
%             AN EIGENVALUE.                    NORMALLY THE ONE CLOSEST
%                                               TO THE INITIAL GUESS.
%
%    V      - A (COMPLEX) STARTING VECTOR       AN EIGENVECTOR OF A,
%             FOR THE SHIFTED INVERSE POWER     CORRESPONDING TO THE
%             METHOD.  IF ALL COMPONENTS OF     COMPUTED EIGENVALUE.
%             V ARE ZERO ON INPUT, A RANDOM
%             STARTING VECTOR WILL BE USED.
%
%    IUPDAT - THE NUMBER OF SHIFTED INVERSE
%             POWER ITERATIONS TO BE DONE
%             BETWEEN UPDATES OF P.  IF
%             IUPDAT=1, P WILL BE UPDATED EVERY
%             ITERATION.  IF IUPDAT > 1000,
%             P WILL NEVER BE UPDATED.
%
%-----------------------------------------------------------------------
%                              EPS = MACHINE FLOATING POINT RELATIVE
%                                    PRECISION
% *****************************
      EPS = eps;
% *****************************
%                             IF V = 0, GENERATE A RANDOM STARTING
%                             VECTOR
      if (V == 0)
      SEED = N+10000;
      DEN = 2.0^31-1.0;
      for I=1:N
         SEED = mod(7^5*SEED,DEN);
         V(I) = SEED/(DEN+1.0);
      end
      end
%                              NORMALIZE V, AND SET VN=V
      VNORM = 0.0;
      for I=1:N
         VNORM = VNORM + abs(V(I))^2;
      end
      VNORM = sqrt(VNORM);
      for I=1:N
         V(I) = V(I)/VNORM;
         VN(I) = V(I);
      end
%                              BEGIN SHIFTED INVERSE POWER ITERATION
      NITER = 1000;
      for ITER=0:NITER
         if (mod(ITER,IUPDAT) == 0)
%                              EVERY IUPDAT ITERATIONS, UPDATE PN
%                              AND SOLVE (A-PN*I)*VNP1 = VN
            PN = EIG;
            for I=1:N
            for J=1:N
               if (I == J)
                  B(I,J) = A(I,J) - PN;
               else
                  B(I,J) = A(I,J);
               end
            end
            end
            [VNP1,IPERM,B] = DLINEQ(B,N,V);
         else
%                              BETWEEN UPDATES, WE CAN USE THE LU
%                              DECOMPOSITION OF B=A-PN*I CALCULATED
%                              EARLIER, TO SOLVE B*VNP1=VN FASTER
            VNP1 = DRESLV(B,N,V,IPERM);
         end
%                              CALCULATE NEW EIGENVALUE ESTIMATE,
%                              PN + (VN*VN)/(VN*VNP1)
         RNUM = 0.0;
         RDEN = 0.0;
         for I=1:N
            RNUM = RNUM + VN(I)*VN(I);
            RDEN = RDEN + VN(I)*VNP1(I);
         end
         R = RNUM/RDEN;
         EIG = PN + R;
%                              SET V = NORMALIZED VNP1
         VNORM = 0.0;
         for I=1:N
            VNORM = VNORM + abs(VNP1(I))^2;
         end
         VNORM = sqrt(VNORM);
         for I=1:N
            V(I) = VNP1(I)/VNORM;
         end
%                              IF R*VNP1 = VN  (R = (VN*VN)/(VN*VNP1) ),
%                              ITERATION HAS CONVERGED.
         ERRMAX = 0.0;
         for I=1:N
            ERRMAX = max(ERRMAX,abs(R*VNP1(I)-VN(I)));
         end
         if (ERRMAX <= sqrt(EPS))
            return
         end
%                              SET VN = V = NORMALIZED VNP1
         for I=1:N
            VN(I) = V(I);
         end
      end
      error('***** INVERSE POWER METHOD DOES NOT CONVERGE *****')
 
