home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / ada_1 / Examples_ada_random < prev    next >
Encoding:
Text File  |  1994-08-14  |  2.6 KB  |  106 lines

  1. -- ++
  2. -- A superior Random Number Generator.
  3. -- This generator is one of the class discovered by Marsaglia and Zaman
  4. -- and printed in .EXE (Nov.1992).
  5. -- The generator uses the subtractive method and has a period of just
  6. -- under 2^1178 or 10^354. The generator is
  7. --      Xn = X[n-24] - X[n-37] - b) MOD 2^32
  8. -- where b is the borrow from the previous iteration.
  9. -- --
  10.  
  11. with Calendar;
  12. package body Random is
  13.  
  14. --  constants           alternatives
  15. NK : constant := 37;    -- 21
  16. NJ : constant := 24;    --  6
  17. NV : constant := 14;    --  8
  18.  
  19. -- random number array and pointer
  20. type Cache_Range is range 0 .. NK - 1;
  21. Cache     : array ( Cache_Range ) of Integer;
  22. Cache_Ptr : Cache_Range := Cache_Range'First;
  23. Borrow    : Integer := 0;
  24.  
  25. function Random return Integer is
  26.    K : Cache_Range := NK - NJ;
  27.    Temp, Diff : Integer;
  28. begin
  29.  
  30.    if Cache_Ptr < Cache_Range'Last then
  31.       Cache_Ptr := Cache_Ptr + 1;
  32.       return Cache(Cache_Ptr);
  33.    end if;
  34.   
  35.    Cache_Ptr := Cache_Range'First;
  36.  
  37.    for I in Cache_Range loop
  38.       Temp := Cache(K);
  39.       Diff := Cache(I);
  40.       if Cache(I) > 0 then
  41.          if Integer'First + Cache(I) + Borrow > Temp then  -- catch -ve overflow
  42.             Temp := Temp + Integer'Last;
  43.          end if;
  44.       elsif Cache(I) < 0 then
  45.          if Integer'Last + Cache(I) + Borrow < Temp then   -- catch +ve overflow
  46.             Temp := Temp + Integer'First;
  47.          end if;
  48.       end if;
  49.       Diff := Temp - Cache(I) - Borrow;
  50.       if Diff < Temp then
  51.          Borrow := 0;
  52.       elsif Diff > Temp then
  53.          Borrow := 1;
  54.       end if;
  55.       Cache(I) := Diff;
  56.       if K < Cache_Range'Last then
  57.          K := K + 1;
  58.       else
  59.          K := 0;
  60.       end if;
  61.    end loop;
  62.    
  63.    return Cache(Cache_Ptr);
  64. end Random;
  65.  
  66. procedure Initialise is
  67.    Seed : Integer := Integer(Calendar.Seconds ( Calendar.Clock ));
  68.    Index : Cache_Range;
  69.    M : Integer := 1;
  70. begin
  71.  
  72.    Borrow := 0;
  73.    Cache_Ptr := Cache_Range'First;
  74.    Cache(Cache_Ptr) := Seed;
  75.  
  76.    -- fill initialisation vector
  77.    for I in 1 .. Cache_Range'Last loop
  78.       Index := (NV * I ) mod NK;
  79.       Cache(Index) := M;
  80.       if M > 0 then
  81.          if Integer'First + M > Seed then   -- catch -ve overflow
  82.             Seed := Seed + Integer'Last;
  83.          end if;
  84.       elsif M < 0 then
  85.          if Integer'Last + M < Seed then    -- catch +ve overflow
  86.             Seed := Seed + Integer'First;
  87.          end if;
  88.       end if;
  89.       M := Seed - M;
  90.       Seed := Cache(Index);
  91.    end loop;
  92.    
  93.    -- warm up the generator
  94.    for I in 1 .. 1000 loop
  95.       M := Random;
  96.    end loop;
  97.  
  98. end Initialise;
  99.  
  100. begin
  101.  
  102. -- initialise the random numbers
  103. Initialise;
  104.  
  105. end Random;
  106.