packages feed

gsl-random-fu (empty) → 0.0.0.1

raw patch · 3 files changed

+111/−0 lines, 3 filesdep +basedep +gsl-randomdep +random-fusetup-changed

Dependencies added: base, gsl-random, random-fu

Files

+ Setup.lhs view
@@ -0,0 +1,5 @@+#!/usr/bin/env runhaskell++> import Distribution.Simple+> main = defaultMain+
+ gsl-random-fu.cabal view
@@ -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
+ src/Data/Random/Source/GSL.hs view
@@ -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