1 /******************************************************************************* 2 3 Copyright: 4 Copyright (c) 2008. Fawzi Mohamed 5 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH. 6 All rights reserved. 7 8 License: 9 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0. 10 See LICENSE_TANGO.txt for details. 11 12 Version: Initial release: July 2008 13 14 Authors: Fawzi Mohamed 15 16 *******************************************************************************/ 17 module ocean.math.random.ExpSource; 18 import Integer = ocean.text.convert.Integer_tango; 19 import ocean.math.Math:exp,log; 20 import ocean.math.random.Ziggurat; 21 import ocean.meta.traits.Basic /* : isRealType */; 22 23 /// class that returns exponential distributed numbers (f=exp(-x) for x>0, 0 otherwise) 24 final class ExpSource(RandG,T){ 25 static assert(isRealType!(T),T.stringof~" not acceptable, only floating point variables supported"); 26 /// probability distribution 27 static real probDensityF(real x){ return exp(-x); } 28 /// inverse probability distribution 29 static real invProbDensityF(real x){ return -log(x); } 30 /// complement of the cumulative density distribution (integral x..infinity probDensityF) 31 static real cumProbDensityFCompl(real x){ return exp(-x); } 32 /// tail for exponential distribution 33 static T tailGenerator(RandG r, T dMin) 34 { 35 return dMin-log(r.uniform!(T)); 36 } 37 alias Ziggurat!(RandG,T,probDensityF,tailGenerator,false) SourceT; 38 /// internal source of exp distribued numbers 39 SourceT source; 40 /// initializes the probability distribution 41 this(RandG r){ 42 source=SourceT.create!(invProbDensityF,cumProbDensityFCompl)(r,0xf.64ec94bf5dc14bcp-1L); 43 } 44 /// chainable call style initialization of variables (thorugh a call to randomize) 45 ExpSource opCall(U,S...)(ref U a,S args){ 46 randomize(a,args); 47 return this; 48 } 49 /// returns a exp distribued number 50 T getRandom(){ 51 return source.getRandom(); 52 } 53 /// returns a exp distribued number with the given beta (survival rate, average) 54 /// f=1/beta*exp(-x/beta) 55 T getRandom(T beta){ 56 return beta*source.getRandom(); 57 } 58 /// initializes the given variable with an exponentially distribued number 59 U randomize(U)(ref U x){ 60 return source.randomize(x); 61 } 62 /// initializes the given variable with an exponentially distribued number with 63 /// scale parameter beta 64 U randomize(U,V)(ref U x,V beta){ 65 return source.randomizeOp((T el){ return el*cast(T)beta; },x); 66 } 67 /// initializes the given variable with an exponentially distribued number and maps op on it 68 U randomizeOp(U,S)(scope S delegate(T)op,ref U a){ 69 return source.randomizeOp(op,a); 70 } 71 /// exp distribution with different default scale parameter beta 72 /// f=1/beta*exp(-x/beta) for x>0, 0 otherwise 73 struct ExpDistribution{ 74 T beta; 75 ExpSource source; // does not use Ziggurat directly to keep this struct small 76 /// constructor 77 static ExpDistribution create()(ExpSource source,T beta){ 78 ExpDistribution res; 79 res.beta=beta; 80 res.source=source; 81 return res; 82 } 83 /// chainable call style initialization of variables (thorugh a call to randomize) 84 ExpDistribution opCall(U,S...)(ref U a,S args){ 85 randomize(a,args); 86 return this; 87 } 88 /// returns a single number 89 T getRandom(){ 90 return beta*source.getRandom(); 91 } 92 /// initialize a 93 U randomize(U)(ref U a){ 94 return source.randomizeOp((T x){return beta*x; },a); 95 } 96 /// initialize a 97 U randomize(U,V)(ref U a,V b){ 98 return source.randomizeOp((T x){return (cast(T)b)*x; },a); 99 } 100 } 101 /// returns an exp distribution with a different beta 102 ExpDistribution expD(T beta){ 103 return ExpDistribution.create(this,beta); 104 } 105 }