Hi Frank (Rubin),


Sometimes life is simpler than appears at first glance :-)

I should  have put in the stuff below in my previous message;
I was thinking of triangular matrices, where you save memory
by  having the rows of different lengths.

But please tell me, have you ever used 3-D arrays?  4-D arrays?

Harley

From Delphi 2010 Help:

SetLength

For dynamic arrays, SetLength may take more than one-length parameter (up to the number of array dimensions). Each parameter specifies the number of elements along a particular dimension.


Structured types/Data types

Multidimensional Dynamic Arrays

To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example:

type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;

declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I and J are integer-valued variables:

SetLength(Msgs,I,J);

allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.

You can create multidimensional dynamic arrays that are not rectangular. The first step is to call SetLength, passing it parameters for the first n dimensions of the array. For example:

var Ints: array of array of Integer;
SetLength(Ints,10);

allocates ten rows for Ints but no columns. Later, you can allocate the columns one at a time (giving them different lengths); for example:

SetLength(Ints[2], 5);

makes the third column of Ints five integers long. At this point (even if the other columns haven't been allocated) you can assign values to the third column - for example, Ints[2,4] := 6.

The following example uses dynamic arrays (and the IntToStr function declared in the SysUtils unit) to create a triangular matrix of strings.

var
  A : array of array of string;
  I, J : Integer;
begin
  SetLength(A, 10);
  for I := Low(A) to High(A) do
  begin
    SetLength(A[I], I);
    for J := Low(A[I]) to High(A[I]) do
      A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
    end;
  end;


Contestcen@aol.com wrote:
When I first started using FPC, I went through the manuals looking for  
useful features.  I came across both open arrays and dynamic arrays, and  
thought that they might be valuable.  But nowhere could I find any notation  for 
the second, third ... dimension of the array.  Without that, open and  
dynamic arrays were little more than curiosities, possibly useful for  
1-dimensional array, but not beyond.
 
Now I see from your email that the notation for the second dimension of an  
array is Length(xarray[i]) where i is any valid index value (and hence can  
always be 0).  By extension, the third dimension presumably would be  
Length(xarray[0,0]), and so forth.
 
Never, ever, would I have guessed that would work.  It  makes sense 
mathematically, but notationally I would have expected  something like 
Length(xarray,2) for the second dimension.  If I had  thought of Length(xarray[0]), I 
would have deemed it so implausible that  I never would have tried it.
 
But simply because this is feasible does not mean that one should use  it.  
For one thing, I would like the compiler to generate warning messages  if I 
try to add two matrices of incompatible sizes.  I don't want to  discover 
this hours into a computation.  That type of checking is one of  the main 
virtues of Pascal.
 
For another, it requires that I code a SetLength statement for every  
array.  That means the array information becomes decentralized.  I  can't just 
read down the VAR section of my procedure and learn what I need about  the 
variables, I must consult two sections. 
 
Of course I wouldn't have to make every array open, but then I would have a 
 mixture of two kinds of array declarations.  This creates an extra  
maintenance task, making some arrays open, when needed, and restoring them  to 
fixed size when they no longer need to be open.  The problem  could become 
fierce when the same declarations are shared by several different  procedures.  
Which one should set the length?  How can I be sure  the length is set 
before I reach MyProc?
 
So, once again, I throw my support towards adding vector operations to the  
compiler.
 
Frank Rubin


In a message dated 8/6/2010 12:23:25 P.M. Eastern Daylight Time,  
harley@umich.edu writes:
Dear Frank Rubin,

"Except that you have to  code every single case separately, 2x6, 3x10, 
4x4x4, etc. You need to write  a separate routine for every shape of array 
you 
want to use."

Not  so:

Use open arrays (always 0-based):

type  Matrix = array of  array of TRing;

Youu can write code, roughly:

operator *  (const  A, B: Matrix): Matrix;

var  RowA, ColA, RowB,  ColB,
I, J, K: Integer;
T: TRing;

begin
RowA := Length(A); ... ColB :=  Length(B[0]);
if  ColA <> RowB then ...
SetLength(Result,  RowA);
for  J := 0 to RowA - 1  do  SetLength(Result[J],  ColB);
for  I := 0  to  RowA - 1  do
for  K  := 0  to  ColB - 1  do
begin
T := Zero;   // prefer just 0
for  J := 0  to  ColA - 1   do
T := T + A[I, J]*B[J, K];
Result[I, K] :=  T;
end;
end;

once and for all, covering all sizes of  matrices.

The problem I do not yet know how to solve:
to do it for all  TRing.

So I need a type TRing that can include any structure
that has  + and * operators, and a 0 element:

Integers,  Floats, Rationals,  Gaussian Integers,
Polynomials  with xxx coefficients,... any  possible
data type I can define with overloaded +, *, etc.

Note that 0  is a problem in itself  -- one really needs
to overload it  too!

Frank Heckenbach's first reply to me may contain the answer.
I  haven't completely digested it yet.

Cheers,

Harley
 


  

-- 
=============================
Prof. Harley Flanders
3533 Windemere Court
Ann Arbor, MI 48105-2867
Home: 734 668 1546
harley@umich.edu
=============================