1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 | -- Main application using a Fortran and C routine
with Ada.Numerics.Real_Arrays;
with Ada.Float_Text_IO;
with Ada.Text_IO;
with Interfaces.C;
with Interfaces.Fortran;
procedure Main is
use Ada;
use Ada.Numerics.Real_Arrays;
use Interfaces;
use type Fortran.Logical;
type Matrix is array (Integer range <>, Integer range <>) of Float'Base;
-- Root matrix type, derived below with C and Fortran convention
-- C binding
type C_Matrix is new Matrix (1 .. 3, 1 .. 3);
pragma Convention (C, C_Matrix);
procedure initmat (M : in out C_Matrix; Line, Column : C.int);
pragma Import (C, initmat, "initmat");
-- Fortran binding
type F_Matrix is new Matrix (1 .. 3, 1 .. 3);
pragma Convention (Fortran, F_Matrix);
procedure multmat
(Res : out Fortran.Logical;
M1 : in F_Matrix; Line1, Column1 : Fortran.Fortran_Integer;
M2 : in F_Matrix; Line2, Column2 : Fortran.Fortran_Integer;
M3 : out F_Matrix);
pragma Import (Fortran, Multmat);
pragma Import_Valued_Procedure (Multmat);
-- Ada code
procedure Copy (FM : in F_Matrix; AM : out Real_Matrix) is
begin
-- We should check the ranges here
for L in FM'Range (1) loop
for C in FM'Range (2) loop
AM (L, C) := FM (L, C);
end loop;
end loop;
end Copy;
procedure Display (M : in Real_Matrix) is
begin
for L in M'Range (1) loop
Text_IO.Put ("| ");
for C in M'Range (2) loop
Float_Text_IO.Put (M (L , C), Fore => 3, Aft => 4, Exp => 0);
Text_IO.Put (", ");
end loop;
Text_IO.Put_Line (" |");
end loop;
Text_IO.New_Line;
end Display;
CM1, CM2 : C_Matrix;
FM1, FM2, FM3 : F_Matrix;
Res : Fortran.Logical;
AM1, AM2 : Real_Matrix (1 .. 3, 1 .. 3);
D : Float;
begin
-- Initialize matrix with the C routine
initmat (CM1, C.int (CM1'Length (1)), C.int (CM1'Length (2)));
initmat (CM2, C.int (CM2'Length (1)), C.int (CM2'Length (2)));
-- Multiply both matrix using the Fortran routine
-- The following copies encure the convertion between both convention
-- (line, column order being different in C/Ada and Fortran.
FM1 := F_Matrix (CM1);
FM2 := F_Matrix (CM2);
multmat (Res,
FM1,
Fortran.Fortran_Integer (FM1'Length (1)),
Fortran.Fortran_Integer (FM1'Length (2)),
FM2,
Fortran.Fortran_Integer (FM2'Length (1)),
Fortran.Fortran_Integer (FM2'Length (2)),
FM3);
if not Res then
Text_IO.Put_Line ("Dimentions are not compatible");
return;
end if;
-- Transpose the matrix using Ada.Numerics support.
-- We need to copy the Fortran matrix into the Ada one.
Copy (FM3, AM1);
AM2 := AM1 / 2.0;
Text_IO.Put_Line ("Matrix :");
Display (AM1);
Text_IO.Put_Line ("Matrix divided by 2 :");
Display (AM2);
D := Determinant (AM2);
Text_IO.Put ("Corresponding determinant :");
Float_Text_IO.Put (D, Fore => 3, Aft => 7, Exp => 0);
Text_IO.New_Line;
end Main;
|