123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
|
/*******************************************************************************
copyright: Copyright (c) 2008. Fawzi Mohamed
license: BSD style: $(LICENSE)
version: Initial release: July 2008
author: Fawzi Mohamed
*******************************************************************************/
module tango.math.random.ExpSource;
private import Integer = tango.text.convert.Integer;
import tango.math.Math:exp,log;
import tango.math.random.Ziggurat;
import tango.core.Traits:isRealType;
/// class that returns exponential distributed numbers (f=exp(-x) for x>0, 0 otherwise)
final class ExpSource(RandG,T){
static assert(isRealType!(T),T.stringof~" not acceptable, only floating point variables supported");
/// probability distribution
static real probDensityF(real x){ return exp(-x); }
/// inverse probability distribution
static real invProbDensityF(real x){ return -log(x); }
/// complement of the cumulative density distribution (integral x..infinity probDensityF)
static real cumProbDensityFCompl(real x){ return exp(-x); }
/// tail for exponential distribution
static T tailGenerator(RandG r, T dMin)
{
return dMin-log(r.uniform!(T)());
}
alias Ziggurat!(RandG,T,probDensityF,tailGenerator,false) SourceT;
/// internal source of exp distribued numbers
SourceT source;
/// initializes the probability distribution
this(RandG r){
source=SourceT.create!(invProbDensityF,cumProbDensityFCompl)(r,0xf.64ec94bf5dc14bcp-1L);
}
/// chainable call style initialization of variables (thorugh a call to randomize)
ExpSource opCall(U,S...)(ref U a,S args){
randomize(a,args);
return this;
}
/// returns a exp distribued number
T getRandom(){
return source.getRandom();
}
/// returns a exp distribued number with the given beta (survival rate, average)
/// f=1/beta*exp(-x/beta)
T getRandom(T beta){
return beta*source.getRandom();
}
/// initializes the given variable with an exponentially distribued number
U randomize(U)(ref U x){
return source.randomize(x);
}
/// initializes the given variable with an exponentially distribued number with
/// scale parameter beta
U randomize(U,V)(ref U x,V beta){
return source.randomizeOp((T el){ return el*cast(T)beta; },x);
}
/// initializes the given variable with an exponentially distribued number and maps op on it
U randomizeOp(U,S)(scope S delegate(T)op,ref U a){
return source.randomizeOp(op,a);
}
/// exp distribution with different default scale parameter beta
/// f=1/beta*exp(-x/beta) for x>0, 0 otherwise
struct ExpDistribution{
T beta;
ExpSource source; // does not use Ziggurat directly to keep this struct small
/// constructor
static ExpDistribution create()(ExpSource source,T beta){
ExpDistribution res;
res.beta=beta;
res.source=source;
return res;
}
/// chainable call style initialization of variables (thorugh a call to randomize)
ExpDistribution opCall(U,S...)(ref U a,S args){
randomize(a,args);
return this;
}
/// returns a single number
T getRandom(){
return beta*source.getRandom();
}
/// initialize a
U randomize(U)(ref U a){
return source.randomizeOp((T x){return beta*x; },a);
}
/// initialize a
U randomize(U,V)(ref U a,V b){
return source.randomizeOp((T x){return (cast(T)b)*x; },a);
}
}
/// returns an exp distribution with a different beta
ExpDistribution expD(T beta){
return ExpDistribution.create(this,beta);
}
}
|