Transpose matrix ada - matrix

How can I transpose matrix in ADA?. I´ve tried:
procedure transpose(A: in out matrix) is
B : matrix(1..A'Last(2),1..A'Last(1));
begin
for i in A'Range(1) loop
for j in A'Range(2) loop
B(j,i):= A(i,j);
end loop;
end loop;
A := B;
end transpose;
but it doesn´t work when A isn´t a square Matrix.
Any help would be appreciated.

As a procedure this can never work for non-square matrices because the output is a different constrained type from the input. However you can return B from a suitable function.
function transpose(A: in matrix) return matrix is
B : matrix(A'Range(2),A'Range(1));
begin
for i in A'Range(1) loop
for j in A'Range(2) loop
B(j,i):= A(i,j);
end loop;
end loop;
return B;
end transpose;
The easiest way to create a matrix of the right constrained type for the result is a declare block:
declare
Transposed : Matrix := Transpose(A);
begin
-- operations on the transposed matrix
end;

You can transpose a matrix by creating a record like:
type Matrix_Type is record
Data : array (1..MAX_SIZE, 1..MAX_SIZE) of Float;
Last_Row : Positive range 1 .. MAX_SIZE;
Last_Column : Positive range 1 .. MAX_SIZE;
end record;
This record can support matrices of any m by n size up to n,m <= MAX_SIZE
Your procedure becomes:
procedure transpose(A: in out Matrix_Type) is
B : Matrix_Type;
begin
for i in 1..A.Last_Row loop
for j in 1..A.Last_Column loop
B(j,i):= A(i,j);
end loop;
end loop;
B.Last_Column := A.Last_Row;
B.Last_Row := A.Last_Column;
A := B;
end transpose;

The easiest way I know of is to use the Fortran convention on an intermediate array-type. (This is because Fortran convention is column-major while in Ada, it is row-major.)
Function Transpose(M : Matrix) return Matrix is
subtype Constrained is Matrix(M'Range(2), M'Range(1));
Type Xposed is new Matrix with Convention => Fortran;
Temp : Xposed := Xposed(M);
Result : Constrained with Import, Address => Temp'Address; --'
begin
Return Result;
end Transpose;

Related

Algorithm name for all 2-uplets of a set

I'm looking for the name (and for the code : in PL/SQL or PG/SQL) of the algorithm which is finding all couple (2-uplets) of a set.
Example :
A - B - C
Result :
1 : A - B
2 : A - C
3 : B - C
I know that the powerset algorithm do this part of the job, but I'm looking for an optimised couple finder algorithm.
Link for the powerset pg/sql algorithm : https://www.postgresql.org/message-id/20060924054759.GA71934%40winnie.fuhr.org
Have you considered something like
Select A.x, B.x
From YourTable as A, YourTable as B
Where A.key <> B.key
You mention SQL so this might be preferable. Note that the number of rows in the cross product is about the same as the number of pairs, so it isn't terribly inefficient.
I've build the solution :
CREATE OR REPLACE FUNCTION twouplets(a anyarray)
RETURNS SETOF anyarray AS
$BODY$
DECLARE
retval a%TYPE;
size integer := array_upper(a, 1);
i integer;
j integer;
BEGIN
i := 0;
j := 1;
FOR i IN 1 .. size LOOP
FOR j IN 1 .. size-i LOOP
retval := '{}';
retval := array_append(retval, a[i]);
retval := array_append(retval, a[i+j]);
RETURN NEXT retval;
END LOOP;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE STRICT
COST 100
ROWS 1000;
ALTER FUNCTION twouplets(anyarray)
OWNER TO postgres;

ADA - I got 2 Bubble sorting algorithm but only one works

