zoukankan      html  css  js  c++  java
  • 简单的矩阵计算(结构体,静态数组)

    有个需求需要用到矩阵工具..从十几年前的资料里找到了一个矩阵计算,但是是用类来实现的,改写了一下,改成结构体.只做了简单测试,发现问题欢迎告诉我...

      1 unit MatrixCal;
      2 
      3 interface
      4 
      5 uses
      6   Windows, SysUtils;
      7 
      8 const
      9   MaxRowCount = 8;
     10   MaxColCount = 8;
     11   
     12 type
     13   EMatrixException = class(Exception);
     14   
     15 type
     16   TMatrixDataAry = array[0..MaxRowCount - 1] of array[0..MaxColCount - 1] of Extended;
     17   TMatrixRecord = record
     18     RowCount, ColCount: Integer;
     19     Data: TMatrixDataAry;
     20   end;
     21 
     22 procedure Matrix_Init(const RowCount, ColCount: Integer; Value: Extended; var M: TMatrixRecord);
     23 
     24 
     25 procedure Matrix_MainBasis(Value: Extended; var M: TMatrixRecord);
     26 function  Matrix_SolveEx(var A, B: TMatrixRecord): Extended;
     27 
     28 
     29 function  Matrix_CalMultValue(M: TMatrixRecord; Value: Extended): TMatrixRecord;
     30 function  Matrix_CalMult(A, B: TMatrixRecord; var C: TMatrixRecord): Boolean;
     31 function  Matrix_CalAdd(A, B: TMatrixRecord; var C: TMatrixRecord): Boolean;
     32 function  Matrix_CalPower(M: TMatrixRecord; Pow: Integer): TMatrixRecord;
     33 function  Matrix_CalDeterminant(M: TMatrixRecord; var Value: Extended): Boolean;
     34 function  Matrix_CalInverse(M: TMatrixRecord; var B: TMatrixRecord): Boolean;
     35 
     36 implementation
     37 
     38 procedure Matrix_Init(const RowCount, ColCount: Integer; Value: Extended; var M: TMatrixRecord);
     39 var
     40   i, j: Integer;
     41 begin
     42   M.RowCount := RowCount;
     43   M.ColCount := ColCount;
     44   for i := 0 to RowCount - 1 do
     45     for j := 0 to ColCount - 1 do
     46       M.Data[i, j] := Value;
     47 end;
     48 
     49 
     50 procedure Matrix_MainBasis(Value: Extended; var M: TMatrixRecord);
     51 var
     52   i: Integer;
     53 begin
     54   if M.RowCount <> M.ColCount then
     55     raise EMatrixException.Create('This operation can be applied only to square matrix');
     56   Matrix_Init(M.RowCount, M.ColCount, 0, M);
     57   for i := 0 to M.RowCount - 1 do
     58     M.Data[i, i] := Value;
     59 end;
     60 
     61 procedure Matrix_ExChangeRows(i, j: Integer; var M: TMatrixRecord);
     62 var
     63   k: Integer;
     64   Temp: Extended;
     65 begin
     66   for k := 0 to M.ColCount - 1 do
     67   begin
     68     Temp := M.Data[i,k];
     69     M.Data[j,k] := M.Data[i,k];
     70     M.Data[j,k] := Temp;
     71   end;
     72 end;
     73 
     74 procedure Matrix_AddRows(i, j: integer; Factor: Extended; var M: TMatrixRecord);
     75 var
     76   k: Integer;
     77 begin
     78   for k := 0 to M.ColCount - 1 do
     79     M.Data[i,k] := M.Data[i,k] + M.Data[j,k] * Factor;
     80 end;
     81 
     82 procedure Matrix_MultLine(i: Integer; Factor: Extended; var M: TMatrixRecord);
     83 var
     84   k: Integer;
     85 begin
     86   for k := 0 to M.ColCount - 1 do
     87     M.Data[i,k] := M.Data[i,k] * Factor;
     88 end;
     89 
     90 function  Matrix_SolveEx(var A, B: TMatrixRecord): Extended;
     91 var
     92   i, j: Integer;
     93   Temp: Extended;
     94   Factor: Integer;
     95 begin
     96   Result := 1;
     97   { Forward pass, choose main element <> 0 }
     98   for i := 0 to A.RowCount - 1 do
     99   begin
    100     j := 0;
    101     while j < A.RowCount do
    102       if A.Data[i, j] <> 0 then
    103         Break
    104       else
    105         Inc(j);
    106     if j = A.RowCount then
    107     begin
    108       Result := 0;
    109       Exit;
    110     end;
    111     Matrix_ExChangeRows(i, j, A);
    112     Matrix_ExChangeRows(i, j, B);
    113     if not Odd(A.ColCount) then Result := -1 * Result;
    114     for j := i + 1 to A.RowCount - 1 do
    115     begin
    116       Temp := A.Data[j, i]/A.Data[i, i];
    117       Matrix_AddRows(j, i, -Temp, A);
    118       Matrix_AddRows(j, i, -Temp, B);
    119     end;
    120   end;
    121 
    122   { Backward pass }
    123   for i := A.RowCount - 1 downto 0 do
    124     for j := i - 1 downto 0 do
    125     begin
    126       Temp := A.Data[j, i]/A.Data[i, i];
    127       Matrix_AddRows(j, i, -Temp, A);
    128       Matrix_AddRows(j, i, -Temp, B);
    129     end;
    130 
    131   { Divide diagonal elements by themself, making identity matrix }
    132   for i := 0 to A.RowCount - 1 do
    133   begin
    134     Result := Result * A.Data[i, i];
    135     Temp := 1/A.Data[i, i];
    136     Matrix_MultLine(i, Temp, B);
    137     Matrix_MultLine(i, Temp, A);
    138   end;
    139 end;
    140 
    141 function  Matrix_CalMultValue(M: TMatrixRecord; Value: Extended): TMatrixRecord;
    142 var
    143   i, j: Integer;
    144 begin
    145   Result := M;
    146   for i := 0 to Result.RowCount - 1 do
    147     for j := 0 to Result.ColCount - 1 do
    148       Result.Data[i,j] := Result.Data[i,j] * Value;
    149 end;
    150 
    151 function  Matrix_CalMult(A, B: TMatrixRecord; var C: TMatrixRecord): Boolean;
    152 var
    153   i, j, k: Integer;
    154   TmpC: TMatrixRecord;
    155 begin
    156   Result := False;
    157   if A.ColCount <> B.RowCount then
    158     Exit; //raise EMatrixException.Create('Can not Multiply these matrixes');
    159   Matrix_Init(A.RowCount, B.ColCount, 0, TmpC);
    160   for k := 0 to A.RowCount - 1 do
    161     for i := 0 to B.ColCount - 1 do
    162       for j := 0 to A.ColCount - 1 do
    163         TmpC.Data[k, i] := TmpC.Data[k, i] + A.Data[k, j] * B.Data[j, i];
    164   Result := True;
    165   C := TmpC;
    166 end;
    167 
    168 function  Matrix_CalAdd(A, B: TMatrixRecord; var C: TMatrixRecord): Boolean;
    169 var
    170   i, j, k: Integer;
    171   TmpC: TMatrixRecord;
    172 begin
    173   Result := False;
    174   if (A.ColCount <> B.ColCount) or (A.RowCount <> B.RowCount) then
    175     Exit; //raise EMatrixException.Create('Can not add these matrixes');
    176   TmpC := A;
    177   for i := 0 to A.RowCount - 1 do
    178     for j := 0 to A.ColCount - 1 do
    179         TmpC.Data[i, j] := TmpC.Data[i, j] + B.Data[i, j];
    180   Result := True;
    181   C := TmpC;
    182 end;
    183 
    184 function  Matrix_CalPower(M: TMatrixRecord; Pow: Integer): TMatrixRecord;
    185 var
    186   i: Integer;
    187 begin
    188   Result := M;
    189   for i := 1 to Pow - 1 do
    190     Matrix_CalMult(Result, M, Result);
    191 end;
    192 
    193 function  Matrix_CalDeterminant(M: TMatrixRecord; var Value: Extended): Boolean;
    194 var
    195   B: TMatrixRecord;
    196 begin
    197   Result := False;
    198   if M.RowCount <> M.ColCount then
    199     Exit;  //raise EMatrixException.Create('This operation can be applied only to square matrix');
    200   B := M;
    201   Matrix_MainBasis(1, B);
    202   Value := Matrix_SolveEx(M, B);
    203   Result := True;
    204 end;
    205 
    206 function  Matrix_CalInverse(M: TMatrixRecord; var B: TMatrixRecord): Boolean;
    207 var
    208   TmpB: TMatrixRecord;
    209 begin
    210   Result := False;
    211   if M.RowCount <> M.ColCount then
    212     Exit; //raise EMatrixException.Create('This operation can be applied only to square matrix');
    213   TmpB := M;
    214   Matrix_MainBasis(1, TmpB);
    215   Result := Matrix_SolveEx(M, TmpB) <> 0;
    216   if Result then
    217     B := TmpB;
    218 end;
    219 
    220 end.
    View Code

    同时附上用类实现的代码.作者不可考.

       1 unit MatLib;
       2 
       3 interface
       4 
       5 uses
       6   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
       7   Forms, Dialogs, StdCtrls;
       8 
       9 const
      10   { Size of Extended }
      11   szExtended = SizeOf(Extended);
      12   szPointer = SizeOf(Pointer);
      13 
      14 type
      15   { Array of Extended }
      16   PExtArray = ^TExtArray;
      17   TExtArray = array [0..MaxInt div szExtended - 1] of Extended;
      18   { Array of pointers }
      19   PPtrArray = ^TPtrArray;
      20   TPtrArray = array [0..MaxInt div szPointer - 1] of PExtArray;
      21 
      22 type
      23   EMatrixException = class(Exception);
      24 
      25   TMatrix = class;
      26   TVector = class;
      27   TMatrixClass = class of TMatrix;
      28   TVectorClass = class of TVector;
      29 
      30   { TMatrix - base abstract class for matrices }
      31   TMatrix = class(TComponent)
      32   protected
      33     FColCount: Integer;
      34     FRowCount: Integer;
      35     FClass: TMatrixClass;
      36     { Must be overrided in decendent class !}
      37     function  GetCells(ARow, ACol: Integer): Extended; virtual; abstract;
      38     { Must be overrided in decendent class !}
      39     procedure SetCells(ARow, ACol: Integer; AValue: Extended); virtual; abstract;
      40     { Must be overrided in decendent class !}
      41     procedure SetRanges(NewRow, NewCol: Integer); virtual; abstract;
      42     procedure SetCols(Value: Integer);
      43     procedure SetRows(Value: Integer);
      44   public
      45     constructor Create(AOwner: TComponent); override;
      46     { Assign matrix from Source }
      47     procedure   Assign(Source: TMatrix);
      48     { Assign Value to all cells of matrix }
      49     procedure   AssignValue(Value: Extended);
      50     { Assign Values array to NLine row of matrix  }
      51     procedure   AssignToLine(NLine: Integer; Values: array of Extended);
      52     { Assign Values array to NCol column of matrix  }
      53     procedure   AssignToCol (NCol : Integer; Values: array of Extended);
      54     { Add matrix AMatrix to Self (this matrix) }
      55     procedure   Add(AMatrix: TMatrix);
      56     { Multiply Self by AMatrix }
      57     procedure   MultAsLeft(AMatrix: TMatrix);
      58     { Multiply Self by AMatrix }
      59     procedure   MultAsRight(AMatrix: TMatrix);
      60     { Multiply Self by Value }
      61     procedure   MultValue(Value: Extended);
      62     { Assign Value to diagonal elements (only square matrix) }
      63     procedure   MainBasis(Value: Extended);
      64     { Calculate determinant }
      65     function    Determinant: Extended;
      66     { Inverses matrix  }
      67     procedure   Inverse;
      68     { Transpose matrix }
      69     procedure   Transpose;
      70     { ExChanges rows (Rows) number i and j }
      71     procedure   ExChangeRows(i, j: Integer);
      72     { Add to i-row j-row muliplied by Factor }
      73     procedure   AddRows(i, j: integer; Factor: Extended);
      74     { Multiply all elements of i-row by Factor }
      75     procedure   MultLine(i: Integer; Factor: Extended);
      76     { Raise to power Pow  }
      77     procedure   Power(Pow: Integer);
      78     property Cells[ARow, ACol: Integer]: Extended read GetCells write SetCells; default;
      79     property ColCount: Integer read FColCount write SetCols;
      80     property RowCount: Integer read FRowCount write SetRows;
      81   end;
      82 
      83   { Matrix of Extended [(MaxInt div 4)x(MaxInt div 10) elements maximum) }
      84   TRealMatrix = class(TMatrix)
      85   protected
      86     FRows: PPtrArray;
      87     destructor  Destroy; override;
      88     function  GetCells(ARow, ACol: Integer): Extended; override;
      89     procedure SetCells(ARow, ACol: Integer; AValue: Extended); override;
      90     procedure SetRanges(NewRow, NewCol: Integer); override;
      91   public
      92     property Cells;
      93   published
      94     property ColCount;
      95     property RowCount;
      96   end;
      97 
      98   { Sparse matrix cell }
      99   PSCell = ^TSCell;
     100   TSCell = record
     101     Col, Row: Integer;  { location of this cell in the matrix }
     102     Value: Extended;    { value to hold in the cell }
     103   end;
     104 
     105   { Sparse matrix row }
     106   TSRow = class(TList)
     107   private
     108     FRowNum: Integer;
     109     function Get(Index: Integer): PSCell;
     110     procedure Put(Index: Integer; ACell: PSCell);
     111   public
     112     constructor Create(ARowNum: Integer);
     113     destructor  Destroy; override;
     114     property RowNum: Integer read FRowNum write FRowNum;
     115     property Items[Index: Integer]: PSCell read Get write Put;
     116     function Find(ACellCol: Integer; var Index: Integer): Boolean;
     117     function Add(const ACellCol: Integer; const AValue: Extended): Integer;
     118   end;
     119 
     120   { Sparse matrix row list }
     121   TRowList = class(TList)
     122   private
     123     function Get(Index: Integer): TSRow;
     124     procedure Put(Index: Integer; ARow: TSRow);
     125   public
     126     destructor Destroy; override;
     127     property Items[Index: Integer]: TSRow read Get write Put;
     128     function Find(ARowNum: Integer; var Index: Integer): Boolean;
     129     function Add(const ARowNum: Integer): Integer;
     130   end;
     131 
     132   { Sparse matrix }
     133   TSparseMatrix = class(TMatrix)
     134   protected
     135     FRows: TRowList;
     136     destructor  Destroy; override;
     137     function  GetCells(ARow, ACol: Integer): Extended; override;
     138     procedure SetCells(ARow, ACol: Integer; AValue: Extended); override;
     139     procedure SetRanges(NewRow, NewCol: Integer); override;
     140   public
     141     property Cells;
     142   published
     143     property ColCount;
     144     property RowCount;
     145   end;
     146 
     147   { TVector - base abstract class for vectors }
     148   TVector = class(TComponent)
     149   protected
     150     FCount: Integer;
     151     FClass: TVectorClass;
     152     { Must be overrided in decendent class !}
     153     function  GetCells(APos: Integer): Extended; virtual; abstract;
     154     { Must be overrided in decendent class !}
     155     procedure SetCells(APos: Integer; AValue: Extended); virtual; abstract;
     156     { Must be overrided in decendent class !}
     157     procedure SetCount(NewCount: Integer); virtual; abstract;
     158   public
     159     constructor Create(AOwner: TComponent); override;
     160     { Assign Vector from Source }
     161     procedure   Assign(Source: TVector);
     162     { Assign Value to all cells of Vector }
     163     procedure   AssignValue(Value: Extended);
     164     { Add Vector AVector to Self (this Vector) }
     165     procedure   Add(AVector: TVector);
     166     {}
     167     procedure   Exchange(i, j: Integer);
     168     { Multiply Self by AVector }
     169     procedure   MultValue(Value: Extended);
     170     { Scalar product }
     171     function    ScalarProduct(AVector: TVector): Extended;
     172     { Transpose Vector }
     173     procedure   Transpose;
     174     property Cells[APos: Integer]: Extended read GetCells write SetCells; default;
     175     property Count: Integer read FCount write SetCount;
     176   end;
     177 
     178   { Vector of Extended [(MaxInt div 10) elements maximum) }
     179   TRealVector = class(TVector)
     180   protected
     181     FData: PExtArray;
     182     destructor  Destroy; override;
     183     function  GetCells(APos: Integer): Extended; override;
     184     procedure SetCells(APos: Integer; AValue: Extended); override;
     185     procedure SetCount(NewCount: Integer); override;
     186   public
     187     property Cells;
     188   published
     189     property Count;
     190   end;
     191 
     192   { Sparse Vector }
     193   TSparseVector = class(TVector)
     194   protected
     195     FData: TSRow;
     196     destructor  Destroy; override;
     197     function  GetCells(APos: Integer): Extended; override;
     198     procedure SetCells(APos: Integer; AValue: Extended); override;
     199     procedure SetCount(NewCount: Integer); override;
     200   public
     201     property Cells;
     202   published
     203     property Count;
     204   end;
     205 
     206 { Routines which returnes matrices. A and B matrices will not ExChange }
     207 { !!! Note that you are responsible for destroying returned matrix.  }
     208 { type of returned matrix is the same as A                           }
     209 
     210 { }
     211 function SolveMatrix(AMatrix: TMatrix; BVector: TVector): Extended;
     212 { }
     213 function SolveMatrixEx(AMatrix: TMatrix; BMatrix: TMatrix): Extended;
     214 { Inverses matrix A }
     215 function M_Inverse(A: TMatrix): TMatrix;
     216 { MultAsLeftiply A * B  }
     217 function M_Mult(A, B: TMatrix): TMatrix;
     218 { Add A to B, A + B }
     219 function M_Add(A, B: TMatrix): TMatrix;
     220 { Mulltiply A by Value }
     221 function M_MultValue(A: TMatrix; Value: Extended): TMatrix;
     222 { Raise A to power Pow  }
     223 function M_Power(A: TMatrix; Pow: Integer): TMatrix;
     224 
     225 procedure Register;
     226 
     227 implementation
     228 
     229 procedure Register;
     230 begin
     231   RegisterComponents('Math', [TRealMatrix, TSparseMatrix, TRealVector, TSparseVector]);
     232 end;
     233 
     234 { SolveMatrix uses Gaussian algorithm to transform AMatrix to identity matrix }
     235 { At the same time it perform same operation on BMatrix, as a result it }
     236 { returns determinant of AMatrix }
     237 function SolveMatrixEx(AMatrix: TMatrix; BMatrix: TMatrix): Extended;
     238 var
     239   i, j: Integer;
     240   Temp: Extended;
     241   Factor: Integer;
     242 begin
     243   Result := 1;
     244   { Forward pass, choose main element <> 0 }
     245   for i := 0 to AMatrix.RowCount - 1 do
     246   begin
     247     j := 0;
     248     while j < AMatrix.RowCount do
     249       if AMatrix.Cells[i, j] <> 0 then break
     250                                   else inc(j);
     251     if j = AMatrix.RowCount then
     252     begin
     253       Result := 0;
     254       Exit;
     255     end;
     256     AMatrix.ExChangeRows(i, j);
     257     BMatrix.ExChangeRows(i, j);
     258     if not Odd(AMatrix.ColCount) then Result := -1 * Result;
     259     for j := i + 1 to AMatrix.RowCount - 1 do
     260     begin
     261       Temp := AMatrix.Cells[j, i]/AMatrix.Cells[i, i];
     262       AMatrix.AddRows(j, i, -Temp);
     263       BMatrix.AddRows(j, i, -Temp);
     264     end;
     265   end;
     266 
     267   { Backward pass }
     268   for i := AMatrix.RowCount - 1 downto 0 do
     269     for j := i - 1 downto 0 do
     270     begin
     271       Temp := AMatrix.Cells[j, i]/AMatrix.Cells[i, i];
     272       AMatrix.AddRows(j, i, -Temp);
     273       BMatrix.AddRows(j, i, -Temp);
     274     end;
     275 
     276   { Divide diagonal elements by themself, making identity matrix }
     277   for i := 0 to AMatrix.RowCount - 1 do
     278   begin
     279     Result := Result * AMatrix.Cells[i, i];
     280     Temp := 1/AMatrix.Cells[i, i];
     281     BMatrix.MultLine(i, Temp);
     282     AMatrix.MultLine(i, Temp);
     283   end;
     284 end;
     285 
     286 function SolveMatrix(AMatrix: TMatrix; BVector: TVector): Extended;
     287 var
     288   i, j: Integer;
     289   Temp: Extended;
     290   Factor: Integer;
     291 begin
     292   Result := 1;
     293   { Forward pass, choose main element <> 0 }
     294   for i := 0 to AMatrix.RowCount - 1 do
     295   begin
     296     j := 0;
     297     while j < AMatrix.RowCount do
     298       if AMatrix.Cells[i, j] <> 0 then break
     299                                   else inc(j);
     300     if j = AMatrix.RowCount then
     301     begin
     302       Result := 0;
     303       Exit;
     304     end;
     305     AMatrix.ExChangeRows(i, j);
     306     BVector.ExChange(i, j);
     307     if not Odd(AMatrix.ColCount) then Result := -1 * Result;
     308     for j := i + 1 to AMatrix.RowCount - 1 do
     309     begin
     310       Temp := AMatrix.Cells[j, i]/AMatrix.Cells[i, i];
     311       AMatrix.AddRows(j, i, -Temp);
     312       BVector[j] := BVector[j] - Temp*BVector[i];
     313     end;
     314   end;
     315 
     316   { Backward pass }
     317   for i := AMatrix.RowCount - 1 downto 0 do
     318     for j := i - 1 downto 0 do
     319     begin
     320       Temp := AMatrix.Cells[j, i]/AMatrix.Cells[i, i];
     321       AMatrix.AddRows(j, i, -Temp);
     322       BVector[j] := BVector[j] - Temp*BVector[i];
     323     end;
     324 
     325   { Divide diagonal elements by themself, making identity matrix }
     326   for i := 0 to AMatrix.RowCount - 1 do
     327   begin
     328     Result := Result * AMatrix.Cells[i, i];
     329     Temp := 1/AMatrix.Cells[i, i];
     330     BVector[i] := BVector[i] * Temp;
     331     AMatrix.MultLine(i, Temp);
     332   end;
     333 end;
     334 
     335 function Min(Num1, Num2: Integer): Integer;
     336 begin
     337   if Num1 < Num2 then Result := Num1
     338                  else Result := Num2;
     339 end;
     340 
     341 { -- TMatrix -- }
     342 constructor TMatrix.Create;
     343 begin
     344   inherited Create(AOwner);
     345   FClass := TMatrixClass(ClassType);
     346   SetRanges(5, 5);
     347 end;
     348 
     349 procedure TMatrix.Assign(Source: TMatrix);
     350 var
     351   i, j: Integer;
     352 begin
     353   RowCount := Source.RowCount;
     354   ColCount := Source.ColCount;
     355   for i := 0 to RowCount - 1 do
     356     for j := 0 to ColCount - 1 do
     357       Cells[i,j] := Source[i, j];
     358 end;
     359 
     360 procedure TMatrix.AssignValue(Value: Extended);
     361 var
     362   i, j: Integer;
     363 begin
     364   for i := 0 to RowCount - 1 do
     365     for j := 0 to ColCount - 1 do
     366       Cells[i,j] := Value;
     367 end;
     368 
     369 procedure TMatrix.AssignToLine(NLine: Integer; Values: array of Extended);
     370 var
     371   j, Min: Integer;
     372 begin
     373   if (NLine >= RowCount) or (NLine < 0)
     374     then raise EMatrixException.Create('Invalid row number');
     375   if ColCount > High(Values)
     376     then Min := High(Values)
     377     else Min := ColCount - 1;
     378   for j := 0 to Min do
     379     Cells[NLine,j] := Values[j];
     380 end;
     381 
     382 procedure TMatrix.AssignToCol(NCol: Integer; Values: array of Extended);
     383 var
     384   j, Min: Integer;
     385 begin
     386   if (NCol >= ColCount) or (NCol < 0)
     387     then raise EMatrixException.Create('Invalid column number');
     388   if RowCount > High(Values)
     389     then Min := High(Values)
     390     else Min := RowCount - 1;
     391   for j := 0 to Min do
     392     Cells[j,NCol] := Values[j];
     393 end;
     394 
     395 procedure TMatrix.Add(AMatrix: TMatrix);
     396 var
     397   i, j: Integer;
     398 begin
     399   if (ColCount <> AMatrix.ColCount) or (RowCount <> AMatrix.RowCount)
     400     then raise EMatrixException.Create('Can not add these matrixes');
     401   for i := 0 to RowCount - 1 do
     402     for j := 0 to ColCount - 1 do
     403       Cells[i,j] := Cells[i,j] + AMatrix[i,j];
     404 end;
     405 
     406 procedure TMatrix.MultAsLeft(AMatrix: TMatrix);
     407 var
     408   A: TMatrix;
     409   i, j, k: Integer;
     410 begin
     411   if ColCount <> AMatrix.RowCount
     412     then raise EMatrixException.Create('Can not Multiply these matrixes');
     413   A := FClass.Create(nil);
     414   A.RowCount := RowCount;
     415   A.ColCount := AMatrix.ColCount;
     416   for k := 0 to RowCount - 1 do
     417     for i := 0 to AMatrix.ColCount - 1 do
     418       for j := 0 to ColCount - 1 do
     419         A[k, i] := A[k, i] + Cells[k, j] * AMatrix.Cells[j, i];
     420   Assign(A);
     421   A.Free;
     422 end;
     423 
     424 procedure TMatrix.MultAsRight(AMatrix: TMatrix);
     425 var
     426   A: TMatrix;
     427   i, j, k: Integer;
     428 begin
     429   if ColCount <> AMatrix.RowCount
     430     then raise EMatrixException.Create('Can not Multiply these matrixes');
     431   A := FClass.Create(nil);
     432   A.RowCount := AMatrix.RowCount;
     433   A.ColCount := ColCount;
     434   for k := 0 to AMatrix.RowCount - 1 do
     435     for i := 0 to ColCount - 1 do
     436       for j := 0 to AMatrix.ColCount - 1 do
     437         A[k, i] := A[k, i] + AMatrix[k, j] * Cells[j, i];
     438   Assign(A);
     439   A.Free;
     440 end;
     441 
     442 procedure TMatrix.MultValue(Value: Extended);
     443 var
     444   i, j: Integer;
     445 begin
     446   for i := 0 to RowCount - 1 do
     447     for j := 0 to ColCount - 1 do
     448       Cells[i,j] := Cells[i,j] * Value;
     449 end;
     450 
     451 procedure TMatrix.MainBasis(Value: Extended);
     452 var
     453   i: Integer;
     454 begin
     455   if RowCount <> ColCount
     456     then raise EMatrixException.Create('This operation can be applied only to square matrix');
     457   AssignValue(0);
     458   for i := 0 to RowCount - 1 do
     459     Cells[i,i] := Value;
     460 end;
     461 
     462 function TMatrix.Determinant: Extended;
     463 var
     464   A, B: TMatrix;
     465 begin
     466   if RowCount <> ColCount
     467     then raise EMatrixException.Create('This operation can be applied only to square matrix');
     468   A := FClass.Create(nil);
     469   A.Assign(Self);
     470 
     471   B := FClass.Create(nil);
     472   B.RowCount := RowCount;
     473   B.ColCount := ColCount;
     474   B.MainBasis(1);
     475 
     476   Result := SolveMatrixEx(A, B);
     477 end;
     478 
     479 procedure TMatrix.Inverse;
     480 var
     481   A: TMatrix;
     482 begin
     483   if RowCount <> ColCount
     484     then raise EMatrixException.Create('This operation can be applied only to' +
     485                                        ' square matrix');
     486   A := FClass.Create(nil);
     487   A.RowCount := RowCount;
     488   A.ColCount := ColCount;
     489   A.MainBasis(1);
     490 
     491   if SolveMatrixEx(Self, A) = 0 then
     492   begin
     493     raise EMatrixException.Create('Could not inverse this matrix');
     494     Exit;
     495   end;
     496   Assign(A);
     497 end;
     498 
     499 procedure TMatrix.Transpose;
     500 var
     501   A: TMatrix;
     502   T: Extended;
     503   i, j: Integer;
     504 begin
     505   for i := 0 to RowCount - 1 do
     506     for j := i + 1 to ColCount - 1 do
     507     begin
     508     end;
     509 end;
     510 
     511 procedure TMatrix.Power(Pow: Integer);
     512 var
     513   Temp: TMatrix;
     514   i: Integer;
     515 begin
     516   Temp := FClass.Create(nil);
     517   Temp.Assign(Self);
     518   for i := 1 to Pow - 1 do
     519     MultAsLeft(Temp);
     520   Temp.Free;
     521 end;
     522 
     523 procedure TMatrix.SetCols(Value: Integer);
     524 begin
     525   try
     526     SetRanges(RowCount, Value);
     527   except
     528   end;
     529 end;
     530 
     531 procedure TMatrix.SetRows(Value: Integer);
     532 begin
     533   try
     534     SetRanges(Value, ColCount);
     535   except
     536   end;
     537 end;
     538 
     539 procedure TMatrix.ExChangeRows(i, j: Integer);
     540 var
     541   k: Integer;
     542   Temp: Extended;
     543 begin
     544   for k := 0 to ColCount - 1 do
     545   begin
     546     Temp := Cells[i,k];
     547     Cells[j,k] := Cells[i,k];
     548     Cells[j,k] := Temp;
     549   end;
     550 end;
     551 
     552 procedure TMatrix.AddRows(i, j: integer; Factor: Extended);
     553 var
     554   k: Integer;
     555 begin
     556   for k := 0 to ColCount - 1 do
     557     Cells[i,k] := Cells[i,k] + Cells[j,k] * Factor;
     558 end;
     559 
     560 procedure TMatrix.MultLine(i: Integer; Factor: Extended);
     561 var
     562   k: Integer;
     563 begin
     564   for k := 0 to ColCount - 1 do
     565     Cells[i,k] := Cells[i,k] * Factor;
     566 end;
     567 
     568 function M_Inverse(A: TMatrix): TMatrix;
     569 var
     570   B: TMatrix;
     571 begin
     572   if A.RowCount <> A.ColCount
     573     then raise EMatrixException.Create('This operation can be applied only to' +
     574                                        ' square matrix');
     575   B := A.FClass.Create(nil);
     576   B.Assign(A);
     577 
     578   Result := A.FClass.Create(nil);
     579   Result.RowCount := A.RowCount;
     580   Result.ColCount := A.ColCount;
     581   Result.MainBasis(1);
     582 
     583   if SolveMatrixEx(B, Result) = 0 then
     584   begin
     585     raise EMatrixException.Create('Could not inverse this matrix');
     586     Result := nil;
     587   end;
     588 end;
     589 
     590 function M_Mult(A, B: TMatrix): TMatrix;
     591 begin
     592   Result := A.FClass.Create(nil);
     593   Result.Assign(A);
     594   Result.MultAsLeft(B);
     595 end;
     596 
     597 function M_Add(A, B: TMatrix): TMatrix;
     598 begin
     599   Result := A.FClass.Create(nil);
     600   Result.Assign(A);
     601   Result.Add(B);
     602 end;
     603 
     604 function M_MultValue(A: TMatrix; Value: Extended): TMatrix;
     605 begin
     606   Result := A.FClass.Create(nil);
     607   Result.Assign(A);
     608   Result.MultValue(Value);
     609 end;
     610 
     611 function M_Power(A: TMatrix; Pow: Integer): TMatrix;
     612 begin
     613   Result := A.FClass.Create(nil);
     614   Result.Assign(A);
     615   Result.Power(Pow);
     616 end;
     617 
     618 { TRealMatrix }
     619 procedure TRealMatrix.SetRanges(NewRow, NewCol: Integer);
     620 var
     621   OldCol, OldRow: Integer;
     622   i, j: Integer;
     623 begin
     624   if (NewRow < 1) or (NewCol < 1)
     625     then raise Exception.Create('Invalid dimensions...');
     626   if (RowCount <> NewRow) or (ColCount <> NewCol)
     627   then begin
     628     OldRow := RowCount;
     629     OldCol := ColCount;
     630     { reallocate memory }
     631     { if OldCol < NewCol then new elements will be equal to 0 }
     632     { if OldCol > NewCol then elements will be lost }
     633     for i := 0 to OldRow - 1 do
     634     begin
     635     {$IFDEF WIN32}
     636       ReAllocMem(FRows^[i], szExtended * NewCol);
     637     {$ELSE}
     638       FRows^[i] := ReAllocMem(FRows^[i], szExtended * OldCol, szExtended * NewCol);
     639     {$ENDIF}
     640       if OldCol < NewCol
     641         then FillChar(FRows^[i]^[OldCol], (NewCol - OldCol)*szExtended, 0);
     642     end;
     643     { if NewRow < OldRow, unnessesary Rows will be destroed }
     644     for i := OldRow - 1 downto NewRow do
     645       FreeMem(FRows^[i], szExtended * OldCol);
     646     { Resize FRows }
     647     {$IFDEF WIN32}
     648     ReAllocMem(FRows, szPointer * NewRow);
     649     {$ELSE}
     650     FRows := ReAllocMem(FRows, szPointer * OldRow, szPointer * NewRow);
     651     {$ENDIF}
     652     { if NewRow > OldRows, new Rows will be added }
     653     for i := OldRow to NewRow - 1 do
     654     begin
     655       FRows^[i] := AllocMem(szExtended * NewCol);
     656       FillChar(FRows^[i]^, NewCol*szExtended, 0);
     657     end;
     658     { update FRowCount }
     659     FRowCount := NewRow;
     660     { update FColCount }
     661     FColCount := NewCol;
     662   end;
     663 end;
     664 
     665 function  TRealMatrix.GetCells(ARow, ACol: Integer): Extended;
     666 begin
     667   { if index is invalid then raise exception }
     668   if (ACol < 0) or (ACol > ColCount - 1) or
     669      (ARow < 0) or (ARow > RowCount - 1)
     670   then  raise EMatrixException.Create('Index out of bounds' + IntTostr(ACol) + ' ' + IntToStr(ARow));
     671   Result := FRows^[ARow]^[ACol];
     672 end;
     673 
     674 procedure TRealMatrix.SetCells(ARow, ACol: Integer; AValue: Extended);
     675 begin
     676   { if index is invalid then raise exception }
     677   if (ACol < 0) or (ACol > ColCount - 1) or
     678      (ARow < 0) or (ARow > RowCount - 1)
     679   then  raise EMatrixException.Create('Index out of bounds');
     680   FRows^[ARow]^[ACol] := AValue;
     681 end;
     682 
     683 destructor TRealMatrix.Destroy;
     684 var
     685   i: Integer;
     686 begin
     687   { deallocate memory }
     688   for i := 0 to RowCount - 1 do
     689     FreeMem(FRows^[i], szExtended * ColCount);
     690   inherited Destroy;
     691 end;
     692 
     693 { -- TSRow methods -- }
     694 constructor TSRow.Create(ARowNum: Integer);
     695 begin
     696   inherited Create;
     697   FRowNum := ARowNum;
     698 end;
     699 
     700 destructor TSRow.Destroy;
     701 var
     702   i: Integer;
     703 begin
     704   for i := 0 to Count - 1 do
     705     Dispose(PSCell(Items[i]));
     706   inherited Destroy;
     707 end;
     708 
     709 function TSRow.Get(Index: Integer): PSCell;
     710 begin
     711   Result := inherited Get(Index);
     712 end;
     713 
     714 procedure TSRow.Put(Index: Integer; ACell: PSCell);
     715 begin
     716   inherited Put(Index, ACell);
     717 end;
     718 
     719 function TSRow.Find(ACellCol: Integer; var Index: Integer): Boolean;
     720 var
     721   L, H, C, I: Integer;
     722 begin
     723   Result := False;
     724   L := 0;
     725   H := Count - 1;
     726   while L <= H do
     727   begin
     728     I := (L + H) shr 1;
     729     if Items[I]^.Col < ACellCol
     730       then L := I + 1
     731       else begin
     732         H := I - 1;
     733         if Items[i]^.Col = ACellCol then
     734         begin
     735           Result := True;
     736           L := I;
     737         end
     738       end;
     739   end;
     740   Index := L;
     741 end;
     742 
     743 function TSRow.Add(const ACellCol: Integer; const AValue: Extended): Integer;
     744 
     745 function NewCell(ARow, ACol: Integer; AValue: Extended): PSCell;
     746 begin
     747   New(Result);
     748   with Result^ do
     749   begin
     750     Row := ARow;
     751     Col := ACol;
     752     Value := AValue;
     753   end;
     754 end;
     755 
     756 begin
     757   Find(ACellCol, Result);
     758   Insert(Result, NewCell(FRowNum, ACellCol, AValue));
     759 end;
     760 
     761 { -- TRowList methods -- }
     762 destructor TRowList.Destroy;
     763 var
     764   i: Integer;
     765 begin
     766   for i := 0 to Count - 1 do
     767     Items[i].Free;
     768   inherited Destroy;
     769 end;
     770 
     771 function TRowList.Get(Index: Integer): TSRow;
     772 begin
     773   Result := inherited Get(Index);
     774 end;
     775 
     776 procedure TRowList.Put(Index: Integer; ARow: TSRow);
     777 begin
     778   inherited Put(Index, ARow);
     779 end;
     780 
     781 function TRowList.Find(ARowNum: Integer; var Index: Integer): Boolean;
     782 var
     783   L, H, C, I: Integer;
     784 begin
     785   Result := False;
     786   L := 0;
     787   H := Count - 1;
     788   while L <= H do
     789   begin
     790     I := (L + H) shr 1;
     791     if Items[i].RowNum < ARowNum
     792       then L := I + 1
     793       else begin
     794         H := I - 1;
     795         if Items[i].RowNum = ARowNum then
     796         begin
     797           Result := True;
     798           L := I;
     799         end
     800       end;
     801   end;
     802   Index := L;
     803 end;
     804 
     805 function TRowList.Add(const ARowNum: Integer): Integer;
     806 begin
     807   Find(ARowNum, Result);
     808   Insert(Result, TSRow.Create(ARowNum));
     809 end;
     810 
     811 {-- TSparseMatrix --}
     812 destructor TSparseMatrix.Destroy;
     813 begin
     814   FRows.Free;
     815   inherited Destroy;
     816 end;
     817 
     818 function  TSparseMatrix.GetCells(ARow, ACol: Integer): Extended;
     819 var
     820   Index: Integer;
     821   tRow: TSRow;
     822 begin
     823   { if index is invalid then raise exception }
     824   if (ACol < 0) or (ACol >= ColCount) or
     825      (ARow < 0) or (ARow >= RowCount)
     826   then  raise EMatrixException.Create('Index out of bounds');
     827   with FRows do
     828     if not Find(ARow, Index)
     829       then Result := 0
     830       else begin
     831         tRow := Items[Index];
     832         if not tRow.Find(ACol, Index)
     833           then Result := 0
     834           else Result := tRow.Items[Index]^.Value;
     835       end;
     836 end;
     837 
     838 procedure TSparseMatrix.SetCells(ARow, ACol: Integer; AValue: Extended);
     839 var
     840   Index: Integer;
     841   tRow: TSRow;
     842 begin
     843   { if index is invalid then raise exception }
     844   if (ACol < 0) or (ACol >= ColCount) or
     845      (ARow < 0) or (ARow >= RowCount)
     846   then  raise EMatrixException.Create('Index out of bounds');
     847   with FRows do
     848     if not Find(ARow, Index)
     849       then begin
     850         Index := Add(ARow);
     851         Items[Index].Add(ACol, AValue);
     852       end
     853       else begin
     854         tRow := Items[Index];
     855         if not tRow.Find(ACol, Index)
     856           then begin
     857             if AValue <> 0 then tRow.Add(ACol, AValue);
     858           end
     859           else begin
     860             if AValue <> 0
     861               then tRow.Items[Index]^.Value := AValue
     862               else begin
     863                 Dispose(PSCell(tRow.Items[Index]));
     864                 tRow.Delete(Index);
     865               end;
     866           end;
     867       end;
     868 end;
     869 
     870 procedure TSparseMatrix.SetRanges(NewRow, NewCol: Integer);
     871 var
     872   i, j, Index: Integer;
     873   tRow: TSRow;
     874 begin
     875   if (NewRow < 1) or (NewCol < 1)
     876     then raise Exception.Create('Invalid dimensions...');
     877   if FRows = nil then FRows := TRowList.Create;
     878   if RowCount > NewRow then
     879     with FRows do
     880       for i := Count - 1 downto 0 do
     881         if Items[i].RowNum >= NewRow then
     882         begin
     883           Items[i].Free;
     884           Delete(i);
     885         end
     886         else break;
     887   if ColCount > NewCol then
     888     with FRows do
     889       for i := 0 to Count - 1 do
     890       begin
     891         tRow := Items[i];
     892         for j := tRow.Count - 1 downto 0 do
     893           if tRow.Items[j]^.Col > NewCol then
     894           begin
     895             Dispose(tRow.Items[j]);
     896             tRow.Delete(j);
     897           end
     898           else break;
     899       end;
     900    FRowCount := NewRow;
     901    FColCount := NewCol;
     902 end;
     903 
     904 {-- TVector --}
     905 constructor TVector.Create(AOwner: TComponent);
     906 begin
     907   inherited Create(AOwner);
     908   SetCount(5);
     909 end;
     910 
     911 procedure TVector.Assign(Source: TVector);
     912 var
     913   i: Integer;
     914 begin
     915   Count := Source.Count;
     916   for i := 0 to Count - 1 do
     917     Cells[i] := Source[i];
     918 end;
     919 
     920 procedure TVector.AssignValue(Value: Extended);
     921 var
     922   i: Integer;
     923 begin
     924   for i := 0 to Count - 1 do
     925     Cells[i] := Value;
     926 end;
     927 
     928 procedure TVector.Add(AVector: TVector);
     929 var
     930   i: Integer;
     931 begin
     932   if Count <> AVector.Count
     933     then raise EMatrixException.Create('Can not add these Vectors');
     934   for i := 0 to Count - 1 do
     935     Cells[i] := Cells[i] + AVector[i];
     936 end;
     937 
     938 procedure TVector.MultValue(Value: Extended);
     939 var
     940   i: Integer;
     941 begin
     942   for i := 0 to Count - 1 do
     943     Cells[i] := Cells[i] * Value;
     944 end;
     945 
     946 procedure TVector.Transpose;
     947 var
     948   T: Extended;
     949   i: Integer;
     950 begin
     951   for i := 0 to (Count - 1) div 2 do
     952     begin
     953       T := Cells[i];
     954       Cells[i] := Cells[Count - i];
     955       Cells[Count - i] := T;
     956     end;
     957 end;
     958 
     959 function TVector.ScalarProduct(AVector: TVector): Extended;
     960 var
     961   i: Integer;
     962 begin
     963   if Count <> AVector.Count
     964     then raise EMatrixException.Create('Can not process these Vectors');
     965   Result := 0;
     966   for i := 0 to Count - 1 do
     967     Result := Cells[i] * AVector[i];
     968 end;
     969 
     970 procedure TVector.Exchange(i, j: Integer);
     971 var
     972   T: Extended;
     973 begin
     974   T := Cells[i];
     975   Cells[i] := Cells[j];
     976   Cells[j] := T;
     977 end;
     978 
     979 {-- TRealVector --}
     980 destructor  TRealVector.Destroy;
     981 begin
     982   FreeMem(FData, szExtended * Count);
     983   inherited Destroy;
     984 end;
     985 
     986 function  TRealVector.GetCells(APos: Integer): Extended;
     987 begin
     988   { if index is invalid then raise exception }
     989   if (APos < 0) or (APos > Count - 1)
     990     then  raise EMatrixException.Create('Index out of bounds');
     991   Result := FData^[APos];
     992 end;
     993 
     994 procedure TRealVector.SetCells(APos: Integer; AValue: Extended);
     995 begin
     996   { if index is invalid then raise exception }
     997   if (APos < 0) or (APos > Count - 1)
     998     then  raise EMatrixException.Create('Index out of bounds');
     999   FData^[APos] := AValue;
    1000 end;
    1001 
    1002 procedure TRealVector.SetCount(NewCount: Integer);
    1003 var
    1004   OldCount: Integer;
    1005 begin
    1006   if (NewCount < 1)
    1007     then raise Exception.Create('Invalid dimension...');
    1008   if Count <> NewCount
    1009   then begin
    1010     OldCount := Count;
    1011     { reallocate memory }
    1012     {$IFDEF WIN32}
    1013       ReAllocMem(FData, szExtended * NewCount);
    1014     {$ELSE}
    1015       FData := ReAllocMem(FData, szExtended * OldCount, szExtended * NewCount);
    1016     {$ENDIF}
    1017       if OldCount < NewCount
    1018         then FillChar(FData^[OldCount], (NewCount - OldCount)*szExtended, 0);
    1019     FCount := NewCount;
    1020   end;
    1021 end;
    1022 
    1023 {-- TSparseVector --}
    1024 destructor  TSparseVector.Destroy;
    1025 begin
    1026   FData.Free;
    1027   inherited Destroy;
    1028 end;
    1029 
    1030 function  TSparseVector.GetCells(APos: Integer): Extended;
    1031 var
    1032   Index: Integer;
    1033 begin
    1034   { if index is invalid then raise exception }
    1035   if (APos < 0) or (APos >= Count)
    1036     then  raise EMatrixException.Create('Index out of bounds');
    1037   if not FData.Find(APos, Index)
    1038     then Result := 0
    1039     else Result := FData.Items[Index]^.Value;
    1040 end;
    1041 
    1042 procedure TSparseVector.SetCells(APos: Integer; AValue: Extended);
    1043 var
    1044   Index: Integer;
    1045 begin
    1046   { if index is invalid then raise exception }
    1047   if (APos < 0) or (APos >= Count)
    1048     then  raise EMatrixException.Create('Index out of bounds');
    1049   if not FData.Find(APos, Index)
    1050     then begin
    1051       if AValue <> 0 then FData.Add(APos, AValue);
    1052     end
    1053     else begin
    1054       if AValue <> 0
    1055         then FData.Items[Index]^.Value := AValue
    1056         else begin
    1057           Dispose(PSCell(FData.Items[Index]));
    1058           FData.Delete(Index);
    1059         end;
    1060     end;
    1061 end;
    1062 
    1063 procedure TSparseVector.SetCount(NewCount: Integer);
    1064 var
    1065   i: Integer;
    1066 begin
    1067   if NewCount < 1
    1068     then raise Exception.Create('Invalid dimension...');
    1069   if FData = nil then FData := TSRow.Create(1);
    1070   if Count > NewCount then
    1071     for i := FData.Count - 1 downto 0 do
    1072       if FData.Items[i]^.Col > NewCount then
    1073       begin
    1074         Dispose(FData.Items[i]);
    1075         FData.Delete(i);
    1076       end
    1077       else break;
    1078   FCount := NewCount;
    1079 end;
    1080 
    1081 end.
    View Code
  • 相关阅读:
    Javascript中eval解析的json的几种用法
    使用JSONlib简单的转换json操作
    Oracle12c导入scott测试用户(转)
    javascript中隐藏显示的样式表属性
    利用递归级联删除的代码
    递归(c++)(转)
    学习web开发遇到几个细节问题
    AJAX代码格式
    AJAX简介(转)
    算法训练 调和数列问题
  • 原文地址:https://www.cnblogs.com/solokey/p/10786823.html
Copyright © 2011-2022 走看看