packages feed

random 1.0.0.3 → 1.0.1.0

raw patch · 2 files changed

+146/−34 lines, 2 filesnew-uploader

Files

System/Random.hs view
@@ -1,3 +1,7 @@+#if __GLASGOW_HASKELL__ >= 701+{-# LANGUAGE Trustworthy #-}+#endif+ ----------------------------------------------------------------------------- -- | -- Module      :  System.Random@@ -33,6 +37,8 @@ -- ----------------------------------------------------------------------------- +#include "MachDeps.h"+ module System.Random 	( @@ -40,8 +46,12 @@  	-- * Random number generators -	  RandomGen(next, split, genRange)-+#ifdef ENABLE_SPLITTABLEGEN+	  RandomGen(next, genRange)+	, SplittableGen(split)+#else+	  RandomGen(next, genRange, split)+#endif 	-- ** Standard random number generators 	, StdGen 	, mkStdGen@@ -67,7 +77,10 @@  import Prelude +import Data.Bits import Data.Int+import Data.Word+import Foreign.C.Types  #ifdef __NHC__ import CPUTime		( getCPUTime )@@ -101,7 +114,7 @@ -- | The class 'RandomGen' provides a common interface to random number -- generators. ----- Minimal complete definition: 'next' and 'split'.+-- Minimal complete definition: 'next'.  class RandomGen g where @@ -110,14 +123,6 @@    -- and a new generator.    next     :: g -> (Int, g) -   -- |The 'split' operation allows one to obtain two distinct random number-   -- generators. This is very useful in functional programs (for example, when-   -- passing a random number generator down to recursive calls), but very-   -- little work has been done on statistically robust implementations of-   -- 'split' (["System.Random\#Burton", "System.Random\#Hellekalek"]-   -- are the only examples we know of).-   split    :: g -> (g, g)-    -- |The 'genRange' operation yields the range of values returned by    -- the generator.    --@@ -140,6 +145,19 @@    -- default method    genRange _ = (minBound, maxBound) +#ifdef ENABLE_SPLITTABLEGEN+-- | The class 'SplittableGen' proivides a way to specify a random number+-- generator that can be split into two new generators.+class SplittableGen g where+#endif+   -- |The 'split' operation allows one to obtain two distinct random number+   -- generators. This is very useful in functional programs (for example, when+   -- passing a random number generator down to recursive calls), but very+   -- little work has been done on statistically robust implementations of+   -- 'split' (["System.Random\#Burton", "System.Random\#Hellekalek"]+   -- are the only examples we know of).+   split    :: g -> (g, g)+ {- | The 'StdGen' instance of 'RandomGen' has a 'genRange' of at least 30 bits. @@ -171,9 +189,13 @@  instance RandomGen StdGen where   next  = stdNext-  split = stdSplit   genRange _ = stdRange +#ifdef ENABLE_SPLITTABLEGEN+instance SplittableGen StdGen where+#endif+  split = stdSplit+ instance Show StdGen where   showsPrec p (StdGen s1 s2) =       showsPrec p s1 . @@ -210,10 +232,11 @@ mkStdGen s = mkStdGen32 $ fromIntegral s  mkStdGen32 :: Int32 -> StdGen-mkStdGen32 s- | s < 0     = mkStdGen32 (-s)- | otherwise = StdGen (s1+1) (s2+1)+mkStdGen32 sMaybeNegative = StdGen (s1+1) (s2+1)       where+	-- We want a non-negative number, but we can't just take the abs+	-- of sMaybeNegative as -minBound == minBound.+	s       = sMaybeNegative .&. maxBound 	(q, s1) = s `divMod` 2147483562 	s2      = q `mod` 2147483398 @@ -271,14 +294,49 @@   randomIO	   = getStdRandom random  -instance Random Int where-  randomR (a,b) g = randomIvalInteger (toInteger a, toInteger b) g-  random g        = randomR (minBound,maxBound) g+instance Random Integer where+  randomR ival g = randomIvalInteger ival g+  random g	 = randomR (toInteger (minBound::Int), toInteger (maxBound::Int)) g +instance Random Int        where randomR = randomIvalIntegral; random = randomBounded+instance Random Int8       where randomR = randomIvalIntegral; random = randomBounded+instance Random Int16      where randomR = randomIvalIntegral; random = randomBounded+instance Random Int32      where randomR = randomIvalIntegral; random = randomBounded+instance Random Int64      where randomR = randomIvalIntegral; random = randomBounded++#ifndef __NHC__+-- Word is a type synonym in nhc98.+instance Random Word       where randomR = randomIvalIntegral; random = randomBounded+#endif+instance Random Word8      where randomR = randomIvalIntegral; random = randomBounded+instance Random Word16     where randomR = randomIvalIntegral; random = randomBounded+instance Random Word32     where randomR = randomIvalIntegral; random = randomBounded+instance Random Word64     where randomR = randomIvalIntegral; random = randomBounded++instance Random CChar      where randomR = randomIvalIntegral; random = randomBounded+instance Random CSChar     where randomR = randomIvalIntegral; random = randomBounded+instance Random CUChar     where randomR = randomIvalIntegral; random = randomBounded+instance Random CShort     where randomR = randomIvalIntegral; random = randomBounded+instance Random CUShort    where randomR = randomIvalIntegral; random = randomBounded+instance Random CInt       where randomR = randomIvalIntegral; random = randomBounded+instance Random CUInt      where randomR = randomIvalIntegral; random = randomBounded+instance Random CLong      where randomR = randomIvalIntegral; random = randomBounded+instance Random CULong     where randomR = randomIvalIntegral; random = randomBounded+instance Random CPtrdiff   where randomR = randomIvalIntegral; random = randomBounded+instance Random CSize      where randomR = randomIvalIntegral; random = randomBounded+instance Random CWchar     where randomR = randomIvalIntegral; random = randomBounded+instance Random CSigAtomic where randomR = randomIvalIntegral; random = randomBounded+instance Random CLLong     where randomR = randomIvalIntegral; random = randomBounded+instance Random CULLong    where randomR = randomIvalIntegral; random = randomBounded+instance Random CIntPtr    where randomR = randomIvalIntegral; random = randomBounded+instance Random CUIntPtr   where randomR = randomIvalIntegral; random = randomBounded+instance Random CIntMax    where randomR = randomIvalIntegral; random = randomBounded+instance Random CUIntMax   where randomR = randomIvalIntegral; random = randomBounded+ instance Random Char where   randomR (a,b) g = -      case (randomIvalInteger (toInteger (ord a), toInteger (ord b)) g) of-        (x,g') -> (chr x, g')+       case (randomIvalInteger (toInteger (ord a), toInteger (ord b)) g) of+         (x,g') -> (chr x, g')   random g	  = randomR (minBound,maxBound) g  instance Random Bool where@@ -295,26 +353,70 @@ 	 int2Bool _	= True    random g	  = randomR (minBound,maxBound) g- -instance Random Integer where-  randomR ival g = randomIvalInteger ival g-  random g	 = randomR (toInteger (minBound::Int), toInteger (maxBound::Int)) g +{-# INLINE randomRFloating #-}+randomRFloating :: (Num a, Ord a, Random a, RandomGen g) => (a, a) -> g -> (a, g)+randomRFloating (l,h) g +    | l>h       = randomRFloating (h,l) g+    | otherwise = let (coef,g') = random g in +		  (l + coef * (h-l), g')+ instance Random Double where-  randomR ival g = randomIvalDouble ival id g-  random g       = randomR (0::Double,1) g-  --- hah, so you thought you were saving cycles by using Float?+  randomR = randomRFloating+  random rng     = +    case random rng of +      (x,rng') -> +          -- We use 53 bits of randomness corresponding to the 53 bit significand:+          ((fromIntegral (mask53 .&. (x::Int64)) :: Double)  +	   /  fromIntegral twoto53, rng')+   where +    twoto53 = (2::Int64) ^ (53::Int64)+    mask53 = twoto53 - 1+  instance Random Float where-  random g        = randomIvalDouble (0::Double,1) realToFrac g-  randomR (a,b) g = randomIvalDouble (realToFrac a, realToFrac b) realToFrac g+  randomR = randomRFloating+  random rng = +    -- TODO: Faster to just use 'next' IF it generates enough bits of randomness.   +    case random rng of +      (x,rng') -> +          -- We use 24 bits of randomness corresponding to the 24 bit significand:+          ((fromIntegral (mask24 .&. (x::Int32)) :: Float) +	   /  fromIntegral twoto24, rng')+	 -- Note, encodeFloat is another option, but I'm not seeing slightly+	 --  worse performance with the following [2011.06.25]:+--         (encodeFloat rand (-24), rng')+   where+     mask24 = twoto24 - 1+     twoto24 = (2::Int32) ^ (24::Int32) +-- CFloat/CDouble are basically the same as a Float/Double:+instance Random CFloat where+  randomR = randomRFloating+  random rng = case random rng of +  	         (x,rng') -> (realToFrac (x::Float), rng')++instance Random CDouble where+  randomR = randomRFloating+  -- A MYSTERY:+  -- Presently, this is showing better performance than the Double instance:+  -- (And yet, if the Double instance uses randomFrac then its performance is much worse!)+  random  = randomFrac+  -- random rng = case random rng of +  -- 	         (x,rng') -> (realToFrac (x::Double), rng')+ mkStdRNG :: Integer -> IO StdGen mkStdRNG o = do     ct          <- getCPUTime     (sec, psec) <- getTime     return (createStdGen (sec * 12345 + psec + ct + o)) +randomBounded :: (RandomGen g, Random a, Bounded a) => g -> (a, g)+randomBounded = randomR (minBound, maxBound)++-- The two integer functions below take an [inclusive,inclusive] range.+randomIvalIntegral :: (RandomGen g, Integral a) => (a, a) -> g -> (a, g)+randomIvalIntegral (l,h) = randomIvalInteger (toInteger l, toInteger h)+ randomIvalInteger :: (RandomGen g, Num a) => (Integer, Integer) -> g -> (a, g) randomIvalInteger (l,h) rng  | l > h     = randomIvalInteger (h,l) rng@@ -330,6 +432,10 @@ 	   (x,g')   = next g 	  in 	  f (n' - 1) (fromIntegral x + acc * b) g'++-- The continuous functions on the other hand take an [inclusive,exclusive) range.+randomFrac :: (RandomGen g, Fractional a) => g -> (a, g)+randomFrac = randomIvalDouble (0::Double,1) realToFrac  randomIvalDouble :: (RandomGen g, Fractional a) => (Double, Double) -> (Double -> a) -> g -> (a, g) randomIvalDouble (l,h) fromDouble rng 
random.cabal view
@@ -1,8 +1,11 @@ name:		random-version:	1.0.0.3+version:	1.0.1.0++-- 1.0.1.0 -- bump for bug fixes, but no SplittableGen yet+ license:	BSD3 license-file:	LICENSE-maintainer:	libraries@haskell.org+maintainer:	rrnewton@gmail.com bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries/random synopsis:	random number library category:       System@@ -11,13 +14,16 @@ build-type: Simple Cabal-Version: >= 1.6 ++ Library     exposed-modules:         System.Random     extensions:	CPP+    GHC-Options: -O2      build-depends: base >= 3 && < 5, time  source-repository head-    type:     darcs-    location: http://darcs.haskell.org/packages/random+    type:     git+    location: http://darcs.haskell.org/packages/random.git/