1 {-
    2    This module implements a (good) random number generator.
    3 
    4    The June 1988 (v31 #6) issue of the Communications of the ACM has an
    5    article by Pierre L'Ecuyer called, "Efficient and Portable Combined
    6    Random Number Generators".  Here is the Portable Combined Generator of
    7    L'Ecuyer for 32-bit computers.  It has a period of roughly 2.30584e18.
    8 
    9    Transliterator: Lennart Augustsson
   10    
   11    Modified 10/11/97 by Alastair Reid:
   12     Added random and randomIO based on GHC's implementation of the
   13     standard Random library.
   14 
   15    Modified 04/02/99 by Erik van der Meer:
   16     Removed randomIO and renamed the module.
   17     Quick fix because GHC won't compile my SET Circuit Simulator
   18     when I import this module, so I included it.
   19     
   20     Comes from the Hugs 1.4 distribution.
   21 -}
   22 
   23 module RandomFix(random) where
   24 
   25 
   26 random :: (Integer, Integer) -> Integer -> [Integer]
   27 random (l, h) s =
   28     if l > h then error "Random.random: Empty interval" else
   29     if s < 0 then random (l, h) (-s) else
   30         let (q, s1) = s `divMod` 2147483562
   31             s2 = q `mod` 2147483398
   32             k = h-l + 1
   33             b = 2147483561
   34             n = iLogBase b k
   35             f is = let (xs, is') = splitAt n is
   36                    in  foldr (\ i r -> fromIntegral i + r * b) 0 xs `mod` k + l : f is'
   37         in  f (randomInts (fromIntegral (s1+1)) (fromIntegral (s2+1)))
   38 
   39 iLogBase b i = if i < b then 1 else 1 + iLogBase b (i `div` b)
   40 
   41 -- Use seeds s1 in 1..2147483562 and s2 in 1..2147483398 to generate
   42 -- an infinite list of random Ints.
   43 randomInts :: Int -> Int -> [Int]
   44 randomInts s1 s2 =
   45     if 1 <= s1 && s1 <= 2147483562 then
   46         if 1 <= s2 && s2 <= 2147483398 then
   47             rands s1 s2
   48         else
   49             error "randomInts: Bad second seed."
   50     else
   51         error "randomInts: Bad first seed."
   52 
   53 rands :: Int -> Int -> [Int]
   54 rands s1 s2 = z' : rands s1'' s2''
   55         where  z'   = if z < 1 then z + 2147483562 else z
   56                 z    = s1'' - s2''
   57 
   58                 k    = s1 `quot` 53668
   59                 s1'  = 40014 * (s1 - k * 53668) - k * 12211
   60                 s1'' = if s1' < 0 then s1' + 2147483563 else s1'
   61     
   62                 k'   = s2 `quot` 52774
   63                 s2'  = 40692 * (s2 - k' * 52774) - k' * 3791
   64                 s2'' = if s2' < 0 then s2' + 2147483399 else s2'
   65