Skip to content
Browse files

Added more haddock docs and simplified the way RNGs are initialised b…

…y default
  • Loading branch information...
1 parent dc0f47b commit f4c28fc5f9b2bd5b6e04bd9778ad9825f94b042b @bjpop committed Aug 29, 2011
Showing with 114 additions and 12 deletions.
  1. +3 −3 examples/Simple.hs
  2. +79 −9 src/Sprng.hs
  3. +26 −0 src/Sprng/Internal.hs
  4. +5 −0 src/cbits/sprng_wrapper.cpp
  5. +1 −0 src/include/sprng_wrapper.h
View
6 examples/Simple.hs
@@ -1,14 +1,14 @@
{-# LANGUAGE ScopedTypeVariables #-}
--- compile with: ghc --make Foo.hs -pgml /path/to/g++
+-- compile with: ghc -O2 --make Foo.hs -pgml /path/to/g++
module Main where
import Sprng
main = do
- gen1 :: RNG LFG <- newRng
- initRng gen1 0 1 985456376 0
+ seed <- newSeed
+ gen1 :: RNG LFG <- newRng seed
[gen2, gen3, gen4] <- spawnRng gen1 3
printRandInts gen1 10
printRandDoubles gen1 10
View
88 src/Sprng.hs
@@ -1,53 +1,123 @@
{-# LANGUAGE EmptyDataDecls #-}
+-- | This library implements a Haskell interface to the
+-- Scalable Parallel Pseudo Random Number Generators Library (SPRNG)
+-- <http://sprng.cs.fsu.edu>.
+--
+-- It provides several types of generator algorithms:
+--
+-- * Additive Lagged Fibonacci (LFG)
+--
+-- * Multiplicative Lagged Fibonacci (MLFG)
+--
+-- * Linear Congruential (LCG)
+--
+-- * Combined Multiple Recursive (CMRG)
+--
+-- * Prime Modulus Linear Congruential (PMLCG)
+--
+-- The generators are splittable, which means that new generators can
+-- be spawned from existing ones (many times, though not infinitely).
module Sprng
( RNG {- abstract -}
+ , UnInitRNG {- abstract -}
, SprngGen (..)
, LFG, LCG, LCG64, CMRG, MLFG, PMLCG
, Internal.newSeed
) where
import qualified Sprng.Internal as Internal
+-- | An abstract Random Number Generator, parameterised by the type of algorithm used.
data RNG a = RNG Internal.Sprng
+-- | An uninitialised abstract Random Number Generator, parameterised by the type of algorithm used.
+data UnInitRNG a = UnInitRNG Internal.Sprng
+
+-- | A token representing the Additive Lagged Fibonacci Generator.
data LFG
+-- | A token representing the Linear Congruential Generator.
data LCG
+-- | A token representing the 64bit Linear Congruential Generator.
data LCG64
+-- | A token representing the Combined Multiple Recursive Generator.
data CMRG
+-- | A token representing the Multiplicative Lagged Fibonnaci Generator.
data MLFG
+-- | A token representing the Prime Modulus Linear Congruential Generator.
data PMLCG
+-- | Interface to the SPRNG generators
class SprngGen a where
- newRng :: IO (RNG a)
- initRng :: RNG a -> Int -> Int -> Int -> Int -> IO ()
+
+ -- | Construct a new generator, given a seed as input, and initialise with default parameters.
+ newRng :: Int -- ^ Seed.
+ -> IO (RNG a) -- ^ Initialised generator.
+
+ -- | Construct a new generator but do not initialise it.
+ newRngUninitialised :: IO (UnInitRNG a)
+
+ -- | Initialise a previously uninitialised generator.
+ initRng :: UnInitRNG a -- ^ Uninitialised generator.
+ -> Int -- ^ Stream number.
+ -> Int -- ^ Number of streams.
+ -> Int -- ^ Seed.
+ -> Int -- ^ RNG specific parameter.
+ -> IO (RNG a) -- ^ Initialised generator.
+
+ -- | Generate a random Int.
randomInt :: RNG a -> IO Int
+
+ -- | Generate a random Float.
randomFloat :: RNG a -> IO Float
+
+ -- | Generate a random Double.
randomDouble :: RNG a -> IO Double
+
+ -- | Create new generators from an existing one.
spawnRng :: RNG a -> Int -> IO [RNG a]
+
+ -- | Print a representation of the generator for diagnostic purposes.
printRng :: RNG a -> IO ()
printRng (RNG rng) = Internal.printRng rng
+ -- default implementations which just call the underlying SPRNG libs.
randomInt (RNG rng) = Internal.getRandomInt rng
randomFloat (RNG rng) = Internal.getRandomFloat rng
randomDouble (RNG rng) = Internal.getRandomDouble rng
spawnRng (RNG rng) n = map RNG `fmap` Internal.spawnRng rng n
- initRng (RNG rng) = Internal.initRng rng
+ initRng (UnInitRNG rng) streamnum nstreams seed param = do
+ Internal.initRng rng streamnum nstreams seed param
+ return $ RNG rng
+
+-- construct a new RNG and initialise it.
+mkNewRng :: Internal.RngType -> Int -> IO (RNG a)
+mkNewRng rngType seed = do
+ rng <- Internal.newRng rngType
+ defaultParam <- Internal.sprngDefault
+ Internal.initRng rng 0 1 seed defaultParam
+ return $ RNG rng
instance SprngGen LFG where
- newRng = RNG `fmap` Internal.newRng Internal.LFG
+ newRng = mkNewRng Internal.LFG
+ newRngUninitialised = UnInitRNG `fmap` Internal.newRng Internal.LFG
instance SprngGen LCG where
- newRng = RNG `fmap` Internal.newRng Internal.LCG
+ newRng = mkNewRng Internal.LCG
+ newRngUninitialised = UnInitRNG `fmap` Internal.newRng Internal.LCG
instance SprngGen LCG64 where
- newRng = RNG `fmap` Internal.newRng Internal.LCG64
+ newRng = mkNewRng Internal.LCG64
+ newRngUninitialised = UnInitRNG `fmap` Internal.newRng Internal.LCG64
instance SprngGen CMRG where
- newRng = RNG `fmap` Internal.newRng Internal.CMRG
+ newRng = mkNewRng Internal.CMRG
+ newRngUninitialised = UnInitRNG `fmap` Internal.newRng Internal.CMRG
instance SprngGen MLFG where
- newRng = RNG `fmap` Internal.newRng Internal.MLFG
+ newRng = mkNewRng Internal.MLFG
+ newRngUninitialised = UnInitRNG `fmap` Internal.newRng Internal.MLFG
instance SprngGen PMLCG where
- newRng = RNG `fmap` Internal.newRng Internal.PMLCG
+ newRng = mkNewRng Internal.PMLCG
+ newRngUninitialised = UnInitRNG `fmap` Internal.newRng Internal.PMLCG
View
26 src/Sprng/Internal.hs
@@ -12,6 +12,7 @@ module Sprng.Internal
, printRng
, spawnRng
, newSeed
+ , sprngDefault
) where
import Foreign.Ptr (Ptr, FunPtr)
@@ -21,6 +22,8 @@ import Foreign.Marshal.Array (peekArray)
type Sprng = ForeignPtr ()
type SprngPtr = Ptr ()
+
+-- An enumeration of all the generator types.
data RngType = LFG | LCG | LCG64 | CMRG | MLFG | PMLCG
deriving (Eq, Show, Enum)
@@ -29,15 +32,38 @@ data RngType = LFG | LCG | LCG64 | CMRG | MLFG | PMLCG
-- attribute allows much faster foreign calls to be made, and this provides
-- a signficant performance benefit, especially for the functions which are
-- typically called frequently (such as get_rn_int).
+
+-- | The default SPRNG value for RNG specific parameters.
+foreign import ccall unsafe "sprng_default" sprngDefault :: IO Int
+
+-- | Generate a new seed value based on local time value.
foreign import ccall unsafe "new_seed" newSeed :: IO Int
+
+-- | Construct a new RNG.
foreign import ccall unsafe "new_rng" new_rng :: CInt -> IO SprngPtr
+
+-- | Initialise a new RNG.
foreign import ccall unsafe "init_rng" init_rng :: SprngPtr -> CInt -> CInt -> CInt -> CInt -> IO ()
+
+-- | Generate a new random int.
foreign import ccall unsafe "get_rn_int" get_rn_int :: SprngPtr -> IO CInt
+
+-- | Generate a new random float.
foreign import ccall unsafe "get_rn_flt" get_rn_flt :: SprngPtr -> IO CFloat
+
+-- | Generate a new random double.
foreign import ccall unsafe "get_rn_dbl" get_rn_dbl :: SprngPtr -> IO CDouble
+
+-- | Print a RNG for diagnostic purposes.
foreign import ccall unsafe "print_rng" print_rng :: SprngPtr -> IO ()
+
+-- | Spawn a new RNG from an existing one.
foreign import ccall unsafe "spawn_rng" spawn_rng :: SprngPtr -> CInt -> IO (Ptr SprngPtr)
+
+-- | Free the memory of an RNG.
foreign import ccall unsafe "&free_rng" freeRngFunPtr :: FunPtr (SprngPtr -> IO ())
+
+-- | Free the memory allocated to a buffer of spawned RNGs.
foreign import ccall unsafe "free_spawn_buffer" freeSpawnBuffer :: Ptr (SprngPtr) -> IO ()
newRng :: RngType -> IO Sprng
View
5 src/cbits/sprng_wrapper.cpp
@@ -1,5 +1,10 @@
#include "sprng_wrapper.h"
+int sprng_default(void)
+{
+ return SPRNG_DEFAULT;
+}
+
int new_seed(void)
{
return make_new_seed();
View
1 src/include/sprng_wrapper.h
@@ -4,6 +4,7 @@
#include "sprng.h"
#include "sprng_cpp.h"
+extern "C" int sprng_default(void);
extern "C" int new_seed(void);
extern "C" Sprng * new_rng(int);
extern "C" void init_rng(Sprng *, int, int, int, int);

0 comments on commit f4c28fc

Please sign in to comment.
Something went wrong with that request. Please try again.