scientific notation and non scientific notation values in one line - ada

This works:
Ada.Text_IO.Put_Line("Oil Rate : " & Float'Image(oil_float);
Ada.Text_IO.Put_Line(oil_float, Exp => 0);
But this doesn't:
Ada.Text_IO.Put_Line("Oil Rate : " & Float'Image(oil_float, Exp => 0) & " is " & (oil_float, Exp => 0));
I wanted to put it in one line. is it possible?

You could write your own function:
function Float_Image (Value : Float; Exponent : Natural) return String is
Result : String (1 .. 64);
begin
Ada.Float_Text_IO.Put (Result, Value, Exp => Exponent);
return Ada.Strings.Fixed.Trim (Result, Ada.Strings.Left);
end Float_Image;
(note the unfortunate fixed-length intermediate result; more than enough to hold Float’Last, though)

Related

Invalid operands to binary expressions

I was solving N queens problem and I wrote isvalid function, but the function gives "invalid operands to binary expressions" error. The error occurs at board[X][Y] == 'Q':
bool isvalid(vector<vector<string>>& board , int &row , int &col , int &n){
int x = row ;
int y = col ;
while(y >= 0){
if(board[x][y] == 'Q'){// THE ERROR IS OCCURING HERE AT BOARD[X][Y]== 'Q'
return false;
}
y-- ;
}
int x = row ;
int y = col ;
while(x >=0 and y>=0){
if(board[x][y] == 'Q')return false;
x-- ;
y-- ;
}
int x = row ;
int y = col ;
while(x < n and y>=0){
if(board[x][y] == 'Q')return false;
x++ ;
y-- ;
}
return true
}
The problem is that there's no corresponding operator== that could be called for the comparison. board[x][y] is a std::string, whereas 'Q' is a char. As you can see on cppreference, second parameter of operator== for comparison with std::string (which is std::basic_string<char>) can either be another std::string (taken by const reference) or const char* (C-style string). Neither of these is char or could be obtained through implicit conversion from char. In particular, see that there's no constructor of std::string taking a single character.
So, the easiest solution is to compare with a string literal "Q" instead. This is an array object of type const char[2] (second character is a null terminator '\0'), which decays into const char* pointer through array-to-pointer conversion, so appropriate overload of operator can be used:
board[x][y] == "Q"
Also, note that you missed a ; after the return statement.

Why it is oveflow in contador in ada?

I dont know why the prove is error at the overflow in the variable contador. I need help.
contador: Integer;
J: Integer;
function noPrimos (lista : My_Array) return Boolean
with
Global => contador,
--Depends => ...,
Pre => True and contador < Integer'Last,
Post => (noPrimos'Result = True or noPrimos'Result = False);
FILE ADB
function noPrimos (lista : My_Array) return Boolean is
contador: Integer;
begin
for I in lista'Range loop
contador:= 0;
if lista(I) /= 1 then
for J in 1.. lista(I) loop
if lista(I) rem J = 0 then
contador := contador + 1;
end if;
end loop;
if contador <= 2 then
return false;
end if;
else
return true;
end if;
pragma Loop_Variant(Increases => I);
end loop;
return true;
end noPrimos;
The problem is the overflow the result:
Phase 1 of 2: generation of Global contracts ...
Phase 2 of 2: flow analysis and proof ...
15:40: medium: overflow check might fail (e.g. when contador = 2147483647)
47:40: medium: overflow check might fail (e.g. when contador = 0)
First of all, I assume that the function noPrimos will return True only if the list lista does not contain any primes. That being said, I'm a little bit puzzled by some aspects of the code snippet:
The type definition of My_Array is missing.
The role of the global instance of contador (english: counter) is not clear from the given code snippet. By writing Global=> contador, you state that the global variable contador will be read by the function noPrimos (see also here), but that doesn't happen because the local instance of contador shadows the global instance of contador.
The reason for the variable J being defined globally is not clear, you can omit it.
The precondition True (on the left side of the Boolean operator and) is trivial and can be omitted.
The postcondition states that the result of noPrimos can either be True or False. This is trivial as noPrimos returns a boolean and can therefore be omitted. The postcondition should state the function's expected result given its inputs.
The loop variant pragma Loop_Variant(Increases => I); is trivial as the variable I will increase by the definition of the for-loop. Hence the loop variant can be omitted.
Below is an example of a function No_Primes that searches the given list L for primes and returns True if none are found. It proves in GNAT CE 2019:
primes.ads (spec)
package Primes with SPARK_Mode is
type List is
array (Natural range <>) of Positive;
--
-- Returns True if N is a prime number (or False otherwise).
--
function Is_Prime (N : Positive) return Boolean
with
Global => null,
Post => Is_Prime'Result =
(if N = 1 then False
else (for all I in 2 .. N - 1 => N rem I /= 0));
--
-- Returns True if list L does not contain any prime numbers (or False otherwise).
--
function No_Primes (L : List) return Boolean
with
Global => null,
Post => No_Primes'Result =
(for all I in L'Range => Is_Prime (L (I)) = False);
end Primes;
primes.adb (body)
package body Primes with SPARK_Mode is
--------------
-- Is_Prime --
--------------
function Is_Prime (N : Positive) return Boolean is
begin
if N = 1 then
return False;
else
for I in 2 .. N - 1 loop
if N rem I = 0 then
return False;
end if;
pragma Loop_Invariant
(for all J in 2 .. I => N rem J /= 0);
end loop;
end if;
return True;
end Is_Prime;
---------------
-- No_Primes --
---------------
function No_Primes (L : List) return Boolean is
begin
for I in L'Range loop
if Is_Prime (L (I)) then
return False;
end if;
pragma Loop_Invariant
(for all J in L'First .. I => Is_Prime (L (J)) = False);
end loop;
return True;
end No_Primes;
end Primes;
A small test program (main.adb)
with Ada.Text_IO; use Ada.Text_IO;
with Primes; use Primes;
procedure Main is
-- Some test vectors.
L1 : List := (1 => 1); -- Expect TRUE : 1 is not a prime.
L2 : List := (1, 2, 3, 5, 7); -- Expect FALSE : All are prime except 1.
L3 : List := (2, 3, 5, 7); -- Expect FALSE : All are prime.
L4 : List := (1, 4, 6, 8, 9); -- Expect TRUE : None are prime.
L5 : List := (4, 6, 8, 9); -- Expect TRUE : None are prime.
L6 : List := (3, 4, 5); -- Expect FALSE : 3 and 5 are prime.
begin
Put_Line ("No_Primes (L1) = " & Boolean'Image (No_Primes (L1)));
Put_Line ("No_Primes (L2) = " & Boolean'Image (No_Primes (L2)));
Put_Line ("No_Primes (L3) = " & Boolean'Image (No_Primes (L3)));
Put_Line ("No_Primes (L4) = " & Boolean'Image (No_Primes (L4)));
Put_Line ("No_Primes (L5) = " & Boolean'Image (No_Primes (L5)));
Put_Line ("No_Primes (L6) = " & Boolean'Image (No_Primes (L6)));
end Main;
yields
No_Primes (L1) = TRUE
No_Primes (L2) = FALSE
No_Primes (L3) = FALSE
No_Primes (L4) = TRUE
No_Primes (L5) = TRUE
No_Primes (L6) = FALSE

Heterogeneous tuple in Ada

Is it possible in ada to create a heterogeneous tuple on the stack without the new operator and access types? I need to make N 2-d arrays depending on a known number in compile time. To be more precise, a certain number of tensors depends on the number of layers in the neural network. I made it like this:
subtype Layer_Value_Type is Float range 0.0 .. 1.0;
package My_Activate is new Activate (Value_Type => Layer_Value_Type);
package My_Logsig is new My_Activate.Logsig;
package My_Layer is new Layer (Value_T => Layer_Value_Type);
package My_Net is new Net (Value_Type => My_Layer.Value_Type,
Layer_Package => My_Layer);
use My_Layer;
Layer1 : My_Layer.Layer (5, null);
Layer2 : My_Layer.Layer (10, My_Logsig.Func'Access);
Layer3 : My_Layer.Layer (3, My_Logsig.Func'Access);
Layers_Array : My_Net.Layers_Array := (Layer1, Layer2, Layer3);
Net : My_Net.Net (Layers_Array'Length);
begin
declare
begin
Net.Make (Layers_Array);
Net.FeedForward(Input => (0.3, 0.4, 0.5, 0.6, 0.7));
end;
generic
type Value_T is digits <>;
package Layer with SPARK_Mode is
subtype Value_Type is Value_T;
type Activate_Type is access function (Item : in Float) return Value_Type;
type Layer (Num : Natural := 0; F : Activate_Type := null) is private;
procedure Make (This : out Layer; Num : in Natural; F : in Activate_Type := null);
private
type Layer (Num : Natural := 0; F : Activate_Type := null) is
record
Length : Natural := Num;
Func : Activate_Type := F;
FuncDeriv : Activate_Type;
end record;
end Layer;
generic
type Value_Type is digits <>;
with package Layer_Package is new Layer(Value_T => Value_Type);
package Net is
type Layers_Array is array (Positive range <>) of Layer_Package.Layer;
type Net (Layers_Num : Positive) is tagged limited private;
subtype Input_Array is Ada.Numerics.Real_Arrays.Real_Vector;
procedure Make (This :in out Net; Layers : in Layers_Array);
function Is_Input_Valid (This : in out Net; Vector : in Input_Array) return Boolean;
procedure FeedForward (This : in out Net; Input : in Input_Array)
with Pre => This.Is_Input_Valid (Vector => Input);
private
--types declaration of values
subtype Value_Arr is Ada.Numerics.Real_Arrays.Real_Vector;
type Values_Arr_Ref is access all Value_Arr;
--types declaration of biases
subtype Bias_Arr is Value_Arr;
type Bias_Arr_Ref is access all Bias_Arr;
--types declaration of waights
subtype Layer_Waights is Ada.Numerics.Real_Arrays.Real_Matrix;
type Layer_Waights_Ref is access all Layer_Waights;
--types declaration of tensors
type Values_Tensor is array (Positive range <>) of Values_Arr_Ref;
type Waights_Tensor is array (Positive range <>) of Layer_Waights_Ref;
--types declaration of activate function array
type Activate_Arr is array (Positive range <>) of Layer_Package.Activate_Type;
type Net (Layers_Num : Positive) is tagged limited
record
Values : Values_Tensor (1 .. Layers_Num);
Waights : Waights_Tensor (2 .. Layers_Num);
Activates : Activate_Arr (2 .. Layers_Num);
end record;
end Net;
procedure Make (This : in out Net; Layers : in Layers_Array) is
type Waight_Tensor_Arr is array (Positive range <>, Positive range <>) of Value_Type;
--task for random number generator
task type Tensor_Randomizer is
entry Init (Item : in out Layer_Waights);
end Tensor_Randomizer;
task body Tensor_Randomizer is
My_Generator : Ada.Numerics.Float_Random.Generator;
function Get return Value_Type with
Post => (Get'Result >= Value_Type'First + 0.2) and
(Get'Result <= Value_Type'Last - 0.2)
is
use Ada.Numerics.Float_Random;
Ratio_For_Large : constant := 0.7;
type Sign_Type is new Boolean with Default_Value => False;
type Constraint_Type is new Boolean with Default_Value => False;
begin
return Result : Value_Type do
declare
Tmp : Value_Type := 0.0;
Is_Negative : Sign_Type;
Large : constant := 0.8;
Small : constant := 0.2;
Is_Over_Constraints : Constraint_Type;
begin
Tmp := Value_Type (Random (Gen => My_Generator));
Is_Negative := (if Tmp >= 0.0 then False else True);
Is_Over_Constraints := (if abs (Tmp) >= Large or abs (Tmp) <= Small then
True else False);
case Is_Over_Constraints is
when False =>
Result := Tmp;
when True =>
Result := (case Is_Negative is
when False => (if abs (Tmp) >= Large then
Tmp * Ratio_For_Large else 0.5 - Tmp),
when True => 0.0 - (abs (Tmp) * (if abs (Tmp) >= Large then
Ratio_For_Large else -0.5 + Tmp)));
end case;
end;
end return;
end Get;
begin
Ada.Numerics.Float_Random.Reset (Gen => My_Generator);
accept Init (Item : in out Layer_Waights) do
begin
Item := (others => (others => Float(Get)));
end;
end Init;
end Tensor_Randomizer;
type Task_Array_Base_Type is array (This.Waights'Range) of Tensor_Randomizer;
subtype Task_Array_Type is Task_Array_Base_Type with
Dynamic_Predicate => Task_Array_Type'Length <= 8;
Task_Array : Task_Array_Type;
--this procedure initializing values tensor to value
procedure Init_Values_Tensor with
Post => (for all I of This.Values (1).all => I = 0.0)
is
Idx : Positive := This.Values'First;
begin
for I of Layers loop
declare
Local_Values_Arr : aliased Value_Arr (1 .. I.Num) := (others => 0.0);
begin
This.Values (Idx) := new Value_Arr (1 .. I.Num);
This.Values (Idx).all := Local_Values_Arr;
Idx := Idx + 1;
end;
end loop;
end Init_Values_Tensor;
--this procedure initializing waights tensor to random value
procedure Init_Waight_Tensor is
Idx : Positive := This.Values'First;
begin
for I in This.Waights'Range loop
This.Waights(I) := new Layer_Waights (1 .. Layers (Idx + 1).Num, 1 .. Layers (Idx).Num);
Task_Array (I).Init (Item => This.Waights (I).all);
Idx := Idx + 1;
end loop;
end Init_Waight_Tensor;
--this procedure initializing activate functions array
procedure Init_Activates is
begin
for I in This.Activates'Range loop
This.Activates (I) := Layers (I).F;
end loop;
end Init_Activates;
begin
Init_Values_Tensor;
Init_Waight_Tensor;
Init_Activates;
end Make;
In C++ I made it like this:
#include<cstddef>
#include<utility>
#include<array>
#include<tuple>
template<typename T>
struct Sigmoid{
void Function(){
}
};
template<typename T, std::size_t num, template<typename> class policy>
struct Layer{
using value_type = T;
using value_arr_type = std::array<T, num>;
static constexpr std::size_t _valuesNum{num};
};
template<typename Tuple, std::size_t... I>
constexpr auto tensor_impl(Tuple t, std::index_sequence<I...>){
using namespace std;
constexpr std::array res{std::get<I>(t)._valuesNum...};
std::tuple<array<array<float, get<I>(t)._valuesNum>, get<I+1>(t)._valuesNum>...> tup{};
return tup;
}
template<typename... Args, typename Indices = std::make_index_sequence<sizeof...(Args)-1>>
constexpr auto tensor_helper(){
constexpr std::tuple<Args...> args;
constexpr std::tuple arr{tensor_impl(args, Indices{})};
return arr;
}
template<typename T, typename... Args> requires(
(std::is_same_v<typename T::value_type, typename Args::value_type>) && ...)
class Net{
std::tuple<typename T::value_arr_type, typename Args::value_arr_type...> values{};
// std::tuple<std::array<std::array<typename T::value_type, 4>, sizeof...(Args)>> waights{};
public:
decltype(tensor_helper<T, Args...>()) _waights{tensor_helper<T, Args...>()};
decltype(auto) tensors(){return _waights;}
};
int main(){
using layer1 = Layer<float, 2, Sigmoid>;
using layer2 = Layer<float, 3, Sigmoid>;
using layer3 = Layer<float, 2, Sigmoid>;
Net<layer1, layer2, layer3> net{};
}
Yes, look at generic packages, you can then instantiate that and create new tuple types from there.
The primary trick for avoiding to use new is to avoid using access types.
Remove all your declarations of access types, and use the actual types instead.
If you just don't want to use new yourself, you can use the various indefinite containers from the standard library.
If you have to avoid using the heap/storage pools completely, you can declare a variant record:
type R (S : T := D) is
record
F1 : T1;
case S is
when V2 =>
F2 : T2;
when V3 =>
F3 : T3;
end case;
end record;
You can make regular arrays of type R using only the stack.

Ada - Long (Grade-School) Multiplication of BigNum Integers

I am trying to implement the Grade-School Multiplication algorithm in Ada, and am currently getting an index out of bounds error. I'd appreciate any input on how to fix the error, and successfully implement the Algorithm. Thanks in advance!
I have a package BigNumPkg which defines type BigNum is array(0..Size - 1) of Integer;
The function I am trying to implement currently looks like this:
FUNCTION "*" (X, Y : BigNum) RETURN BigNum IS
Product : BigNum:= Zero;
Carry : Natural := 0;
Base : Constant Integer := 10;
BEGIN
FOR I IN REVERSE 0..Size-1 LOOP
Carry := 0;
FOR N IN REVERSE 0..Size-1 LOOP
Product(N + I - 1) := Product(N + I - 1) + Carry + X(N) * Y(I);
Carry := Product(N + I -1) / Base;
Product(N + I -1) := Product(N +I-1) mod Base;
END LOOP;
Product(I+Size-1) := Product(I+Size-1) + Carry;
END LOOP;
RETURN Product;
END "*";
Package specification:
package Big_Integer is
Base : constant := 10;
Size : constant := 3;
type Extended_Digit is range 0 .. Base * Base;
subtype Digit is Extended_Digit range 0 .. Base - 1;
type Instance is array (0 .. Size - 1) of Digit;
function "*" (Left, Right : in Instance) return Instance;
function Image (Item : in Instance) return String;
end Big_Integer;
You can of course adjust the parameters as needed, but these are nice for manual inspection of the results. Note that I haven't assured myself that the range of Extended_Digit is correct, but it seems to work in this case.
Package implementation:
with Ada.Strings.Unbounded;
package body Big_Integer is
function "*" (Left, Right : in Instance) return Instance is
Carry : Extended_Digit := 0;
Sum : Extended_Digit;
begin
return Product : Instance := (others => 0) do
for I in Left'Range loop
for J in Right'Range loop
if I + J in Product'Range then
Sum := Left (I) * Right (J) + Carry + Product (I + J);
Product (I + J) := Sum mod Base;
Carry := Sum / Base;
else
Sum := Left (I) * Right (J) + Carry;
if Sum = 0 then
Carry := 0;
else
raise Constraint_Error with "Big integer overflow.";
end if;
end if;
end loop;
if Carry /= 0 then
raise Constraint_Error with "Big integer overflow.";
end if;
end loop;
end return;
end "*";
function Image (Item : in Instance) return String is
Buffer : Ada.Strings.Unbounded.Unbounded_String;
begin
for E of reverse Item loop
Ada.Strings.Unbounded.Append (Buffer, Digit'Image (E));
end loop;
return Ada.Strings.Unbounded.To_String (Buffer);
end Image;
end Big_Integer;
Test driver:
with Ada.Text_IO;
with Big_Integer;
procedure Use_Big_Integers is
use all type Big_Integer.Instance;
procedure Multiply (A, B : in Big_Integer.Instance);
procedure Multiply (A, B : in Big_Integer.Instance) is
use Ada.Text_IO;
begin
Put (Image (A));
Put (" * ");
Put (Image (B));
Put (" = ");
Put (Image (A * B));
New_Line;
exception
when Constraint_Error =>
Put_Line ("Constraint_Error");
end Multiply;
begin
Multiply (A => (0 => 1, others => 0),
B => (others => Big_Integer.Digit'Last));
Multiply (A => (0 => Big_Integer.Digit'Last, others => 0),
B => (0 => Big_Integer.Digit'Last, others => 0));
Multiply (A => (0 => 2, others => 0),
B => (others => Big_Integer.Digit'Last));
Multiply (A => (2 => 0, 1 => 1, 0 => 2),
B => (2 => 0, 1 => 4, 0 => 5));
Multiply (A => (2 => 0, 1 => 2, 0 => 2),
B => (2 => 0, 1 => 4, 0 => 5));
Multiply (A => (2 => 0, 1 => 2, 0 => 3),
B => (2 => 0, 1 => 4, 0 => 5));
end Use_Big_Integers;
It is good style to provide a complete reproducer, but never mind...
When I is going to be used as an index into Y, it is good style to write the loop statement as for I in reverse Y'Range ... end loop;. Similarly for N.
Are you certain that N + I - 1 always is a valid index for Product? I'm pretty sure that you can get both too large and too small indices with your current implementation. I suspect that the too small indices is an off-by-one error in the implementation of the algorithm. The too large indices are because you haven't thought clearly about how to handle integer overflow (the traditional way in Ada is to raise Constraint_Error).
Shouldn't yo check the value of Carry at the end of the function?

How to get the first value in a recursive function?

I'm trying to do a school quiz again. I'm trying to match if my result is equal to number "x". I wrote a recursive function, I always get the value 0, not the one I used to call the function (such as 153). What should I change ?
public static boolean isArmstrong(int x, Armstrong s) {
while (a != true) {
while (x != 0) {
int number = x / 10;
int remain = x % 10;
s.push(remain);
return isArmstrong(number, s);
}
a = true;
}
if (getResult() == x) {
System.out.println("True , result is : " + getResult());
} else {
System.out.println("False , x is : " + x + " result is : " + getResult());
//x always prints out 0 which ends the while loop.But i need to get the x value when i call the function
}
return true;
}
}
You've supplied incomplete information, no definition for the method getResult() nor for the type Armstrong s, but there are still some issues we can address. First, your boolean method isArmstrong() never returns false, only true, so we can't expect it to detect non Armstrong numbers. Second, you're doing too much in your recursive method, both the test for an Armstrong number and the announcing of the result -- these might best be handled by separate methods.
Below's a rework that changes isArmstrong() from a boolean method to one that returns its calculation as an integer. An input value of zero breaks the recursion causing a result to be returned. We use a separate function to compare the argument to isArmstrong() against the returned value to announce success or failure:
public class Armstrong
{
public static int isArmstrong(int x, int power) {
if (x != 0) {
int quotient = x / 10;
int remainder = x % 10;
return (int)Math.pow(remainder, power) + isArmstrong(quotient, power);
}
return 0;
}
public static void main(String args[]) {
int number = 0, power = 0;
if (args.length > 0) {
try {
power = args[0].length();
number = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.err.println("Argument " + args[0] + " must be an integer.");
System.exit(1);
}
}
int result = isArmstrong(number, power);
if (result == number) {
System.out.println("True, result is: " + result);
} else {
System.out.println("False, number is: " + number + " but result is: " + result);
}
}
}
OUTPUT
> java Armstrong 153
True, result is: 153
> java Armstrong 123
False, number is: 123 but result is: 36
> java Armstrong 1634
True, result is: 1634
> java Armstrong 1635
False, number is: 1635 but result is: 2003
>

Resources