{-# Language CPP, BangPatterns, ScopedTypeVariables #-}
-- |
-- Module    : System.Random.TF.Instances
-- Copyright : (c) 2012-2013 Michał Pałka
-- License   : BSD3
--
-- Maintainer  : michal.palka@chalmers.se
-- Stability   : experimental
-- Portability : portable
--
-- This module defines alternative 'Random' instances for
-- common integral types, which make use of 
-- the 'System.Random.TF.Gen.RandomGen' class from "System.Random.TF.Gen".

module System.Random.TF.Instances
 (Random (..), randomEnum) where

import Data.Bits
import Data.Int
import Data.Word

import System.Random.TF.Gen

#if !MIN_VERSION_base(4,5,0)
unsafeShiftR :: Bits a => a -> Int -> a
unsafeShiftR = shiftR

unsafeShiftL :: Bits a => a -> Int -> a
unsafeShiftL = shiftL
#endif

myUnfoldr :: (t -> (a, t)) -> t -> [a]
myUnfoldr :: (t -> (a, t)) -> t -> [a]
myUnfoldr t -> (a, t)
f t
g = a
x' a -> [a] -> [a]
forall a. a -> [a] -> [a]
: (t -> (a, t)) -> t -> [a]
forall t a. (t -> (a, t)) -> t -> [a]
myUnfoldr t -> (a, t)
f t
g'
  where
  (a
x', t
g') = t -> (a, t)
f t
g

class Random a where
  randomR :: RandomGen g => (a,a) -> g -> (a,g)

  random  :: RandomGen g => g -> (a, g)

  randomRs :: RandomGen g => (a,a) -> g -> [a]
  randomRs (a, a)
ival g
g = (g -> (a, g)) -> g -> [a]
forall t a. (t -> (a, t)) -> t -> [a]
myUnfoldr ((a, a) -> g -> (a, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (a, a)
ival) g
g

  randoms  :: RandomGen g => g -> [a]
  randoms  g
g      = (g -> (a, g)) -> g -> [a]
forall t a. (t -> (a, t)) -> t -> [a]
myUnfoldr g -> (a, g)
forall a g. (Random a, RandomGen g) => g -> (a, g)
random g
g
{-
  randomRIO :: (a,a) -> IO a

  randomIO  :: IO a
-}

boundsWrap :: Integral a => (a -> g -> (a, g)) -> (a, a) -> g -> (a, g)
boundsWrap :: (a -> g -> (a, g)) -> (a, a) -> g -> (a, g)
boundsWrap a -> g -> (a, g)
f (a
l, a
h) g
rng
  | a
l a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
h    = (a
l, g
rng)
  | a
l a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
h     = (a -> a) -> (a, g) -> (a, g)
forall t a b. (t -> a) -> (t, b) -> (a, b)
mapFst (a
ha -> a -> a
forall a. Num a => a -> a -> a
+) ((a, g) -> (a, g)) -> (a, g) -> (a, g)
forall a b. (a -> b) -> a -> b
$ a -> g -> (a, g)
f (a
l a -> a -> a
forall a. Num a => a -> a -> a
- a
h) g
rng
  | Bool
otherwise = (a -> a) -> (a, g) -> (a, g)
forall t a b. (t -> a) -> (t, b) -> (a, b)
mapFst (a
la -> a -> a
forall a. Num a => a -> a -> a
+) ((a, g) -> (a, g)) -> (a, g) -> (a, g)
forall a b. (a -> b) -> a -> b
$ a -> g -> (a, g)
f (a
h a -> a -> a
forall a. Num a => a -> a -> a
- a
l) g
rng
  where mapFst :: (t -> a) -> (t, b) -> (a, b)
mapFst t -> a
g (t
x, b
y) = (t -> a
g t
x, b
y)

randomWord32 :: RandomGen g => (Word32, Word32) -> g -> (Word32, g)
randomWord32 :: (Word32, Word32) -> g -> (Word32, g)
randomWord32 (Word32
l, Word32
h) g
rng = (Word32 -> g -> (Word32, g))
-> (Word32, Word32) -> g -> (Word32, g)
forall a g.
Integral a =>
(a -> g -> (a, g)) -> (a, a) -> g -> (a, g)
boundsWrap Word32 -> g -> (Word32, g)
forall g. RandomGen g => Word32 -> g -> (Word32, g)
randomWord32' (Word32
l, Word32
h) g
rng

randomInt32 :: RandomGen g => (Int32, Int32) -> g -> (Int32, g)
randomInt32 :: (Int32, Int32) -> g -> (Int32, g)
randomInt32 (Int32
l, Int32
h) g
rng = (Int32 -> g -> (Int32, g)) -> (Int32, Int32) -> g -> (Int32, g)
forall a g.
Integral a =>
(a -> g -> (a, g)) -> (a, a) -> g -> (a, g)
boundsWrap Int32 -> g -> (Int32, g)
forall b a a. (RandomGen b, Integral a, Num a) => a -> b -> (a, b)
randomInt32' (Int32
l, Int32
h) g
rng
  where
  randomInt32' :: a -> b -> (a, b)
randomInt32' a
m b
r = case Word32 -> b -> (Word32, b)
forall g. RandomGen g => Word32 -> g -> (Word32, g)
randomWord32' (a -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
m) b
r of
                       (Word32
x, b
r') -> (Word32 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x, b
r')

word32Mask :: Word32 -> Word32
word32Mask :: Word32 -> Word32
word32Mask Word32
w =
  (((((Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
.>. Int
1) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
.>. Int
2) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
.>. Int
4) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
.>. Int
8) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
.>. Int
16)
  where
  a
w .>. :: a -> Int -> a
.>. Int
n = a
w a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
w a -> Int -> a
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
n)

