7 Type calc_logZ(Type loglambda, Type nu){
8 using atomic::tiny_ad::isfinite;
9 bool ok = (0 < nu && isfinite(loglambda) && isfinite(nu) );
15 Type logmu = loglambda / nu;
20 nu * mu - 0.5 * log(nu) -
21 ((nu - 1) / 2) * log(mu) -
22 ((nu - 1) / 2) * log(2 * M_PI);
23 }
else if ( (mu > 100) && (mu * nu > 200) && (nu < 2 * mu) ) {
27 Type H1 = lgamma<2>(jhat + 1.);
28 Type fhat1 = jhat * logmu -
lgamma(jhat + 1.);
29 Type logL1 = log(sqrt(2. * M_PI)) - .5 * log(H1) + fhat1;
31 Type err1 = logL1 - mu;
34 Type fhat = nu * fhat1;
35 Type logL = log(sqrt(2. * M_PI)) - .5 * log(H) + fhat;
45 double reltol = 1e-12;
48 int index_mode = floor(mu);
49 Type logT_mode = index_mode * loglambda - nu *
lgamma(index_mode + 1.);
53 for(i = 1; i<iter_max; i++) {
54 index = index_mode - i;
56 dlogT = loglambda - nu * log( (
double) index + 1);
59 if ( logT - logZ < log(reltol) )
break;
63 for(i = 1; i<iter_max; i++) {
64 index = index_mode + i;
65 dlogT = loglambda - nu * log( (
double) index);
68 if ( logT - logZ < log(reltol) )
break;
75 Type logT_tail = logT + index * dlogT -
logspace_sub(Type(0), dlogT);
83 Type calc_mean(Type loglambda, Type nu){
84 typedef atomic::tiny_ad::variable<1, 1, Type> ADType;
85 ADType loglambda_ (loglambda, 0);
86 ADType ans = calc_logZ<ADType>(loglambda_, nu);
87 return ans.getDeriv()[0];
93 Type calc_loglambda(Type logmean, Type nu) {
94 using atomic::tiny_ad::isfinite;
95 bool ok = (0 < nu && isfinite(logmean) && isfinite(nu) );
97 int iter_max = 100;
double reltol = 1e-9, abstol = 1e-12;
98 typedef atomic::tiny_ad::variable<1, 1, Type> ADType;
99 ADType x = nu * logmean;
101 ADType f_previous = INFINITY;
103 for ( ; i < iter_max ; i++ ) {
105 ADType y = calc_mean<ADType>(x, nu);
106 if( ! isfinite(y) ) {
107 if (i==0)
return NAN;
114 log(y) - ADType( logmean ) :
115 y - ADType( exp(logmean) ) );
116 if( fabs(f) > fabs(f_previous) ) {
122 step = ( f.deriv[0] != 0 ?
123 -f.value / f.deriv[0] : 0 );
124 x += step; f_previous = f;
125 if(fabs(step) <= reltol * fabs(x))
127 if(fabs(step) <= abstol)
131 Rf_warning(
"calc_loglambda: Maximum number of iterations exceeded");
136 double Rf_lgammafn(
double);
137 double Rf_psigamma(
double,
double);
138 double Rf_expm1(
double);
139 double Rf_pgeom(
double x,
double p,
int lower_tail,
int log_p);
140 double Rf_runif(
double a,
double b);
141 double Rf_qgeom(
double p,
double prob,
int lower_tail,
int log_p);
142 double Rf_rgeom(
double p);
155 double simulate(
double loglambda,
double nu);
157 double simulate(
double loglambda,
double nu) {
158 #define logf_target(x) ( nu * ( x * logmu - Rf_lgammafn(x+1) ) ) 159 #define logf_propose(x) ( x < jhat ? logf0(x) : logf1(x) ) 160 #define logf0(x) ( v0 + slope0 * (x - j0) ) 161 #define logf1(x) ( v1 + slope1 * (x - j1) ) 162 double logmu = loglambda / nu;
163 double mu = exp(logmu);
164 double jhat = (mu > 1 ? mu - .5 : 1);
165 double sd = 1. / sqrt(nu * Rf_psigamma(jhat+1, 1));
166 double j0 = (mu > 1 ? jhat - fmin(sd, .5 * jhat) : 0);
167 double j1 = jhat + sd;
168 double slope0 = (mu > 1 ? nu * ( logmu - Rf_psigamma(j0+1, 0) ) : 0);
169 double slope1 = nu * ( logmu - Rf_psigamma(j1+1, 0) );
170 double v0 = nu * ( j0 * logmu - Rf_lgammafn(j0+1) );
171 double v1 = nu * ( j1 * logmu - Rf_lgammafn(j1+1) );
173 double prob0 = (mu > 1 ? -expm1(-slope0) : 1);
174 double prob1 = -expm1(slope1);
175 double mu0 = (mu > 1 ? floor(jhat) : 0);
176 double mu1 = mu0 + 1;
177 double p0 = Rf_pgeom(mu0, prob0, 1, 0);
178 double w0 = p0 * exp(logf0(mu0)) / prob0;
179 double w1 = 1 * exp(logf1(mu1)) / prob1;
184 for(
int i=0; i<1e6; i++) {
185 St += exp(logf_target(i));
186 Sp += exp(logf_propose(i));
188 double paccept = St / Sp;
191 int i=0, iter_max = 1e4;
192 for ( ; i < iter_max; i++ ) {
194 if( Rf_runif(0, 1) < w0 / (w0 + w1) ) {
195 samp = mu0 - Rf_qgeom(Rf_runif(0, p0), prob0, 1, 0);
197 samp = mu1 + Rf_rgeom(prob1);
199 double paccept = exp(logf_target(samp) - logf_propose(samp));
202 Rf_warning(
"compois sampler failed (probably overflow: paccept = %f)", paccept);
205 if( Rf_runif(0, 1) < paccept )
break;
209 Rf_warning(
"compois sampler failed (iteration limit exceeded)");
212 Rf_warning(
"compois sampler returned NaN for mu=%f nu=%f", mu, nu);
Type lgamma(Type x)
Logarithm of gamma function (following R argument convention).
Type logspace_add(Type logx, Type logy)
Addition in log-space.
Type logspace_sub(Type logx, Type logy)
Subtraction in log-space.