{-# LANGUAGE ForeignFunctionInterface #-}------------------------------------------------------------------------------- |-- Module : GSL.Random.Gen.Internal-- Copyright : Copyright (c) , Patrick Perry <patperry@stanford.edu>-- License : BSD3-- Maintainer : Patrick Perry <patperry@stanford.edu>-- Stability : experimental--moduleGSL.Random.Gen.Internal(-- * Data typesRNG(..),RNGType,-- * InitializingnewRNG,setSeed,-- * SamplinggetSample,getUniform,getUniformPos,getUniformInt,-- * Auxiliary functionsgetName,getMax,getMin,getSize,getState,setState,-- * Copying statecopyRNG,cloneRNG,-- * Algorithmsmt19937,rngType,)whereimportControl.MonadimportData.Maybe(fromJust)importForeignimportForeign.C.StringimportForeign.C.TypesnewtypeRNG=MkRNG(ForeignPtr())newtypeRNGType=MkRNGType(Ptr())--------------------------- Initialization ------------------------------------ | Allocate a new random number generator of the given type and initialize-- it with the default seed.newRNG::RNGType->IORNGnewRNGt=doptr<-gsl_rng_alloctfptr<-newForeignPtrp_gsl_rng_freeptrreturn$!MkRNGfptrforeignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_alloc::RNGType->IO(Ptr())foreignimportccallunsafe"gsl/gsl_rng.h &gsl_rng_free"p_gsl_rng_free::FunPtr(Ptr()->IO())-- | Seed the generator with the given value.setSeed::RNG->Word64->IO()setSeed(MkRNGfptr)seed=letseed'=(fromInteger.toInteger)seedinwithForeignPtrfptr$flipgsl_rng_setseed'foreignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_set::Ptr()->CULong->IO()--------------------------- Sampling ------------------------------------------ | Returns a value uniform in [rngMin, rngMax]getSample::RNG->IOWord64getSample(MkRNGfptr)=withForeignPtrfptr$\ptr->gsl_rng_getptr>>=return.fromInteger.toIntegerforeignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_get::Ptr()->IOCULong-- | Returns a value uniform on [0,1)getUniform::RNG->IODoublegetUniform(MkRNGfptr)=withForeignPtrfptr$\ptr->gsl_rng_uniformptr>>=return.realToFracforeignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_uniform::Ptr()->IOCDouble-- | Returns a value uniform on (0,1)getUniformPos::RNG->IODoublegetUniformPos(MkRNGfptr)=withForeignPtrfptr$\ptr->gsl_rng_uniform_posptr>>=return.realToFracforeignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_uniform_pos::Ptr()->IOCDouble-- | Returns an integer uniform on [0,n-1]. @n@ must be greater than @0@.getUniformInt::RNG->Int->IOIntgetUniformInt(MkRNGfptr)n|n<=0=ioError$userError$"rngUnifInt: expected \"n\" to be greater than 0"++" but got `"++shown++"' instead."|otherwise=letn'=(fromInteger.toInteger)ninwithForeignPtrfptr$\ptr->gsl_rng_uniform_intptrn'>>=return.fromInteger.toIntegerforeignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_uniform_int::Ptr()->CULong->IOCULong--------------------------- Auxiliary Functions ------------------------------- | Get the name of the generator.getName::RNG->IOStringgetName(MkRNGfptr)=withForeignPtrfptr$\ptr->peekCAString(gsl_rng_nameptr)foreignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_name::Ptr()->CString-- | Get the largest value that the generator can return.getMax::RNG->IOWord64getMax(MkRNGfptr)=withForeignPtrfptr$\ptr->(return.fromInteger.toInteger)(gsl_rng_maxptr)foreignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_max::Ptr()->CULong-- | Get the smallest value that the generator can return.getMin::RNG->IOWord64getMin(MkRNGfptr)=withForeignPtrfptr$\ptr->(return.fromInteger.toInteger)(gsl_rng_minptr)foreignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_min::Ptr()->CULong-- | Get the size of the generator state, in bytes.getSize::RNG->IOWord64getSize(MkRNGfptr)=withForeignPtrfptr$\ptr->(return.fromInteger.toInteger)(gsl_rng_sizeptr)foreignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_size::Ptr()->CSize-- | Get the generator state.getState::RNG->IO[Word8]getStaterng@(MkRNGfptr)=don<-liftM(fromInteger.toInteger)(getSizerng)withForeignPtrfptr$\ptr->peekArrayn(gsl_rng_stateptr)foreignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_state::Ptr()->PtrWord8-- | Set the generator state. The input array should have size equal-- to @getSize@ of the generator; otherwise, strange things will happen.setState::RNG->[Word8]->IO()setState(MkRNGfptr)state=dowithForeignPtrfptr$\ptr->pokeArray(gsl_rng_stateptr)state--------------------------- Copying State ------------------------------------- | @copyRNG dst src@ copies the state from one generator to another. The-- two generators must have the same type.copyRNG::RNG->RNG->IO()copyRNG(MkRNGfdst)(MkRNGfsrc)=withForeignPtrfdst$\dst->withForeignPtrfsrc$\src->gsl_rng_memcpydstsrcforeignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_memcpy::Ptr()->Ptr()->IO()-- | Allocate a new random number generator that is an exact copy of another-- generatorcloneRNG::RNG->IORNGcloneRNG(MkRNGfptr)=withForeignPtrfptr$\ptr->doptr'<-gsl_rng_cloneptrfptr'<-newForeignPtrp_gsl_rng_freeptr'ptr'`seq`return$!MkRNGfptr'foreignimportccallunsafe"gsl/gsl_rng.h"gsl_rng_clone::Ptr()->IO(Ptr())--------------------------- Algorithms --------------------------------------mt19937::RNGTypemt19937=fromJust$rngType"mt19937"rngType::String->MaybeRNGTyperngTypestr=unsafePerformIO$withCAStringstr$\name->getRngTypenamegetRngType::CString->IO(MaybeRNGType)getRngTypename=gogsl_rng_types_setupwherego::Ptr(Ptr())->IO(MaybeRNGType)gotypes=dot<-peektypesift==nullPtrthenreturnNothingelsedoname'<-peek(castPtrt)cmp<-c_strcmpnamename'ifcmp==0thenreturn$Just(MkRNGTypet)elsego$types`advancePtr`1foreignimportccallunsafe"string.h strcmp"c_strcmp::CString->CString->IOCIntforeignimportccallunsafe"gsl/gsl_randist.h"gsl_rng_types_setup::Ptr(Ptr())