Setting a range for Random float generation in Ada - random

Adam.Numerics.Float_Random generates Float values for 0 - 1.0 but i want to generate a Float value between a user defined range. Like Min := 100.0 and Max := 200.0. Something like this:
with Ada.Text_IO, Ada.Integer_Text_IO, Ada.Float_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO, Ada.Float_Text_IO;
with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
procedure test1 is
Min, Max, Answer : Float;
subtype Custom is Float range Min .. Max;
package New_Package is new Ada.Numerics.Float_Random(Custom);
use New_Package;
RF : Generator;
begin
Reset(RF);
Get(Min);
Get(Max);
Answer := Random(RF);
Put(Answer, Fore => 1, Aft => 2, Exp => 0);
end test1;

Looks like homework... I usually don't give the answer for such a task :)
First of all, you should get a warning when compiling your code as Min and Max are uninitialized when building your subtype.
To avoid this, the subtype must be declared after values are known.
To do this, declare your subtype inside a declare block.
About the random generation, getting a value inside your range is only a matter of translating and scaling.
In the end, I would do something like this.
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
procedure test1 is
Min, Max : Float;
RF : Generator;
begin
Reset(RF);
Get(Min);
Get(Max);
declare
subtype Custom is Float range Min .. Max;
Answer : Custom;
begin
Answer := (Random(RF) * (Max - Min)) + Min;
Put(Answer, Fore => 1, Aft => 2, Exp => 0);
end;
end test1;
In this particular case, the subtype is quite useless here.

Related

Dynamic array in Turbo Pascal

