I'm trying to do a few mathematical operations on integers in a piece of vhdl code but when i try to compile the tool says "0 definitions of operator "+" match here". Here is what i'm trying to do:
for i in 0 to arr_size - 1 loop
for j in 0 to arr_size - 1 loop
for k in 0 to arr_size - 1 loop
for l in 0 to arr_size - 1 loop
for m in 0 to arr_size - 1 loop
mega_array(i)(j)(k)(l)(m) <= i*(arr_size**4) + j*(arr_size**3) + k*(arr_size**2) + l*(arr_size**1) + m*(arr_size**0);
end loop;
end loop;
end loop;
end loop;
end loop;
The problem was encountered in the line where mega_array is set. Note that this whole block is in a process.
Additionally:
arr_size : integer := 4;
sig_size : integer := 32
type \1-line\ is array (arr_size - 1 downto 0) of unsigned (sig_size - 1 downto 0);
type square is array (arr_size - 1 downto 0) of \1-line\;
type cube is array (arr_size - 1 downto 0) of square;
type hypercube is array (arr_size - 1 downto 0) of cube;
type \5-cube\ is array (arr_size - 1 downto 0) of hypercube;
signal mega_array : \5-cube\;
When reading your older post, the mega_array is an array of 4 levels with at the lowest level an unsigned. In your code in this question I see 5 levels. So at the fifth level you have bit. You can not assign an integer to a std_logic.
Could it be this code is what you want?
for i in 0 to arr_size - 1 loop -- 5-cube
for j in 0 to arr_size - 1 loop -- hypercube
for k in 0 to arr_size - 1 loop -- cube
for l in 0 to arr_size - 1 loop -- square
for m in 0 to arr_size - 1 loop -- 1-line
mega_array(i)(j)(k)(l) <= to_unsigned(i*(arr_size**4) + j*(arr_size**3) + k*(arr_size**2) + l*(arr_size**1), 32);
end loop
end loop;
end loop;
end loop;
end loop;
The to_unsigned functions converts the integer to an unsigned, what is the type of 1-line. The second parameter is the size of the vector to convert the integer into. It must be the same as the size of 1-line.
Related
I am trying to prove that my implementation of Select Sort in Ada is correct. I have tried a few loop invariants, but using gnatprove only proves inner loop's invariant:
package body Selection with SPARK_Mode is
procedure Sort (A : in out Arr) is
I: Integer := A'First;
J: Integer;
Min_Idx: Integer;
Tmp: Integer;
begin
while I < A'Last loop
pragma Loop_Invariant
(Sorted( A (A'First .. I) ));
Min_Idx := I;
J := I + 1;
while J <= A'Last loop
if A (J) < A (Min_Idx) then
Min_Idx := J;
end if;
pragma Loop_Invariant
(for all Index in I .. J => (A (Min_Idx) <= A (Index)));
J := J + 1;
end loop;
Tmp := A (Min_Idx);
A (Min_Idx) := A (I);
A (I) := Tmp;
I := I + 1;
end loop;
end Sort;
end Selection;
package Selection with SPARK_Mode is
type Arr is array (Integer range <>) of Integer;
function Sorted (A : Arr) return Boolean
is (for all I in A'First .. A'Last - 1 => A(I) <= A(I + 1))
with
Ghost,
Pre => A'Last > Integer'First;
procedure Sort (A : in out Arr)
with
Pre => A'First in Integer'First + 1 .. Integer'Last - 1 and
A'Last in Integer'First + 1 .. Integer'Last - 1,
Post => Sorted (A);
end Selection;
Gnatprove tells me
selection.adb:15:14: medium: loop invariant might not be preserved by an arbitrary iteration, cannot prove Sorted( A (A'First..I)) (e.g. when A = (-1 => 0, 0 => 0, others => 1) and A'First = -1)
Do you have any ideas how to solve this problem?
I reworked the routine a little bit, added two loop invariants to the outer loops and moved all of them to the end of the loop. The two additional loop invariants state that the element being processed is always greater-than or equal-than those that have already been processed and less-than or equal-than those yet to be processed.
I also changed the Sorted ghost function / predicate to only apply the quantified expression to arrays with length greater than 1. This is to prevent problems with overflow. For arrays of length 0 or 1, the function returns True by definition as (if False then <bool_expr>) is True (or vacuously true, if I remember correctly).
All VCs can be discharged/proved with gnatprove that ships with GNAT/SPARK CE 2020 at level 1:
$ gnatprove -Pdefault.gpr -j0 --report=all --level=1
selection.ads
package Selection with SPARK_Mode is
type Arr is array (Integer range <>) of Integer;
function Sorted (A : Arr) return Boolean is
(if A'Length > 1 then
(for all I in A'First + 1 .. A'Last => A (I - 1) <= A (I)))
with Ghost;
procedure Sort (A : in out Arr)
with Post => Sorted (A);
end Selection;
selection.adb
package body Selection with SPARK_Mode is
----------
-- Sort --
----------
procedure Sort (A : in out Arr) is
M : Integer;
begin
if A'Length > 1 then
for I in A'First .. A'Last - 1 loop
M := I;
for J in I + 1 .. A'Last loop
if A (J) <= A (M) then
M := J;
end if;
pragma Loop_Invariant (M in I .. J);
pragma Loop_Invariant (for all K in I .. J => A (M) <= A (K));
end loop;
declare
T : constant Integer := A (I);
begin
A (I) := A (M);
A (M) := T;
end;
-- Linear incremental sorting in ascending order.
pragma Loop_Invariant (for all K in A'First .. I => A (K) <= A (I));
pragma Loop_Invariant (for all K in I .. A'Last => A (I) <= A (K));
pragma Loop_Invariant (Sorted (A (A'First .. I)));
end loop;
end if;
end Sort;
end Selection;
In this code, I am trying to write a program that prints out the Fibonacci series based on the users' input (Index, Size). An then, the program should print out all the Fibonacci numbers between Index..Size. I have trouble, writing a recursion that calculates and prints out the Fibonacci numbers. Any suggestions?
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Text_IO, Ada.Unchecked_Deallocation;
procedure Fibonacci is
type Arr is array (Positive range <>) of Integer;
type Array_Access is access Arr;
Size, Index : Positive;
Variable : Array_Access;
procedure Free is new Ada.Unchecked_Deallocation (Arr, Array_Access);
procedure Recursion (Item : Arr) is --Recursion
begin
Put_Line
(Item (Item'First)'Image); --Prints out the numbers
Recursion
(Item
(Item'First + Item'First + 1 ..
Item'Last)); --Calculating the Fibonacci numbers
end Recursion;
begin
Put ("Welcome to the Fibonacci number series!");
Put
("Enter an initial value and how many Fibonacci numbers you want to print: ");
Get (Index);
Get (Size);
Variable := new Arr (Index .. Size);
Recursion (Variable);
end Fibonacci;
Example: Enter Index (the initial value of the Fibonacci series): 1
Enter Size (how many Fibonacci numbers to print): 5
The first 5 Fibonacci numbers are: 1 1 2 3 5
From Wikipedia,
In mathematics, the Fibonacci numbers, commonly denoted Fn, form a sequence, called the Fibonacci sequence, such that each number is the sum of the two preceding ones, starting from 0 and 1. That is,
F0 = 0
F1 = 1
and
Fn = Fn - 1 + Fn - 2
which translates pretty directly into
function Fibonacci (N : Natural) return Natural is
(case N is
when 0 => 0,
when 1 => 1,
when others => Fibonacci (N - 1) + Fibonacci (N - 2));
or, old style,
function Fibonacci (N : Natural) return Natural is
begin
if N = 0 then
return 0;
elsif N = 1 then
return 1;
else
return Fibonacci (N - 1) + Fibonacci (N - 2);
end if;
end Fibonacci;
You do have to do your printing outside the function, and admittedly there’s an inefficiency in repeatedly calculating the lower results, but you weren’t asking for efficiency.
Here is how you can do it (this code is based on https://rosettacode.org/wiki/Fibonacci_sequence#Recursive)
with Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Fibonacci is
First, Amount: Positive;
function Fib(P: Positive) return Positive is --Recursion
begin
if P <= 2 then
return 1;
else
return Fib(P-1) + Fib(P-2);
end if;
end Fib;
begin
Ada.Text_IO.Put_Line("Welcome to the Fibonacci number series!");
Ada.Text_IO.Put_Line("Enter an initial value and how many Kombinacci numbers you want to print: ");
Ada.Integer_Text_IO.Get(First);
Ada.Integer_Text_IO.Get(Amount);
for I in First .. First + Amount loop
Ada.Text_IO.Put("Fibonacci(" & Positive'Image(I) & " ) = ");
Ada.Text_IO.Put_Line(Positive'Image(Fib(I)));
end loop;
end Fibonacci;
I just started to learn some ada code and would create my very own primes calculator.
To procress, I use one of most known method, which is :
"each primes is a result of 6 * x -+ 1 "
So this is my code :
with Ada.Text_IO, Ada.Integer_Text_IO ;
use Ada.Text_IO, Ada.Integer_Text_IO ;
procedure main is
count_prime : Integer := 0 ;
counter : Integer := 1 ;
wanted : Integer ;
iteration : Integer := 0 ;
testing : Integer := 0 ;
is_prime : Boolean ;
answer : Character ;
begin
loop
Put("Prime calculator") ;
New_line(2) ;
Put("Put 'p' to process") ;
New_Line(1);
Put("Put 'q' to quit") ;
New_Line(2) ;
Put(">> ") ;
Get(answer) ;
if answer = 'p' then
Put("Enter wanted primes :");
Get(wanted) ;
Skip_line ;
if wanted > 0 then
Put("2");
New_Line(1);
if wanted > 1 then
Put("3");
New_Line(1);
end if ;
if wanted > 2 then
count_prime := 2;
loop
if counter = 1 then
counter := 0 ;
iteration := iteration + 1 ;
testing := ( 6 * iteration ) - 1 ;
else
counter := 1 ;
testing := ( 6 * iteration ) + 1 ;
end if ;
is_prime := True ;
for i in 2..(testing-1) loop
if (testing rem i = 0) then
is_prime := False ;
end if ;
end loop;
if is_prime = True then
Put(testing);
New_Line(1);
count_prime := count_prime + 1 ;
end if ;
exit when count_prime = wanted;
end loop ;
end if;
Put("Ended") ;
else
Put("It's can't be a negative number");
end if ;
end if ;
New_Line(3);
exit when answer = 'q' ;
end loop ;
end main ;
I really know this is a basic, I mean ouh, extremely basic program. But I would just solve the problem I've asked :
with 'p' and 2 :
2
3
with 'p' and '7'
2
3
5
7
11
13
17
with 'p' and 1200
2
3
19
23
29
31
37
41
....
Where are gone all primes between 3 and 19 ?
You keep running the calculation in a cycle, but do not reset it's initial state. The loop that performs the calculation continues using values of iteration, counter and a few other variables from the previous run.
Either decompose the loop into a separate procedure, or at least surround it with declare block, e.g.:
declare
count_prime : Integer := 2;
counter : Integer := 1;
iteration : Integer := 0;
testing : Integer := 0;
is_prime : Boolean;
begin
loop
…
end loop;
end;
However, I'd strongly recommend decomposing into a separate procedure.
if wanted > 2 then
count_prime := 2;
-- you probably want to reset iteration here...
iteration := 0;
loop
if counter = 1 then
I'm coding the spigot algorithm for displaying digits of pi in ada, but my output is wrong and I can't figure out why
I've tried messing with the range of my loops and different ways to output my data but nothings worked properly
with ada.integer_text_io; use ada.integer_text_io;
with Ada.Text_IO; use Ada.Text_IO;
procedure Spigot is
n : constant Integer := 1000;
length : constant Integer := 10*n/3+1;
x,q,nines,predigit :Integer :=0;
a: array (0..length) of Integer;
begin
nines:=0;
predigit:=0;
for j in 0..length loop
a(j):=2;
end loop;
for j in 1..n loop
q:=0;
for i in reverse 1..length loop
x:=10*a(i) + q*i;
a(i):= x mod (2*i-1);
q:= x/(2*i-1);
end loop;
a(1):= q mod 10;
q:=q/10;
if q = 9 then
nines:=nines+1;
elsif q = 10 then
put(predigit+1);
for k in 0..nines loop
put("0");
end loop;
predigit:=0;
nines:=0;
else
put(predigit);
predigit:=q;
if nines/=0 then
for k in 0..nines loop
put("9");
end loop;
nines:=0;
end if;
end if;
end loop;
put(predigit);
end Spigot;
so it should just be displayed at 0 3 1 4 1 5 9 2 6 5 3 5 8 9... but the output i get is 0 3 1 4 1 599 2 6 5 3 5 89... it should only be 1 digit at a time and also the outputted values for pi aren't completely correct
I don't know the algorithm well enough to talk about why the digits are off, but I did notice some issues:
Your array is defined with bounds 0 .. Length, which would give you 1 extra element
In your loop that does the calculation, you loop from 1..length, which is ok, but you don't adjust the variable i consistently. The array indices need to be one less than the i's used in the actual calculations (keep in mind they still have to be correctly in bounds of your array). For example
x:=10*a(i) + q*i;
needs to either be
x:=10*a(i-1) + q*i;
or
x:=10*a(i) + q*(i+1);
depending on what you decide your array bounds to be. This applies to multiple lines in your code. See this Stackoverflow thread
You assign A(1) when your array starts at 0
Your loops to print out "0" and "9" should be either 1..length or 0 .. length-1
When you print the digits using Integer_Text_IO.Put, you need to specify a width of 1 to get rid of the spaces
There might be more, that's all I saw.
I think you are translating this answer.
You need to be more careful of your indices and your loop ranges; for example, you’ve translated
for(int i = len; i > 0; --i) {
int x = 10 * A[i-1] + q*i;
A[i-1] = x % (2*i - 1);
q = x / (2*i - 1);
}
as
for i in reverse 1..length loop
x:=10*a(i) + q*i;
a(i):= x mod (2*i-1);
q:= x/(2*i-1);
end loop;
The loop ranges are the same. But in the seocnd line, the C code uses A[i-1], whereas yours uses a(i); similarly in the third line.
Later, for
for (int k = 0; k < nines; ++k) {
printf("%d", 0);
}
you have
for k in 0..nines loop
put("0");
end loop;
in which the C loop runs from 0 to nines - 1, but yours runs from 0 to nines. So you put out one more 0 than you should (and later on, likewise for 9s).
Also, you should use put (predigit, width=> 0).
I have the following program:
procedure Main with SPARK_Mode is
F : array (0 .. 10) of Integer := (0, 1, others => 0);
begin
for I in 2 .. F'Last loop
F (I) := F (I - 1) + F (I - 2);
end loop;
end Main;
If I run gnatprove, I get the following result, pointing to the + sign:
medium: overflow check might fail
Does this mean that F (I - 1) could be equal to Integer'Last, and adding anything to that would overflow? If so, then is it not clear from the flow of the program that this is impossible? Or do I need to specify this with a contract? If not, then what does it mean?
A counterexample shows that indeed gnatprove in this case worries about the edges of Integer:
medium: overflow check might fail (e.g. when F = (1 => -1, others => -2147483648) and I = 2)
Consider adding a loop invariant to your code. The following is an example from the book "Building High Integrity Applications with Spark".
procedure Copy_Into(Buffer : out Buffer_Type;
Source : in String) is
Characters_To_Copy : Buffer.Count_Type := Maximum_Buffer_Size;
begin
Buffer := (Others => ' '); -- Initialize to all blanks
if Source'Length < Characters_To_Copy then
Characters_To_Copy := Source'Length;
end if;
for Index in Buffer.Count_Type range 1..Characters_To_Copy loop
pragma Loop_Invariant
(Characters_To_Copy <= Source'Length and
Characters_To_Copy = Characters_To_Copy'Loop_Entry);
Buffer (Index) := Source(Source'First + (Index - 1));
end loop;
end Copy_Into;
This is already an old question, but I would like to add an answer anyway (just for future reference).
With the advancement of provers, the example as stated in the question now proves out-the-box in GNAT CE 2019 (i.e. no loop invariant needed). A somewhat more advanced example can also be proven:
main.adb
procedure Main with SPARK_Mode is
-- NOTE: The theoretical upper bound for N is 46 as
--
-- Fib (46) < 2**31 - 1 < Fib (47)
-- 1_836_311_903 < 2_147_483_647 < 2_971_215_073
-- NOTE: Proved with Z3 only. Z3 is pretty good in arithmetic. Additional
-- options for gnatprove:
--
-- --prover=Z3 --steps=0 --timeout=10 --report=all
type Seq is array (Natural range <>) of Natural;
function Fibonacci (N : Natural) return Seq with
Pre => (N in 2 .. 46),
Post => (Fibonacci'Result (0) = 0)
and then (Fibonacci'Result (1) = 1)
and then (for all I in 2 .. N =>
Fibonacci'Result (I) = Fibonacci'Result (I - 1) + Fibonacci'Result (I - 2));
---------------
-- Fibonacci --
---------------
function Fibonacci (N : Natural) return Seq is
F : Seq (0 .. N) := (0, 1, others => 0);
begin
for I in 2 .. N loop
F (I) := F (I - 1) + F (I - 2);
pragma Loop_Invariant
(for all J in 2 .. I =>
F (J) = F (J - 1) + F (J - 2));
-- NOTE: The loop invariant below helps the prover to proof the
-- absence of overflow. It "reminds" the prover that all values
-- from iteration 3 onwards are strictly monotonically increasing.
-- Hence, if absence of overflow is proven in this iteration,
-- then absence is proven for all previous iterations.
pragma Loop_Invariant
(for all J in 3 .. I =>
F (J) > F (J - 1));
end loop;
return F;
end Fibonacci;
begin
null;
end Main;
This loop invariant should work - since 2^(n-1) + 2^(n-2) < 2^n - but I can't convince the provers:
procedure Fibonacci with SPARK_Mode is
F : array (0 .. 10) of Natural := (0 => 0,
1 => 1,
others => 0);
begin
for I in 2 .. F'Last loop
pragma Loop_Invariant
(for all J in F'Range => F (J) < 2 ** J);
F (I) := F (I - 1) + F (I - 2);
end loop;
end Fibonacci;
You can probably convince the provers with a bit of manual assistance (showing how 2^(n-1) + 2^(n-2) = 2^(n-2) * (2 + 1) = 3/4 * 2^n < 2^n).