diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,5 @@
+#!/usr/bin/env runhaskell
+
+> import Distribution.Simple
+> main = defaultMain
+
diff --git a/gsl-random-fu.cabal b/gsl-random-fu.cabal
new file mode 100644
--- /dev/null
+++ b/gsl-random-fu.cabal
@@ -0,0 +1,21 @@
+name:                   gsl-random-fu
+version:                0.0.0.1
+stability:              provisional
+
+cabal-version:          >= 1.2
+build-type:             Simple
+
+author:                 James Cook <james.cook@usma.edu>
+maintainer:             James Cook <james.cook@usma.edu>
+license:                PublicDomain
+homepage:               http://code.haskell.org/~mokus/gsl-random-fu
+
+category:               Math
+synopsis:               Instances for using gsl-random with random-fu
+description:            Instances for using gsl-random's RNG type as a
+                        random-fu RandomSource.
+
+Library
+  hs-source-dirs:       src
+  exposed-modules:      Data.Random.Source.GSL
+  build-depends:        gsl-random, random-fu >= 0.0.1.1, base >= 3
diff --git a/src/Data/Random/Source/GSL.hs b/src/Data/Random/Source/GSL.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Random/Source/GSL.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE
+        MultiParamTypeClasses
+  #-}
+
+module Data.Random.Source.GSL
+    ( wrapRNG
+    , newWrappedRNG
+    , WrappedRNG
+    ) where
+
+import GSL.Random.Gen
+import Data.Random.Source
+
+import Data.Word
+import Data.List
+import Data.Maybe
+import Data.Bits
+
+-- |'RNG's may not produce random words in the full range of Word64.  Therefore,
+-- 'getRandomWordFrom' requires that the range of the generator be checked, and
+-- if it does not produce the full range, multiple samples will be taken to produce
+-- a suitable 'Word64'.  The triage part will be done every time if sampling from
+-- a raw 'RNG'.  Using 'WrappedRNG' allows that triage to be done ahead of time,
+-- speeding up sampling integral values at the expense of an unwrap
+-- when sampling 'Double's.
+data WrappedRNG
+    = RNG32 { unwrapRNG :: RNG }
+    | RNG64 { unwrapRNG :: RNG }
+    | RNGOther { unwrapRNG :: RNG, getWord64 :: IO Word64 }
+
+newWrappedRNG rng = newRNG rng >>= wrapRNG
+
+wrapRNG rng = do
+    mn <- getMin rng
+    mx <- getMax rng
+    return $ case (mn, mx) of
+        (0,18446744073709551615)    -> RNG64 rng
+        (_,x) -> if mn == 0 && x >= 4294967295
+            then RNG32 rng 
+            else RNGOther rng getWord64
+            
+            where 
+                getAdjustedSample
+                    | mn == 0   = getSample rng
+                    | otherwise = do
+                        x <- getSample rng
+                        return (x - mn)
+                
+                mxAdjusted = mx - mn
+                
+                bitsPerSample = log2 mxAdjusted
+                
+                -- Need to mask a sample if bitsPerSample is not precise?
+                -- Seems like no, because any determinism will be
+                -- smashed by the next sample
+                
+                getWord64 = getBits 0 0
+                
+                getBits offset accum
+                    | offset >= 64 = return accum
+                    | otherwise = do
+                        x <- getAdjustedSample
+                        getBits (offset + bitsPerSample) $! (accum `xor` (x `shiftL` offset))
+
+log2 :: Word64 -> Int
+log2 x = fromJust (findIndex (>x) powersOf2)
+
+powersOf2 :: [Word64]
+powersOf2 = map bit [0..63]
+
+instance RandomSource IO WrappedRNG where
+    getRandomWordFrom (RNG32 rng) = do
+        x <- getSample rng
+        y <- getSample rng
+        return (x .|. (y `shiftL` 32))
+    getRandomWordFrom (RNG64 rng) = getSample rng
+    getRandomWordFrom other = getWord64 other
+        
+    getRandomDoubleFrom = getUniform . unwrapRNG
+    getRandomByteFrom rng = fmap fromIntegral (getUniformInt (unwrapRNG rng) 255)
+
+instance RandomSource IO RNG where
+    getRandomByteFrom rng = fmap fromIntegral (getUniformInt rng 255)
+    getRandomWordFrom rng = wrapRNG rng >>= getRandomWordFrom
+    getRandomDoubleFrom = getUniform