I am working on my school project and I would like to use Dynamic (not static) array. I worked with ObjectPascal, so I am used to some syntax. But now I am programming in the old TurboPascal (I am using Turbo Pascal 7 for Windows).
It doesn't seem to know the ObjectPascal, so I thought, that you Turbo Pascal doesn't know dynamic arrays.
Could anyone tell me, if my theory is right or not? I tried to google, but I was not succesfull.
Basicly I am asking "how is it with dynamic arrays in Turbo Pascal 7" ?
Thank you for all reactions.
As MartynA says, there is no dynamic array type in Turbo Pascal. You need to manually allocate memory using pointers, and be careful if you use rangechecks.
Typically you define an array type
TYPE
TArrayT = array[0.. ((65535-spillbytes) div sizeof(T))-1] of T;
where spillbytes is a constant for a small deduction because you can't use the whole 64k, see what the compiler accepts. (Probably this deduction is for heapmanager structures inside the 64k block)
Then you define a pointer
PArrayT= ^TArrayT;
and a variable to it
var
P : PArrayT;
and you allocate nrelement elements using getmem;
getmem(P,SizeOf(T) * nrelements);
and optionally fill them with zero to initialize them:
fillchar(p^,SizeOf(T) * nrelements,#0);
You can access elements using
p^[index]
to free them, use freemem using the exact opposite of the getmem line.
freemem(P,Sizeof(T)*nrelements);
Which means you have to save the allocated number of elements somewhere. This was fixed/solved in Delphi and FPC.
Also keep in mind that you can't find bugs with rangechecking anymore.
If you want arrays larger than 64k, that is possible, but only with constraints, and it matters more which exact TP target (dos, dos-protected or Windows you use) I advise you to search for the online SWAG archive that has many examples. And of course I would recommend to go to FreePascal/Lazarus too where you can simply do:
var x : array of t;
begin
setlength(x,1000000);
and be done with it without additional lines and forget about all of this nonsense.
I'm using Turbo Pascal 5.5 and to create a dynamic array, perhaps the trick is to declare an array with zero dimension as follows:
dArray = array [0..0] of integer;
And then declare a pointer to that array:
pArray = ^dArray ;
And finally, create a pointer variable:
ArrayPtr : pArray;
You can now reference the pointer variable ArrayPtr as follows:
ArrayPtr^[i]; { The index 'i' is of type integer}
See the complete example below:
{
Title: dynarr.pas
A simple Pascal program demonstrating dynamic array.
Compiled and tested with Turbo Pascal 5.5.
}
program dynamic_array;
{Main Program starts here}
type
dArray = array [0..0] of integer;
pArray = ^dArray ;
var
i : integer;
ArrayPtr : pArray;
begin
for i := 0 to 9 do { In this case, array index starts at 0 instead of 1. }
ArrayPtr^[i] := i + 1;
writeln('The Dynamic Array now contains the following:');
writeln;
for i := 0 to 9 do
writeln(ArrayPtr^[i]);
end.
In this example, we have declared the array as:
array[0..0] of integer;
Therefore, the index starts at 0 and if we have n elements, the last element is at index n-1 which is similar to array indexing in C/C++.
Regular Pascal arrays start at 1 but for this case, it starts at 0.
unit Vector;
interface
const MaxVector = 8000;
// 64 k div SizeOf(float); number of float-values that fit in 64 K of stack
VectorError: boolean = False;
// toggle if error occurs. Calling routine can handle or abort
type
VectorStruc = record
Length: word;
Data: array [1..MaxVector] of float;
end;
VectorTyp = ^VectorStruc;
procedure CreateVector(var Vec: VectorTyp; Length: word; Value: float);
{ Generates a vector of length Length and sets all elements to Value }
procedure DestroyVector(var Vec: VectorTyp);
{ release memory occupied by vector }
procedure SetVectorElement(var Vec: VectorTyp; n: word; c: float);
function GetVectorElement(const Vec: VectorTyp; n: word): float;
implementation
var ch: char;
function WriteErrorMessage(Text: string): char;
begin
Write(Text);
Read(WriteErrorMessage);
VectorError := True; // toggle the error marker
end;
procedure CreateVector(var Vec: VectorTyp; Length: word; Value: float);
var
i: word;
begin
try
GetMem(Vec, Length * SizeOf(float) + SizeOf(word) + 6);
except
ch := WriteErrorMessage(' Not enough memory to create vector');
exit;
end;
Vec^.Length := Length;
for i := 1 to Length do
Vec^.Data[i] := Value;
end;
procedure DestroyVector(var Vec: VectorTyp);
var
x: word;
begin
x := Vec^.Length * SizeOf(float) + SizeOf(word) + 6;
FreeMem(Vec, x);
end;
function VectorLength(const Vec: VectorTyp): word;
begin
VectorLength := Vec^.Length;
end;
function GetVectorElement(const Vec: VectorTyp; n: word): float;
var
s1, s2: string;
begin
if (n <= VectorLength(Vec)) then
GetVectorElement := Vec^.Data[n]
else
begin
Str(n: 4, s1);
Str(VectorLength(Vec): 4, s2);
ch := WriteErrorMessage(' Attempt to read non-existent vector element No ' +
s1 + ' of ' + s2);
end;
end;
procedure SetVectorElement(var Vec: VectorTyp; n: word; C: float);
begin
if (n <= VectorLength(Vec)) then
Vec^.Data[n] := C
else
ch := WriteErrorMessage(' Attempt to write to non-existent vector element');
end;
end.
As long as your data fit on the stack, i.e., are smaller than 64 kB, the task is relatively simple. The only thing I don't know is where the 6 bit of extra size go, they are required, however.

How to use a variable in an array?

I'm using PASCAL for a course i'm doing and i'm having trouble with an assignment, in my program i'm using 2 arrays that uses a variable from a user's input but when i go to run the program it comes up with, Error: Can't evaluate constant expression. The code for the array is:
Var
x : integer;
s : array[1..x] of real;
n : array[1..x] of string[30];
Here x is the user's input, is there a way for an array to go from 1 to x?
If x is a variable, that won't work indeed. The range of a so called static array must be a constant expression, i.e. it must be known at compile time.
So what you want won't work, as is.
In FreePascal, you can use dynamic arrays, though. Their lengths can be set and changed at runtime.
var
x: Integer;
s: array of Real;
n: array of string[30]; // why not just string?
and later:
x := someUserInput(); // pseudo code!
SetLength(s, x);
SetLength(n, x);
You should be aware of the fact that dynamic arrays are 0-based, so your indexes run from 0 up to x - 1. But for the limits of the array, you should rather use Low() and High() instead:
for q := Low(s) to High(s) do
// access s[q];
(Low() and High() are not the topic, but just know they can also be used for static arrays, and that they return the actual array bounds -- I always use High and Low for this)
Here is not so simple as using managed types like dynamic arrays suggested by #RudyVelthuis but more funny solution providing some comprehension
about how it works internally :)
program dynarr;
{$mode objfpc}{$H+}
type
TArrayReal = array[1..High(Integer)] of Real;
TArrayString30 = array[1..High(Integer)] of string[30];
PArrayReal = ^TArrayReal;
PArrayString30 = ^TArrayString30;
var
i: Integer;
x: Integer;
s: PArrayReal;
n: PArrayString30;
begin
Write('Count: '); Readln(x);
// Allocate memory for the actual count of the elements
s := GetMem(SizeOf(Real) * x);
n := GetMem(SizeOf(string[30]) * x);
try
for i := 1 to x do
begin
Write('Row ', i:3, ': '); Readln(s^[i], n^[i]);
end;
Writeln('Your input was:');
for i := 1 to x do
Writeln('Row ', i:3, ': ', s^[i]:10:3, n^[i]: 20);
finally
// Do not forget to release allocated memory
FreeMem(s);
FreeMem(n);
end;
end.

Change array type: 8bit type to 6bit type

