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(a)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