with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.Fortran; use Interfaces.Fortran;
procedure Test is
type Cell_Matrix is array (1..4, 1..2) of Real with
Convention => Fortran;
type Matrix is array (1..2, 1..4) of Real;
A : Cell_Matrix := ((1.1, 1.2), (2.1, 2.2), (3.1, 3.2), (4.1, 4.2));
B : Matrix;
pragma Import (Ada, B);
for B'Address use A'Address;
begin
for I in A'Range (1) loop
for J in A'Range (2) loop
Put (Real'Image (A (I, J)));
Put (' ');
end loop;
New_Line;
end loop;
New_Line;
for I in B'Range (1) loop
for J in B'Range (2) loop
Put (Real'Image (B (I, J)));
Put (' ');
end loop;
New_Line;
end loop;
end Test;
It is only Implementation Advice that arrays with Convention Fortran use column-major order, so a compiler does not have to do so. However, I know that GNAT does so, at least for unpacked arrays of numbers. You’re packing your array into a single byte, and that may conflict with or take precedence over the convention. I tried
with Ada.Text_IO;
with Ada.Unchecked_Conversion;
procedure Fortran_Test is
type Cell_Base is array (1 .. 4, 1 .. 2) of Boolean;
type Cell_Fortran is new Cell_Base with Convention => Fortran;
type Cell_Packed is new Cell_Base with Component_Size => 1, Size => 8;
type Cell_PF is new Cell_Packed with Convention => Fortran;
B : constant Cell_Base := ( (False, False), (False, True), (True, False), (True, True) );
F : constant Cell_Fortran := Cell_Fortran (B);
PB : constant Cell_Packed := Cell_Packed (B);
PF : constant Cell_PF := Cell_PF (F);
type Byte is mod 256;
function To_Byte is new Ada.Unchecked_Conversion (Source => Cell_Packed, Target => Byte);
function To_Byte is new Ada.Unchecked_Conversion (Source => Cell_PF, Target => Byte);
begin -- Fortran_Test
Ada.Text_IO.Put_Line (Item => "PB =" & To_Byte (PB)'Image & " PF =" & To_Byte (PF)'Image);
end Fortran_Test;
with GNAT and got 216 for both. With ObjectAda I get PB = 216 PF = 2; the value for PF is clearly wrong.
So it’s the packing that in the case of GNAT is nullifying the Fortran convention.
Anyway, as long as those are recommendations and there’s no way to be sure that the compiler either gives you what you want or a compilation error, I’m not happy with relying on any behavior. And GNAT at least is not warning about not honoring the convention.
It might be worth putting in a report with AdaCore and see if it is intended. Even though it is implementation advice, I always took that to be more of the advice was “to either provide the convention or not and if you do here are the rules”. It would be odd to have the convention only it doesn’t actually map to the language types correctly in some situations (without warnings).
Fortran does have booleans and arrays of booleans. HOWEVER, it does not have bit arrays (packed arrays of booleans). Bit arrays in Fortran, as expected by the standard and by its users, are Arrays of integers on which bit operators can be performed (or just a single INT*8/16/…).
Therefore, what you are trying to do here is illegal in Fortran and its behaviour is either undefined or implementation defined. I think this is good. Though true, GNAT could issue a warning!
Also, I would like to see more Fortran/Ada interop ^^
This is not a very satisfactory answer: the notion of an array of integers —even constrained to the range 0 to 1, inclusive— indexed in row- or column-major ordering is separate and distinct from the mere implementation-detail of how much space said integers take up.
Yes, I agree, but the problem remains. I also did not want to focus too much on the space required for the integers… Though I understand that the underlying memory should be the same, so Ada/GNAT could try a bit harder or just be honest and say that this is a mistake
This is a valid point, but I’m really not interested in interoperating with Fortran, it was just the only thing I found that could affect the component layout. I would be perfectly happy with something like
type Matrix is array (1 .. 4, 1 .. 2) of Boolean with
Storage_Layout => Column_Major;
I find interesting that you can be precise (and get guarantees) with record representation clauses, but there seems to be no similar capabilities for arrays.
type Bit_Map is array (1 .. 8) of Boolean with Component_Size => 1, Size => 8;
the language doesn’t specify which index corresponds to which bit position. If you need to use indices to access specific bit positions, it’s probably best to use a private type with appropriate operations.