I have two types and two arrays of that types in file.ads
type Ebit is mod 2**8;
type Sbit is mod 2**6;
type Data_Type is array (Positive range <>) of Ebit;
type Changed_Data_Type is array (Positive range <>) of Sbit;
and function:
function ChangeDataType (D : in Data_Type) return Changed_Data_Type
with
Pre => D'Length rem 3 = 0 and D'Last < Positive'Last / 4,
Post => ChangeDataType'Result'Length = 4 * (D'Length / 3)
Ok i can understand all of this.
For example we have arrays of:
65, 66, 65, 65, 66, 65 in 8bit values function should give to us 16, 20, 9, 1, 16, 20, 9, 1 in 6bit values.
I dont know how i can build a 6bit table from 8 bit table.
My idea of sollutions is for example taking bit by bit from type:
fill all bites in 6bit type to 0 (propably default)
if first bit (2**1) is 1 set bit (2**1) in 6bit type to 1;
and do some iterations
But i dont know how to do this, always is a problem with types. Is this good idea or i can do this with easier way? I spend last nigt to try write this but without success.
Edit:
I wrote some code, its working but i have problem with array initialization.
function ChangeDataType (D: in Data_Type) return Changed_Data_Type
is
length: Natural := (4*(D'Length / 3));
ER: Changed_Data_type(length);
Temp: Ebit;
Temp1: Ebit;
Temp2: Ebit;
Actual: Ebit;
n: Natural;
k: Natural;
begin
n := 0;
k := 0;
Temp := 2#00000000#;
Temp1 := 2#00000000#;
Temp2 := 2#00000000#;
Array_loop:
for k in D'Range loop
case n is
when 0 =>
Actual := D(k);
Temp1 := Actual / 2**2;
ER(k) := Sbit(Temp1);
Temp := Actual * ( 2**4);
n := 2;
when 2 =>
Actual := D(k);
Temp1 := Actual / 2**4;
Temp2 := Temp1 or Temp;
ER(k) := Sbit(Temp2);
Temp := Actual * ( 2**2);
n := 4;
when 4 =>
Actual := D(k);
Temp1 := Actual / 2**6;
Temp2 := Temp1 or Temp;
ER(k) := Sbit(Temp2);
n := 6;
when 6 =>
Temp1 := Actual * ( 2**2);
Temp2 := Actual / 2**2;
ER(k) := Sbit(Temp2);
n := 0;
when others =>
n := 0;
end case;
end loop Array_Loop;
return ER;
end;
IF I understand what you're asking... it's that you want to re-pack the same 8-bit data into 6-bit values such that the "leftover" bits of the first EBit become the first bits (highest or lowest?) of the second Sbit.
One way you can do this - at least for fixed size arrays, e.g. your 6 words * 8 bits, 8 words * 6 bits example, is by specifying the exact layout in memory for each array type, using packing, and representation aspects (or pragmas, before Ada-2012) which are nicely described here.
I haven't tested the following, but it may serve as a starting point.
type Ebit is mod 2**8;
type Sbit is mod 2**6;
for Ebit'Size use 8;
for Sbit'Size use 6;
type Data_Type is array (1 .. 6) of Ebit
with Alignment => 0; -- this should pack tightly
type Changed_Data_Type is array (1 .. 8) of Sbit
with Alignment => 0;
Then you can instantiate the generic Unchecked_Conversion function with the two array types, and use that function to convert from one array to the other.
with Ada.Unchecked_Conversion;
function Change_Type is new Ada.Unchecked_Conversion(Data_Type, Changed_Data_Type);
declare
Packed_Bytes : Changed_Data_Type := Change_Type(Original_Bytes);
begin ...
In terms of code generated, it's not slow, because Unchecked_Conversion doesn't do anything, except tell the compile-time type checking to look the other way.
I view Unchecked_Conversion like the "I meant to do that" look my cat gives me after falling off the windowledge. Again...
Alternatively, if you wish to avoid copying, you can declare Original_Bytes as aliased, and use a similar trick with access types and Unchecked_Access to overlay both arrays on the same memory (like a Union in C). I think this is what DarkestKhan calls "array overlays" in a comment below. See also section 3 of this rather dated page which describes the technique further. It notes the overlaid variable must not only be declared aliased but also volatile so that accesses to one view aren't optimised into registers, but reflect any changes made via the other view. Another approach to overlays is in the Ada Wikibook here.
Now this may be vulnerable to endian-ness considerations, i.e. it may work on some platforms but not others. The second reference above gives an example of a record with exact bit-alignment of its members : we can at least take the Bit_Order aspect, as in with Alignment => 0, Bit_Order => Low_Order_First; for the arrays above...
-- code stolen from "Rationale" ... see link above p.11
type RR is record
Code: Opcode;
R1: Register;
R2: Register;
end record
with Alignment => 2, Bit_Order => High_Order_First;
for RR use record
Code at 0 range 0 .. 7;
R1 at 1 range 0 .. 3;
R2 at 1 range 4 .. 7;
end record;
One thing that's not clear to me is if there's a formulaic way to specify the exact layout of each element in an array, as is done in a record here - or even if there's a potential need to. If necessary, one workaround would be to replace the arrays above with records. But I'd love to see a better answer if there is one.

Transpose matrix ada

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;

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;

Resources