As the title says I have two algorithm for bubble sorting but the one I wrote is not working in all cases.
This is the code that works in every case
procedure Sort( t: in out Item_array) is
Finished : Boolean;
tmp: Item;
begin
loop
Finished := True;
for J in t'First..Index'Pred(t'Last) loop
if t(J) < t(Index'Succ(J)) then
Finished := False;
tmp := t(Index'Succ(J));
t(Index'Succ(J)) := t(J);
t(J) := tmp;
end if;
end loop;
exit when Finished;
end loop;
end Sort;
And here is my code which is not working with the following array (2,4,3,2,2,5). I assume It is because of multiple '2's.
procedure Sort( t: in out Item_array) is
I : Index := t'Last;
CS: Index := t'First;
tmp: Item;
begin
while I >= Index'Succ(t'First) loop
for J in t'First..Index'Pred(I) loop
if t(J) < t(Index'Succ(J)) then
tmp := t(Index'Succ(J));
t(Index'Succ(J)) := t(j);
t(j) := tmp;
CS := J;
end if;
end loop;
I := CS;
end loop;
end Sort;
In both cases the "<" operator is a function template parameter, not a regular "less" or "more" operator.
And this is how I call the function.
function Asc(A,B : in Integer) return Boolean is (A > B); // Sorting function
procedure Sort_Asc is new Sort(Item=>Integer,
Index=>Positive,
Item_Array=>Int_Array,
"<"=>Asc);
x : Int_Array := (2,4,3,2,2,5);
Sort_Asc(x);
If I use the second algorithm, It'll stuck in an infinite loop.
//Please don't mind my english.

Package vhdl inclusion error

Hi guys i have the following package, defined by myself
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
package util_pkg is
function log2c(n : natural) return natural;
end package util_pkg;
package body util_pkg is
function log2c(n : natural) return natural is
variable temp : natural := n;
variable ret_val : natural := 0;
begin
while temp > 1 loop
ret_val := ret_val + 1;
temp = temp/2;
end loop;
return ret_val;
end function log2c;
end package body util_pkg;
while my design is
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
use work.util_pkg.all;
entity ldz is
generic(n : natural); --i can assume n > 1
port(x : in std_logic_vector(n - 1 downto 0);
y : out std_logic_vector(log2c(n) - 1 downto 0));
end entity ldz;
-- Example
architecture ldz_arch of ldz is
function ldz_count(x : unsigned) return natural is
n_ldz : natural := 0;
begin
for i in x'high to 0 loop
if(x(i) = '1') then
return x'length - i - 1;
end if;
end loop;
return x'length - 1;
end function ldz_count;
begin
y <= std_logic_vector(to_unsigned(ldz_count(to_unsigned(x)));
end architecture ldz_arch;
When i try to verify the syntax with ncvhdl this is the error i get
unit (UTIL_PKG) not found in library (WORKLIB)
however such unit (package) is in the same library of the design.
the file is util_pkg.vhd while the design is ldz.vhd
What is wrong?
The tool complains because the package has not been analysed (compiled) before ldz. Compile it first and ldz next.
As mentioned in the comments, your code suffers several problems. The following code computes the log2 of a positive, rounded towards 0 or infinity:
function log2_down(n: positive) is
variable res: natural := 0;
begin
if n /= 1 then
res := 1 + log2_down(n / 2);
end if;
return res;
end function log2_down;
function log2_up(n: positive) is
variable res: natural := 0;
begin
if n /= 1 then
res := 1 + log2_up((n + 1) / 2);
end if;
return res;
end function log2_up;
Yes, VHDL supports recursion and most synthesisers too, at least when the number of iterations is statically computable.
The res variable could be avoided but it helps avoiding the warnings of some tools that warn you if the return statements of a function are all under control of a control structure. They do this because they cannot prove that the function will always return while a function shall always return. I always try to suppress the warnings such that any remaining warning is meaningful and cannot be ignored.
Declaring the parameter as positive is a simple way to deal with the log2(0) error. I always try to use the built-in features of the language to deal with errors.
With the same two principles (no warnings, let the built-in features of the language deal with errors), your leading zero counter ldz_count function could be written:
function ldz_count(x: unsigned) return natural is
constant n: positive := x'length;
constant v: unsigned(0 to n - 1) := x;
variable res: natural := n;
begin
for i in 0 to n - 1 loop
if v(i) = '1' then
res := i;
end if;
end if;
return res;
end function ldz_count;
Copying the x parameter with a chosen bit indexing will make your function usable with any x parameter whatever its declaration (7 to 35 or 9 downto 4) as long as it is at least one bit long. This is the third principle I like: if you make something generic, make it really generic.

Insert row function for matrix (2D array) in vhdl?

Is there a shorthand way to set a row of values in a matrix? I'm looking for a function/procedure type of solution.
Just to clarify, by matrix I don't mean an array of array but rather a 2D array.
I've managed to read a specific row using:
function extract_row(matrix : matrix_type; row_index : natural) return row_type is
variable res : row_type (matrix'range(2));
begin
for i in res'range loop
res(i) := matrix(row, i);
end loop;
return res;
end function;
And now I need a way to set a row in a fashion similar to how one can set a subarray in the array of arrays:
signal x : array_of_rows_type(range_a)(range_b);
signal y : row_type(range_b);
x(0) <= y;
I realise the shorthand isn't necessary and that one can work around it using loops and generates, but I have many places where I need to do this, and it's becoming increasingly difficult to keep legible code (and my sanity).
For those wondering, the reason why I'm using the matrix approach and not the array of arrays is because I need to reuse the type in multiple entities with different ranges.
Bonus points if the solution somehow allows me to use it in port mapping (although I realise this is impossible, unless I've misunderstood VHDL completely). i.e.:
port map (
row_type_outport => row_insert_solution(matrix, row)
)
I seem to recognize the code for the extract_row function. Perhaps you could adapt the function replace_matrix_column that is given in the same package?
function replace_matrix_column(
input_matrix: bit_matrix;
new_column: bit_vector;
column_index: integer
) return bit_matrix is
variable output: bit_matrix(input_matrix'range(1), input_matrix'range(2));
begin
for i in input_matrix'range(1) loop
for j in input_matrix'range(2) loop
if j = column_index then
output(i, j) := new_column(i);
else
output(i, j) := input_matrix(i, j);
end if;
end loop;
end loop;
return output;
end;
Then you could call it like this:
x <= replace_matrix_row(x, y, 0);
Or, for better clarity:
x <= replace_matrix_row(input_matrix => x, new_row => y, row_index => 0);
I don't have your types, so I can't compile this to make sure it works, but this might help get you close.
function row_insert_solution(matrix : matrix_type;
row_insert : row_type;
row_index : natural
) return matrix_type is
variable res : matrix_type := matrix;
begin
for i in row_insert'range loop
res(row_index, i) := row_insert(i);
end loop;
return res;
end function;

small problem In Pascal , Could you please help?

I write this program with pascal
which ask the user to enter two arrays and constant value which is K
the program muli the K with arrays .
and then save the answer in new array
and do some operation in new array
addition << work well
Subtraction << also work
BUT the problem in Multi << I am trying to ask the user to enter a new array and do Muti but still there is a problem.
ALSO
I want these operation repeated until the user press exit <<< I could not do this options because i am not perfect with pascal .
I would be grateful if you could help me
This is My Code
program BST6;
const maxN=100;maxM=100;
type mat=array[1..maxN,1..maxM]of integer;
var A,B,c:mat;
n,m,l,s,i,j,k:integer;
ch : char;
procedure readMat(var A:mat;var m,n:integer);
begin
for i:=1 to m do
for j:=1 to n do
begin
write('mat[',i,',',j,']=');
readln(A[i,j]);
end;
end;
procedure writeMat(A:mat;m,n:integer);
begin
for i:=1 to m do
begin
for j:=1 to n do
write(a[i,j]:4);
writeln;
end;
end;
function multK(A:mat;k:integer):mat;
begin
for i:=1 to n do
for j:=1 to m do
begin
B[i,j]:= K*A[i,j];
end;
multK:=B;
end;
function minus(A,B:mat):mat;
begin
for i:=1 to m do
for j:=1 to n do
C[i,j]:=A[i,j]-B[i,j];
minus:=C;
end;
function plus(A,B:mat):mat;
begin
for i:=1 to m do
for j:=1 to n do
C[i,j]:=A[i,j]+B[i,j];
plus:=C;
end;
function mult(A,B:mat;m,l,n:integer):mat;
begin
for i:=1 to m do
for j:=1 to n do
for k:=1 to l do
c[i,j]:=c[i,j]+A[i,k]*B[k,j];
mult:=C;
end;
begin
write('input m<=',maxM,'.. m=' );readln(m);
write('input n<=',maxN,'.. n=');readln(n);
readMat(A,m,n);
writeln('input the const K');readln(k);
B:=multK(A,K);
writeln('The matrix A : ');
writeMat(A,m,n);
writeln('The matrix B=K*A : ');
writeMat(B,m,n);
writeln('choose the operation + , - or * ');
readln(ch);
case ch of
'+' : c:=plus(A,B);
'-' : c:=minus(A,B);
'*' : begin
writeln('input m<=',maxM,'input l<=',maxN);readln(m,l);readMat(A,m,l);
writeln('input l<=',maxN);readln(n);readMat(B,l,n);
c:=mult(A,B,m,l,n);
end;
end;
writeMat(c,m,n);
readln;
end.
First of all having global one letter variables which collide with function parameters with the same name is insane.
Why does multK modify the global variable B as a sideeffect?
Why does minus modify the global variable C as a sideeffect?
Why global integers as for index variables?
And mult is even worse: It doesn't only modify C as a sideeffect, but it assumes C contains meaningful values beforehand. I think it needs to initialize C to all zeros beforehand.
My guess is some of your side effects interfere in strange ways. But I don't want to think it through. Refactor your code first. In particular learn how and when to use local variables.

Resources