comp.lang.ada
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: Array of records with default values not propagating to array
  2018-02-03 11:06  4% Array of records with default values not propagating to array Bojan Bozovic
  2018-02-03 14:16  0% ` Jere
  2018-02-04  4:59  0% ` Bojan Bozovic
@ 2018-02-04 10:19  0% ` Jeffrey R. Carter
  2 siblings, 0 replies; 106+ results
From: Jeffrey R. Carter @ 2018-02-04 10:19 UTC (permalink / raw)


On 02/03/2018 12:06 PM, Bojan Bozovic wrote:
> When I defined a record, and set a default value for some of its components, these don't propagate when I make array of these records. Here is code that can be compiled, but I wonder do I need to explicitly assign value for 'others' in 'Initialize' procedure. This has nothing to do with Ada random number generation, I might have as well used Ada.Numerics.Float_Random, or the reusable code that was posted in another thread, with the same result, so I will post in this separate thread. When I omit "others =>" in Initialize, I get compilation errors at these lines both on FSF compiler and AdaCore GPL compiler on Windows. Is this intended behavior or I am missing something?

I'm not sure what you're experiencing. Your code, as given, compiles and works 
fine for me.

-- 
Jeff Carter
"I like it when the support group complains that they have
insufficient data on mean time to repair bugs in Ada software."
Robert I. Eachus
91


^ permalink raw reply	[relevance 0%]

* Re: Array of records with default values not propagating to array
  2018-02-03 11:06  4% Array of records with default values not propagating to array Bojan Bozovic
  2018-02-03 14:16  0% ` Jere
@ 2018-02-04  4:59  0% ` Bojan Bozovic
  2018-02-04 10:19  0% ` Jeffrey R. Carter
  2 siblings, 0 replies; 106+ results
From: Bojan Bozovic @ 2018-02-04  4:59 UTC (permalink / raw)


On Saturday, February 3, 2018 at 12:06:52 PM UTC+1, Bojan Bozovic wrote:
> When I defined a record, and set a default value for some of its components, these don't propagate when I make array of these records. Here is code that can be compiled, but I wonder do I need to explicitly assign value for 'others' in 'Initialize' procedure. This has nothing to do with Ada random number generation, I might have as well used Ada.Numerics.Float_Random, or the reusable code that was posted in another thread, with the same result, so I will post in this separate thread. When I omit "others =>" in Initialize, I get compilation errors at these lines both on FSF compiler and AdaCore GPL compiler on Windows. Is this intended behavior or I am missing something?
> 
> with Ada.Numerics.Discrete_Random;
> with Ada.Text_IO;
> with Ada.Text_IO.Unbounded_IO;
> with Ada.Strings;
> with Ada.Strings.Unbounded;
> 
> procedure Tarot1 is
> 
> Maximum_Deck_Length: constant integer := 78;
> subtype Card_Position is Positive range 1..Maximum_Deck_Length;
> type Card_Suits is (Cups,Pentacles,Swords,Wands);
> type Trump_Values is new Natural range 0..21;
> type Card_Values is (Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Page,Knight,Queen,King,Ace);
> type Card_Info (Trump: Boolean := False) is record
> -- we will skip giving name and divinatory meaning to cards - its just ordinary assignment but for each card separately;
> -- PROBLEM: Assignment here does nothing, so I have to assign these values in Initialize procedure below as well
> 
> Name : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
> Divinatory_Meaning: Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
> 
> case Trump is 
> 	when True => Trump_Value:Trump_Values;
> 	when False =>  Card_Value:Card_Values;
> 					Suit_Value:Card_Suits;
> end case;
> end record;
> type Deck is array (Card_Position) of Card_Info;
> package Card_Position_Random is new Ada.Numerics.Discrete_Random (Result_Subtype => Card_Position);
> 
> procedure Initialize ( TDeck : in out Deck) is
> 	Index: Card_Position := 1;
> 	begin
> 		-- first lay 22 trump cards in a deck
> 			for Index_1 in Trump_Values loop
> 			TDeck (Index) := (Trump => True, Trump_Value => Index_1, others => Ada.Strings.Unbounded.Null_Unbounded_String);
> 			Index := Index + 1;
> 			end loop;
> 		-- now lay 4 suits of 14 cards each;
> 		for Suit_Index in Card_Suits loop
> 			for Card_Index in Card_Values loop
> 			TDeck (Index) := (Trump => False, Card_Value => Card_Index, Suit_Value => Suit_Index, others => Ada.Strings.Unbounded.Null_Unbounded_String);
> 			exit when Index=Maximum_Deck_Length; -- preventing CONSTRAINT_ERROR;
> 			Index:=Index+1;
> 			end loop;
> 			end loop;
> end Initialize;
> 
>    procedure Shuffle (TDeck : in out Deck) is
>       Position_Gen   : Card_Position_Random.Generator;
>       Temporary_Data : Card_Info;
>       Index_Random   : Card_Position;
>    begin
>       Card_Position_Random.Reset (Gen => Position_Gen);
>       for Index in Card_Position loop
>          Index_Random         := Card_Position_Random.Random (Gen => Position_Gen);
>          Temporary_Data       := TDeck (Index);
>          TDeck (Index)        := TDeck (Index_Random);
>          TDeck (Index_Random) := Temporary_Data;
>       end loop;
>    end Shuffle;
>    Tarot_Deck : Deck;
>    begin
>    Initialize(Tarot_Deck);
>    Shuffle(Tarot_Deck);
>    for Index in Card_Position loop -- just print the deck as shuffled
>    if Tarot_Deck(Index).Trump then
> 	Ada.Text_IO.Put_Line("Major Arcana/Trump: "&Trump_Values'Image(Tarot_Deck(Index).Trump_Value));
> else
> 	Ada.Text_IO.Put_Line("Minor Arcana: "&Card_Values'Image(Tarot_Deck(Index).Card_Value)&" of "&Card_Suits'Image(Tarot_Deck(Index).Suit_Value));
> 	end if;
> 	end loop;
>    end Tarot1;
> 
> Thanks for help.

The compiler does compile assignment of others => <> to uninitialized record components as Mr. Simon Wright noticed above, I have reproduced the bug both with GNAT 2017 GPL and FSF GNAT on Cygwin (6.4.0), problem is I don't have GNAT Pro subscription for access to AdaCore GNAT tracker, and I can't open an account on GCC Bugzilla either, as my mail to administration is rejected and direct account creation is disabled. We can only hope that powers that be take notice of this. Thanks for the suggestions by the way.


^ permalink raw reply	[relevance 0%]

* Re: Array of records with default values not propagating to array
  2018-02-03 11:06  4% Array of records with default values not propagating to array Bojan Bozovic
@ 2018-02-03 14:16  0% ` Jere
  2018-02-04  4:59  0% ` Bojan Bozovic
  2018-02-04 10:19  0% ` Jeffrey R. Carter
  2 siblings, 0 replies; 106+ results
From: Jere @ 2018-02-03 14:16 UTC (permalink / raw)


On Saturday, February 3, 2018 at 6:06:52 AM UTC-5, Bojan Bozovic wrote:
> When I defined a record, and set a default value for some of its components, these don't propagate when I make array of these records. Here is code that can be compiled, but I wonder do I need to explicitly assign value for 'others' in 'Initialize' procedure. This has nothing to do with Ada random number generation, I might have as well used Ada.Numerics.Float_Random, or the reusable code that was posted in another thread, with the same result, so I will post in this separate thread. When I omit "others =>" in Initialize, I get compilation errors at these lines both on FSF compiler and AdaCore GPL compiler on Windows. Is this intended behavior or I am missing something?
> 
> with Ada.Numerics.Discrete_Random;
> with Ada.Text_IO;
> with Ada.Text_IO.Unbounded_IO;
> with Ada.Strings;
> with Ada.Strings.Unbounded;
> 
> procedure Tarot1 is
> 
> Maximum_Deck_Length: constant integer := 78;
> subtype Card_Position is Positive range 1..Maximum_Deck_Length;
> type Card_Suits is (Cups,Pentacles,Swords,Wands);
> type Trump_Values is new Natural range 0..21;
> type Card_Values is (Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Page,Knight,Queen,King,Ace);
> type Card_Info (Trump: Boolean := False) is record
> -- we will skip giving name and divinatory meaning to cards - its just ordinary assignment but for each card separately;
> -- PROBLEM: Assignment here does nothing, so I have to assign these values in Initialize procedure below as well
> 
> Name : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
> Divinatory_Meaning: Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
> 
> case Trump is 
> 	when True => Trump_Value:Trump_Values;
> 	when False =>  Card_Value:Card_Values;
> 					Suit_Value:Card_Suits;
> end case;
> end record;
> type Deck is array (Card_Position) of Card_Info;
> package Card_Position_Random is new Ada.Numerics.Discrete_Random (Result_Subtype => Card_Position);
> 
> procedure Initialize ( TDeck : in out Deck) is
> 	Index: Card_Position := 1;
> 	begin
> 		-- first lay 22 trump cards in a deck
> 			for Index_1 in Trump_Values loop
> 			TDeck (Index) := (Trump => True, Trump_Value => Index_1, others => Ada.Strings.Unbounded.Null_Unbounded_String);
> 			Index := Index + 1;
> 			end loop;
> 		-- now lay 4 suits of 14 cards each;
> 		for Suit_Index in Card_Suits loop
> 			for Card_Index in Card_Values loop
> 			TDeck (Index) := (Trump => False, Card_Value => Card_Index, Suit_Value => Suit_Index, others => Ada.Strings.Unbounded.Null_Unbounded_String);
> 			exit when Index=Maximum_Deck_Length; -- preventing CONSTRAINT_ERROR;
> 			Index:=Index+1;
> 			end loop;
> 			end loop;
> end Initialize;
> 
>    procedure Shuffle (TDeck : in out Deck) is
>       Position_Gen   : Card_Position_Random.Generator;
>       Temporary_Data : Card_Info;
>       Index_Random   : Card_Position;
>    begin
>       Card_Position_Random.Reset (Gen => Position_Gen);
>       for Index in Card_Position loop
>          Index_Random         := Card_Position_Random.Random (Gen => Position_Gen);
>          Temporary_Data       := TDeck (Index);
>          TDeck (Index)        := TDeck (Index_Random);
>          TDeck (Index_Random) := Temporary_Data;
>       end loop;
>    end Shuffle;
>    Tarot_Deck : Deck;
>    begin
>    Initialize(Tarot_Deck);
>    Shuffle(Tarot_Deck);
>    for Index in Card_Position loop -- just print the deck as shuffled
>    if Tarot_Deck(Index).Trump then
> 	Ada.Text_IO.Put_Line("Major Arcana/Trump: "&Trump_Values'Image(Tarot_Deck(Index).Trump_Value));
> else
> 	Ada.Text_IO.Put_Line("Minor Arcana: "&Card_Values'Image(Tarot_Deck(Index).Card_Value)&" of "&Card_Suits'Image(Tarot_Deck(Index).Suit_Value));
> 	end if;
> 	end loop;
>    end Tarot1;
> 
> Thanks for help.

The big issue I see is not incrementing Index in the first loop.  As it
stands, you simply keep reassigning trumps to the same card over and over
again.  Since the type is uninitialized and the next for loop cannot fill
the deck, you get a constraint error later on in the print statement when
trying to print a minor arcana.  As a note, defaulting the variant portion
of the record definition did prevent the constraint error, though obviously
the results were wrong because Initialize did not initialize the whole deck.

Try:

with Ada.Numerics.Discrete_Random;
with Ada.Text_IO;
with Ada.Text_IO.Unbounded_IO;
with Ada.Strings;
with Ada.Strings.Unbounded; 

procedure Tarot1 is
   
   Maximum_Deck_Length: constant integer := 78;
   subtype Card_Position is Positive range 1..Maximum_Deck_Length;
   type Card_Suits is (Cups,Pentacles,Swords,Wands);
   type Trump_Values is new Natural range 0..21;
   type Card_Values is (Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Page,Knight,Queen,King,Ace);
   type Card_Info (Trump: Boolean := False) is record
      -- we will skip giving name and divinatory meaning to cards - its just ordinary assignment but for each card separately;
      -- PROBLEM: Assignment here does nothing, so I have to assign these values in Initialize procedure below as well

      Name : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
      Divinatory_Meaning: Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;

      case Trump is
         when True =>
            Trump_Value:Trump_Values;
         when False =>
            Card_Value:Card_Values;
            Suit_Value:Card_Suits;
      end case;
   end record;
   type Deck is array (Card_Position) of Card_Info;
   package Card_Position_Random is new Ada.Numerics.Discrete_Random (Result_Subtype => Card_Position);

   procedure Initialize ( TDeck : in out Deck) is
      Index: Card_Position := 1;
   begin
      -- first lay 22 trump cards in a deck
      for Index_1 in Trump_Values loop
         TDeck (Index) := (Trump => True, Trump_Value => Index_1, others => <>);
         Index := Index + 1;  -- Jere:  I added this
      end loop;
      
      -- now lay 4 suits of 14 cards each;
      for Suit_Index in Card_Suits loop
         for Card_Index in Card_Values loop
            TDeck (Index) := (Trump => False, Card_Value => Card_Index, Suit_Value => Suit_Index, others => <>);
            exit when Index=Maximum_Deck_Length; -- preventing CONSTRAINT_ERROR;
            Index:=Index+1;
         end loop;
      end loop;
   end Initialize;

   procedure Shuffle (TDeck : in out Deck) is
      Position_Gen   : Card_Position_Random.Generator;
      Temporary_Data : Card_Info;
      Index_Random   : Card_Position;
   begin
      Card_Position_Random.Reset (Gen => Position_Gen);
      for Index in Card_Position loop
         Index_Random         := Card_Position_Random.Random (Gen => Position_Gen);
         Temporary_Data       := TDeck (Index);
         TDeck (Index)        := TDeck (Index_Random);
         TDeck (Index_Random) := Temporary_Data;
      end loop;
   end Shuffle;
   Tarot_Deck : Deck; 
   
begin
   
   Initialize(Tarot_Deck);
   Shuffle(Tarot_Deck);
   for Index in Card_Position loop -- just print the deck as shuffled
      Ada.Text_IO.put("Index = " & Card_Position'Image(Index) & " => ");
      if Tarot_Deck(Index).Trump then
         Ada.Text_IO.Put_Line("Major Arcana/Trump: "&Trump_Values'Image(Tarot_Deck(Index).Trump_Value));
      else
         Ada.Text_IO.Put_Line("Minor Arcana: "&Card_Values'Image(Tarot_Deck(Index).Card_Value)&" of "&Card_Suits'Image(Tarot_Deck(Index).Suit_Value));
      end if;
   end loop;
   
end Tarot1;

^ permalink raw reply	[relevance 0%]

* Array of records with default values not propagating to array
@ 2018-02-03 11:06  4% Bojan Bozovic
  2018-02-03 14:16  0% ` Jere
                   ` (2 more replies)
  0 siblings, 3 replies; 106+ results
From: Bojan Bozovic @ 2018-02-03 11:06 UTC (permalink / raw)


When I defined a record, and set a default value for some of its components, these don't propagate when I make array of these records. Here is code that can be compiled, but I wonder do I need to explicitly assign value for 'others' in 'Initialize' procedure. This has nothing to do with Ada random number generation, I might have as well used Ada.Numerics.Float_Random, or the reusable code that was posted in another thread, with the same result, so I will post in this separate thread. When I omit "others =>" in Initialize, I get compilation errors at these lines both on FSF compiler and AdaCore GPL compiler on Windows. Is this intended behavior or I am missing something?

with Ada.Numerics.Discrete_Random;
with Ada.Text_IO;
with Ada.Text_IO.Unbounded_IO;
with Ada.Strings;
with Ada.Strings.Unbounded;

procedure Tarot1 is

Maximum_Deck_Length: constant integer := 78;
subtype Card_Position is Positive range 1..Maximum_Deck_Length;
type Card_Suits is (Cups,Pentacles,Swords,Wands);
type Trump_Values is new Natural range 0..21;
type Card_Values is (Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Page,Knight,Queen,King,Ace);
type Card_Info (Trump: Boolean := False) is record
-- we will skip giving name and divinatory meaning to cards - its just ordinary assignment but for each card separately;
-- PROBLEM: Assignment here does nothing, so I have to assign these values in Initialize procedure below as well

Name : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
Divinatory_Meaning: Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;

case Trump is 
	when True => Trump_Value:Trump_Values;
	when False =>  Card_Value:Card_Values;
					Suit_Value:Card_Suits;
end case;
end record;
type Deck is array (Card_Position) of Card_Info;
package Card_Position_Random is new Ada.Numerics.Discrete_Random (Result_Subtype => Card_Position);

procedure Initialize ( TDeck : in out Deck) is
	Index: Card_Position := 1;
	begin
		-- first lay 22 trump cards in a deck
			for Index_1 in Trump_Values loop
			TDeck (Index) := (Trump => True, Trump_Value => Index_1, others => Ada.Strings.Unbounded.Null_Unbounded_String);
			Index := Index + 1;
			end loop;
		-- now lay 4 suits of 14 cards each;
		for Suit_Index in Card_Suits loop
			for Card_Index in Card_Values loop
			TDeck (Index) := (Trump => False, Card_Value => Card_Index, Suit_Value => Suit_Index, others => Ada.Strings.Unbounded.Null_Unbounded_String);
			exit when Index=Maximum_Deck_Length; -- preventing CONSTRAINT_ERROR;
			Index:=Index+1;
			end loop;
			end loop;
end Initialize;

   procedure Shuffle (TDeck : in out Deck) is
      Position_Gen   : Card_Position_Random.Generator;
      Temporary_Data : Card_Info;
      Index_Random   : Card_Position;
   begin
      Card_Position_Random.Reset (Gen => Position_Gen);
      for Index in Card_Position loop
         Index_Random         := Card_Position_Random.Random (Gen => Position_Gen);
         Temporary_Data       := TDeck (Index);
         TDeck (Index)        := TDeck (Index_Random);
         TDeck (Index_Random) := Temporary_Data;
      end loop;
   end Shuffle;
   Tarot_Deck : Deck;
   begin
   Initialize(Tarot_Deck);
   Shuffle(Tarot_Deck);
   for Index in Card_Position loop -- just print the deck as shuffled
   if Tarot_Deck(Index).Trump then
	Ada.Text_IO.Put_Line("Major Arcana/Trump: "&Trump_Values'Image(Tarot_Deck(Index).Trump_Value));
else
	Ada.Text_IO.Put_Line("Minor Arcana: "&Card_Values'Image(Tarot_Deck(Index).Card_Value)&" of "&Card_Suits'Image(Tarot_Deck(Index).Suit_Value));
	end if;
	end loop;
   end Tarot1;

Thanks for help.



^ permalink raw reply	[relevance 4%]

* Read-write mutex sometimes fails on deadlock
@ 2017-10-28 20:02  1% pascal.malaise
  0 siblings, 0 replies; 106+ results
From: pascal.malaise @ 2017-10-28 20:02 UTC (permalink / raw)


Hi,

[long post because it includes the full sources and output, sorry]

I have a package that implements several kinds of mutexes, including a
read-write mutex. Here is the full source (spec and body) with only the
read-write part.

mutexes.ads
-----------

private with Ada.Task_Identification;
-- Mutex (single and Read_Write) management
package Mutexes is

  -- Kind of mutex
  -- Read_Write allows several readers but one writer at a time.
  --  This implementation is fair but somewhat CPU-consuming because
  --  the arrival of a reader while writer(s) are waiting triggers a
  --  re-evaluation to let it pass if it has a higher (task) priority.
  -- Kind of requested access for a Read_Write mutex
  type Access_Kind is (Read, Write);

  -- Mutex object, free at creation
  type Mutex is tagged limited private;

  -- Get access to a mutex.
  -- With RW mutex (Read_Write), simultaneous read are possible,
  --  but there is only one writer at a time and no reader at that time.
  -- If delay is negative, wait until mutex is got,
  -- If delay is null, try and give up if not free,
  -- If delay is positive, try during the specified delay.
  -- Raises Already_Got if the current task if it has already got the RW mutex
  --  for write.
  -- Note that there is no check of "Read then Write" deadlock.
  Already_Got : exception;
  function Get (A_Mutex      : in out Mutex;
                Waiting_Time : in Duration;
                Kind         : in Access_Kind := Read) return Boolean;
  -- Get access to a mutex : infinite wait.
  procedure Get (A_Mutex      : in out Mutex;
                 Kind         : in Access_Kind := Read);
  function Get (A_Mutex : in out Mutex) return Boolean;


  -- Release access to a mutex.
  -- Raises Not_Owner if current task doesn't own the the RW mutex for write
  --  (no check when releasing RW mutex aquired for read).
  Not_Owner : exception;
  procedure Release (A_Mutex : in out Mutex);

  -- Is current task the "owner" (access got) of a simple mutex
  -- Is it the writer in case of a RW mutex
  function Is_Owner (A_Mutex : in Mutex) return Boolean;

private

  -- Read/write mutex
  -- We want to queue all requests (read and write) within the same queue
  --  to ensure fairness (avoid starvation).
  -- But the condition for read is "no writer" (not Writer)
  --  and for write it is "no writer and no reader"
  --  (not Writer and then Readers = 0)
  -- So the guard of the common queue is "no writer", but a writer may pass it
  --  while there are reader. In this case, we would like to requeue it in the
  --  same queue and in the beginning of it; note that "requeue" requeues at
  --  the end :-(. The artifact is to requeue the task, and all other
  --  tasks queueing after it as well, in an alternate queue (Swapping).
  -- Benefit: a new reader may enter while writer(s) are queueing, if its
  --  priority is better. Fairness ++.
  -- Drawback: each new reader while writer(s) are queueing triggers an open
  --  then a swap of the queues. Perfo --.

  -- So there are two queues
  type Queue_Range is mod 2;

  -- The read/write access lock and queues. No time.
  protected type Rw_Mutex_Protect is

    -- Gets the lock. Blocking.
    entry Mutex_Get (Kind : in Access_Kind);

    -- Releases the lock
    procedure Mutex_Release;

    -- Is current task write owner of the lock
    function Mutex_Owns return Boolean;
  private
    -- Number of readers
    Readers : Natural := 0;
    -- Writer identification
    Owner : Ada.Task_Identification.Task_Id;
    -- Numer of times it has got the write lock
    Writer : Natural := 0;

    -- Two queues, one is active at a time
    entry Queues (Queue_Range) (Kind : in Access_Kind);
    Current_Queue : Queue_Range := Queue_Range'First;
    -- The status of the queue:
    -- Swapping or not
    Swapping : Boolean := False;
    -- If not swapping, is the mutex open or not
    -- if swapping, will it be open or not
    Open : Boolean := True;

  end Rw_Mutex_Protect;

  -- The general purpose mutex
  type Mutex is tagged limited record
    Rw_Mutex : Rw_Mutex_Protect;
  end record;
end Mutexes;


mutexes.adb
-----------

with Ada.Text_Io;
package body Mutexes is

  use type Ada.Task_Identification.Task_Id;
  function Image (Id : in Ada.Task_Identification.Task_Id) return String
           renames Ada.Task_Identification.Image;

  Debug_Set : Boolean := False;
  Debug_On : Boolean := False;
  procedure Trace (Id : in Ada.Task_Identification.Task_Id;
                   Msg : in String) is
  begin
    if not Debug_Set then
      -- Initial setup
      Debug_Set := True;
      Debug_On := True;
    end if;
    if Debug_On then
      Ada.Text_Io.Put_Line (Msg & " " & Image (Id));
    end if;
  end Trace;

  -- The protected object which implements the read/write mutex
  protected body Rw_Mutex_Protect is

    -- Gets the lock. Blocking.
    -- Do not let a new request be inserted in the middle of a queue while
    -- we are swapping queues.
    entry Mutex_Get (Kind : in Access_Kind) when not Swapping is
    begin
      -- Are we already the writer
      if Writer /= 0 and then Mutex_Get'Caller = Owner then
        raise Already_Got;
      end if;

      -- Queue the request in the active queue
      Trace (Mutex_Get'Caller, "Read_Write get queueing");
      requeue Queues(Current_Queue) with abort;
    end Mutex_Get;

    -- Releases the lock. No Check of kind but the lock must have been
    -- got.
    procedure Mutex_Release is
    begin
      if Readers > 0 then
        -- There are readers, one of them is releasing the lock
        Readers := Readers - 1;
        if Readers = 0 then
          -- The last reader leaves, so the lock becomes available
          --  for writers
          Trace (Ada.Task_Identification.Current_Task, "Last reader releases");
          Open := True;
        else
          Trace (Ada.Task_Identification.Current_Task, "Reader releases");
        end if;
      elsif Writer /= 0
      and then Ada.Task_Identification.Current_Task = Owner then
        -- The writer is releasing the lock
        if Writer /= 1 then
          Writer := Writer - 1;
          return;
        end if;
        -- Really releasing
        Trace (Ada.Task_Identification.Current_Task, "Writer releases");
        Writer := 0;
        Open := True;
      else
        -- Called while no lock was got or not called by the writer
        raise Not_Owner;
      end if;
    end Mutex_Release;

    function Mutex_Owns return Boolean is
      (Writer /= 0 and then Ada.Task_Identification.Current_Task = Owner);

    -- Two queues, one active at a time
    -- Passes when swapping queues or else when open
    entry Queues (for Queue in Queue_Range) (Kind : in Access_Kind)
          when Queue = Current_Queue
          and then (Swapping or else Open) is
    begin
      if Swapping then
        -- Swapping queueing tasks from one queue to the other
        Trace (Queues'Caller, "Swapping");
        if Queues(Queue)'Count = 0 then
          -- This is the last task: end of swapping
          -- Open remains unchanged (maybe open by a release)
          Swapping := False;
          Current_Queue := Current_Queue + 1;
          Trace (Queues'Caller, "End swapping");
        end if;
        -- Requeue the task on the other queue
        requeue Queues(Queue + 1) with abort;
      else
        -- The queue is open: The lock is either free or allocated to reader(s)
        if Kind = Read then
          Trace (Queues'Caller, "Another reader");
          -- Read lock
          Readers := Readers + 1;
        else
          -- Write lock:
          -- If we are here, it means that the gate is open so no writer
          --  has already got the lock
          -- Either we get the lock (queue is closed until we release)
          -- or we queue (no currently queueing read can pass)
          -- so in both case, the queue is closed
          -- Note that a new request may re-open the queue and enter
          --  before us if it as a better prio
          Open := False;
          if Readers = 0 then
            -- No reader => we get the write lock
            Writer := 1;
            Owner := Queues'Caller;
            Trace (Queues'Caller, "Writer has got lock");
          else
            -- We have to wait until last reader releases the lock
            -- If we are alone, requeue ourself. Otherwise
            --  requeue in the alternate queue this task, then all the other
            --  queueing tasks, so we remain first (if same prios)
            Swapping := Queues(Queue)'Count > 0;
            if Swapping then
              Trace (Queues'Caller, "Start swapping");
              requeue Queues(Queue + 1) with abort;
            else
              Trace (Queues'Caller, "Writer waits for current reader");
              requeue Queues(Queue) with abort;
            end if;
          end if;
        end if;
      end if;
    end Queues;

  end Rw_Mutex_Protect;

  function Get (A_Mutex      : in out Mutex;
                Waiting_Time : in Duration;
                Kind         : in Access_Kind := Read) return Boolean is
    Result : Boolean;
  begin
    if Waiting_Time < 0.0 then
      -- Negative delay : unconditional waiting
      A_Mutex.Rw_Mutex.Mutex_Get (Kind);
      Result := True;
    else
      select
        A_Mutex.Rw_Mutex.Mutex_Get (Kind);
        Result := True;
      or
        delay Waiting_Time;
        Result := False;
      end select;
    end if;
    return Result;
  end Get;

  function Get (A_Mutex : in out Mutex) return Boolean is
    (Get (A_Mutex, -1.0, Read));

  -- Get a mutex : infinite wait
  procedure Get (A_Mutex      : in out Mutex;
                 Kind         : in Access_Kind := Read) is
    Dummy : Boolean;
  begin
    Dummy := Get (A_Mutex, -1.0, Kind);
  end Get;

  -- Release a mutex
  procedure Release (A_Mutex : in out Mutex) is
  begin
    -- Request releasing
    A_Mutex.Rw_Mutex.Mutex_Release;
  end Release;

  -- Does current task own the mutex (for write)
  function Is_Owner (A_Mutex : Mutex) return Boolean is
  begin
    return A_Mutex.Rw_Mutex.Mutex_Owns;
  end Is_Owner;

end Mutexes;



Finally, I have a test program of the read-write mutex, which creates 10 tasks,
each of them taking the mutex, for read or write, during some time. The tasks
randomly terminate, and when all of them are done then the test is OK.


t_read_write.adb
----------------
with Ada.Text_Io, Ada.Command_Line, Ada.Calendar, Ada.Task_Identification,
     Ada.Numerics.Float_Random;
with Gnat.Calendar;
with Mutexes;
-- Test Read-Write mutex
procedure T_Read_Write is
  pragma Priority(10);

  -- True if gnat, otherwise remove usage of Gnat.Calendar
  Has_Gnat : constant Boolean := True;

  -- The number of tasks
  subtype Range_Actor is Natural range 0 .. 10;
  Main_Index : constant Range_Actor := 0;
  subtype Range_Task is Positive range 1 .. Range_Actor'Last;

  -- Date of last output of a task
  Last_Time : Ada.Calendar.Time;
  use type Ada.Calendar.Time;
  -- Delay of inactivity
  Inactivity : constant Duration := 5.0;

  -- Random generator
  Gen : Ada.Numerics.Float_Random.Generator;
  function Random (Mini : in Integer := 0;
                   Maxi : in Integer := 1) return Integer is
    F : Float;
    Res : Integer;
  begin
    F := Float(Mini) + Ada.Numerics.Float_Random.Random(Gen)
                       * Float(Maxi - Mini);
    Res := Integer (F);
    while Res > Maxi and then Res > Mini loop
      Res := Res - 1;
    end loop;
    return Res;
  end Random;

  -- Image of a date 
  function Image (Date : Ada.Calendar.Time) return String is
    Year   : Ada.Calendar.Year_Number;
    Month  : Ada.Calendar.Month_Number;
    Day    : Ada.Calendar.Day_Number;

    Hour       : Gnat.Calendar.Hour_Number;
    Minute     : Gnat.Calendar.Minute_Number;
    Second     : Gnat.Calendar.Second_Number;
    Sub_Second : Gnat.Calendar.Second_Duration;
    function Img (D : Gnat.Calendar.Second_Duration) return String is
      S : constant String := D'Img;
    begin
      return S(3 .. S'Last);
    end Img;
    Dur    : Ada.Calendar.Day_Duration;
    function Img (N : Integer) return String is
      S : constant String := N'Img;
    begin
      if S'Last = 2 then
        -- " d", 1 digit => "0" & d
        return "0" & S(2);
      else
        -- " dd", d
        return S(2 .. S'Last);
      end if;
    end Img;
    
  begin
    if Has_Gnat then
      Gnat.Calendar.Split (Date, Year, Month, Day, Hour, Minute, Second,
                           Sub_Second);
      return Img (Year) & "-" & Img (Month) & "-" & Img (Day) & "T"
           & Img (Hour) & ":" & Img (Minute) & ":" & Img (Second)
           & Img (Sub_Second);

    else
      Ada.Calendar.Split (Date, Year, Month, Day, Dur);
      return Img (Year) & "/" & Img (Month) & "/" & Img (Day) & Dur'Img;
    end if;
  end Image;

  -- Put a task activity
  procedure Put_Line (Index : in Range_Actor; Msg : in String) is
  begin
    Last_Time := Ada.Calendar.Clock;
    declare
      Date : constant String := Image (Last_Time);
      Str : constant String
          := (if Index in Range_Task then Index'Img else "Main")
           & " " & Msg;
    begin
      Ada.Text_Io.Put_Line (Date & " " & Str);
    end;
  end Put_Line;
  Lock : access Mutexes.Mutex;

  -- The client tasks
  task type T is
   pragma Priority(10);
    entry Num (I : in Range_Task);
    entry Done;
  end T;

  function Image (D : Duration) return String is
    Str : constant String := D'Img;
  begin
    return Str (1 .. 4);
  end Image;

  task body T is
    Index : Range_Task;
    Dur : Duration;
    Kind : Mutexes.Access_Kind;
    subtype Str5 is String (1 .. 5);
    Kind_Strs : constant array (Mutexes.Access_Kind) of Str5 := (
      Mutexes.Read  => " Read",
      Mutexes.Write => "Write");
    Res : Boolean;
  begin
    -- Get name
    accept Num (I : in Range_Task) do
      Index := I;
    end Num;
    Put_Line (Index ,
      "Task started, id "
    & Ada.Task_Identification.Image (Ada.Task_Identification.Current_Task));
    -- Work until termination requested in Critical
    loop
      delay 0.01;
      -- Wait from -0.1 to 0.5
      Dur := Duration (Random (-1, 5)) / 10.0;
      -- 10% chances to write
      if Random (0, 9) = 0 then
        Kind := Mutexes.Write;
      else
        Kind := Mutexes.Read;
      end if;
      -- Get lock
      Put_Line (Index, "get " & Kind_Strs(Kind) & " " & Image(Dur));
      Res := Lock.Get (Dur, Kind);
      -- Trace result
      if Res then
        Put_Line (Index, "OK");
      else
        Put_Line (Index, "NOK");
      end if;

      if Res then
        -- Got it: Work (wait) from 0.1 to 0.5
        Put_Line (Index, "waiting");
        delay Duration (Random (1, 5)) / 10.0;
        Put_Line (Index, "waited");

        -- Release lock
        Put_Line (Index, "release");
        Lock.Release;
      end if;

      -- 10% chances to terminate
      exit when Random (0, 9) = 0;
    end loop;
    Put_Line (Index, "terminate");
    -- Ready to end
    accept Done;
  end T;

  Tasks : array (Range_Task) of T;
  Runs  : array (Range_Task) of Boolean;
  Nb_Run : Natural;

-- The main: activate and monitor the tasks
begin
  Lock := new Mutexes.Mutex;

  -- Randomize
  Ada.Numerics.Float_Random.Reset (Gen, 
    Integer (Ada.Calendar.Seconds (Ada.Calendar.Clock)));

  -- Give to each actor it's name
  Put_Line (Main_Index, "Starting");
  Nb_Run := 0;
  for I in Range_Task loop
    Tasks(I).Num (I);
    Runs(I) := True;
    Nb_Run := Nb_Run + 1;
  end loop;

  -- Wait until termination of all tasks
  Main: while Nb_Run /= 0 loop

    -- Try to terminate tasks: wait 1s altogether
    for I in Range_Task loop
      if Runs(I) then
        select
          Tasks(I).Done;
          Runs(I) := False;
          Nb_Run := Nb_Run - 1;
        or
          delay 1.0 / Duration(Nb_Run);
        end select;
      end if;
    end loop;

    -- Monitor activity
    if Ada.Calendar.Clock - Last_Time > Inactivity then
      -- Deadlock detected => abort tasks
      Put_Line (Main_Index, "Deadlock detected, aborting");
      Ada.Command_Line.Set_Exit_Status (1);
      for I in Range_Task loop
        if Runs(I) then
          abort Tasks(I);
          -- This will exit Main
          Nb_Run := Nb_Run - 1;
        end if;
      end loop;
    end if;
  end loop Main;

  Put_Line (Main_Index, "Done");

end T_Read_Write;


Most of the time it works, but from time to time (every 100 to 1000 iterations)
the test fails: the main detects a deadlock because of no output activity during
more than 5 secs, and exits on error.
You can test on Unix with the following scripts (launch "./Loop"):

trw
---
#!/bin/bash
./t_read_write >out 2>err

Loop
----
#!/bin/bash

# Loop until failure
res=0
let n=0+1
while [ $res -eq 0 ] ; do
  echo `date +"%Y-%m-%dT%H:%M:%S"`" Iteration "$n":"
  ./trw
  if [ $? -ne 0 ] ; then
    echo "Failed!"
    exit 1
  fi
  let n=$n+1
done



When everything is OK all the tasks terminate one after the other, but in case
of failure, here is the output:

2017-10-28T21:15:21.139556000 Main Starting
2017-10-28T21:15:21.139602000  1 Task started, id tasks(1)_0000000000E63F10
2017-10-28T21:15:21.139618000  2 Task started, id tasks(2)_0000000000E68040
2017-10-28T21:15:21.139644000  3 Task started, id tasks(3)_0000000000E6B650
2017-10-28T21:15:21.139662000  4 Task started, id tasks(4)_0000000000E6EC60
2017-10-28T21:15:21.139679000  5 Task started, id tasks(5)_0000000000E72270
2017-10-28T21:15:21.139695000  6 Task started, id tasks(6)_0000000000E75880
2017-10-28T21:15:21.139709000  7 Task started, id tasks(7)_0000000000E78E90
2017-10-28T21:15:21.139732000  8 Task started, id tasks(8)_0000000000E7C4A0
2017-10-28T21:15:21.139752000  9 Task started, id tasks(9)_0000000000E7FAB0
2017-10-28T21:15:21.139759000  10 Task started, id tasks(10)_0000000000E830C0
2017-10-28T21:15:21.149687000  1 get  Read  0.0
2017-10-28T21:15:21.149690000  3 get Write  0.1
2017-10-28T21:15:21.149700000  2 get  Read  0.0
Read_Write get queueing tasks(1)_0000000000E63F10
2017-10-28T21:15:21.149744000  5 get  Read  0.0
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:21.149782000  4 get Write  0.5
Read_Write get queueing tasks(3)_0000000000E6B650
Writer waits for current reader tasks(3)_0000000000E6B650
2017-10-28T21:15:21.149804000  8 get  Read  0.1
2017-10-28T21:15:21.149786000  1 OK
2017-10-28T21:15:21.149769000  6 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
2017-10-28T21:15:21.149825000  9 get  Read  0.5
2017-10-28T21:15:21.149829000  2 NOK
Read_Write get queueing tasks(9)_0000000000E7FAB0
2017-10-28T21:15:21.149855000  10 get  Read  0.0
2017-10-28T21:15:21.149875000  7 get  Read  0.2
2017-10-28T21:15:21.149816000  1 waiting
Read_Write get queueing tasks(4)_0000000000E6EC60
Read_Write get queueing tasks(8)_0000000000E7C4A0
Read_Write get queueing tasks(6)_0000000000E75880
Read_Write get queueing tasks(5)_0000000000E72270
2017-10-28T21:15:21.149917000  6 NOK
2017-10-28T21:15:21.149926000  5 NOK
Read_Write get queueing tasks(10)_0000000000E830C0
Read_Write get queueing tasks(7)_0000000000E78E90
2017-10-28T21:15:21.149940000  10 NOK
2017-10-28T21:15:21.159909000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
2017-10-28T21:15:21.159990000  5 get  Read  0.3
Read_Write get queueing tasks(5)_0000000000E72270
2017-10-28T21:15:21.160006000  10 get  Read  0.5
2017-10-28T21:15:21.159993000  6 get  Read  0.0
Read_Write get queueing tasks(6)_0000000000E75880
2017-10-28T21:15:21.160032000  6 NOK
Read_Write get queueing tasks(10)_0000000000E830C0
2017-10-28T21:15:21.170103000  6 get  Read  0.4
Read_Write get queueing tasks(6)_0000000000E75880
2017-10-28T21:15:21.249871000  3 NOK
2017-10-28T21:15:21.249967000  8 NOK
2017-10-28T21:15:21.259960000  2 NOK
2017-10-28T21:15:21.259964000  3 get  Read  0.1
Read_Write get queueing tasks(3)_0000000000E6B650
2017-10-28T21:15:21.260036000  8 get  Read -0.1
Read_Write get queueing tasks(8)_0000000000E7C4A0
2017-10-28T21:15:21.270048000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
2017-10-28T21:15:21.270066000  2 NOK
2017-10-28T21:15:21.280139000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
2017-10-28T21:15:21.349953000  1 waited
2017-10-28T21:15:21.349976000  1 release
Last reader releases tasks(1)_0000000000E63F10
Another reader tasks(9)_0000000000E7FAB0
Start swapping tasks(4)_0000000000E6EC60
Swapping tasks(7)_0000000000E78E90
2017-10-28T21:15:21.350007000  9 OK
2017-10-28T21:15:21.350051000  9 waiting
Swapping tasks(5)_0000000000E72270
2017-10-28T21:15:21.360060000  1 get  Read  0.0
Swapping tasks(10)_0000000000E830C0
Swapping tasks(6)_0000000000E75880
Swapping tasks(8)_0000000000E7C4A0
Swapping tasks(2)_0000000000E68040
End swapping tasks(2)_0000000000E68040
Read_Write get queueing tasks(1)_0000000000E63F10
2017-10-28T21:15:21.360109000  3 NOK
2017-10-28T21:15:21.360121000  1 NOK
2017-10-28T21:15:21.370195000  3 get  Read  0.3
Read_Write get queueing tasks(3)_0000000000E6B650
2017-10-28T21:15:21.370204000  1 get Write  0.0
Read_Write get queueing tasks(1)_0000000000E63F10
2017-10-28T21:15:21.370242000  1 NOK
2017-10-28T21:15:21.380223000  2 NOK
2017-10-28T21:15:21.380324000  1 get  Read -0.1
Read_Write get queueing tasks(1)_0000000000E63F10
2017-10-28T21:15:21.390298000  2 get  Read  0.2
Read_Write get queueing tasks(2)_0000000000E68040
2017-10-28T21:15:21.460071000  5 NOK
2017-10-28T21:15:21.470153000  5 get  Read  0.0
Read_Write get queueing tasks(5)_0000000000E72270
2017-10-28T21:15:21.470170000  5 NOK
2017-10-28T21:15:21.480242000  5 get  Read  0.1
Read_Write get queueing tasks(5)_0000000000E72270
2017-10-28T21:15:21.570194000  6 NOK
2017-10-28T21:15:21.580275000  6 get  Read  0.0
Read_Write get queueing tasks(6)_0000000000E75880
2017-10-28T21:15:21.580293000  6 NOK
2017-10-28T21:15:21.580321000  5 NOK
2017-10-28T21:15:21.590365000  2 NOK
2017-10-28T21:15:21.590374000  6 get  Read  0.4
Read_Write get queueing tasks(6)_0000000000E75880
2017-10-28T21:15:21.590401000  5 get  Read  0.2
Read_Write get queueing tasks(5)_0000000000E72270
2017-10-28T21:15:21.600438000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
2017-10-28T21:15:21.649962000  4 NOK
2017-10-28T21:15:21.660056000  4 get  Read  0.2
Read_Write get queueing tasks(4)_0000000000E6EC60
2017-10-28T21:15:21.660107000  10 NOK
2017-10-28T21:15:21.670184000  10 get  Read  0.0
Read_Write get queueing tasks(10)_0000000000E830C0
2017-10-28T21:15:21.670203000  10 NOK
2017-10-28T21:15:21.670286000  3 NOK
2017-10-28T21:15:21.680277000  10 get  Read -0.1
Read_Write get queueing tasks(10)_0000000000E830C0
2017-10-28T21:15:21.680365000  3 get  Read  0.3
Read_Write get queueing tasks(3)_0000000000E6B650
2017-10-28T21:15:21.750125000  9 waited
2017-10-28T21:15:21.750140000  9 release
Last reader releases tasks(9)_0000000000E7FAB0
Another reader tasks(8)_0000000000E7C4A0
Another reader tasks(1)_0000000000E63F10
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:21.750191000  1 OK
2017-10-28T21:15:21.750202000  6 OK
Another reader tasks(5)_0000000000E72270
2017-10-28T21:15:21.750215000  6 waiting
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:21.750166000  8 OK
2017-10-28T21:15:21.750251000  5 OK
Another reader tasks(4)_0000000000E6EC60
2017-10-28T21:15:21.750264000  5 waiting
2017-10-28T21:15:21.750275000  4 OK
2017-10-28T21:15:21.750286000  2 OK
2017-10-28T21:15:21.750298000  2 waiting
Another reader tasks(10)_0000000000E830C0
2017-10-28T21:15:21.750287000  4 waiting
2017-10-28T21:15:21.750254000  8 waiting
Another reader tasks(3)_0000000000E6B650
2017-10-28T21:15:21.750353000  9 terminate
2017-10-28T21:15:21.750356000  3 OK
2017-10-28T21:15:21.750205000  1 waiting
2017-10-28T21:15:21.750381000  3 waiting
2017-10-28T21:15:21.750338000  10 OK
2017-10-28T21:15:21.750420000  10 waiting
2017-10-28T21:15:21.950478000  3 waited
2017-10-28T21:15:21.950503000  3 release
Reader releases tasks(3)_0000000000E6B650
2017-10-28T21:15:21.960583000  3 get  Read  0.0
Read_Write get queueing tasks(3)_0000000000E6B650
Another reader tasks(3)_0000000000E6B650
2017-10-28T21:15:21.960607000  3 OK
2017-10-28T21:15:21.960615000  3 waiting
2017-10-28T21:15:22.150289000  6 waited
2017-10-28T21:15:22.150308000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:22.150351000  5 waited
2017-10-28T21:15:22.150361000  5 release
Reader releases tasks(5)_0000000000E72270
2017-10-28T21:15:22.150377000  2 waited
2017-10-28T21:15:22.150386000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:22.150411000  4 waited
2017-10-28T21:15:22.150425000  4 release
Reader releases tasks(4)_0000000000E6EC60
2017-10-28T21:15:22.150444000  8 waited
2017-10-28T21:15:22.150453000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:22.150488000  10 waited
2017-10-28T21:15:22.150498000  10 release
Reader releases tasks(10)_0000000000E830C0
2017-10-28T21:15:22.160386000  5 get  Read  0.3
2017-10-28T21:15:22.160388000  6 get  Read  0.3
Read_Write get queueing tasks(5)_0000000000E72270
Another reader tasks(5)_0000000000E72270
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:22.160455000  2 get  Read  0.1
2017-10-28T21:15:22.160498000  4 get  Read  0.2
2017-10-28T21:15:22.160457000  6 OK
2017-10-28T21:15:22.160517000  6 waiting
Read_Write get queueing tasks(2)_0000000000E68040
2017-10-28T21:15:22.160433000  5 OK
2017-10-28T21:15:22.160542000  8 get  Read  0.0
2017-10-28T21:15:22.160547000  5 waiting
Another reader tasks(2)_0000000000E68040
Read_Write get queueing tasks(4)_0000000000E6EC60
Another reader tasks(4)_0000000000E6EC60
2017-10-28T21:15:22.160580000  2 OK
2017-10-28T21:15:22.160611000  4 OK
Read_Write get queueing tasks(8)_0000000000E7C4A0
2017-10-28T21:15:22.160578000  10 get  Read  0.4
2017-10-28T21:15:22.160624000  4 waiting
Another reader tasks(8)_0000000000E7C4A0
Read_Write get queueing tasks(10)_0000000000E830C0
Another reader tasks(10)_0000000000E830C0
2017-10-28T21:15:22.160615000  2 waiting
2017-10-28T21:15:22.160655000  8 OK
2017-10-28T21:15:22.160674000  10 OK
2017-10-28T21:15:22.160692000  8 waiting
2017-10-28T21:15:22.160702000  10 waiting
2017-10-28T21:15:22.250462000  1 waited
2017-10-28T21:15:22.250475000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:22.260551000  1 get  Read  0.0
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:22.260571000  1 OK
2017-10-28T21:15:22.260579000  1 waiting
2017-10-28T21:15:22.260775000  10 waited
2017-10-28T21:15:22.260785000  10 release
Reader releases tasks(10)_0000000000E830C0
2017-10-28T21:15:22.270860000  10 get  Read -0.1
Read_Write get queueing tasks(10)_0000000000E830C0
Another reader tasks(10)_0000000000E830C0
2017-10-28T21:15:22.270879000  10 OK
2017-10-28T21:15:22.270887000  10 waiting
2017-10-28T21:15:22.360594000  6 waited
2017-10-28T21:15:22.360619000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:22.360646000  1 waited
2017-10-28T21:15:22.360658000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:22.360684000  4 waited
2017-10-28T21:15:22.360686000  3 waited
2017-10-28T21:15:22.360696000  4 release
Reader releases tasks(4)_0000000000E6EC60
2017-10-28T21:15:22.360706000  3 release
2017-10-28T21:15:22.360723000  4 terminate
Reader releases tasks(3)_0000000000E6B650
2017-10-28T21:15:22.360743000  2 waited
2017-10-28T21:15:22.360767000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:22.370699000  6 get  Read -0.1
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:22.370720000  6 OK
2017-10-28T21:15:22.370728000  6 waiting
2017-10-28T21:15:22.370735000  1 get  Read  0.0
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:22.370754000  1 OK
2017-10-28T21:15:22.370762000  1 waiting
2017-10-28T21:15:22.370817000  3 get  Read  0.0
Read_Write get queueing tasks(3)_0000000000E6B650
Another reader tasks(3)_0000000000E6B650
2017-10-28T21:15:22.370835000  3 OK
2017-10-28T21:15:22.370838000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:22.370843000  3 waiting
2017-10-28T21:15:22.370866000  2 OK
2017-10-28T21:15:22.370882000  2 waiting
2017-10-28T21:15:22.460633000  5 waited
2017-10-28T21:15:22.460653000  5 release
Reader releases tasks(5)_0000000000E72270
2017-10-28T21:15:22.460667000  5 terminate
2017-10-28T21:15:22.560780000  8 waited
2017-10-28T21:15:22.560798000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:22.570880000  8 get  Read  0.3
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:22.570902000  8 OK
2017-10-28T21:15:22.570911000  8 waiting
2017-10-28T21:15:22.570949000  2 waited
2017-10-28T21:15:22.570959000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:22.581035000  2 get  Read  0.2
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:22.581054000  2 OK
2017-10-28T21:15:22.581062000  2 waiting
2017-10-28T21:15:22.670800000  6 waited
2017-10-28T21:15:22.670856000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:22.680902000  6 get  Read  0.2
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:22.680930000  6 OK
2017-10-28T21:15:22.680938000  6 waiting
2017-10-28T21:15:22.770837000  1 waited
2017-10-28T21:15:22.770857000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:22.770938000  3 waited
2017-10-28T21:15:22.770939000  10 waited
2017-10-28T21:15:22.770951000  3 release
Reader releases tasks(3)_0000000000E6B650
2017-10-28T21:15:22.770965000  10 release
Reader releases tasks(10)_0000000000E830C0
2017-10-28T21:15:22.780936000  1 get  Read  0.1
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:22.780975000  1 OK
2017-10-28T21:15:22.780983000  1 waiting
2017-10-28T21:15:22.781041000  3 get  Read  0.2
Read_Write get queueing tasks(3)_0000000000E6B650
Another reader tasks(3)_0000000000E6B650
2017-10-28T21:15:22.781059000  10 get  Read  0.0
Read_Write get queueing tasks(10)_0000000000E830C0
Another reader tasks(10)_0000000000E830C0
2017-10-28T21:15:22.781059000  3 OK
2017-10-28T21:15:22.781092000  10 OK
2017-10-28T21:15:22.781102000  3 waiting
2017-10-28T21:15:22.781112000  10 waiting
2017-10-28T21:15:22.881010000  6 waited
2017-10-28T21:15:22.881023000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:22.891099000  6 get  Read  0.4
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:22.891118000  6 OK
2017-10-28T21:15:22.891126000  6 waiting
2017-10-28T21:15:22.981185000  3 waited
2017-10-28T21:15:22.981200000  3 release
Reader releases tasks(3)_0000000000E6B650
2017-10-28T21:15:22.991277000  3 get  Read  0.3
Read_Write get queueing tasks(3)_0000000000E6B650
Another reader tasks(3)_0000000000E6B650
2017-10-28T21:15:22.991297000  3 OK
2017-10-28T21:15:22.991305000  3 waiting
2017-10-28T21:15:23.070985000  8 waited
2017-10-28T21:15:23.071001000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:23.081054000  1 waited
2017-10-28T21:15:23.081066000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:23.081078000  8 get  Read  0.4
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:23.081098000  8 OK
2017-10-28T21:15:23.081106000  8 waiting
2017-10-28T21:15:23.081130000  2 waited
2017-10-28T21:15:23.081139000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:23.091142000  1 get  Read  0.0
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:23.091162000  1 OK
2017-10-28T21:15:23.091170000  1 waiting
2017-10-28T21:15:23.091220000  2 get  Read  0.2
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:23.091242000  2 OK
2017-10-28T21:15:23.091250000  2 waiting
2017-10-28T21:15:23.091369000  3 waited
2017-10-28T21:15:23.091379000  3 release
Reader releases tasks(3)_0000000000E6B650
2017-10-28T21:15:23.091391000  3 terminate
2017-10-28T21:15:23.181190000  10 waited
2017-10-28T21:15:23.181206000  10 release
Reader releases tasks(10)_0000000000E830C0
2017-10-28T21:15:23.191284000  10 get  Read  0.4
Read_Write get queueing tasks(10)_0000000000E830C0
Another reader tasks(10)_0000000000E830C0
2017-10-28T21:15:23.191304000  10 OK
2017-10-28T21:15:23.191312000  10 waiting
2017-10-28T21:15:23.291193000  6 waited
2017-10-28T21:15:23.291207000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:23.291316000  2 waited
2017-10-28T21:15:23.291329000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:23.301282000  6 get  Read  0.1
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:23.301302000  6 OK
2017-10-28T21:15:23.301310000  6 waiting
2017-10-28T21:15:23.301406000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:23.301442000  2 OK
2017-10-28T21:15:23.301450000  2 waiting
2017-10-28T21:15:23.381183000  8 waited
2017-10-28T21:15:23.381228000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:23.391314000  8 get  Read  0.2
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:23.391339000  8 OK
2017-10-28T21:15:23.391347000  8 waiting
2017-10-28T21:15:23.501526000  2 waited
2017-10-28T21:15:23.501556000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:23.511639000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:23.511663000  2 OK
2017-10-28T21:15:23.511671000  2 waiting
2017-10-28T21:15:23.591239000  1 waited
2017-10-28T21:15:23.591261000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:23.591417000  8 waited
2017-10-28T21:15:23.591432000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:23.601334000  1 get  Read  0.2
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:23.601356000  1 OK
2017-10-28T21:15:23.601365000  1 waiting
2017-10-28T21:15:23.601513000  8 get  Read  0.5
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:23.601535000  8 OK
2017-10-28T21:15:23.601544000  8 waiting
2017-10-28T21:15:23.691386000  10 waited
2017-10-28T21:15:23.691426000  10 release
Reader releases tasks(10)_0000000000E830C0
2017-10-28T21:15:23.701508000  10 get  Read -0.1
Read_Write get queueing tasks(10)_0000000000E830C0
Another reader tasks(10)_0000000000E830C0
2017-10-28T21:15:23.701530000  10 OK
2017-10-28T21:15:23.701538000  10 waiting
2017-10-28T21:15:23.801385000  6 waited
2017-10-28T21:15:23.801402000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:23.811480000  6 get  Read  0.3
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:23.811501000  6 OK
2017-10-28T21:15:23.811509000  6 waiting
2017-10-28T21:15:23.901439000  1 waited
2017-10-28T21:15:23.901452000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:23.901611000  10 waited
2017-10-28T21:15:23.901623000  10 release
Reader releases tasks(10)_0000000000E830C0
2017-10-28T21:15:23.901637000  10 terminate
2017-10-28T21:15:23.911529000  1 get  Read  0.0
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:23.911553000  1 OK
2017-10-28T21:15:23.911561000  1 waiting
2017-10-28T21:15:23.911744000  2 waited
2017-10-28T21:15:23.911758000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:23.921835000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:23.921856000  2 OK
2017-10-28T21:15:23.921864000  2 waiting
2017-10-28T21:15:24.101621000  8 waited
2017-10-28T21:15:24.101640000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:24.111575000  6 waited
2017-10-28T21:15:24.111589000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:24.111717000  8 get  Read  0.3
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:24.111737000  8 OK
2017-10-28T21:15:24.111745000  8 waiting
2017-10-28T21:15:24.121665000  6 get  Read  0.2
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:24.121684000  6 OK
2017-10-28T21:15:24.121692000  6 waiting
2017-10-28T21:15:24.211634000  1 waited
2017-10-28T21:15:24.211658000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:24.221736000  6 waited
2017-10-28T21:15:24.221737000  1 get  Read  0.0
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:24.221767000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:24.221793000  1 OK
2017-10-28T21:15:24.221834000  1 waiting
2017-10-28T21:15:24.221931000  2 waited
2017-10-28T21:15:24.221941000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:24.231875000  6 get  Read  0.1
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:24.231895000  6 OK
2017-10-28T21:15:24.231903000  6 waiting
2017-10-28T21:15:24.232011000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:24.232030000  2 OK
2017-10-28T21:15:24.232037000  2 waiting
2017-10-28T21:15:24.411815000  8 waited
2017-10-28T21:15:24.411839000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:24.421919000  8 get  Read -0.1
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:24.421940000  8 OK
2017-10-28T21:15:24.421948000  8 waiting
2017-10-28T21:15:24.431974000  6 waited
2017-10-28T21:15:24.431986000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:24.442064000  6 get  Read  0.3
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:24.442087000  6 OK
2017-10-28T21:15:24.442094000  6 waiting
2017-10-28T21:15:24.521907000  1 waited
2017-10-28T21:15:24.521922000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:24.531998000  1 get  Read  0.2
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:24.532018000  1 OK
2017-10-28T21:15:24.532026000  1 waiting
2017-10-28T21:15:24.532108000  2 waited
2017-10-28T21:15:24.532119000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:24.542201000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:24.542224000  2 OK
2017-10-28T21:15:24.542232000  2 waiting
2017-10-28T21:15:24.622024000  8 waited
2017-10-28T21:15:24.622040000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:24.632119000  8 get  Read  0.2
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:24.632139000  8 OK
2017-10-28T21:15:24.632147000  8 waiting
2017-10-28T21:15:24.832096000  1 waited
2017-10-28T21:15:24.832133000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:24.842170000  6 waited
2017-10-28T21:15:24.842188000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:24.842214000  1 get  Read -0.1
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:24.842235000  1 OK
2017-10-28T21:15:24.842243000  1 waiting
2017-10-28T21:15:24.852266000  6 get  Read  0.0
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:24.852287000  6 OK
2017-10-28T21:15:24.852295000  6 waiting
2017-10-28T21:15:24.932222000  8 waited
2017-10-28T21:15:24.932238000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:24.942304000  8 get  Read  0.5
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:24.942309000  2 waited
2017-10-28T21:15:24.942346000  8 OK
2017-10-28T21:15:24.942357000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:24.942367000  8 waiting
2017-10-28T21:15:24.952453000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:24.952480000  2 OK
2017-10-28T21:15:24.952488000  2 waiting
2017-10-28T21:15:25.052369000  6 waited
2017-10-28T21:15:25.052384000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:25.062461000  6 get  Read  0.4
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:25.062481000  6 OK
2017-10-28T21:15:25.062489000  6 waiting
2017-10-28T21:15:25.162556000  6 waited
2017-10-28T21:15:25.162575000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:25.172668000  6 get  Read -0.1
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:25.172689000  6 OK
2017-10-28T21:15:25.172697000  6 waiting
2017-10-28T21:15:25.242313000  1 waited
2017-10-28T21:15:25.242329000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:25.252407000  1 get  Read  0.0
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:25.252428000  1 OK
2017-10-28T21:15:25.252436000  1 waiting
2017-10-28T21:15:25.342454000  8 waited
2017-10-28T21:15:25.342491000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:25.352573000  8 get  Read  0.4
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:25.352594000  8 OK
2017-10-28T21:15:25.352602000  8 waiting
2017-10-28T21:15:25.452564000  2 waited
2017-10-28T21:15:25.452584000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:25.452672000  8 waited
2017-10-28T21:15:25.452686000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:25.462663000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:25.462683000  2 OK
2017-10-28T21:15:25.462691000  2 waiting
2017-10-28T21:15:25.462762000  8 get  Read  0.2
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:25.462781000  8 OK
2017-10-28T21:15:25.462789000  8 waiting
2017-10-28T21:15:25.572774000  6 waited
2017-10-28T21:15:25.572789000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:25.582868000  6 get  Read  0.1
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:25.582889000  6 OK
2017-10-28T21:15:25.582897000  6 waiting
2017-10-28T21:15:25.662860000  8 waited
2017-10-28T21:15:25.662894000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:25.672970000  8 get  Read  0.5
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:25.672993000  8 OK
2017-10-28T21:15:25.673001000  8 waiting
2017-10-28T21:15:25.752510000  1 waited
2017-10-28T21:15:25.752531000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:25.762609000  1 get  Read  0.3
Read_Write get queueing tasks(1)_0000000000E63F10
Another reader tasks(1)_0000000000E63F10
2017-10-28T21:15:25.762630000  1 OK
2017-10-28T21:15:25.762638000  1 waiting
2017-10-28T21:15:25.862708000  1 waited
2017-10-28T21:15:25.862720000  1 release
Reader releases tasks(1)_0000000000E63F10
2017-10-28T21:15:25.862732000  1 terminate
2017-10-28T21:15:25.862767000  2 waited
2017-10-28T21:15:25.862783000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:25.872861000  2 get  Read  0.2
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:25.872882000  2 OK
2017-10-28T21:15:25.872890000  2 waiting
2017-10-28T21:15:26.073070000  8 waited
2017-10-28T21:15:26.073087000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:26.082972000  6 waited
2017-10-28T21:15:26.082988000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:26.083163000  8 get  Read  0.2
Read_Write get queueing tasks(8)_0000000000E7C4A0
Another reader tasks(8)_0000000000E7C4A0
2017-10-28T21:15:26.083181000  8 OK
2017-10-28T21:15:26.083189000  8 waiting
2017-10-28T21:15:26.093071000  6 get  Read  0.3
Read_Write get queueing tasks(6)_0000000000E75880
Another reader tasks(6)_0000000000E75880
2017-10-28T21:15:26.093095000  6 OK
2017-10-28T21:15:26.093103000  6 waiting
2017-10-28T21:15:26.172971000  2 waited
2017-10-28T21:15:26.172987000  2 release
Reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:26.183059000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:26.183080000  2 OK
2017-10-28T21:15:26.183106000  2 waiting
2017-10-28T21:15:26.383260000  8 waited
2017-10-28T21:15:26.383286000  8 release
Reader releases tasks(8)_0000000000E7C4A0
2017-10-28T21:15:26.383301000  8 terminate
2017-10-28T21:15:26.393182000  6 waited
2017-10-28T21:15:26.393198000  6 release
Reader releases tasks(6)_0000000000E75880
2017-10-28T21:15:26.393212000  6 terminate
2017-10-28T21:15:26.483178000  2 waited
2017-10-28T21:15:26.483208000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:26.493292000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:26.493316000  2 OK
2017-10-28T21:15:26.493325000  2 waiting
2017-10-28T21:15:26.993401000  2 waited
2017-10-28T21:15:26.993437000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:27.003520000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:27.003542000  2 OK
2017-10-28T21:15:27.003550000  2 waiting
2017-10-28T21:15:27.203619000  2 waited
2017-10-28T21:15:27.203647000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:27.213722000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:27.213746000  2 OK
2017-10-28T21:15:27.213754000  2 waiting
2017-10-28T21:15:27.513830000  2 waited
2017-10-28T21:15:27.513855000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:27.523934000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:27.523956000  2 OK
2017-10-28T21:15:27.523964000  2 waiting
2017-10-28T21:15:27.624041000  2 waited
2017-10-28T21:15:27.624061000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:27.634138000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:27.634166000  2 OK
2017-10-28T21:15:27.634175000  2 waiting
2017-10-28T21:15:28.034250000  2 waited
2017-10-28T21:15:28.034286000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:28.044367000  2 get  Read  0.2
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:28.044390000  2 OK
2017-10-28T21:15:28.044398000  2 waiting
2017-10-28T21:15:28.144463000  2 waited
2017-10-28T21:15:28.144477000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:28.154554000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:28.154574000  2 OK
2017-10-28T21:15:28.154582000  2 waiting
2017-10-28T21:15:28.554654000  2 waited
2017-10-28T21:15:28.554694000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:28.564788000  2 get  Read  0.2
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:28.564809000  2 OK
2017-10-28T21:15:28.564817000  2 waiting
2017-10-28T21:15:28.964892000  2 waited
2017-10-28T21:15:28.964930000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:28.975011000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:28.975033000  2 OK
2017-10-28T21:15:28.975041000  2 waiting
2017-10-28T21:15:29.375116000  2 waited
2017-10-28T21:15:29.375152000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:29.385233000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:29.385256000  2 OK
2017-10-28T21:15:29.385264000  2 waiting
2017-10-28T21:15:29.585340000  2 waited
2017-10-28T21:15:29.585369000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:29.595450000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:29.595472000  2 OK
2017-10-28T21:15:29.595499000  2 waiting
2017-10-28T21:15:29.995580000  2 waited
2017-10-28T21:15:29.995616000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:30.005699000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:30.005720000  2 OK
2017-10-28T21:15:30.005728000  2 waiting
2017-10-28T21:15:30.405807000  2 waited
2017-10-28T21:15:30.405841000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:30.415924000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:30.415949000  2 OK
2017-10-28T21:15:30.415957000  2 waiting
2017-10-28T21:15:30.916029000  2 waited
2017-10-28T21:15:30.916066000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:30.926148000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:30.926170000  2 OK
2017-10-28T21:15:30.926178000  2 waiting
2017-10-28T21:15:31.026251000  2 waited
2017-10-28T21:15:31.026271000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:31.036349000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:31.036370000  2 OK
2017-10-28T21:15:31.036378000  2 waiting
2017-10-28T21:15:31.436457000  2 waited
2017-10-28T21:15:31.436496000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:31.446579000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:31.446603000  2 OK
2017-10-28T21:15:31.446611000  2 waiting
2017-10-28T21:15:31.746681000  2 waited
2017-10-28T21:15:31.746717000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:31.756798000  2 get  Read  0.5
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:31.756820000  2 OK
2017-10-28T21:15:31.756828000  2 waiting
2017-10-28T21:15:32.056900000  2 waited
2017-10-28T21:15:32.056916000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:32.066994000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:32.067014000  2 OK
2017-10-28T21:15:32.067022000  2 waiting
2017-10-28T21:15:32.167094000  2 waited
2017-10-28T21:15:32.167110000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:32.177187000  2 get Write  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Writer has got lock tasks(2)_0000000000E68040
2017-10-28T21:15:32.177207000  2 OK
2017-10-28T21:15:32.177214000  2 waiting
2017-10-28T21:15:32.477286000  2 waited
2017-10-28T21:15:32.477325000  2 release
Writer releases tasks(2)_0000000000E68040
2017-10-28T21:15:32.487402000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:32.487424000  2 OK
2017-10-28T21:15:32.487432000  2 waiting
2017-10-28T21:15:32.687509000  2 waited
2017-10-28T21:15:32.687547000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:32.697628000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:32.697651000  2 OK
2017-10-28T21:15:32.697659000  2 waiting
2017-10-28T21:15:32.897731000  2 waited
2017-10-28T21:15:32.897745000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:32.907822000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:32.907842000  2 OK
2017-10-28T21:15:32.907850000  2 waiting
2017-10-28T21:15:33.307919000  2 waited
2017-10-28T21:15:33.307952000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:33.318032000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:33.318071000  2 OK
2017-10-28T21:15:33.318080000  2 waiting
2017-10-28T21:15:33.718160000  2 waited
2017-10-28T21:15:33.718215000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:33.728307000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:33.728329000  2 OK
2017-10-28T21:15:33.728337000  2 waiting
2017-10-28T21:15:34.228412000  2 waited
2017-10-28T21:15:34.228445000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:34.238526000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:34.238548000  2 OK
2017-10-28T21:15:34.238556000  2 waiting
2017-10-28T21:15:34.538629000  2 waited
2017-10-28T21:15:34.538647000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:34.548728000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:34.548752000  2 OK
2017-10-28T21:15:34.548761000  2 waiting
2017-10-28T21:15:34.948840000  2 waited
2017-10-28T21:15:34.948878000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:34.958963000  2 get Write  0.2
Read_Write get queueing tasks(2)_0000000000E68040
Writer has got lock tasks(2)_0000000000E68040
2017-10-28T21:15:34.958987000  2 OK
2017-10-28T21:15:34.958995000  2 waiting
2017-10-28T21:15:35.259070000  2 waited
2017-10-28T21:15:35.259088000  2 release
Writer releases tasks(2)_0000000000E68040
2017-10-28T21:15:35.269165000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:35.269186000  2 OK
2017-10-28T21:15:35.269194000  2 waiting
2017-10-28T21:15:35.569274000  2 waited
2017-10-28T21:15:35.569311000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:35.579396000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:35.579420000  2 OK
2017-10-28T21:15:35.579428000  2 waiting
2017-10-28T21:15:35.879506000  2 waited
2017-10-28T21:15:35.879541000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:35.889623000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:35.889644000  2 OK
2017-10-28T21:15:35.889652000  2 waiting
2017-10-28T21:15:36.189721000  2 waited
2017-10-28T21:15:36.189744000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:36.199823000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:36.199844000  2 OK
2017-10-28T21:15:36.199852000  2 waiting
2017-10-28T21:15:36.599930000  2 waited
2017-10-28T21:15:36.599964000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:36.610050000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:36.610076000  2 OK
2017-10-28T21:15:36.610084000  2 waiting
2017-10-28T21:15:37.010162000  2 waited
2017-10-28T21:15:37.010200000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:37.020282000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:37.020305000  2 OK
2017-10-28T21:15:37.020313000  2 waiting
2017-10-28T21:15:37.420390000  2 waited
2017-10-28T21:15:37.420417000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:37.430498000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:37.430519000  2 OK
2017-10-28T21:15:37.430527000  2 waiting
2017-10-28T21:15:37.730596000  2 waited
2017-10-28T21:15:37.730633000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:37.740713000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:37.740754000  2 OK
2017-10-28T21:15:37.740762000  2 waiting
2017-10-28T21:15:38.140840000  2 waited
2017-10-28T21:15:38.140862000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:38.150942000  2 get  Read  0.5
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:38.150963000  2 OK
2017-10-28T21:15:38.150972000  2 waiting
2017-10-28T21:15:38.551046000  2 waited
2017-10-28T21:15:38.551084000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:38.561169000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:38.561193000  2 OK
2017-10-28T21:15:38.561201000  2 waiting
2017-10-28T21:15:38.761271000  2 waited
2017-10-28T21:15:38.761315000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:38.771407000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:38.771429000  2 OK
2017-10-28T21:15:38.771437000  2 waiting
2017-10-28T21:15:39.171511000  2 waited
2017-10-28T21:15:39.171539000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:39.181620000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:39.181645000  2 OK
2017-10-28T21:15:39.181653000  2 waiting
2017-10-28T21:15:39.381735000  2 waited
2017-10-28T21:15:39.381777000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:39.391859000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:39.391881000  2 OK
2017-10-28T21:15:39.391889000  2 waiting
2017-10-28T21:15:39.691968000  2 waited
2017-10-28T21:15:39.692008000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:39.702089000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:39.702111000  2 OK
2017-10-28T21:15:39.702119000  2 waiting
2017-10-28T21:15:40.002188000  2 waited
2017-10-28T21:15:40.002214000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:40.012293000  2 get Write  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Writer has got lock tasks(2)_0000000000E68040
2017-10-28T21:15:40.012314000  2 OK
2017-10-28T21:15:40.012322000  2 waiting
2017-10-28T21:15:40.412390000  2 waited
2017-10-28T21:15:40.412415000  2 release
Writer releases tasks(2)_0000000000E68040
2017-10-28T21:15:40.422496000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:40.422517000  2 OK
2017-10-28T21:15:40.422525000  2 waiting
2017-10-28T21:15:40.822601000  2 waited
2017-10-28T21:15:40.822637000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:40.832719000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:40.832741000  2 OK
2017-10-28T21:15:40.832749000  2 waiting
2017-10-28T21:15:41.132824000  2 waited
2017-10-28T21:15:41.132845000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:41.142924000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:41.142945000  2 OK
2017-10-28T21:15:41.142953000  2 waiting
2017-10-28T21:15:41.443034000  2 waited
2017-10-28T21:15:41.443077000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:41.453160000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:41.453184000  2 OK
2017-10-28T21:15:41.453192000  2 waiting
2017-10-28T21:15:41.753267000  2 waited
2017-10-28T21:15:41.753306000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:41.763387000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:41.763426000  2 OK
2017-10-28T21:15:41.763434000  2 waiting
2017-10-28T21:15:41.863510000  2 waited
2017-10-28T21:15:41.863525000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:41.873605000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:41.873629000  2 OK
2017-10-28T21:15:41.873637000  2 waiting
2017-10-28T21:15:42.273708000  2 waited
2017-10-28T21:15:42.273741000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:42.283819000  2 get  Read  0.3
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:42.283844000  2 OK
2017-10-28T21:15:42.283853000  2 waiting
2017-10-28T21:15:42.583929000  2 waited
2017-10-28T21:15:42.583954000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:42.594034000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:42.594056000  2 OK
2017-10-28T21:15:42.594065000  2 waiting
2017-10-28T21:15:42.794142000  2 waited
2017-10-28T21:15:42.794182000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:42.804264000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:42.804287000  2 OK
2017-10-28T21:15:42.804296000  2 waiting
2017-10-28T21:15:43.104374000  2 waited
2017-10-28T21:15:43.104400000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:43.114481000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:43.114504000  2 OK
2017-10-28T21:15:43.114513000  2 waiting
2017-10-28T21:15:43.314585000  2 waited
2017-10-28T21:15:43.314605000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:43.324684000  2 get  Read  0.0
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:43.324707000  2 OK
2017-10-28T21:15:43.324715000  2 waiting
2017-10-28T21:15:43.724984000  2 waited
2017-10-28T21:15:43.725023000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:43.735103000  2 get  Read -0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:43.735134000  2 OK
2017-10-28T21:15:43.735143000  2 waiting
2017-10-28T21:15:44.035217000  2 waited
2017-10-28T21:15:44.035255000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:44.045346000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:44.045369000  2 OK
2017-10-28T21:15:44.045377000  2 waiting
2017-10-28T21:15:44.245450000  2 waited
2017-10-28T21:15:44.245471000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:44.255551000  2 get  Read  0.5
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:44.255574000  2 OK
2017-10-28T21:15:44.255582000  2 waiting
2017-10-28T21:15:44.355662000  2 waited
2017-10-28T21:15:44.355703000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:44.365786000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:44.365812000  2 OK
2017-10-28T21:15:44.365821000  2 waiting
2017-10-28T21:15:44.565899000  2 waited
2017-10-28T21:15:44.565930000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:44.576016000  2 get  Read  0.1
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:44.576041000  2 OK
2017-10-28T21:15:44.576050000  2 waiting
2017-10-28T21:15:44.876120000  2 waited
2017-10-28T21:15:44.876158000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:44.886240000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:44.886281000  2 OK
2017-10-28T21:15:44.886290000  2 waiting
2017-10-28T21:15:45.186362000  2 waited
2017-10-28T21:15:45.186384000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:45.196462000  2 get  Read  0.4
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:45.196483000  2 OK
2017-10-28T21:15:45.196492000  2 waiting
2017-10-28T21:15:45.296562000  2 waited
2017-10-28T21:15:45.296585000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:45.306664000  2 get  Read  0.5
Read_Write get queueing tasks(2)_0000000000E68040
Another reader tasks(2)_0000000000E68040
2017-10-28T21:15:45.306685000  2 OK
2017-10-28T21:15:45.306693000  2 waiting
2017-10-28T21:15:45.706766000  2 waited
2017-10-28T21:15:45.706804000  2 release
Last reader releases tasks(2)_0000000000E68040
2017-10-28T21:15:45.706821000  2 terminate
2017-10-28T21:15:50.729534000 Main Deadlock detected, aborting
2017-10-28T21:15:50.729586000 Main Done

Task 7 did not terminate.
Last report of it was "21:15:21.149875000  7 get  Read  0.2"
At this time, 1 has got the lock for read, 3 is requesting it for write and
the other tasks are queueing for read or write (7 is queueing for read).
When 1 releases the lock: 017-10-28T21:15:21.349976000  1 release
the log of swapping shows that task 4, requesting for write, triggers the
swapping: Start swapping tasks(4)_0000000000E6EC60
At that time, all the queueing tasks are logged as being swapped except 7,
and task 7 seems to be blocked somewhere and is never activated.

Can you reproduce it? On Windows?
Is the bug in the test program, or in the mutex implementation, in Linux, or in Gnat?

Thanks

^ permalink raw reply	[relevance 1%]

* Re: Community Input for the Maintenance and Revision of the Ada Programming Language
  @ 2017-09-09 14:48  3%           ` G.B.
  0 siblings, 0 replies; 106+ results
From: G.B. @ 2017-09-09 14:48 UTC (permalink / raw)


On 06.09.17 17:02, Johan Söderlind Åström wrote:
> I do not know how Ada accesses a array element internally. But a zero indexed array must be cheaper than a custom indexed array, see:
>
> Accessing nth element from zero indexed array:
> (base_address + index*element_size).
>
> Accessing nth element from a custom indexed array:
> (base_address + (index - first)*element_size)
>
> I do not think that accessing a element from a array is a complicated thing and starting from a zero indexed array is even simpler, then why would a compiler not guarantee such a simple thing to work?

It seems to work well the way it is?
Is it a certainty that your assumptions describe
how our processors are working?

So, I checked, starting from a naive Average function, and
another Average_0 function. Both perform the same algorithm
with the exception of the parameter types: these are,
respectively, an array type with Index range <> and
a zero-based fixed size array type. (Index starts at 0.)

This is the loop body of both functions:

       for V : Likeness of Difference loop
          Result := Result + V / Likeness'Base (Difference'Length);
       end loop;

where Likeness is like Uniformly_Distributed from
Ada.Numerics.Float_Random, and Difference is an array.

The difference in the resulting loop bodies, on Intel,
for Average and Average_0 is this, when passing options
-O2 -gnatp -fno-inline to GNAT:

L17:
	addq	$1, %rax
	movss	(%rcx,%rax,4), %xmm1
	cmpq	%rdx, %rax
	divss	%xmm2, %xmm1
	addss	%xmm1, %xmm0
	jne	L17

L45:
	movss	(%rdi), %xmm1
	addq	$4, %rdi
	cmpq	%rax, %rdi
	divss	%xmm2, %xmm1
	addss	%xmm1, %xmm0
	jne	L45

When I have the functions called 100_000 times, the calls
result in execution time of some 50 seconds for either function.

There are 6 instructions for either 0-based or free bounds.

Maybe the loop isn't sufficiently dominated by addressing
from one or two registers, given DIVSS?

But first, using a modular type as the index type in place
of a range type starting at 0, I get

L24:
	movl	%eax, %edx
	addq	$1, %rax
	subq	%rsi, %rdx
	cmpq	%rax, %rcx
	movss	(%rdi,%rdx,4), %xmm1
	divss	%xmm2, %xmm1
	addss	%xmm1, %xmm0
	jne	L24

L59:
	movss	(%rdi,%rax,4), %xmm1
	addq	$1, %rax
	cmpq	$100000, %rax
	divss	%xmm2, %xmm1
	addss	%xmm1, %xmm0
	jne	L59

Still, no difference. So, using Sum now, here is the loop body
of Sum and Sum_0:

       for V : Likeness of Difference loop
          Result := Result + Float (V);
       end loop;


L63:
	movl	%eax, %edx
	addq	$1, %rax
	subq	%rsi, %rdx
	cmpq	%rax, %rcx
	addss	(%rdi,%rdx,4), %xmm0
	jne	L63

L67:
	addss	(%rdi,%rax,4), %xmm0
	addq	$1, %rax
	cmpq	$100000, %rax
	jne	L67
	ret

This result is independent of the choice of index type.
I had expected the first block to be slower than
the second due to SUB, but was wrong, seemingly.
Durations are around 10 seconds now.

So, if I haven't made some other stupid mistake, 0-based
arrays appear to be a non-issue, at least on Intel CPUs.


^ permalink raw reply	[relevance 3%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-10-01 15:49  7%               ` Dmitry A. Kazakov
@ 2016-10-01 16:44  6%                 ` Robert Eachus
  0 siblings, 0 replies; 106+ results
From: Robert Eachus @ 2016-10-01 16:44 UTC (permalink / raw)


On Saturday, October 1, 2016 at 11:50:04 AM UTC-4, Dmitry A. Kazakov wrote:
> On 2016-10-01 16:23, Robert Eachus wrote:
> 
> > But there is infinite state, and infinite state. An infinite state
> > that is a simple counter of the number of values returned is probably
> > acceptable, a generator that requires storing the whole sequence is not.
> 
> There is no difference both are infinite. Single infinite counter is 
> capable to store whole sequence and conversely.

My point was that a state which slowly grows toward infinity (the counter) can easily be stored.  Any state that requires infinite storage or grows non-polynomially is right out.  States which grow by some polynomial in the counter?  Depends. 

On the issue of multiple seeds, Pi times an integer is also trancendental, but the values would be correlated between sequences.  Multiplying Pi by a rational number is better, but I think natural logs of primes would work.  Of course, now we have the problem of converting the seed selected by the programmer, or the clock, or whatever, into unique prime seeds.


^ permalink raw reply	[relevance 6%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-10-01 14:23  5%             ` Robert Eachus
@ 2016-10-01 15:49  7%               ` Dmitry A. Kazakov
  2016-10-01 16:44  6%                 ` Robert Eachus
  0 siblings, 1 reply; 106+ results
From: Dmitry A. Kazakov @ 2016-10-01 15:49 UTC (permalink / raw)


On 2016-10-01 16:23, Robert Eachus wrote:

> But there is infinite state, and infinite state. An infinite state
> that is a simple counter of the number of values returned is probably
> acceptable, a generator that requires storing the whole sequence is not.

There is no difference both are infinite. Single infinite counter is 
capable to store whole sequence and conversely.

> Of course, these are unbounded
> integers which will eventually require an array of finite integers to
> represent. (Multiprecision arithmetic) I think that is acceptable.

An unbounded array of integers is infinite. Once you have it bound, you 
get repeating states or else a program halt.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[relevance 7%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-10-01  3:59  7%           ` Paul Rubin
@ 2016-10-01 14:23  5%             ` Robert Eachus
  2016-10-01 15:49  7%               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 106+ results
From: Robert Eachus @ 2016-10-01 14:23 UTC (permalink / raw)


On Friday, September 30, 2016 at 11:59:15 PM UTC-4, Paul Rubin wrote:
> Robert Eachus <rieachus@comcast.net> writes:
> >> aren't *all* PRNGs cyclic?
> > No, a simple counter-example is a generator that uses the digits of
> > pi.  The digits of any transcendental number will do. 
> 
> I don't see how this would work--to never cycle, it would need infinite
> internal state.  You could consider the digits of pi to be part of the
> state, but to count off the digits, you need a counter of infinite
> width.

A quick proof that a PRNG that never cycles requires infinite state:  If the generator ever returns to a previous state?  It cycles.

But there is infinite state, and infinite state.  An infinite state that is a simple counter of the number of values returned is probably acceptable, a generator that requires storing the whole sequence is not.  (Hmm.  The generators in http://www.cs.ox.ac.uk/people/jeremy.gibbons/publications/spigot.pdf for Pi have a state of k integers for some k.  Of course, these are unbounded integers which will eventually require an array of finite integers to represent.  (Multiprecision arithmetic)  I think that is acceptable.

However, there is another problem with using the digits (binary, decimal, or hexadecimal) of Pi.  There is only one such sequence, so every program that uses it should start where other programs (in particular reruns of the same simulation) left off.  Choosing an n, then calulating ln n or e^n provides a seed that can be different for each run.

Is this discussion more than just idle chatter?  I think so.  Some of the spigot algorithms Paul Rubin points to are practical, given the speed of machines today.  Even if they are not quite, you can use a transcendental PRNG to seed a very long period non-trancendental generator every k values. Also more practical, if you are running a simulation on thousands of CPU cores, you can use a trancendental PRNG to seed each CPUs PRNG, or better reseed every n steps of the simulation.  (Note that you do not need to distribute the new seeds, they can be generated locally.  Again, a trancendental generator with a parameter or parameters is the next thing to look for. ;-)

^ permalink raw reply	[relevance 5%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-10-01  3:35  6%         ` Robert Eachus
@ 2016-10-01  3:59  7%           ` Paul Rubin
  2016-10-01 14:23  5%             ` Robert Eachus
  0 siblings, 1 reply; 106+ results
From: Paul Rubin @ 2016-10-01  3:59 UTC (permalink / raw)


Robert Eachus <rieachus@comcast.net> writes:
>> aren't *all* PRNGs cyclic?
> No, a simple counter-example is a generator that uses the digits of
> pi.  The digits of any transcendental number will do. 

I don't see how this would work--to never cycle, it would need infinite
internal state.  You could consider the digits of pi to be part of the
state, but to count off the digits, you need a counter of infinite
width.

> But about how to implement it so that you don't have arbitrary pauses.

https://en.wikipedia.org/wiki/Spigot_algorithm


^ permalink raw reply	[relevance 7%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-29  9:42  7%       ` Some Dude
@ 2016-10-01  3:35  6%         ` Robert Eachus
  2016-10-01  3:59  7%           ` Paul Rubin
  0 siblings, 1 reply; 106+ results
From: Robert Eachus @ 2016-10-01  3:35 UTC (permalink / raw)


On Thursday, September 29, 2016 at 5:42:17 AM UTC-4, Some Dude wrote:
> To add to Bruce's comment, aren't *all* PRNGs cyclic? I was always under this impression, but admittedly never looked for a proof.

No, a simple counter-example is a generator that uses the digits of pi.  The digits of any transcendental number will do. I'll have to think about generator based on a square root. (Not about whether it would work, it would.  But about how to implement it so that you don't have arbitrary pauses.  Hmm.  One task to generate the root?  Managing priorities could be tricky.)

^ permalink raw reply	[relevance 6%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-26 18:48  5%     ` brbarkstrom
@ 2016-09-29  9:42  7%       ` Some Dude
  2016-10-01  3:35  6%         ` Robert Eachus
  0 siblings, 1 reply; 106+ results
From: Some Dude @ 2016-09-29  9:42 UTC (permalink / raw)


To add to Bruce's comment, aren't *all* PRNGs cyclic? I was always under this impression, but admittedly never looked for a proof.


^ permalink raw reply	[relevance 7%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-26 13:04  5%   ` Robert Eachus
@ 2016-09-26 18:48  5%     ` brbarkstrom
  2016-09-29  9:42  7%       ` Some Dude
  0 siblings, 1 reply; 106+ results
From: brbarkstrom @ 2016-09-26 18:48 UTC (permalink / raw)


On Monday, September 26, 2016 at 9:04:34 AM UTC-4, Robert Eachus wrote:
> > 
> > > I hope that there is a better solution to this.  Is there?
> > 
> > Probably best consult Knuth on Random Numbers.  Complicated subject; lots
> > of numerical issues - testing involves some high-powered math.  See also
> > Park and Miller in CACM back a fer decades ago.
>  
> Sigh! I'm probably not the best expert available on random numbers (and pseudo RNGs).  But I could write a book on the inadequacies of Park and Miller, or all that has been learned since Knuth.  It is now possible to have fast PRNGs based on Blum, Blum, and Schub (https://en.wikipedia.org/wiki/Blum_Blum_Shub ) and that is now thirty year old technology. The latest includes not only cryptographically secure RNGs, but quantum cryptography which allows for seeds to be communicated without risk of evesdropping.
> 
> Most of that is more than needed for most RNGs, but there is no reason not to be at least that good. Park and Miller for example will "roll over" and start generating the same sequence again.  When it was publish this was not a big risk.  Today even "small" simulations will use more values that Park and Miller should be used to generate.
> 
> Oh, and I should probably write up a paper on using RNGs correctly.  It is silly to use an RNG that has lots of (theoretical) nice properties, then throw all that away in how you use the RNG.

Of course most of the RNG's roll over.  That's been known - and is even
referenced in Knuth.  The key question is selecting the appropriate values
for the algorithm so you can get longer cycles.  I know Park was
moving toward running multiple RNGs and then selecting one of them 
(approximately at random), but that was a long time ago.  

The National Institute for Standards and Technology (NIST) has probably
included RNG's in a note:
https://www.nist.gov/news-events/news/2014/04/nist-removes-cryptography-algorithm-random-number-generator-recommendations.  http://www.colostate.edu/~pburns/monte/rngreport.pdf doesn't have references after 2000.  The most
recent URL I could find in Wikipedia was https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator, which has
an update from Sept. 1, 2016.

Probably the place to start is the NIST URL: http://csrc.nist.gov/groups/ST/toolkit/random_number.html and then consult the last major entry on
that page for the NIST approved algorithms and their suggested validation
algorithms that include recommended statistical tests.

Bruce B.


^ permalink raw reply	[relevance 5%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-25 23:41  7% ` brbarkstrom
@ 2016-09-26 13:04  5%   ` Robert Eachus
  2016-09-26 18:48  5%     ` brbarkstrom
  0 siblings, 1 reply; 106+ results
From: Robert Eachus @ 2016-09-26 13:04 UTC (permalink / raw)


On Sunday, September 25, 2016 at 7:41:26 PM UTC-4, brbar...@gmail.com wrote:
> 
> > I hope that there is a better solution to this.  Is there?
> 
> Probably best consult Knuth on Random Numbers.  Complicated subject; lots
> of numerical issues - testing involves some high-powered math.  See also
> Park and Miller in CACM back a fer decades ago.
 
Sigh! I'm probably not the best expert available on random numbers (and pseudo RNGs).  But I could write a book on the inadequacies of Park and Miller, or all that has been learned since Knuth.  It is now possible to have fast PRNGs based on Blum, Blum, and Schub (https://en.wikipedia.org/wiki/Blum_Blum_Shub ) and that is now thirty year old technology. The latest includes not only cryptographically secure RNGs, but quantum cryptography which allows for seeds to be communicated without risk of evesdropping.

Most of that is more than needed for most RNGs, but there is no reason not to be at least that good. Park and Miller for example will "roll over" and start generating the same sequence again.  When it was publish this was not a big risk.  Today even "small" simulations will use more values that Park and Miller should be used to generate.

Oh, and I should probably write up a paper on using RNGs correctly.  It is silly to use an RNG that has lots of (theoretical) nice properties, then throw all that away in how you use the RNG. 


^ permalink raw reply	[relevance 5%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-17 19:40 14% Ada.Numerics.Float_Random.Generator question Andrew Shvets
                   ` (2 preceding siblings ...)
  2016-09-19 19:07  4% ` rieachus
@ 2016-09-25 23:41  7% ` brbarkstrom
  2016-09-26 13:04  5%   ` Robert Eachus
  3 siblings, 1 reply; 106+ results
From: brbarkstrom @ 2016-09-25 23:41 UTC (permalink / raw)


On Saturday, September 17, 2016 at 3:40:13 PM UTC-4, Andrew Shvets wrote:
> Hello,
> 
> If I want a random float number to be generated, the way that I did this in the past was something along these lines:
> 
>   function Create_Random_Float(
>     From : in Float;
>     To : in Float)
>       return Float is
> 
>     Seed : Ada.Numerics.Float_Random.Generator;
>   begin
>     Ada.Numerics.Float_Random.Reset(Seed);
> 
>     return From + (Ada.Numerics.Float_Random.Random(Seed) * To);
>   end Create_Random_Float;
> 
> This works.  However, as I'm now looking into the Ada.Numerics.Discrete_Random package, I've noticed that it can generate a random value based on the type that is passed in.  This appeals to me and I'd like to do the same for a custom float type (say I want the delta to be 0.01.)
> 
> As Ada.Numerics.Float_Random.Generator is not a generic package, I can't use the same approach.  The best way that I can think of is to create the same result using From and To and then cast the result to the custom float type.
> 
> I hope that there is a better solution to this.  Is there?

Probably best consult Knuth on Random Numbers.  Complicated subject; lots
of numerical issues - testing involves some high-powered math.  See also
Park and Miller in CACM back a fer decades ago.

Bruce B.

^ permalink raw reply	[relevance 7%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-17 19:40 14% Ada.Numerics.Float_Random.Generator question Andrew Shvets
  2016-09-17 20:09  6% ` J-P. Rosen
  2016-09-17 21:01  6% ` Jeffrey R. Carter
@ 2016-09-19 19:07  4% ` rieachus
  2016-09-25 23:41  7% ` brbarkstrom
  3 siblings, 0 replies; 106+ results
From: rieachus @ 2016-09-19 19:07 UTC (permalink / raw)


On Saturday, September 17, 2016 at 3:40:13 PM UTC-4, Andrew Shvets wrote:
 
> This works.  However, as I'm now looking into the Ada.Numerics.Discrete_Random package, I've noticed that it can generate a random value based on the type that is passed in.  This appeals to me and I'd like to do the same for a custom float type (say I want the delta to be 0.01.)
> 
> As Ada.Numerics.Float_Random.Generator is not a generic package, I can't use the same approach.  The best way that I can think of is to create the same result using From and To and then cast the result to the custom float type.
> 
> I hope that there is a better solution to this.  Is there?

Since working has to be better, yes.  First, what you seem to be asking for is a PRNG that selects from a uniform distribution of fixed point values.  To do this take the generic discrete random package, and redeclare it with a fixed point type:

generic
   type Result_Subtype is delta <>;
package My_Fixed_Random is

   -- Basic facilities

   type Generator is limited private;

   function Random (Gen : Generator) return Result_Subtype;

   procedure Reset (Gen       : in Generator;
                    Initiator : in Integer);
   procedure Reset (Gen       : in Generator);

   -- Advanced facilities

   type State is private;

   procedure Save  (Gen        : in  Generator;
                    To_State   : out State);
   procedure Reset (Gen        : in  Generator;
                    From_State : in  State);

   Max_Image_Width : constant := implementation-defined integer value;

   function Image (Of_State    : State)  return String;
   function Value (Coded_State : String) return State;

private
   
end My_Fixed_Random;

Now in the body, put an instance of generic discrete random fit to your fixed point type:

package body My_Fixed_Random is
  type Hidden is range Int64(Result_Subtype'First/Result_Subtype'Small)     ..Int64(Result_Subtype'Last/Result_Subtype'Small);

  package Hidden_Pkg is new Ada.Numerics.Discrete_Random(Hidden);

  Complete with the operations from My_Fixed_Random, multiplying by 'Small and converting to Result_Subtype where needed. All done. ;-)  I wish I had gotten this package added to the Numerics section, as you can see it is about a page of very easy code.  But there were lots of other issues that needed resolving, and not enough time to resolve them all.

Now for the evils that I hope you never meet.  With this package, you should generate only numbers that are multiples of 'Small, and each legal value for Result_Subtype should occur with equal probability.  You might have an issue with a value next below 'First, but usually if you have a fixed point type that officially has 2^n - 1 values, you will know what to do to avoid Constraint_Error.  More troubling is that the language rules allow for fixed point types where the specified 'Small or 'Delta does not evenly divide one.  I do think that permission is right--but if you use it, you had better know a lot about numerics.

^ permalink raw reply	[relevance 4%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-17 21:01  6% ` Jeffrey R. Carter
@ 2016-09-17 23:53  7%   ` Andrew Shvets
  0 siblings, 0 replies; 106+ results
From: Andrew Shvets @ 2016-09-17 23:53 UTC (permalink / raw)


On Saturday, September 17, 2016 at 5:01:29 PM UTC-4, Jeffrey R. Carter wrote:
> On 09/17/2016 12:40 PM, Andrew Shvets wrote:
> > Hello,
> > 
> > If I want a random float number to be generated, the way that I did this in the past was something along these lines:
> > 
> >   function Create_Random_Float(
> >     From : in Float;
> >     To : in Float)
> >       return Float is
> > 
> >     Seed : Ada.Numerics.Float_Random.Generator;
> >   begin
> >     Ada.Numerics.Float_Random.Reset(Seed);
> > 
> >     return From + (Ada.Numerics.Float_Random.Random(Seed) * To);
> >   end Create_Random_Float;
> > 
> > This works.  
> 
> No, it doesn't. If From is 5 and To is 10, This gives a value in 5 .. 15.

You're right.

^ permalink raw reply	[relevance 7%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-17 19:40 14% Ada.Numerics.Float_Random.Generator question Andrew Shvets
  2016-09-17 20:09  6% ` J-P. Rosen
@ 2016-09-17 21:01  6% ` Jeffrey R. Carter
  2016-09-17 23:53  7%   ` Andrew Shvets
  2016-09-19 19:07  4% ` rieachus
  2016-09-25 23:41  7% ` brbarkstrom
  3 siblings, 1 reply; 106+ results
From: Jeffrey R. Carter @ 2016-09-17 21:01 UTC (permalink / raw)


On 09/17/2016 12:40 PM, Andrew Shvets wrote:
> Hello,
> 
> If I want a random float number to be generated, the way that I did this in the past was something along these lines:
> 
>   function Create_Random_Float(
>     From : in Float;
>     To : in Float)
>       return Float is
> 
>     Seed : Ada.Numerics.Float_Random.Generator;
>   begin
>     Ada.Numerics.Float_Random.Reset(Seed);
> 
>     return From + (Ada.Numerics.Float_Random.Random(Seed) * To);
>   end Create_Random_Float;
> 
> This works.  

No, it doesn't. If From is 5 and To is 10, This gives a value in 5 .. 15.

However, as I'm now looking into the Ada.Numerics.Discrete_Random package, I've
noticed that it can generate a random value based on the type that is passed in.
 This appeals to me and I'd like to do the same for a custom float type (say I
want the delta to be 0.01.)
> 
> As Ada.Numerics.Float_Random.Generator is not a generic package, I can't use the same approach.  The best way that I can think of is to create the same result using From and To and then cast the result to the custom float type.

The PragmAda Reusable Components contain several RNGs, all of which can be used
to obtain random values of user-defined floating-point types. You can find them at

https://github.com/jrcarter/PragmARC

-- 
Jeff Carter
"C++ is like jamming a helicopter inside a Miata
and expecting some sort of improvement."
Drew Olbrich
51

^ permalink raw reply	[relevance 6%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-17 20:09  6% ` J-P. Rosen
@ 2016-09-17 20:14  7%   ` Andrew Shvets
  0 siblings, 0 replies; 106+ results
From: Andrew Shvets @ 2016-09-17 20:14 UTC (permalink / raw)


On Saturday, September 17, 2016 at 4:10:03 PM UTC-4, J-P. Rosen wrote:
> Le 17/09/2016 à 21:40, Andrew Shvets a écrit :
> > This works.  However, as I'm now looking into the
> > Ada.Numerics.Discrete_Random package, I've noticed that it can
> > generate a random value based on the type that is passed in.  This
> > appeals to me and I'd like to do the same for a custom float type
> > (say I want the delta to be 0.01.)
> 
> Beware! Random number generators are tricky. It took megabytes of
> discussion to come to the conclusion that it was not possible to make a
> proper discrete generator out of a floating point generator...
> 
> Now, if you want a delta of 0.01, it looks more like a fixed point than
> a floating point. This can be easily achieved by instantiating
> discrete_random on an integer type with the proper number of values and
> then multiplying by 0.01.
> -- 
> J-P. Rosen
> Adalog
> 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
> Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
> http://www.adalog.fr

So, basically, there is no equally elegant solution for floats as there is for Ada.Numerics.Discrete_Random and integer types.

That's unfortunate.

^ permalink raw reply	[relevance 7%]

* Re: Ada.Numerics.Float_Random.Generator question
  2016-09-17 19:40 14% Ada.Numerics.Float_Random.Generator question Andrew Shvets
@ 2016-09-17 20:09  6% ` J-P. Rosen
  2016-09-17 20:14  7%   ` Andrew Shvets
  2016-09-17 21:01  6% ` Jeffrey R. Carter
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 106+ results
From: J-P. Rosen @ 2016-09-17 20:09 UTC (permalink / raw)


Le 17/09/2016 à 21:40, Andrew Shvets a écrit :
> This works.  However, as I'm now looking into the
> Ada.Numerics.Discrete_Random package, I've noticed that it can
> generate a random value based on the type that is passed in.  This
> appeals to me and I'd like to do the same for a custom float type
> (say I want the delta to be 0.01.)

Beware! Random number generators are tricky. It took megabytes of
discussion to come to the conclusion that it was not possible to make a
proper discrete generator out of a floating point generator...

Now, if you want a delta of 0.01, it looks more like a fixed point than
a floating point. This can be easily achieved by instantiating
discrete_random on an integer type with the proper number of values and
then multiplying by 0.01.
-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


^ permalink raw reply	[relevance 6%]

* Ada.Numerics.Float_Random.Generator question
@ 2016-09-17 19:40 14% Andrew Shvets
  2016-09-17 20:09  6% ` J-P. Rosen
                   ` (3 more replies)
  0 siblings, 4 replies; 106+ results
From: Andrew Shvets @ 2016-09-17 19:40 UTC (permalink / raw)


Hello,

If I want a random float number to be generated, the way that I did this in the past was something along these lines:

  function Create_Random_Float(
    From : in Float;
    To : in Float)
      return Float is

    Seed : Ada.Numerics.Float_Random.Generator;
  begin
    Ada.Numerics.Float_Random.Reset(Seed);

    return From + (Ada.Numerics.Float_Random.Random(Seed) * To);
  end Create_Random_Float;

This works.  However, as I'm now looking into the Ada.Numerics.Discrete_Random package, I've noticed that it can generate a random value based on the type that is passed in.  This appeals to me and I'd like to do the same for a custom float type (say I want the delta to be 0.01.)

As Ada.Numerics.Float_Random.Generator is not a generic package, I can't use the same approach.  The best way that I can think of is to create the same result using From and To and then cast the result to the custom float type.

I hope that there is a better solution to this.  Is there?


^ permalink raw reply	[relevance 14%]

* Re: Quick Sort in Rosetta Code
  @ 2016-02-10 10:16  6%   ` gautier_niouzes
  0 siblings, 0 replies; 106+ results
From: gautier_niouzes @ 2016-02-10 10:16 UTC (permalink / raw)


I did not dig too far into the fixing (the tricky thing is to avoid going out of range with indices) but here is, as an inspiration, a simplified case where the index type is integer, and this one is working (I've taken the C version to start with):

with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;

--with Ada.Text_IO; use Ada.Text_IO;

procedure Qsort is

  type Item_array is array(Integer Range <>) of Float;

  procedure Quick_sort (a: in out Item_array) is
    n: Integer:= a'Length;
    i, j: Integer;
    p, t: Float;
  begin
    if n < 2 then
      return;
    end if;
    p := a(n / 2 + a'First);
    i:= 0;
    j:= n - 1;
    loop
      while a(i + a'First) < p loop
        i:= i + 1;
      end loop;
      while p < a(j + a'First) loop
        j:= j - 1;
      end loop;
      exit when i >= j;
      t := a(i + a'First);
      a(i + a'First) := a(j + a'First);
      a(j + a'First) := t;
      i:= i + 1;
      j:= j - 1;
    end loop;
    Quick_sort(a(a'First .. a'First + i - 1));
    Quick_sort(a(a'First + i .. a'Last));
  end;

  gen: Generator;

begin
  Reset(gen);
  for n in 1..100 loop
    for round in 1..500 loop
      declare
        start: Integer:= Integer(10.0 * (Random(gen)-0.5));
        a: Item_array(start .. start + n - 1);
      begin
        for i in a'Range loop
          a(i):= Random(gen);
        end loop;
        Quick_sort(a);
        for i in a'Range loop
          -- Put_Line(Float'Image(a(i)));
          if i > a'First and then a(i-1) > a(i) then
            raise Program_Error;  --  Buggy sorting
          end if;
        end loop;
      end;
    end loop;
  end loop;
end;
_________________________ 
Gautier's Ada programming 
http://sf.net/users/gdemont/ 

^ permalink raw reply	[relevance 6%]

* Re: Ada e-books
  2015-11-19 18:19  4%         ` Jeffrey R. Carter
@ 2015-11-19 19:44  0%           ` Serge Robyns
  0 siblings, 0 replies; 106+ results
From: Serge Robyns @ 2015-11-19 19:44 UTC (permalink / raw)


On Thursday, 19 November 2015 19:19:49 UTC+1, Jeffrey R. Carter  wrote:
> The Kindle app on Android tablets works well. I've heard that Calibre can
> convert AZW to EPUB, but unless you've done it before you probably won't want to
> buy a book
> 

Precisely!  If I buy it will take the paper version.  I do love paper books but e-books are convenient when you travel.

> The Rosen trick is used to gain write access to an in-mode parameter. It was
> needed pre-Ada 12 to simulate in-out mode parameters to functions; Ada 12 allows
> such parameters so it is not needed as much. An example is the Generator passed
> to a random-number function such as Ada.Numerics.Float_Random.Random, specified as
> 

And I thought I was also used to implement some kind of multiple inheritance with containers.  I'll open a new discussion with why I've been looking into it.

Thanks.

^ permalink raw reply	[relevance 0%]

* Re: Ada e-books
  @ 2015-11-19 18:19  4%         ` Jeffrey R. Carter
  2015-11-19 19:44  0%           ` Serge Robyns
  0 siblings, 1 reply; 106+ results
From: Jeffrey R. Carter @ 2015-11-19 18:19 UTC (permalink / raw)


On 11/19/2015 02:41 AM, Serge Robyns wrote:
> 
> I did indeed find the LRM e-book and this is why I've been asking for the
> 2012 AARM (I'll add 2A's to avoid confusion).  I'm interested in the
> annotated version in e-book format.  I want to try to read it as I've been
> facing a few issues, miscomprehension, etc. in the hope to understand better
> some 'particularities' and things like the Rosen trick and others.

The ARM and AARM are available at

http://www.ada-auth.org/arm.html

in HTML, PDF, and text versions. I'm not aware of any e-book versions of the
AARM. Most e-readers can display PDFs.

The title of the document is /Ada Reference Manual/, which is why many of us
refer to it as the ARM and interpret the A in ARM as "Ada". It's sometimes
referred to as the RM or LRM, which naturally lead to the questions, "RM for
what?" and "Which language?", which in this context are both answered, "Ada." So
yes, you need to say AARM here to refer to the Annotated ARM.

> I do agree with another post about the price of Programming in Ada 2012.
> However the Kindle format is reasonably priced, but then I don't have a
> Kindle.

The Kindle app on Android tablets works well. I've heard that Calibre can
convert AZW to EPUB, but unless you've done it before you probably won't want to
buy a book

The Rosen trick is used to gain write access to an in-mode parameter. It was
needed pre-Ada 12 to simulate in-out mode parameters to functions; Ada 12 allows
such parameters so it is not needed as much. An example is the Generator passed
to a random-number function such as Ada.Numerics.Float_Random.Random, specified as

function Random (Gen : Generator) return Uniformly_Distributed;

An example of its use can be found in pkg PragmARC.Threefry_Random:

   type Generator is tagged limited private;

   function Random (State : in Generator) return Unsigned_32;
...
   type Generator_Ptr is access all Generator;

   type Generator_Handle (State : Generator_Ptr) is limited null record;

   type Generator is new Ada.Finalization.Limited_Controlled with record
      Handle  : Generator_Handle (State => Generator'Unchecked_Access);
         -- The Rosen Trick
      Key     : Unsigned_256;
      State   : Unsigned_256;
      Output  : Unsigned_256;
      Counter : Natural;
   end record;

Write access to the State parameter of Random can be obtained though

      S : Generator renames State.Handle.State.all;

The PragmARCs are available at

https://pragmada.x10hosting.com/pragmarc.htm

PragmARC.Threefry_Random is only part of the version for ISO/IEC 8652:2007.

-- 
Jeff Carter
"Go and boil your bottoms."
Monty Python & the Holy Grail
01


^ permalink raw reply	[relevance 4%]

* Re: How to shuffle/jumble letters of a given word?
  2015-06-29  8:05  5%     ` Simon Wright
@ 2015-06-29  8:13  0%       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 106+ results
From: Dmitry A. Kazakov @ 2015-06-29  8:13 UTC (permalink / raw)


On Mon, 29 Jun 2015 09:05:50 +0100, Simon Wright wrote:

> "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> writes:
> 
>> On 06/28/2015 02:07 PM, Simon Wright wrote:
>>> 
>>> Then, given a String, create an Elements array with each Key a new
>>> random number and each Ch the corresponding character in the String;
>>> sort it (which, since the Keys were random, is effectively a shuffle);
>>> and return a String formed of the Chs in their new order.
>>
>> You could also just sort the String.
> 
> I don't see how this would work?
> 
> Though I see I made myself less than clear. At the risk of solving even
> more of the OP's problem for her than I already have,
> 
>       Keyed : Elements (Str'Range);
>    begin
>       for J in Str'Range loop
>          Keyed (J) := (Ada.Numerics.Float_Random.Random (Gen), Str (J));

It should be non-repeating random numbers in this case, provided
"shuffling" meant permutation.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[relevance 0%]

* Re: How to shuffle/jumble letters of a given word?
  @ 2015-06-29  8:05  5%     ` Simon Wright
  2015-06-29  8:13  0%       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 106+ results
From: Simon Wright @ 2015-06-29  8:05 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> writes:

> On 06/28/2015 02:07 PM, Simon Wright wrote:
>> 
>> Then, given a String, create an Elements array with each Key a new
>> random number and each Ch the corresponding character in the String;
>> sort it (which, since the Keys were random, is effectively a shuffle);
>> and return a String formed of the Chs in their new order.
>
> You could also just sort the String.

I don't see how this would work?

Though I see I made myself less than clear. At the risk of solving even
more of the OP's problem for her than I already have,

      Keyed : Elements (Str'Range);
   begin
      for J in Str'Range loop
         Keyed (J) := (Ada.Numerics.Float_Random.Random (Gen), Str (J));
      end loop;
      Sort (Keyed);

^ permalink raw reply	[relevance 5%]

* Re: How to shuffle/jumble letters of a given word?
  @ 2015-06-28 21:07  4% ` Simon Wright
    0 siblings, 1 reply; 106+ results
From: Simon Wright @ 2015-06-28 21:07 UTC (permalink / raw)


Trish Cayetano <trishacayetano@gmail.com> writes:

> I am creating a "text twist game" where you guess the words in a
> jumbled manner. How do I set the code to shuffle the letters?
>
> Example: word to be guessed is HELLO
>
> What should be displayed is: LOLEH or LELHO

You want to take the letters in a random order, so you'll find
Ada.Numerics.Float_Random[1] useful.

You can't just take the random'th character of the original string,
because you mustn't take the same character twice.

One (possibly heavyweight) approach would be to create a new type
containing a float and a character,

   type Item is record
      Key : Float;
      Ch  : Character;
   end record;

and a type for an array of Items, rather like the String you want to
jumble,

   type Elements is array (Positive range <>) of Item;

and then instantiate Ada.Containers.Generic_Array_Sort[2] for Elements.
You'll need a function "<" to compare two Items on the basis of their
Keys, e.g.

   function "<" (L, R : Item) return Boolean is (L.Key < R.Key);

Then, given a String, create an Elements array with each Key a new
random number and each Ch the corresponding character in the String;
sort it (which, since the Keys were random, is effectively a shuffle);
and return a String formed of the Chs in their new order.

[1] http://www.ada-auth.org/standards/12rm/html/RM-A-5-2.html
[2] http://www.ada-auth.org/standards/12rm/html/RM-A-18-26.html#p2

^ permalink raw reply	[relevance 4%]

* Re: Lotto simulation
  @ 2014-06-16 11:15  6%         ` Stefan.Lucks
  0 siblings, 0 replies; 106+ results
From: Stefan.Lucks @ 2014-06-16 11:15 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 2730 bytes --]

On Mon, 16 Jun 2014, J-P. Rosen wrote:

>> but mathematically, given a uniformly
>> distributed real number F between 0.0 and 1.0, one can get a uniformly
>> distributed discrete D between Low and high: D := Truncate(Low + F *
>> (High-Low + 1)).
> I think it all depends on the definition of "uniformly distributed". If
> it is uniformly distributed among all representable floating point
> numbers (which you get if you take an integer random number and
> unchecked-convert it to Float), you'll get many more values below 0.5
> than above (since the range 0.5..1.0 is represented with only one value
> of the exponent).

Well, do you think the Annotated Reference Manual 
<http://www.ada-auth.org/standards/12aarm/html/AA-A-5-2.html> needs a 
clarification? It explicitely tells

   A sufficiently long sequence of random numbers obtained by successive
   calls to Random is approximately uniformly distributed over the range of
   the result subtype.

From my point of view, "uniformly distributed over the range of the result 
subtype" would seem to imply values > 0.5 to be as often as values < 0.5.

In fact, I would claim that any random generator, choosing floats between 
0.0 and 1.0 with a significant bias towards 0.0 or 1.0 would be plain 
stupid and worse than useless, and a standard which allows that, would 
need urgent repair!

Fortunately, my Ada compiler (gnat) is not such stupid and behaves as I 
had expected:

with Ada.Text_IO, Ada.Numerics.Float_Random, Ada.Command_Line;

procedure Test_Rnd is

    package ANFR renames Ada.Numerics.Float_Random;
    Gen: ANFR.Generator;

    High: Natural := 0;
    Sample_Size: constant Natural := Natural'Value(Ada.Command_Line.Argument(1));
begin
    ANFR.Reset(Gen);
    for I in 1 .. Sample_Size loop
       if ANFR.Random(Gen) > 0.5 then
 	 High := High + 1;
       end if;
    end loop;

    Ada.Text_IO.Put_Line(Integer'Image(High) &" /"& Integer'Image(Sample_Size));
end Test_Rnd;

Compiling and running the above program indicates an even distribution of 
values > 0.5 and <= 0.5 (i.e., there is no statistically significant 
bias):

$ ./test_rnd 100000000
  49999482 / 100000000
$ ./test_rnd 1000000000
  499991845 / 1000000000

Note that the results are biased towards 0.0, but the bias is 
statistically insignificant. (It would be statistically strange, indeed, 
if *exactly* half of the random values would be below 0.5, and the other 
half would be above.)

So long

------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

^ permalink raw reply	[relevance 6%]

* Interresting difference in Normal-Returns/Expression-Functions and Extended-Returns.
@ 2013-04-22 18:27  6% Shark8
  0 siblings, 0 replies; 106+ results
From: Shark8 @ 2013-04-22 18:27 UTC (permalink / raw)


I recently ran into unexpected behavior in the differences between a normal return and an extended return [in GNAT]: namely an extended return used to generate items in an array of tasks will *ALWAYS* execute in a sequential manner whereas the array generated with an expression-function or normal return is executed simultaneously.

Is there some subtle difference in the extended return that I'm unaware of? (Is this a bug?)

--------------------
-- Experiment.adb --
--------------------
Pragma Ada_2012;

With
Ada.Text_IO,
Ada.Numerics.Float_Random
;

Procedure Experiment is

    -----------------------------------------------------
    -- RNG; This sets up random numbers for durations. --
    -----------------------------------------------------
    Package RNG is
	Function Random Return Duration;
    Private
	Use Ada.Numerics.Float_Random;
	G : Generator;
	Function Random Return Duration is
	    ( Duration( Random(G) ) );
    End RNG;
    
    Package Body RNG is
    Begin
	Ada.Numerics.Float_Random.Reset( G );
    End RNG;
    
    --------------------------------------------------
    -- Resource; Protected object handling Text-IO. --
    --------------------------------------------------
   protected Resource is
      procedure Write( Input : In String );
      procedure New_Line;
   private
   end Resource;
    
   protected body Resource is
      procedure Write( Input : In String ) is
      begin
         Ada.Text_IO.Put_Line( Input );
      end Write;

      Procedure New_Line is begin Write(""); end New_Line;
   end Resource;
    
    ---------------------------------------------------------
    -- Testing; This is the task-type we are playing with. --
    ---------------------------------------------------------
   Task Type Testing( Text : Not Null Access Constant String ) is
    end Testing;


   Task Body Testing is
      D : Duration := RNG.Random; -- Get a random duration.
    Begin
	delay  D; -- Delay for that duration.
      -- Then print the Text for the task as well as the Delay.
      Resource.Write( Text.ALL & ASCII.HT & Duration'Image(D) );
   End Testing;

    
    -- Make; these functions make an access-to-tasks for arrays.
    -- Note: these should all be equivelant.
   Function Make_EF(Input : in String) Return Not Null Access Testing is
    ( New Testing( Text => New String'(Input) ) );

   Function Make_ER(Input : in String) Return Not Null Access Testing is
   begin
      Return Result : Not Null Access Testing:= New Testing(New String'(Input));
   End Make_ER;

   Function Make_NR(Input : in String) Return Not Null Access Testing is
   begin
      Return New Testing(New String'(Input));
   End Make_NR;

    
Begin

    Resource.Write("TEST_1:"& ASCII.HT &"Expression Function");
    TEST_1:
    declare
	Function Make(Input : in String) Return Not Null Access Testing
	       Renames Make_EF;

	P : Constant Array (Positive Range <>) of
	  Not Null Access Constant Testing:=
	    ( Make("Bob"), Make("Steve"), Make("Dave"), Make("Joey") );
    begin
	null;
    end TEST_1;
    Resource.New_Line;
    Resource.Write("TEST_2:"& ASCII.HT &"Normal Return Function");
    TEST_2:
    declare
	Function Make(Input : in String) Return Not Null Access Testing
	       Renames Make_NR;

	P : Constant Array (Positive Range <>) of
	  Not Null Access Constant Testing:=
	    ( Make("Bob"), Make("Steve"), Make("Dave"), Make("Joey") );
    begin
	null;
    end TEST_2;
    Resource.New_Line;
    Resource.Write("TEST_3:"& ASCII.HT &"Extended Return Function");
    TEST_3:
    declare
	Function Make(Input : in String) Return Not Null Access Testing
	       Renames Make_ER;

	P : Constant Array (Positive Range <>) of
	  Not Null Access Constant Testing:=
	    ( Make("Bob"), Make("Steve"), Make("Dave"), Make("Joey") );
    begin
	null;
    end TEST_3;
    Resource.New_Line;
    
   Resource.Write( "Terminating." );
End Experiment;



^ permalink raw reply	[relevance 6%]

* Re: Parallel_Simulation
  2013-02-25 18:30  0%     ` Parallel_Simulation John B. Matthews
@ 2013-02-26  7:13  0%       ` Vincent LAFAGE
  0 siblings, 0 replies; 106+ results
From: Vincent LAFAGE @ 2013-02-26  7:13 UTC (permalink / raw)


Le 25/02/2013 19:30, John B. Matthews a écrit :
> In article <kgg6b2$kma$1@ccpntc8.in2p3.fr>,
>  Vincent LAFAGE <lafage@ipno.in2p3.fr> wrote:
> 
>> Le 25/02/2013 13:40, John B. Matthews a écrit :
>>> In article <kgfdsp$tb0$1@ccpntc8.in2p3.fr>,
>>>  Vincent LAFAGE <lafage@ipno.in2p3.fr> wrote:
>>>
>>>> I am interested in MonteCarlo simulation and I had translated a 
>>>> former F77 code to Ada with success, with the goal of 
>>>> parallelizing it, but one part in the algorithm still resists 
>>>> parallelization: the random number generator. I need the different 
>>>> worker to rely on independant random number generators.
>>>>
>>>> Then I found a precious example in
>>>>  RM-A-5-2 59., 60., 61.
>>>> that compiles smoothly.
>>>>
>>>> I will now attempt to check the independance of the sequence 
>>>> generated by each thread. But this kind of check is always more 
>>>> subtle than expected.
>>>>
>>>> I wonder whether there is a statement about the independance of 
>>>> such generator, in particular in the gnat implementation?
>>>
>>> You should check your implementation's required documentation and 
>>> any statements on implementation advice. For example, GNAT includes 
>>> a comment in Ada.Numerics.Float_Random.ads, and the GNAT Reference 
>>> Manual says, "The generator period is sufficiently long for the 
>>> first condition here [A.5.2(47)] to hold true."
>>
>> Thanks for the advice, but the particular doesn't exactly fit my 
>> question. I understand that the sequence is long enough. But 
>> different seeds will in the end be different starting points along 
>> the same sequence (well, at least for congruential generators, I 
>> still have to confirm it for Mersenne Twister algorithm that is 
>> used). And this would in turn lead to fine correlations between the 
>> sequences.
>>
>> The best statement I have found until now is in gnat_rm-4.6.info:
>>
>> *67*.  The minimum time interval between calls to the time-dependent 
>> Reset procedure that are guaranteed to initiate different random 
>> number sequences.  See A.5.2(45).
>>   The minimum period between reset calls to guarantee distinct
>>   series of random numbers is one microsecond.
>>
>> So I need to assert the delay between the reset of each worker in 
>> RM-A-5-2 60 to be sure that there is at least one microsecond.
> 
> IIUC, the example in A.5.2(60) uses the version of Reset that is _not_ 
> time-dependent; it initializes each Worker's generator to "a state 
> denoted by a single integer." As long as you're not using the 
> time-dependent version, I don't see how the minimum period would come 
> into play.

Indeed.

>> Would you think of another way?
> 
> If you Reset a single instance of Discrete_Random in a time-dependent 
> way and use it to generate each Worker's Initiator, as suggested in 
> A.5.2(61), I don't see much chance of correlation.

Thank you for your guidance and detailled answer!

Vincent



^ permalink raw reply	[relevance 0%]

* Re: Parallel_Simulation
  2013-02-25 17:17  0%   ` Parallel_Simulation Vincent LAFAGE
  2013-02-25 18:30  0%     ` Parallel_Simulation John B. Matthews
@ 2013-02-26  7:09  0%     ` Vincent LAFAGE
  1 sibling, 0 replies; 106+ results
From: Vincent LAFAGE @ 2013-02-26  7:09 UTC (permalink / raw)


Le 25/02/2013 18:17, Vincent LAFAGE a écrit :
> Le 25/02/2013 13:40, John B. Matthews a écrit :
>> In article <kgfdsp$tb0$1@ccpntc8.in2p3.fr>,
>>  Vincent LAFAGE <lafage@ipno.in2p3.fr> wrote:
>>
>>> I am interested in MonteCarlo simulation and I had translated a 
>>> former F77 code to Ada with success, with the goal of parallelizing 
>>> it, but one part in the algorithm still resists parallelization: the 
>>> random number generator. I need the different worker to rely on 
>>> independant random number generators.
>>>
>>> Then I found a precious example in
>>>  RM-A-5-2 59., 60., 61.
>>> that compiles smoothly.
>>>
>>> I will now attempt to check the independance of the sequence 
>>> generated by each thread. But this kind of check is always more 
>>> subtle than expected.
>>>
>>> I wonder whether there is a statement about the independance of such 
>>> generator, in particular in the gnat implementation?
>>
>> You should check your implementation's required documentation and any 
>> statements on implementation advice. For example, GNAT includes a 
>> comment in Ada.Numerics.Float_Random.ads, and the GNAT Reference Manual 
>> says, "The generator period is sufficiently long for the first condition 
>> here [A.5.2(47)] to hold true."
> 
> Thanks for the advice,
> but the particular doesn't exactly fit my question.

Ooups...
Sorry I hastened to answer while I had not read carefully enough
A.5.2(47)

 47. If the generator period is sufficiently long in relation to the
     number of distinct initiator values, then each possible value of
     Initiator passed to Reset should initiate a sequence of random
     numbers that does not, in a practical sense, overlap the sequence
     initiated by any other value. If this is not possible, then the
     mapping between initiator values and generator states should be a
     rapidly varying function of the initiator value.

I see the statement, but while Mersenne Twister algorithms provides
very, very long period (2^19937?),  I would appreciate order of
magnitudes of the subperiods.

I guess I have to test,
And read much more m(__)m

Best regards

> I understand that the sequence is long enough.
> But different seeds will in the end be different starting points along
> the same sequence (well, at least for congruential generators, I still
> have to confirm it for Mersenne Twister algorithm that is used).
> And this would in turn lead to fine correlations between the sequences.
> 
> The best statement I have found until now is in gnat_rm-4.6.info:
> 
> *67*.  The minimum time interval between calls to the time-dependent
> Reset procedure that are guaranteed to initiate different random number
> sequences.  See A.5.2(45).
>    The minimum period between reset calls to guarantee distinct series
> of random numbers is one microsecond.
> 
> So I need to assert the delay between the reset of each worker in
>    RM-A-5-2 60.
> to be sure that there is at least one microsecond.
> 
> Would you think of another way?
> 
> Best regards
> Vincent




^ permalink raw reply	[relevance 0%]

* Re: Parallel_Simulation
  2013-02-25 17:17  0%   ` Parallel_Simulation Vincent LAFAGE
@ 2013-02-25 18:30  0%     ` John B. Matthews
  2013-02-26  7:13  0%       ` Parallel_Simulation Vincent LAFAGE
  2013-02-26  7:09  0%     ` Parallel_Simulation Vincent LAFAGE
  1 sibling, 1 reply; 106+ results
From: John B. Matthews @ 2013-02-25 18:30 UTC (permalink / raw)


In article <kgg6b2$kma$1@ccpntc8.in2p3.fr>,
 Vincent LAFAGE <lafage@ipno.in2p3.fr> wrote:

> Le 25/02/2013 13:40, John B. Matthews a écrit :
> > In article <kgfdsp$tb0$1@ccpntc8.in2p3.fr>,
> >  Vincent LAFAGE <lafage@ipno.in2p3.fr> wrote:
> > 
> >> I am interested in MonteCarlo simulation and I had translated a 
> >> former F77 code to Ada with success, with the goal of 
> >> parallelizing it, but one part in the algorithm still resists 
> >> parallelization: the random number generator. I need the different 
> >> worker to rely on independant random number generators.
> >>
> >> Then I found a precious example in
> >>  RM-A-5-2 59., 60., 61.
> >> that compiles smoothly.
> >>
> >> I will now attempt to check the independance of the sequence 
> >> generated by each thread. But this kind of check is always more 
> >> subtle than expected.
> >>
> >> I wonder whether there is a statement about the independance of 
> >> such generator, in particular in the gnat implementation?
> > 
> > You should check your implementation's required documentation and 
> > any statements on implementation advice. For example, GNAT includes 
> > a comment in Ada.Numerics.Float_Random.ads, and the GNAT Reference 
> > Manual says, "The generator period is sufficiently long for the 
> > first condition here [A.5.2(47)] to hold true."
> 
> Thanks for the advice, but the particular doesn't exactly fit my 
> question. I understand that the sequence is long enough. But 
> different seeds will in the end be different starting points along 
> the same sequence (well, at least for congruential generators, I 
> still have to confirm it for Mersenne Twister algorithm that is 
> used). And this would in turn lead to fine correlations between the 
> sequences.
> 
> The best statement I have found until now is in gnat_rm-4.6.info:
> 
> *67*.  The minimum time interval between calls to the time-dependent 
> Reset procedure that are guaranteed to initiate different random 
> number sequences.  See A.5.2(45).
>   The minimum period between reset calls to guarantee distinct
>   series of random numbers is one microsecond.
> 
> So I need to assert the delay between the reset of each worker in 
> RM-A-5-2 60 to be sure that there is at least one microsecond.

IIUC, the example in A.5.2(60) uses the version of Reset that is _not_ 
time-dependent; it initializes each Worker's generator to "a state 
denoted by a single integer." As long as you're not using the 
time-dependent version, I don't see how the minimum period would come 
into play.

> Would you think of another way?

If you Reset a single instance of Discrete_Random in a time-dependent 
way and use it to generate each Worker's Initiator, as suggested in 
A.5.2(61), I don't see much chance of correlation.

-- 
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>



^ permalink raw reply	[relevance 0%]

* Re: Parallel_Simulation
  2013-02-25 12:40  5% ` Parallel_Simulation John B. Matthews
@ 2013-02-25 17:17  0%   ` Vincent LAFAGE
  2013-02-25 18:30  0%     ` Parallel_Simulation John B. Matthews
  2013-02-26  7:09  0%     ` Parallel_Simulation Vincent LAFAGE
  0 siblings, 2 replies; 106+ results
From: Vincent LAFAGE @ 2013-02-25 17:17 UTC (permalink / raw)


Le 25/02/2013 13:40, John B. Matthews a écrit :
> In article <kgfdsp$tb0$1@ccpntc8.in2p3.fr>,
>  Vincent LAFAGE <lafage@ipno.in2p3.fr> wrote:
> 
>> I am interested in MonteCarlo simulation and I had translated a 
>> former F77 code to Ada with success, with the goal of parallelizing 
>> it, but one part in the algorithm still resists parallelization: the 
>> random number generator. I need the different worker to rely on 
>> independant random number generators.
>>
>> Then I found a precious example in
>>  RM-A-5-2 59., 60., 61.
>> that compiles smoothly.
>>
>> I will now attempt to check the independance of the sequence 
>> generated by each thread. But this kind of check is always more 
>> subtle than expected.
>>
>> I wonder whether there is a statement about the independance of such 
>> generator, in particular in the gnat implementation?
> 
> You should check your implementation's required documentation and any 
> statements on implementation advice. For example, GNAT includes a 
> comment in Ada.Numerics.Float_Random.ads, and the GNAT Reference Manual 
> says, "The generator period is sufficiently long for the first condition 
> here [A.5.2(47)] to hold true."

Thanks for the advice,
but the particular doesn't exactly fit my question.
I understand that the sequence is long enough.
But different seeds will in the end be different starting points along
the same sequence (well, at least for congruential generators, I still
have to confirm it for Mersenne Twister algorithm that is used).
And this would in turn lead to fine correlations between the sequences.

The best statement I have found until now is in gnat_rm-4.6.info:

*67*.  The minimum time interval between calls to the time-dependent
Reset procedure that are guaranteed to initiate different random number
sequences.  See A.5.2(45).
   The minimum period between reset calls to guarantee distinct series
of random numbers is one microsecond.

So I need to assert the delay between the reset of each worker in
   RM-A-5-2 60.
to be sure that there is at least one microsecond.

Would you think of another way?

Best regards
Vincent



^ permalink raw reply	[relevance 0%]

* Re: Parallel_Simulation
  @ 2013-02-25 12:40  5% ` John B. Matthews
  2013-02-25 17:17  0%   ` Parallel_Simulation Vincent LAFAGE
  0 siblings, 1 reply; 106+ results
From: John B. Matthews @ 2013-02-25 12:40 UTC (permalink / raw)


In article <kgfdsp$tb0$1@ccpntc8.in2p3.fr>,
 Vincent LAFAGE <lafage@ipno.in2p3.fr> wrote:

> I am interested in MonteCarlo simulation and I had translated a 
> former F77 code to Ada with success, with the goal of parallelizing 
> it, but one part in the algorithm still resists parallelization: the 
> random number generator. I need the different worker to rely on 
> independant random number generators.
> 
> Then I found a precious example in
>  RM-A-5-2 59., 60., 61.
> that compiles smoothly.
> 
> I will now attempt to check the independance of the sequence 
> generated by each thread. But this kind of check is always more 
> subtle than expected.
> 
> I wonder whether there is a statement about the independance of such 
> generator, in particular in the gnat implementation?

You should check your implementation's required documentation and any 
statements on implementation advice. For example, GNAT includes a 
comment in Ada.Numerics.Float_Random.ads, and the GNAT Reference Manual 
says, "The generator period is sufficiently long for the first condition 
here [A.5.2(47)] to hold true."

-- 
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>



^ permalink raw reply	[relevance 5%]

* Re: A thicker binding for Lapack
  @ 2012-12-29 19:59  7%     ` Simon Wright
  0 siblings, 0 replies; 106+ results
From: Simon Wright @ 2012-12-29 19:59 UTC (permalink / raw)


jpwoodruff@gmail.com writes:

> Conclusion:   transpose appears necessary.

For info, the compiler (well, GNAT) will automatically transpose when
doing assignment between arrays with different conventions. And it's
quicker (not by very much at -O2, though).

with Ada.Calendar; use Ada.Calendar;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Float_Random;
with Interfaces.Fortran;
with System.Generic_Array_Operations;
procedure Sauvage_Timing is

   package BLAS is

      --  Copied from old GNAT Interfaces.Fortran.BLAS.

      --  Vector types

      type Real_Vector is array (Integer range <>)
        of Interfaces.Fortran.Real;

      type Complex_Vector is array (Integer range <>)
        of Interfaces.Fortran.Complex;

      type Double_Precision_Vector is array (Integer range <>)
        of Interfaces.Fortran.Double_Precision;

      type Double_Complex_Vector is array (Integer range <>)
        of Interfaces.Fortran.Double_Complex;

      --  Matrix types

      type Real_Matrix is array (Integer range <>, Integer range <>)
        of Interfaces.Fortran.Real;

      type Double_Precision_Matrix
         is array (Integer range <>, Integer range <>)
        of Interfaces.Fortran.Double_Precision;

      type Complex_Matrix is array (Integer range <>, Integer range <>)
        of Interfaces.Fortran.Complex;

      type Double_Complex_Matrix is array (Integer range <>, Integer range <>)
        of Interfaces.Fortran.Double_Complex;

   end BLAS;

   procedure Transpose
   is new System.Generic_Array_Operations.Transpose
     (Scalar => Interfaces.Fortran.Double_Precision'Base,
      Matrix => BLAS.Double_Precision_Matrix);

   type Double_Precision_Matrix is array (Integer range <>, Integer range <>)
     of Interfaces.Fortran.Double_Precision;
   pragma Convention (Fortran, Double_Precision_Matrix);

   A, B : BLAS.Double_Precision_Matrix (1 .. 100, 1 .. 100);
   C : Double_Precision_Matrix (1 .. 100, 1 .. 100);
   pragma Volatile (B);
   pragma Volatile (C);

   Gen : Ada.Numerics.Float_Random.Generator;

   Start, Finish : Time;

   use type Interfaces.Fortran.Double_Precision;

begin

   Ada.Numerics.Float_Random.Reset (Gen);

   for J in A'Range (1) loop
      for K in A'Range (2) loop
         A (J, K) :=
           Interfaces.Fortran.Double_Precision (J * K)
           * Interfaces.Fortran.Double_Precision
           (Ada.Numerics.Float_Random.Random (Gen));
      end loop;
   end loop;

   Start := Clock;
   for J in 1 .. 100 loop
      Transpose (A, B);
   end loop;
   Finish := Clock;
   Put_Line ("Transpose took " & Duration'Image (Finish - Start));

   Start := Clock;
   for J in 1 .. 100 loop
      C := Double_Precision_Matrix (A);
   end loop;
   Finish := Clock;
   Put_Line ("Assignment took" & Duration'Image (Finish - Start));

   declare
      Same : Boolean := True;
   begin
      for J in 1 .. 100 loop
         for K in 1 .. 100 loop
            if B (J, K) /= C (K, J) then
               Same := False;
            end if;
         end loop;
      end loop;
      Put_Line ("B = ~C: " & Same'Img);
   end;

end Sauvage_Timing;



^ permalink raw reply	[relevance 7%]

* Re: Efficient Sequential Access to Arrays
  @ 2012-07-15 21:44  5%     ` Georg Bauhaus
  0 siblings, 0 replies; 106+ results
From: Georg Bauhaus @ 2012-07-15 21:44 UTC (permalink / raw)


On 15.07.12 22:03, Keean Schupke wrote:
> On Sunday, 15 July 2012 20:48:35 UTC+1, Dmitry A. Kazakov  wrote:
>> On Sun, 15 Jul 2012 11:40:08 -0700 (PDT), Keean Schupke wrote:
>>
>> &gt; However in order to achieve this performance I needed to rework the arrays
>> &gt; as the use of Indexes was too slow.
>>
>> You have to measure it in order to know. Write two variants and compare
>> their performance.
>
> Have done, the difference is about 10k simulations per second.
>
>>
>> &gt; An example of this is lets say we are
>> &gt; accessing element 5 from array A &quot;A(5)&quot; this requires a multiplication to
>> &gt; access (base_address + index * record_size).
>>
>> It does not, because 5 is constant.
>
> Obviously the index is not actually a constant but the result of selecting a random element in the list. The multiplication is necessary for finding this first element, but the operations on relative elements (+/-1, +/-2 etc) can use addition with a pointer, not so with an index.

There is address arithmetic in System.*. For the simple case of
constant distances, something like the following might have some
hints. Or it might if redone after thinking. procedure Grab has
the multiplication for offsets of components of a record type
object in an array.

The point is that one may express offsets by referring
to type attributes that follow from representation clauses
and then convert between addresses and pointers.

with Ada.Numerics.Float_Random;    use  Ada.Numerics.Float_Random;
with System.Address_To_Access_Conversions, System.Storage_Elements;
procedure Iter_Arrays (Size : Natural) is

    Storage_Elements : constant := 1;

    type Index is mod 2**32;
    type Data is digits 6;
    for Data'Size use 32;

    G : Generator;

    type Things is record
       One: Data := Data (Random (G));
       Two: Data := Data (Random (G));
    end record;

    for Things use record
       One at 0 * Storage_Elements range 0 .. Data'Size - 1;
       Two at 4 * Storage_Elements range 0 .. Data'Size - 1;
    end record;
    pragma Assert (Things'Size = 64);

    type List is array (Index range <>) of Things;
    for List'Alignment use 4 * Storage_Elements;
    for List'Component_Size use 64;


--  using array indexing

    procedure Bumble (A : in out List; Step : Index) is
    begin
       for K in A'First + Step .. A'Last - Step loop
          declare
             Diff_Backward : constant Data := A (K).One - A (K - Step).Two;
             Diff_Forward : constant Data := A (K).Two - A (K + Step).One;
          begin
             if (abs Diff_Backward) < (abs Diff_Forward) then
                A (K).One := A (K - Step).One;
             else
                A (K).Two := A (K + Step).Two;
             end if;
          end;
       end loop;
    end Bumble;


--  using relative addresses

    package Indirection is new System.Address_To_Access_Conversions
      (Object => Data);
    subtype Data_Pointer is Indirection.Object_Pointer;


    procedure Grab  (A : in out List; Step : Index) is
       -- [A] = [one][two][one][two]...[one][two]
       use System.Storage_Elements, Indirection;
       Offset_Backward : constant Storage_Offset :=
         Storage_Offset (0 + Step * 8 + 4);
       Offset_Forward : constant Storage_Offset :=
         Storage_Offset (0 - Step * 8 + 0);
    begin
       for K in A'First + Step .. A'Last - Step loop
          declare
             Back : constant Data_Pointer :=
               To_Pointer (A (K).One'Address + Offset_Backward);
             Ahead : constant Data_Pointer :=
               To_Pointer (A (K).Two'Address + Offset_Backward);
             Diff_Backward : constant Data := A (K).One - Back.all;
             Diff_Forward : constant Data := A (K).One - Ahead.all;
          begin
             if (abs Diff_Backward) < (abs Diff_Forward) then
                A (K).One := A (K - Step).One;
             else
                A (K).Two := A (K + Step).Two;
             end if;
          end;
       end loop;
    end Grab;

    Test_Data : List (0 .. Index(Size));

begin
    Bumble (Test_Data, 2);
    Grab (Test_Data, 3);
end Iter_Arrays;



^ permalink raw reply	[relevance 5%]

* Error in gnat-4.6  (opensuse 11.4) ?
@ 2011-03-17 13:33  7% reinkor
  0 siblings, 0 replies; 106+ results
From: reinkor @ 2011-03-17 13:33 UTC (permalink / raw)


Hello there,

I did strip down my program to the following (below) in order to
communicate
a possible error in gnat-4.6 (I use opensuse 11.4 on an hp Elitebook
6930p).
Could anybody try the same?

I get the following (test1.adb is listed below):

gnatmake -gnat2012 test1.adb
gcc -c -gnat2012 test1.adb
gnatbind -x test1.ali
gnatlink test1.ali
aaa > ./test1

raised STORAGE_ERROR : stack overflow (or erroneous memory access)

If I change:   "type Real is Digits 16;"  ->  "type Real is Digits
15;"
then I do not get "stack overflow".  Similarly, if I comment out for
example the statement " fe,xe : fe_t;"

reinert


------------------program listing-----------------
with Text_IO;
use  Text_IO;

with Ada.Numerics.Float_Random;
use  Ada.Numerics.Float_Random;
use  Ada.Numerics;

procedure test1 is

   type Real is Digits 16;

   G : Float_Random.Generator;

   type f_t  is array(1..0400) of Real;
   type fe_t is array(1..1000) of Real;

   type Node_t is
     record
        f, fm : f_t;
        fe,xe : fe_t;
        x  : Real;
     end record;

   Node : array (1..200) of Node_t;

   procedure initiate_nodes is
   begin
      for i in Node'range loop
          Node(i).x := Real(Float_Random.Random(Gen => G));
      end loop;
   end initiate_nodes;

begin

   Put( " Hello World! ");

end test1;



^ permalink raw reply	[relevance 7%]

* Re: GNAT's Protected Objects
  2010-11-08 22:32  6%   ` Jeffrey Carter
@ 2010-11-09  1:50  0%     ` Anh Vo
  0 siblings, 0 replies; 106+ results
From: Anh Vo @ 2010-11-09  1:50 UTC (permalink / raw)


On Nov 8, 2:32 pm, Jeffrey Carter <spam.jrcarter....@spam.not.acm.org>
wrote:
> On 11/08/2010 02:38 PM, Anh Vo wrote:
>
>
>
> > How may tasks used, two or four, when slowness was observed when
> > compared to simple task? I will be supprised if the answer is two. It
> > is logically expected that two tasks should perform better than single
> > task. However, when it comes to four or greater task, the result may
> > not be true due to task switching cost.
>
> That's what I expected. However, any number of tasks > 1 took longer than a
> single task.
>
> > I would be glad to test it on my two core CPU mahine if the your
> > little program is posted.
>
> I have appended the code to this message. Watch for line wrapping.
>
> --
> Jeff Carter
> "Sir Robin the not-quite-so-brave-as-Sir-Lancelot,
> who had nearly fought the Dragon of Angnor,
> who nearly stood up to the vicious Chicken of Bristol,
> and who had personally wet himself at the
> Battle of Badon Hill."
> Monty Python & the Holy Grail
> 68
>
> with Ada.Exceptions;
> with Ada.Numerics.Float_Random;
> with Ada.Real_Time;
> with Ada.Text_IO;
>
> with System.Task_Info;
>
> procedure MP_Mult_PO is
>     Num_Processors : constant Positive := System.Task_Info.Number_Of_Processors;
>
>     subtype Index_Value is Integer range 1 .. 500;
>
>     type Matrix is array (Index_Value, Index_Value) of Float;
>
>     function Mult (Left : in Matrix; Right : in Matrix; Num_Tasks : in Positive)
> return Matrix;
>     -- Perform a concurrent multiplication of Left * Right using Num_Tasks tasks
>
>     function Mult (Left : in Matrix; Right : in Matrix; Num_Tasks : in Positive)
> return Matrix is
>        task type Calc_One;
>
>        protected Control is
>           procedure Get (Row : out Natural; Col : out Natural);
>           -- Returns the row and column of a result to calculate.
>           -- Returns zero for both when there are no more results to calculate.
>        private -- Control
>           Next_Row : Positive := 1;
>           Next_Col : Positive := 1;
>           Done     : Boolean  := False;
>        end Control;
>
>        Result : Matrix;
>
>        task body Calc_One is
>           Row : Natural;
>           Col : Natural;
>        begin -- Calc_One
>           All_Results : loop
>              Control.Get (Row => Row, Col => Col);
>
>              exit All_Results when Row = 0;
>
>              Result (Row, Col) := 0.0;
>
>              Sum : for K in Index_Value loop
>                 Result (Row, Col) := Result (Row, Col) + Left (Row, K) * Right
> (K, Col);
>              end loop Sum;
>           end loop All_Results;
>        exception -- Calc_One
>        when E : others =>
>           Ada.Text_IO.Put_Line (Item => "Calc_One " &
> Ada.Exceptions.Exception_Information (E) );
>        end Calc_One;
>
>        protected body Control is
>           procedure Get (Row : out Natural; Col : out Natural) is
>           begin -- Get
>              if Done then
>                 Row := 0;
>                 Col := 0;
>
>                 return;
>              end if;
>
>              Row := Next_Row;
>              Col := Next_Col;
>
>              if Next_Col < Index_Value'Last then
>                 Next_Col := Next_Col + 1;
>
>                 return;
>              end if;
>
>              Next_Col := 1;
>              Next_Row := Next_Row + 1;
>
>              Done := Next_Row > Index_Value'Last;
>           end Get;
>        end Control;
>     begin -- Mult
>        Create_Tasks : declare
>           type Task_List is array (1 .. Num_Tasks) of Calc_One;
>
>           Tasks : Task_List;
>        begin -- Create_Tasks
>           null; -- Wait for all tasks to complete
>        end Create_Tasks;
>
>        return Result;
>     exception -- Mult
>     when E : others =>
>        Ada.Text_IO.Put_Line (Item => "Mult " &
> Ada.Exceptions.Exception_Information (E) );
>
>        raise;
>     end Mult;
>
>     function Random return Float;
>
>     Gen : Ada.Numerics.Float_Random.Generator;
>
>     function Random return Float is
>     begin -- Random
>        return 200.0 * Ada.Numerics.Float_Random.Random (Gen) - 100.0; -- -100 ..
> 100.
>     end Random;
>
>     A : constant Matrix := Matrix'(others => (others => Random) );
>     B : constant Matrix := Matrix'(others => (others => Random) );
>
>     C : Matrix;
>
>     Elapsed   : Duration;
>     Prev      : Duration := Duration'Last;
>     Start     : Ada.Real_Time.Time;
>     Num_Tasks : Positive := 1;
>
>     use type Ada.Real_Time.Time;
> begin -- MP_Mult_PO
>     Ada.Text_IO.Put_Line (Item => "Num processors" & Integer'Image
> (Num_Processors) );
>
>     All_Calls : loop
>        Start := Ada.Real_Time.Clock;
>        C := Mult (A, B, Num_Tasks);
>        Elapsed := Ada.Real_Time.To_Duration (Ada.Real_Time.Clock - Start);
>        Ada.Text_IO.Put_Line (Item => Integer'Image (Num_Tasks) & ' ' &
> Duration'Image (Elapsed) );
>
>        exit All_Calls when Num_Tasks > 2 * Num_Processors and Elapsed > Prev;
>
>        Prev := Elapsed;
>        Num_Tasks := Num_Tasks + 1;
>     end loop All_Calls;
> exception -- MP_Mult_PO
> when E : others =>
>     Ada.Text_IO.Put_Line (Item => "MP_Mult_PO " &
> Ada.Exceptions.Exception_Information (E) );
> end MP_Mult_PO;

Below are the test results conducted on GNAT 2010 running on Windows
XP.

Num processors 2
 1  0.077000009
 2  0.055627741
 3  0.023719495
 4  0.018366580
 5  0.018512129

The output looks reasonable. The speed is improved up to 4 tasks. It
slows down with 5 tasks due to tasking switch. However, it is still
better than single task.

As Robert suggested, I would divide work among tasks by passing
paramter into each task. For example, in case of two tasks, one task
handles from rows 1 .. 250 while the other task handle from rows
251 .. 500. By the way, the protected singleton type Control is no
longer needed.

Anh Vo



^ permalink raw reply	[relevance 0%]

* Re: GNAT's Protected Objects
  @ 2010-11-08 22:32  6%   ` Jeffrey Carter
  2010-11-09  1:50  0%     ` Anh Vo
  0 siblings, 1 reply; 106+ results
From: Jeffrey Carter @ 2010-11-08 22:32 UTC (permalink / raw)


On 11/08/2010 02:38 PM, Anh Vo wrote:
>
> How may tasks used, two or four, when slowness was observed when
> compared to simple task? I will be supprised if the answer is two. It
> is logically expected that two tasks should perform better than single
> task. However, when it comes to four or greater task, the result may
> not be true due to task switching cost.

That's what I expected. However, any number of tasks > 1 took longer than a 
single task.

> I would be glad to test it on my two core CPU mahine if the your
> little program is posted.

I have appended the code to this message. Watch for line wrapping.

-- 
Jeff Carter
"Sir Robin the not-quite-so-brave-as-Sir-Lancelot,
who had nearly fought the Dragon of Angnor,
who nearly stood up to the vicious Chicken of Bristol,
and who had personally wet himself at the
Battle of Badon Hill."
Monty Python & the Holy Grail
68

with Ada.Exceptions;
with Ada.Numerics.Float_Random;
with Ada.Real_Time;
with Ada.Text_IO;

with System.Task_Info;

procedure MP_Mult_PO is
    Num_Processors : constant Positive := System.Task_Info.Number_Of_Processors;

    subtype Index_Value is Integer range 1 .. 500;

    type Matrix is array (Index_Value, Index_Value) of Float;

    function Mult (Left : in Matrix; Right : in Matrix; Num_Tasks : in Positive) 
return Matrix;
    -- Perform a concurrent multiplication of Left * Right using Num_Tasks tasks

    function Mult (Left : in Matrix; Right : in Matrix; Num_Tasks : in Positive) 
return Matrix is
       task type Calc_One;

       protected Control is
          procedure Get (Row : out Natural; Col : out Natural);
          -- Returns the row and column of a result to calculate.
          -- Returns zero for both when there are no more results to calculate.
       private -- Control
          Next_Row : Positive := 1;
          Next_Col : Positive := 1;
          Done     : Boolean  := False;
       end Control;

       Result : Matrix;

       task body Calc_One is
          Row : Natural;
          Col : Natural;
       begin -- Calc_One
          All_Results : loop
             Control.Get (Row => Row, Col => Col);

             exit All_Results when Row = 0;

             Result (Row, Col) := 0.0;

             Sum : for K in Index_Value loop
                Result (Row, Col) := Result (Row, Col) + Left (Row, K) * Right 
(K, Col);
             end loop Sum;
          end loop All_Results;
       exception -- Calc_One
       when E : others =>
          Ada.Text_IO.Put_Line (Item => "Calc_One " & 
Ada.Exceptions.Exception_Information (E) );
       end Calc_One;

       protected body Control is
          procedure Get (Row : out Natural; Col : out Natural) is
          begin -- Get
             if Done then
                Row := 0;
                Col := 0;

                return;
             end if;

             Row := Next_Row;
             Col := Next_Col;

             if Next_Col < Index_Value'Last then
                Next_Col := Next_Col + 1;

                return;
             end if;

             Next_Col := 1;
             Next_Row := Next_Row + 1;

             Done := Next_Row > Index_Value'Last;
          end Get;
       end Control;
    begin -- Mult
       Create_Tasks : declare
          type Task_List is array (1 .. Num_Tasks) of Calc_One;

          Tasks : Task_List;
       begin -- Create_Tasks
          null; -- Wait for all tasks to complete
       end Create_Tasks;

       return Result;
    exception -- Mult
    when E : others =>
       Ada.Text_IO.Put_Line (Item => "Mult " & 
Ada.Exceptions.Exception_Information (E) );

       raise;
    end Mult;

    function Random return Float;

    Gen : Ada.Numerics.Float_Random.Generator;

    function Random return Float is
    begin -- Random
       return 200.0 * Ada.Numerics.Float_Random.Random (Gen) - 100.0; -- -100 .. 
100.
    end Random;

    A : constant Matrix := Matrix'(others => (others => Random) );
    B : constant Matrix := Matrix'(others => (others => Random) );

    C : Matrix;

    Elapsed   : Duration;
    Prev      : Duration := Duration'Last;
    Start     : Ada.Real_Time.Time;
    Num_Tasks : Positive := 1;

    use type Ada.Real_Time.Time;
begin -- MP_Mult_PO
    Ada.Text_IO.Put_Line (Item => "Num processors" & Integer'Image 
(Num_Processors) );

    All_Calls : loop
       Start := Ada.Real_Time.Clock;
       C := Mult (A, B, Num_Tasks);
       Elapsed := Ada.Real_Time.To_Duration (Ada.Real_Time.Clock - Start);
       Ada.Text_IO.Put_Line (Item => Integer'Image (Num_Tasks) & ' ' & 
Duration'Image (Elapsed) );

       exit All_Calls when Num_Tasks > 2 * Num_Processors and Elapsed > Prev;

       Prev := Elapsed;
       Num_Tasks := Num_Tasks + 1;
    end loop All_Calls;
exception -- MP_Mult_PO
when E : others =>
    Ada.Text_IO.Put_Line (Item => "MP_Mult_PO " & 
Ada.Exceptions.Exception_Information (E) );
end MP_Mult_PO;



^ permalink raw reply	[relevance 6%]

* Re: Benchmarking
  @ 2009-08-10 20:23  6% ` Gautier write-only
  0 siblings, 0 replies; 106+ results
From: Gautier write-only @ 2009-08-10 20:23 UTC (permalink / raw)


Hello!
Here is the generic Timing procedure I'm using for "shooting-out" a
bit. The instanciation for one test holds then in one line:
  with Timing, Fasta_O, Fasta; procedure Fasta_Timing is new Timing
( 100, "Fasta 2005", "Fasta 2009", Fasta_O, Fasta);
HTH
Gautier

-- Timing of two algorithms P1, P2 (wall clock time).
-- P1 and P2 are run "runs" times (+1 as "tour de chauffe").

generic
  runs: Positive;
  n1, n2: String;
  with procedure P1;
  with procedure P2;
procedure Timing;

with Ada.Text_IO;                       use Ada.Text_IO;
with Ada.Calendar;                      use Ada.Calendar;
with Ada.Numerics.Float_Random;         use Ada.Numerics.Float_Random;

procedure Timing is
  a1,z1,a2,z2: Time;
  f, t1s,t2s: Long_Float;
  package LFIO is new Ada.Text_IO.Float_IO(Long_Float); use LFIO;
  gen: Generator;
begin
  Put_Line("Heating..."); -- Skip (most of) cache effects
  P1;
  P2;
  -- Now we start for real:
  t1s:= 0.0;
  t2s:= 0.0;
  Reset(gen);
  for run in 1..runs loop
    Put_Line(Standard_Error, "========= Run" & run'img & " of" &
runs'img);
    if Random(gen) > 0.5 then
      a1:= Clock;  P1;  z1:= Clock;
      a2:= Clock;  P2;  z2:= Clock;
    else
      a2:= Clock;  P2;  z2:= Clock;
      a1:= Clock;  P1;  z1:= Clock;
    end if;
    Put_Line(Standard_Error, "Time in seconds for...");
    Put(Standard_Error, "P1 ("&n1&"): " & Duration'Image(z1-a1));
    Put(Standard_Error, " -- average so far: ");
    Put(Standard_Error, t1s / Long_Float(run),0,5,0);
    New_Line(Standard_Error);
    Put(Standard_Error, "P2 ("&n2&"): " & Duration'Image(z2-a2));
    Put(Standard_Error, " -- average so far: ");
    Put(Standard_Error, t2s / Long_Float(run),0,5,0);
    New_Line(Standard_Error);
    f:= Long_Float(z2-a2) / Long_Float(z1-a1);
    Put(Standard_Error, "\--> time factor (T2/T1): "); Put
(Standard_Error, f,0,5,0);
    t1s:= t1s + Long_Float(z1-a1);
    t2s:= t2s + Long_Float(z2-a2);
    Put(Standard_Error, " -- average so far: ");
    Put(Standard_Error, t2s / t1s,0,5,0);
    New_Line(Standard_Error);
  end loop;
  -- Put("[press return]"); Skip_Line;
end;



^ permalink raw reply	[relevance 6%]

* Re: Randomness tests
  @ 2009-07-17 20:41  6%   ` Gautier write-only
  0 siblings, 0 replies; 106+ results
From: Gautier write-only @ 2009-07-17 20:41 UTC (permalink / raw)


Nicholas Paul Collin Gloucester:

> Please let us know your conclusions.

So - the mentioned package is indeed the "universal" random generator
from Dr. George Marsaglia, which seems to have appeared in the Ada
letters in 1988, which circulates under the name U_Rand.
According to the machine and compiler, I get a speedup from 5x to 6.8x
(net of overhead).
No more advanced tests yet...
There are a couple of others generators I've to try, e.g. the Mersenne
Twister:
http://adrianhoe.com/adrianhoe/projects/adamt19937/
or a very simple one from Peter:
http://groups.google.ch/group/comp.lang.ada/msg/cf300f84f8782702

I've just "repimped" U_Rand with generics, no more global variables
but a type Generator, and some Ada 95 A.N.Float_Random-style
"renames", which facilitates the switch between random packages, like
in this example:

  -- *** Choice of the floating-point type used for the whole
Portfolio Model:
  subtype Real is Long_Float;

  package Real_U_Rand is new U_Rand(Real);

  -- *** Choice of a random generator: A.N.F_R, or U_Rand (faster),
or...:
  package RRand renames
    -- Ada.Numerics.Float_Random;
    Real_U_Rand;

The funny thing is that RRand can be plugged in its turn into another
generic package

  package GRA is new Ada.Numerics.Generic_Real_Arrays(Real);

  package RCopulas is new Copulas(
    Real,
    RRand.Uniformly_Distributed, RRand.Generator, RRand.Random,
    GRA
  );

In case someone is interested, mail me.
Anytime soon I'll open a SourceForge project with various random
variable goodies.
_________________________________________________________
Gautier's Ada programming -- http://sf.net/users/gdemont/
NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[relevance 6%]

* Re: GNAT compiler switches and optimization
    2006-10-22  7:39  7%               ` Jeffrey R. Carter
@ 2006-10-22 15:57  4%               ` Jeffrey Creem
  1 sibling, 0 replies; 106+ results
From: Jeffrey Creem @ 2006-10-22 15:57 UTC (permalink / raw)


Followup on the bug report.

One of the comments asserted that the two programs were not equivilent 
though I am not yet 100% convinced that I believe it yet.

His recommendation was to remove a level of indirection by changing the 
way the array is declared.

    N : Positive := Positive'Value (Argument (1));
    G : Ada.Numerics.Float_Random.Generator;

    type Real_Matrix is array (1..N, 1..N) of Float;
    type Matrix_Access is access Real_Matrix;

    A,B,C : Matrix_Access;
    Start, Finish : Ada.Calendar.Time;
    Sum : Float := 0.0;
begin
    A := new Real_Matrix;
    B := new Real_Matrix;
    C := new Real_Matrix;

This does indeed substantially improve the performance (still not quite 
to FORTRAN levels). The reason I question the equilivence is that in the 
original version, the array could have been passed to a procedure that 
took in an unconstrained array (which is pretty much what I think the 
FORTRAN version would allow) while this new version would not do that.


A quick check shows the FORTRAN is now only 1.2 times faster (did not do 
the multiple run thing yet). Perhaps tonight.

I'll also attempt to take one of the threaded ones and include that as well.


Can someone that understands FORTRAN better make an argument about the 
"closeness" of this approach v.s. the other?



^ permalink raw reply	[relevance 4%]

* Re: GNAT compiler switches and optimization
  @ 2006-10-22  7:39  7%               ` Jeffrey R. Carter
  2006-10-22 15:57  4%               ` Jeffrey Creem
  1 sibling, 0 replies; 106+ results
From: Jeffrey R. Carter @ 2006-10-22  7:39 UTC (permalink / raw)


Jeffrey Creem wrote:
> 
> Actually, as a result of this, I submitted a bug report to the GCC 
> bugzilla list. You can follow progress on it here:
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29543
> 
> Interesting initial feedback is that
> 1) Not an Ada bug.
> 2) Is a FORTRAN bug
> 3) Is a backend limitation of the optimizer.
> 
> Of course, the FORTRAN one still runs correctly so I don't think most 
> users will care that it is because of a bug :)

Interesting. I've been experimenting with some variations simply out of 
curiosity and found some things that seem a bit strange. (All results 
for an argument of 800.)

Adding the Sum variable makes an important difference, as others have 
reported, in my case from 5.82 to 4.38 s. Hoisting the indexing 
calculation for the result (C) matrix location is a basic optimization, 
and I would be surprised if it isn't done. The only thing I can think of 
is that it's a cache issue: that all 3 matrices can't be kept in cache 
at once. Perhaps compiler writers would be able to make sense of this.

Previously, I found no difference between -O2 and -O3. With this change, 
-O2 is faster.

The issue of using 'range compared to using "1 .. N" makes no difference 
in my version of the program.

Something I found really surprising is that putting the multiplication 
in a procedure makes the program faster, down to 4.03 s. I have no idea 
why this would be so.

Compiled with MinGW GNAT 3.4.2, -O2, -gnatnp -fomit-frame-pointer. Run 
under Windows XP SP2 on a 3.2 GHz Pentium 4 HT with 1 GB RAM.

Here's the code:

with Ada.Numerics.Float_Random;
with Ada.Command_Line;          use Ada.Command_Line;
with Ada.Text_IO;               use Ada.Text_IO;
with Ada.Calendar;              use Ada.Calendar;

procedure Tst_Array is
    package F_IO is new Ada.Text_IO.Float_IO (Float);
    package D_IO is new Ada.Text_Io.Fixed_Io (Duration);

    N : constant Positive := Integer'Value (Argument (1) );

    type Real_Matrix is array (1 .. N, 1 .. N) of Float;
    pragma Convention (FORTRAN, Real_Matrix);

    G : Ada.Numerics.Float_Random.Generator;

    A,B : Real_Matrix :=
       (others => (others => Ada.Numerics.Float_Random.Random (G) ) );
    C : Real_Matrix := (others => (others => 0.0) );
    Start, Finish : Ada.Calendar.Time;

    procedure Multiply is
       Sum : Float;
    begin -- Multiply
       All_Rows : for Row in A'range (1) loop
          All_Columns : for Column in B'range (2) loop
             Sum := 0.0;

             All_Common : for R in A'range (2) loop
                Sum := Sum + A (Row, R) * B (R, Column);
             end loop All_Common;

             C (Row, Column) := Sum;
          end loop All_Columns;
       end loop All_Rows;
    end Multiply;
begin
    Start := Ada.Calendar.Clock;
    Multiply;
    Finish := Ada.Calendar.Clock;

    F_IO.Put (C (1, 1) );
    F_IO.Put (C (1, 2) );
    New_Line;
    F_IO.Put (C (2, 1) );
    F_IO.Put (C (2, 2) );
    New_Line;

    Put ("Time: ");
    D_IO.Put (Finish - Start);
    New_Line;
end Tst_Array;

Next, since there have been reported some meaningful speed-up of quick 
sort on a Pentium 4 HT processor by using 2 tasks, I thought I'd see 
what effect that had. With 2 tasks, I got a time of 3.70 s. That's not a 
significant speed up, about 9.1%.

Same compilation options and platform.

Here's that code:

with Ada.Numerics.Float_Random;
with Ada.Command_Line;          use Ada.Command_Line;
with Ada.Text_IO;               use Ada.Text_IO;
with Ada.Calendar;              use Ada.Calendar;

procedure Tst_Array is
    package F_IO is new Ada.Text_IO.Float_IO (Float);
    package D_IO is new Ada.Text_Io.Fixed_Io (Duration);

    N : constant Positive := Integer'Value (Argument (1) );

    type Real_Matrix is array (1 .. N, 1 .. N) of Float;
    pragma Convention (FORTRAN, Real_Matrix);

    G : Ada.Numerics.Float_Random.Generator;

    A, B : Real_Matrix :=
       (others => (others => Ada.Numerics.Float_Random.Random (G) ) );
    C : Real_Matrix := (others => (others => 0.0) );
    Start, Finish : Ada.Calendar.Time;

    procedure Multiply is
       procedure Multiply
          (Start_Row : in Positive; Stop_Row : in Positive)
       is
          Sum : Float;
       begin -- Multiply
          All_Rows : for Row in Start_Row .. Stop_Row loop
             All_Columns : for Column in B'range (2) loop
                Sum := 0.0;

                All_Common : for R in A'range (2) loop
                   Sum := Sum + A (Row, R) * B (R, Column);
                end loop All_Common;

                C (Row, Column) := Sum;
             end loop All_Columns;
          end loop All_Rows;
       end Multiply;

       task type Multiplier (Start_Row : Positive; Stop_Row : Positive);

       task body Multiplier is
          -- null;
       begin -- Multiplier
          Multiply (Start_Row => Start_Row, Stop_Row => Stop_Row);
       end Multiplier;

       Stop  : constant Positive := N / 2;
       Start : constant Positive := Stop + 1;

       Mult : Multiplier (Start_Row => 1, Stop_Row => Stop);
    begin -- Multiply
       Multiply (Start_Row => Start, Stop_Row => N);
    end Multiply;
begin
    Start := Ada.Calendar.Clock;
    Multiply;
    Finish := Ada.Calendar.Clock;

    F_IO.Put (C (1, 1) );
    F_IO.Put (C (1, 2) );
    New_Line;
    F_IO.Put (C (2, 1) );
    F_IO.Put (C (2, 2) );
    New_Line;

    Put ("Time: ");
    D_IO.Put (Finish - Start);
    New_Line;
end Tst_Array;

If I inline the inner Multiply, or put equivalent code in the task and 
the outer Mutliply, the time is much more than for the sequential 
version, presumably due to cache effects.

Since it appears you have 2 physical processors ("Dual Xeon 2.8 Ghz"), I 
would be interested in seeing what effect this concurrent version has on 
that platform. I also wonder how easy such a version would be to create 
in FORTRAN.

-- 
Jeff Carter
"Ada has made you lazy and careless. You can write programs in C that
are just as safe by the simple application of super-human diligence."
E. Robert Tisdale
72



^ permalink raw reply	[relevance 7%]

* Re: GNAT compiler switches and optimization
  2006-10-20 10:47  7% GNAT compiler switches and optimization tkrauss
                   ` (3 preceding siblings ...)
  2006-10-20 13:27  0% ` claude.simon
@ 2006-10-20 22:11  6% ` Jeffrey R. Carter
    4 siblings, 1 reply; 106+ results
From: Jeffrey R. Carter @ 2006-10-20 22:11 UTC (permalink / raw)


tkrauss wrote:
> I'm a bit stuck trying to figure out how to coax more performance
> out of some Ada code.  I suspect there is something simple (like
> compiler switches) but I'm missing it.  As an example I'm using
> a simple matrix multiply and comparing it to similar code in
> Fortran.  Unfortunately the Ada code takes 3-4 times as long.

1st, make sure you're timing the same thing. How does Ada matrix 
multiplication compare to FORTRAN? You don't know, because you're also 
timing the random number generators and I/O. Ada.Text_IO, especially, is 
quite heavy-weight compared to other languages.

Here's my version of your program:

with Ada.Numerics.Float_Random;
with Ada.Command_Line;          use Ada.Command_Line;
with Ada.Text_IO;               use Ada.Text_IO;
with Ada.Calendar;              use Ada.Calendar;

procedure Tst_Array is
    package F_IO is new Ada.Text_IO.Float_IO (Float);
    package D_IO is new Ada.Text_Io.Fixed_Io (Duration);

    N : constant Positive := Integer'Value (Argument (1) );

    type Real_Matrix is array (1 .. N, 1 .. N) of Float;
    pragma Convention (FORTRAN, Real_Matrix);

    G : Ada.Numerics.Float_Random.Generator;

    A,B : Real_Matrix :=
       (others => (others => Ada.Numerics.Float_Random.Random (G) ) );
    C : Real_Matrix := (others => (others => 0.0) );
    Start, Finish : Ada.Calendar.Time;
begin
    Start := Ada.Calendar.Clock;

    for I in A'range (1) loop
       for J in A'range (2) loop
          for R in A'range (2) loop
             C (I, J) := C (I, J) + A (I, R) * B (R, J);
          end loop;
       end loop;
    end loop;

    Finish := Ada.Calendar.Clock;

    F_IO.Put (C (1, 1) );
    F_IO.Put (C (1, 2) );
    New_Line;
    F_IO.Put (C (2, 1) );
    F_IO.Put (C (2, 2) );
    New_Line;

    Put ("Time: ");
    D_IO.Put (Finish - Start);
    New_Line;
end Tst_Array;

I compiled as

gnatmake -O3 -gnatnp -fomit-frame-pointer tst_array

With MinGW GNAT 3.4.2, Windows XP, and a 3.2 GHz Pentium 4 HT processor, 
I get

C:\Documents and Settings\All Users\Documents\Code>tst_array 800
  2.05839E+02 2.01230E+02
  2.00866E+02 1.94039E+02
Time:           5.821082831

I don't have a FORTRAN compiler for comparison. FORTRAN will probably do 
better, but I wouldn't expect the difference to be as great as your values.

-- 
Jeff Carter
"I was hobbling along, minding my own business, all of a
sudden, up he comes, cures me! One minute I'm a leper with
a trade, next minute my livelihood's gone! Not so much as a
'by your leave!' You're cured, mate. Bloody do-gooder!"
Monty Python's Life of Brian
76



^ permalink raw reply	[relevance 6%]

* Re: GNAT compiler switches and optimization
  2006-10-20 10:47  7% GNAT compiler switches and optimization tkrauss
                   ` (2 preceding siblings ...)
  2006-10-20 12:35  8% ` Dmitry A. Kazakov
@ 2006-10-20 13:27  0% ` claude.simon
  2006-10-20 22:11  6% ` Jeffrey R. Carter
  4 siblings, 0 replies; 106+ results
From: claude.simon @ 2006-10-20 13:27 UTC (permalink / raw)


with some change you could speedup your code :

First the matrix product is not optimum, you can transpose B.

Second, matrix A is used  vector by vector you can copy A (I,1..N) in a
vector, say AI and replace A(I,R) by AI(R) in the product (it is to the
compiler to see that :-( ).

By apply this change I got an ada version faster that the fortran one
(at the same -O3 optimization level).

You can make the same change to your fortran code and then search a new
trick to speedup your ada code :-).

Claude SIMON

tkrauss a écrit :

> I'm a bit stuck trying to figure out how to coax more performance
> out of some Ada code.  I suspect there is something simple (like
> compiler switches) but I'm missing it.  As an example I'm using
> a simple matrix multiply and comparing it to similar code in
> Fortran.  Unfortunately the Ada code takes 3-4 times as long.
>
> I'm using GNAT (GPL 2006) and GFortran (4.2.0) and the following
> compile options:
>
> gnat make -O3 -gnatp tst_array
> gfortran -O3 tst_array.f95
>
> Running them on 800x800 matrices (on my 2GHz laptop)
>
> for Ada: "tst_array 800" runs in 18 seconds
> for Fortran "tst_array 800" runs in 6 seconds
>
> (if I use the fortran "matmul" intrinsic the fortran time drops to
> 2.5 seconds)
>
> Note, I tried reordering the loops, removing the random calls, etc.
> none of which made huge changes.  There is something killing
> performance
> and/or a switch or two that I'm missing, but I can't seem to find it.
> Any
> thoughts?
>
>
> Here is the code:
>
>
> -- tst_array.adb
> with Ada.Numerics.Float_Random;      use Ada.Numerics.Float_Random;
> with Ada.Command_Line;               use Ada.Command_Line;
> with Ada.Text_IO;                    use Ada.Text_IO;
> with Ada.Calendar;                   use Ada.Calendar;
>
> procedure tst_array is
>    package F_IO is new Ada.Text_IO.Float_IO(Float);
>    package D_IO is new Ada.Text_Io.Fixed_Io(Duration);
>    type Real_Matrix is array(Integer range <>,Integer range <>) of
> Float;
>    type Matrix_Access is access Real_Matrix;
>
>    N    : Positive;
>    G    : Ada.Numerics.Float_Random.Generator;
>
>    A,B,C    : Matrix_Access;
>    Start, Finish : Ada.Calendar.Time;
>    Sum : Float := 0.0;
> begin
>    N := Positive'Value (Argument (1));
>    Start := Ada.Calendar.Clock;
>
>    A := new Real_Matrix(1..N, 1..N);
>    B := new Real_Matrix(1..N, 1..N);
>    C := new Real_Matrix(1..N, 1..N);
>    for I in A'range(1) loop
>       for J in A'range(2) loop
>          A(I,J) := Ada.Numerics.Float_Random.Random(G);
>          B(I,J) := Ada.Numerics.Float_Random.Random(G);
>       end loop;
>    end loop;
>
>    for I in A'range(1) loop
>       for J in A'range(2) loop
>          Sum := 0.0;
>          for R in A'range(2) loop
>             Sum := Sum + A(I,R)*B(R,J);
>          end loop;
>          C(I,J) := Sum;
>       end loop;
>    end loop;
>
>    Finish := Ada.Calendar.Clock;
>
>    F_IO.Put (C(1,1)); F_IO.Put (C(1,2)); New_Line;
>    F_IO.Put (C(2,1)); F_IO.Put (C(2,2)); New_Line;
>
>    Finish := Ada.Calendar.Clock;
>    Put ("Time: "); D_IO.Put(Finish-Start); New_Line;New_Line;
> end tst_array;
>
>
>
> -- tst_array.f95
> program test_array
>    integer,parameter :: seed = 86456
>    integer :: N
>    integer :: numArgs
>    real, dimension(:,:), allocatable :: a, b, c
>    real, dimension(:,:), allocatable :: d, e, f
>    real :: sum
>    character*100 buffer
>    real :: begin, finish
>    integer :: I, J, R
>
>    call getarg(1,buffer)
>    read(buffer,*) N
>
>    call srand(seed)
>
>    begin = second()
>
>    allocate( a(N,N) )
>    allocate( b(N,N) )
>    allocate( c(N,N) )
>    forall (I = 1:N, J = 1:N)
>       a(i,j) = rand()
>       b(i,j) = rand()
>    end forall
>
>    !c = matmul(a, b)
>    do I = 1,N
>       do J = 1,N
>          sum = 0.0
>          do R = 1,N
>             sum = sum + A(I,R)*B(R,J)
>          end do
>          C(I,J) = sum
>       end do
>    end do
>
>    print *, c(1,1), c(1,2), c(2,1), c(2,2)
>    finish = second()
>    print *, 'Time: ', (finish-begin)
>    
> end program test_array




^ permalink raw reply	[relevance 0%]

* Re: GNAT compiler switches and optimization
  2006-10-20 10:47  7% GNAT compiler switches and optimization tkrauss
    2006-10-20 12:12  5% ` Gautier
@ 2006-10-20 12:35  8% ` Dmitry A. Kazakov
  2006-10-20 13:27  0% ` claude.simon
  2006-10-20 22:11  6% ` Jeffrey R. Carter
  4 siblings, 0 replies; 106+ results
From: Dmitry A. Kazakov @ 2006-10-20 12:35 UTC (permalink / raw)


On 20 Oct 2006 03:47:44 -0700, tkrauss wrote:

> I'm a bit stuck trying to figure out how to coax more performance
> out of some Ada code.  I suspect there is something simple (like
> compiler switches) but I'm missing it.  As an example I'm using
> a simple matrix multiply and comparing it to similar code in
> Fortran.  Unfortunately the Ada code takes 3-4 times as long.
> 
> I'm using GNAT (GPL 2006) and GFortran (4.2.0) and the following
> compile options:
> 
> gnat make -O3 -gnatp tst_array
> gfortran -O3 tst_array.f95
> 
> Running them on 800x800 matrices (on my 2GHz laptop)
> 
> for Ada: "tst_array 800" runs in 18 seconds
> for Fortran "tst_array 800" runs in 6 seconds
> 
> (if I use the fortran "matmul" intrinsic the fortran time drops to
> 2.5 seconds)
> 
> Note, I tried reordering the loops, removing the random calls, etc.
> none of which made huge changes.  There is something killing
> performance
> and/or a switch or two that I'm missing, but I can't seem to find it.
> Any thoughts?
> 
> Here is the code:
[...]

Pointers + index checks I'd say. Try this:

with Ada.Numerics.Float_Random;      use Ada.Numerics.Float_Random;
with Ada.Command_Line;               use Ada.Command_Line;
with Ada.Text_IO;                    use Ada.Text_IO;
with Ada.Calendar;                   use Ada.Calendar;

procedure tst_array_2 is
   package F_IO is new Ada.Text_IO.Float_IO(Float);
   package D_IO is new Ada.Text_Io.Fixed_Io(Duration);
   type Real_Matrix is array(Integer range <>,Integer range <>) of Float;

   N    : Positive;
   G    : Ada.Numerics.Float_Random.Generator;

   Start, Finish : Ada.Calendar.Time;
   Sum : Float := 0.0;
begin
   N := Positive'Value (Argument (1));
   declare
      subtype Matrix is Real_Matrix (1..N, 1..N);
      A, B, C : Matrix;
   begin
      for I in A'range(1) loop
         for J in A'range(2) loop
            A(I,J) := Ada.Numerics.Float_Random.Random(G);
            B(I,J) := Ada.Numerics.Float_Random.Random(G);
         end loop;
      end loop;

      Start := Ada.Calendar.Clock;

      for I in A'range(1) loop
         for J in A'range(2) loop
            Sum := 0.0;
            for R in A'range(2) loop
               Sum := Sum + A(I,R)*B(R,J);
            end loop;
            C(I,J) := Sum;
         end loop;
      end loop;

      Finish := Ada.Calendar.Clock;

      F_IO.Put (C(1,1)); F_IO.Put (C(1,2)); New_Line;
      F_IO.Put (C(2,1)); F_IO.Put (C(2,2)); New_Line;
   end;
   Put ("Time: "); D_IO.Put(Finish-Start); New_Line;New_Line;
end tst_array_2;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 8%]

* Re: GNAT compiler switches and optimization
  @ 2006-10-20 12:18  5%   ` Samuel Tardieu
  0 siblings, 0 replies; 106+ results
From: Samuel Tardieu @ 2006-10-20 12:18 UTC (permalink / raw)


>>>>> "Sam" == Samuel Tardieu <sam@rfc1149.net> writes:

Sam> Still, this is a huge penaly for Ada. Unfortunately, I don't have
Sam> the time to investigate further right now. However, I would be
Sam> interested in other people findings.

Oh, also this one lowers the Ada execution time by around 10%: do not
use an unconstrained type and do not use pointers.

   N    : constant Positive := Positive'Value (Argument (1));
   G    : Ada.Numerics.Float_Random.Generator;

   type Real_Matrix is array(1 .. N, 1 .. N) of Float;
   pragma Convention (Fortran, Real_Matrix);

   A,B,C    : Real_Matrix;

And as Duncan says, you should try with a newer backend for Ada.

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/



^ permalink raw reply	[relevance 5%]

* Re: GNAT compiler switches and optimization
  2006-10-20 10:47  7% GNAT compiler switches and optimization tkrauss
  @ 2006-10-20 12:12  5% ` Gautier
  2006-10-20 12:35  8% ` Dmitry A. Kazakov
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 106+ results
From: Gautier @ 2006-10-20 12:12 UTC (permalink / raw)


tkrauss:
> I'm a bit stuck trying to figure out how to coax more performance
> out of some Ada code.  I suspect there is something simple (like
> compiler switches) but I'm missing it.  As an example I'm using
> a simple matrix multiply and comparing it to similar code in
> Fortran.  Unfortunately the Ada code takes 3-4 times as long.

One thing is already that you start the timer at the wrong place.
You should start it after filling your array with random numbers.
In the present state you compare the random generator, then your matrix 
multiplication. It is possible that Ada.Numerics.Float_Random.Random takes 
significantly more time due to Ada's quality requirements in the random 
generation.
On the other hand, switches you can try are:
  -O2 instead of -O3, -funroll-loops (usually good) -ffast-math,
  for both Ada and Fortran
  -gnatn, for Ada
Since you are measuring real time and not CPU time, you might want also to 
take a bit larger matrices in order to have disk swaps and rests of 
initializations effects statistically small.

HTH, Gautier
______________________________________________________________
Ada programming -- http://www.mysunrise.ch/users/gdm/gsoft.htm

NB: For a direct answer, e-mail address on the Web site!!



^ permalink raw reply	[relevance 5%]

* GNAT compiler switches and optimization
@ 2006-10-20 10:47  7% tkrauss
                     ` (4 more replies)
  0 siblings, 5 replies; 106+ results
From: tkrauss @ 2006-10-20 10:47 UTC (permalink / raw)


I'm a bit stuck trying to figure out how to coax more performance
out of some Ada code.  I suspect there is something simple (like
compiler switches) but I'm missing it.  As an example I'm using
a simple matrix multiply and comparing it to similar code in
Fortran.  Unfortunately the Ada code takes 3-4 times as long.

I'm using GNAT (GPL 2006) and GFortran (4.2.0) and the following
compile options:

gnat make -O3 -gnatp tst_array
gfortran -O3 tst_array.f95

Running them on 800x800 matrices (on my 2GHz laptop)

for Ada: "tst_array 800" runs in 18 seconds
for Fortran "tst_array 800" runs in 6 seconds

(if I use the fortran "matmul" intrinsic the fortran time drops to
2.5 seconds)

Note, I tried reordering the loops, removing the random calls, etc.
none of which made huge changes.  There is something killing
performance
and/or a switch or two that I'm missing, but I can't seem to find it.
Any
thoughts?


Here is the code:


-- tst_array.adb
with Ada.Numerics.Float_Random;      use Ada.Numerics.Float_Random;
with Ada.Command_Line;               use Ada.Command_Line;
with Ada.Text_IO;                    use Ada.Text_IO;
with Ada.Calendar;                   use Ada.Calendar;

procedure tst_array is
   package F_IO is new Ada.Text_IO.Float_IO(Float);
   package D_IO is new Ada.Text_Io.Fixed_Io(Duration);
   type Real_Matrix is array(Integer range <>,Integer range <>) of
Float;
   type Matrix_Access is access Real_Matrix;

   N    : Positive;
   G    : Ada.Numerics.Float_Random.Generator;

   A,B,C    : Matrix_Access;
   Start, Finish : Ada.Calendar.Time;
   Sum : Float := 0.0;
begin
   N := Positive'Value (Argument (1));
   Start := Ada.Calendar.Clock;

   A := new Real_Matrix(1..N, 1..N);
   B := new Real_Matrix(1..N, 1..N);
   C := new Real_Matrix(1..N, 1..N);
   for I in A'range(1) loop
      for J in A'range(2) loop
         A(I,J) := Ada.Numerics.Float_Random.Random(G);
         B(I,J) := Ada.Numerics.Float_Random.Random(G);
      end loop;
   end loop;

   for I in A'range(1) loop
      for J in A'range(2) loop
         Sum := 0.0;
         for R in A'range(2) loop
            Sum := Sum + A(I,R)*B(R,J);
         end loop;
         C(I,J) := Sum;
      end loop;
   end loop;

   Finish := Ada.Calendar.Clock;

   F_IO.Put (C(1,1)); F_IO.Put (C(1,2)); New_Line;
   F_IO.Put (C(2,1)); F_IO.Put (C(2,2)); New_Line;

   Finish := Ada.Calendar.Clock;
   Put ("Time: "); D_IO.Put(Finish-Start); New_Line;New_Line;
end tst_array;



-- tst_array.f95
program test_array
   integer,parameter :: seed = 86456
   integer :: N
   integer :: numArgs
   real, dimension(:,:), allocatable :: a, b, c
   real, dimension(:,:), allocatable :: d, e, f
   real :: sum
   character*100 buffer
   real :: begin, finish
   integer :: I, J, R

   call getarg(1,buffer)
   read(buffer,*) N

   call srand(seed)

   begin = second()

   allocate( a(N,N) )
   allocate( b(N,N) )
   allocate( c(N,N) )
   forall (I = 1:N, J = 1:N)
      a(i,j) = rand()
      b(i,j) = rand()
   end forall

   !c = matmul(a, b)
   do I = 1,N
      do J = 1,N
         sum = 0.0
         do R = 1,N
            sum = sum + A(I,R)*B(R,J)
         end do
         C(I,J) = sum
      end do
   end do

   print *, c(1,1), c(1,2), c(2,1), c(2,2)
   finish = second()
   print *, 'Time: ', (finish-begin)
   
end program test_array




^ permalink raw reply	[relevance 7%]

* Re: Aliasing or referencing assignment
  2005-09-09  0:20  4% Aliasing or referencing assignment David Trudgett
@ 2005-09-09  2:13  0% ` Steve
  0 siblings, 0 replies; 106+ results
From: Steve @ 2005-09-09  2:13 UTC (permalink / raw)


"David Trudgett" <wpower@zeta.org.au.nospamplease> wrote in message 
news:m3slwf3xcy.fsf@rr.trudgett...
>
> I'm having a little difficulty with assign by reference and assign by
> value (copy) semantics in a piece of code I'm working on. In the
> chunk of code that follows below, I want to avoid repeating
> "Self.List(Opponent_Win, Can_I_Play)" many times, and just replace it
> with a variable name like "C".
>
> "Self.List(Opponent_Win, Can_I_Play)" returns a Charles container
> library Vector of Unbounded_String. The assignment:
>
>      C := Self.List(Opponent_Win, Can_I_Play); -- "List" is 2D array
>

How about something like:

  declare
      C : ListElementType renames Self.List(Opponent_Win, Can_I_Play);
  begin
        ... code that uses C ...
       Append( C, To_Unbounded_String( "Blah blah" ) );
  end;


Steve
(The Duck)

> is ineffective in doing what I want because it is doing a value
> copy. I've tried to turn the type definition of "C" into an access
> type, but with no success. I also tried the "To_Access" function (in
> charles.vectors.unbounded), but that returns a reference to an
> "Element_Array" and not a Container_Type with which I can use
> "Append".
>
> Anyway, here is the code:
>
>
>
>   procedure Initialize (Self : in out Comments)
>   is
>      C : String_List.Container_Type;
>      package Random_Integer is new Ada.Numerics.Discrete_Random(Integer);
>      use Random_Integer;
>      G : Generator;
>   begin
>
>      Reset(G);
>      Ada.Numerics.Float_Random.Reset(Self.PRNG, Random(G));
>
>      -- OPPONENT WIN COMMENTS
>      -- Can I Play difficulty
>      C := Self.List(Opponent_Win, Can_I_Play);
>
>      Append
>        (C, To_Unbounded_String
>         ("You're too good for me"));
>      Append
>        (C, To_Unbounded_String
>         ("How did you manage that?"));
>
>      ... and so on.
>
> That works if I then finish with:
>
>      Self.List(Opponent_Win, Can_I_Play) := C;
>
>
> But that's copy overhead I want to avoid (fifteen times, what's
> more). For the time being, I've just replaced all of the "C"s in the
> Append procedure calls with "Self.List(Opponent_Win, Can_I_Play)" (and
> variations thereof further down).
>
> How can I make "C" act like a reference to the Unbounded_String Vector?
>
> Also, is the 'To_Unbounded_String("this is a string")' really
> necessary? I thought I read in the ARM that string literals were
> defined for all the string types.
>
> Thanks,
>
> David
>
>
> P.S.
>
> Later on, I will probably read these comments from an XML file, but
> for now I'm just hard coding them into the program.
>
>
> -- 
>
> David Trudgett
> http://www.zeta.org.au/~wpower/
>
> FORTH IF HONK THEN
> 





^ permalink raw reply	[relevance 0%]

* Aliasing or referencing assignment
@ 2005-09-09  0:20  4% David Trudgett
  2005-09-09  2:13  0% ` Steve
  0 siblings, 1 reply; 106+ results
From: David Trudgett @ 2005-09-09  0:20 UTC (permalink / raw)



I'm having a little difficulty with assign by reference and assign by
value (copy) semantics in a piece of code I'm working on. In the
chunk of code that follows below, I want to avoid repeating
"Self.List(Opponent_Win, Can_I_Play)" many times, and just replace it
with a variable name like "C".

"Self.List(Opponent_Win, Can_I_Play)" returns a Charles container
library Vector of Unbounded_String. The assignment:

      C := Self.List(Opponent_Win, Can_I_Play); -- "List" is 2D array

is ineffective in doing what I want because it is doing a value
copy. I've tried to turn the type definition of "C" into an access
type, but with no success. I also tried the "To_Access" function (in
charles.vectors.unbounded), but that returns a reference to an
"Element_Array" and not a Container_Type with which I can use
"Append".

Anyway, here is the code:



   procedure Initialize (Self : in out Comments)
   is
      C : String_List.Container_Type;
      package Random_Integer is new Ada.Numerics.Discrete_Random(Integer);
      use Random_Integer;
      G : Generator;
   begin

      Reset(G);
      Ada.Numerics.Float_Random.Reset(Self.PRNG, Random(G));

      -- OPPONENT WIN COMMENTS
      -- Can I Play difficulty
      C := Self.List(Opponent_Win, Can_I_Play);

      Append
        (C, To_Unbounded_String
         ("You're too good for me"));
      Append
        (C, To_Unbounded_String
         ("How did you manage that?"));

      ... and so on.

That works if I then finish with:

      Self.List(Opponent_Win, Can_I_Play) := C;


But that's copy overhead I want to avoid (fifteen times, what's
more). For the time being, I've just replaced all of the "C"s in the
Append procedure calls with "Self.List(Opponent_Win, Can_I_Play)" (and
variations thereof further down).

How can I make "C" act like a reference to the Unbounded_String Vector?

Also, is the 'To_Unbounded_String("this is a string")' really
necessary? I thought I read in the ARM that string literals were
defined for all the string types.

Thanks,

David


P.S.

Later on, I will probably read these comments from an XML file, but
for now I'm just hard coding them into the program.


-- 

David Trudgett
http://www.zeta.org.au/~wpower/

FORTH IF HONK THEN




^ permalink raw reply	[relevance 4%]

* Re: [newbie question] tasks and protected types
  2005-04-29  4:04  5% [newbie question] tasks and protected types fabio de francesco
@ 2005-04-29  9:43  6% ` Jacob Sparre Andersen
  0 siblings, 0 replies; 106+ results
From: Jacob Sparre Andersen @ 2005-04-29  9:43 UTC (permalink / raw)


Fabio de Francesco wrote:

[...]

>     G : Generator;

Global objects are a _very_ bad idea when doing tasking.  Move it into
your task type.

>     task body Door is
>         Msg : String := "";

Here you make the lenght of the string Msg 0.

>         Val : Positive;
>         Times : Positive;
>     begin
>         accept Start( Str : in String; Tm : in Positive ) do
>             Msg := Str;

And here you try to assign a string of length 6 to a string of length
0.  It will fail with a Constraint_Error, but with tasking you don't
always see the exceptions.

And then I also prefer to keep the printing to a single protected
object.

Here's a modified version of your program using the advice above (and
my pretty-printing style):

-----
with Ada.Text_IO, Ada.Numerics.Float_Random;
use Ada.Numerics.Float_Random;

procedure Manage is

   protected Printer is
      procedure Put_Line (Item : in     String);
   end Printer;

   protected body Printer is
      procedure Put_Line (Item : in     String) is
      begin
         Ada.Text_IO.Put_Line (Item => Item);
         Ada.Text_IO.Flush;
      end Put_Line;
   end Printer;

   protected Tickets is
      procedure Assign (New_Value :    out Positive);
   private
      Data: Integer := 0;
   end Tickets;

   protected body Tickets is
      procedure Assign (New_Value :    out Positive) is
      begin
         Data := Data + 1;
         New_Value := Data;
      end Assign;
   end Tickets;

   subtype Message is String (1 .. 6);

   task type Door is
      entry Start (Str : in     Message;
                   Tm  : in     Positive);
   end Door;

   task body Door is
      G     : Generator;
      Msg   : Message := "      ";
      Val   : Positive;
      Times : Positive;
   begin
      Reset (G);
      accept Start (Str : in     Message;
                    Tm  : in     Positive) do
         Msg := Str;
         Times := Tm;
      end Start;
      for I in 1..Times loop
         delay Duration (Random (G));
         Tickets.Assign (Val);
         Printer.Put_Line (Msg & " counts " & Natural'Image (Val));
      end loop;
   end Door;

   D1 : Door;
   D2 : Door;

begin
   D1.Start ("Task 1", 6);
   D2.Start ("Task 2", 6);
end Manage;
-----

Greetings,

Jacob
-- 
�It will not be forever. - It will just seem like it.� -- Death




^ permalink raw reply	[relevance 6%]

* [newbie question] tasks and protected types
@ 2005-04-29  4:04  5% fabio de francesco
  2005-04-29  9:43  6% ` Jacob Sparre Andersen
  0 siblings, 1 reply; 106+ results
From: fabio de francesco @ 2005-04-29  4:04 UTC (permalink / raw)


Hello,

It's the first time I have something to do with protected types and
tasks, so please forgive this newbie question.

The problem is that I have the following program that compiles without
errors but that must have some logical errors. When it is run, it hangs
endlessy. I have only copied the relevant part omitting what is
unneeded to this discussion, anyway it can be compiled without syntax
errors.

First please let me explain what I wanted it to do. I want two
concurrent tasks to get some numbered "tickets" at random intervals.
Each different "ticket" number must be given to each task without
duplication. Every time a task is provided with "ticket" the name of
the task itself and the number is showed. This is like a bank with two
doors assigning numbered tickets to entering customers in order to be
later served at the counter by showing tickets representing order of
arrival.

So I wanted to create two tasks (D1, D2) that wait to be activated with
"Start()". Each of them ask the protected object for a number at random
intervals and then show it with "Put()".

I am not even sure if it is the correct logical implementation. Please,
let me know what I am missing. I apologize you all if my poor English
prevented proper explanation of this issue.

Regards,

fmdf


-- manage.adb

with Ada.Text_IO, Ada.Numerics.Float_Random;
use Ada.Text_IO, Ada.Numerics.Float_Random;

procedure Manage is

    protected Tickets is
        procedure Assign(New_Value: out Positive);
    private
            Data: Integer := 0;
    end Tickets;

    protected body Tickets is
        procedure Assign(New_Value: out Positive) is
        begin
            Data := Data + 1;
            New_Value := Data;
        end Assign;
    end Tickets;

    G : Generator;

    task type Door is
        entry Start( Str : in String; Tm : in Positive );
    end Door;

    task body Door is
        Msg : String := "";
        Val : Positive;
        Times : Positive;
    begin
        accept Start( Str : in String; Tm : in Positive ) do
            Msg := Str;
            Times := Tm;
        end Start;
        for I in 1..Times loop
            delay( Duration( Random( G ) ) );
            Tickets.Assign( Val );
            Put( Msg & " counts " & Natural'Image( Val ) );
            Flush;
        end loop;
    end Door;

    D1 : Door;
    D2 : Door;

begin

    Reset( G );
    D1.Start( "Task 1", 6 );
    D2.Start( "Task 2", 6 );
    
end Manage;




^ permalink raw reply	[relevance 5%]

* Re: graphical output with claw
  @ 2005-04-19 21:29  7% ` tmoran
  0 siblings, 0 replies; 106+ results
From: tmoran @ 2005-04-19 21:29 UTC (permalink / raw)


>Can somebody show me an example program with claw that draws just one
>pixel in a defined color into a window?
   How about 50 pixels (a single pixel is hard to see)
with Claw,
     Claw.Basic_Window,
     Claw.Canvas;
package Pixels is
  type Window_Type is new Claw.Basic_Window.Basic_Window_Type with private;
  -- an open window of this type shows a cloud of random red dots

  procedure Open(Window   : in out Window_Type;
                 Title    : in String);

private
  type Window_Type is new Claw.Basic_Window.Basic_Window_Type with record
    Is_Active : Boolean := False;
  end record;

  procedure When_Draw(Window           : in out Window_Type;
                      Easel            : in out Claw.Canvas.Basic_Canvas_Type'Class;
                      Erase_Background : in     Boolean;
                      Area             : in     Claw.Rectangle_Type);
end Pixels;
-----------------
with Ada.Numerics.Float_Random,
     Claw.Bitmaps;
package body Pixels is

  Gen : Ada.Numerics.Float_Random.Generator;

  procedure Open(Window   : in out Window_Type;
                 Title    : in String) is
  begin
    Create(Window, Title);
    Show(Window, Claw.Codes.Show_Startup);
    Window.Is_Active := True;
    Update(Window);
  end Open;

  procedure When_Draw(Window           : in out Window_Type;
                      Easel            : in out Claw.Canvas.Basic_Canvas_Type'Class;
                      Erase_Background : in     Boolean;
                      Area             : in     Claw.Rectangle_Type) is
    use Ada.Numerics.Float_Random;
  begin
    if Window.Is_Active then
      for i in 1 .. 50 loop
        Claw.Bitmaps.Set_Pixel(Easel,
                               (X=>Claw.Int(10.0+40.0*Random(Gen)),
                                Y=>Claw.Int(10.0+20.0*Random(Gen))),
                               Claw.Colors.RGB(Red=>255,Blue=>0,Green=>0));
      end loop;
    end if;
  end When_Draw;

end Pixels;
-----------------
with Claw,
     Pixels;
procedure Showdots is
  A_Window : Pixels.Window_Type;
begin
  Pixels.Open(A_Window,"Simple Example");
  delay 10.0;
end Showdots;



^ permalink raw reply	[relevance 7%]

* Re: question on tasks
  @ 2004-09-18 10:21  7% ` Martin Dowie
  0 siblings, 0 replies; 106+ results
From: Martin Dowie @ 2004-09-18 10:21 UTC (permalink / raw)


"Peter Walker" <p.walker@trinet.com> wrote in message 
news:414bf572@dnews.tpgi.com.au...
> Hi, is it possible to have a task do the following two things 
> simultaneously:

No _exactly_ at the same time but I think I know what you mean...

...is this what you're after?

with Ada.Numerics.Float_Random; use Ada.Numerics;
with Ada.Text_Io; use Ada.Text_Io;
procedure Peter is
   type Location is (Alpha, Beta);
   package Communication_Buffer is
      procedure C1 (A, B : Integer; C : String);
   end Communication_Buffer;
   package body Communication_Buffer is
      procedure C1 (A, B : Integer; C : String) is
      begin
         Put_Line ("C1 got [" & C & "]");
      end C1;
   end Communication_Buffer;
   task A is
      entry Incoming (Source : Location; Destination : Location; Message : 
String);
   end A;
   task body A is
      Done : Boolean := False;
      Messages_To_Send : Integer := 3;
      A, B : Integer := 0;
      G : Float_Random.Generator;
   begin
      while not Done loop
         select
            accept Incoming (Source : Location; Destination : Location; 
Message : String) do
               Put_Line ("Recieved message " & Message & " from " & 
Location'Image (Source));
            end Incoming;
         or
            -- delay Duration (Random_Time.Random (Seed));
            delay Duration (Float_Random.Random (G));
            if Messages_To_Send > 0 then
               Communication_Buffer.C1 (A, B, "Hello");
               Messages_To_Send := Messages_To_Send - 1;
            end if;
         end select;
      end loop;
   end A;
begin
   A.Incoming (Alpha, Beta, "foo");
end Peter;





^ permalink raw reply	[relevance 7%]

* Re: In-Out Parameters for functions
  2004-01-27 20:48  0% ` Alexandre E. Kopilovitch
@ 2004-01-28 10:16  0%   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 106+ results
From: Dmitry A. Kazakov @ 2004-01-28 10:16 UTC (permalink / raw)


On Tue, 27 Jan 2004 23:48:58 +0300 (MSK), "Alexandre E. Kopilovitch"
<aek@VB1162.spb.edu> wrote:

>Stephen Leake wrote:
>
>> > Look at this formulae:
>> > 
>> >   F(A) + G(A);
>> > 
>> > If F is permitted to change value of A then the result of the formulae may
>> > depend on order of computation. And this is obviously dangerous, because the
>> > formulae looks as typical mathematical expression, where this effect usually
>> > is not anticipated. 
>>
>> Hmm. Let F be Sqrt (Ada.Numerics.Float_Random.Random), and G be
>> Ada.Numerics.Float_Random.Random. Then we see that Ada _requires_ the
>> behavior you are describing. So it's clearly a Good Thing :).
>
>"Random" is very special case, in which an intention is quite opposite to what
>is common in normal "regular" circumstances. In "regular" circumstances we want
>the same result

And we have the *same* result, a realization of a *random* number. It
indeed does not depend on the input parameters (ideally). A program
using random numbers in turn becomes random in the sense that its code
and results are random. So we could treat Random as a constant, in a
random program. Of course Random is pseudo random, so it needs a
parameter, which is an implementation detail.

BTW, amusing A.5.2:

   procedure Reset (Gen : in Generator);  -- Reset an *IN* parameter!

but consistent with the design choice. Interestingly, that a true
Random, taking numbers from a hardware, should indeed have "in
Generator", provided, that it does not destroy the hardware just by
reading the values. (:-))

--
Regards,
Dmitry A. Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[relevance 0%]

* Re: In-Out Parameters for functions
       [not found]     ` <iSwwi50LxF@VB1162.spb.edu>
@ 2004-01-27 22:38  0%   ` Stephen Leake
  0 siblings, 0 replies; 106+ results
From: Stephen Leake @ 2004-01-27 22:38 UTC (permalink / raw)
  To: comp.lang.ada

"Alexandre E. Kopilovitch" <aek@VB1162.spb.edu> writes:

> Stephen Leake wrote:
> 
> > > Look at this formulae:
> > > 
> > >   F(A) + G(A);
> > > 
> > > If F is permitted to change value of A then the result of the
> > > formulae may depend on order of computation. And this is
> > > obviously dangerous, because the formulae looks as typical
> > > mathematical expression, where this effect usually is not
> > > anticipated.
> >
> > Hmm. Let F be Sqrt (Ada.Numerics.Float_Random.Random), and G be
> > Ada.Numerics.Float_Random.Random. Then we see that Ada _requires_ the
> > behavior you are describing. So it's clearly a Good Thing :).
> 
> "Random" is very special case, in which an intention is quite
> opposite to what is common in normal "regular" circumstances. 

Ok, fine. What is wrong with using mode "in out" for functions in
special cases?

-- 
-- Stephe




^ permalink raw reply	[relevance 0%]

* Re: In-Out Parameters for functions
       [not found]     <uhdyhq1zl.fsf@acm.org>
@ 2004-01-27 20:48  0% ` Alexandre E. Kopilovitch
  2004-01-28 10:16  0%   ` Dmitry A. Kazakov
       [not found]     ` <iSwwi50LxF@VB1162.spb.edu>
  1 sibling, 1 reply; 106+ results
From: Alexandre E. Kopilovitch @ 2004-01-27 20:48 UTC (permalink / raw)
  To: comp.lang.ada

Stephen Leake wrote:

> > Look at this formulae:
> > 
> >   F(A) + G(A);
> > 
> > If F is permitted to change value of A then the result of the formulae may
> > depend on order of computation. And this is obviously dangerous, because the
> > formulae looks as typical mathematical expression, where this effect usually
> > is not anticipated. 
>
> Hmm. Let F be Sqrt (Ada.Numerics.Float_Random.Random), and G be
> Ada.Numerics.Float_Random.Random. Then we see that Ada _requires_ the
> behavior you are describing. So it's clearly a Good Thing :).

"Random" is very special case, in which an intention is quite opposite to what
is common in normal "regular" circumstances. In "regular" circumstances we want
the same result for the same input data and we are in trouble when this does
not happen for any reason (for example, after moving to another compiler). But
when we use Random we want and expect some diversity of the results (perhaps
intermediate results), and the changes produced by the effect mentioned above
not necessary will defeat our purpose. Anyway, if you use Random for some stable
results you should always be very careful with all computations as well as with
mathematical background for them; so in such a case this effect is just a minor
(and easy) detail among various issues.




Alexander Kopilovitch                      aek@vib.usr.pu.ru
Saint-Petersburg
Russia




^ permalink raw reply	[relevance 0%]

* Re: In-Out Parameters for functions
       [not found]     ` <dSgYj40LxF@VB1162.spb.edu>
@ 2004-01-27  7:34  7%   ` Stephen Leake
  0 siblings, 0 replies; 106+ results
From: Stephen Leake @ 2004-01-27  7:34 UTC (permalink / raw)
  To: comp.lang.ada

"Alexandre E. Kopilovitch" <aek@VB1162.spb.edu> writes:

> Look at this formulae:
> 
>   F(A) + G(A);
> 
> If F is permitted to change value of A then the result of the formulae may
> depend on order of computation. And this is obviously dangerous, because the
> formulae looks as typical mathematical expression, where this effect usually
> is not anticipated. 

Hmm. Let F be Sqrt (Ada.Numerics.Float_Random.Random), and G be
Ada.Numerics.Float_Random.Random. Then we see that Ada _requires_ the
behavior you are describing. So it's clearly a Good Thing :).

Which is pretty ironic, since one reason
Ada.Numerics.Float_Random.Random is defined as a function is to
satisfy some notion of "mathematical purity". The closest the AARM
comes to saying that is in AARM A.5.2:

32.b
          Reason: The requirement for a level of indirection in
          accessing the internal state of a generator arises from the
          desire to make Random a function, rather than a procedure.

Given that Ada _requires_ that users be allowed to write expressions
with the order dependency you describe, what would be wrong with defining
Ada.Numerics.Float_Random.Random with parameter mode "in out"? 

Or, to be fully consistent, Ada.Numerics.Float_Random.Random should be
a procedure.

I'll have to remember to never add two functions of a random number
together in one expression, if I want truly portable results. I don't
think I actually do that, anyway; there are usually intermediate
values when a final result depends on more than one random number. 

But I suspect casual users of random numbers will not be worried about
precisely repeatable results from different compilers for this kind of
expression.

Users will always be able to shoot themselves in the foot. The
language should help them avoid that, but it cannot prevent it. The
language needs to find a reasonable balance between prevention of bad
effects and expressive power. In this particular case I think Ada
strayed too far to the "prevention" side. 

C++, on the other hand, is too far on the "expressive" side in
general.

-- 
-- Stephe




^ permalink raw reply	[relevance 7%]

* Re: Mutable parameter of a function (long ago was: Re: What evil would happen?)
  2004-01-03  1:56  3% ` Robert I. Eachus
@ 2004-01-03 11:18  0%   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 106+ results
From: Dmitry A. Kazakov @ 2004-01-03 11:18 UTC (permalink / raw)


Robert I. Eachus wrote:

> Alexandre E. Kopilovitch wrote:
> 
>> While I was generally satisfied with that particular idiom for the need,
>> as well as with overall explanations given around it, nevertheless a
>> feeling remained that some final bit is still missing. And now I came to
>> an idea about that missing bit, that is, which thing is actually missing,
>> and how it can be provided.
>> 
>> So, I think that the primary problem with that idiom is that it may be
>> unknown for a programmer, and the secondary problem is that it isn't
>> always easily recognizable. In general, the missing thing is a reference
>> point for this idiom.
>> 
>> Therefore it seems suitable to introduce a pragma for this purpose - to
>> provide a reference point. This pragma will not affect the code, it will
>> merely state that the idiom is used for particular parameter of the
>> subroutine:
>> 
>>   pragma Mutable(subroutine-name, parameter-name); -- or
>>   Mutable_Parameter
> 
> First, I see absolutely nothing wrong with a project using this idea,
> even if the compiler doesn't support the pragma.  Second, it would be a
> very useful pragma for portable code that uses "the Rosen trick."

No, it is better never use tricks. The Rosen trick is in general an ability
for an object to identify itself in all context, even in ones stating
something opposite about it. That is an extremely dangerous thing, which
breaks substitutability and so the contract. Is this the motivation for
exposing this potential contract violation to code maintainer using a
pragma? But that would by no means solve the problem. It would make things
only worse. It would say, look, this is an in-parameter, but wait, that was
just joking, because, here is a pragma, carefully hidden somewhere else,
that states the opposite.

> But I have a different worry.  Cases where the Rosen trick are used are
> often for performance reasons, and are almost always equivalent to
> passing an access value instead of a record as the actual parameter.
> 
> If the fix for constructors of limited types becomes part of the next
> version of Ada, there will be a better way to deal with the issue.  The
>    Generator type in Ada.Numerics.Float_Random, and
> Ada.Numerics.Discrete_Random is declared limited private, and should be.
>   The same applies to any case where this trick is appropriate.  What
> you will be able to do with constructors for limited private objects in
> Ada 0Y is to make the object created on the stack of the correct size,
> and make the actual parameter type an access type.  Yeah, I know, this
> is a different cheat that works out to the same thing, but assuming the
> compiler supports it, growing the stack to create the actual object and
> doing the necessary initializations will result in something which is
> just as efficient as the Rosen trick but results in an access parameter
> which won't be altered.  (Its target will of course.)

Yes, this would be much better than the Rosen trick, for the reasons I
mentioned above. But I do not think that people will be happy with buzzing
'Access, aliased, 'Unchecked_Access all over the program. Hopefully this
would errode the position of purists, maybe.

> In case this sounds "over the top,"  I currently have a package I use
> that creates per task generators.  Of course, in that case you may need
> to do explicit allocate and free operations to keep the officially per
> task object small, but from a user perspective what is going on in all
> cases is the same.
> 
> I certainly don't know what the correct way to deal with the issue of
> access constant parameters is.  I think I would do it by allowing
> constant subtypes for access types.  Maybe in Ada 1Z?

That should be for *all* types then! For example:

type Object is ...;
subtype Read_Only is constant Object;

But better to provide all theoretically possible variants of subtypes. That
is:

1. in-subtype (= constant = in: no inout, out operations allowed =
specialization)

2. inout-subtype (= what we presently have)

3. out-subtype (= no in, inout operations = generalization)

Then something should be done with two keywords for the *same* thing. I mean
"constant" and "in".

> I don't think we know enough to fix that issue yet.  To clarify, there
> are two issues here.  One is that you want some access values to be
> marked as accessing constants, and in other cases you want to restrict
> the use of the designated object.

What is the difference? Or you mean to go further, and additionally to
support operation disallowing:

type Ball is ...;
procedure Spin (X : in out Game'Class; Y : Ball);

subtype Plain_Ball is Object;
procedure Spin (X : in out Game'Class; Y : Plain_Ball) is null;

> I feel that there is an elegant
> solution out there, but I don't know how to fill in all the blanks yet.)

Interface inheritance for all types is one. You inherit interface of an
access type and implement it in some different way, for example, by making
all mutators illegal.

> Let me give an example (assuming some new syntax where needed:
> 
>     type Foo is ...
>     type Bar is access Foo;
>     subtype CBar is access constant Foo;
>     F: Foo;

F : aliased Foo; -- I suppose

>     CF: constant Foo;

CF : constant aliased Foo;

There is a problem with renamings. Presently

CF : Foo renames Read_Foo (Stream);

breaks the contract! The result is not Foo, but in fact, constant Foo. This
is in breach with the concept of constant/in subtypes. It should be

CF : constant Foo renames Read_Foo (Stream);

But what to do with the backward compatibility?

>     B: Bar;
>     CB: CBar;
>     procedure Some_Proc(CBP: in CBar);
>     ...
>   begin
>     B := F'Access;  --okay
>     CB := CF'Access; -- no problem
>     B := CF'Access; -- illegal?

It is contradictory! Presently in Ada substitutability errors for the
predefined subtypes (in, inout, constant etc) are statically checkable and
the code with such errors is illegal. At the same time for the user-defined
subtypes these errors are subject of run-time checks and thus the code is
legal. IF "constant" becomes a user-defined subtype, then what to do with
this? It is a real problem, I see no good solution of. For example, if we
would make that all statically checkable violations illegal, then this
would break a lot of existing code.

>     CB := F'Access; -- should be okay?

Yes.

>     B := CB; -- illegal, or a run-time check?

Same as B := CF'Access;, we have a difficult problem here.

>     CB := B; -- should be okay.
>     Some_Proc(B); --should be okay, but...
>   ...
>     procedure Some_Proc(CBP: in CBar) is
>     ...
>     begin
>       CBP.Some_Comp := New_Value; -- must be illegal.

Yes. But where you see any problem? When B is passed to Some_Proc it is
*converted* to CBar. That is.

>       ...
>     end Some_Proc;
> 
> Just too many question marks in that prototype.  I'd want to prototype
> this and try to fill in the blanks, but only after some of the bigger
> pieces of Ada 0Y have been frozen.

IMO it would be difficult to make it in a consistent way without reviewing
the ADT model in Ada. But the time will come, I hope.

-- 
Regards,
Dmitry A. Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[relevance 0%]

* Re: Mutable parameter of a function (long ago was: Re: What evil would happen?)
  @ 2004-01-03  1:56  3% ` Robert I. Eachus
  2004-01-03 11:18  0%   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 106+ results
From: Robert I. Eachus @ 2004-01-03  1:56 UTC (permalink / raw)


Alexandre E. Kopilovitch wrote:

> While I was generally satisfied with that particular idiom for the need,
> as well as with overall explanations given around it, nevertheless a feeling
> remained that some final bit is still missing. And now I came to an idea
> about that missing bit, that is, which thing is actually missing, and how it
> can be provided.
> 
> So, I think that the primary problem with that idiom is that it may be
> unknown for a programmer, and the secondary problem is that it isn't always
> easily recognizable. In general, the missing thing is a reference point for
> this idiom.
> 
> Therefore it seems suitable to introduce a pragma for this purpose - to
> provide a reference point. This pragma will not affect the code, it will
> merely state that the idiom is used for particular parameter of the
> subroutine:
> 
>   pragma Mutable(subroutine-name, parameter-name); -- or Mutable_Parameter

First, I see absolutely nothing wrong with a project using this idea, 
even if the compiler doesn't support the pragma.  Second, it would be a 
very useful pragma for portable code that uses "the Rosen trick."

But I have a different worry.  Cases where the Rosen trick are used are 
often for performance reasons, and are almost always equivalent to 
passing an access value instead of a record as the actual parameter.

If the fix for constructors of limited types becomes part of the next 
version of Ada, there will be a better way to deal with the issue.  The 
   Generator type in Ada.Numerics.Float_Random, and 
Ada.Numerics.Discrete_Random is declared limited private, and should be. 
  The same applies to any case where this trick is appropriate.  What 
you will be able to do with constructors for limited private objects in 
Ada 0Y is to make the object created on the stack of the correct size, 
and make the actual parameter type an access type.  Yeah, I know, this 
is a different cheat that works out to the same thing, but assuming the 
compiler supports it, growing the stack to create the actual object and 
doing the necessary initializations will result in something which is 
just as efficient as the Rosen trick but results in an access parameter 
which won't be altered.  (Its target will of course.)

In case this sounds "over the top,"  I currently have a package I use 
that creates per task generators.  Of course, in that case you may need 
to do explicit allocate and free operations to keep the officially per 
task object small, but from a user perspective what is going on in all 
cases is the same.

I certainly don't know what the correct way to deal with the issue of 
access constant parameters is.  I think I would do it by allowing 
constant subtypes for access types.  Maybe in Ada 1Z?

I don't think we know enough to fix that issue yet.  To clarify, there 
are two issues here.  One is that you want some access values to be 
marked as accessing constants, and in other cases you want to restrict 
the use of the designated object.  I feel that there is an elegant 
solution out there, but I don't know how to fill in all the blanks yet.)

Let me give an example (assuming some new syntax where needed:

    type Foo is ...
    type Bar is access Foo;
    subtype CBar is access constant Foo;
    F: Foo;
    CF: constant Foo;
    B: Bar;
    CB: CBar;
    procedure Some_Proc(CBP: in CBar);
    ...
  begin
    B := F'Access;  --okay
    CB := CF'Access; -- no problem
    B := CF'Access; -- illegal?
    CB := F'Access; -- should be okay?
    B := CB; -- illegal, or a run-time check?
    CB := B; -- should be okay.
    Some_Proc(B); --should be okay, but...
  ...
    procedure Some_Proc(CBP: in CBar) is
    ...
    begin
      CBP.Some_Comp := New_Value; -- must be illegal.
      ...
    end Some_Proc;

Just too many question marks in that prototype.  I'd want to prototype 
this and try to fill in the blanks, but only after some of the bigger 
pieces of Ada 0Y have been frozen.

-- 
                                           Robert I. Eachus

"The war on terror is a different kind of war, waged capture by capture, 
cell by cell, and victory by victory. Our security is assured by our 
perseverance and by our sure belief in the success of liberty." -- 
George W. Bush




^ permalink raw reply	[relevance 3%]

* Re: Ideas for Ada 200X
  @ 2003-06-05  4:40  5%                         ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 2003-06-05  4:40 UTC (permalink / raw)


Russ wrote:

> In any case, the performance hit taken to keep A unchanged when a
> Constraint_Error is raised seems rather expensive to me. If it were up
> to me, I would take the factor of four better efficiency over
> preserving A in the rare case of an overflow. And I'll bet most
> programmers doing heavy-duty number crunching for simulation would
> too.

You are mixing up two things here that should be kept separate.  There 
are Ada rule for predefined "+" operators which make a lot of sense in 
those cases.  The effect of other Ada rules is that compilers can't go 
behind the programmers back and change a user defined "+" function to 
break what the programmer has written and expects.  However it is 
actually easier to define a two parameter Add procedure and use it to 
add in place--if that is what you want to do.  Appended is an Ada 
program that runs eight test cases Integer vs. Float, "+" vs. Add, and 
constraint checking on vs. all checks suppressed.  As you can see, in 
this particular case, suppressing checks is a win for Integer, a lose 
for Float.  This is fairly typical.  (If you compile with GNAT remember 
to invoke gnatmake with -gnato, to enable integer constraint checking. 
Of course, the program should let you know if you forgot.)

E:\Ada\Test\New Folder>test_matrix_add
test_matrix_add
  Initialize Generators.
  Initialize Integer Matricies.
  Initialize Float Matrices.
  Initialization Completed.
  Integer "+" operator, checks on,  required 320.349 milliseconds.
  Integer Add operator, checks on,  required 221.992 milliseconds.
  Integer "+" operator, checks off, required 262.464 milliseconds.
  Integer Add operator, checks off, required 170.612 milliseconds.
  Float "+" operator,   checks on,  required 222.519 milliseconds.
  Float Add operator,   checks on,  required 150.401 milliseconds.
  Float "+" operator,   checks off, required 222.297 milliseconds.
  Float Add operator,   checks off, required 171.129 milliseconds.
  All Done.

> I know that Ada is preferable for safety-critical applications, but
> based on what you are telling me, it sure seems to be a poor choice
> for non-safety-critical simulation with heavy number crunching. Thanks
> for clarifying that. I guess C++ is good for something after all, eh?

No, what we are telling you is that in Ada, you have a choice.  If you 
choose safety, the rules are very carefully designed so you get it.  If 
you want to trade safety for speed, Ada lets you do that. Most of the 
Ada safety you get "for free."  There are some areas where you have to 
intelligently decide whether or not you are willing to pay for it.  And 
remember the case here where Float is faster with checks on.  That is 
not all that uncommon.  This is why, if you are going to Suppress 
checks, you should always test to see if there is a benefit.

Cut at line and compile.  One source file.
----------------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Calendar; use Ada.Calendar;
with Ada.Numerics.Discrete_Random;
with Ada.Numerics.Float_Random;
procedure Test_Matrix_Add is
   type Matrix is array (1..1000,1..1000) of Integer;
   type Acc_Matrix is access all Matrix;

   type Float_Matrix is array (1..1000,1..1000) of Float;
   type Acc_Float is access all Float_Matrix;

   A, B, C : Acc_Matrix := new Matrix;
   D, E, F : Acc_Float := new Float_Matrix;

   subtype Int is Integer range -100_000_000..100_000_000;
   package Int_Random is new Ada.Numerics.Discrete_Random(Int);
   Int_Gen: Int_Random.Generator;
   package Float_Random renames Ada.Numerics.Float_Random;
   Float_Gen: Float_Random.Generator;
   package Clock_IO is new Ada.Text_IO.Fixed_IO(Duration);
   Start, Stop: Ada.Calendar.Time;

   procedure Init_Matrix(M: in out Matrix) is
   begin
     for I in M'Range(1) loop
       for J in M'Range(2) loop
           M(I,J) := Int_Random.Random(Int_Gen);
       end loop;
     end loop;
   end Init_Matrix;

   procedure Init_Float(M: in out Float_Matrix) is
   begin
     for I in M'Range(1) loop
       for J in M'Range(2) loop
           M(I,J) := Float_Random.Random(Float_Gen);
       end loop;
     end loop;
   end Init_Float;

begin
   Put_Line(" Initialize Generators.");
   Int_Random.Reset(Int_Gen);
   Float_Random.Reset(Float_Gen);

   Put_Line(" Initialize Integer Matricies.");
   Init_Matrix(A.all);
   Init_Matrix(B.all);
   C.all := A.all;
   Put_Line(" Initialize Float Matrices.");
   Init_Float(D.all);
   Init_Float(E.all);
   F.all := D.all;
   Put_Line(" Initialization Completed.");

   declare

     function "+" (Left, Right: Matrix) return Matrix is
       Temp: Matrix := Left;
     begin
       for I in Temp'Range(1) loop
         for J in Temp'Range(2) loop
           Temp(I,J) := Temp(I,J) + Right(I,J);
         end loop;
       end loop;
       return Temp;
     end "+";

     procedure Add (Left: in out Matrix; Right: Matrix) is
     begin
       for I in Left'Range(1) loop
         for J in Left'Range(2) loop
           Left(I,J) := Left(I,J) + Right(I,J);
         end loop;
       end loop;
       return;
     end Add;

   begin

     Start := Clock;
     A.all := A.all + B.all;
     Stop := Clock;
     Put(" Integer ""+"" operator, checks on,  required ");
     Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural 
alignment.
     Put_Line(" milliseconds.");
     Start := Clock;
     Add(C.all,B.all);
     Stop := Clock;
     Put(" Integer Add operator, checks on,  required ");
     Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural 
alignment.
     Put_Line(" milliseconds.");
   Int_Check:
     for K in A'Range(1) loop
       for L in A'Range(2) loop
         if A(K,L) /= C(K,L)
         then
           Put_Line(" Integer results do not match.");
           exit Int_Check;
         end if;
       end loop;
     end loop Int_Check;

   end; -- declare Block Integer Checks on

   declare

     function "+" (Left, Right: Matrix) return Matrix is
       pragma Suppress(All_Checks);
       Temp: Matrix := Left;
     begin
       for I in Temp'Range(1) loop
         for J in Temp'Range(2) loop
           Temp(I,J) := Temp(I,J) + Right(I,J);
         end loop;
       end loop;
       return Temp;
     end "+";

     procedure Add (Left: in out Matrix; Right: Matrix) is
       pragma Suppress(All_Checks);
     begin
       for I in Left'Range(1) loop
         for J in Left'Range(2) loop
           Left(I,J) := Left(I,J) + Right(I,J);
         end loop;
       end loop;
       return;
     end Add;

   begin

     Start := Clock;
     A.all := A.all + B.all;
     Stop := Clock;
     Put(" Integer ""+"" operator, checks off, required ");
     Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural 
alignment.
     Put_Line(" milliseconds.");
     Start := Clock;
     Add(C.all,B.all);
     Stop := Clock;
     Put(" Integer Add operator, checks off, required ");
     Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural 
alignment.
     Put_Line(" milliseconds.");
   Int_Check2:
     for K in A'Range(1) loop
       for L in A'Range(2) loop
         if A(K,L) /= C(K,L)
         then
           Put_Line(" Integer results do not match.");
           exit Int_Check2;
         end if;
       end loop;
     end loop Int_Check2;

   end; -- declare block integer, checks off


   declare

     function "+" (Left, Right: Float_Matrix) return Float_Matrix is
       Temp: Float_Matrix := Left;
     begin
       for I in Temp'Range(1) loop
         for J in Temp'Range(2) loop
           Temp(I,J) := Temp(I,J) + Right(I,J);
         end loop;
       end loop;
       return Temp;
     end "+";

     procedure Add (Left: in out Float_Matrix; Right: Float_Matrix) is
     begin
       for I in Left'Range(1) loop
         for J in Left'Range(2) loop
           Left(I,J) := Left(I,J) + Right(I,J);
         end loop;
       end loop;
       return;
     end Add;

   begin

     Start := Clock;
     D.all := D.all + E.all;
     Stop := Clock;
     Put(" Float ""+"" operator,   checks on,  required ");
     Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural 
alignment.
     Put_Line(" milliseconds.");
     Start := Clock;
     Add(F.all,E.all);
     Stop := Clock;
     Put(" Float Add operator,   checks on,  required ");
     Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural 
alignment.
     Put_Line(" milliseconds.");

   Float_Check:
     for K in D'Range(1) loop
       for L in D'Range(2) loop
         if abs(D(K,L)-F(K,L)) > Float'Epsilon
         then
           Put_Line("Float result differences greater than Float'Epsilon.");
           exit Float_Check;
         end if;
       end loop;
     end loop Float_Check;

   end; -- declare block, Float, checks on

   declare

     function "+" (Left, Right: Float_Matrix) return Float_Matrix is
       pragma Suppress(All_Checks);
       Temp: Float_Matrix := Left;
     begin
       for I in Temp'Range(1) loop
         for J in Temp'Range(2) loop
           Temp(I,J) := Temp(I,J) + Right(I,J);
         end loop;
       end loop;
       return Temp;
     end "+";

     procedure Add (Left: in out Float_Matrix; Right: Float_Matrix) is
       pragma Suppress(All_Checks);
     begin
       for I in Left'Range(1) loop
         for J in Left'Range(2) loop
           Left(I,J) := Left(I,J) + Right(I,J);
         end loop;
       end loop;
       return;
     end Add;

   begin

     Start := Clock;
     D.all := D.all + E.all;
     Stop := Clock;
     Put(" Float ""+"" operator,   checks off, required ");
     Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural 
alignment.
     Put_Line(" milliseconds.");
     Start := Clock;
     Add(F.all,E.all);
     Stop := Clock;
     Put(" Float Add operator,   checks off, required ");
     Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural 
alignment.
     Put_Line(" milliseconds.");

   Float_Check2:
     for K in D'Range(1) loop
       for L in D'Range(2) loop
         if abs(D(K,L)-F(K,L)) > Float'Epsilon
         then
           Put_Line("Float result differences greater than Float'Epsilon.");
           exit Float_Check2;
         end if;
       end loop;
     end loop Float_Check2;

   end; -- declare block; Float checks off.

   Put_Line(" All Done.");

end Test_Matrix_Add;





^ permalink raw reply	[relevance 5%]

* Re: Random numbers in tasks
  2003-06-02 20:50  8%           ` Robert I. Eachus
@ 2003-06-03 19:37  0%             ` Papastefanos Serafeim
  0 siblings, 0 replies; 106+ results
From: Papastefanos Serafeim @ 2003-06-03 19:37 UTC (permalink / raw)


Thank you

"Robert I. Eachus" <rieachus@attbi.com> wrote in message
news:3EDBB85D.3050505@attbi.com...
> Papastefanos Serafeim wrote:
> > Thank you for the big answer... I tried your program and
> > it works just fine, but when I try to convert it to my
> > requirements it is not working:
>
> > I want to use it with discrete rundom numbers with a
> > variable range... I have made changes to your program
> > and now looks like this ->
> > with Ada.Numerics.Discrete_Random;
> > with Ada.Task_Attributes;
> > package body Rnds is
> >    function Give_Rnd (
> >          L : Integer;
> >          U : Integer;
> > )      return Integer is
> >       subtype Rng is Integer range L..U;
> >       package Rnd_Num is new Ada.Numerics.Discrete_Random (Rng);
>
> Never instantiate a random number package inside a function.  As you
> have noticed, the results are not what you want.  Here is a version of
> what I gave you before, but with the init generator settings based on
> one clock call.
>
> with Ada.Numerics.Discrete_Random;
> package body My_Float_Random is
>     type Generator_Pointer is access Ada.Numerics.Float_Random.Generator;
>
>     package Int_Rand is new Ada.Numerics.Discrete_Random(Positive);
>
>     protected Gen_Source is
>       procedure Initialize_Generator(Pointer: in out Generator_Pointer);
>     private
>       Int_Gen: Int_Rand.Generator;
>       Initial: Boolean := True;
>     end Gen_Source;
>
>     protected body Gen_Source is
>       procedure Initialize_Generator
>                   (Pointer: in out Generator_Pointer) is
>        begin
>          if Initial then
>            Int_Rand.Reset(Int_Gen);
>            Initial := False; -- use time of day once
>          end if;
>          Pointer := new Ada.Numerics.Float_Random.Generator;
>          Ada.Numerics.Float_Random.Reset
>                 (Pointer.all, Int_Rand.Random(Int_Gen));
>        end  Initialize_Generator;
>     end Gen_Source;
>
>     function Initialize return Generator_Pointer is
>       GP : Generator_Pointer;
>     begin
>       Gen_Source.Initialize_Generator(GP);
>       return GP;
>     end Initialize;
>
>     package Per_Task is new
>       Ada.Task_Attributes(Generator_Pointer, Initialize);
>
>     function Random return
>        Ada.Numerics.Float_Random.Uniformly_Distributed is
>     begin
>       return Ada.Numerics.Float_Random.Random(Per_Task.Value.all);
>     end Random;
>
> end My_Float_Random;
>





^ permalink raw reply	[relevance 0%]

* Re: Random numbers in tasks
  2003-06-02 14:35  0%         ` Papastefanos Serafeim
@ 2003-06-02 20:50  8%           ` Robert I. Eachus
  2003-06-03 19:37  0%             ` Papastefanos Serafeim
  0 siblings, 1 reply; 106+ results
From: Robert I. Eachus @ 2003-06-02 20:50 UTC (permalink / raw)


Papastefanos Serafeim wrote:
> Thank you for the big answer... I tried your program and
> it works just fine, but when I try to convert it to my
> requirements it is not working:

> I want to use it with discrete rundom numbers with a
> variable range... I have made changes to your program
> and now looks like this ->
> with Ada.Numerics.Discrete_Random;
> with Ada.Task_Attributes;
> package body Rnds is
>    function Give_Rnd (
>          L : Integer;
>          U : Integer;
> )      return Integer is
>       subtype Rng is Integer range L..U;
>       package Rnd_Num is new Ada.Numerics.Discrete_Random (Rng);

Never instantiate a random number package inside a function.  As you 
have noticed, the results are not what you want.  Here is a version of 
what I gave you before, but with the init generator settings based on 
one clock call.

with Ada.Numerics.Discrete_Random;
package body My_Float_Random is
    type Generator_Pointer is access Ada.Numerics.Float_Random.Generator;

    package Int_Rand is new Ada.Numerics.Discrete_Random(Positive);

    protected Gen_Source is
      procedure Initialize_Generator(Pointer: in out Generator_Pointer);
    private
      Int_Gen: Int_Rand.Generator;
      Initial: Boolean := True;
    end Gen_Source;

    protected body Gen_Source is
      procedure Initialize_Generator
                  (Pointer: in out Generator_Pointer) is
       begin
         if Initial then
           Int_Rand.Reset(Int_Gen);
           Initial := False; -- use time of day once
         end if;
         Pointer := new Ada.Numerics.Float_Random.Generator;
         Ada.Numerics.Float_Random.Reset
                (Pointer.all, Int_Rand.Random(Int_Gen));
       end  Initialize_Generator;
    end Gen_Source;

    function Initialize return Generator_Pointer is
      GP : Generator_Pointer;
    begin
      Gen_Source.Initialize_Generator(GP);
      return GP;
    end Initialize;

    package Per_Task is new
      Ada.Task_Attributes(Generator_Pointer, Initialize);

    function Random return
       Ada.Numerics.Float_Random.Uniformly_Distributed is
    begin
      return Ada.Numerics.Float_Random.Random(Per_Task.Value.all);
    end Random;

end My_Float_Random;




^ permalink raw reply	[relevance 8%]

* Re: Random numbers in tasks
  2003-06-02  3:29  8%       ` Robert I. Eachus
@ 2003-06-02 14:35  0%         ` Papastefanos Serafeim
  2003-06-02 20:50  8%           ` Robert I. Eachus
  0 siblings, 1 reply; 106+ results
From: Papastefanos Serafeim @ 2003-06-02 14:35 UTC (permalink / raw)


Thank you for the big answer... I tried your program and
it works just fine, but when I try to convert it to my
requirements it is not working:
I want to use it with discrete rundom numbers with a
variable range... I have made changes to your program
and now looks like this ->
with Ada.Numerics.Discrete_Random;
with Ada.Task_Attributes;
package body Rnds is
   function Give_Rnd (
         L : Integer;
         U : Integer;
)      return Integer is
      subtype Rng is Integer range L..U;
      package Rnd_Num is new Ada.Numerics.Discrete_Random (Rng);
      type Generator_Pointer is access Rnd_Num.Generator;
      protected Gen_Source is
         procedure Initialize_Generator (
               Pointer : in out Generator_Pointer );
      private
         Init: Integer := 10;
      end Gen_Source;

      protected body Gen_Source is
         procedure Initialize_Generator (
               Pointer : in out Generator_Pointer ) is
         begin
            Pointer := new Rnd_Num.Generator;
            Rnd_Num.Reset(Pointer.All, Init);
            Init := Init + 10;
         end Initialize_Generator;
      end Gen_Source;

      function Initialize return Generator_Pointer is
         Gp : Generator_Pointer;
      begin
         Gen_Source.Initialize_Generator(Gp);
         return Gp;
      end Initialize;
      package Per_Task is new
         Ada.Task_Attributes(Generator_Pointer, Initialize);

   begin
      return Rnd_Num.Random(Per_Task.Value.All);
   end Give_Rnd;
end Rnds;

It compiles fine but when I try to call the function Give_Rnd(...)
from inside a task it always returns the same result - Am I doing
something wrong ?



"Robert I. Eachus" <rieachus@attbi.com> wrote in message
news:3EDAC482.40604@attbi.com...
> Papastefanos Serafeim wrote:
> > There is a small problem in that solution, I cannot just
> > declare the generator in the task type: There is a function in
> > a different package that is used to return a random
> > number in a given range and that function is used at
> > other places too...
>
> There is magic in Ada for especially this purpose.  It is in Annex C, so
> it is possible that some compilers don't support it.  Look at C.7.2 The
> Package Task_Attributes.  Here is an example and output using GNAT.
> Notice that this version uses a fixed seed for each different task.  If
> you want different seeds for every run modify the body of
> My_Float_Random.Gen_Source.  But notice that just using a call to get
> seeds based on the clock may not be sufficient, unless you put a delay in.
>
> with Ada.Task_Attributes;
> with Ada.Numerics.Float_Random;
> package My_Float_Random is
>    function Random return Ada.Numerics.Float_Random.Uniformly_Distributed;
> end My_Float_Random;
>
> package body My_Float_Random is
>     type Generator_Pointer is access Ada.Numerics.Float_Random.Generator;
>
>     protected Gen_Source is
>       procedure Initialize_Generator(Pointer: in out Generator_Pointer);
>     private
>       Init: Integer := 10;
>     end Gen_Source;
>
>     protected body Gen_Source is
>       procedure Initialize_Generator
>                   (Pointer: in out Generator_Pointer) is
>        begin
>          Pointer := new Ada.Numerics.Float_Random.Generator;
>          Ada.Numerics.Float_Random.Reset(Pointer.all, Init);
>          Init := Init + 10;
>        end  Initialize_Generator;
>
>     end Gen_Source;
>
>     function Initialize return Generator_Pointer is
>       GP : Generator_Pointer;
>     begin
>       Gen_Source.Initialize_Generator(GP);
>       return GP;
>     end Initialize;
>
>     package Per_Task is new
>       Ada.Task_Attributes(Generator_Pointer, Initialize);
>
>     function Random return
>        Ada.Numerics.Float_Random.Uniformly_Distributed is
>     begin
>       return Ada.Numerics.Float_Random.Random(Per_Task.Value.all);
>     end Random;
>
> end My_Float_Random;
>
> with Ada.Text_IO;
> with My_Float_Random;
> procedure Test_Task_Random is
>
>     package Rand_IO is new Ada.Text_IO.Float_IO(Float);
>
>     task type Rand_Task (ID: Integer) is end Rand_Task;
>
>     type Task_Pointer is access Rand_Task;
>     TP : Task_Pointer;
>
>     protected IO_Serialize is
>       procedure Write_Line(S: in String);
>     end IO_Serialize;
>
>     protected body IO_Serialize is
>       procedure Write_Line (S: in String)
>       is begin Ada.Text_IO.Put_Line(S); end Write_Line;
>     end IO_Serialize;
>
>     task body Rand_Task is
>       Rand_String: String(1..10);
>     begin
>       for I in 1..10 loop
>         Rand_IO.Put(Rand_String, My_Float_Random.Random, 7, 0);
>         IO_Serialize.Write_Line( "Task" & Integer'Image(ID) &
>            " Random number: " & Rand_String);
>       end loop;
>     end Rand_Task;
>
> begin
>
>     for I in 1..10 loop
>       TP := new Rand_Task(I);
>     end loop;
>
> end Test_Task_Random;
>
> E:\Ada\Random>test_task_random
> test_task_random
> Task 1 Random number:  0.7443592
> Task 1 Random number:  0.1400007
> Task 1 Random number:  0.9659407
> Task 1 Random number:  0.6070659
> ...
> Task 6 Random number:  0.3006703
> Task 7 Random number:  0.5094006
> Task 8 Random number:  0.9858680
> Task 10 Random number:  0.2958182
> Task 9 Random number:  0.7662218
> Task 10 Random number:  0.4117813
> Task 9 Random number:  0.9709954
> Task 10 Random number:  0.2093689
> Task 9 Random number:  0.3808535
> Task 10 Random number:  0.6235309
>
>
>
>
>





^ permalink raw reply	[relevance 0%]

* Re: Random numbers in tasks
  @ 2003-06-02  3:29  8%       ` Robert I. Eachus
  2003-06-02 14:35  0%         ` Papastefanos Serafeim
  0 siblings, 1 reply; 106+ results
From: Robert I. Eachus @ 2003-06-02  3:29 UTC (permalink / raw)


Papastefanos Serafeim wrote:
> There is a small problem in that solution, I cannot just
> declare the generator in the task type: There is a function in
> a different package that is used to return a random
> number in a given range and that function is used at
> other places too...

There is magic in Ada for especially this purpose.  It is in Annex C, so 
it is possible that some compilers don't support it.  Look at C.7.2 The 
Package Task_Attributes.  Here is an example and output using GNAT. 
Notice that this version uses a fixed seed for each different task.  If 
you want different seeds for every run modify the body of 
My_Float_Random.Gen_Source.  But notice that just using a call to get 
seeds based on the clock may not be sufficient, unless you put a delay in.

with Ada.Task_Attributes;
with Ada.Numerics.Float_Random;
package My_Float_Random is
   function Random return Ada.Numerics.Float_Random.Uniformly_Distributed;
end My_Float_Random;

package body My_Float_Random is
    type Generator_Pointer is access Ada.Numerics.Float_Random.Generator;

    protected Gen_Source is
      procedure Initialize_Generator(Pointer: in out Generator_Pointer);
    private
      Init: Integer := 10;
    end Gen_Source;

    protected body Gen_Source is
      procedure Initialize_Generator
                  (Pointer: in out Generator_Pointer) is
       begin
         Pointer := new Ada.Numerics.Float_Random.Generator;
         Ada.Numerics.Float_Random.Reset(Pointer.all, Init);
         Init := Init + 10;
       end  Initialize_Generator;

    end Gen_Source;

    function Initialize return Generator_Pointer is
      GP : Generator_Pointer;
    begin
      Gen_Source.Initialize_Generator(GP);
      return GP;
    end Initialize;

    package Per_Task is new
      Ada.Task_Attributes(Generator_Pointer, Initialize);

    function Random return
       Ada.Numerics.Float_Random.Uniformly_Distributed is
    begin
      return Ada.Numerics.Float_Random.Random(Per_Task.Value.all);
    end Random;

end My_Float_Random;

with Ada.Text_IO;
with My_Float_Random;
procedure Test_Task_Random is

    package Rand_IO is new Ada.Text_IO.Float_IO(Float);

    task type Rand_Task (ID: Integer) is end Rand_Task;

    type Task_Pointer is access Rand_Task;
    TP : Task_Pointer;

    protected IO_Serialize is
      procedure Write_Line(S: in String);
    end IO_Serialize;

    protected body IO_Serialize is
      procedure Write_Line (S: in String)
      is begin Ada.Text_IO.Put_Line(S); end Write_Line;
    end IO_Serialize;

    task body Rand_Task is
      Rand_String: String(1..10);
    begin
      for I in 1..10 loop
        Rand_IO.Put(Rand_String, My_Float_Random.Random, 7, 0);
        IO_Serialize.Write_Line( "Task" & Integer'Image(ID) &
           " Random number: " & Rand_String);
      end loop;
    end Rand_Task;

begin

    for I in 1..10 loop
      TP := new Rand_Task(I);
    end loop;

end Test_Task_Random;

E:\Ada\Random>test_task_random
test_task_random
Task 1 Random number:  0.7443592
Task 1 Random number:  0.1400007
Task 1 Random number:  0.9659407
Task 1 Random number:  0.6070659
...
Task 6 Random number:  0.3006703
Task 7 Random number:  0.5094006
Task 8 Random number:  0.9858680
Task 10 Random number:  0.2958182
Task 9 Random number:  0.7662218
Task 10 Random number:  0.4117813
Task 9 Random number:  0.9709954
Task 10 Random number:  0.2093689
Task 9 Random number:  0.3808535
Task 10 Random number:  0.6235309








^ permalink raw reply	[relevance 8%]

* Re: Using Ada for device drivers? (Was: the Ada mandate, and why it collapsed and died)
  @ 2003-05-11 21:57  3%                             ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 2003-05-11 21:57 UTC (permalink / raw)


Robert I. Eachus wrote:

 > My favorite example is a program I wrote in a few hours to 
demonstrate > the "right" way to generate random permutations in Ada.

Hyman Rosen wrote:
> I think this is a perfect example of the blind spot of Ada programmers.
> You are so enamored of enumerations and perfectly indexed arrays and
> lack of buffer overflows that you will probably miss the most likely
> and subtle bug of this kind of code, which is that the Shuffle routine
> fails to produce each possible permutation with uniform probability!

Did you read what I wrote, really?  Should I have included the notes in 
the Shufflling routine which showed why this particular method of 
generation permutations was unbiased?  Okay done:

    procedure Shuffling (List : in out List_Type;
                         Gen  : in     Generator) is
-- a routine for producing permutations of a list of elements.  Note
-- that this method is unbiased for any independent sequence.  (For
-- any two cards the possibility that they will be in a particular
-- order is exactly 1/2, this can be extended by iteration to show
-- that each sequence has a probablity of 1/N!   Note that for large
-- lists of elements not all permutations will be generated.  There
-- are N! permutations of a list of N values, and this may be much
-- greater than the number of generator states.  Note also that the
-- actual number of different possible permutations generated from
-- one starting seed is k/GCD(N,k) for a generator with k states.

       List_Copy : constant List_Type := List;

       type Rec is
          record
             Index : Index_Type;
             Rand  : Float;
          end record;

       type Rec_Array is array (Index_Type range <>) of Rec;

       Temp : Rec_Array(List'Range);

       function "<" (L, R: Rec) return Boolean is
       begin return L.Rand < R.Rand; end "<";

       procedure Sort is new Sorting(Rec, Index_Type, Rec_Array, "<");

     begin
        for I in Temp'Range loop
           Temp(I) := (I, NFR.Random(Gen));
        end loop;

        Sort(Temp);  --  Sort based on value of random number

        --  Now rearrange List based on the order of indices in Temp
        for I in List'Range loop
           List(I) := List_Copy(Temp(I).Index);
        end loop;
     end Shuffling;

Again, no subtlety present or wanted.

Note that for Ada, the generator you get from Ada.Numerics.Float_Random 
will usually have more that 2^32 states.  If it is the one I wrote that 
is in Gnat, the GCD mentioned will be one, unless N has a factor that is 
one of two five digit primes. Oh, and this is the body of a generic 
where Element_Type, List_Type, and Index_Type are generic parameters. 
Okay? No?

Well if you really need a longer period generator, write me.  The other 
alternative is to combine two generators with independent seeds and 
periods.  Adding typical [0..1) generators and if >1, subtracting 1 
works just fine unless one of the generators is biased.  In fact, for 
most tests of randomness, you get more random behavior than either 
generator alone.







^ permalink raw reply	[relevance 3%]

* Re: Ada2005 random
  @ 2003-04-13 14:56  6%       ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 2003-04-13 14:56 UTC (permalink / raw)


Dale Stanbrough wrote:
> Randy Brukardt wrote:
> 
> 
>>I needed that for a 'choosing' algorithm, say drawing balls one by one
>>out of a bowl. If you have 8 balls originally, you're choosing 1 out of
>>7, then 1 out of 6, etc. If you try to use 1 out of 8 the whole time and
>>discarding the useless ones, the second last draw can take a very long
>>time (only 2 out of 8 choices are meaningful). I'm pretty sure that this
>>is a valid technique; certainly the underlying float generator is still
>>random (at least as much as it ever was!), and the use of that result is
>>unbiased.
>>
>>While it would be nice if Ada supported this directly, it's easy enough
>>to write it yourself.

If you need a permutation, the best way to do it is to generate a set of 
random (float) values, associate them with the data to be permuted and 
the sort on this key.  I have seen a lot of code that attempts to 
permute a list by going through the list and exchanging elements.  For 
lists of length greater than two this can easily be shown to be biased.

For example there are 3! = 6 possible permutions of a list of three 
elements, the usual version of the swapping algorithm has 3^3 = 27 
possible outcomes, another (worse) variation has 2^3 = 8 different 
outcomes.  In either case the number of outcomes is not evenly divisible 
by the number of different permutations.

Even if you do this, there is another potential problem.  For a set of 
size N, there are N! possible permutations.  For example for a deck of 
cards, there are 52! possible permutations.  If you are generating 
bridge hands, there are 52!/(13!)^4 different possible deals.  Now if 
you are taking the (pseudo-)random sequence from a single generator, 
there will be at most as many different possible hands as there are 
possible starting seeds for the generator.  For the generator that I 
wrote, which AFAIK is still used by GNAT, if you use the time based 
version of Reset, there are more than 2^32 possible starting values, but 
of course, they won't all occur in a particular year.

If you really, really care about making it possible to generate a large 
fraction of all possible permutations, the way to do it is to take 
several generators with seeds generated based on different random data, 
then shuffle the deck more than once.

This program should serve as an example of how to do this.  (Note, I 
don't claim this is "right" since I don't use two generators, and 
shuffle twice.)

with Ada.Numerics.Float_Random;
package Statistics is

    subtype Generator is Ada.Numerics.Float_Random.Generator;

    type Direction is (Ascending, Descending);

    generic
      type Element_Type is private;
      type Index_Type is (<>);
      type List_Type is array (Index_Type range <>) of Element_Type;
      with function "<" (L, R : Element_Type) return Boolean is <>;
    procedure Sorting (List : in out List_Type);
    --  General-purpose sorting procedure

    generic
      type Element_Type is private;
      type Index_Type is (<>);
      type List_Type is array (Index_Type range <>) of Element_Type;
    procedure Shuffling (List : in out List_Type;
                         Gen  : in     Generator);
    --  Permute the contents of List randomly

end Statistics;
------------------------------------------------------------------------
with Ada.Numerics.Float_Random;
package body Statistics is

    package NFR renames Ada.Numerics.Float_Random;

--  generic
--    type Element_Type is private;
--    type Index_Type is (<>);
--    type List_Type is array (Index_Type range <>) of Element_Type;
--    with function "<" (L, R : Element_Type) return Boolean is <>;
    procedure Sorting (List : in out List_Type) is
       --  Quicksort
       Part  : Element_Type;
       First : Index_Type;
       Last  : Index_Type;
    begin
      --  Don't break on short lists;
       if List'Length <= 1
       then return;
       elsif List'Length = 2 then
          if List(List'Last) < List(List'First)
          then
             Part := List(List'First);
             List(List'First) := List(List'Last);
             List(List'Last) := Part;
          end if;
          return;
       end if;

       --  now it is safe to assume that List'First and List'Last
       --  are in range.

       First := List'First;
       Last  := List'Last;

       -- choose partition value
       Part := List(First);

       -- partition list
    Main_Loop:
       loop
          if Part < List(Last) then
             Last := Index_Type'PRED(Last);
             exit Main_Loop when Last=First;
          else
             List(First) := List(Last);
             First := Index_Type'SUCC(First);
             exit Main_Loop when Last=First;
             while List(First) < Part loop
                First := Index_Type'SUCC(First);
                exit Main_Loop when Last=First;
             end loop;
             List(Last) := List(First);
             Last := Index_Type'PRED(Last);
             exit Main_Loop when Last=First;
          end if;
       end loop Main_Loop;

       List(First) := Part; -- at this point First = Last.
       Sorting(List(List'First..Index_Type'PRED(Last)));
       Sorting(List(Index_Type'SUCC(Last)..List'Last));
    end Sorting;


    --  generic
    --   type Element_Type is private;
    --   type Index_Type is (<>);
    --   type List_Type is array (Index_Type range <>) of Element_Type;
    procedure Shuffling (List : in out List_Type;
                         Gen  : in     Generator) is
       List_Copy : constant List_Type := List;

       type Rec is
          record
             Index : Index_Type;
             Rand  : Float;
          end record;

       type Rec_Array is array (Index_Type range <>) of Rec;

       Temp : Rec_Array(List'Range);

       function "<" (L, R: Rec) return Boolean is
       begin return L.Rand < R.Rand; end "<";

       procedure Sort is new Sorting(Rec, Index_Type, Rec_Array, "<");

     begin
        for I in Temp'Range loop
           Temp(I) := (I, NFR.Random(Gen));
        end loop;

        Sort(Temp);  --  Sort based on value of random number

        --  Now rearrange List based on the order of indices in Temp
        for I in List'Range loop
           List(I) := List_Copy(Temp(I).Index);
        end loop;
     end Shuffling;

end Statistics;
---------------------------------------------------------------------------
with Ada.Numerics.Float_Random;
with Statistics;
with Text_IO; use Text_IO;
procedure Bridge_Hands is
-- a procedure to produce random (but sorted) bridge hands for duplicate.

   package NFR        renames Ada.Numerics.Float_Random;

   Gen: NFR.Generator;
   function Rand(G: in NFR.Generator := Gen) return Float renames 
NFR.Random;

   type Direction is (North, East, South, West);
   type Suits is (Spades, Hearts, Diamonds, Clubs);
   type Ranks is (Ace, King, Queen, Jack, Ten, Nine, Eight, Seven,
                 Six, Five, Four, Three, Deuce);

   Display_Suit: constant array(Suits) of Character := "SHDC";
   Display_Rank: constant array(Ranks) of Character := "AKQJT98765432";

   subtype Dealer_Name is String(1..5);
   Display_Dealers: constant array(0..3) of Dealer_Name :=
      ("North", "East ", "South", "West ");
   subtype Vulnerability is String(1..11);
   Display_Vulnerability: constant array(0..3) of Vulnerability :=
      ("None       ","North/South","East/West  ","Both       ");
   package Int_IO is new Text_IO.Integer_IO(Integer);
   Number_of_Hands: Integer;

   type Card is record
     Suit: Suits;
     Rank: Ranks;
   end record;

   type Card_Array is array (Natural range <>) of Card;

   Deck: Card_Array(0..51);

   subtype Hand is Card_Array(0..12);
   Hands: array(Direction) of Hand;


   function By_Rank(L,R: Card) return Boolean is
   begin return L.Rank < R.Rank; end By_Rank;
   pragma INLINE(By_Rank);

   procedure Sort_Hand is
     new Statistics.Sorting(Card, Natural, Card_Array, By_Rank);

   procedure Shuffle is
     new Statistics.Shuffling(Card, Natural, Card_Array);

   procedure Deal is
   begin
     for I in Hand'Range loop
       for J in Hands'Range loop
         Hands(J)(I) := Deck(I*4 + Direction'POS(J));
       end loop;
     end loop;
     for I in Hands'Range loop
       Sort_Hand(Hands(I));
       -- sort cards by rank, but not by suit.
     end loop;
   end Deal;

   function Cards(D: in Direction; S: in Suits) return String is
     Temp: String(1..26) := (others => ' ');
     Index: Natural := 3;
   begin
     Temp(1) := Display_Suit(S);
     for I in Hand'Range loop
       if Hands(D)(I).Suit = S
       then
         Temp(Index) := Display_Rank(Hands(D)(I).Rank);
         Index := Index + 2;
       end if;
     end loop;
     if Index = 3 then Temp(3..5) := "---"; end if;
     return Temp;
   end Cards;

begin

   -- Use time-dependant random numbers:

   NFR.Reset(Gen);

   -- Initialize deck.

   for I in Deck'Range loop
     Deck(I) := (Suits'VAL(I/13), Ranks'VAL(I mod 13));
   end loop;

   Text_IO.Put_Line("Enter number of hands, default is 32:");

   begin
     Int_IO.Get(Number_of_Hands);
   exception when others =>
     Number_of_Hands := 32;
   end;

   for I in 0..Number_of_Hands - 1 loop
     Text_IO.New_Page;
     Text_IO.New_Line(3);
     Text_IO.Put_Line("                                Board:        "
         & Integer'IMAGE(I+1));
     Text_IO.Put_Line("                                Dealer:        "
       & Display_Dealers(I mod 4));
     Text_IO.Put_Line("                                Vulnerability: "
       & Display_Vulnerability((I + I/4) mod 4));
     New_Line(3);

     Shuffle(Deck, Gen);

     Deal;

     Text_IO.Put_Line("                                NORTH");
     Text_IO.New_Line;
     Text_IO.Put_Line("                              " &
                      Cards(North,Spades));
     Text_IO.Put_Line("                              " &
                      Cards(North,Hearts));
     Text_IO.Put_Line("                              " &
                      Cards(North,Diamonds));
     Text_IO.Put_Line("                              " &
                      Cards(North,Clubs));
     New_Line(2);
     Text_IO.Put_Line("       WEST                                  " &
                      "          EAST");
     Text_IO.New_Line;
     Text_IO.Put_Line("     " & Cards(West,Spades) &
                      "                      " & Cards(East,Spades));
     Text_IO.Put_Line("     " & Cards(West,Hearts) &
                      "                      " & Cards(East,Hearts));
     Text_IO.Put_Line("     " & Cards(West,Diamonds) &
                      "                      " & Cards(East,Diamonds));
     Text_IO.Put_Line("     " & Cards(West,Clubs) &
                      "                      " & Cards(East,Clubs));
     New_Line(2);
     Text_IO.Put_Line("                                SOUTH");
     Text_IO.New_Line;
     Text_IO.Put_Line("                              " &
                      Cards(South,Spades));
     Text_IO.Put_Line("                              " &
                      Cards(South,Hearts));
     Text_IO.Put_Line("                              " &
                      Cards(South,Diamonds));
     Text_IO.Put_Line("                              " &
                      Cards(South,Clubs));
   end loop;

end Bridge_Hands;




^ permalink raw reply	[relevance 6%]

* Re: Ada2005 random
  2003-04-07  7:26  4% ` Jean-Etienne Doucet
@ 2003-04-07  8:09  0%   ` Lutz Donnerhacke
  0 siblings, 0 replies; 106+ results
From: Lutz Donnerhacke @ 2003-04-07  8:09 UTC (permalink / raw)


* Jean-Etienne Doucet wrote:
> For this kind of problems, I use the Ada.Numerics.Float_Random generator,
> along with the function:

If performance is not an issue, you are right.



^ permalink raw reply	[relevance 0%]

* Re: Ada2005 random
  @ 2003-04-07  7:26  4% ` Jean-Etienne Doucet
  2003-04-07  8:09  0%   ` Lutz Donnerhacke
  0 siblings, 1 reply; 106+ results
From: Jean-Etienne Doucet @ 2003-04-07  7:26 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1555 bytes --]

Randy Brukardt wrote:
|
| I needed that for a 'choosing' algorithm, say drawing balls one by one
| out of a bowl. If you have 8 balls originally, you're choosing 1 out of
| 7, then 1 out of 6, etc. If you try to use 1 out of 8 the whole time and
| discarding the useless ones, the second last draw can take a very long
| time (only 2 out of 8 choices are meaningful). I'm pretty sure that this
| is a valid technique; certainly the underlying float generator is still
| random (at least as much as it ever was!), and the use of that result is
| unbiased.
|

For this kind of problems, I use the Ada.Numerics.Float_Random generator,
along with the function:

  function Rand (N : Positive) return Positive is
     -- gives a random integer in the range 1 .. N
  begin
     return Integer(Float(N) * Random(Gen) + 0.5);
  end Rand;


It can be used for ranges other than 1 .. N:

  function Rand (Min, Max : Integer) return Integer is
     -- gives a random integer in the range Min .. Max
  begin
     return Rand(Max - Min + 1) + Min - 1;
  end Rand;


It works as well for enum types:

  type Enum is (...);
  
  function Random_Enum return Enum is 
     -- gives a random Enum value
  begin
     return Enum'Val(Rand(Enum'Pos(Enum'Last) + 1) - 1);
  end Random_Enum;


I've never had a problem with this.

_______________________________________________________________________________
Jean-Etienne Doucet / LAAS-CNRS / Toulouse, France       E-mail: doucet@laas.fr
"S'il n'y a pas de solution, c'est qu'il n'y a pas de probl�me."  (Les Shadoks)






^ permalink raw reply	[relevance 4%]

* Re: ML-like alternatives to out parameters for functions
  @ 2003-04-01  3:39  4%         ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 2003-04-01  3:39 UTC (permalink / raw)


Frank J. Lhota wrote:

> This approach would probably the best approach given the current Ada 95
> restrictions, since it specifies precisely how Random works: it updates the
> generator and returns a value. For ease of use, however, it would be hard to
> beat the function solution with the "in out" parameter (if it only were
> legal Ada!).

Let's not revisit this again.  During the Ada 9X development process, 
the arguments on both sides were explained, and a formal WG9 vote taken 
(by countries--this is ISO).  Allowing function parameters to have an in 
out mode was defeated.

Note that this does not mean you cannot write functions in Ada that 
alter their parameters.

    function Random(Gen: in Generator) return Uniformly_Distributed is
      Local_Gen: Generator;
      for Local_Gen'Address use Gen'Address;
    begin...

is perfectly legal Ada.  Note that in this particular case, since 
Generator is a limited type, it is only legal inside the body of the 
package that defines Generator (Presumbably Ada.Numerics.Float_Random, 
but you can write your own random number generators.  I do. ;-)

And that should make the reason why things have stayed the way they are 
perfectly clear.  There is a workaround for the cases where it is 
appropriate to work around the restriction, and the workaround is 
limited in a useful way.  You don't want users poking around inside the 
Generator object, and such poking around--by say passing the Generator 
object to a unit written in C--is flagged with warnings all around.






^ permalink raw reply	[relevance 4%]

* Re: ML-like alternatives to out parameters for functions
  @ 2003-03-18 17:04  3%   ` Frank J. Lhota
    0 siblings, 1 reply; 106+ results
From: Frank J. Lhota @ 2003-03-18 17:04 UTC (permalink / raw)


> The prefered Ada solution for this particular case is to raise an
> exception for errors, not return a status variable (or discriminant).

I heartily agree that error checking is best done with exceptions. That is
especially true with functions; the proposed specification of Calculate
rules out its use in more complex expressions, such as

    Process( Calculate (Arg, Valid), My_Data );

since we cannot validly use the result of Calculate until the Valid
parameter is checked.

To make the case for "out" parameters in functions, a much better example
would be the random number generators. For example the package
Ada.Numerics.Float_Random declares the function

    function Random (Gen : Generator) return Uniformly_Distributed;

This function returns the next random number in the range 0.0 .. 1.0, using
the state information associated with Gen. I would argue that it would be
far preferable if the random function could be declared as follows:

    function Random (Gen : in out Generator) return Uniformly_Distributed;

This would be preferable since, by its very nature, a call to Random update
the Generator state. The random number generator package implementations I
know of basically circumvent the 'in' parameter restrictions to update its
parameter value. (If anyone knows of an Ada compiler that does NOT alter the
value of Gen after a call to Random, please post the details!) That suggests
a flaw in the specification of the Random function.

A frequent way to get the effect of "in" / "in out"  function parameters is
to use anonymous access types, e.g.

    function Random (Gen : access Generator) return Uniformly_Distributed;

but there are problems with the access parameter hack.

1)    The functions with access parameters are more of a hassle to call. You
must remember to declare the actual parameters as "aliased" and use the
'Access or 'Unchecked_Access attribute to get the needed access value.

2)    The anonymous access parameter does not distinguish between "out" and
"in out" modes. When compiling a call to this kind of function, the compiler
cannot do the frequently useful check to see if variables that are to be
read have been initialized.

3)    This hack forces the programmer to specify the parameter passing
convention. Granted, in most cases "in out" and "out" parameters are passed
by reference, but it still feels wrong to require it, and to require
programmers working at a high level of abstract to be aware of this
implementation detail.

I fully understand the Ada 83/95 rationale for the requirement that
functions have only "in" parameters. There is the fear that if a function
could change its parameters, we would see code like this

      x + f(x)

where the result would depend on which order the operands were evaluated.
One wishes that this is only a hypothetical concern, but in my career I have
seen expressions this bad in professional software that I had to maintain,
including a C expression like

    a[i++] = b[i] + offset;

or the PL/1 expression

    fp, fp->prev = fp->next;

It is understandable that the language designers wish to prohibit these
atrocities, but the restriction on function parameters seems to have
backfired. It is time this restriction is removed.





^ permalink raw reply	[relevance 3%]

* Re: Discrete random with given distribution ?
  @ 2002-06-14 10:01  7% ` Gautier
  0 siblings, 0 replies; 106+ results
From: Gautier @ 2002-06-14 10:01 UTC (permalink / raw)


Reinert Korsnes:

> Is it under Ada any "natural" way to generate random
> elements of enumeration type (for example (a,b,c))
> and with a given non-uniform probability distribution ?

Maybe you'll be interested by gnatchopping the following...
____________________________________________________________
Gautier  --  http://www.mysunrise.ch/users/gdm/index.htm#Ada

NB: For a direct answer, address on the Web site!

---8<--gnatchop---8<--gnatchop---8<--gnatchop---8<--gnatchop---8<--

--From: Reinert Korsnes (reinert.korsnes@chello.no)
--Subject: Discrete random with given distribution ? 
--Newsgroups: comp.lang.ada
--View this article only 
--Date: 2002-06-13 05:25:17 PST 

--Hi,

--Is it under Ada any "natural" way to generate random
--elements of enumeration type (for example (a,b,c))
--and with a given non-uniform probability distribution ?

--I.e. so for example "a" is produced by probability 1/2
--and "b" and "c" both with probability 1/4 ?

generic
  type A_float is digits <>;
  type Thing is (<>);
  type Proba_array is array(Thing) of A_float;
  with function Uniform_random return A_float;
function Finite_distributed_random(proba: Proba_array) return Thing;

function Finite_distributed_random(proba: Proba_array) return Thing is
  subtype AF01 is A_float range 0.0 .. 1.0;
  U: constant AF01:= Uniform_random;
  p: AF01:= 0.0;
  Probabilities_dont_sum_up_to_1: exception;
begin
  for th in Thing loop
    p:= p + AF01(proba(th));
    if U < p then
      return th;
    end if;
  end loop;
  if (p-1.0) > A_float'epsilon then
    raise Probabilities_dont_sum_up_to_1;
  end if;
  return Thing'last;
end Finite_distributed_random;

with Finite_distributed_random;

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

procedure Test_Finite_distributed_random is

  G: Ada.Numerics.Float_Random.Generator;

  function URand return Float is
  begin
    return Ada.Numerics.Float_Random.Random(G);
  end;

  type ABC is (a,b,c);
  
  type Proba_array is array(ABC) of Float;

  function ABC_Rand is new
    Finite_distributed_random(
      A_float        => Float,
      Thing          => ABC,
      Proba_array    => Proba_array,
      Uniform_random => URand);
  
  procedure Test( tirages: Positive; proba: Proba_array ) is
    sample: array(ABC) of Natural;
    res: ABC;
  begin
    Ada.Numerics.Float_Random.Reset(G);
    sample:= (others => 0);
    for i in 1..tirages loop
      res:= ABC_Rand( proba );
      sample(res):= sample(res) + 1;
    end loop;
    for x in ABC loop
      Put( ABC'image(x) & " :    prob = ");
      Put( proba(x), 1,4,0);
      Put(                " ;    stat = ");
      Put( Float( sample(x) ) / Float( tirages ), 1,4,0);
      New_Line;
    end loop;
    New_Line;
  end Test;
  
begin
  Test( 100_000, (A=> 0.50, B=> 0.25, C=> 0.25) );
  Test( 100_000_000, (A=> 0.123, B=> 0.456, C=> 0.421) );
end;



^ permalink raw reply	[relevance 7%]

* Re: Building on Random_Float?
  2002-05-09 20:29  8% Building on Random_Float? Mars Gralia
@ 2002-05-26 23:24  0% ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 2002-05-26 23:24 UTC (permalink / raw)


Mars Gralia wrote:

> Ada Wizards and Gentle Folk,
> 
> I would like a high-level Ada95 design that allows me to build a
> layered series of random number generators which ultimately use
> Ada.Numerics.Float_Random.  Could you please provide me one?
> 
> Details are given below.


I guess I don't see your problem.  Generators are and should be limited, 
because of the mischief that can come from making a copy of one.  (The 
mechanism for states insures that you can save, copy, etc. generator 
states, but that random sequences from a generator have guaranteed 
properties between resets.

But there is nothing to prevent you from creating a normal generator 
that is also limited with a uniform generator (or two) as components.
I say or two because the best normal distribution generator I know uses 
two uniform variates.  But remember if you do use two generators, to get 
full benefit, you need to initialize (reset) them using different 
sources of randomness.

My current email address is rieachus@attbi.com.





^ permalink raw reply	[relevance 0%]

* Building on Random_Float?
@ 2002-05-09 20:29  8% Mars Gralia
  2002-05-26 23:24  0% ` Robert I. Eachus
  0 siblings, 1 reply; 106+ results
From: Mars Gralia @ 2002-05-09 20:29 UTC (permalink / raw)


Ada Wizards and Gentle Folk,

I would like a high-level Ada95 design that allows me to build a
layered series of random number generators which ultimately use
Ada.Numerics.Float_Random.  Could you please provide me one?

Details are given below.

Thank you,
Mars Gralia, D.Sc.
The Johns Hopkins University
Applied Physics Laboratory
gralia@jhuapl.edu
443.778.5509 (USA)


Appendix A: Software Specification
Appendix B: Specification Amplification
Appendix C: Background
Appendix D: Desired Specification Files



----------------- Appendix A: Software Specification

10) The goal is a "package Interest_Rate_Pkg", which produces random
    numbers from a gamma distribution.
20) The "package specification", file Interest_Rate_Pkg.ads, differs
    form Ada.Numerics.Float_Random only
    a) in the package name and
    b) the data type Uniformly_Distributed
      b1)  declaration is eliminated
      b2)  is converted to "Float" for the "function Random".
30) The package is built in the following layers:
        package Interest_Rate_Pkg, which "withs"
          package General_Gamma_Pkg, which "withs"
            package Standard_Gamma_Pkg, which "withs"
              package Exponential_Pkg, which "withs"
                package Ada.Numerics.Float_Random;
              package Normal_Pkg, which "withs"
                package Ada.Numerics.Float_Random;
              package Ada.Numerics.Float_Random.
40) I am not requesting the algorithms, for I have all of them.  Indeed,
    they run with the uniform generator the author supplies.  But I
    prefer the Ada95 generator as the basis.





----------------- Appendix B: Specification Details

10) This note more carefully defines the family of generators I
    would like to use.  It's code skelton is:

    package Interest_Rate_Pkg is ... end Interest_Rate_Pkg;
    with General_Gamma_Pkg; package body Interest_Rate_Pkg is
      ...  end Interest_Rate_Pkg;

    package General_Gamma_Pkg is ... end General_Gamma_Pkg;
    with Standard_Gamma_Pkg; package body General_Gamma_Pkg is
      ... end General_Gamma_Pkg;

    package Standard_Gamma_Pkg is ... end Standard_Gamma_Pkg;
    with Normal_Pkg, Exponential_Pkg, Ada.Numerics.Float_Random;
    package body Standard_Gamma_Pkg is ... end Standard_Gamma_Pkg;

    package Exponential_Pkg is ... end Exponential_Pkg;
    with Ada.Numerics.Float_Random;  package body Exponential_Pkg is
      ... end Exponential_Pkg;

    package Normal_Pkg is ... end Normal_Pkg;
    with Ada.Numerics.Float_Random;  package body Normal_Pkg is
      ... end Normal_Pkg;

20) I would prefer the technology allow me to continue the
    layering even deeper than the four levels I need in this example.



----------------- Appendix C: Background

I'm working under Gnat 3.13p, but would like to use only standard
Ada.

I've tried, and failed:
a) To simply build the second layer on Ada.Numerics.Float_Random.
   As expected, this failed because Float_Random is a "limited private",
   so I can't use an assignment statement to store it in
   Normal_Pkg.Generator.
b) To make a package Ada.Numerics.Float_Random.Normal.  The
   specific message was:
   --> ada.numerics.float_random.random_brown_pkg.ads:1:01:
   --> current unit cannot depend on "Float_Random" (wrong
   --> categorization)
c) To use pointers as did Mr. Eachus in his ADAR_Random_Number.
   Hint: I got it from the Google archives.  It had the header:
   --> From: Robert I. Eachus (eachus@spectre.mitre.org)
   --> Subject: Re: Random number generators
   --> Newsgroups: comp.lang.ada
   --> Date: 1995/07/25

I feel I'm a journeyman programmer, certainly not a formal
student.  (But aren't we all still learning?)

The source of my current algorithm for all the layers are found in
http://odin.mdacc.tmc.edu/anonftp/page_2.html#RANDLIB They were
developed by Barry W. Brown, James Lovato, Kathy Russell and John
Venier.  On the web, it was called "randlib".  Internally, it is labeled
"RANDLIB; Library of Fortran Routines for Random Number Generation;
Version 1.3 -- August, 1997".  The authors are with the
> Department of Biomathematics, Box 237;
> The University of Texas, M.D. Anderson Cancer Center;
> 1515 Holcombe Boulevard;
> Houston, TX      77030
They also tell us "This work was supported by grant CA-16672 from the
National Cancer Institute."



----------------- Appendix D: Desired Specification Files

This section gives the package specs I'd like to have in the end.
Note they are virtually identical.

  package Interest_Rate_Pkg is
    type Generator is limited private;
    function Random (Gen: Generator) return Float;
    procedure Reset (Gen: in Generator; Initiator: in Integer);
    procedure Reset (Gen: in Generator);
    type State is private;
    procedure Save (Gen: in Generator; To_State: out State);
    procedure Reset (Gen: in Generator; From_State: in State);
    Max_Image_Width: constant := implementation-defined integer value;
    function Image (Of_State: State) return String;
    function Value (Coded_State: String) return State;
  private
    ... -- not specified by Gralia
  end Interest_Rate_Pkg;

  package General_Gamma_Pkg is
    type Generator is limited private;
    function Random (Gen: Generator) return Float;
    procedure Reset (Gen: in Generator; Initiator: in Integer);
    procedure Reset (Gen: in Generator);
    type State is private;
    procedure Save (Gen: in Generator; To_State: out State);
    procedure Reset (Gen: in Generator; From_State: in State);
    Max_Image_Width: constant := implementation-defined integer value;
    function Image (Of_State: State) return String;
    function Value (Coded_State: String) return State;
  private
    ... -- not specified by Gralia
  end General_Gamma_Pkg;

  package Standard_Gamma_Pkg is
    type Generator is limited private;
    function Random (Gen: Generator) return Float;
    procedure Reset (Gen: in Generator; Initiator: in Integer);
    procedure Reset (Gen: in Generator);
    type State is private;
    procedure Save (Gen: in Generator; To_State: out State);
    procedure Reset (Gen: in Generator; From_State: in State);
    Max_Image_Width: constant := implementation-defined integer value;
    function Image (Of_State: State) return String;
    function Value (Coded_State: String) return State;
  private
    ... -- not specified by Gralia
  end Standard_Gamma_Pkg;

  package Exponential_Pkg is
    type Generator is limited private;
    function Random (Gen: Generator) return Float;
    procedure Reset (Gen: in Generator; Initiator: in Integer);
    procedure Reset (Gen: in Generator);
    type State is private;
    procedure Save (Gen: in Generator; To_State: out State);
    procedure Reset (Gen: in Generator; From_State: in State);
    Max_Image_Width: constant := implementation-defined integer value;
    function Image (Of_State: State) return String;
    function Value (Coded_State: String) return State;
  private
    ... -- not specified by Gralia
  end Exponential_Pkg;

  package Normal_Pkg is
    type Generator is limited private;
    function Random (Gen: Generator) return Float;
    procedure Reset (Gen: in Generator; Initiator: in Integer);
    procedure Reset (Gen: in Generator);
    type State is private;
    procedure Save (Gen: in Generator; To_State: out State);
    procedure Reset (Gen: in Generator; From_State: in State);
    Max_Image_Width: constant := implementation-defined integer value;
    function Image (Of_State: State) return String;
    function Value (Coded_State: String) return State;
  private
    ... -- not specified by Gralia
  end Normal_Pkg;


(end of note)



^ permalink raw reply	[relevance 8%]

* Re: GMGPL (was Improved version (2002/1/26) of MT19937 PRNG)
  2002-02-09  1:55  5%     ` Adrian Hoe
@ 2002-02-09  5:56  0%       ` David Starner
  0 siblings, 0 replies; 106+ results
From: David Starner @ 2002-02-09  5:56 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1134 bytes --]

On Sat, 09 Feb 2002 09:55:48 +0800, Adrian Hoe <byhoe@greenlime.com> wrote:
> I released a package MT19937 and was GPL'ed few days ago. My new
> revision would contain the code from package Ada.Numerics.Float_Random
> (a-nuflra.adb) which is GMGPL'ed. So my new revision would also be
> GMGPL'ed. And of course, the package will be switched from GPL to GMGPL
> or both.

Your code doesn't nessecarily have to be GMGPL'ed. You can add GMGPL
code to a GPL program, and leave it GPL; the GMGPL code still retains
the license, but any permissions above the GPL would be moot if you
couldn't use the code without your GPL'ed additions.
 
> But I thought GMGPL (or/and GPL?) supposed to be standard? Why exist the
> authors' own interpretation of GMGPL, if any?

Just standard legal reality. If you disagree with how someone is using
your code, you get to chose whether to sue them or not. 

-- 
David Starner / Давид Старнзр - starner@okstate.edu
Pointless website: http://dvdeug.dhis.org
What we've got is a blue-light special on truth. It's the hottest thing 
with the youth. -- Information Society, "Peace and Love, Inc."



^ permalink raw reply	[relevance 0%]

* Re: GMGPL (was Improved version (2002/1/26) of MT19937 PRNG)
  @ 2002-02-09  1:55  5%     ` Adrian Hoe
  2002-02-09  5:56  0%       ` David Starner
  0 siblings, 1 reply; 106+ results
From: Adrian Hoe @ 2002-02-09  1:55 UTC (permalink / raw)


Ted Dennison wrote:
> 
> Adrian Hoe <byhoe@greenlime.com> wrote in message news:<3C632D2C.83BBBB1@greenlime.com>...
> > To my understanding, I can copy the code into my source and mention the
> > origin and the authors of this copied code in my source and I will have
> > to also released my work under GMGPL.
> 
> If you are saying that the units that will contain the copied code
> will be GMGPL'ed, that sounds right to me. If you are worried about
> it, I'd suggest contacting the authors. Its their interpretation of
> the GMGPL that will decide whether or not you will actually have legal
> hassles.


I do not wish to waste the bandwidth. But I guess it is good to get
everyone's (if possible) opinions. This is the first time for me to
release work under GMGPL which contains other people's code which is
also GMGPL'ed.

I released a package MT19937 and was GPL'ed few days ago. My new
revision would contain the code from package Ada.Numerics.Float_Random
(a-nuflra.adb) which is GMGPL'ed. So my new revision would also be
GMGPL'ed. And of course, the package will be switched from GPL to GMGPL
or both.

But I thought GMGPL (or/and GPL?) supposed to be standard? Why exist the
authors' own interpretation of GMGPL, if any?


> --
> T.E.D.

-- 
                              -- Adrian Hoe
                              -- http://greenlime.com/users/adrian.hoe



^ permalink raw reply	[relevance 5%]

* Re: Dimensionality Checking (Ada 20XX)
  2001-12-14 22:01  5%                   ` Nick Roberts
@ 2001-12-17 11:10  0%                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 106+ results
From: Dmitry A. Kazakov @ 2001-12-17 11:10 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 4239 bytes --]

On Fri, 14 Dec 2001 22:01:23 -0000, "Nick Roberts"
<nickroberts@adaos.worldonline.co.uk> wrote:

>So, the expression Exp(X) is dimensionless, and X must be (checked to be)
>dimensionless. Ditto for Log(X).
>
>The same is also true for the trigonometric functions. I recall someone
>posting in this thread suggesting, in effect, that the same is also true for
>square root; I'd like this confirmed.

The equation X <unitX>*X <unitX> = Y <unitY> has a solution when Y is
not negative and <unitY> has even powers of all base units. Thus we
could define sqrt.

>Secondly, I suppose the standard package
>Ada.Numerics.Generic_Elementary_Functions could and should check (upon
>instantiation) that the generic parameter type Float_Type is either
>dimensionless or not unit-specific. Am I correct in assuming that the Cycle
>parameter must always be dimensionless?
>
>I have accepted the idea of units being applicable to floating point types,
>as well as fixed point types, with the concern that unit-specific floating
>point types are (more) liable to abuse. Am I right that
>Ada.Numerics.Float_Random.Uniformly_Distributed should not be unit-specific?

>As a slightly separate issue, is there any merit in the idea of adding
>standard packages that provide Log, Exp, sin, Cos, Tan, etc. for fixed point
>types?

Let's look at this from slightly other point of view. I believe that
there is a lot of confusion between units and scales. Your wish to
have "logarithmic" units is rightful and IMO there is an answer. It
sounds "logarithmic scale". A scale determines the representation of a
value, but not its dimension. With scales there would be also no fixed
vs. floating point dilemma. Both are *just* different scales of the
same thing *real number*. Same is with units. There is no log(m), but
there can be logarithmically graduated scales of meters. If I dare to
misuse Ada (:-)) it could be something like:

type meters is ...
type log_meters is ...

if x is of meters then

log_meters (x) = log_meters'Val (log (meters'Pos(x)))

From this point of view Celsius degree is of course Kelvin scaled by
s(x)=x+273.15. Foot is a proportionally scaled Meter etc. Happily
there is no need in Cycle parameter for sin/cos, because rad and
degree are of different scales [but of same unit 1 SI]. 

So dimensioned types of values should be characterized by two
attributes, discriminants, tag whatsoever: unit and scale.

[ I played with this idea for a while. It is easy to make unit
discriminant a modular number. Unfortunately an attempt to use access
type discriminants to represent scales is doomed to fail, because then
the type shall be limited. Damn, but there are good reasons why the
type with a discriminant of an access type shall be limited (sigh) ]

Differently scaled values cannot be mixed but can be explicitly
converted. Values of same scale can be added and subtracted [when unit
is same], multiplied and divided.

Now problems (:-():

1. There are different ways to define operations on scaled values. For
instance: s(X+Y) vs. s(X)+s(Y). With �C we are using the first way
[2�C+2�C=4�C], with floating point numbers the second. [for scales
s(x)=ax and additive/multiplicative operations they are equivalent].

2. Multiplicative operations may produce new scales.

3. Scales and units should be matched rather "by-structure" than
by-name.

Last note. If we want to do it consistently then of course there
should be a possibility to assign units to any type. Consider complex
numbers, matrices etc.

a) Let I want to implement fuzzy readings. Then I should have an
ability to write "type Fuzzy_Number is private;" and give some public
specification that it has a dimension.

b) A biz application could treat currency as a unit and different
currencies as fixed point numbers of different scales with no loss of
precision as long all calculations are made in one currency.

c) Let I write a matrix package. I would like to define matrices of
different sizes as ones having different units. For instance NxN and
Nx1 should be two different units, so I cannot add matrices of this
sizes. Yet I can multiple one of NxN to Nx1 and have Nx1 matrix
(vector). Then I leave all checks to the compiler (:-))

Regards,
Dmitry Kazakov



^ permalink raw reply	[relevance 0%]

* Re: Dimensionality Checking (Ada 20XX)
  @ 2001-12-14 22:01  5%                   ` Nick Roberts
  2001-12-17 11:10  0%                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 106+ results
From: Nick Roberts @ 2001-12-14 22:01 UTC (permalink / raw)


Dmitry, you're an absolute gem! It's worth a thousand "well I reckon"s to
actually produce the proof.

I have been doing a bit of reading up on dimensionsal analysis, and from
what I can tell from 'the texts', any and all exponentiations and logarithms
are dimensionless, and their arguments must be dimensionless (of dimensions
all 0).

So, the expression Exp(X) is dimensionless, and X must be (checked to be)
dimensionless. Ditto for Log(X).

The same is also true for the trigonometric functions. I recall someone
posting in this thread suggesting, in effect, that the same is also true for
square root; I'd like this confirmed.

So, may I first apologise for the confusion I seem to sow in my wake like a
talented double-glazing salesman. Secondly, I suppose the standard package
Ada.Numerics.Generic_Elementary_Functions could and should check (upon
instantiation) that the generic parameter type Float_Type is either
dimensionless or not unit-specific. Am I correct in assuming that the Cycle
parameter must always be dimensionless?

I have accepted the idea of units being applicable to floating point types,
as well as fixed point types, with the concern that unit-specific floating
point types are (more) liable to abuse. Am I right that
Ada.Numerics.Float_Random.Uniformly_Distributed should not be unit-specific?

As a slightly separate issue, is there any merit in the idea of adding
standard packages that provide Log, Exp, sin, Cos, Tan, etc. for fixed point
types?

--
Best wishes,
Nick Roberts






^ permalink raw reply	[relevance 5%]

* Re: Random Number Generator
  @ 2000-02-26  0:00  6% ` David C. Hoos, Sr.
  0 siblings, 0 replies; 106+ results
From: David C. Hoos, Sr. @ 2000-02-26  0:00 UTC (permalink / raw)



Hustler <bdowney@wvu.edu> wrote in message
news:8981l1$1dfqk$1@homer.cfw.com...
> Does anyone know where the number generator is located, ie the package? Is
> it in ada.elementary_functions packages or do I need to find a package
that
> contains a random number generator?
For pseudo-random floating-point random numbers, it's in the package
Ada.Numerics.Float_Random.  For pseudo-random integers and enumeration type
it's in the package Ada.Numerics.Discrete_Random.








^ permalink raw reply	[relevance 6%]

* Re: Gnat Chat, Random Numbers in GNAT
  2000-01-24  0:00  3% Gnat Chat, Random Numbers in GNAT Kent Paul Dolan
  2000-01-24  0:00  0% ` Gisle S�lensminde
@ 2000-02-06  0:00  0% ` Ashley Deas Eachus
  2000-02-06  0:00  0%   ` Kent Paul Dolan
  1 sibling, 1 reply; 106+ results
From: Ashley Deas Eachus @ 2000-02-06  0:00 UTC (permalink / raw)


Kent Paul Dolan wrote:

> I want to do some genetic algorithm (GA) programming in GNAT, to do
> proof of concept for some new approaches I've been mulling to speed up
> convergence and remove the need for sorts, and I need to know about the
> kind and quality of the Ada.Numerics.Float_Random implementation in
> GNAT, to decide whether I can trust it to work well in a statistical
> distribution sense when called (probably) hundreds of millions of times
> in a single program run (you may guess that I have abundant cpu cycles
> at work, and you'd be correct, at least 15 machines behind our firewall
> sit mostly idle for good reason that my using them for week long low
> priority GA runs wouldn't impact significantly).
>
> Header excerpts from the source, from someone who knows right where to
> look, so I don't have to slog through it from a zero knowledge starting
> point, would be a perfectly fine answer, if the info is there.  Formal
> pseudorandom number generator test reports of whatever style have
> become popular since I was last doing that kind of quality control
> personally back in the sixties would be good.  Anecdotal personal
> experience is also welcome as an answer.  URLs pointing to any of the
> non-source code information would be equally useful.

      Haven't seen you around for a while Kent, but I am probably the best
one to answer this, since it is sort of my algorithm.   (The sequence
generated is a Blum, Blum, and Shub sequence, which for your purposes will
be polynomial-time unpredictable, but the implementation tricks to generate
it efficiently are mine.)   In any case, for the size of GA run you are
anticipating, there are three other factors to consider.  You will not
exceed the period of the generator, but you will probably get into the
range where the generator could be predicted from the previous state
information you have used.  Since for most generators, this happens when
you have have used under a dozen, and in some cases a single value, this is
more of theoretical interest.

      The second issue is that the number of possible values generated does
not completely cover all of the representable values in [0.0 .. 1.0).
Again the generator in gnat is much better than most in this area, but it
only generates about 2**50 values, so there are small floating-point values
near zero that cannot be generated.  Not a big worry, unless you are
creating events with a very small probability of occurring.

      Finally, and very important, if you use several instances of this
generator, you must concern yourself with distributing entropy to the
various generators.  (One generator per Ada task that needs random variates
is probably best.)  You need to insure that multiple generators don't start
with the same seed.  The algorithm for initializing the generator is such
that providing such seeds in sequence works fine, but the standard Ada
interface limits you to 2**32 possible starting values.   The simple model
for GA would create lots of tasks, and you might start pushing that limit.
So recycle tasks without resetting the task specific generator and you
should be fine.

      If this particular generator is not sufficient for your purpose, I
can send you an electronic copy of the design paper.  It has a few other
prime pairs in it that will give you a longer period and more possible
values.  I only recommend this if you are using more than 64-bit
floating-point, and expect to generate more than 10**40 variates in a
single run.





^ permalink raw reply	[relevance 0%]

* Re: Gnat Chat, Random Numbers in GNAT
  2000-02-06  0:00  0% ` Ashley Deas Eachus
@ 2000-02-06  0:00  0%   ` Kent Paul Dolan
  0 siblings, 0 replies; 106+ results
From: Kent Paul Dolan @ 2000-02-06  0:00 UTC (permalink / raw)


Ashley Deas Eachus  <rieachus@earthlink.net> wrote:
>Kent Paul Dolan wrote:

>> ...I need to know about the
>> kind and quality of the Ada.Numerics.Float_Random implementation in
>> GNAT, to decide whether I can trust it to work well in a statistical
>> distribution sense when called (probably) hundreds of millions of times
>> in a single program run

>      Haven't seen you around for a while Kent,

Oh, I never go away, but my attention drifts around the net a lot.  Since I
have little of value to contribute to comp.lang.ada, I can resist the urge
to post for sometimes months in a row of lurking.

>but I am probably the best
>one to answer this, since it is sort of my algorithm.

Always nice to find an authoritative opinion, I always say.

>(The sequence
>generated is a Blum, Blum, and Shub sequence, which for your purposes will
>be polynomial-time unpredictable, but the implementation tricks to generate
>it efficiently are mine.)   In any case, for the size of GA run you are
>anticipating, there are three other factors to consider.  You will not
>exceed the period of the generator, but you will probably get into the
>range where the generator could be predicted from the previous state
>information you have used.  Since for most generators, this happens when
>you have have used under a dozen, and in some cases a single value, this is
>more of theoretical interest.

Not a problem, since there is no cryptographic aspect to the use.

>      The second issue is that the number of possible values generated does
>not completely cover all of the representable values in [0.0 .. 1.0).
>Again the generator in gnat is much better than most in this area, but it
>only generates about 2**50 values, so there are small floating-point values
>near zero that cannot be generated.  Not a big worry, unless you are
>creating events with a very small probability of occurring.

Hmm.  Thanks for the warning, I'll need to be very careful about that, there
are other ways to get messed up by discontinuities in the generated random
numbers.  The current Java applet which I would like to improve upon:

http://www.coyotegulch.com/alife/Traveller.html

for which I don't yet have the source, can go at least the square of the
expected number of iterations expected to accomplish a certain change, without
making that change.  It
is hard to isolate that to algorithm problems or RNG problems based just
on the symptoms, so I have to be very careful about the RNG ideosyncracies.

>      Finally, and very important, if you use several instances of this
>generator, you must concern yourself with distributing entropy to the
>various generators.  (One generator per Ada task that needs random variates
>is probably best.)  You need to insure that multiple generators don't start
>with the same seed.  The algorithm for initializing the generator is such
>that providing such seeds in sequence works fine, but the standard Ada
>interface limits you to 2**32 possible starting values.

One can only hope that will be fixed _real soon now_; that's a pretty terrible
misfeature.

>The simple model
>for GA would create lots of tasks, and you might start pushing that limit.
>So recycle tasks without resetting the task specific generator and you
>should be fine.

Thanks again for the warning.

>      If this particular generator is not sufficient for your purpose, I
>can send you an electronic copy of the design paper.  It has a few other
>prime pairs in it that will give you a longer period and more possible
>values.  I only recommend this if you are using more than 64-bit
>floating-point, and expect to generate more than 10**40 variates in a
>single run.

I'd like the paper just for the education I'll gain reading it.  I can cope
with *.html, *.ps, *.pdf immediately, TeX with a little trouble I need to
undergo anyway, MS word with some pain, and Framemaker with some expense,
in case you have a choice of formats.

My work email would be best: xanthian@whistle.com.

Thanks very much for your help!



               ===== random archival quality quote =====

[the new kind of mysticism called Quantum Mind] must be rejected as
non-parsimonious, especially since we have in our hands a perfectly
economical and logically-consistent theory that agrees with all the
data and requires no additional component in the universe beyond
matter.
   -- http://www.phys.hawaii.edu/vjs/www/meta.txt Victor J. Stenger

--
Kent Paul Dolan.
<xanthian@well.com> <xanthian@aztec.asu.edu> <xanthian@whistle.com>





^ permalink raw reply	[relevance 0%]

* Re: Gnat Chat, Random Numbers in GNAT
  2000-01-24  0:00  6%   ` Jeff Carter
@ 2000-01-26  0:00  0%     ` Kent Paul Dolan
  0 siblings, 0 replies; 106+ results
From: Kent Paul Dolan @ 2000-01-26  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 4158 bytes --]

Jeff Carter  <jrcarter@acm.org> wrote:
>"Gisle S�lensminde" wrote:

>> In article <SLSi4.702$dw3.34085@news.wenet.net>, Kent Paul Dolan wrote:
>> >I want to do some genetic algorithm (GA) programming in GNAT, to do
>> >proof of concept for some new approaches I've been mulling to speed up
>> >convergence and remove the need for sorts, and I need to know about the
>> >kind and quality of the Ada.Numerics.Float_Random implementation in
>> >GNAT, to decide whether I can trust it to work well in a statistical
>> >distribution sense when called (probably) hundreds of millions of times
>> >in a single program run (you may guess that I have abundant cpu cycles
>> >at work, and you'd be correct, at least 15 machines behind our firewall
>> >sit mostly idle for good reason that my using them for week long low
>> >priority GA runs wouldn't impact significantly).

>> >Header excerpts from the source, from someone who knows right where to
>> >look, so I don't have to slog through it from a zero knowledge starting
>> >point, would be a perfectly fine answer, if the info is there.  Formal
>> >pseudorandom number generator test reports of whatever style have
>> >become popular since I was last doing that kind of quality control
>> >personally back in the sixties would be good.  Anecdotal personal
>> >experience is also welcome as an answer.  URLs pointing to any of the
>> >non-source code information would be equally useful.

>> >Thanks for any help.  I read and archive this newsgroup daily, so an
>> >email response is welcome, but not necessary.

>> In the gnat runtime library sources I found the following comment
>> in bot the float_random and discrete_random packages, on how they
>> are implemented.

>> --  Note: the implementation used in this package was contributed by
>> --  Robert Eachus. It is based on the work of L. Blum, M. Blum, and
>> --  M. Shub, SIAM Journal of Computing, Vol 15. No 2, May 1986. The
>> --  particular choices for P and Q chosen here guarantee a period of
>> --  562,085,314,430,582 (about 2**49), and the generated sequence has
>> --  excellent randomness properties. For further details, see the
>> --  paper "Fast Generation of Trustworthy Random Numbers", by Robert
>> --  Eachus, which describes both the algorithm and the efficient
>> --  implementation approach used here. This paper is available at
>> --  the Ada Core Technologies web site (http://www.gnat.com).

Thanks Gisel!  That is more than good enough for my modest needs.

>The sources of Ada.Numerics.Float_Random for GNAT are in a-nuflra.ad?

>If you have GNAT, you can examine the implementation for yourself.

I have gnat, and can easily bring it down again from the FreeBSD
/usr/ports mechanisms with a few keystrokes, but now there's no need.
On my stingy hard drive, by choice, the sources disappeared with the
object modules when I cleaned up after building gnat.

>FWIW (personal experience anecdote), I did a parking-lot test of both
>Float_Random and Marsaglia's Universal Random-Number algorithm and no
>structure was apparent in either.

Thanks for that reassurance, too, Jeff.

>I can provide you with Ada source for the Marsaglia generator if you
>have tests you'd like to run on it.

Thanks, Jeff.  No, as I said earlier, my 1962-era random number generator
testing experience is pretty useless today, and I'm more than willing to
go ahead on the advice of others.  I've just been burned a dozen or more
times by RNGs delivered as part of compilers and interpreters that were
of very low quality, so I wanted to see if someone else had "tried" before
I "buyed"(sic).  I don't have any reason to distrust the gnat implementation,
I just needed some help to trust it; I'm happy to hear that Dr. Dewar and
the rest of the ACT troups have done their usual professional job.

               ===== random archival quality quote =====

"...Roxanne  falls  in  love  with  Christian,  a  cavileer  in Cyrano's
regiment who hasn't got the brains god gave an eclair..."
                                                      -- reviewer on NPR

--
Kent Paul Dolan.
<xanthian@well.com> <xanthian@aztec.asu.edu> <xanthian@whistle.com>





^ permalink raw reply	[relevance 0%]

* Re: Gnat Chat, Random Numbers in GNAT
  2000-01-24  0:00  0% ` Gisle S�lensminde
@ 2000-01-24  0:00  6%   ` Jeff Carter
  2000-01-26  0:00  0%     ` Kent Paul Dolan
  0 siblings, 1 reply; 106+ results
From: Jeff Carter @ 2000-01-24  0:00 UTC (permalink / raw)


"Gisle S�lensminde" wrote:
> 
> In article <SLSi4.702$dw3.34085@news.wenet.net>, Kent Paul Dolan wrote:
> >I want to do some genetic algorithm (GA) programming in GNAT, to do
> >proof of concept for some new approaches I've been mulling to speed up
> >convergence and remove the need for sorts, and I need to know about the
> >kind and quality of the Ada.Numerics.Float_Random implementation in
> >GNAT, to decide whether I can trust it to work well in a statistical
> >distribution sense when called (probably) hundreds of millions of times
> >in a single program run (you may guess that I have abundant cpu cycles
> >at work, and you'd be correct, at least 15 machines behind our firewall
> >sit mostly idle for good reason that my using them for week long low
> >priority GA runs wouldn't impact significantly).
> >
> >Header excerpts from the source, from someone who knows right where to
> >look, so I don't have to slog through it from a zero knowledge starting
> >point, would be a perfectly fine answer, if the info is there.  Formal
> >pseudorandom number generator test reports of whatever style have
> >become popular since I was last doing that kind of quality control
> >personally back in the sixties would be good.  Anecdotal personal
> >experience is also welcome as an answer.  URLs pointing to any of the
> >non-source code information would be equally useful.
> >
> >Thanks for any help.  I read and archive this newsgroup daily, so an
> >email response is welcome, but not necessary.
> 
> In the gnat runtime library sources I found the following comment
> in bot the float_random and discrete_random packages, on how they
> are implemented.
> 
> --  Note: the implementation used in this package was contributed by
> --  Robert Eachus. It is based on the work of L. Blum, M. Blum, and
> --  M. Shub, SIAM Journal of Computing, Vol 15. No 2, May 1986. The
> --  particular choices for P and Q chosen here guarantee a period of
> --  562,085,314,430,582 (about 2**49), and the generated sequence has
> --  excellent randomness properties. For further details, see the
> --  paper "Fast Generation of Trustworthy Random Numbers", by Robert
> --  Eachus, which describes both the algorithm and the efficient
> --  implementation approach used here. This paper is available at
> --  the Ada Core Technologies web site (http://www.gnat.com).

The sources of Ada.Numerics.Float_Random for GNAT are in a-nuflra.ad?

If you have GNAT, you can examine the implementation for yourself.

FWIW (personal experience anecdote), I did a parking-lot test of both
Float_Random and Marsaglia's Universal Random-Number algorithm and no
structure was apparent in either.

I can provide you with Ada source for the Marsaglia generator if you
have tests you'd like to run on it.

-- 
Jeff Carter
"Monsieur Arthur King, who has the brain of a duck, you know."
Monty Python & the Holy Grail




^ permalink raw reply	[relevance 6%]

* Gnat Chat, Random Numbers in GNAT
@ 2000-01-24  0:00  3% Kent Paul Dolan
  2000-01-24  0:00  0% ` Gisle S�lensminde
  2000-02-06  0:00  0% ` Ashley Deas Eachus
  0 siblings, 2 replies; 106+ results
From: Kent Paul Dolan @ 2000-01-24  0:00 UTC (permalink / raw)


Aside:

I realize this should go to the Gnat Chat mailing list, but I'm on too
many mailing lists as it is, so my first question is, would it be
appropriate, and would there be any interest in or support for moving
Gnat Chat to a new leaf of comp.lang.ada?  I'm assuming without
evidence that the level of traffic would justify a newsgroup, and I
much prefer newsgroup threading to mailing list linearity.

If several anyones encourage me quite a bit, and no furor of protest
emerges, I'd do a newsgroup RFD to make comp.lang.ada into
comp.lang.ada.*, but I'd like before going to the four months of
trouble that would take to find out if there would be any interest in a
split, and if so along what lines people would like to see things
divided.  I will confess in advance that there is nothing that
overwhelming about the traffic in comp.lang.ada, I just like more
neatly sorted out conversations.

Whatever.

On to my main agenda.

I want to do some genetic algorithm (GA) programming in GNAT, to do
proof of concept for some new approaches I've been mulling to speed up
convergence and remove the need for sorts, and I need to know about the
kind and quality of the Ada.Numerics.Float_Random implementation in
GNAT, to decide whether I can trust it to work well in a statistical
distribution sense when called (probably) hundreds of millions of times
in a single program run (you may guess that I have abundant cpu cycles
at work, and you'd be correct, at least 15 machines behind our firewall
sit mostly idle for good reason that my using them for week long low
priority GA runs wouldn't impact significantly).

Header excerpts from the source, from someone who knows right where to
look, so I don't have to slog through it from a zero knowledge starting
point, would be a perfectly fine answer, if the info is there.  Formal
pseudorandom number generator test reports of whatever style have
become popular since I was last doing that kind of quality control
personally back in the sixties would be good.  Anecdotal personal
experience is also welcome as an answer.  URLs pointing to any of the
non-source code information would be equally useful.

Thanks for any help.  I read and archive this newsgroup daily, so an
email response is welcome, but not necessary.

--
Kent Paul Dolan.
<xanthian@well.com> <xanthian@aztec.asu.edu> <xanthian@whistle.com>




^ permalink raw reply	[relevance 3%]

* Re: Gnat Chat, Random Numbers in GNAT
  2000-01-24  0:00  3% Gnat Chat, Random Numbers in GNAT Kent Paul Dolan
@ 2000-01-24  0:00  0% ` Gisle S�lensminde
  2000-01-24  0:00  6%   ` Jeff Carter
  2000-02-06  0:00  0% ` Ashley Deas Eachus
  1 sibling, 1 reply; 106+ results
From: Gisle S�lensminde @ 2000-01-24  0:00 UTC (permalink / raw)


In article <SLSi4.702$dw3.34085@news.wenet.net>, Kent Paul Dolan wrote:
>Aside:
>On to my main agenda.
>
>I want to do some genetic algorithm (GA) programming in GNAT, to do
>proof of concept for some new approaches I've been mulling to speed up
>convergence and remove the need for sorts, and I need to know about the
>kind and quality of the Ada.Numerics.Float_Random implementation in
>GNAT, to decide whether I can trust it to work well in a statistical
>distribution sense when called (probably) hundreds of millions of times
>in a single program run (you may guess that I have abundant cpu cycles
>at work, and you'd be correct, at least 15 machines behind our firewall
>sit mostly idle for good reason that my using them for week long low
>priority GA runs wouldn't impact significantly).
>
>Header excerpts from the source, from someone who knows right where to
>look, so I don't have to slog through it from a zero knowledge starting
>point, would be a perfectly fine answer, if the info is there.  Formal
>pseudorandom number generator test reports of whatever style have
>become popular since I was last doing that kind of quality control
>personally back in the sixties would be good.  Anecdotal personal
>experience is also welcome as an answer.  URLs pointing to any of the
>non-source code information would be equally useful.
>
>Thanks for any help.  I read and archive this newsgroup daily, so an
>email response is welcome, but not necessary.

In the gnat runtime library sources I found the following comment
in bot the float_random and discrete_random packages, on how they
are implemented. 

--  Note: the implementation used in this package was contributed by
--  Robert Eachus. It is based on the work of L. Blum, M. Blum, and
--  M. Shub, SIAM Journal of Computing, Vol 15. No 2, May 1986. The
--  particular choices for P and Q chosen here guarantee a period of
--  562,085,314,430,582 (about 2**49), and the generated sequence has
--  excellent randomness properties. For further details, see the
--  paper "Fast Generation of Trustworthy Random Numbers", by Robert
--  Eachus, which describes both the algorithm and the efficient
--  implementation approach used here. This paper is available at
--  the Ada Core Technologies web site (http://www.gnat.com).




--
Gisle S�lensminde ( gisle@ii.uib.no )   

ln -s /dev/null ~/.netscape/cookies




^ permalink raw reply	[relevance 0%]

* Re: Elimination of "use" clauses
  @ 1999-07-02  0:00  3%     ` Robert Dewar
  0 siblings, 0 replies; 106+ results
From: Robert Dewar @ 1999-07-02  0:00 UTC (permalink / raw)


In article <377CE178.6C15F543@hso.link.com>,
  "Samuel T. Harris" <sam_harris@hso.link.com> wrote:
> There are times when no tool can be of any help.
> Doing work for NASA, we have customers which insist on
> reviewing code in their private work area. With no
> connectivity to our environment, they do not have
> access to our tools. Some of they even require hardcopy
> and reject any electronic form.

Well there are people who refuse to drive automobiles, but
that does not mean that we necessarily take into account
those requirements in deciding how to layout our highways.
You may also have customers who require Hungarian notation,
but that does not mean it is a good thing.

Yes, of course a dotifier (or for that matter a Hungarianizer)
may be useful in bizarre environments

> So the problem is not entirely handled by good tools.
> Reasonable restrictions on the use clause are still
> appropriate to support such edge cases.

Well be careful. By supporting such edge cases, you may be
making the programs harder to read and work with by everyone
else.

As I pointed out in a previous message, it is actually
relatively unusual for people to fully qualify, that is
especially true in these days of child packages.

Do you really want to say:

   X := Ada.Numerics.Float_Random.Random (Gen);

rather than

   X := Random (Gen);

?
and that is by NO means the worst case. Well if you are really
usephobic, or worse, live in an environment which mandates that
use be disallowed (I have encountered such absurdities), then
you end up doing a package renaming:

   X := NFR.Random (Gen);

But this is *precisely* no help at all if you have decent
tools, and creates useless noise. It does not tell you
immediately where something is. The only purpose of the
prefix NFR is to help you find the declaration of Random
using decrepit tools. That to me is hard to justify.

Once again, I think the critical factor is to consider what
makes the code clearer. If you have people who insist on wasting
their time by reading the code on paper, by all means get a
dotifying tool and give them the entire long form above if
that's what they want!

Note that I am not arguing against qualification, just trying to
stress that the decision to qualify should be based on factors
other than the requirement of using decrepit tools. Of course
there are those who have no choice. Fine, but that does not
provide a source of inspiration on what ideal Ada style should
be in an ideal environment.

(actually for me, I agree with what someone wrote earlier, any
Ada environment not providing this capability is broken and
unusable as far as I am concerned). Even if you use FULL
qualification, it is nowhere NEAR as convenient as going
directly to the declaration with a decent tool. If you have
not tried working in such an environment, give it a try, you
may find it enlightening (and not have to reach so often for
the baseball bat :-)


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




^ permalink raw reply	[relevance 3%]

* Re: 'Random' function in Ada
@ 1999-05-27  0:00  6% Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 1999-05-27  0:00 UTC (permalink / raw)




iang@iplbath.com wrote:
> 
> Does anyone know of the existence of a freely available or easily
> implementable Random function in Ada?
 
    Yes.  Look in Ada.Numerics.Float_Random or
Ada.Numerics.Discrete_Random, or in the reference manual in A.5.2.  If
you are using Ada 83, or care a lot about algorithms used, send me
e-mail. 
-- 

                                        Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[relevance 6%]

* Re: (no subject)
  @ 1998-11-13  0:00  7%   ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 1998-11-13  0:00 UTC (permalink / raw)


In article <72hgcq$5d4$1@nnrp1.dejanews.com> dennison@telepath.com writes:

  > Ada.Numerics.Discrete_Random

  Good answer, but there is a typo/bug in gnat 3.10p and some earlier
versions that causes it to generate biased results. This program will
show you if you have the problem, if the values for the three doors
are not approximately equal.  (The fix is trivial, correct the sign in
the line below, but cause confusion by broadcasting a non-CM version
of the package. Of course, if you fix the installed version you have
to recompile it with -gnatg.)


  if TF > Flt (Rst'Pos (Rst'Last)) + 0.5 then
         return Rst'First;


----------------------------------------------------------------------------

with Discrete_Random;
with Ada.Numerics.Float_Random;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
procedure Random_Bug is
   Tries: constant := 10000;
   Wins, Switch_Wins, Offers: Integer := 0;
   type Doors is (Door1, Door2, Door3);
   package Select_Door is new Discrete_Random(Doors);
   Door_Gen: Select_Door.Generator;
   function Random_Door(Gen: in Select_Door.Generator := Door_Gen)
           return Doors renames Select_Door.Random;
   Float_Gen: Ada.Numerics.Float_Random.Generator;
   function Rand(Gen: in Ada.Numerics.Float_Random.Generator :=
Float_Gen)
           return Float renames Ada.Numerics.Float_Random.Random;
   Door_Counts: array(Doors) of Integer := (0,0,0);
   Old_Door, New_Door: Doors;
begin

   Select_Door.Reset(Door_Gen);
   Old_Door := Random_Door;
   for Test in 1..8 loop
     Door_Counts := (0,0,0);
     Wins := 0;
     for I in 1..Tries loop
       New_Door := Random_Door;
       Door_Counts(New_Door) := Door_Counts(New_Door) + 1;
       if New_Door = Old_Door then Wins := Wins + 1; end if;
       Old_Door := New_Door;
     end loop;
     Put (" Door 1: " & Integer'Image(Door_Counts(Door1)));
     Put (" Door 2: " & Integer'Image(Door_Counts(Door2)));
     Put (" Door 3: " & Integer'Image(Door_Counts(Door3)));
     New_Line;
     Put (" Wins: " & Integer'Image(Wins));
     New_Line(2);
   end loop;
  
end Random_Bug;

--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[relevance 7%]

* Re: Long Float Error from Gnat
  @ 1998-10-30  0:00  7%   ` Al Christians
  0 siblings, 0 replies; 106+ results
From: Al Christians @ 1998-10-30  0:00 UTC (permalink / raw)


The problem is a little stranger than previously presented.  The 
program below will generate lots of errors with other values of
aft than 9.  The errors all seem to occur when the negative of the
exponent plus the digits after the decimal equals 41.  Wow!

Al

------------------------------------------------------------------------------

with Ada.Text_Io;
with Ada.Long_Float_Text_Io;
with Ada.Numerics.Long_Elementary_Functions;
with Ada.Numerics.Float_Random;
procedure Numeric_Test is

   The_Generator:  Ada.Numerics.Float_Random.Generator;

   function Generate_Random_Number return Long_Float is
   x:   Long_Float;
   begin
      X := Long_Float( Ada.Numerics.Float_Random.Random( The_Generator )
);
      X := X * 300.0 - 150.0;
      return Ada.Numerics.Long_Elementary_Functions.exp( X );
   end;


   Number_Of_Tests:   Natural := 1_000_000;
   X:       Long_Float;
   Y:       Long_Float;
   Count:   Integer  := 0;
   X_String,
   Y_String:   String(1..30);
   Last_Pos:   Natural;
   Largest:    Long_Float := -99.99E+99;
   Smallest:   Long_Float := +99.99E+99;

begin
   for I in 1..Number_Of_Tests loop
      X := Generate_Random_Number;
         for Digits_Aft in 6..12 loop
            begin
               Ada.Long_Float_Text_Io.Put( X_String, X, Aft =>
Digits_Aft );
               Ada.Long_Float_Text_Io.Get( X_String, Y, Last_Pos );
               Ada.Long_Float_Text_Io.Put( Y_String, Y, Aft =>
Digits_Aft );
               if  X_String /= Y_String then
                  Ada.Text_Io.Put( "Aft =>" & Integer'Image( Digits_Aft
) );
                  Ada.Text_Io.Put( Long_Float'Image(X) );
                  Ada.Text_Io.Put( "   ");
                  Ada.Text_Io.Put( Long_Float'Image(Y) );
                  Ada.Text_Io.New_Line;
                  if  x > Largest then
                     Largest := X;
                  end if;
                  if  x < Smallest then
                     Smallest := X;
                  end if;
                  Count := Count + 1;
               end if;
            exception
               when others =>
                  Ada.Text_Io.Put( "Exception:" & Long_Float'Image(X) );
                  Ada.Text_Io.Put( "   Aft:" & Integer'Image(Digits_Aft)
);
            end;
      end loop;
   end loop;
   Ada.Text_IO.Put_Line( "Largest:  " & Long_Float'Image(Largest) );
   Ada.Text_IO.Put_Line( "Smallest: " & Long_Float'Image(Smallest) );
   Ada.Text_IO.Put_Line( "Count:    " & Integer'Image(Count) );
end Numeric_Test;




^ permalink raw reply	[relevance 7%]

* Re: Random numbers and ADA.
  @ 1997-11-22  0:00  6% ` Matthew Heaney
  0 siblings, 0 replies; 106+ results
From: Matthew Heaney @ 1997-11-22  0:00 UTC (permalink / raw)



In article <34738DD6.633867D7@wvu.edu>, Ghost <awillia8@wvu.edu> wrote:

>Hi,
>        I'm new to ADA, but I've programmed in a few other languages.  I was
>wondering if ADA has a predefined RANDOM function.  I know Pascal has
>one, and I think C does(never had to use it, oddly enough), but I
>haven't found anything about it in my rather limited ADA resources.
>Does such a function exist, and if it does, which package is it in?

Yes, a random number function exists.

Ada.Numerics.Float_Random
Ada.Numerics.Discrete_Random

P.S. Ada isn't an acronym, so you don't need to spell it in all-caps.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[relevance 6%]

* Re: need help in random numbers.
  @ 1997-06-13  0:00  7% ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 1997-06-13  0:00 UTC (permalink / raw)



In article <339FFFCD.B71A2392@telem.openu.ac.il> Amos Ortal <amosor@telem.openu.ac.il> writes:

  > How do I create random numbers, in ada.calendar.time type?

  Interesting problem, but let's first state it correctly:

  How do you create random values of type Ada.Calendar.Time?

  The immediate response is to ask:  With what distribution?  Over
what range?  And for what purpose?

  If the answers are uniform, Jan. 1, 1901..Dec. 31, 2099, and to test
year 2000 problems, I'd do the following:

  Look at the private part of Ada.Calendar, and discover the
representation of Time.  Write your own package, with an identical
declaration and use Unchecked_Coversion between the two.  In GNAT this
is pretty easy:

   type Time is new Duration;

   Determine the actual values for the range of interest (call them
FIRST_DATE and DOOM_DATE in this example), then write a package:

  with Ada.Calendar;
  package Random_Times is
    function Random_Time return Ada.Calendar.Time;
  end Random_Times;

  with Ada.Unchecked_Conversion;
  with Ada.Numerics.Float_Random;
  package body Random_Times is
  
    Gen: Ada.Numerics.Float_Random.Generator;

    function To_Duration is new
          Ada.Unchecked_Conversion(Ada.Calendar.Time,Duration);

    function To_Time is new
          Ada.Unchecked_Conversion(Duration,Ada.Calendar.Time);

    Doom_Date: constant Duration := 
           To_Duration(Ada.Calendar.Time_Of(2099,12,31,86399.99));
    First_Date: constant Duration := 
           To_Duration(Ada.Calendar.Time_Of(1901,1,1,0.0));
    Scale: constant Duration := Doom_Date-First_Date;
     -- Yes, I know that this could overflow, but in this example it
     -- won't and the work-around, if necessary, should be obvious.

    function Random_Time return Ada.Calendar.Time is
    begin
     return To_Time(First_Date + 
              Duration(Float(Scale) * Ada.Numerics.Float_Random.Random(Gen)));
    end Random_Time;

  begin
    Ada.Numerics.Float_Random.Reset(Gen);
    -- Don't forget this initialization call, or to a different
    -- version of Reset.
  end Random_Times;

  (Compiled, but not throughly tested.)






--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[relevance 7%]

* Re: How do you randomise integers?
  @ 1997-05-20  0:00  6% ` Nick Roberts
  0 siblings, 0 replies; 106+ results
From: Nick Roberts @ 1997-05-20  0:00 UTC (permalink / raw)





the AJE <whippet@light.iinet.net.au> wrote in article
<01bc6221$5c8b3100$1a8602cb@whippet>...
> I have only just begun learning ADA, but I can't find a book with decent
> examples on randomising numbers.  I could try using C++, but I much
prefer
> ADA.  The biggest problem is finding something to connect the randomizer
to
> the timer so that a different seed is used everytime the programme is
run. 
> I would appreciate some examples using dice-rolls etc. because I can't
> decipher syntaxes very well.


All standard implementations of Ada 95 must provide the packages
Ada.Numerics.Float_Random and Ada.Numerics.Discrete_Random, which provide
the facilities you require. In particular, calling the Reset procedure
without the Initiator parameter will seed the generator according to the
clock (in an implementation-defined manner).

A random (six-sided) dice-roll is easy to program using the Discrete_Random
package. First, declare a suitable subtype (or type):

   type Die_Face is range 1..6;

and then instantiate the package:

   package Dice_Random is new Ada.Numerics.Discrete_Random(Die_Face);
   use Dice_Random;

then declare a generator:

   type Die_Gen: Dice_Random.Generator;

and call Reset to seed by the clock:

   Reset(Die_Gen);

then you can call the Random function at any time to get a random 'dice
roll':

   DR: Die_Face;
   ...
   DR := Random(Die_Gen);

Hope this is of use.
Nick.





^ permalink raw reply	[relevance 6%]

* Re: Not intended for use in medical,
       [not found]                         ` <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com>
  1997-05-16  0:00  5%                       ` Robert A Duff
@ 1997-05-16  0:00  6%                       ` Robert Dewar
  1 sibling, 0 replies; 106+ results
From: Robert Dewar @ 1997-05-16  0:00 UTC (permalink / raw)



Nick asks/says

<<Would you care to give one or two examples?>>

  (of functions with useful side effects)
  No, I don't think so, this horse has been beaten to death too many times
  to be worth discussing any more. Well I will give just one phrase,
  memo functions, that should be enough! Note that this issue was
  discussed in the very early stages of the language design, and everyone
  agrees that there is a necessity in a language like Ada to permit
  functions with side effects. The issue that was discussed was whether
  to distinguish between functions without side effects, and value
  returning procedures with side effects. But even that attempt fails,
  because you can have functions that at a conceptual interface level
  are pure, but their implementations require side effects (memo functions
  are the canonical example). Note that it will work just fine to give
  the pragma Pure_Function in GNAT for a memo function, even though it
  has side effects.

<<Ada.Numerics.Float_Random and Ada.Numerics.Discrete_Random are
grandchildren of the package Ada, which is declared as pure, they must be
pure also, and pure packages are not allowed to have any state (such as
internal generators). Silly me. (Is this it, or is there some other reason
that I have missed?)>>

  The Pure is completely irrelevant here, the problem has no solution in
  pure Ada without using the heap even if you did not have pragma Pure.
  Furthermore the idea that children of a pure package must be pure is
  a pretty serious misconception about the whole structure of child
  packages. It is of course the other way round, you cannot have pure
  children of an impure parent, but OF COURSE you can have impure
  children of pure parents -- what would make you think this was not
  allowed.

<<Quite right. I was forgetting that as the packages
Ada.Numerics.Float_Random and Ada.Numerics.Discrete_Random are
grandchildren of the package Ada, which is declared as pure, they must be
pure also, and pure packages are not allowed to have any state (such as
internal generators). Silly me. (Is this it, or is there some other reason
that I have missed?)>>

  As above, you are confused.

<<However, I did spot that the RM95 has "pragma Pure(Ada.Numerics);" in the
Ada.Numerics package, which seems odd to me, since Ada.Numerics must be
pure anyway (because it's a child of Ada). Why the extra pragma Pure?>>

  If you see something that seems odd to you in the RM, it is quite likely
  that, as in this case, it corresponds to a misunderstanding on your part.
  As per above, there is no extra Pure, and the Pure here is important.





^ permalink raw reply	[relevance 6%]

* Re: Not intended for use in medical,
       [not found]                         ` <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com>
@ 1997-05-16  0:00  5%                       ` Robert A Duff
  1997-05-16  0:00  3%                         ` Robert I. Eachus
  1997-05-16  0:00  6%                       ` Robert Dewar
  1 sibling, 1 reply; 106+ results
From: Robert A Duff @ 1997-05-16  0:00 UTC (permalink / raw)



In article <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com>,
Nick Roberts <Nick.Roberts@dial.pipex.com> wrote:
>Quite right. I was forgetting that as the packages
>Ada.Numerics.Float_Random and Ada.Numerics.Discrete_Random are
>grandchildren of the package Ada, which is declared as pure, they must be
>pure also, ...

There is no such rule.  Ada.Numerics.Float_Random and
Ada.Numerics.Discrete_Random are in fact *not* pure.
AARM-A.5.2(27.a) explains why.

Note that all library units are (direct or indirect) children of
Standard.  And Standard is declared Pure.  So the (nonexistent) rule you
stated above wouldn't quite work -- good thing it's not in the RM!  ;-)

>...(Is this it, or is there some other reason
>that I have missed?)

As Robert said: Try to write the code using only portable features -- I
think you'll find that there's nowhere to put the Generator data, except
in the heap.  (Actually, I suppose I should say "a heap" -- you could
create your own data structure that acts as a heap.)  No fair using
Unchecked_Conversion to convert an Address (or an access-to-constant) to
an access-to-variable type -- you could do it that way on some
compilers, but it's not formally portable.  Actually, the semantics of
GNAT's 'Unrestricted_Access are defined as Unch_Conv of a 'Address --
which of course doesn't really "define" the semantics at all, since the
semantics of such an unchecked conversion is not defined.

An 'in' parameter is a constant.  If you succeed in modifying one, you
are necessarily doing something undefined!

- Bob




^ permalink raw reply	[relevance 5%]

* Re: Not intended for use in medical,
  1997-05-16  0:00  5%                       ` Robert A Duff
@ 1997-05-16  0:00  3%                         ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 1997-05-16  0:00 UTC (permalink / raw)



In article <EAA6so.JAz@world.std.com> bobduff@world.std.com (Robert A Duff) writes:

  > As Robert said: Try to write the code using only portable features -- I
  > think you'll find that there's nowhere to put the Generator data, except
  > in the heap.  (Actually, I suppose I should say "a heap" -- you could
  > create your own data structure that acts as a heap.)

  Yep.  I pointed out to Robert Dewer in a back-channel discussion,
but a point which definitely belongs here, that the real problem comes
from the implicit assumption that programs that create lots of
generators are somehow "normal."  One generator is very normal, two or
three is even understandable but, there is not enough entropy in the
environment to make dozens of PRNGs meaningful absent access to a
source of true random bits.

  In point of fact for most RNGs, creating more than, say, a dozen
generators will make your results very suspect.  For the generator in
GNAT, you can create a set of thousands of independent generators
using the standard interface.  But it ain't easy.

  If you need to do it.  Create a random integer from a source of
entropy outside the program, or just use a default generator and reset
it using the clock.  Now use a sequence of integers to seed your
generators:

   Seed: Integer := ...;
   Generators: array (Integer range 1..10000) of
           Ada.Numerics.Float_Random.Generator;
   ...

   if Seed > Integer'Last - Generators'Last
   then Seed = Seed + Integer'First; end if;
   --technically this introduces a bias but a very slight one...

   for I in Generators'Range loop
     Reset(Generators(I),Seed + I);
   end loop;

   Okay, now you can generate away knowing that no two of your
generators will create a correlated sequence, or a sequence that
correlates with a lead or lag.  (Unless you use tens of millions of
values from each generator.)

  > No fair using Unchecked_Conversion to convert an Address (or an
  > access-to-constant) to an access-to-variable type -- you could do
  > it that way on some compilers, but it's not formally portable.

  Having gone through the why, it is perfectly reasonable to make the
Generator parameter an index into a small set of actual generators in
the body of the generator package.  (Use index mod N for some small N
if you don't want to worry people whose programs are junk.  However,
you had better make those generators protected objects in a tasking
environment.)

  > Actually, the semantics of GNAT's 'Unrestricted_Access are defined
  > as Unch_Conv of a 'Address -- which of course doesn't really
  > "define" the semantics at all, since the semantics of such an
  > unchecked conversion is not defined.

  > An 'in' parameter is a constant.  If you succeed in modifying one, you
  > are necessarily doing something undefined!

  Worse than that.  Since you are actually accessing the Generator
through two different paths (an in parameter and an access type), this
is formally a bounded error. see 6.2(12).  Of course it is harmless in
this case--the compiler vendor provides the package and knows what the
behavior is.


--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[relevance 3%]

* Re: Source for Random Number Generator
       [not found]     ` <EACHUS.97Feb6161130@spectre.mitre.org>
@ 1997-02-07  0:00  8%   ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 1997-02-07  0:00 UTC (permalink / raw)




   Following up my own posting, how gauche.  Oh, well I didn't want to
mislead anyone...

  >  with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
  >  function Biased_Random(Gen: in Generator) return Float is
  >  begin
  >    return Random(Gen) * 0.9 + 0.1;
  >  end Biased_Random;

  Ask for quick and dirty and get it.  I probably should have put a
smiley face on this.

  >    Now if you will settle for not so quick and dirty, I would
  > recommend:

  >  with Ada.Numerics.Float_Random;
  >  generic
  >    type Result_Type is digits <>;
  >    Gen: in out Ada.Numerics.Float_Random.Generator;
  >  function Generalized_Random return Result_Type;

  Do not instantiate this with an unconstrained floating-point type.
It will break, and I can see no reason slow things down to deal with
such a bogus choice.  But I probably should have put in a comment.

  >   function Generalized_Random return Result_Type is
  >	Temp: Result_Type;
  >   begin
  >     Temp := Result_Type(Float(Result_Type'First) +
  >	       Float(Result_Type'Last-Result_Type'First) * 
  >	       Ada.Numerics.Float_Random.Random(Gen));
  >	return Temp;
-- Temp is only used for expository purposes. On some hardware it may
-- be better to just say:
  >     return Result_Type(Float(Result_Type'First) +
  >	       Float(Result_Type'Last-Result_Type'First) * 
  >	       Ada.Numerics.Float_Random.Random(Gen));
-- But it depends on your compiler's inlining policy.
  >   exception when others => return Generalized_Random;
  >   -- rounding errors can result in a value of Temp outside the result
  >   -- subtype when the bounds are not model numbers.
  >   end Generalized_Random;

-- This comment is technically not true if the compiler doesn't
-- support the numerics annex or you are not running in strict mode.
-- But you still want the exception handler there.

      with Ada.Numerics.Float_Random; with Generalized_Random; with Text_IO;
      procedure Test_GR is
	subtype Result_Subtype is Float range 0.1..1.0;
	My_Gen: Ada.Numerics.Float_Random.Generator;
	function Rand is new Generalized_Random(Result_Subtype, My_Gen);
-- add pragma Inline for Rand here.
	package Floating_IO is new Text_IO.Float_IO(Result_Subtype);
      begin
	Text_IO.New_Line;
	for I in 1..10 loop
	  for J in 1..6 loop
	    Floating_IO.Put(Rand,3,9,0);
	  end loop;
	  Text_IO.New_Line;
	end loop;
      end Test_GR;

--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[relevance 8%]

* Unchecked Conversion and 'Valid
@ 1996-10-07  0:00  5% Nigel J. Tracey
  0 siblings, 0 replies; 106+ results
From: Nigel J. Tracey @ 1996-10-07  0:00 UTC (permalink / raw)



I am using unchecked conversion to generate random Floats
over large ranges (up to Float'First..Float'Last). The
problem is that it generates values which are out of
the specified range for the float subtype, but 'Valid
still says that the value is valid. Having tried the same
thing for integer types the 'Valid attribute returns
False if the number is out of range. My question is
that if an array of bits is converted to a floating point
sub-type (using unchecked conversion), should 'Valid
indicate that the value is invalid if it is out of the
sub-types range?

The code I have used is below. The Valid attribute always
appears to be true even when the value of Conv_Float is
outside the range of My_Float.

Thanks for any help, information or guidance,

Nigel

--------------------
Nigel J. Tracey MEng, Research Associate (High Integrity Systems Group).
Department of Computer Science,   Office: X/D016
University of York,               Tel   : [0|+44]1904 432769
York, England.                    E-Mail: njt@minster.york.ac.uk
YO1 5DD.                          URL   : http://sv1pc161.cs.york.ac.uk/~njt



with Unchecked_Conversion;
th Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
with Text_IO; use Text_IO;

procedure Unchecked is

	type My_Float is digits 6 range -3.0E+15..+3.0+E15;

	type Bit_Type is new integer range 0..1;
	for Bit_Type'Size use 1;

	type Bit_Array_Type is array(Integer range <>) of Bit_Type;
	for Bit_Array_Type'Component_Size use 1;
	pragma Pack(Bit_Array_Type);

	type Float_Bit_Array_Type is new Bit_Array_Type(1..My_Float'Size);

	function Bit_Array_To_Float is new
	   Unchecked_Conversion(Float_Bit_Array_Type, My_Float);

	package Bit_IO is new Integer_IO(Bit_Type); use Bit_IO;
	package Int_IO is new Float_IO(My_Float)  ; use Int_IO;

	Float_Bit_Array : Float_Bit_Array_Type;
	Gen : Generator;
	Conv_Float : My_Float;

begin
   Reset(Gen);

   for I in 1..My_Float'Size
   loop
      if Random(Gen) > (0.5-Float'Small) then
         Float_Bit_Array(I) := 1;
      else
         Float_Bit_Array(I) := 0;
      end if;
   end loop;

   Conv_Float := Bit_Array_To_Float(Float_Bit_Array);

   Put_Line("The Float is");
   Put(Conv_Float);
   New_Line;
   if Conv_Float'Valid then
      Put_Line("This value is Valid");
   else
      Put_Line("This value is not Valid");
   end if;

end Unchecked;




^ permalink raw reply	[relevance 5%]

* Re: Random Number Generation
  1996-09-23  0:00  6% ` Tucker Taft
  1996-10-02  0:00  4%   ` Robert I. Eachus
@ 1996-10-03  0:00  8%   ` Nigel J. Tracey
  1 sibling, 0 replies; 106+ results
From: Nigel J. Tracey @ 1996-10-03  0:00 UTC (permalink / raw)



Robert I. Eachus (eachus@spectre.mitre.org) wrote:
: In article <52ten0$ish@netty.york.ac.uk> njt@minster.york.ac.uk (Nigel J. Tracey) writes:
: 
:   > I really need
:   > to be able to generate random values in the range of
:   > Float'Safe_First..Float'Safe_Last. Or perhaps a variable
:   > sub-range of these. Any idea...
: 
:   With what distribution?  If you are using this for testing
: arithmetic units, I suggest unchecked converting a string of random
: bits of the right length.  This will be a distribution which covers
: all representable numbers equally. (To save Robert Dewar the
: trouble...Certain bit patterns do not correspond to legal floating
: point values.  This a legitimate use for 'VALID).  However if you want
: a numerically uniform distribution:
: 
:    2.0 * Float'Safe_Last * (Ada.Numerics.Float_Random.Random(Gen) - 0.5);
: 
:    Actually you may want to add more bits to the typical floating
: point generator value.
: 
: 
: --
: 
: 					Robert I. Eachus

I have managed to write something which works with some limitations.
The problem this has is that if the range includes 0.0 and is not
sufficiently large then there is a stong bias towards 0.0. e.g
numbers in the range -1.0..1.0 are most often 0.0. However for
larger ranges or ranges not including 0.0 it seem okay. An ideas
on an improvement to the 0.0 bias...

The code is as follows (Random_Seed is declared in the package
body, it is initialised to a random integer on ellaboration
and incremented after each reset so that repeated calls to
the routine do no give non random results, due to granularity
of the reset(Gen) function):

with  Ada.Numerics.Discrete_Random,
      Ada.Numerics.Float_Random;

   function Random(Min, Max : Float) return Float is

      subtype Exponent_Type is Integer range
         Float'Machine_EMin..Float'Machine_EMax;

      package Exp_Random is new
         Ada.Numerics.Discrete_Random(Exponent_Type);

      Gen1 		: Ada.Numerics.Float_Random.Generator;
      Gen2 		: Exp_Random.Generator;
      Mantissa : Float range -1.0..1.0;
      Result   : Float;

   begin
      Ada.Numerics.Float_Random.Reset(Gen1, Random_Seed);
      Random_Seed := Random_Seed + 1;
      Exp_Random.Reset(Gen2, Random_Seed);
      Random_Seed := Random_Seed + 1;

      loop
         Mantissa := -1.0;
         Mantissa := Mantissa + Ada.Numerics.Float_Random.Random(Gen1);
         Mantissa := Mantissa + Ada.Numerics.Float_Random.Random(Gen1);

         Result := Float'Compose(Mantissa, Exp_Random.Random(Gen2));
      exit when Result > Min and Result < Max;
      end loop;

      return Result;
   end Random;





^ permalink raw reply	[relevance 8%]

* Re: Random Number Generation
  1996-09-23  0:00  6% ` Tucker Taft
@ 1996-10-02  0:00  4%   ` Robert I. Eachus
  1996-10-03  0:00  8%   ` Nigel J. Tracey
  1 sibling, 0 replies; 106+ results
From: Robert I. Eachus @ 1996-10-02  0:00 UTC (permalink / raw)



In article <52ten0$ish@netty.york.ac.uk> njt@minster.york.ac.uk (Nigel J. Tracey) writes:

  > Thanks for all the replies on this issue. I now have the problem
  > sorted for discrete random values. However nobody has suggested
  > a solution for generating large random reals. I really need
  > to be able to generate random values in the range of
  > Float'Safe_First..Float'Safe_Last. Or perhaps a variable
  > sub-range of these. Any idea...

  With what distribution?  If you are using this for testing
arithmetic units, I suggest unchecked converting a string of random
bits of the right length.  This will be a distribution which covers
all representable numbers equally. (To save Robert Dewar the
trouble...Certain bit patterns do not correspond to legal floating
point values.  This a legitimate use for 'VALID).  However if you want
a numerically uniform distribution:

   2.0 * Float'Safe_Last * (Ada.Numerics.Float_Random.Random(Gen) - 0.5);

   Actually you may want to add more bits to the typical floating
point generator value.


--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[relevance 4%]

* Re: Random Number Generation
  1996-09-30  0:00  6% `  Dr J Parker
@ 1996-10-01  0:00  5%   ` Tucker Taft
  0 siblings, 0 replies; 106+ results
From: Tucker Taft @ 1996-10-01  0:00 UTC (permalink / raw)



Dr J Parker (jp3@rl.ac.uk) wrote:
: Tucker Taft suggests: 

: "In any case, Ada.Numerics.Float_Random is the easiest one to adapt to your
: use, since it always generates values between 0.0 and 1.0.  You
: can then multiply that value by an appropriate integer or float
: and add the low bound to produce the desired dynamic range.

:   declare
:     Result : Integer range Low_Bound .. High_Bound;
:     Range_Length : constant Integer := High_Bound - Low_Bound + 1;
:   begin
:     Result := (Integer(Float(Range_Length) *
:       Ada.Numerics.Float_Random.Random(Gen)) mod Range_Length) + Low_Bound;
:     ...
: "


: Careful, there are some limits in which this fails. Simple example:
: Suppose you have a high quality random number generator R1 in the range
: 0 .. 127
: and you want to turn it into a high quality random number generator R2
: in the range 0 .. 82.
: Only the rejection method works: you must throw out at least
: 45 of the values returned by R1.  eg, if R1 returns a number in the range
: 83..127, then reject it and keep calling R1 until you get
: a number in the range 0 .. 82.  You'll get a stream of high quality random
: numbers in the range 0 .. 82.  In general, you reject just enough to make
: the number of elements (think bins) in range of R1 an integer multiple of
: the number of elements in the range of R2 (you reject never more than 50% of
: the number of elements in range of R1).  Then you
: can use "*"'s, etc to transform R1 into R2. Floating point doesn't
: change the problem.

I don't believe my suggestion suffers from the problem you fear.

The standard Float random number generator generates values uniformly
distributed from 0.0 to 1.0.  By multiplying these values by the number
of distinct integers wanted, and then (carefully) "pushing" them to a
neighboring exact integral value, you can get a uniform distribution
across any desired sequence of integers, provided the number of distinct
integers is significantly less than the period of the underlying generator.

The only trickiness above is that Ada rounds on conversion from float
to integer, so after multiplying by N and rounding to integer, you end 
up with 0 and N each occuring half as often as the values 1..N-1.  The
"mod" folds the N and 0 together, providing the desired uniform distribution
from 0 .. N-1, and then adding the low bound gives the desired low .. high
distribution.  If N is a very large number, on the order of the
underlying period of the Float random number generator, then clearly
the "uniformity" of the generator will not be as good, but provided
N << period, there is no need to use "rejection" to produce reasonable
uniformity.

-Tucker Taft   stt@inmet.com   http://www.inmet.com/~stt/
Intermetrics, Inc.  Cambridge, MA  USA




^ permalink raw reply	[relevance 5%]

* Re: Random Number Generation
  @ 1996-10-01  0:00  4%   ` Robert I. Eachus
  0 siblings, 0 replies; 106+ results
From: Robert I. Eachus @ 1996-10-01  0:00 UTC (permalink / raw)




In article <DyD3DF.Exo@thomsoft.com> kst@thomsoft.com (Keith Thompson) writes:

  > It might have been nice if the Random function had been declared like
  > this:

  >     function Random
  >	  ( Gen   : Generator; 
  >	    First : Result_Subtype := Result_Subtype'First;
  >	    Last  : Result_Subtype := Result_Subtype'Last );

  > allowing successive calls to Random with different specified bounds to
  > share the same generator, but this wasn't done.

   This wasn't done because defining the required behavior of such a
generator is beyond the state of the art.  (Not defining the
generator, THAT part is easy.)  We could have tried to extent the art
by defining tests for randomness for such a generator, but that is not
a job for a programming language standards committee.

  > Probably the best way to handle this is to use Ada.Numerics.Float_Random
  > and scale the result to the desired discrete range.  I think someone
  > else has posted code that does this.  Watch for rounding errors near
  > the endpoints!

  Yes, this can usually be done as a "one-liner," but if you think you
need the capability, think the issue through carefully.  There are
some cases where you need such behavior, but precious few.  (The bias
that can be introduced by rounding from float to integer is why I
don't want to post code without knowing the hardware, and the RNG
used.  But as long as there are hundreds of values from the generator
mapped to each possible integer value, the bias shouldn't cause a
problem.)

--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[relevance 4%]

* Re: Random Number Generation
    1996-09-23  0:00  6% ` Tucker Taft
  @ 1996-09-30  0:00  6% `  Dr J Parker
  1996-10-01  0:00  5%   ` Tucker Taft
  2 siblings, 1 reply; 106+ results
From:  Dr J Parker @ 1996-09-30  0:00 UTC (permalink / raw)



Tucker Taft suggests: 

"In any case, Ada.Numerics.Float_Random is the easiest one to adapt to your
use, since it always generates values between 0.0 and 1.0.  You
can then multiply that value by an appropriate integer or float
and add the low bound to produce the desired dynamic range.

  declare
    Result : Integer range Low_Bound .. High_Bound;
    Range_Length : constant Integer := High_Bound - Low_Bound + 1;
  begin
    Result := (Integer(Float(Range_Length) *
      Ada.Numerics.Float_Random.Random(Gen)) mod Range_Length) + Low_Bound;
    ...
"


Careful, there are some limits in which this fails. Simple example:
Suppose you have a high quality random number generator R1 in the range
0 .. 127
and you want to turn it into a high quality random number generator R2
in the range 0 .. 82.
Only the rejection method works: you must throw out at least
45 of the values returned by R1.  eg, if R1 returns a number in the range
83..127, then reject it and keep calling R1 until you get
a number in the range 0 .. 82.  You'll get a stream of high quality random
numbers in the range 0 .. 82.  In general, you reject just enough to make
the number of elements (think bins) in range of R1 an integer multiple of
the number of elements in the range of R2 (you reject never more than 50% of
the number of elements in range of R1).  Then you
can use "*"'s, etc to transform R1 into R2. Floating point doesn't
change the problem.




^ permalink raw reply	[relevance 6%]

* Re: Random Number Generation
  @ 1996-09-23  0:00  6% ` Tucker Taft
  1996-10-02  0:00  4%   ` Robert I. Eachus
  1996-10-03  0:00  8%   ` Nigel J. Tracey
    1996-09-30  0:00  6% `  Dr J Parker
  2 siblings, 2 replies; 106+ results
From: Tucker Taft @ 1996-09-23  0:00 UTC (permalink / raw)
  Cc: njt


Nigel J. Tracey (njt@minster.york.ac.uk) wrote:

: Can anyone point me in the direction of a routines to do
: random number generation. The requirements are as follows.

: 	A routine which will generate a integer between a given
: 		minimum and maximum value. Up to Integer'First and Integer'Last

: 	A routine which will do the same for floats i.e. a random
: 		value from Float'First to Float'Last but between two
: 		given values.

: The values of the min and max value for the above routines
: are not known at compile time, hence why I don't thing
: I can use Ada.Numerics.Discrete_Random

Discrete_Random does not require compile-time-known values.
However, it does require that the values be known at the time
of the instantiation.  Hence, the following is legal:

    subtype Random_Range is Integer range F(x) .. G(y);
    package Dyn_Random is new Ada.Numerics.Discrete_Random(Random_Range);

However, it may be want to change the range after the instantiation
takes place, or the instantiation needs to be at the library level,
and you won't know these values until you are inside the main
subprogram.

In any case, Ada.Numerics.Float_Random is the easiest one to adapt to your
use, since it always generates values between 0.0 and 1.0.  You
can then multiply that value by an appropriate integer or float
and add the low bound to produce the desired dynamic range.
Some care may be needed when converting from float back to integer,
to provide the desired distribution, if you want the end points to
be just as likely as any other value.  Conversion from
float to integer rounds, so you may want to use the following
trick (using "mod") to get the desired range, with no spillover to 
High_Bound+1 (this trick originates with Robert Eachus, I believe):

  declare
    Result : Integer range Low_Bound .. High_Bound;
    Range_Length : constant Integer := High_Bound - Low_Bound + 1;
  begin
    Result := (Integer(Float(Range_Length) * 
      Ada.Numerics.Float_Random.Random(Gen)) mod Range_Length) + Low_Bound;
    ...

: Any help would be very much appreciated (please also e-mail
: a copy of relies as the news feed is a little unreliable here)

: Thanks a lot,

: 	Nigel

: --------------------
: Nigel J. Tracey MEng, Research Associate (High Integrity Systems Group).
: Department of Computer Science,   Office: X/D016
: University of York,               Tel   : [0|+44]1904 432769
: York, England.                    E-Mail: njt@minster.york.ac.uk
: YO1 5DD.                          URL   : http://sv1pc161.cs.york.ac.uk/~njt

-Tucker Taft   stt@inmet.com   http://www.inmet.com/~stt/
Intermetrics, Inc.  Cambridge, MA  USA




^ permalink raw reply	[relevance 6%]

* Re: Random numbers in Gnat
    1995-03-02  8:31  6% ` Dave Marshall
@ 1995-03-02 15:50  7% ` Robert I. Eachus
  1 sibling, 0 replies; 106+ results
From: Robert I. Eachus @ 1995-03-02 15:50 UTC (permalink / raw)


In article <3j2q9t$s3n@solar.Armstrong.EDU> ab@captblood.armstrong.edu () writes:

 > with text_io; use text_io;
 > with ada.numerics.random; use ada.numerics.random;
 >   procedure randtest is
 >   package int_io is new integer_io(integer); use int_io;

 >	     rand_state: state:= make_state;

--     This initialization is wrong! The GNAT people will have to figure
-- out why it got through.  It seems to be a call to the function
-- Make_State in the private package Ada.Numerics.Random.

 >     -- return random number in 0..up_bound
 >     function my_random(up_bound: integer) return integer is
 >	   r: Uniformly_Distributed;
 >     begin
 >	   random( rand_state, r);
 >	   return integer(r*float(up_bound));
 >     end my_random;          
 >   begin

-- At this point you can insert a call to Reset, in theory it is not
-- needed, but the current generator seems to have some problems with
-- degenerate seeds.  I used:

       Reset(rand_state, 1234);
 >     for i in 1..10 loop
 >	   put(my_random(1000)); new_line;
 >     end loop;
 >   end randtest;

-- Under separate cover I'll send you a better generator. ;-)

 > The program prints out only zeros rather than 10 random numbers in the
 > 0..1000 range. I dislike the use of the global rand_state variable. 
 > However using it as a parameter is no better either. Indeed, why
 > should one be bothered with this quantity anyway? (In C one
 > just seeds the generator, and then calls the random() as a 
 > parameterless function, why not here?)

--  Because there is a serious issue involving tasking.  There are two
-- solutions in the tasking case: a single state with atomic updates,
-- or a state per task.  The solution chosen was to allow the Ada
-- language to be used and not force the wrong choice on users.  In
-- the non-tasking case, a pair of declarations like:

   My_Gen: Ada.Numerics.Float_Random.Generator;
   function Rand(Gen: in Ada.Numerics.Float_Random.Generator := My_Gen)
      return Ada.Numerics.Float_Random.Uniformly_Distributed renames
      Ada.Numerics.Float_Random.Random;

--    And all the heavy breathing is in one place.  (This particular
-- example does make a powerful argument for use clauses though.)

> I'll appreciate your discussion as to how the random number
> generator should be used. Pointers to some documentation/discussion
> of the objects in a-numran.ads would also be helpful.

-- Also by e-mail I'll send some documentation of how the generator I
-- use works.


--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...



^ permalink raw reply	[relevance 7%]

* Re: Random numbers in Gnat
  @ 1995-03-02  8:31  6% ` Dave Marshall
  1995-03-02 15:50  7% ` Robert I. Eachus
  1 sibling, 0 replies; 106+ results
From: Dave Marshall @ 1995-03-02  8:31 UTC (permalink / raw)


ab@captblood.armstrong.edu () writes:


>I cannot find any discussion of the use of random() procedure

Please, humor me.  Don't put parentheses in when it's not C.

>in gnat-2.03 Unix version for SunOS 4.1.3. The only information
>that I found is in file a-numran.ads, and as the following
>shows I must have misunderstood the intent and use of the objects
>in that file.

Always consult the LRM for definitive discussion.  Read the Rationale, 
too, for a more narrative-type approach.

>Here is a little test that I've concocted:

>        with text_io; use text_io;
>		with ada.numerics.random; use ada.numerics.random;

I hate "use"s.  Thank God for "use types."  Whoever is getting royalties 
on "renames" is going to become poor very soon.

>		procedure randtest is
>          package int_io is new integer_io(integer); use int_io;

I hate Text_IO.Integer_IO, too.

>		  rand_state: state:= make_state;

>          -- return random number in 0..up_bound
>          function my_random(up_bound: integer) return integer is
>                r: Uniformly_Distributed;
>          begin
>                random( rand_state, r);
>                return integer(r*float(up_bound));
>          end my_random;          
>        begin
>          for i in 1..10 loop
>                put(my_random(1000)); new_line;
>          end loop;
>        end randtest;

This is far too complicated.  By the way, my copy of the latest and 
greatest RM just doesn't mention Ada.Numerics.Random.  I see 
Ada.Numerics.Discrete_Random and Ada.Numerics.Float_Random.

>The program prints out only zeros rather than 10 random numbers in the
>0..1000 range. I dislike the use of the global rand_state variable. 
>However using it as a parameter is no better either. Indeed, why
>should one be bothered with this quantity anyway? (In C one
>just seeds the generator, and then calls the random() as a 
>parameterless function, why not here?)

Because different tasks may want different seeds.

>I'll appreciate your discussion as to how the random number
>generator should be used. Pointers to some documentation/discussion
>of the objects in a-numran.ads would also be helpful.

Here's my program that attempts to do the same thing.

with Text_IO;
with Ada.Numerics.Discrete_Random;

   type Some_Numbers is range 0 .. 1_000;

   package Some_Random is new Ada.Numerics.Discrete_Random(Some_Numbers);

   Some_Generator : Some_Random.Generator;

begin

   Some_Random.Reset(Some_Generator);
   for I in 1 .. 10 loop
      Text_IO.Put(Some_Numbers'Image(Some_Random.Random(Some_Generator)));
   end loop;

end Rand_Test;

>Dr. A.Bykat
>Fuller E. Callaway Professor

-- 
Dave Marshall
dmarshal@netcom.com




^ permalink raw reply	[relevance 6%]

Results 1-106 of 106 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
1995-03-01 21:51     Random numbers in Gnat ab
1995-03-02  8:31  6% ` Dave Marshall
1995-03-02 15:50  7% ` Robert I. Eachus
1996-09-23  0:00     Random Number Generation Nigel J. Tracey
1996-09-23  0:00  6% ` Tucker Taft
1996-10-02  0:00  4%   ` Robert I. Eachus
1996-10-03  0:00  8%   ` Nigel J. Tracey
1996-09-25  0:00     ` James_Rogers
1996-10-01  0:00  4%   ` Robert I. Eachus
1996-09-30  0:00  6% `  Dr J Parker
1996-10-01  0:00  5%   ` Tucker Taft
1996-10-07  0:00  5% Unchecked Conversion and 'Valid Nigel J. Tracey
     [not found]     <5d8b95$oec@zeus.orl.mmc.com>
     [not found]     ` <EACHUS.97Feb6161130@spectre.mitre.org>
1997-02-07  0:00  8%   ` Source for Random Number Generator Robert I. Eachus
1997-04-23  0:00     Not intended for use in medical, Robert C. Leif, Ph.D.
1997-05-06  0:00     ` Kaz Kylheku
1997-05-06  0:00       ` Robert A Duff
1997-05-07  0:00         ` Robert Dewar
1997-05-08  0:00           ` Robert A Duff
1997-05-09  0:00             ` Robert I. Eachus
1997-05-11  0:00               ` Robert Dewar
1997-05-12  0:00                 ` Robert I. Eachus
1997-05-13  0:00                   ` Robert Dewar
1997-05-14  0:00                     ` Nick Roberts
1997-05-14  0:00                       ` Robert Dewar
     [not found]                         ` <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com>
1997-05-16  0:00  5%                       ` Robert A Duff
1997-05-16  0:00  3%                         ` Robert I. Eachus
1997-05-16  0:00  6%                       ` Robert Dewar
1997-05-16  0:00     How do you randomise integers? the AJE
1997-05-20  0:00  6% ` Nick Roberts
1997-06-12  0:00     need help in random numbers Amos Ortal
1997-06-13  0:00  7% ` Robert I. Eachus
1997-11-19  0:00     Random numbers and ADA Ghost
1997-11-22  0:00  6% ` Matthew Heaney
1998-10-29  0:00     Long Float Error from Gnat Al Christians
1998-10-30  0:00     ` Stephen Leake
1998-10-30  0:00  7%   ` Al Christians
1998-11-13  0:00     (no subject) niel.williams
1998-11-13  0:00     ` dennison
1998-11-13  0:00  7%   ` Robert I. Eachus
1999-05-27  0:00  6% 'Random' function in Ada Robert I. Eachus
1999-07-01  0:00     Elimination of "use" clauses Dr. Neil C. Audsley
1999-07-02  0:00     ` Robert Dewar
1999-07-02  0:00       ` Samuel T. Harris
1999-07-02  0:00  3%     ` Robert Dewar
2000-01-24  0:00  3% Gnat Chat, Random Numbers in GNAT Kent Paul Dolan
2000-01-24  0:00  0% ` Gisle S�lensminde
2000-01-24  0:00  6%   ` Jeff Carter
2000-01-26  0:00  0%     ` Kent Paul Dolan
2000-02-06  0:00  0% ` Ashley Deas Eachus
2000-02-06  0:00  0%   ` Kent Paul Dolan
2000-02-26  0:00     Random Number Generator Hustler
2000-02-26  0:00  6% ` David C. Hoos, Sr.
2001-12-07  0:09     Dimensionality Checking (Ada 20XX) Snodgrass, Britt (NM75)
2001-12-07 16:15     ` Ian
2001-12-09 17:58       ` Nick Roberts
2001-12-10  0:17         ` Mark Lundquist
2001-12-10 18:56           ` Nick Roberts
2001-12-11 16:39             ` Stephen Leake
2001-12-12  9:35               ` Dmitry A. Kazakov
2001-12-12 14:26                 ` Stephen Leake
2001-12-13 17:02                   ` daniele andreatta
2001-12-14 10:16                     ` Dmitry A. Kazakov
2001-12-14 22:01  5%                   ` Nick Roberts
2001-12-17 11:10  0%                     ` Dmitry A. Kazakov
2002-02-05 10:24     Improved version (2002/1/26) of MT19937 PRNG Adrian Hoe
2002-02-08  1:43     ` GMGPL (was Improved version (2002/1/26) of MT19937 PRNG) Adrian Hoe
2002-02-08 21:41       ` Ted Dennison
2002-02-09  1:55  5%     ` Adrian Hoe
2002-02-09  5:56  0%       ` David Starner
2002-05-09 20:29  8% Building on Random_Float? Mars Gralia
2002-05-26 23:24  0% ` Robert I. Eachus
2002-06-13 12:10     Discrete random with given distribution ? Reinert Korsnes
2002-06-14 10:01  7% ` Gautier
2003-03-17 22:17     ML-like alternatives to out parameters for functions Mark Lorenzen
2003-03-17 21:47     ` Stephen Leake
2003-03-18 17:04  3%   ` Frank J. Lhota
2003-03-18 18:52         ` Mark Lorenzen
2003-03-18 19:16           ` Frank J. Lhota
2003-04-01  3:39  4%         ` Robert I. Eachus
2003-04-03 12:27     Ada2005 random David C. Hoos, Sr.
2003-04-03 12:39     ` Peter Hermann
2003-04-03 22:10       ` Randy Brukardt
2003-04-04 10:21         ` Dale Stanbrough
2003-04-13 14:56  6%       ` Robert I. Eachus
2003-04-04 12:20     Stuart Palin
2003-04-07  7:26  4% ` Jean-Etienne Doucet
2003-04-07  8:09  0%   ` Lutz Donnerhacke
2003-04-23 12:24     the Ada mandate, and why it collapsed and died (was): 64 bit addressing and OOP soft-eng
2003-04-23 17:18     ` tmoran
2003-04-24 12:46       ` soft-eng
2003-04-24 13:04         ` Using Ada for device drivers? (Was: the Ada mandate, and why it collapsed and died) Jacob Sparre Andersen
2003-04-24 17:50           ` soft-eng
2003-04-30  3:09             ` Will
2003-04-30  6:13               ` John R. Strohm
2003-04-30 16:35                 ` Kaz Kylheku
2003-04-30 20:15                   ` John R. Strohm
2003-05-01 14:21                     ` soft-eng
2003-05-01 15:22                       ` Wesley Groleau
2003-05-01 15:56                         ` Hyman Rosen
2003-05-02  3:24                           ` Wesley Groleau
2003-05-11 18:52                             ` Robert I. Eachus
2003-05-11 20:11                               ` Hyman Rosen
2003-05-11 21:57  3%                             ` Robert I. Eachus
2003-05-27  7:44     Ideas for Ada 200X Tony Gair
2003-05-28  1:38     ` Jeffrey Carter
2003-05-28  8:04       ` Stuart Palin
2003-05-28  8:06         ` Stuart Palin
2003-05-28 17:38           ` Alfred Hilscher
2003-05-29  2:59             ` Steve
2003-05-30  7:26               ` Russ
2003-05-30 17:18                 ` Wesley Groleau
2003-05-31 18:49                   ` Russ
2003-06-02  5:27                     ` Wesley Groleau
2003-06-03  5:27                       ` Russ
2003-06-03 15:26                         ` Robert I. Eachus
2003-06-03 22:20                           ` Russ
2003-06-05  4:40  5%                         ` Robert I. Eachus
2003-05-31 22:01     Random numbers in tasks Papastefanos Serafeim
2003-06-01  2:09     ` David C. Hoos
2003-06-01  3:42       ` Bobby D. Bryant
2003-06-01 18:05         ` Papastefanos Serafeim
2003-06-02  3:29  8%       ` Robert I. Eachus
2003-06-02 14:35  0%         ` Papastefanos Serafeim
2003-06-02 20:50  8%           ` Robert I. Eachus
2003-06-03 19:37  0%             ` Papastefanos Serafeim
2004-01-02 17:55     Mutable parameter of a function (long ago was: Re: What evil would happen?) Alexandre E. Kopilovitch
2004-01-03  1:56  3% ` Robert I. Eachus
2004-01-03 11:18  0%   ` Dmitry A. Kazakov
2004-01-24 15:21     In-Out Parameters for functions Wojtek Narczynski
     [not found]     ` <dSgYj40LxF@VB1162.spb.edu>
2004-01-27  7:34  7%   ` Stephen Leake
     [not found]     <uhdyhq1zl.fsf@acm.org>
2004-01-27 20:48  0% ` Alexandre E. Kopilovitch
2004-01-28 10:16  0%   ` Dmitry A. Kazakov
     [not found]     ` <iSwwi50LxF@VB1162.spb.edu>
2004-01-27 22:38  0%   ` Stephen Leake
2004-09-18  8:44     question on tasks Peter Walker
2004-09-18 10:21  7% ` Martin Dowie
2005-04-19 19:45     graphical output with claw Duke Luke
2005-04-19 21:29  7% ` tmoran
2005-04-29  4:04  5% [newbie question] tasks and protected types fabio de francesco
2005-04-29  9:43  6% ` Jacob Sparre Andersen
2005-09-09  0:20  4% Aliasing or referencing assignment David Trudgett
2005-09-09  2:13  0% ` Steve
2006-10-20 10:47  7% GNAT compiler switches and optimization tkrauss
2006-10-20 12:09     ` Samuel Tardieu
2006-10-20 12:18  5%   ` Samuel Tardieu
2006-10-20 12:12  5% ` Gautier
2006-10-20 12:35  8% ` Dmitry A. Kazakov
2006-10-20 13:27  0% ` claude.simon
2006-10-20 22:11  6% ` Jeffrey R. Carter
2006-10-20 23:52       ` Jeffrey Creem
2006-10-21  7:37         ` Gautier
2006-10-21 16:35           ` Jeffrey Creem
2006-10-21 17:04             ` Pascal Obry
2006-10-21 21:22               ` Jeffrey Creem
2006-10-22  3:03                 ` Jeffrey Creem
2006-10-22  7:39  7%               ` Jeffrey R. Carter
2006-10-22 15:57  4%               ` Jeffrey Creem
2009-07-16 19:41     Randomness tests Gautier write-only
2009-07-17 10:58     ` Nicholas Paul Collin Gloucester
2009-07-17 20:41  6%   ` Gautier write-only
2009-08-10 15:39     Benchmarking ravege
2009-08-10 20:23  6% ` Benchmarking Gautier write-only
2010-11-08 20:34     GNAT's Protected Objects Jeffrey Carter
2010-11-08 21:38     ` Anh Vo
2010-11-08 22:32  6%   ` Jeffrey Carter
2010-11-09  1:50  0%     ` Anh Vo
2011-03-17 13:33  7% Error in gnat-4.6 (opensuse 11.4) ? reinkor
2012-07-15 18:40     Efficient Sequential Access to Arrays Keean Schupke
2012-07-15 19:48     ` Dmitry A. Kazakov
2012-07-15 20:03       ` Keean Schupke
2012-07-15 21:44  5%     ` Georg Bauhaus
2012-12-27 18:48     A thicker binding for Lapack jpwoodruff
2012-12-27 19:18     ` Shark8
2012-12-29 18:36       ` jpwoodruff
2012-12-29 19:59  7%     ` Simon Wright
2013-02-25 10:20     Parallel_Simulation Vincent LAFAGE
2013-02-25 12:40  5% ` Parallel_Simulation John B. Matthews
2013-02-25 17:17  0%   ` Parallel_Simulation Vincent LAFAGE
2013-02-25 18:30  0%     ` Parallel_Simulation John B. Matthews
2013-02-26  7:13  0%       ` Parallel_Simulation Vincent LAFAGE
2013-02-26  7:09  0%     ` Parallel_Simulation Vincent LAFAGE
2013-04-22 18:27  6% Interresting difference in Normal-Returns/Expression-Functions and Extended-Returns Shark8
2014-06-15 17:07     Lotto simulation montgrimpulo
2014-06-15 18:54     ` Stefan.Lucks
2014-06-15 19:53       ` J-P. Rosen
2014-06-16  5:25         ` Stefan.Lucks
2014-06-16  7:49           ` J-P. Rosen
2014-06-16 11:15  6%         ` Stefan.Lucks
2015-06-28 14:06     How to shuffle/jumble letters of a given word? Trish Cayetano
2015-06-28 21:07  4% ` Simon Wright
2015-06-28 21:23       ` Jeffrey R. Carter
2015-06-29  8:05  5%     ` Simon Wright
2015-06-29  8:13  0%       ` Dmitry A. Kazakov
2015-11-17 22:55     Ada e-books Serge Robyns
2015-11-17 23:01     ` Paul Rubin
2015-11-18  8:29       ` Serge Robyns
2015-11-18 12:14         ` Dirk Craeynest
2015-11-19  9:41           ` Serge Robyns
2015-11-19 18:19  4%         ` Jeffrey R. Carter
2015-11-19 19:44  0%           ` Serge Robyns
2016-02-10  5:27     Quick Sort in Rosetta Code gautier_niouzes
2016-02-10  7:14     ` Leo Brewin
2016-02-10 10:16  6%   ` gautier_niouzes
2016-09-17 19:40 14% Ada.Numerics.Float_Random.Generator question Andrew Shvets
2016-09-17 20:09  6% ` J-P. Rosen
2016-09-17 20:14  7%   ` Andrew Shvets
2016-09-17 21:01  6% ` Jeffrey R. Carter
2016-09-17 23:53  7%   ` Andrew Shvets
2016-09-19 19:07  4% ` rieachus
2016-09-25 23:41  7% ` brbarkstrom
2016-09-26 13:04  5%   ` Robert Eachus
2016-09-26 18:48  5%     ` brbarkstrom
2016-09-29  9:42  7%       ` Some Dude
2016-10-01  3:35  6%         ` Robert Eachus
2016-10-01  3:59  7%           ` Paul Rubin
2016-10-01 14:23  5%             ` Robert Eachus
2016-10-01 15:49  7%               ` Dmitry A. Kazakov
2016-10-01 16:44  6%                 ` Robert Eachus
2017-08-03  5:45     Community Input for the Maintenance and Revision of the Ada Programming Language Randy Brukardt
2017-08-28 23:49     ` faryumg
2017-09-02 10:49       ` Vincent DIEMUNSCH
2017-09-02 11:21         ` Johan Söderlind Åström
2017-09-03  1:30           ` Randy Brukardt
2017-09-06 15:02             ` Johan Söderlind Åström
2017-09-09 14:48  3%           ` G.B.
2017-10-28 20:02  1% Read-write mutex sometimes fails on deadlock pascal.malaise
2018-02-03 11:06  4% Array of records with default values not propagating to array Bojan Bozovic
2018-02-03 14:16  0% ` Jere
2018-02-04  4:59  0% ` Bojan Bozovic
2018-02-04 10:19  0% ` Jeffrey R. Carter

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