Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pnorm and Dnorm on log scale #25

Open
adamlauretig opened this issue Jun 21, 2018 · 0 comments
Open

Pnorm and Dnorm on log scale #25

adamlauretig opened this issue Jun 21, 2018 · 0 comments

Comments

@adamlauretig
Copy link

Thanks for the package, I've found it's really useful!

I ran into overflow/underflow problems, and was able to re-implement them on the log scale, which fixed this problem. I thought I'd share it, in case this is a problem others have run into:

I did not do this using the truncated above and below, only for the separate ones, since those were the only two I'm using. Here's the c++ code:

`
using namespace Rcpp ;

/// No Truncation
double e0 (const double mean,
const double sd,
const double low,
const double high
) {
return(mean) ;
}

/// Truncated Below and Above
double e1 (const double mean,
const double sd,
const double low,
const double high
) {
double s_low = (low - mean) / sd ;
double s_high = (high - mean) / sd ;

double q1 = R::dnorm(s_low, 0.0, 1.0, false) ;
double q2 = R::dnorm(s_high, 0.0, 1.0, false) ;
double q3 = R::pnorm(s_low, 0.0, 1.0, true, false) ;
double q4 = R::pnorm(s_high, 0.0, 1.0, true, false) ;

return(mean + sd * ((q1 - q2) / (q4 - q3))) ;

}

/// Truncated Below
double e2 (const double mean,
const double sd,
const double low
) {
double s_low = (low - mean) / sd ;

double q1 = R::dnorm(s_low, 0.0, 1.0, true) ;
double q3 = R::pnorm(s_low, 0.0, 1.0, true, true) ;

return(mean + sd * exp((q1) - (1 - q3))) ;

}

/// Truncated Above
double e3 (const double mean,
const double sd,
const double high
) {
double s_high = (high - mean) / sd ;

double q2 = R::dnorm(s_high, 0.0, 1.0, false) ;
double q4 = R::pnorm(s_high, 0.0, 1.0, true, false) ;

return( mean - sd * exp(q2 - q4)) ;

}

/// Main Function
double etn2(const double mean,
const double sd,
const double low,
const double high
) {
// Init Useful Values
double out = NA_REAL ;
//

if (low == R_NegInf &&
    high == R_PosInf
    ) {
  // No Truncation
    out = e0(mean, sd, low, high) ;
} else if (low == R_NegInf) {
    // Truncated Above
    out = e3(mean, sd, high) ;
} else if (high == R_PosInf) {
    // Truncation Below
    out = e2(mean, sd, low) ;
} else {
    // Truncation Above and Below
    out = e1(mean, sd, low, high) ;
}
// Check if Mirror Problem is Numerically Better
if (!std::isfinite(out)) {
    return(-e1(-mean, sd, -high, -low)) ;
}
//
return(out) ;

}`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant