comp.lang.ada
 help / color / mirror / Atom feed
* basic questions on using Ada arrays
@ 2010-10-06 15:43 Nasser M. Abbasi
  2010-10-06 16:17 ` Pascal Obry
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Nasser M. Abbasi @ 2010-10-06 15:43 UTC (permalink / raw)


Ada experts:

I am really rusty with Ada. Wanted to find if I apply a function to an 
array in one call without having to loop calling the function for each 
entry in the array?

Suppose I have an array of values, and I want to take the sin() of each 
value in the array?

This below does not work, last statement is wrong

---------------------------------------
with ada.text_io; use ada.text_io;
with Ada.Numerics; use  Ada.Numerics;
with Ada.Numerics.Elementary_Functions;
use  Ada.Numerics.Elementary_Functions;
with Ada.float_Text_IO; use Ada.float_Text_IO;

procedure test2  is
    nPoints : constant :=100;
    del : float := 2.0*Pi/float(nPoints-1);
    x   : array(1..nPoints) of float;
    y   : array(1..nPoints) of float;
begin

    x(1):=0.0;
    for i in 2..nPoints loop
       x(i)  := x(i-1)+del;
    end loop;

    x:=sin(x(1..nPoints));

end test2;
------------------------------------

Also, is there a way to initialize an array using a formula or a 
function call? I know I can do

  x   : array(1..nPoints) of float := (others => 0.0)

But I wanted to make each entry in the array to have some value 
depending on the index value.  I did not know how, so that is what the 
above small loop does, to initialize x array.

It would be nice to have been to do this initialization at declaration time.

The bigger question really, is if one map functions on array in Ada, or 
do operations on array in one call, say like multiply a constant by 
array, without using loops all the time. loops are so out of fashion 
these days :)

Something like this in Fortran

----------------------
program main
    integer :: x(10)=1 ;
    x = 5 * x;
end program
-----------------------

compiles, runs ok, but The Ada code

----------------------
procedure test3  is
    x   : array(1..10) of integer :=(others=>1);
begin
    x:= 5 * x;
end test3;
---------------

$ gnatmake test3.adb
test3.adb:4:12: expected type universal integer
test3.adb:4:12: found type of x declared at line 2

I undertand exactly the error and why. My question is how to code it in 
Ada to the same, without using loops?

thanks,
--Nasser





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-06 15:43 basic questions on using Ada arrays Nasser M. Abbasi
@ 2010-10-06 16:17 ` Pascal Obry
  2010-10-06 16:22 ` Jacob Sparre Andersen
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Pascal Obry @ 2010-10-06 16:17 UTC (permalink / raw)


Le 06/10/2010 17:43, Nasser M. Abbasi a �crit :
> I am really rusty with Ada. Wanted to find if I apply a function to an
> array in one call without having to loop calling the function for each
> entry in the array?

Ada does not support this.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|    http://www.obry.net  -  http://v2p.fr.eu.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver keys.gnupg.net --recv-key F949BD3B




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-06 15:43 basic questions on using Ada arrays Nasser M. Abbasi
  2010-10-06 16:17 ` Pascal Obry
@ 2010-10-06 16:22 ` Jacob Sparre Andersen
  2010-10-07  1:55   ` Keith Thompson
  2010-10-06 17:03 ` Jeffrey Carter
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Jacob Sparre Andersen @ 2010-10-06 16:22 UTC (permalink / raw)


Nasser M. Abbasi wrote:

> I am really rusty with Ada. Wanted to find if I apply a function to an
> array in one call without having to loop calling the function for each
> entry in the array?

Only if the function/operation is declared for the array type.

The operator "and" is automatically declared for arrays of Booleans.

> Suppose I have an array of values, and I want to take the sin() of
> each value in the array?

The function "Sin" is not declared automatically for arrays of Floats.
You will have to declare it yourself:

   function Sin (Item : in The_Array_Type) return The_Array_Type is
   begin
      return Result : The_Array_Type do
         for I in Item'Range loop
            Result (I) := Sin (Item (I));
         end loop;
      end return;
   end Sin;      

> But I wanted to make each entry in the array to have some value
> depending on the index value.

You have to use a loop to do that (you may of course hide the loop in a
function).

> The bigger question really, is if one map functions on array in Ada,
> or do operations on array in one call, say like multiply a constant by
> array, without using loops all the time. loops are so out of fashion
> these days :)

There are generally no predefined mathematical operations on arrays of
scalars in Ada.  You could propose it to the ARG.  They might even
accept it.

> Something like this in Fortran
>
> ----------------------
> program main
>    integer :: x(10)=1 ;
>    x = 5 * x;
> end program
> -----------------------
>
> compiles, runs ok, but The Ada code
>
> ----------------------
> procedure test3  is
>    x   : array(1..10) of integer :=(others=>1);
> begin
>    x:= 5 * x;
> end test3;
> ---------------

... should be:

   procedure Test_3 is
      type Demo_Array is array (1 .. 10) of Integer;

      function "*" (Left : Integer; Right : Demo_Array)
        return Demo_Array is
      begin
         return Result : Demo_Array do
            for I in Right'Range loop
               Result (I) := Left * Right (I);
            end loop;
         end return;
      end "*";

      X : Demo_Array := (others => 1);
   begin
      X := 5 * X;
   end Test_3;

Jacob
-- 
Jacob Sparre Andersen Research & Innovation
Vesterbrogade 148K, 1. th.
1620 K�benhavn V
Danmark



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-06 15:43 basic questions on using Ada arrays Nasser M. Abbasi
  2010-10-06 16:17 ` Pascal Obry
  2010-10-06 16:22 ` Jacob Sparre Andersen
@ 2010-10-06 17:03 ` Jeffrey Carter
  2010-10-06 19:54 ` Simon Wright
  2010-10-08  8:02 ` Alex Mentis
  4 siblings, 0 replies; 11+ messages in thread
