Stan  1.1
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
internal_math.hpp
Go to the documentation of this file.
1 #ifndef __STAN__PROB__INTERNAL_MATH_HPP__
2 #define __STAN__PROB__INTERNAL_MATH_HPP__
3 
4 #include <math.h>
5 #include <boost/math/special_functions/gamma.hpp>
6 #include <boost/math/special_functions/beta.hpp>
7 
8 namespace stan {
9 
10  namespace math {
11 
12 
13  double F32(double a, double b, double c, double d, double e, double z)
14  {
15 
16  double F = 1;
17 
18  double tOld = 1;
19  double tNew = 0;
20 
21  double logT = 0;
22 
23  double logZ = std::log(z);
24 
25  for(int k = 0; k < 500; ++k)
26  {
27 
28  double p = (a + k) * (b + k) * (c + k) / ( (d + k) * (e + k) * (k + 1) );
29 
30  // If a, b, or c is a negative integer then the series terminates
31  // after a finite number of interations
32  if(p == 0) break;
33 
34  logT += (p > 0 ? 1 : -1) * std::log(fabs(p)) + logZ;
35 
36  tNew = std::exp(logT);
37 
38  F += tNew;
39 
40  tOld = tNew;
41 
42  }
43 
44  return F;
45 
46  }
47 
48  void gradF32(double* g, double a, double b, double c, double d, double e, double z)
49  {
50 
51  double gOld[6];
52 
53  for(double *p = g; p != g + 6; ++p) *p = 0;
54  for(double *p = gOld; p != gOld + 6; ++p) *p = 0;
55 
56  double tOld = 1;
57  double tNew = 0;
58 
59  double logT = 0;
60 
61  double logZ = std::log(z);
62 
63  for(int k = 0; k < 500; ++k)
64  {
65 
66  double C = (a + k) / (d + k);
67  C *= (b + k) / (e + k);
68  C *= (c + k) / (1 + k);
69 
70  // If a, b, or c is a negative integer then the series terminates
71  // after a finite number of interations
72  if(C == 0) break;
73 
74  logT += (C > 0 ? 1 : -1) * std::log(fabs(C)) + logZ;
75 
76  tNew = std::exp(logT);
77 
78  gOld[0] = tNew * (gOld[0] / tOld + 1.0 / (a + k) );
79  gOld[1] = tNew * (gOld[1] / tOld + 1.0 / (b + k) );
80  gOld[2] = tNew * (gOld[2] / tOld + 1.0 / (c + k) );
81 
82  gOld[3] = tNew * (gOld[3] / tOld - 1.0 / (d + k) );
83  gOld[4] = tNew * (gOld[4] / tOld - 1.0 / (e + k) );
84 
85  gOld[5] = tNew * ( gOld[5] / tOld + 1.0 / z );
86 
87  for(int i = 0; i < 6; ++i) g[i] += gOld[i];
88 
89  tOld = tNew;
90 
91  }
92 
93  }
94 
95  // Gradient of the hypergeometric function 2F1(a, b | c | z) with respect to a and c
96  void grad2F1(double& gradA, double& gradC, double a, double b, double c, double z, double precision = 1e-6)
97  {
98 
99  gradA = 0;
100  gradC = 0;
101 
102  double gradAold = 0;
103  double gradCold = 0;
104 
105  int k = 0;
106  double tOld = 1.0;
107  double tNew = (a * b) / c;
108 
109  while(fabs(tNew) > precision)
110  {
111 
112  gradAold = tNew * (gradAold / tOld + 1.0 / (a + k) );
113  gradCold = tNew * (gradCold / tOld - 1.0 / (c + k) );
114 
115  gradA += gradAold;
116  gradC += gradCold;
117 
118  ++k;
119 
120  tNew = ( (a + k) / (c + k) ) * ( (b + k) / (k + 1) ) * z * tOld;
121 
122  if(tNew == 0) break;
123 
124  }
125 
126  }
127 
128  // Gradient of the incomplete beta function beta(a, b, z)
129  // with respect to the first two arguments, using the
130  // equivalence to a hypergeometric function.
131  // See http://dlmf.nist.gov/8.17#ii
132  void gradIncBeta(double& g1, double& g2, double a, double b, double z)
133  {
134 
135  double c1 = std::log(z);
136  double c2 = std::log(1 - z);
137  double c3 = boost::math::beta(a, b, z);
138 
139  double C = std::exp( a * c1 + b * c2 ) / a;
140 
141  double dF1 = 0;
142  double dF2 = 0;
143 
144  grad2F1(dF1, dF2, a + b, 1, a + 1, z);
145 
146  g1 = (c1 - 1.0 / a) * c3 + C * (dF1 + dF2);
147  g2 = c2 * c3 + C * dF1;
148 
149  }
150 
151  // Gradient of the regularized incomplete beta function ibeta(a, b, z)
152  void gradRegIncBeta(double& g1, double& g2, double a, double b, double z,
153  double digammaA, double digammaB, double digammaSum, double betaAB)
154  {
155 
156  double dBda = 0;
157  double dBdb = 0;
158 
159  gradIncBeta(dBda, dBdb, a, b, z);
160 
161  double b1 = boost::math::beta(a, b, z);
162 
163  g1 = ( dBda - b1 * (digammaA - digammaSum) ) / betaAB;
164  g2 = ( dBdb - b1 * (digammaB - digammaSum) ) / betaAB;
165 
166  }
167 
168  // Gradient of the regularized incomplete gamma functions igamma(a, g)
169  double gradRegIncGamma(double a, double z, double g, double dig, double precision = 1e-6)
170  {
171 
172  using boost::math::gamma_p;
173 
174  double S = 0;
175  double s = 1;
176  double l = std::log(z);
177 
178  int k = 0;
179  double delta = s / (a * a);
180 
181  while (fabs(delta) > precision)
182  {
183  S += delta;
184  ++k;
185  s *= - z / k;
186  delta = s / ((k + a) * (k + a));
187  }
188 
189  // Precomputed values
190  // dig -> digamma(a)
191  // g -> g(a)
192  return gamma_p(a, z) * ( dig - l ) + std::exp( a * l ) * S / g;
193 
194  }
195 
196  }
197 
198 }
199 
200 #endif

     [ Stan Home Page ] © 2011–2013, Stan Development Team.