Ada compilers MUST not allow multiple references to the same memory block to be passed into a procedure if one of those references will be used to change the memory blocks contents within the procedure!
The reason for this is explained below but if Ada followed the rule above, it could not happen. Of course you can write code to get around the problem but that is not the point. There will be some code out there that suffers from this and it could be part of something critical like a rocket. Complex numbers are often used in dynamics.
BASICS: When you pass parameters to a procedure (or function) the Ada compiler decides to pass by reference or by value. Passing by reference just means no new memory is allocated and any changes will be to the original variable's memory. Passing by value means some new memory is allocated and a copy of the variable's value is copied into it on entry and if necessary copied back out on exit.
BASICS: Ada allows three possible forms of parameter passing "in", "out" and "in out" and although there are restrictions on when values are copied in and and copied out, ada can use passing by value or by reference in all three cases. It will prefer passing by reference on larger parameters in order to save wasting time making copies.
BASICS: It is the compilers decision, and here lies the root of the fault I am highlighting!
In the code below if myArray is (0..2) then opComplexProduct2(X,X) fails and if (0..1) it succeeds because Ada decides to pass by reference or value respectively. I am using the gcc compiler so other compilers may optimise differently. opComplexProduct2(X,Y); will still succeed as X and Y are different variables.
Obviously this is because X and Y are passed by reference, if myArray is (0..2) or (0..3) or more and by value if myArray is (0..1) or (0..0).
This is a very serious "side effect"!
Question: Why on earth should you pass the same parameter twice? Because opComplexProduct2(X,X); gives the square of the complex number which has many applications.
I repeat: **Ada compilers MUST not allow multiple references to the same memory block to be passed into a procedure if one of those references will be used to change the memory blocks contents within the procedure!**
Dummy line to overcome your editor BUG!
–
–
type type_Complex is record
x:Integer:=0;
iy:Integer:=0;
end record;
--COMMENT OUT ONE OF THESE LINES BELOW
type myArray is array (0..2) of type_Complex; -- opComplexProduct3(A,A); FAILS
--type myArray is array (0..1) of type_Complex; -- opComplexProduct3(A,A);SUCCEEDS
procedure opComplexProduct3(A:in out myArray; B:in myArray) is
n:Integer:=0;
t:Integer:=A(n).x;
begin
A(n).x := t * B(n).x - A(n).iy * B(n).iy;
A(n).iy := A(n).iy * B(n).x + t * B(n).iy;
return;
end opComplexProduct3;
procedure opComplexProduct3(A:in myArray; B:in myArray; C:out myArray) is
n:Integer:=0;
begin
C(n).x := A(n).x * B(n).x - A(n).iy * B(n).iy;
C(n).iy := A(n).iy * B(n).x + A(n).x * B(n).iy;
return;
end opComplexProduct3;
procedure opTest is
X,Y,Z:myArray;
begin
X(0).x:=2;X(0).iy:=3;
Y(0).x:=2;Y(0).iy:=3;
opComplexProduct2(X,X); --FAILS
Put_Line("The complex product is: ("
& Integer'Image(X(0).x) & ","
& Integer'Image(X(0).iy) & ")");
X(0).x:=2;X(0).iy:=3;
Y(0).x:=2;Y(0).iy:=3;
opComplexProduct2(X,Y);
Put_Line("The complex product is: ("
& Integer'Image(X(0).x) & ","
& Integer'Image(X(0).iy) & ")");
X(0).x:=2;X(0).iy:=3;
Y(0).x:=2;Y(0).iy:=3;
opComplexProduct3(X,Y,Z);
Put_Line("The complex product is for sure: ("
& Integer'Image(Z(0).x) & ","
& Integer'Image(Z(0).iy) & ")");
X(0).x:=2;X(0).iy:=3;
Y(0).x:=2;Y(0).iy:=3;
opComplexProduct3(X,X,X);
Put_Line("The complex product is: ("
& Integer'Image(Z(0).x) & ","
& Integer'Image(Z(0).iy) & ")");
return;
end opTest;