From: Peter C. Chapin on
This is something of a newbie question..

I'm working with a two dimensional array of floating point values. Lets call
it A. The array has type

type Matrix is array(Positive range <>, Positive range <>) of Floating_Type;

I need to exchange two rows in this array. What I'd like to do is something
along these lines:

Temp_Array := A(I, 1 .. Size);
A(I, 1 .. Size) := A(K, 1 .. Size);
A(K, 1 .. Size) := Temp_Array;

The compiler (GNAT GPL 2009) has a problem with this syntax and, after looking
into it some, I think that's because slicing only works for one dimensional
arrays. Fair enough.

So I thought, "Perhaps A needs to be an array of arrays."

type Matrix is array(Positive range <>) of WHAT_EXACTLY?

Apparently the component type of an array needs to be fully constrained (which
again makes sense) yet I don't know the size I'll want to use at the point
where this type is declared.

So now I'm thinking that I'll have to write a procedure to explicity swap each
row element one at a time. Of course this is not a terrible thing, but I'm
wondering if there is a more elegant way that I'm missing. I have some
confidence that the compiler can optimize slice operations reasonably well.
I'm less confident about its ability to optimize element by element
operations (maybe I'm overly pessimistic).

Peter

From: Jeffrey R. Carter on
Peter C. Chapin wrote:
>
> type Matrix is array(Positive range <>, Positive range <>) of Floating_Type;
>
> I need to exchange two rows in this array. What I'd like to do is something
> along these lines:
>
> Temp_Array := A(I, 1 .. Size);
> A(I, 1 .. Size) := A(K, 1 .. Size);
> A(K, 1 .. Size) := Temp_Array;
>
> The compiler (GNAT GPL 2009) has a problem with this syntax and, after looking
> into it some, I think that's because slicing only works for one dimensional
> arrays. Fair enough.

That's correct: slicing is only defined for one-D arrays.

> So I thought, "Perhaps A needs to be an array of arrays."
>
> type Matrix is array(Positive range <>) of WHAT_EXACTLY?

Row_Vector?

> Apparently the component type of an array needs to be fully constrained (which
> again makes sense) yet I don't know the size I'll want to use at the point
> where this type is declared.

Correct again: array components must be definite.

I'm not aware of a solution other than the brute force approach.

--
Jeff Carter
"Gentlemen, you can't fight in here. This is the War Room!"
Dr. Strangelove
30
From: Niklas Holsti on
Peter C. Chapin wrote:
> This is something of a newbie question..
>
> I'm working with a two dimensional array of floating point values. Lets call
> it A. The array has type
>
> type Matrix is array(Positive range <>, Positive range <>) of Floating_Type;
>
> I need to exchange two rows in this array. What I'd like to do is something
> along these lines:
>
> Temp_Array := A(I, 1 .. Size);
> A(I, 1 .. Size) := A(K, 1 .. Size);
> A(K, 1 .. Size) := Temp_Array;
>
> The compiler (GNAT GPL 2009) has a problem with this syntax and, after looking
> into it some, I think that's because slicing only works for one dimensional
> arrays. Fair enough.
>
> So I thought, "Perhaps A needs to be an array of arrays."
>
> type Matrix is array(Positive range <>) of WHAT_EXACTLY?
>
> Apparently the component type of an array needs to be fully constrained (which
> again makes sense) yet I don't know the size I'll want to use at the point
> where this type is declared.

One solution -- which may not match your design in other respects -- is
to make the Matrix an array of accesses to rows:

type Row is array (Positive range <>) of Float;
type Row_Ref is access Row;
type Matrix is array (Positive range <>) of Row_Ref;

Exchanging two rows is then very quick:

Temp_Ref := A(I);
A(I) := A(K);
A(K) := Temp_Ref;

However, you now have to allocate the rows using "new Row (1 .. Size)"
and perhaps later deallocate them using Unchecked_Deallocation.

Another solution -- which perhaps you have considered -- is to use a
generic package to define row and matrix types:

generic Size : Positive;
package Matrices
is
type Row is array (1 .. Size) of Float;
type Matrix is array (1 .. Size) of Row;
end Matrices;

However, this will probably force some other parts of your code to
become generic, too, parametrized either by a Size, or by an instance of
Matrices.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
From: Dmitry A. Kazakov on
On Sun, 31 Jan 2010 21:11:12 -0500, Peter C. Chapin wrote:

> So I thought, "Perhaps A needs to be an array of arrays."
>
> type Matrix is array(Positive range <>) of WHAT_EXACTLY?
>
> Apparently the component type of an array needs to be fully constrained (which
> again makes sense)

Not really. Arrays should have been allowed to have discriminants. That was
missed in the language design. If they had discriminants you could write:

type Row is array (Positive range <>) of Float;
type Matrix (Width : Positive) is
array (Positive range <>) of Row (1..Width);

(Of course the array bounds should have been discriminants rather than
attributes)

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Jerry on
I've never understood why Ada does not allow slicing in
multidimensional arrays. What are the safety issues involved? And how
is it safe to force the programmer into ad hoc methods?

Jerry