⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linalg.pas

📁 Delphi math processing compononets and sources. Release.
💻 PAS
📖 第 1 页 / 共 3 页
字号:
      for i:=mn downto 1  do
        begin
          l := i+1;
          G := W[i];
          if i<>N  then
            for j:=l to N  do
              U[i]^[j] := 0.0;
          if G<>0.0  then
            begin
              if i<>mn  then
                for j:=l to N  do
                  begin
                    S := 0.0;
                    for k:=l to M  do
                      S := S+U[k]^[i]*U[k]^[j];
                    F := (S/U[i]^[i]) / G;
                    for k:=i to M  do
                      U[k]^[j] := U[k]^[j]+F*U[k]^[i];
                  end;
              for j:=i to M  do
                U[j]^[i] := U[j]^[i]/G;
            end      else
            for j:=i to M  do
              U[j]^[i] := 0.0;

          U[i]^[i] := U[i]^[i]+1.0;

        end;
    end;

  { Diagonalization of the two-diagonal form }
  for k:=N downto 1  do
    begin
      k1  := k-1;
      its := 0;

      repeat
        ExitKey  := 0;
        l        := k+1;
        while (ExitKey=0) and (l>1)  do
          begin
            dec(l);
            l1 := l-1;
            if  abs(RV1[l])+ANorm = ANorm   then   ExitKey:=1
            else  if  l1>0  then
              if abs(W[l1])+ANorm = ANorm   then   ExitKey:=2;
          end;

        if ExitKey<>1  then
          begin
            C       := 0.0;
            S       := 1.0;
            ExitKey := 0;
            i       := l;
            while (ExitKey=0) and (i<=k)  do
              begin
                F       :=  S*RV1[i];
                RV1[i]  :=  C*RV1[i];
                if abs(F)+ANorm = ANorm  then   ExitKey := 1
                                         else
                  begin
                    G := W[i];
                    H := SrX2Y2(F,G);
                    W[i] := H;
                    C := G/H;
                    S := -F/H;
                    if  MatU  then
                      for j:=1 to M  do
                        begin
                          Y          :=  U[j]^[l1];
                          Z          :=  U[j]^[i];
                          U[j]^[l1]  :=  Y*C+Z*S;
                          U[j]^[i]   :=  -Y*S+Z*C
                        end;
                    inc(i);
                  end;
              end;
          end;

        { Convergency  Check }
        Z := W[k];
        if l<>k  then
          begin
            if its=Itnlimit  then
              begin
                RetCode := k;    Exit;
              end;
            inc(its);
            X  :=  W[l];
            Y  :=  W[k1];
            G  :=  RV1[k1];
            H  :=  RV1[k];
            F  :=  ((Y-Z)*(Y+Z) + (G-H)*(G+H)) /(2.0*H*Y);
            if  abs(F)<=1.0  then   GG := Sign2(sqrt(F*F+1.0),F)
                             else   GG := F*sqrt(1.0+1.0/F/F);
            F  :=  ((X-Z)*(X+Z) + H*(Y/(F+GG)-H)) / X;

       { Next  QR - Transformation  }
            C  :=  1.0;
            S  :=  1.0;
            for i1:=l to k1  do
              begin
                i := i1+1;
                G := RV1[i];
                Y := W[i];
                H := S*G;
                G := C*G;
                Z := SrX2Y2(F,H);
                RV1[i1] := Z;
                C := F/Z;
                S := H/Z;
                F := X*C+G*S;
                G := -X*S+G*C;
                H := Y*S;
                Y := Y*C;
                if  MatV  then
                  for j:=1 to N  do
                    begin
                      X          :=  V[j]^[i1];
                      Z          :=  V[j]^[i];
                      V[j]^[i1]  :=  X*C+Z*S;
                      V[j]^[i]   :=  -X*S+Z*C;
                    end;

                Z := SrX2Y2(F,H);
                W[i1] := Z;
                if Z<>0.0  then
                  begin
                    C := F/Z;
                    S := H/Z;
                  end;
                F := C*G+S*Y;
                X := -S*G+C*Y;
                if  MatU  then
                  for J:=1 to M  do
                    begin
                      Y          :=  U[j]^[i1];
                      Z          :=  U[j]^[i];
                      U[j]^[i1]  :=  Y*C+Z*S;
                      U[j]^[i]   :=  -Y*S+Z*C;
                    end;

              end;

            RV1[l] := 0.0;
            RV1[k] := F;
            W[k]   := X;
          end

          else if Z<0.0  then
            begin
              W[k] := -Z;
              if  MatV  then
                for j:=1 to N  do
                  V[j]^[k] := -V[j]^[k];
            end;
        until  l=k;
    end;{ Of the kk-loop }

  if NA = N  then
    for i:=1 to M  do
      for j:=1 to N  do
      begin
        G := V[i]^[j];
        V[i]^[j] := U[i]^[j];
        U[i]^[j] := G;
      end;
