home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / ada / setl2 / samples / random.stl < prev   
Text File  |  1991-11-16  |  4KB  |  155 lines

  1. --
  2. --  RANDOM NUMBERS
  3. --  ==============
  4. --
  5. --  This package is meant to replace the "random" built-in procedure in
  6. --  SETL.  It is somewhat different conceptually from that procedure.
  7. --
  8. --  We allow the creation and access of `streams' of random numbers.  To
  9. --  create a stream, call start_random passing it some kind of source and
  10. --  an initial seed.  The source should be one of the following:
  11. --
  12. --     1.  An integer.  In this case we return integers from 1 to that
  13. --         integer.
  14. --
  15. --     2.  A real.  We return reals from 0.0 to that real.
  16. --
  17. --     3.  A set.  We return random elements from that set.
  18. --
  19. --     4.  A tuple.  We return random elements from that tuple.
  20. --
  21. --  The seed may be an integer, or om.  If it is om we use the time as
  22. --  the initial seed.
  23. --
  24.  
  25. package Random_Numbers;
  26.  
  27.    procedure Start_Random(Source,Seed);
  28.  
  29.    procedure Random(Handle);
  30.  
  31. end Random_Numbers;
  32.  
  33. package body Random_Numbers;
  34.  
  35.    const  Modulus      := 2 ** 64 - 59,
  36.           Multiplier   := 2 ** 60 - 93,
  37.           Increment    := 2 ** 15 - 19;
  38.  
  39.    var    Stream_Set   := {},
  40.           Source_Map   := {},
  41.           Seed_Map     := {};
  42.  
  43.    --
  44.    --  Start_Random
  45.    --  ------------
  46.    --
  47.    --  This procedure is called to initialize a stream of random numbers.
  48.    --  It returns a handle which is used to access the stream.
  49.    --
  50.  
  51.    procedure Start_Random(Source,Seed);
  52.  
  53.       var Handle;
  54.  
  55.       --
  56.       --  Allocate a handle for this stream.
  57.       --
  58.  
  59.       Handle := newat();
  60.       Stream_Set with := Handle;
  61.  
  62.       --
  63.       --  Set the initial seed.  If we get one from the caller, use that.
  64.       --  Otherwise use the time.
  65.       --
  66.  
  67.       if Seed = om then
  68.  
  69.          t := Time();
  70.          Seed_Map(Handle) := unstr(t(1 .. 2)) * 60 ** 2 +
  71.                              unstr(t(4 .. 5)) * 60 +
  72.                              unstr(t(7 ..));
  73.  
  74.       elseif not is_integer(Seed) then
  75.  
  76.          print("Invalid seed in Start_Random => ",seed);
  77.          stop;
  78.  
  79.       else
  80.  
  81.          Seed_Map(Handle) := Seed;
  82.  
  83.       end if;
  84.  
  85.       --
  86.       --  Save the source in a map.
  87.       --
  88.  
  89.       case type(Source)
  90.  
  91.          when "INTEGER", "REAL", "TUPLE" =>
  92.  
  93.             Source_Map(Handle) := Source;
  94.  
  95.          when "SET" =>
  96.  
  97.             Source_Map(Handle) := [x : x in Source];
  98.  
  99.          otherwise =>
  100.  
  101.             print("Invalid source in Start_Random => ", Source);
  102.             stop;
  103.  
  104.       end case;
  105.  
  106.       return Handle;
  107.  
  108.    end Start_Random;
  109.  
  110.    --
  111.    --  Random
  112.    --  ------
  113.    --
  114.    --  This procedure returns a single random number (or element from set
  115.    --  or tuple).
  116.    --
  117.  
  118.    procedure Random(Handle);
  119.  
  120.       --
  121.       --  Validate the handle.
  122.       --
  123.  
  124.       if Handle notin Stream_Set then
  125.  
  126.          print("Invalid handle for Random");
  127.          stop;
  128.  
  129.       end if;
  130.  
  131.       --
  132.       --  Find a random integer (linear congruential method).
  133.       --
  134.  
  135.       New_Seed := (Seed_Map(Handle) * Multiplier + Increment) mod Modulus;
  136.       Seed_Map(Handle) := New_Seed;
  137.       Source := Source_Map(Handle);
  138.  
  139.       --
  140.       --  Return the random number.
  141.       --
  142.  
  143.       return case type(Source)
  144.          when "INTEGER" =>
  145.             (New_Seed mod Source_Map(Handle)) + 1
  146.          when "REAL" =>
  147.             float(New_Seed) / float(Modulus) * Source_Map(Handle)
  148.          when "TUPLE" =>
  149.             Source((New_Seed mod #Source) + 1)
  150.       end case;
  151.  
  152.    end Random;
  153.  
  154. end Random_Numbers;
  155.