I want to write a code for postgis in pgAdmin that is based on postgresql. It defines a 3-dimensional array of geometry.
I used this code for it:
DECLARE
G geometry[9][9][9];
BEGIN
for i IN 1..9 LOOP
for j IN 1..9 LOOP
for k IN 1..9 LOOP
G[i][j][k] := [value that I want];
END LOOP;
END LOOP;
END LOOP;
But it returned this error:
"array subscript out of range"
I used this instead:
DECLARE
G geometry[9][9][9];
BEGIN
for i IN array_lower(G, 1)..array_upper(G, 1) LOOP
for j IN array_lower(G, 1)..array_upper(G, 1) LOOP
for k IN array_lower(G, 1)..array_upper(G, 1) LOOP
G[i][j][k] := [value that I want];
END LOOP;
END LOOP;
END LOOP;
I have a different error this time:
"lower bound of FOR loop cannot be null"
I used this in BEGIN Part and solved all the errors:
G[1][1][1] := '01010000200400000000000000000000000000000000000000';
But I think this is not true and doesn't calculate all of the iterations for loops. I think this takes in account only the G[1][1][1]. What should I do now?
In PostgreSQL, simply declaring the array dimensions does not initialize or pre-allocate anything. The array is dynamic in all its dimensions. That differs significantly from the multi-dimensional array implementations found in general programming language like C.
To mimic the logic of these languages, you may first initialize the 9x9x9 array with a statement like this:
G:=array_fill('point(0 0)'::geometry, array[9,9,9]);
Then the rest of the code will just work when refering to G[i][j][k] either as source or destination of assignments.
Related
I have declared an array
type datastream is array(0 to 10) of signed (5 downto 0);
For simulation, I want to display the array as integer-numbers
So I created
type datastream_int is array(0 to 10) of integer;
and
signal DIN_ARRAY: datastream;
signal DIN_ARRAY_int: datastream_int;
...
DIN_ARRAY_real <= datastream_int(DIN_ARRAY);
But it fails. How to convert it? Dont want to use a for loop
The numeric_std package, that I assume you are using, provides a to_integer function to convert from a single signed value to a single integer object. For an array, you're going to have to use a for loop. Something like this:
for i in DIN_ARRAY'range loop
DIN_ARRAY_int <= to_integer(DIN_ARRAY(i));
end loop;
You could also provide a conversion function (it will also contain a for loop)
function datastream_to_datastream_int( d : datastream ) return datastream_int is
variable r : datastream_int;
begin
for i in d'range loop
r(i) := to_integer(d(i));
end loop;
return r;
end function;
....
--no loop required
DIN_ARRAY_int <= datastream_to_datastream_int(DIN_ARRAY);
So, there will be a for loop somewhere.
Your code fails because you have attempted a type conversion, which is only allowed between similar types - ie. array or record types where the element types match between the two types.
PS. VHDL 2008 provides an integer_vector type in the std.standard library (which is included by default) which may help by allowing you to do this:
signal DIN_ARRAY_int: integer_vector(DIN_ARRAY'range);
If you did decide to keep datastream_int as per your original, you could type convert it to an integer_vector, because the types are similar:
my_iv <= integer_vector(DIN_ARRAY_int);
module rev_array;
int array_in[10]={0,1,2,3,4,5,6,7,8,9};
typedef integer array[9:0];
function array reverse(int array_in[10]);
for(int j=$size(array_in)-1,int i=0;j>=0;j--,i++)
begin
reverse[j]=array_in[i];
end
// working for(integer k=0;k<$size(array_in)-1;k++)
// working $display("reverse[%0d]:%0d", k, reverse[k]);
$display("inside function");
endfunction:reverse
initial
begin
reverse(array_in);
for(integer k=0;k<$size(array_in)-1;k++)
begin
$display("reverse[%0d]:%0d", k, reverse[k]);
end
end
endmodule
Error-[IUS] Illegal use of scope
testbench.sv, 22
rev_array, "rev_array.reverse"
Scope cannot be used in this context
Error-[XMRIBS] Illegal bit select
testbench.sv, 22
Error is found in following cross-module reference, illegal bit select on
the target.
Source info: $display("reverse[%0d]:%0d", k, rev_array.reverse[k]);
I am trying to reverse an array and return it in system verilog function, I am able to see the reversed array inside the function by printing it but
when I try to print it using $display outside the function, I think it is
not being returned properly somehow, in the 4th line from end, getting
errorError-[IUS]
your both issues are related to the line where you use reverse function name as an array within $display.
$display("reverse[%0d]:%0d", k, reverse[k]);
--------------------------------^^^^^^^^^^
this is an illegal syntax causing both messages.
your initial block should look like the following.
initial
begin
array result;
result = reverse(array_in);
//^^^^^^^^^^^^^^^^^^^^^^^^^//
for(integer k=0;k<$size(array_in)-1;k++)
begin
$display("reverse[%0d]:%0d", k, result[k]);
// ^^^^^^ //
end
end
call the function and use returned results for display.
module rev_array;
initial
begin
int array_in[10]={0,1,2,3,4,5,6,7,8,9};
typedef integer array[9:0];
function array reverse(int array_in[10]);
array reverse;
for(integer i=0;i<$size(array_in)-1;i++)
begin
for(int j=$size(array_in)-1;j>=0;j--)
begin
reverse[j]=array_in[i];
end
end
return reverse;
endfunction:reverse
reverse(array_in);
for(integer k=0;k<$size(array_in)-1;k++)
begin
$display("reverse[%0d]:%0d", k, reverse[k]);
end
end
endmodule
For the above code, I am getting error
Error-[SE] Syntax error
Following verilog source has syntax error :
"testbench.sv", 7: token is 'function'
function array reverse(int array_in[10]);
I want to return an array named reverse(same name as the function ) which has 10 elements, each element being an integer, what am I doing wrong here ?
You cannot define a function in the middle of a procedural block. Move it to the top level of the module. You have many other problems. Note there is a built-in reverse array method.
foreach(a.b[i]) begin
foreach(a.b[i][j]) begin
foreach (a.b[i][j].c[k]) begin
d = a.b[i][j].c[k];
end
end
end
a is a class, b is an object of a separate class e in class a, c is a member of class e which is being accessed through b and d is variable being assigned the value present in c.
I am getting a syntax error in first line itself. What is the correct way to loop over the elements of the multi-dimensional array b?
As per section 12.7.3 of the IEEE 1800-2017 LRM, the proper syntax to loop over your multi-dimensional array is:
foreach(a.b[i, j]) begin
foreach (a.b[i][j].c[k]) begin
d = a.b[i][j].c[k];
end
end
ERROR at line 8: PL/SQL: Statement ignored
CREATE OR REPLACE PROCEDURE POS(A IN NUMBER,M IN NUMBER,TOTAL OUT NUMBER)
AS
BEGIN
TOTAL:=0;
WHILE A>0 LOOP
M:=MOD(A,10);
TOTAL:=TOTAL+M;
A:=(A/10);//statement ignored error
END LOOP;
DBMS_OUTPUT.PUT_LINE(TOTAL);
END;
DECLARE
X NUMBER;
Y NUMBER:=5;
Z NUMBER;
BEGIN
POA(X,Y,Z);
END;
OK, I've had a look at your procedure and tried to resolve the issues you are having with it.
You haven't explained much (or indeed anything) about what you are trying to achieve which makes it really difficult to get you an answer.
People on here really want to help but you have to at least give us the tools with witch to provide that help.
Anyhow, with a host of assumptions, here is my version of your procedure with the following assumptions:
Your procedure is names POS (you name it POS in the procedure definition but then try to execute it as POA).
Your main issue was trying to assign a new value to input parameter "a" within the loop. As it is an input parameter it is immutable and you cannot assign new values to it. I have got round this by declaring a local variable "v_iter" and assigning that the value of "a" and then using it to control the loop.
I have added an "exception" section to handle any unexpected errors and output that error via DBMS_OUTPUT. You might want to make this more robust.
You do not test to check if the input parameter "a" is null or a valid number (i.e. not negative), you might want to do this to make your procedure more robust.
Here is the changed code:
CREATE OR REPLACE
PROCEDURE POS (
a IN NUMBER,
m IN NUMBER,
total OUT NUMBER
)
AS
— Declare variables
v_iter NUMBER := a;
BEGIN
— Initialise total
total := 0;
— Loop through “v_iter”
WHILE v_iter > 0
LOOP
m := MOD(v_iter,10);
total := total + m;
v_iter := (v_iter/10);
END LOOP;
DBMS_OUTPUT.put_line(total);
EXCEPTION
WHEN others
THEN
— Output and raise an error;
DBMS_OUTPUT.put_line(sqlerrm);
RAISE;
END POS;
/
To call it:
DECLARE
X NUMBER;
Y NUMBER:=5;
Z NUMBER;
BEGIN
POS(X,Y,Z);
END;
/
Hope it helps.