Why is array'First always 1 in this example? - ada

I have a array of Nodes:
type NodeArray is array (Positive range 1 .. 5) of XNode;
The node has some data and an integer ID but thats not important right now.
The way I undestand it is that array'First (excuse the abuse of notation) always points or references the first item in a range or array, not the integer of the range type.
My question is why I always get 1 instead of the first entry in my array.
If you need to see more code I can provide it, I just thought I'd keep my example simple and short.

Your
type NodeArray is array (Positive range 1 .. 5) of XNode;
defines a constrained array type (ALRM 3.6(5)), whose first index will always be 1.
If you want to use one type to create array objects with different index ranges, you need an unconstrained array type (ALRM 3.6(3)) with bounds like Positive range <> (note 1, once you’ve created such an object, its bounds are fixed; note 2, instead of Positive you can use any scalar appropriate to the problem).
with Ada.Text_IO; use Ada.Text_IO;
procedure Zython is
type Unconstrained_Node_Array is array (Positive range <>) of Float;
subtype Constrained_Node_Array is Unconstrained_Node_Array (1 .. 5);
U : Unconstrained_Node_Array (42 .. 44); -- must include the index range
C : Constrained_Node_Array; -- the index range is 1 .. 5
begin
for J in U'Range loop
U (J) := Float (J) * 2.0;
end loop;
Put_Line ("U'First: "
& Positive'Image (U'First)
& ", U (U'First): "
& Float'Image (U (U'First)));
for J in C'Range loop
C (J) := Float (J) * 2.0;
end loop;
Put_Line ("C'First: "
& Positive'Image (C'First)
& ", C (C'First): "
& Float'Image (C (C'First)));
end Zython;

Related

How to use recursion to add the product of two Integers together?