-- Inspired by Java's java.util.Random.
-- This version avoids division modulo.
-- Returns a random number from range [0..k-1], or from the full range if k = 0.
{-# INLINE randomWord32' #-}
randomWord32' :: RandomGen g => Word32 -> g -> (Word32, g)
randomWord32' :: Word32 -> g -> (Word32, g)
randomWord32' Word32
k
  -- Case 1: k is the maxBound.
  | Word32
k' Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0       = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next
  -- Case 2: k' is a power of two; k is a bit mask.
  | Word32
k' Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
k Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0 = \g
rng ->
      case g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
rng of
        (Word32
x, g
rng') -> (Word32
x Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
k, g
rng')
  -- Case 3: The general case. Case 3 subsumes Case 2,
  -- and Case 2 subsumes Case 1. Cases 1 and 2 are
  -- there for efficiency.
  | Bool
otherwise     = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
loop
  where
  k' :: Word32
k' = Word32
k Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
1
  mask :: Word32
mask = Word32 -> Word32
word32Mask Word32
k
  loop :: t -> (Word32, t)
loop t
rng
    | Word32
x' Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word32
k   = (Word32
x', t
rng')
    | Bool
otherwise = t -> (Word32, t)
loop t
rng'
    where
    (Word32
x, t
rng') = t -> (Word32, t)
forall g. RandomGen g => g -> (Word32, g)
next t
rng
    x' :: Word32
x' = Word32
x Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
mask

makeWord64 :: Word32 -> Word32 -> Word64
makeWord64 :: Word32 -> Word32 -> Word64
makeWord64 Word32
w1 Word32
w2 = Word64
w1' Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
32 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64
w2'
  where
  w1', w2' :: Word64
  w1' :: Word64
w1' = Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
w1
  w2' :: Word64
w2' = Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
w2

randomWord64 :: RandomGen g => (Word64, Word64) -> g -> (Word64, g)
randomWord64 :: (Word64, Word64) -> g -> (Word64, g)
randomWord64 (Word64
l, Word64
h) g
rng = (Word64 -> g -> (Word64, g))
-> (Word64, Word64) -> g -> (Word64, g)
forall a g.
Integral a =>
(a -> g -> (a, g)) -> (a, a) -> g -> (a, g)
boundsWrap Word64 -> g -> (Word64, g)
forall g. RandomGen g => Word64 -> g -> (Word64, g)
randomWord64' (Word64
l, Word64
h) g
rng

randomInt64 :: RandomGen g => (Int64, Int64) -> g -> (Int64, g)
randomInt64 :: (Int64, Int64) -> g -> (Int64, g)
randomInt64 (Int64
l, Int64
h) g
rng = (Int64 -> g -> (Int64, g)) -> (Int64, Int64) -> g -> (Int64, g)
forall a g.
Integral a =>
(a -> g -> (a, g)) -> (a, a) -> g -> (a, g)
boundsWrap Int64 -> g -> (Int64, g)
forall b a a. (RandomGen b, Integral a, Num a) => a -> b -> (a, b)
randomInt64' (Int64
l, Int64
h) g
rng
  where
  randomInt64' :: a -> b -> (a, b)
randomInt64' a
m b
r = case Word64 -> b -> (Word64, b)
forall g. RandomGen g => Word64 -> g -> (Word64, g)
randomWord64' (a -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
m) b
r of
                       (Word64
x, b
r') -> (Word64 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x, b
r')

-- Works similarly to randomWord32'
randomWord64' :: RandomGen g => Word64 -> g -> (Word64, g)
randomWord64' :: Word64 -> g -> (Word64, g)
randomWord64' Word64
k
  -- Case 1: The range fits in 32 bits.
  | Word64
k Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word64
m32      = \g
rng ->
    case Word32 -> g -> (Word32, g)
forall g. RandomGen g => Word32 -> g -> (Word32, g)
randomWord32' (Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
k) g
rng of
      (Word32
x, g
rng') -> (Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x, g
rng')
  -- Case 2: (l,h) is the full range. This case should
  -- probably be removed
  | Word64
k' Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0       = \g
rng ->
    let !(Word32
x1, g
rng')  = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
rng
        !(Word32
x2, g
rng'') = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
rng'
    in (Word32 -> Word32 -> Word64
makeWord64 Word32
x1 Word32
x2, g
rng'')
  -- Case 3: k' is a power of two; k is a bit mask.
  | Word64
k' Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
k Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 = \g
rng ->
    let !(Word32
x1, g
rng')  = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
rng
        !(Word32
x2, g
rng'') = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
rng'
    in (Word32 -> Word32 -> Word64
makeWord64 Word32
x1 Word32
x2 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
k, g
rng'')
  -- Case 4: The general case. Case 4 subsumes Cases 1 and 3,
  -- and Case 3 subsumes Case 2. Cases 1, 2 and 3 are
  -- there for efficiency.
  | Bool
otherwise     = g -> (Word64, g)
forall t. RandomGen t => t -> (Word64, t)
loop
  where
  m32 :: Word64
  m32 :: Word64
m32 = Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
forall a. Bounded a => a
maxBound :: Word32)
  k' :: Word64
k' = Word64
k Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1
  mask :: Word32
mask = Word32 -> Word32
word32Mask (Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word32) -> Word64 -> Word32
forall a b. (a -> b) -> a -> b
$ Word64
k Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
32)
  loop :: t -> (Word64, t)
loop t
rng
    | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word64
k    = (Word64
x, t
rng'')
    | Bool
otherwise = t -> (Word64, t)
loop t
rng''
    where
    (Word32
x1, t
rng')  = t -> (Word32, t)
forall g. RandomGen g => g -> (Word32, g)
next t
rng
    (Word32
x2, t
rng'') = t -> (Word32, t)
forall g. RandomGen g => g -> (Word32, g)
next t
rng'
    x :: Word64
x  = Word32 -> Word32 -> Word64
makeWord64 (Word32
x1 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
mask) Word32
x2

-- Returns the most significant word and the number of extra words.
-- x must be non-negative
getShiftAndLead :: (Integral a, Bits a) => a -> (Int, Word32)
getShiftAndLead :: a -> (Int, Word32)
getShiftAndLead !a
x = a -> Int -> (Int, Word32)
forall t b t.
(Integral t, Num b, Num t, Bits t) =>
t -> t -> (t, b)
cWords a
x Int
0
  where
  cWords :: t -> t -> (t, b)
cWords !t
x !t
c
    | t
x' t -> t -> Bool
forall a. Eq a => a -> a -> Bool
== t
0   = (t
c, t -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral t
x)
    | Bool
otherwise = t -> t -> (t, b)
cWords t
x' (t
ct -> t -> t
forall a. Num a => a -> a -> a
+t
1)
    where
    x' :: t
x' = t
x t -> Int -> t
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
32

randomInteger :: RandomGen g => (Integer, Integer) -> g -> (Integer, g)
randomInteger :: (Integer, Integer) -> g -> (Integer, g)
randomInteger (Integer
l, Integer
h) g
rng = (Integer -> g -> (Integer, g))
-> (Integer, Integer) -> g -> (Integer, g)
forall a g.
Integral a =>
(a -> g -> (a, g)) -> (a, a) -> g -> (a, g)
boundsWrap Integer -> g -> (Integer, g)
forall g. RandomGen g => Integer -> g -> (Integer, g)
randomInteger' (Integer
l, Integer
h) g
rng

{-# INLINE randomInteger' #-}
randomInteger' :: forall g. RandomGen g => Integer -> g -> (Integer, g)
randomInteger' :: Integer -> g -> (Integer, g)
randomInteger' Integer
k g
rng
  | Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
2Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
64  = case Word64 -> g -> (Word64, g)
forall g. RandomGen g => Word64 -> g -> (Word64, g)
randomWord64' (Integer -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
k) g
rng of
                  (Word64
x, g
rng') -> (Word64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x, g
rng')
  | Bool
otherwise = g -> (Integer, g)
loop g
rng
  where
  (Int
w, Word32
l) = Integer -> (Int, Word32)
forall a. (Integral a, Bits a) => a -> (Int, Word32)
getShiftAndLead Integer
k
  -- Constructing Integers is very expensive, so it is better
  -- to do it from Word64s than from Word32s.
  construct :: g -> (Integer, g)
construct g
rng
    | Int -> Bool
forall a. Integral a => a -> Bool
even Int
w    = Integer -> Int -> g -> (Integer, g)
construct' (Word32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
lx) Int
w   g
rng'
    | Bool
otherwise = Integer -> Int -> g -> (Integer, g)
construct' (Word64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x) (Int
wInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) g
rng''
    where
    (Word32
lx, g
rng')  = Word32 -> g -> (Word32, g)
forall g. RandomGen g => Word32 -> g -> (Word32, g)
randomWord32' Word32
l g
rng
    (Word32
x2, g
rng'') = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
rng'
    x :: Word64
x  = Word32 -> Word32 -> Word64
makeWord64 Word32
lx Word32
x2
  construct' :: Integer -> Int -> g -> (Integer, g)
  construct' :: Integer -> Int -> g -> (Integer, g)
construct' !Integer
a Int
0 g
rng = (Integer
a, g
rng)
  construct' !Integer
a Int
n g
rng =
    Integer -> Int -> g -> (Integer, g)
construct' (Integer
a Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftL` Int
64 Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.|. Word64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x) (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2) g
rng''
    where
    (Word32
x1, g
rng')  = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
rng
    (Word32
x2, g
rng'') = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
rng'
    x :: Word64
x  = Word32 -> Word32 -> Word64
makeWord64 Word32
x1 Word32
x2
  loop :: g -> (Integer, g)
loop g
rng
    | Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
k   = (Integer
x, g
rng')
    | Bool
otherwise = g -> (Integer, g)
loop g
rng'
    where
    (Integer
x, g
rng') = g -> (Integer, g)
construct g
rng

randomBounded :: (RandomGen g, Random a, Bounded a) => g -> (a, g)
randomBounded :: g -> (a, g)
randomBounded = (a, a) -> g -> (a, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (a
forall a. Bounded a => a
minBound, a
forall a. Bounded a => a
maxBound)

instance Random Int where
  randomR :: (Int, Int) -> g -> (Int, g)
randomR (Int
a, Int
b) g
rng = (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
x, g
rng')
    where !(Int64
x, g
rng') = (Int64, Int64) -> g -> (Int64, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a :: Int64, Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
b) g
rng
  random :: g -> (Int, g)
random  = g -> (Int, g)
forall g a. (RandomGen g, Random a, Bounded a) => g -> (a, g)
randomBounded

randomEnum :: (Enum a, RandomGen g) => (a, a) -> g -> (a, g)
randomEnum :: (a, a) -> g -> (a, g)
randomEnum (a
a,a
b) g
g = 
  case (Int, Int) -> g -> (Int, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (a -> Int
forall a. Enum a => a -> Int
fromEnum a
a, a -> Int
forall a. Enum a => a -> Int
fromEnum a
b) g
g of
    (Int
x, g
g') -> (Int -> a
forall a. Enum a => Int -> a
toEnum Int
x, g
g')

instance Random Char where
  randomR :: (Char, Char) -> g -> (Char, g)
randomR = (Char, Char) -> g -> (Char, g)
forall a g. (Enum a, RandomGen g) => (a, a) -> g -> (a, g)
randomEnum
  random :: g -> (Char, g)
random  = g -> (Char, g)
forall g a. (RandomGen g, Random a, Bounded a) => g -> (a, g)
randomBounded

instance Random Bool where
  randomR :: (Bool, Bool) -> g -> (Bool, g)
randomR = (Bool, Bool) -> g -> (Bool, g)
forall a g. (Enum a, RandomGen g) => (a, a) -> g -> (a, g)
randomEnum
  random :: g -> (Bool, g)
random  = g -> (Bool, g)
forall g a. (RandomGen g, Random a, Bounded a) => g -> (a, g)
randomBounded

-- For random Integers we use the range of Int
instance Random Integer where
  randomR :: (Integer, Integer) -> g -> (Integer, g)
randomR = (Integer, Integer) -> g -> (Integer, g)
forall g. RandomGen g => (Integer, Integer) -> g -> (Integer, g)
randomInteger
  random :: g -> (Integer, g)
random  = (Integer, Integer) -> g -> (Integer, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Int -> Integer
forall a. Integral a => a -> Integer
toInteger (Int
forall a. Bounded a => a
minBound::Int), Int -> Integer
forall a. Integral a => a -> Integer
toInteger (Int
forall a. Bounded a => a
maxBound::Int))

instance Random Word32 where
  randomR :: (Word32, Word32) -> g -> (Word32, g)
randomR = (Word32, Word32) -> g -> (Word32, g)
forall g. RandomGen g => (Word32, Word32) -> g -> (Word32, g)
randomWord32
  -- Optimised version
  random :: g -> (Word32, g)
random  = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next

instance Random Word64 where
  randomR :: (Word64, Word64) -> g -> (Word64, g)
randomR = (Word64, Word64) -> g -> (Word64, g)
forall g. RandomGen g => (Word64, Word64) -> g -> (Word64, g)
randomWord64
  random :: g -> (Word64, g)
random  = g -> (Word64, g)
forall g a. (RandomGen g, Random a, Bounded a) => g -> (a, g)
randomBounded

instance Random Int32 where
  randomR :: (Int32, Int32) -> g -> (Int32, g)
randomR = (Int32, Int32) -> g -> (Int32, g)
forall g. RandomGen g => (Int32, Int32) -> g -> (Int32, g)
randomInt32
  -- Optimised version
  random :: g -> (Int32, g)
random g
g = let (Word32
x, g
g') = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
g in (Word32 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x, g
g')

instance Random Int64 where
  randomR :: (Int64, Int64) -> g -> (Int64, g)
randomR = (Int64, Int64) -> g -> (Int64, g)
forall g. RandomGen g => (Int64, Int64) -> g -> (Int64, g)
randomInt64
  random :: g -> (Int64, g)
random  = g -> (Int64, g)
forall g a. (RandomGen g, Random a, Bounded a) => g -> (a, g)
randomBounded

instance Random Word8 where
  randomR :: (Word8, Word8) -> g -> (Word8, g)
randomR (Word8
l, Word8
h) g
g =
    let (Word32
x, g
g') = (Word32, Word32) -> g -> (Word32, g)
forall g. RandomGen g => (Word32, Word32) -> g -> (Word32, g)
randomWord32 (Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
l, Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
h) g
g
    in (Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x, g
g')
  -- Optimised version
  random :: g -> (Word8, g)
random g
g = let (Word32
x, g
g') = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
g in (Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x, g
g')

instance Random Int8 where
  randomR :: (Int8, Int8) -> g -> (Int8, g)
randomR (Int8
l, Int8
h) g
g =
    let (Int32
x, g
g') = (Int32, Int32) -> g -> (Int32, g)
forall g. RandomGen g => (Int32, Int32) -> g -> (Int32, g)
randomInt32 (Int8 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
l, Int8 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
h) g
g
    in (Int32 -> Int8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
x, g
g')
  -- Optimised version
  random :: g -> (Int8, g)
random g
g = let (Word32
x, g
g') = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
g in (Word32 -> Int8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x, g
g')

instance Random Word16 where
  randomR :: (Word16, Word16) -> g -> (Word16, g)
randomR (Word16
l, Word16
h) g
g =
    let (Word32
x, g
g') = (Word32, Word32) -> g -> (Word32, g)
forall g. RandomGen g => (Word32, Word32) -> g -> (Word32, g)
randomWord32 (Word16 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
l, Word16 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
h) g
g
    in (Word32 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x, g
g')
  -- Optimised version
  random :: g -> (Word16, g)
random g
g = let (Word32
x, g
g') = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
g in (Word32 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x, g
g')

instance Random Int16 where
  randomR :: (Int16, Int16) -> g -> (Int16, g)
randomR (Int16
l, Int16
h) g
g =
    let (Int32
x, g
g') = (Int32, Int32) -> g -> (Int32, g)
forall g. RandomGen g => (Int32, Int32) -> g -> (Int32, g)
randomInt32 (Int16 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
l, Int16 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
h) g
g
    in (Int32 -> Int16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
x, g
g')
  -- Optimised version
  random :: g -> (Int16, g)
random g
g = let (Word32
x, g
g') = g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
next g
g in (Word32 -> Int16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x, g
g')