namespace my_atomic {
template<class Float>
struct GaussBinomial_t {
typedef Float Scalar;
Float x, n;
Float mu, sd;
Float operator() (Float u) {
Float ans = 0;
ans +=
dnorm(u, Float(0.), Float(1.),
true);
ans += x * log(p) + (n - x) * log(1. - p);
ans = exp(ans);
if (ans == 0) ans = 0;
using atomic::tiny_ad::isfinite;
if (!isfinite(ans)) ans = 0;
return ans;
}
Float marginal() {
Float ans =
if(n > 1) {
using atomic::gamma_utils::gammafn;
ans /= gammafn(n+1) / (gammafn(x+1) * gammafn(n-x+1));
}
return ans;
}
};
template<class Float>
Float eval(Float x, Float n, Float mu, Float sd) {
GaussBinomial_t<Float> f = {x, n, mu, sd};
return f.marginal();
}
TMB_BIND_ATOMIC(func, 0011, eval(x[0], x[1], x[2], x[3]))
template<class Type>
Type GaussBinomial(Type x, Type n, Type mu, Type sd) {
args << x, n, mu, sd, 0;
return my_atomic::func(CppAD::vector<Type>(args))[0];
}
}
template<class Type>
Type objective_function<Type>::operator() ()
{
Type sd = exp(logsd);
Type ans = 0;
Type tiny = 0.0;
for(int i=0; i < x.size(); i++) {
ans -= log( my_atomic::GaussBinomial(x(i), n(i), mu(i), sd) + tiny );
}
return ans;
}