void rtnorm(double *x, double *left, double* right, double *mu, double *sig, int *num) { // TODO: NEED TO DEAL WITH Inf/NA/NaN RNG r; #ifdef USE_R GetRNGstate(); #endif for(int i=0; i < *num; ++i){ #ifdef USE_R if (i%SAMPCHECK==0) R_CheckUserInterrupt(); if (ISNAN(left[i]) || ISNAN(right[i]) || ISNAN(mu[i]) || ISNAN(sig[i])) x[i] = R_NaN; if (ISNA(left[i]) || ISNA(right[i]) || ISNA(mu[i]) || ISNA(sig[i])) x[i] = NA_REAL; #endif #ifdef USE_R if (left[i] != R_NegInf && right[i] != R_PosInf) { x[i] = r.tnorm(left[i], right[i], mu[i], sig[i]); } else if (left[i] != R_NegInf && right[i] == R_PosInf) { x[i] = r.tnorm(left[i], mu[i], sig[i]); } else if (left[i] == R_NegInf && right[i] != R_PosInf) { x[i] = -1.0 * r.tnorm(-1.0 * right[i], -1.0 * mu[i], sig[i]); } else if (left[i] == R_NegInf && right[i] == R_PosInf) { x[i] = r.norm(mu[i], sig[i]); } else { x[i] = R_NaN; } #else // TODO: Need to adjust so that we deal with +/- inf. if (MYFINITE(left[i]) && MYFINITE(right[i])) x[i] = r.tnorm(left[i], right[i], mu[i], sig[i]); else if (MYFINITE(left[i])) x[i] = r.tnorm(left[i], mu[i], sig[i]); else if (MYFINITE(right[i])) x[i] = -1.0 * r.tnorm(-1.0 * right[i], -1.0 * mu[i], sig[i]); else x[i] = r.norm(mu[i], sig[i]); #endif } #ifdef USE_R PutRNGstate(); #endif }
inline void Logit::draw_beta(MF beta, MF w, RNG& r) { // tXRtOm = tX sqrt(Om) Matrix tXRtOm(P, N); for(unsigned int j=0; j<tX.cols(); j++) for(unsigned int i=0; i<tX.rows(); i++) tXRtOm(i,j) = tX(i,j) * sqrt(w(j)); // PP = X' Om X + P0. PP = P0; syrk(PP, tXRtOm, 'N', 1.0, 1.0); // PP = U'U. // U'U mP = bP --> U' y = bP; U mP = y; // ep = U z // dr = mP + z. Matrix U; chol(U, PP, 'U'); r.norm(beta, 1.0); Matrix mP(bP); trsm(U, mP, 'U', 'L', 'T'); // U' y = bP trsm(U, mP, 'U', 'L', 'N'); // U mP = y trsm(U, beta, 'U', 'L', 'N'); // U z = ep. for(uint i=0; i<P; i++) beta(i) += mP(i); }
double PolyaGamma::rtigauss(double Z, RNG& r) { Z = fabs(Z); double t = __TRUNC; double X = t + 1.0; if (__TRUNC_RECIP > Z) { // mu > t double alpha = 0.0; while (r.unif() > alpha) { // X = t + 1.0; // while (X > t) // X = 1.0 / r.gamma_rate(0.5, 0.5); // Slightly faster to use truncated normal. double E1 = r.expon_rate(1.0); double E2 = r.expon_rate(1.0); while ( E1*E1 > 2 * E2 / t) { E1 = r.expon_rate(1.0); E2 = r.expon_rate(1.0); } X = 1 + E1 * t; X = t / (X * X); alpha = exp(-0.5 * Z*Z * X); } } else { double mu = 1.0 / Z; while (X > t) { double Y = r.norm(1.0); Y *= Y; double half_mu = 0.5 * mu; double mu_Y = mu * Y; X = mu + half_mu * mu_Y - half_mu * sqrt(4 * mu_Y + mu_Y * mu_Y); if (r.unif() > mu / (mu + X)) X = mu*mu / X; } } return X; }
int main(int argc, char** argv) { RNG r; // MatrixXd A(4,1); // Matrix<double, 1, 1> mu; mu(0) = 0.0; // Matrix<double, 1, 1> sig; sig(0) = 1.0; MatrixXd A(4,1); VectorXd v(4); r.norm(A, 1.0); Map<MatrixXd> M(&A(0), 4, 1); fun2(M); fun3(v); cout << "A:\n" << A << endl; return 0; }