module Random.MWC.Pure
(
Seed (), seed,
BoundedRandom (..), UnitRandom (..), RangeRandom (..),
random_list,
)
where
import Data.Bits
import Data.Word
import Data.Int
import Random.MWC.Primitive
class Bounded x => BoundedRandom x where
bounded_random :: Seed -> (x, Seed)
class Ord x => UnitRandom x where
unit_random :: Seed -> (x, Seed)
class Ord x => RangeRandom x where
range_random :: (x, x) -> Seed -> (x, Seed)
random_list :: (Seed -> (x, Seed)) -> Int -> Seed -> ([x], Seed)
random_list f n s
| n < 0 = error "Random.MWC.random_list: negative length"
| n == 0 = ([], s)
| otherwise =
let
(x , s' ) = f s
(xs, s'') = random_list f (n1) s'
in (x:xs, s'')
instance BoundedRandom Bool where
bounded_random s =
let (x, s') = next_word s
in (odd x, s')
instance BoundedRandom Word8 where
bounded_random s =
let (x, s') = next_word s
in (fromIntegral x, s')
instance BoundedRandom Word16 where
bounded_random s =
let (x, s') = next_word s
in (fromIntegral x, s')
instance BoundedRandom Word32 where
bounded_random = next_word
instance BoundedRandom Word64 where
bounded_random s0 =
let
(x1, s1) = next_word s0
(x2, s2) = next_word s1
w1 = fromIntegral x1
w2 = fromIntegral x2
in (w1 `shift` 32 .|. w2, s2)
instance BoundedRandom Int8 where
bounded_random s =
let (x, s') = next_word s
in (fromIntegral x, s')
instance BoundedRandom Int16 where
bounded_random s =
let (x, s') = next_word s
in (fromIntegral x, s')
instance BoundedRandom Int32 where
bounded_random s =
let (x, s') = next_word s
in (fromIntegral x, s')
instance BoundedRandom Int64 where
bounded_random s =
let (x, s') = bounded_random s :: (Word64, Seed)
in (fromIntegral x, s')
instance BoundedRandom Int where
bounded_random s =
let (x, s') = next_word s
in (fromIntegral x, s')
instance BoundedRandom Word where
bounded_random s =
let (x, s') = next_word s
in (fromIntegral x, s')
instance UnitRandom Float where
unit_random s =
let
(x, s') = next_word s
magic = 2**(32) :: Float
in (magic * fromIntegral x, s')
instance UnitRandom Double where
unit_random s =
let
(x, s') = bounded_random s :: (Word64, Seed)
magic = 2**(64) :: Double
in (magic * fromIntegral x, s')
instance RangeRandom Float where
range_random (x0, x1) s =
let (x, s') = unit_random s
in ((x1x0)*x + x0, s')
instance RangeRandom Double where
range_random (x0, x1) s =
let (x, s') = unit_random s
in ((x1x0)*x + x0, s')
instance RangeRandom Word8 where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')
instance RangeRandom Word16 where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')
instance RangeRandom Word32 where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')
instance RangeRandom Word64 where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')
instance RangeRandom Int8 where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')
instance RangeRandom Int16 where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')
instance RangeRandom Int32 where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')
instance RangeRandom Int64 where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')
instance RangeRandom Int where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')
instance RangeRandom Word where
range_random (x0, x1) s =
let
dx = x1 x0
(x, s') = bounded_random s
(xa, xb) = x `divMod` dx
in
if (xa+1)*dx < xa*dx
then range_random (x0, x1) s'
else (xb + x0, s')