From: Jeffrey Carter @ 2010-10-06 17:03 UTC (permalink / raw)


On 10/06/2010 08:43 AM, Nasser M. Abbasi wrote:
>
> Also, is there a way to initialize an array using a formula or a
> function call? I know I can do
>
> x : array(1..nPoints) of float := (others => 0.0)
>
> But I wanted to make each entry in the array to have some value
> depending on the index value. I did not know how, so that is what the
> above small loop does, to initialize x array.

Certainly, but one must use a named array type, not anonymous types as you have 
done.

You can find examples of such functions in Ada.Strings.Fixed (ARM A.4.3). Type 
String is simply an array type. For example

X : String := 5 * 'x';

results is X having the subtype String (1 .. 5) and the value "xxxxx". This 
doesn't give a different value for each component, but it's easy enough to write 
one yourself:

function Digit_List (Length : in Natural) return String;
-- Returns a value of subtype String (1 .. Length) containing repeated
-- sequences of "1234567890". Each position contains the value of its
-- index modulo 10.

function Digit_List (Length : in Natural) return String is
    function Last_Digit (Value : in Positive) return Character;
    -- returns the Character representation of the last digit in the
    -- base 10 image of Value.

    function Last_Digit (Value : in Positive) return Character is
       Image : constant String := Integer'Image (Value);
    begin -- Last_Digit
       return Image (Image'Last);
    end Last_Digit;

    Result : String (1 .. Length);
begin -- Digit_List
    All_Digits : for I in Result'range loop
       Result (I) := Last_Digit (I);
    end loop All_Digits;

    return Result;
end Digit_List;

Column_Header : constant String := Digit_List (80);

Of course, all of this requires you to write loops. Loops may be "out of 
fashion", but Ada isn't about following fashion; if it were, it would look like 
C, not have all those inefficient run-time checks, and give far fewer 
compilation errors.

-- 
Jeff Carter
"Don't knock masturbation. It's sex with someone I love."
Annie Hall
45



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-06 15:43 basic questions on using Ada arrays Nasser M. Abbasi
                   ` (2 preceding siblings ...)
  2010-10-06 17:03 ` Jeffrey Carter
@ 2010-10-06 19:54 ` Simon Wright
  2010-10-08  8:02 ` Alex Mentis
  4 siblings, 0 replies; 11+ messages in thread
From: Simon Wright @ 2010-10-06 19:54 UTC (permalink / raw)


"Nasser M. Abbasi" <nma@12000.org> writes:

> I am really rusty with Ada. Wanted to find if I apply a function to an
> array in one call without having to loop calling the function for each
> entry in the array?

This is probably GNAT-only, and may result in compilation warnings about
use of implementation-specific packages, but in recent GNATs there's a
package System.Generic_Array_Operations containing

   generic
      type X_Scalar is private;
      type Result_Scalar is private;
      type X_Vector is array (Integer range <>) of X_Scalar;
      type Result_Vector is array (Integer range <>) of Result_Scalar;
      with function Operation (X : X_Scalar) return Result_Scalar;
   function Vector_Elementwise_Operation (X : X_Vector) return Result_Vector;

which you'd instantiate something like

   type Vector is array (Positive range <>) of Float;

   function Sin 
   is new System.Generic_Array_Operations.Vector_Elementwise_Operation
     (X_Scalar => Float,
      Result_Scalar => Float,
      X_Vector => Vector,
      Result_Vector => Vector,
      Operation => Ada.Numerics.Elementary_Functions.Sin);

   V : Vector;

begin

   --  Set up V

    V := Sin (V);

(NOT COMPILED!)



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-06 16:22 ` Jacob Sparre Andersen
@ 2010-10-07  1:55   ` Keith Thompson
  2010-10-08  0:04     ` Randy Brukardt
  0 siblings, 1 reply; 11+ messages in thread
From: Keith Thompson @ 2010-10-07  1:55 UTC (permalink / raw)


Jacob Sparre Andersen <sparre@nbi.dk> writes:
> Nasser M. Abbasi wrote:
>
>> I am really rusty with Ada. Wanted to find if I apply a function to an
>> array in one call without having to loop calling the function for each
>> entry in the array?
>
> Only if the function/operation is declared for the array type.
>
> The operator "and" is automatically declared for arrays of Booleans.
>
>> Suppose I have an array of values, and I want to take the sin() of
>> each value in the array?
>
> The function "Sin" is not declared automatically for arrays of Floats.
> You will have to declare it yourself:
>
>    function Sin (Item : in The_Array_Type) return The_Array_Type is
>    begin
>       return Result : The_Array_Type do
>          for I in Item'Range loop
>             Result (I) := Sin (Item (I));
>          end loop;
>       end return;
>    end Sin;      

A more "generic" solution (though it doesn't use generics) is:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics; use Ada.Numerics;
with Ada.Numerics.Elementary_Functions;
use  Ada.Numerics.Elementary_Functions;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;

procedure Test2 is
   type Func_Ptr is access function(F: Float) return Float;
   type Float_Array is array(positive range <>) of Float;

   function Apply(Func: Func_Ptr; Arr: Float_Array) return Float_Array is
      Result: Float_Array(Arr'Range);
   begin
      for I in Result'Range loop
         Result(I) := Func(Arr(I));
      end loop;
      return Result;
   end Apply;

   function Init return Float_Array is
      nPoints : constant := 100;
      del : constant Float := 2.0*Pi/Float(nPoints-1);
      Result: Float_Array(1 .. nPoints);
   begin
      for I in Result'Range loop
         Result(I) := Float(I - 1) * del;
      end loop;
      return result;
   end Init;

   X: constant Float_Array := Init;
   Y: constant Float_Array := Apply(sin'Access, X);
begin
   for I in X'Range loop
      Put(X(I), Exp => 0);
      Put(" => ");
      Put(Y(I), Exp => 0);
      New_Line;
   end loop;
end Test2;

[...]

Note that the initialization function multiplies by "del" for each entry
rather than adding "del"; the latter can cause cumulative errors.

For numeric work, consider using Long_Float rather than Float; it's more
precise (well, at least as precise) and very often no more expensive.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-07  1:55   ` Keith Thompson
@ 2010-10-08  0:04     ` Randy Brukardt
  2010-10-08 14:47       ` Jacob Sparre Andersen
  0 siblings, 1 reply; 11+ messages in thread
From: Randy Brukardt @ 2010-10-08  0:04 UTC (permalink / raw)


"Keith Thompson" <kst-u@mib.org> wrote in message 
news:ln8w2apy0u.fsf@nuthaus.mib.org...
...
> A more "generic" solution (though it doesn't use generics) is:

If you're using an Ada 2005, this solution is better using an anonymous 
access type, as in that case you can pass any matching subprogram, not just 
one from the same level. (If you don't do this, this will be annoyingly hard 
to use.) That is, change as follows:

> with Ada.Text_IO; use Ada.Text_IO;
> with Ada.Numerics; use Ada.Numerics;
> with Ada.Numerics.Elementary_Functions;
> use  Ada.Numerics.Elementary_Functions;
> with Ada.Float_Text_IO; use Ada.Float_Text_IO;
>
> procedure Test2 is
>   type Func_Ptr is access function(F: Float) return Float;

Delete this type.

>   type Float_Array is array(positive range <>) of Float;
>
>   function Apply(Func: Func_Ptr; Arr: Float_Array) return Float_Array is

Change this declaration to:

function Apply(Func: access function(F: Float) return Float; Arr: 
Float_Array) return Float_Array is

>      Result: Float_Array(Arr'Range);
>   begin
>      for I in Result'Range loop
>         Result(I) := Func(Arr(I));
>      end loop;
>      return Result;
>   end Apply;
>
>   function Init return Float_Array is
>      nPoints : constant := 100;
>      del : constant Float := 2.0*Pi/Float(nPoints-1);
>      Result: Float_Array(1 .. nPoints);
>   begin
>      for I in Result'Range loop
>         Result(I) := Float(I - 1) * del;
>      end loop;
>      return result;
>   end Init;
>
>   X: constant Float_Array := Init;
>   Y: constant Float_Array := Apply(sin'Access, X);
> begin
>   for I in X'Range loop
>      Put(X(I), Exp => 0);
>      Put(" => ");
>      Put(Y(I), Exp => 0);
>      New_Line;
>   end loop;
> end Test2;
>
> [...]


                       Randy.





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-06 15:43 basic questions on using Ada arrays Nasser M. Abbasi
                   ` (3 preceding siblings ...)
  2010-10-06 19:54 ` Simon Wright
@ 2010-10-08  8:02 ` Alex Mentis
  4 siblings, 0 replies; 11+ messages in thread
From: Alex Mentis @ 2010-10-08  8:02 UTC (permalink / raw)


On Oct 6, 6:43 pm, "Nasser M. Abbasi" <n...@12000.org> wrote:
> Ada experts:
>
> I am really rusty with Ada. Wanted to find if I apply a function to an
> array in one call without having to loop calling the function for each
> entry in the array?
>
> Suppose I have an array of values, and I want to take the sin() of each
> value in the array?
>
> This below does not work, last statement is wrong
>
> ---------------------------------------
> with ada.text_io; use ada.text_io;
> with Ada.Numerics; use  Ada.Numerics;
> with Ada.Numerics.Elementary_Functions;
> use  Ada.Numerics.Elementary_Functions;
> with Ada.float_Text_IO; use Ada.float_Text_IO;
>
> procedure test2  is
>     nPoints : constant :=100;
>     del : float := 2.0*Pi/float(nPoints-1);
>     x   : array(1..nPoints) of float;
>     y   : array(1..nPoints) of float;
> begin
>
>     x(1):=0.0;
>     for i in 2..nPoints loop
>        x(i)  := x(i-1)+del;
>     end loop;
>
>     x:=sin(x(1..nPoints));
>
> end test2;
> ------------------------------------
>
> Also, is there a way to initialize an array using a formula or a
> function call? I know I can do
>
>   x   : array(1..nPoints) of float := (others => 0.0)
>
> But I wanted to make each entry in the array to have some value
> depending on the index value.  I did not know how, so that is what the
> above small loop does, to initialize x array.
>
> It would be nice to have been to do this initialization at declaration time.
>
> The bigger question really, is if one map functions on array in Ada, or
> do operations on array in one call, say like multiply a constant by
> array, without using loops all the time. loops are so out of fashion
> these days :)
>
> Something like this in Fortran
>
> ----------------------
> program main
>     integer :: x(10)=1 ;
>     x = 5 * x;
> end program
> -----------------------
>
> compiles, runs ok, but The Ada code
>
> ----------------------
> procedure test3  is
>     x   : array(1..10) of integer :=(others=>1);
> begin
>     x:= 5 * x;
> end test3;
> ---------------
>
> $ gnatmake test3.adb
> test3.adb:4:12: expected type universal integer
> test3.adb:4:12: found type of x declared at line 2
>
> I undertand exactly the error and why. My question is how to code it in
> Ada to the same, without using loops?
>
> thanks,
> --Nasser

You can write your own.  I'm in a hurry, so I don't have time to tweak
this the way I'd like...I'd want to try to do this with a generic
array type and with more flexible signatures for the functions/
procedures to be mapped, but my general idea is below.  Putting it in
a package would be more flexible.  You could probably gin up the code
to do a mapped initialization as well...but not sure.  Haven't given
it much thought at the moment.

Alex

--------------------------------------------------------------------------------
-- File: Ada_Map.adb
--
-- Created on Oct 8, 2010
--------------------------------------------------------------------------------
--
-- Description of Ada_Map
--
-- @author alexander.mentis
--
with Ada.Text_IO, Ada.Numerics.Elementary_Functions;
use  Ada.Text_IO, Ada.Numerics.Elementary_Functions;

procedure Ada_Map is

   type Array_Type is array (1 .. 10) of Float;

   function Map (F : not null access function (N : Float) return
Float;
                 A : Array_Type)
                 return Array_Type is

      Result : Array_Type;

   begin -- Map
      for I in A'Range loop
         Result (I) := F (A (I));
      end loop;
      return Result;
   end Map;

   procedure Map (P : not null access procedure (S : String);
                  A : Array_Type) is
   begin -- Map

      for I in A'Range loop
         P (A (I)'Img);
      end loop;

   end Map;

   X : Array_Type := (others => 5.0);

begin -- Ada_Map

   X := Map (Sin'Access, X);
   Map(Put_Line'Access, X);

end Ada_Map;



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-08  0:04     ` Randy Brukardt
@ 2010-10-08 14:47       ` Jacob Sparre Andersen
  2010-10-09  6:35         ` Randy Brukardt
  0 siblings, 1 reply; 11+ messages in thread
From: Jacob Sparre Andersen @ 2010-10-08 14:47 UTC (permalink / raw)


Randy Brukardt wrote;

> If you're using an Ada 2005, [...]

> function Apply(Func: access function(F: Float) return Float; Arr: 
> Float_Array) return Float_Array is
>
>>      Result: Float_Array(Arr'Range);
>>   begin
>>      for I in Result'Range loop
>>         Result(I) := Func(Arr(I));
>>      end loop;
>>      return Result;
>>   end Apply;

Wouldn't this implementation of the function be more elegant?

   function Apply (Func : access function (F : Float) return Float;
                   Arr  : in     Float_Array) return Float_Array is
   begin
      return Result : Float_Array (Arr'Range) do
         Result (I) := Func (Arr (I));
      end return;
   end Apply;

Greetings,

Jacob
-- 
Adlai Stevenson said it all when, at an event during the
1956 Presidential campaign, a woman shouted, "You have the
vote of every thinking person!" Stevenson shouted back,
"That's not enough, madam, we need a majority!"



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-08 14:47       ` Jacob Sparre Andersen
@ 2010-10-09  6:35         ` Randy Brukardt
  2010-10-26  2:20           ` Yannick Duchêne (Hibou57)
  0 siblings, 1 reply; 11+ messages in thread
From: Randy Brukardt @ 2010-10-09  6:35 UTC (permalink / raw)


"Jacob Sparre Andersen" <sparre@nbi.dk> wrote in message 
news:871v80g2s7.fsf@hugsarin.sparre-andersen.dk...
> Randy Brukardt wrote;
>
>> If you're using an Ada 2005, [...]
>
...
> Wouldn't this implementation of the function be more elegant?
>
>   function Apply (Func : access function (F : Float) return Float;
>                   Arr  : in     Float_Array) return Float_Array is
>   begin
>      return Result : Float_Array (Arr'Range) do
>         Result (I) := Func (Arr (I));
>      end return;
>   end Apply;

It's too elegant: you forgot the for loop! (Thus, there is no declaration 
for I). It should be:

   function Apply (Func : access function (F : Float) return Float;
                   Arr  : in     Float_Array) return Float_Array is
   begin
      return Result : Float_Array (Arr'Range) do
         for I in Arr'Range loop
            Result (I) := Func (Arr (I));
         end loop;
      end return;
   end Apply;

Using the extended return does simplify the code and possibly improves the 
performance as well (by eliminating a copy of the array).

                            Randy.






^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: basic questions on using Ada arrays
  2010-10-09  6:35         ` Randy Brukardt
@ 2010-10-26  2:20           ` Yannick Duchêne (Hibou57)
  0 siblings, 0 replies; 11+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2010-10-26  2:20 UTC (permalink / raw)


Le Sat, 09 Oct 2010 08:35:37 +0200, Randy Brukardt <randy@rrsoftware.com>  
a écrit:
> Using the extended return does simplify the code and possibly improves  
> the
> performance as well (by eliminating a copy of the array).

Already discussed last year. This may be an optimization hint for some  
compilers, as other compilers may apply the same optimization even in the  
lack of this extended return statement (it is related to avoiding copy,  
but this semantic formally apply to limited type only). This is compiler  
specific, unless Ada 2012 changed this to make it the standard semantic.


-- 
Si les chats miaulent et font autant de vocalises bizarres, c’est pas pour  
les chiens.



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2010-10-26  2:20 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-06 15:43 basic questions on using Ada arrays Nasser M. Abbasi
2010-10-06 16:17 ` Pascal Obry
2010-10-06 16:22 ` Jacob Sparre Andersen
2010-10-07  1:55   ` Keith Thompson
2010-10-08  0:04     ` Randy Brukardt
2010-10-08 14:47       ` Jacob Sparre Andersen
2010-10-09  6:35         ` Randy Brukardt
2010-10-26  2:20           ` Yannick Duchêne (Hibou57)
2010-10-06 17:03 ` Jeffrey Carter
2010-10-06 19:54 ` Simon Wright
2010-10-08  8:02 ` Alex Mentis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox