-- Stability : stable
-- Portability : portable
--
--- Random numbers.
+-- This library deals with the common task of pseudo-random number
+-- generation. The library makes it possible to generate repeatable
+-- results, by starting with a specified initial random number generator,
+-- or to get different results on each run by using the system-initialised
+-- generator or by supplying a seed from some other source.
+--
+-- The library is split into two layers:
+--
+-- * A core /random number generator/ provides a supply of bits.
+-- The class 'RandomGen' provides a common interface to such generators.
+-- The library provides one instance of 'RandomGen', the abstract
+-- data type 'StdGen'. Programmers may, of course, supply their own
+-- instances of 'RandomGen'.
+--
+-- * The class 'Random' provides a way to extract values of a particular
+-- type from a random number generator. For example, the 'Float'
+-- instance of 'Random' allows one to generate random values of type
+-- 'Float'.
+--
+-- This implementation uses the Portable Combined Generator of L'Ecuyer
+-- ["System.Random\#LEcuyer"] for 32-bit computers, transliterated by
+-- Lennart Augustsson. It has a period of roughly 2.30584e18.
--
-----------------------------------------------------------------------------
-- $intro
- -- * The 'RandomGen' class, and the 'StdGen' generator
+ -- * Random number generators
RandomGen(next, split, genRange)
+
+ -- ** Standard random number generators
, StdGen
, mkStdGen
- -- * The 'Random' class
- , Random ( random, randomR,
- randoms, randomRs,
- randomIO, randomRIO )
-
- -- * The global random number generator
+ -- ** The global random number generator
-- $globalrng
, setStdGen
, newStdGen
+ -- * Random values of various types
+ , Random ( random, randomR,
+ randoms, randomRs,
+ randomIO, randomRIO )
+
-- * References
-- $references
#ifdef __NHC__
import CPUTime ( getCPUTime )
import Foreign.Ptr ( Ptr, nullPtr )
+import Foreign.C ( CTime, CUInt )
#else
import System.CPUTime ( getCPUTime )
import System.Time ( getClockTime, ClockTime(..) )
-- replacement here.
#ifdef __NHC__
data ClockTime = TOD Integer ()
-foreign import ccall "time.h time" readtime :: Ptr () -> IO Int
+foreign import ccall "time.h time" readtime :: Ptr CTime -> IO CTime
getClockTime :: IO ClockTime
-getClockTime = do t <- readtime nullPtr; return (TOD (toInteger t) ())
+getClockTime = do CTime t <- readtime nullPtr; return (TOD (toInteger t) ())
#endif
-{- $intro
-
-This library deals with the common task of pseudo-random
-number generation. The library makes it possible to generate
-repeatable results, by starting with a specified initial random
-number generator; or to get different results on each run by using the
-system-initialised generator, or by supplying a seed from some other
-source.
-
-The library is split into two layers:
-
-* A core /random number generator/ provides a supply of bits. The class
-'RandomGen' provides a common interface to such generators.
-
-* The class 'Random' provides a way to extract particular values from
-a random number generator. For example, the 'Float' instance of 'Random'
-allows one to generate random values of type 'Float'.
-
-This implementation uses the Portable Combined Generator of L'Ecuyer
-["System.Random\#LEcuyer"] for 32-bit computers, transliterated by
-Lennart Augustsson. It has a period of roughly 2.30584e18.
-
--}
-
-- | The class 'RandomGen' provides a common interface to random number
-- generators.
+--
+-- Minimal complete definition: 'next' and 'split'.
class RandomGen g where
--
-- * If @(a,b) = 'genRange' g@, then @a < b@.
--
- -- * 'genRange' is not strict.
+ -- * 'genRange' always returns a pair of defined 'Int's.
--
-- The second condition ensures that 'genRange' cannot examine its
-- argument, and hence the value it returns can be determined only by the
-- a single call to 'genRange' to establish a generator's range, without
-- being concerned that the generator returned by (say) 'next' might have
-- a different range to the generator passed to 'next'.
+ --
+ -- The default definition spans the full range of 'Int'.
genRange :: g -> (Int,Int)
-- default method
genRange g = (minBound,maxBound)
-{- |The "System.Random" library provides one instance of 'RandomGen', the
-abstract data type 'StdGen'.
-
+{- |
The 'StdGen' instance of 'RandomGen' has a 'genRange' of at least 30 bits.
The result of repeatedly using 'next' should be at least as statistically
instance RandomGen StdGen where
next = stdNext
split = stdSplit
+ genRange _ = stdRange
instance Show StdGen where
showsPrec p (StdGen s1 s2) =
The function 'mkStdGen' provides an alternative way of producing an initial
generator, by mapping an 'Int' into a generator. Again, distinct arguments
should be likely to produce distinct generators.
-
-Programmers may, of course, supply their own instances of 'RandomGen'.
-}
mkStdGen :: Int -> StdGen -- why not Integer ?
mkStdGen s
iLogBase :: Integer -> Integer -> Integer
iLogBase b i = if i < b then 1 else 1 + iLogBase b (i `div` b)
+stdRange :: (Int,Int)
+stdRange = (0, 2147483562)
+
stdNext :: StdGen -> (Int, StdGen)
+-- Returns values in the range stdRange
stdNext (StdGen s1 s2) = (z', StdGen s1'' s2'')
where z' = if z < 1 then z + 2147483562 else z
z = s1'' - s2''