### EBK & NVS    Library

Object Pascal (since Delphi 4) supports dynamic zero-based arrays. This library was developed for supporting dynamic arrays in Turbo Pascal and earlier versions of Delphi.

The algorithms collected in the library were translated from various languages, modified  and developed by us. The references to the original publications are presented wherever they are available.

All arrays are 1-based (old good FORTRAN style). We employed  the simplest and reliable approach (see the the unit MathTypes for details). However it requires some explanation. This is done below in a form of test application.

```Some declarations from the unit MathTypes:
type
RealType  =  extended;
IntType = longint;

{ The dimension in declarations can be of any value }
Vector    =  array
[1..999] of RealType;
VcPtr     =  ^Vector;

Matrix    =  array
[1..999] of VcPtr;
MtPtr     =  ^Matrix;
```

And how it works

```procedure MathTypesDemo;
var
Vp, Vc: VcPtr;
Mp: MtPtr;
K, L, i, j: IntType;
s: string;

// Example of Vector and Matrix declaration - this is recommended as more convinient
procedure MatTimesVec(var A: Vector; const B: Matrix; const C: Vector; N, M: IntType);
// A must be var because Vector is the array of RealType
// Vector access: A[i] or C[j]
// Matrix is the atrray of pointers and can be always declared as const
// Comment: Turbo-Pascal did not have const parameters and all variable were declared as var
// Matrix access: B[i]^[j] because B[i]^ is a Vector
// see declarations in the units MathTypes and ComplexType
var
i, j: IntType;
s: RealType;
begin
for i := 1 to N do
begin
s := 0.0;
for j := 1 to M do
s := s + B[i]^[j]*C[j]; // For comparison of static and dynamic arrays see the table below
A[i] := s;
end;
end;

// Example of pointer declarations - this is less convenient (one more '^' )but still OK
procedure InitMatVec(const A: VcPtr; const B: MtPtr; N, M: IntType);
// Both A and B are pointers and can be declared as const
// Vector access: A^[i]
// Matrix access: B^[i]^[j]
var
i, j: IntType;
begin
for i := 1 to N do
for j := 1 to M do
B^[i]^[j] := i*j; // pointer access

for j := 1 to M do
A^[j] := j; // pointer access
end;

begin
K := 2;
L := 3;
GetMatrixMemory(Mp, K, L);
GetVectorMemory(Vp, K);
GetVectorMemory(Vc, L);

InitMatVec(Vc, Mp, K, L); // Actual parameters are pointers

Memo3.Clear;

for i := 1 to K do
begin
s := '';
for j := 1 to L do
s := s  +' [ '+ FloatToStr(Mp^[i]^[j])+' ] ';
end;

s := '';

for j := 1 to L do
s := s +' [ '+ FloatToStr(Vc^[j])+' ] ';

{ Vp^ is Vector, Mp^ is Matrix }
MatTimesVec(Vp^, Mp^, Vc^, K, L); // Actual parameters are Vector and Matrix

s := '';
for i := 1 to K do
s := s + ' [ '+ FloatToStr(Vp^[i])+' ] ';

FreeVectorMemory(Vp, K);
FreeVectorMemory(Vc, L);
FreeMatrixMemory(Mp, K, L);
end;
```
Remarks
1. Delphi provides a safe way of getting and freeing memory:
```  try
GetMatrixMemory((Mp, K, L);
. . .
finally
FreeMatrixMemory(Mp, K, L);
end;
```
2. Static-Dynamic array comparison:
 Dimension Static Dynamic 1 A[k] A[k] 2 B[n,m] B[n]^[m] 3 C[k,m,n] C[k]^[m]^[n]

Probably the notation in in the right column is less convenient (for dimensions > 1)  but this is a small price for non-object dynamic arrays.

1. This implementation of dynamic arrays is fast in execution, however it is nor fool-proof .
2. One of the advantages is fast row vector manipulation. For example, this code swaps two rows of a two-dimensional array (matrix):
```  M: Matrix;
vc: VcPtr;

vc := M[j];
M[j] := M[i];
M[i] := vc;

see Gram_Schmidt or SortTVec as  an example.
```

Authors: Nikolai V. Shokhirev and Eugene B. Krissinel

ŠNikolai V. Shokhirev, 2001-2002