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

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