ADMB Documentation  -a65f1c97
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
drangam.cpp
Go to the documentation of this file.
1 /*
2  * $Id$
3  *
4  * Authors: H. H. Ahrens, U. Dieter and B. W. Brown.
5  * License: Public domain.
6  */
11 #include <fvar.hpp>
12 
13 /*
14 void main()
15 {
16  int n=1000;
17  dvector v(1,n);
18  random_number_generator rng(1011);
19 
20  v(1)=sgamma(18.0,rng);
21  for (int i=1;i<=n;i++)
22  {
23  //v(i)=sgamma(double(i),rng);
24  v(i)=sgamma(.5,rng);
25  }
26  cout << mean(v) << endl;
27 }
28 */
29 
33 static double fsign( double num, double sign )
34 {
35 if ( ( sign>0.0f && num<0.0f ) || ( sign<0.0f && num>0.0f ) )
36  return -num;
37 else return num;
38 }
39 
44 double sgamma(double a,const random_number_generator& _rng)
45 /*
46 **********************************************************************
47 
48 
49  (STANDARD-) G A M M A DISTRIBUTION
50 
51 
52 **********************************************************************
53 **********************************************************************
54 
55  PARAMETER A >= 1.0 !
56 
57 **********************************************************************
58 
59  FOR DETAILS SEE:
60 
61  AHRENS, J.H. AND DIETER, U.
62  GENERATING GAMMA VARIATES BY A
63  MODIFIED REJECTION TECHNIQUE.
64  COMM. ACM, 25,1 (JAN. 1982), 47 - 54.
65 
66  STEP NUMBERS CORRESPOND TO ALGORITHM 'GD' IN THE ABOVE PAPER
67  (STRAIGHTFORWARD IMPLEMENTATION)
68 
69  Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of
70  SUNIF. The argument IR thus goes away.
71 
72 **********************************************************************
73 
74  PARAMETER 0.0 < A < 1.0 !
75 
76 **********************************************************************
77 
78  FOR DETAILS SEE:
79 
80  AHRENS, J.H. AND DIETER, U.
81  COMPUTER METHODS FOR SAMPLING FROM GAMMA,
82  BETA, POISSON AND BINOMIAL DISTRIBUTIONS.
83  COMPUTING, 12 (1974), 223 - 246.
84 
85  (ADAPTED IMPLEMENTATION OF ALGORITHM 'GS' IN THE ABOVE PAPER)
86 
87 **********************************************************************
88  INPUT: A =PARAMETER (MEAN) OF THE STANDARD GAMMA DISTRIBUTION
89  OUTPUT: SGAMMA = SAMPLE FROM THE GAMMA-(A)-DISTRIBUTION
90  COEFFICIENTS Q(K) - FOR Q0 = SUM(Q(K)*A**(-K))
91  COEFFICIENTS A(K) - FOR Q = Q0+(T*T/2)*SUM(A(K)*V**K)
92  COEFFICIENTS E(K) - FOR EXP(Q)-1 = SUM(E(K)*Q**K)
93  PREVIOUS A PRE-SET TO ZERO - AA IS A', AAA IS A"
94  SQRT32 IS THE SQUAREROOT OF 32 = 5.656854249492380
95 */
96 {
98 static double q1 = 4.166669E-2;
99 static double q2 = 2.083148E-2;
100 static double q3 = 8.01191E-3;
101 static double q4 = 1.44121E-3;
102 static double q5 = -7.388E-5;
103 static double q6 = 2.4511E-4;
104 static double q7 = 2.424E-4;
105 static double a1 = 0.3333333;
106 static double a2 = -0.250003;
107 static double a3 = 0.2000062;
108 static double a4 = -0.1662921;
109 static double a5 = 0.1423657;
110 static double a6 = -0.1367177;
111 static double a7 = 0.1233795;
112 static double e1 = 1.0;
113 static double e2 = 0.4999897;
114 static double e3 = 0.166829;
115 static double e4 = 4.07753E-2;
116 static double e5 = 1.0293E-2;
117 static double aa = 0.0;
118 static double aaa = 0.0;
119 static double sqrt32 = 5.656854;
120 /* JJV added b0 to fix rare and subtle bug */
121 static double sgamma,s2,s,d,t,x,u,r,q0,b,b0,si,c,v,q,e,w,p;
122  if(a == aa) goto S10;
123  if(a < 1.0) goto S120;
124 /*
125  STEP 1: RECALCULATIONS OF S2,S,D IF A HAS CHANGED
126 */
127  aa = a;
128  s2 = a-0.5;
129  s = sqrt(s2);
130  d = sqrt32-12.0*s;
131 S10:
132 /*
133  STEP 2: T=STANDARD NORMAL DEVIATE,
134  X=(S,1/2)-NORMAL DEVIATE.
135  IMMEDIATE ACCEPTANCE (I)
136 */
137  t = gasdev(rng);
138  x = s+0.5*t;
139  sgamma = x*x;
140  if(t >= 0.0)
141  return sgamma;
142 /*
143  STEP 3: U= 0,1 -UNIFORM SAMPLE. SQUEEZE ACCEPTANCE (S)
144 */
145  u = rng.better_rand();
146  //u=ranf();
147  if(d*u <= t*t*t) return sgamma;
148 /*
149  STEP 4: RECALCULATIONS OF Q0,B,SI,C IF NECESSARY
150 */
151  if(a == aaa) goto S40;
152  aaa = a;
153  r = 1.0/ a;
154  q0 = ((((((q7*r+q6)*r+q5)*r+q4)*r+q3)*r+q2)*r+q1)*r;
155 /*
156  APPROXIMATION DEPENDING ON SIZE OF PARAMETER A
157  THE CONSTANTS IN THE EXPRESSIONS FOR B, SI AND
158  C WERE ESTABLISHED BY NUMERICAL EXPERIMENTS
159 */
160  if(a <= 3.686) goto S30;
161  if(a <= 13.022) goto S20;
162 /*
163  CASE 3: A .GT. 13.022
164 */
165  b = 1.77;
166  si = 0.75;
167  c = 0.1515/s;
168  goto S40;
169 S20:
170 /*
171  CASE 2: 3.686 .LT. A .LE. 13.022
172 */
173  b = 1.654+7.6E-3*s2;
174  si = 1.68/s+0.275;
175  c = 6.2E-2/s+2.4E-2;
176  goto S40;
177 S30:
178 /*
179  CASE 1: A .LE. 3.686
180 */
181  b = 0.463+s+0.178*s2;
182  si = 1.235;
183  c = 0.195/s-7.9E-2+1.6E-1*s;
184 S40:
185 /*
186  STEP 5: NO QUOTIENT TEST IF X NOT POSITIVE
187 */
188  if(x <= 0.0) goto S70;
189 /*
190  STEP 6: CALCULATION OF V AND QUOTIENT Q
191 */
192  v = t/(s+s);
193  if(fabs(v) <= 0.25) goto S50;
194  q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v);
195  goto S60;
196 S50:
197  q = q0+0.5*t*t*((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;
198 S60:
199 /*
200  STEP 7: QUOTIENT ACCEPTANCE (Q)
201 */
202  if(log(1.0-u) <= q) return sgamma;
203 S70:
204 /*
205  STEP 8: E=STANDARD EXPONENTIAL DEVIATE
206  U= 0,1 -UNIFORM DEVIATE
207  T=(B,SI)-DOUBLE EXPONENTIAL (LAPLACE) SAMPLE
208 */
209  e = expdev(rng);
210  u = rng.better_rand();
211  // u = ranf();
212  u += (u-1.0);
213  t = b+fsign(si*e,u);
214 /*
215  STEP 9: REJECTION IF T .LT. TAU(1) = -.71874483771719
216 */
217  if(t < -0.7187449) goto S70;
218 /*
219  STEP 10: CALCULATION OF V AND QUOTIENT Q
220 */
221  v = t/(s+s);
222  if(fabs(v) <= 0.25) goto S80;
223  q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v);
224  goto S90;
225 S80:
226  q = q0+0.5*t*t*((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;
227 S90:
228 /*
229  STEP 11: HAT ACCEPTANCE (H) (IF Q NOT POSITIVE GO TO STEP 8)
230 */
231  if(q <= 0.0) goto S70;
232  if(q <= 0.5) goto S100;
233 /*
234  * JJV modified the code through line 115 to handle large Q case
235  */
236  if(q < 15.0) goto S95;
237 /*
238  * JJV Here Q is large enough that Q = log(exp(Q) - 1.0) (for real Q)
239  * JJV so reformulate test at 110 in terms of one EXP, if not too big
240  * JJV 87.49823 is close to the largest real which can be
241  * JJV exponentiated (87.49823 = log(1.0E38))
242  */
243  if((q+e-0.5*t*t) > 87.49823) goto S115;
244  if(c*fabs(u) > exp(q+e-0.5*t*t)) goto S70;
245  goto S115;
246 S95:
247  w = exp(q)-1.0;
248  goto S110;
249 S100:
250  w = ((((e5*q+e4)*q+e3)*q+e2)*q+e1)*q;
251 S110:
252 /*
253  IF T IS REJECTED, SAMPLE AGAIN AT STEP 8
254 */
255  if(c*fabs(u) > w*exp(e-0.5*t*t)) goto S70;
256 S115:
257  x = s+0.5*t;
258  sgamma = x*x;
259  return sgamma;
260 S120:
261 /*
262  ALTERNATE METHOD FOR PARAMETERS A BELOW 1 (.3678794=EXP(-1.))
263 
264  JJV changed B to B0 (which was added to declarations for this)
265  JJV in 120 to END to fix rare and subtle bug.
266  JJV Line: 'aa = 0.0' was removed (unnecessary, wasteful).
267  JJV Reasons: the state of AA only serves to tell the A >= 1.0
268  JJV case if certain A-dependent constants need to be recalculated.
269  JJV The A < 1.0 case (here) no longer changes any of these, and
270  JJV the recalculation of B (which used to change with an
271  JJV A < 1.0 call) is governed by the state of AAA anyway.
272  aa = 0.0;
273 */
274  b0 = 1.0+0.3678794*a;
275 S130:
276  p = b0*rng.better_rand();
277  // p = b0*ranf();
278  if(p >= 1.0) goto S140;
279  sgamma = exp(log(p)/ a);
280  if(expdev(rng) < sgamma) goto S130;
281  return sgamma;
282 S140:
283  sgamma = -log((b0-p)/ a);
284  if(expdev(rng) < (1.0-a)*log(sgamma)) goto S130;
285  return sgamma;
286 }
287 
292 double gasdev(const random_number_generator& _rng)
293 {
295  double fac,rsq,v1,v2;
296 
297  do
298  {
299  v1=2.0* rng.better_rand() -1.0;
300  v2=2.0*rng.better_rand()-1.0;
301  rsq=v1*v1+v2*v2;
302  } while (rsq >= 1.0 || rsq == 0.0);
303  fac=sqrt(-2.0*log(rsq)/rsq);
304  return v1*fac;
305 }
306 
311 double expdev(const random_number_generator& _rng)
312 {
314  double dum;
315 
316  do
317  dum=rng.better_rand();
318  while (dum == 0.0);
319  return -log(dum);
320 }
#define x
static double fsign(double num, double sign)
Transfers sign of argument sign to argument num.
Definition: drangam.cpp:33
df1_two_variable fabs(const df1_two_variable &x)
Definition: df12fun.cpp:891
double better_rand()
Random number generator.
Definition: rngen.cpp:134
double expdev(const random_number_generator &_rng)
Description not yet available.
Definition: drangam.cpp:311
Description not yet available.
Definition: fvar.hpp:7951
d3_array sqrt(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2c.cpp:11
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
double sgamma(double a, const random_number_generator &_rng)
Description not yet available.
Definition: drangam.cpp:44
d3_array exp(const d3_array &arr3)
Returns d3_array results with computed exp from elements in arr3.
Definition: d3arr2a.cpp:28
double gasdev(const random_number_generator &_rng)
Description not yet available.
Definition: drangam.cpp:292
#define w
double sign(const double x)
The sign of a number.
Definition: gaussher.cpp:25
d3_array log(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2a.cpp:13