PasMatLib

Dynamic Array Objects

by Nikolai Shokhirev

(Development . . . Please check later)

PasMatLib Tutorial

Design remarks

Linear algebra is about indexed objects (tensors, vectors, matrices). Pascal-type arrays with arbitrary low and high bounds (including zero and negative ones) would be ideal for this, except that they are not dynamic. 

Starting with the version 4 Delphi has dynamic arrays of arbitrary type. However they all are zero-based.

Objects with indexed properties allow implementation of dynamic arrays with the arbitrary index range. This approach was realized in ObjMath library. The objects are based on the direct memory allocation (GetMem/FreeMem). 

In the current version the objects are based on the Delphi dynamic arrays. They are light-weight objects, many functions and properties are moved to the stand-alone functions and procedures. It makes the creation of objects less expensive and the code more readable.

The objects support the arbitrary boundaries of arrays: 

Column Vector: C[Lo1..Hi1]

Row Vector R[Lo1..Hi1


        2D Matrix [Lo1..Hi1,Lo2..Hi2]    


3D Matrix

(Pictures by Max Shokhirev)

The arbitrary indexing may be convenient, for example, in treatment of some problems in physics: .

The default is the FORTRAN-like (one-based) indexing. This indexing is the most common in mathematics. The base can be changed dynamically.

 In order to simplify the use of algebra objects and avoid memory leaks, the interface-based approach was chosen.

 

 Examples

Below are several simplified examples (see the Examples directory). 

// Simple sort of row-vectors
procedure TestSort;
var
  i, j: TInt;
  M: IFArr2D;
begin
//  M := TFArr2D.Create(0,3,0,2);    // Zero-based 2D array 4 x 3
  M := TFArr2D.Create(4,3);          // One-based 2D array 4 x 3
  RandArr2D(M,-1.0,1.0,0);           // Fill with random numbers r: -1 < r < 1
                                     // RandMt(-1.0,1.0,M,0); can also be used
  for i := M.Lo1 to M.Hi1-1 do       // For One-based array it also can be: for i := 1 to M.Dim1-1 do
    for j := i+1 to M.Hi1 do
      if M.Norm2(i,_) > M.Norm2(j,_) then    //  |M.Row[i]|**2 > |M.Row[j]|**2
        M.Swap(i, j, _Row);;
end;                                         // no need to destroy M!

// Gram-Schmidt Orthonormalization
procedure TestGramSchmidt;
var
  i, j, m: TInt;
  t: TFloat;
  D: IFArr2D;
begin
  D := TFArr2D.Create(3,4);          // One-based 2D array 3 x 4
  m := D.Dim2; 
  RandArr2D(D,-1.0,1.0);             // Fill with random numbers [-1 < r < 1] 
  // The algorithm itself 
  for i := 1 to D.Dim2 do            // For arbitrary limits: for i := D.Lo2 to D.Hi2 do
  begin
    t := t := D.Norm2(_,i);          // = |D.Col[i]|**2
    if t > MinFloat then
    begin
      CxCol(D, i, 1.0/t);            // = D.Col[i]/t 
      for j := i+1 to D.Dim2 do
      begin
        t := ColxCol(D, i, j);       // = <D.Col[i]|D.Col[j]>
        ColAddCol(D, j, i, -t);      // = D.Col[j] - t*D.Col[i]) 
      end;
    end else
    begin
      m := i-1;                      // m is the number of linear independent vectors
      break;
    end;
  end;                               // no need to destroy D!
end;
(see also DUnit tests)
 

Interface Hierarchy

               IComment
                  |
                ILim1D
                  |
                ILim2D
                  |
                ILim3D


                ILim1D
                  |
  +-------+-------+-------+-------+
  |       |       |       |       |
ISArr1D IBArr1D IIArr1D IFArr1D ICArr1D

                ILim2D
                  |
          +-------+-------+-------+
          |       |       |       |
        IBArr2D IIArr2D IFArr2D ICArr2D

                ILim3D
                  |
          +-------+-------+
          |       |       |
        IBArr3D IIArr3D IFArr3D


               IComment
                  |
       +----------+----------+
       |          |          |
    IEigenSys  IHEigenSys ISVDSys

 

Unit dependence

uMatTypes
  |
uDynArrays
  |
uDynArrUtils
  |
  +------------+--------------+
  |            |              |
uDynArrIO    uDynArrUtilsX  uDynLinAlg
  |

This is the hierarchy of interfaces for basic algebra objects:

 

Float

Integer

Boolean

 String
 1D 
 IFArr1D 
 IIArr1D 
 IBArr1D 
 ISArr1D 
 2D 
 IFArr2D 
 IIArr2D 
 IBArr2D 
 ISArr2D 
 3D 
 IFArr3D
 IIArr3D
 - 
 - 

For unified handling of the limits of indices all objects implement the corresponding ILimND interfaces (N = 1, 2, 3).

 

Compound Objects

 These objects are also defined in the unit uDynArrays. They consist of the objects defined above.

Compound Float

 IEigenSys   IHEigenSys   ISVDSys

The objects can be presented graphically as follows:

IEigenSys  IHEigenSys  ISVDSys

 

DUnit tests

The unit tests are mainly self-explanatory. They can be used as examples as well.

More documentation and DUnit tests are still coming

 

Download

The PasMatLib units are available in the Download section

PasMatLib Tutorial


Programming toolsPasMatLib Tutorial | User guide | Download

Home  |   Shokhirev.com |  Sample code  |   Programming  |    Resume

Please e-mail me at nikolai@shokhirev.com

ŠNikolai V. Shokhirev, 2002-2007