end;{ SVD }

{ sorting }
procedure OrderSVD(M,N: integer; const U,V: Matrix; var W: Vector;
                      MatU, MatV: boolean );
var
  i,k,j: integer;
  P  : RealType;

begin

  {  External loop of the re-ordering  }
  for i:=1 to N-1  do
    begin
      k := i;
      P := W[i];

      { Internal loop: finding of the index of the largest
       singular value among the remaining }
      for j:=i+1 to N  do
        if  W[j]>P  then
          begin
            k := j;   P := W[j];
          end;

      if  k<>i  then
        begin
          { swapping  of the singular values }
          W[k] := W[i];
          W[i] := P;
          for j:=1 to M  do
            begin
              { swapping of the U's columns (if needed) }
              if  MatU  then
                begin
                  P        := U[j]^[i];
                  U[j]^[i] := U[j]^[k];
                  U[j]^[k] := P;
                end;
              { swapping of the V's columns (if needed)}
              if  MatV  then
                begin
                  P        := V[j]^[i];
                  V[j]^[i] := V[j]^[k];
                  V[j]^[k] := P;
                end;
            end;
        end;
    end;
end;

{ Perturbated Cholesky Decomposition }
procedure CholDecomp(N : integer; var HDiag: Vector; MaxOff,MachEps: RealType;
                        const L: Matrix; var MaxAdd: RealType);
var
  i,j,k       : integer;
  MinL, MinL2, S, MinLjj: RealType;
  MaxOffl     : RealType;

begin
  MaxOffl := MaxOff;
  MinL   := sqrt(sqrt(MachEps))*MaxOffl;
  if MaxOffl=0.0  then
    begin
      for i:=1 to N  do
        if abs(HDiag[i])>MaxOffl  then
                    MaxOffl := abs(HDiag[i]);
      MaxOffl := sqrt(MaxOffl);
    end;

  MinL2  := sqrt(MachEps)*MaxOffl;
  MaxAdd := 0.0;
  for j:=1 to N  do
    begin
      S := 0.0;
      if j>1  then
        for i:=1 to j-1  do
          S := S+sqr(L[j]^[i]);
      L[j]^[j] := HDiag[j]-S;
      MinLjj := 0.0;
      if j<N  then
        for i:=j+1 to N  do
          begin
            S := 0.0;
            if j>1  then
              for k:=1 to j-1  do
                S := S+L[i]^[k]*L[j]^[k];
            L[i]^[j] := L[j]^[i]-S;
            if abs(L[i]^[j])>MinLjj  then
                   MinLjj := abs(L[i]^[j]);
          end;
      if MinLjj/MaxOffl>MinL  then
                   MinLjj := MinLjj/MaxOffl
            else   MinLjj := MinL;
      if L[j]^[j]>sqr(MinLjj)  then
                 L[j]^[j] := sqrt(L[j]^[j])
                               else
        begin
          if MinL2>MinLjj  then  MinLjj := MinL2;
          if sqr(MinLjj)-L[j]^[j]>MaxAdd  then
                         MaxAdd := sqr(MinLjj)-L[j]^[j];
          L[j]^[j] := MinLjj;
        end;
      if j<N  then
        for i:=j+1 to N  do
          L[i]^[j] := L[i]^[j]/L[j]^[j];
    end;
end;

{ Cholesky   L - Solution  of L*Y  =  B (given  B)  }
procedure LSolve(N: integer; const L: Matrix;  var B,Y: Vector );
var
  i,j: integer;
begin
  Y[1] := B[1]/L[1]^[1];
  if  N>1  then
    for i:=2 to N  do
      begin
        Y[i] := B[i];
        for j:=1 to i-1  do
          Y[i] := Y[i]-L[i]^[j]*Y[j];
        Y[i] := Y[i]/L[i]^[i];
      end;
end;

{ Cholesky   LT - Solution  of LT*X  =  Y (given Y )   }
procedure LTSolve(N: integer; const L: Matrix;  var Y,X: Vector );
var
  i,j: integer;
begin
  X[N] := Y[N]/L[N]^[N];
  if  N>1  then
    for i:=N-1 downto 1  do
      begin
        X[i] := Y[i];
        for j:=i+1 to N  do
          X[i] := X[i]-L[j]^[i]*X[j];
        X[i] := X[i]/L[i]^[i];
      end;
end;

{ Solution of the equation    L*LT*S = G by the  Cholesky  method    }
procedure ChSolve(N: integer; const L: Matrix; var G,S: Vector );
var
  i: integer;
begin
  LSolve (N,L,G,S);
  LTSolve(N,L,S,S);
  for i:=1 to N  do
    S[i] := -S[i];
end;

{ @lastmod(10.10.2002) }
procedure CholBandDec(N,p: integer; const H,L: Matrix);
var
  i,j,k,m: integer;
  p1,i1,j1: integer;
  S: RealType;
begin
  p1 := p+1;
  for j:=1 to N  do
    begin
      S  := 0.0;
      j1 := p+1-j;
      if j>1  then
        for i:=Max(j-p,1) to j-1  do
          S := S+sqr(L[i+j1]^[i]);
      L[p1]^[j] := sqrt(H[p1]^[j]-S);
      if j<N  then
        for i:=j+1 to Min(j+p,N)  do
          begin
            S  := 0.0;
            i1 := p+1-i;
            m  := Max(i-p,1);
            if j>m  then
              for k:=m to j-1  do
                S := S+L[k+i1]^[k]*L[k+j1]^[k];
            L[j+i1]^[j] := (H[j+i1]^[j]-S)/L[p1]^[j];
          end;
    end;
end;

{ Cholesky   L - Solution  of L*Y  =  B (given  B)  }
procedure LBandSolve(N,p: integer; const L: Matrix; var B,Y: Vector );
var
  i,j,p1,i1: integer;
  S: RealType;
begin
  p1 := p+1;
  Y[1] := B[1]/L[p1]^[1];
  if  N>1  then
    for i:=2 to N  do
      begin
        S  := B[i];
        i1 := p+1-i;
        for j:=Max(i-p,1) to i-1  do
          S := S - L[j+i1]^[j]*Y[j];
        Y[i] := S/L[p1]^[i];
      end;
end;

{ Cholesky   LT - Solution  of LT*X  =  Y (given  Y )   }
procedure LTBandSolve(N,p: integer;  const L: Matrix; var Y,X: Vector );
var
  i,j,p1,i1: integer;
begin
  p1 := p+1;
  X[N] := Y[N]/L[p1]^[N];
  if  N>1  then
    for i:=N-1 downto 1  do
      begin
        X[i] := Y[i];
        i1   := p+i+1;
        for j:=i+1 to Min(i+p,N)  do
          X[i] := X[i]-L[i1-j]^[i]*X[j];
        X[i] := X[i]/L[p1]^[i];
      end;
end;

{  Solution of the equation    L*LT*S = G   by the  Cholesky  method    }
procedure ChBandSolve(N,p: integer; const L: Matrix; var G,S: Vector );
begin
  LBandSolve (N,p,L,G,S);
  LTBandSolve(N,p,L,S,S);
end;

{ QR - Decomposition of the  M  }
procedure QRDecomp(N: integer; const M: Matrix; var M1,M2: Vector;
                    var Sing: boolean);
var
  i,j,k: integer;
  Etha,Norm,Tau: RealType;
begin

  Sing := false;  {  set true if the degeneracy of M is found }
  if N>1  then
    for k:=1 to N-1  do
      begin
        Etha := 0.0;
        for i:=k to N  do
          if abs(M[i]^[k])>Etha  then
            Etha := abs(M[i]^[k]);
        if Etha=0.0  then
          begin
            {  degeneracy is found  }
            M1[k] := 0.0;
            M2[k] := 0.0;
            Sing  := true;
          end        else
          begin
            Norm := 0.0;
            for i:=k to N  do
              begin
                M[i]^[k] := M[i]^[k]/Etha;
                Norm := Norm + sqr(M[i]^[k]);
              end;
            Norm := sqrt(Norm);
            if M[k]^[k]<0.0  then  Norm := -Norm;
            M[k]^[k] := M[k]^[k] + Norm;
            M1[k]    := Norm*M[k]^[k];
            M2[k]    := -Etha*Norm;
            for j:=k+1 to N  do
              begin
                Tau := 0.0;
                for i:=k to N  do
                  Tau := Tau + M[i]^[k]*M[i]^[j];
                Tau := Tau/M1[k];
                for i:=k to N  do
                  M[i]^[j] := M[i]^[j] - Tau*M[i]^[k];
              end;
          end;
      end;

  if M[N]^[N]=0.0  then  Sing := true;
  M2[N] := M[N]^[N];

end;

{ This routine solves  R*X = B  for  X , where  R  is placed in the  M  by the
   QRDecomp  routine ;   X  is returned in the  B }
procedure RSolve(N: integer; const M: Matrix; var M2,B: Vector );
var
  i,j: integer;
begin
  B[N] := B[N]/M2[N];
  if  N>1  then
    for i:=N-1 downto 1  do
      begin
        for j:=i+1 to N  do
          B[i] := B[i]-M[i]^[j]*B[j];
        B[i] := B[i]/M2[i];
      end;
end;

{ This routine solves the equation  (QR)*X = B,
  where Q and R are placed in the  M  by the QRDecomp  routine;
  the computed  X  is returned   in the  B .}
procedure QRSolve(N: integer; const M: Matrix; var M1,M2,B: Vector );
var
  i,j: integer;
  Tau: RealType;
begin
  {  1.  B := QT*B  }
  if  N>1  then
    for j:=1 to N-1  do
      begin
        {  B := Qj*B  }
        Tau := 0.0;
        for i:=j to N  do
          Tau := Tau + M[i]^[j]*B[i];
        Tau := Tau/M1[j];
        for i:=j to N  do
          B[i] := B[i] - Tau*M[i]^[j];
      end;
  {  2.  B := R**(-1)*B  }
  RSolve(N,M,M2,B);
end;

{ Gram-Schmidt Orthogonalization                      }
{ On input:                                           }
{ VT -  row vectors;  Vi[k] = VT[i,k]                 }
{ Nvec - number of vectors to be normalized           }
{ On output:                                          }
{ VT: <Vi|Vi> = 1, <Vi|Vj> = 0, i <> j                }
{ Nvec is the actual number of orthogonalized vectors }
procedure Gram_Schmidt(var Nvec: IntType; N: IntType; var VT: Matrix);
var
  m, k, i: IntType;
  vk, vm: VcPtr;
  x, nn: RealType;
begin
  m := 1;
  while m <= Nvec do
  begin
    // find the largest vector
    i := m;
    nn := 0.0;
    for k := m to Nvec do
    begin
      x := Norm2V(N, VT[k]^); // <Vk|Vk> = |Vk|**2
      if x > nn then
      begin
        nn := x;
        i := k;
      end;
    end;
    // move it in the beginning
    vm := VT[i];
    VT[i] := VT[m];
    VT[m] := vm;
    if nn > MinReal then
    begin // |Vm| > 0
      x := 1.0/sqrt(nn);    // 1/|Vm|
      VxR(N, vm^,vm^,x);   // m-th vector (row) is normalized
      for k := m+1 to Nvec do
      begin
        vk := VT[k];
        x := VTxV(N, vk^,vm^);          // x := <Vk|Vm>
        CombineV(N,vk^,vk^,vm^,1.0,-x); // Vk := Vk - x*Vm
      end;
      inc(m);
    end else // Vm = 0
    begin
      Nvec := m-1;
    end;
  end;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -