```-- |
-- Module:     FRP.NetWire.Random
-- Copyright:  (c) 2011 Ertugrul Soeylemez
-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
--
-- Noise generators.

module FRP.NetWire.Random
( -- * Impure noise generators
noise,
noise1,
noiseGen,
noiseR,
wackelkontakt,

-- * Pure noise generators
pureNoise,
pureNoiseR
)
where

import qualified System.Random as R
import FRP.NetWire.Wire
import System.Random.Mersenne

-- | Impure noise between 0 (inclusive) and 1 (exclusive).

noise :: MonadIO m => Wire m a Double
noise = noiseGen

-- | Impure noise between -1 (inclusive) and 1 (exclusive).

noise1 :: MonadIO m => Wire m a Double
noise1 =
mkGen \$ \(wsRndGen -> mt) _ -> do
x <- liftM (pred . (2*)) . liftIO \$ random mt
x `seq` return (Right x, noise1)

-- | Impure noise.

noiseGen :: (MonadIO m, MTRandom b) => Wire m a b
noiseGen =
mkGen \$ \(wsRndGen -> mt) _ -> do
x <- liftIO (random mt)
x `seq` return (Right x, noiseGen)

-- | Impure noise between 0 (inclusive) and the input signal
-- (exclusive).  Note:  The noise is generated by multiplying a
-- 'Double', hence the precision is limited.

noiseR :: (MonadIO m, Real a, Integral b) => Wire m a b
noiseR =
mkGen \$ \(wsRndGen -> mt) n -> do
x' <- liftIO (random mt)
let x = floor ((x' :: Double) * realToFrac n)
x `seq` return (Right x, noiseR)

-- | Pure noise.  For impure wires it's recommended to use the impure
-- noise generators.

pureNoise :: (Monad m, R.RandomGen g, R.Random b) => g -> Wire m a b
pureNoise g' =
mkGen \$ \_ _ ->
let (x, g) = R.random g'
in x `seq` return (Right x, pureNoise g)

-- | Pure noise in a range.  For impure wires it's recommended to use
-- the impure noise generators.

pureNoiseR :: (Monad m, R.RandomGen g, R.Random b) => g -> Wire m (b, b) b
pureNoiseR g' =
mkGen \$ \_ range ->
let (x, g) = R.randomR range g'
in x `seq` return (Right x, pureNoise g)

-- | Impure random boolean.

wackelkontakt :: MonadIO m => Wire m a Bool
wackelkontakt = noiseGen
```