From: sof Date: Mon, 19 May 1997 04:51:33 +0000 (+0000) Subject: [project @ 1997-05-19 04:51:33 by sof] X-Git-Tag: Approximately_1000_patches_recorded~588 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=64ac59d5f0e1b03f34580eded129efddbc2f4410;p=ghc-hetmet.git [project @ 1997-05-19 04:51:33 by sof] new std lib --- diff --git a/ghc/lib/required/Random.lhs b/ghc/lib/required/Random.lhs new file mode 100644 index 0000000..faae80a --- /dev/null +++ b/ghc/lib/required/Random.lhs @@ -0,0 +1,67 @@ + +This module implements a (good) random number generator. + +The June 1988 (v31 #6) issue of the Communications of the ACM has an +article by Pierre L'Ecuyer called, "Efficient and Portable Combined +Random Number Generators". Here is the Portable Combined Generator of +L'Ecuyer for 32-bit computers. It has a period of roughly 2.30584e18. + +Transliterator: Lennart Augustsson + +\begin{code} +module Random + ( + random, + randomIO + ) where + +import CPUTime (getCPUTime) +import Time (getClockTime, ClockTime(..)) + +randomIO :: (Integer, Integer) -> IO [Integer] +randomIO lh = do + ct <- getCPUTime + (TOD sec _) <- getClockTime + return (random lh (sec * 12345 + ct)) + +random :: (Integer, Integer) -> Integer -> [Integer] +random (l, h) s = + if l > h then error "Random.random: Empty interval" else + if s < 0 then random (l, h) (-s) else + let (q, s1) = s `divMod` 2147483562 + s2 = q `mod` 2147483398 + k = h-l + 1 + b = 2147483561 + n = iLogBase b k + f is = let (xs, is') = splitAt n is + in foldr (\ i r -> fromInt i + r * b) 0 xs `mod` k + l : f is' + in f (randomInts (toInt (s1+1)) (toInt (s2+1))) + +iLogBase b i = if i < b then 1 else 1 + iLogBase b (i `div` b) + +-- Use seeds s1 in 1..2147483562 and s2 in 1..2147483398 to generate +-- an infinite list of random Ints. +randomInts :: Int -> Int -> [Int] +randomInts s1 s2 = + if 1 <= s1 && s1 <= 2147483562 then + if 1 <= s2 && s2 <= 2147483398 then + rands s1 s2 + else + error "randomInts: Bad second seed." + else + error "randomInts: Bad first seed." + +rands :: Int -> Int -> [Int] +rands s1 s2 = z' : rands s1'' s2'' + where z' = if z < 1 then z + 2147483562 else z + z = s1'' - s2'' + + k = s1 `quot` 53668 + s1' = 40014 * (s1 - k * 53668) - k * 12211 + s1'' = if s1' < 0 then s1' + 2147483563 else s1' + + k' = s2 `quot` 52774 + s2' = 40692 * (s2 - k' * 52774) - k' * 3791 + s2'' = if s2' < 0 then s2' + 2147483399 else s2' + +\end{code}