In this code, I am asking the user to input two integers (Index, Mindex) and then I display all the integers between 1..Index and 1..Mindex. What my problem is here that I do not know how to multiply the values of Integers in Index and Integers in `Mindex and then add up the product of these two together
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Add is
Index, Mindex : Integer;
procedure calc (Item : in Integer) is
New_Value : Integer;
begin
Put ("The value of the index is now");
Put (Item);
New_Line;
New_Value := (Item - 1);
if New_Value > 0 then
calc (New_Value);
end if;
end calc;
begin
Get (Index);
Get (Mindex);
calc (Index);
New_Line;
calc (Mindex);
end Add;
A factorial keeps chaining multiplication with each decreasing value: 5! = 5 * 4 * 3 * 2 * 1 = 120. In order to do the recursion, you'll need to have two cases inside your recursive function: If your value is above 1, then multiply that value with the next smallest number. That's the recursive part where you will call Factorial(N-1) inside of Factorial(N). Otherwise just return 1 (factorial of 0 is 1 mathematically, so both 1! and 0! equal 1).
The way this works in Ada is:
function Factorial(Value : Natural) return Natural is
begin
if Value > 1 then
-- Keep chaining the multiplication with recursion
return Value * Factorial(Value - 1);
else
-- No need to chain as the result is always 1
return 1;
end if;
end Factorial;
You can then call that Factorial function on each of your numbers and add the results.

How to use Assert and loop_invariants

Specification:
package PolyPack with SPARK_Mode is
type Vector is array (Natural range <>) of Integer;
function RuleHorner (X: Integer; A : Vector) return Integer
with
Pre => A'Length > 0 and A'Last < Integer'Last;
end PolyPack ;
I want to write body of PolyPack package with Assert and loop_invariants that the gnatprove program can prove my function RuleHorner correctness.
I write my function Horner but I don;t know how put assertions and loop_invariants in this program to prove its corectness :
with Ada.Integer_Text_IO;
package body PolyPack with SPARK_Mode is
function RuleHorner (X: Integer; A : Vector) return Integer is
Y : Integer := 0;
begin
for I in 0 .. A'Length - 1 loop
Y := (Y*X) + A(A'Last - I);
end loop;
return Y;
end RuleHorner ;
end PolyPack ;
gnatprove :
overflow check might fail (e.g. when X = 2 and Y = -2)
overflow check might fail
overflow check are for line Y := (Y*X) + A(A'Last - I);
Can someone help me how remove overflow check with loop_invariants
The analysis is correct. The element type for type Vector is Integer. When X = 2, Y = -2, and A(A'Last - I) is less than Integer'First + 4 an underflow will occur. How do you think this should be handled in your program? Loop invariants will not work here because you cannot prove that an overflow or underflow cannot occur.
Is there a way you can design your types and/or subtypes used within Vector and for variables X and Y to prevent Y from overflowing or underflowing?
I am also curious why you want to ignore the last value in your Vector. Are you trying to walk through the array in reverse? If so simply use the following for loop syntax:
for I in reverse A'Range loop

How do you get the square root in Ada?

So I have been given an assignment to read in a file put the numbers into two matrices, multiply the matrices, and finally put the output into a .txt file.
I have never used Ada before and I figured it would be a good challenge. I am stuck in trying to determine the bounds for the two separate arrays.
This is what I currently have:
currentSpread := I;
g := Ada.Numerics.Generic_Complex_Elementary_Functions.Sqrt(I);
while J < g loop
if(I mod J = 0) THEN
if(currentSpread > ((I/J - J)/2)) THEN
currentSpread := ((I/J - J)/2);
arrayBounds := J;
end if;
end if;
J := J + 1;
end loop;
The problem I am having is with the sqrt function. I want to find the factors for the best bounds of the matrix multiplication and this was the only way that I thought to implement it.
The error I am getting is:
invalid prefix in selected component "Ada.Numerics.Generic_Complex_Elementary_Functions"
Thanks a lot for any help.
--Update
Full Code as requested:
with Ada.Text_IO;use Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Numerics.Generic_Complex_Elementary_Functions;
with Ada.Numerics.Generic_Elementary_Functions;
with Ada.Numerics.Complex_Elementary_Functions;
with Ada.Numerics.Generic_Complex_Types;
procedure Main is
dataFile : File_Type;
resultFile : File_Type;
value : Integer;
I : Integer := 0;
J : Integer;
currentSpread : Integer;
arrayBounds : Integer;
g : Integer;
begin
Ada.Text_IO.Open(File => dataFile, Mode => Ada.Text_IO.In_File, Name =>"C:\Users\Jeffrey\Desktop\data.txt");
while not End_Of_File(dataFile) loop
Ada.Integer_Text_IO.Get(File => dataFile, Item => value);
Ada.Integer_Text_IO.Put(Item => value);
Ada.Text_IO.New_Line;
I := I + 1;
end loop;
Ada.Integer_Text_IO.Put(I);
I := I/2;
J := 1;
currentSpread := I;
g := Ada.Numerics.Generic_Complex_Elementary_Functions.Sqrt(I);
while J < g loop
if(I mod J = 0) THEN
if(currentSpread > ((I/J - J)/2)) THEN
currentSpread := ((I/J - J)/2);
arrayBounds := J;
end if;
end if;
J := J + 1;
end loop;
declare
type newArray is array(Integer range <>, Integer range<>) of Integer;
X : Integer := J;
Y : Integer := I/J;
Arr1 : newArray(1..Y, 1..X);
Arr2 : newArray(1..X, 1..Y);
finAnswer : newArray(1..X, 1..X);
begin
for z in 1 .. X loop
for k in 1 .. Y loop
Ada.Integer_Text_IO.Get(File => dataFile, Item => value);
Arr1(z, k) := value;
end loop;
end loop;
for z in 1 .. Y loop
for k in 1 .. X loop
Ada.Integer_Text_IO.Get(File => dataFile, Item => value);
Arr2(z, k) := value;
end loop;
end loop;
for l in 1 .. X loop
for m in 1 .. Y loop
for n in 1 .. X loop
finAnswer(l, n) := finAnswer(l, n) + Arr1(l, n)* Arr2(n, m);
end loop;
end loop;
end loop;
end;
Ada.Text_IO.Close(File => dataFile);
end Main;
I am using the square root exclusively to figure out the factors of a number nothing else. How I have it set up now is it will go up to the square root and then it will take the smallest spread of the factors. I do not care about rounding errors or anything else if it isn't a perfect square it can round either way.
Thanks.
Generic_Complex_Elementary_Functions is a generic package. It cannot be used directly. That is why the compiler gives you an error on this line:
Ada.Numerics.Generic_Complex_Elementary_Functions.Sqrt(I);
To use it, you have to instantiate the generic Generic_Complex_Types with the floating-point type you want to use, and then instantiate Generic_Complex_Elementary_Functions with an instance of Generic_Complex_Types. Fortunately, you don't have to go through all that if you're willing to use the built-in type Float; the language provides Ada.Numerics.Complex_Elementary_Functions for you, that uses Float as the floating-point type, or Ada.Numerics.Long_Complex_Elementary_Functions that uses Long_Float if your compiler vendors support it.
However, I don't think you want to use Complex anything. That deals with complex numbers, and I doubt that you want to use those. Use Ada.Numerics.Elementary_Functions (or Long_Elementary_Functions), which deal with real numbers.
Finally, even this isn't going to work:
Ada.Numerics.Elementary_Functions.Sqrt(I)
if I is an integer, because the argument type needs to be a Float. You'll have to use a type conversion.
Ada.Numerics.Elementary_Functions.Sqrt(Float(I))

About "range" in Ada

The following source code line in Ada,
type Airplane_ID is range 1..10;
, can be written as
type Airplane_ID is range 1..x;
, where x is a variable? I ask this because I want to know if the value of x can be modified, for example through text input. Thanks in advance.
No, the bounds of the range both have to be static expressions.
But you can declare a subtype with dynamic bounds:
X: Integer := some_value;
subtype Dynamic_Subtype is Integer range 1 .. X;
Can type Airplane_ID is range 1..x; be written where x is a
variable? I ask this because I want to know if the value of x can be
modified, for example through text input.
I assume that you mean such that altering the value of x alters the range itself in a dynamic-sort of style; if so then strictly speaking, no... but that's not quite the whole answer.
You can do something like this:
Procedure Test( X: In Positive; Sum: Out Natural ) is
subtype Test_type is Natural Range 1..X;
Result : Natural:= Natural'First;
begin
For Index in Test_type'range loop
Result:= Result + Index;
end loop;
Sum:= Result;
end Test;
No. An Ada range declaration must be constant.
As the other answers have mentioned, you can declare ranges in the way you want, so long as they are declared in some kind of block - a 'declare' block, or a procedure or function; for instance:
with Ada.Text_IO,Ada.Integer_Text_IO;
use Ada.Text_IO,Ada.Integer_Text_IO;
procedure P is
l : Positive;
begin
Put( "l =" );
Get( l );
declare
type R is new Integer range 1 .. l;
i : R;
begin
i := R'First;
-- and so on
end;
end P;

Ada Generic Averaging Function

I have a function which averages a certain numeric value from an array of records. This value is either a natural or an enumerated type delta. I have it summing up the values correctly but my question is this: how do I get the length of an array into a generic type, so that it can divide both integers and delta type numbers?
On your array-of-records use the 'Length attribute; this has the advantage of always working even if your bounds are somewhat odd, like -18..3, or an enumeration, like cheeses..fruits.
Something like:
Function Average( Input : In Array_of_Records ) Return float is
-- You say you already have a summation function, so...
Sum : Natural:= Summation( Input );
Begin
Return Sum / Input'Length;
End Average;
You may need to convert the numeric types, by saying Float(Sum) or the like, as Ada does no automatic type "promotions."
This has some flaws in it, but is this closer to what you wanted ?
NWS.
with Ada.Text_Io;
procedure Main is
generic
type Element_T is private;
Zero : Element_T;
One : Element_T;
type Vec_T is array (Integer range <>) of Element_T;
with function "+"(Left, Right : in Element_T) return Element_T is <>;
with function "/"(Left, Right : in Element_T) return Element_T is <>;
package Arrayops is
function Sum (Vec : in Vec_T) return Element_T;
function Count (Vec : in Vec_T) return Element_T;
function Average (Vec : in Vec_T) return Element_T;
end Arrayops;
package body Arrayops is
function Sum (Vec : in Vec_T) return Element_T is
S : Element_T := Zero;
begin
for I in Vec'First .. Vec'Last loop
S := S + Vec(I);
end loop;
return S;
end Sum;
function Count (Vec : in Vec_T) return Element_T is
C : Element_T := Zero;
begin
for I in Vec'First .. Vec'Last loop
C := C + One;
end loop;
return C;
end Count;
function Average (Vec : in Vec_T) return Element_T is
S : constant Element_T := Sum (Vec);
Len : constant Element_T := Count (Vec);
begin
return S / Len;
end Average;
end Arrayops;
type Fl_Arr_T is array (Integer range <>) of Float;
package Fl_Arr is new Arrayops (Element_T => Float,
Zero => 0.0,
One => 1.0,
Vec_T => Fl_Arr_T);
type Int_Arr_T is array (Integer range <>) of Integer;
package Int_Arr is new Arrayops (Element_T => Integer,
Zero => 0,
One => 1,
Vec_T => Int_Arr_T);
My_Ints : constant Int_Arr_T (1 .. 5) := (6,7,5,1,2);
My_Floats : constant Fl_Arr_T (1 .. 7) := (6.1,7.2,5.3,1.4,2.5,8.7,9.7);
Int_Sum : constant Integer := Int_Arr.Sum (My_Ints);
Int_Count : constant Integer := Int_Arr.Count (My_Ints);
Int_Avg : constant Integer := Int_Arr.Average (My_Ints);
Float_Sum : constant Float := Fl_Arr.Sum (My_Floats);
Float_Count : constant Float := Fl_Arr.Count (My_Floats);
Float_Avg : constant Float := Fl_Arr.Average (My_Floats);
begin
Ada.Text_Io.Put_Line ("Integers => Sum: " & Integer'Image (Int_Sum) & ", Count: " & Integer'Image (Int_Count) & ", Avg: " & Integer'Image (Int_Avg));
Ada.Text_Io.Put_Line ("Floats => Sum: " & Float'Image (Float_Sum) & ", Count: " & Float'Image (Float_Count) & ", Avg: " & Float'Image (Float_Avg));
end Main;
Result :
Integers => Sum: 21, Count: 5, Avg: 4
Floats => Sum: 4.09000E+01, Count: 7.00000E+00, Avg: 5.84286E+00
Expanding on Shark8 a bit here...
Ada allows you to declare array types as unconstrained. Something like
type Array_of_Records is array (Natural range <>) of My_Record;
Gives you a type that can be used for arrays of records with starting and ending array indices that could be anywhere in the range of Natural.
One of the nifty things I can do with such a type is use it as a subroutine parameter, like so:
function Sum (Vector : in Array_of_Records) return Natural;
OK, so inside that routine, how do I know where the array bounds are? By using attributes, like so:
for index in Vector'first..Vector'last loop
or
for index in Vector'range loop
Of course for this to work, you must pass in a perfectly-sized array to your Sum routine. Supppose that isn't what you have. Suppose you instead have a huge array (kind of a buffer) and not all of the values are valid? Well, you keep track of what are the valid values, and pass in only those by using a slice.
Rec_Buffer : Array_of_Records (1..10_000);
Last_Valid_Rec : Natural := 0;
....
--// Rec_Buffer gets loaded with 2,128 values or something. We pass it into Sum
--// like so:
Ada.Text_IO ("Sum of vector is " &
natural'image(Sum (Rec_Buffer (1..Last_Valid_Rec));
(warning - uncompiled code)

Resources