diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+### 0.1.3.2
+
+* Added System.Random.PCG.Fast.Pure module.
+
 ### 0.1.3.1
 
 * Added `withFrozen` function.
diff --git a/pcg-random.cabal b/pcg-random.cabal
--- a/pcg-random.cabal
+++ b/pcg-random.cabal
@@ -1,5 +1,5 @@
 name:                pcg-random
-version:             0.1.3.1
+version:             0.1.3.2
 synopsis:            Haskell bindings to the PCG random number generator.
 description:
   PCG is a family of simple fast space-efficient statistically good
@@ -38,6 +38,7 @@
     System.Random.PCG
     System.Random.PCG.Class
     System.Random.PCG.Fast
+    System.Random.PCG.Fast.Pure
     System.Random.PCG.Unique
     System.Random.PCG.Single
   hs-source-dirs:      src
diff --git a/src/System/Random/PCG.hs b/src/System/Random/PCG.hs
--- a/src/System/Random/PCG.hs
+++ b/src/System/Random/PCG.hs
@@ -146,7 +146,7 @@
 -- | Type alias of 'Gen' specialized to 'IO'.
 type GenIO = Gen RealWorld
 
--- | Type alias of 'Gen' specialized to 'ST'. (
+-- | Type alias of 'Gen' specialized to 'ST'.
 type GenST s = Gen s
 -- Note this doesn't force it to be in ST. You can write (STGen Realworld)
 -- and it'll work in IO. Writing STGen s = Gen (PrimState (ST s)) doesn't
@@ -166,8 +166,8 @@
   pcg32_srandom_r p a b
   return (Gen p)
 
--- | Seed with system random number. (\"@\/dev\/urandom@\" on Unix-like
---   systems, time otherwise).
+-- | Seed with system random number. (@\/dev\/urandom@ on Unix-like
+--   systems and CryptAPI on Windows).
 withSystemRandom :: (GenIO -> IO a) -> IO a
 withSystemRandom f = do
   w1 <- sysRandom
diff --git a/src/System/Random/PCG/Fast.hs b/src/System/Random/PCG/Fast.hs
--- a/src/System/Random/PCG/Fast.hs
+++ b/src/System/Random/PCG/Fast.hs
@@ -147,8 +147,8 @@
   pcg32f_srandom_r p a
   return  (Gen p)
 
--- | Seed with system random number. (\"@\/dev\/urandom@\" on Unix-like
---   systems, time otherwise).
+-- | Seed with system random number. (@\/dev\/urandom@ on Unix-like
+--   systems and CryptAPI on Windows).
 withSystemRandom :: (GenIO -> IO a) -> IO a
 withSystemRandom f = do
   w <- sysRandom
diff --git a/src/System/Random/PCG/Fast/Pure.hs b/src/System/Random/PCG/Fast/Pure.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Random/PCG/Fast/Pure.hs
@@ -0,0 +1,332 @@
+{-# LANGUAGE BangPatterns               #-}
+{-# LANGUAGE CPP                        #-}
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE ForeignFunctionInterface   #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MagicHash                  #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE TypeFamilies               #-}
+{-# LANGUAGE UnboxedTuples              #-}
+#if __GLASGOW_HASKELL__ >= 707
+{-# LANGUAGE RoleAnnotations            #-}
+#endif
+-- |
+-- Module     : System.Random.PCG.Fast
+-- Copyright  : Copyright (c) 2015, Christopher Chalmers <c.chalmers@me.com>
+-- License    : BSD3
+-- Maintainer : Christopher Chalmers <c.chalmers@me.com>
+-- Stability  : experimental
+-- Portability: CPP, FFI
+--
+-- Fast variant of the PCG random number generator. This module performs
+-- around 20% faster than the multiple streams version but produces slightly
+-- lower quality (still good) random numbers.
+--
+-- See <http://www.pcg-random.org> for details.
+--
+-- @
+-- import Control.Monad.ST
+-- import System.Random.PCG.Fast
+--
+-- three :: [Double]
+-- three = runST $ do
+--   g <- create
+--   a <- uniform g
+--   b <- uniform g
+--   c <- uniform g
+--   return [a,b,c]
+-- @
+module System.Random.PCG.Fast.Pure
+  ( -- * Gen
+    Gen, GenIO, GenST
+  , create, createSystemRandom, initialize, withSystemRandom
+
+    -- * Getting random numbers
+  , Variate (..)
+  , advance, retract
+
+  , u1, u2, u3, Pair (..), pair, nxt, bounded, state, output
+
+    -- * Seeds
+  , FrozenGen, save, restore, seed, initFrozen
+
+    -- * Type restricted versions
+    -- ** uniform
+  , uniformW8, uniformW16, uniformW32, uniformW64
+  , uniformI8, uniformI16, uniformI32, uniformI64
+  , uniformF, uniformD, uniformBool
+
+    -- ** uniformR
+  , uniformRW8, uniformRW16, uniformRW32, uniformRW64
+  , uniformRI8, uniformRI16, uniformRI32, uniformRI64
+  , uniformRF, uniformRD, uniformRBool
+
+    -- ** uniformB
+  , uniformBW8, uniformBW16, uniformBW32, uniformBW64
+  , uniformBI8, uniformBI16, uniformBI32, uniformBI64
+  , uniformBF, uniformBD, uniformBBool
+  ) where
+
+import Control.Monad.Primitive
+import Data.Bits
+import Data.Primitive.ByteArray
+import Data.Primitive.Types
+import GHC.Word
+
+import System.Random
+import System.Random.PCG.Class
+
+newtype FrozenGen = F Word64
+  deriving (Show, Eq, Ord, Prim)
+
+newtype Gen s = G (MutableByteArray s)
+
+type GenIO = Gen RealWorld
+type GenST = Gen
+
+-- $setup
+-- >>> import System.Random.PCG.Fast.Pure
+-- >>> import System.Random.PCG.Class
+-- >>> import Control.Monad
+
+-- internals -----------------------------------------------------------
+
+data Pair = P {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word32
+  deriving Show
+
+fastMultiplier :: Word64
+fastMultiplier = 6364136223846793005
+
+-- Compute the next state of the generator
+state :: Word64 -> Word64
+state s = s * fastMultiplier
+
+-- Compute the output random number from the state of the generator.
+output :: Word64 -> Word32
+output s = fromIntegral $
+  ((s `shiftR` 22) `xor` s) `unsafeShiftR` (fromIntegral (s `shiftR` 61) + 22)
+
+-- Compute the next state and output in a strict pair.
+pair :: Word64 -> Pair
+pair s = P (state s) (output s)
+
+-- Given some bound and the generator, compute the new state and bounded
+-- random number.
+bounded :: Word32 -> Word64 -> Pair
+bounded b s0 = go s0
+  where
+    t = negate b `mod` b
+    go !s | r >= t    = P s' (r `mod` b)
+          | otherwise = go s'
+      where P s' r = pair s
+{- INLINE bounded #-}
+
+advancing
+  :: Word64 -- amount to advance by
+  -> Word64 -- state
+  -> Word64 -- multiplier
+  -> Word64 -- increment
+  -> Word64 -- new state
+advancing d0 s m0 p0 = go d0 m0 p0 1 0
+  where
+    go d cm cp am ap
+      | d <= 0    = am * s + ap
+      | odd d     = go d' cm' cp' (am * cm) (ap * cm + cp)
+      | otherwise = go d' cm' cp' am        ap
+      where
+        cm' = cm * cm
+        cp' = (cm + 1) * cp
+        d'  = d `div` 2
+
+advanceFast :: Word64 -> FrozenGen -> FrozenGen
+advanceFast d (F s) = F $ advancing d s fastMultiplier 0
+
+nxt :: FrozenGen -> (Word32, FrozenGen)
+nxt (F s) = (w, F s')
+  where
+    P s' w = pair s
+
+-- uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, uint64_t cur_mult,
+--                             uint64_t cur_plus)
+-- {
+--     uint64_t acc_mult = 1u;
+--     uint64_t acc_plus = 0u;
+--     while (delta > 0) {
+--         if (delta & 1) {
+--             acc_mult *= cur_mult;
+--             acc_plus = acc_plus * cur_mult + cur_plus;
+--         }
+--         cur_plus = (cur_mult + 1) * cur_plus;
+--         cur_mult *= cur_mult;
+--         delta /= 2;
+--     }
+--     return acc_mult * state + acc_plus;
+-- }
+
+------------------------------------------------------------------------
+-- Seed
+------------------------------------------------------------------------
+
+-- | Immutable state of a random number generator. Suitable for storing
+--   for later use.
+-- newtype FrozenGen = FrozenGen Word64
+--   deriving (Show, Eq, Ord, Storable, Data, Typeable, Generic)
+
+-- | Save the state of a 'Gen' in a 'Seed'.
+save :: PrimMonad m => Gen (PrimState m) -> m FrozenGen
+save (G a) = readByteArray a 0
+{-# INLINE save #-}
+
+-- | Restore a 'Gen' from a 'Seed'.
+restore :: PrimMonad m => FrozenGen -> m (Gen (PrimState m))
+restore f = do
+  a <- newByteArray 8
+  writeByteArray a 0 f
+  return $! G a
+{-# INLINE restore #-}
+
+-- | Generate a new seed using single 'Word64'.
+--
+--   >>> initFrozen 0
+--   FrozenGen 1
+initFrozen :: Word64 -> FrozenGen
+initFrozen w = F (w .|. 1)
+
+-- | Standard initial seed.
+seed :: FrozenGen
+seed = F 0xcafef00dd15ea5e5
+
+-- | Create a 'Gen' from a fixed initial seed.
+create :: PrimMonad m => m (Gen (PrimState m))
+create = restore seed
+
+------------------------------------------------------------------------
+-- Gen
+------------------------------------------------------------------------
+
+-- | State of the random number generator
+-- newtype Gen s = Gen (MutableByteArray s)
+--   deriving (Eq, Ord)
+-- #if __GLASGOW_HASKELL__ >= 707
+-- type role Gen representational
+-- #endif
+
+-- type GenIO = Gen RealWorld
+-- type GenST = Gen
+
+-- | Initialize a generator a single word.
+--
+--   >>> initialize 0 >>= save
+--   FrozenGen 1
+initialize :: PrimMonad m => Word64 -> m (Gen (PrimState m))
+initialize a = restore (initFrozen a)
+
+-- | Seed with system random number. (\"@\/dev\/urandom@\" on Unix-like
+--   systems, time otherwise).
+withSystemRandom :: (GenIO -> IO a) -> IO a
+withSystemRandom f = do
+  w <- sysRandom
+  initialize w >>= f
+
+-- | Seed a PRNG with data from the system's fast source of pseudo-random
+-- numbers. All the caveats of 'withSystemRandom' apply here as well.
+createSystemRandom :: IO GenIO
+createSystemRandom = withSystemRandom (return :: GenIO -> IO GenIO)
+
+-- -- | Generate a uniform 'Word32' bounded by the given bound.
+-- uniformB :: PrimMonad m => Word32 -> Gen (PrimState m) -> m Word32
+-- uniformB u (Gen p) = unsafePrimToPrim $ pcg32f_boundedrand_r p u
+-- {-# INLINE uniformB #-}
+
+-- | Advance the given generator n steps in log(n) time. (Note that a
+--   \"step\" is a single random 32-bit (or less) 'Variate'. Data types
+--   such as 'Double' or 'Word64' require two \"steps\".)
+--
+--   >>> create >>= \g -> replicateM_ 1000 (uniformW32 g) >> uniformW32 g
+--   3725702568
+--   >>> create >>= \g -> replicateM_ 500 (uniformD g) >> uniformW32 g
+--   3725702568
+--   >>> create >>= \g -> advance 1000 g >> uniformW32 g
+--   3725702568
+advance :: PrimMonad m => Word64 -> Gen (PrimState m) -> m ()
+advance u (G a) = do
+  s <- readByteArray a 0
+  let s' = advanceFast u s
+  writeByteArray a 0 s'
+{-# INLINE advance #-}
+
+-- | Retract the given generator n steps in log(2^64-n) time. This
+--   is just @advance (-n)@.
+--
+--   >>> create >>= \g -> replicateM 3 (uniformW32 g)
+--   [2951688802,2698927131,361549788]
+--   >>> create >>= \g -> retract 1 g >> replicateM 3 (uniformW32 g)
+--   [954135925,2951688802,2698927131]
+retract :: PrimMonad m => Word64 -> Gen (PrimState m) -> m ()
+retract u g = advance (-u) g
+{-# INLINE retract #-}
+
+------------------------------------------------------------------------
+-- Instances
+------------------------------------------------------------------------
+
+u1 :: GenIO -> IO Word32
+u1 (G !a) = do
+  s <- readByteArray a 0
+  let P s' r = pair s
+  writeByteArray a 0 s'
+  return r
+{-# INLINE u1 #-}
+
+u2 :: GenIO -> IO Word32
+u2 (G a) = do
+  s <- readByteArray a 0
+  let P s' r = pair s
+  writeByteArray a 0 s'
+  return r
+
+u3 :: GenIO -> IO Word32
+u3 (G a) = do
+  s <- readByteArray a 0
+  let P s' r = pair s
+  writeByteArray a 0 s'
+  return $! r
+
+instance (PrimMonad m, s ~ PrimState m) => Generator (Gen s) m where
+  uniform1 f (G a) = do
+    s <- readByteArray a 0
+    let P s' r = pair s
+    writeByteArray a 0 s'
+    return $! f r
+  {-# INLINE uniform1 #-}
+
+  uniform2 f (G a) = do
+    s <- readByteArray a 0
+    let s' = state s
+    writeByteArray a 0 (state s')
+    return $! f (output s) (output s')
+  {-# INLINE uniform2 #-}
+
+  uniform1B f b (G a) = do
+    s <- readByteArray a 0
+    let P s' r = bounded b s
+    writeByteArray a 0 s'
+    return $! f r
+  {-# INLINE uniform1B #-}
+
+instance RandomGen FrozenGen where
+  next (F s) = (wordsTo64Bit w1 w2, F s'')
+    where
+      P s'  w1 = pair s
+      P s'' w2 = pair s'
+
+  split (F s) = (mk w1 w2, mk w3 w4)
+    where
+      mk a b  = initFrozen $! wordsTo64Bit a b
+      P s1 w1 = pair s
+      P s2 w2 = pair s1
+      P s3 w3 = pair s2
+      w4 = output s3 -- abandon old state
+
diff --git a/src/System/Random/PCG/Single.hs b/src/System/Random/PCG/Single.hs
--- a/src/System/Random/PCG/Single.hs
+++ b/src/System/Random/PCG/Single.hs
@@ -142,8 +142,8 @@
   pcg32s_srandom_r p a
   return (Gen p)
 
--- | Seed with system random number. (\"@\/dev\/urandom@\" on Unix-like
---   systems, time otherwise).
+-- | Seed with system random number. (@\/dev\/urandom@ on Unix-like
+--   systems and CryptAPI on Windows).
 withSystemRandom :: (GenIO -> IO a) -> IO a
 withSystemRandom f = sysRandom >>= initialize >>= f
 
