From b64f9fe088c534a4b405921fafb90d248384ae6f Mon Sep 17 00:00:00 2001 From: Jacob Smith <jake@laptop.(none)> Date: Mon, 19 Apr 2010 04:03:25 -0400 Subject: [PATCH] tao updates --- CFiles/rand.c | 85 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 26 deletions(-) diff --git a/CFiles/rand.c b/CFiles/rand.c index 1c7306a..03d08db 100644 --- a/CFiles/rand.c +++ b/CFiles/rand.c @@ -143,12 +143,15 @@ double gaussrnd(void) When a<1.0, Johnk's generator (Devroye, page 418). When a>1.0, a rejection method or Best's algorithm (Devroye, page 410). - A general gamma variate can be obtained as follows. Let z=b*x. Then, + A general gamma variate can be obtained as follows. Let z=x/b. Then, z is drawn from a general gamma distribution whose density is - 1 - p(z) = -------------- z^(a-1) exp(-z/b). - gamma(a) b^a + b^a + p(z) = ---------- z^(a-1) exp(-b*z). + gamma(a) + + This density is the same as Matlab where b is an inverse scale parameter (same + as Gelman's book but different from Matlab). Uses algorithm translated by Iskander Karibzhanov from the Matlab function gamrnd.m, which follows Johnk's generator in Devroye ("Non-Uniform Random @@ -158,16 +161,14 @@ double gammrnd(double a) { double b = a-1.0, u, v, w, x, y, z; - if (a <= 0.0) { + if (a <= 0.0) + { //** When used with a C MEX-file for MATLAB. printf("\nThe input argument x for gammrnd(x) in rand.c must be a positive double."); - #ifdef WIN_MATLABAPI - mexErrMsgTxt("Error! ???."); // This terminates the entire Matlab program. - #else - //@ When used entirely with C. - getchar(); - exit(1); // This exits the entire C program. - #endif + + //@ When used entirely with C. + getchar(); + exit(1); // This exits the entire C program. } if (a==1.0) return -log(unirnd()); @@ -198,6 +199,24 @@ double gammrnd(double a) { } +/* + Returns a random draw from beta(a,b). The density function is + + gamma(a+b) + p(x) = ------------------- x^(a-1) (1-x)^(b-1). + gamma(a)*gamma(b) + + where a>0, b>0 and gamma denotes the gamma function, which is defined as + the integral with respect to t from 0 to infinity of exp(-t)*t^(z-1). +*/ +double betarnd(double a, double b) +{ + double xa=2.0*gammrnd(a), + xb=2.0*gammrnd(b); + + return (xa/(xa+xb)); +} + /* Returns the integral from -infinity to x of 1/sqrt(2*PI)*exp(-y^2/2). @@ -276,12 +295,19 @@ double StandardNormalDouble(void) { double x; imsls_d_random_normal(1, IMSLS_RETURN_USER, &x, 0); return x; - #else - // CASE2_RANDOMNUMBERGENERATOR Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. + #else CASE2_RANDOMNUMBERGENERATOR //Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. return gaussrnd(); #endif } +double NormalDouble(double m, double s) +{ + //m: mean; + //s: standard deviation. + + return (m+s*StandardNormalDouble()); +} + double LogNormalDouble(double mean, double std) { //Return x where log(x) is normal(mean, std^2). @@ -290,8 +316,7 @@ double LogNormalDouble(double mean, double std) double x; imsls_d_random_lognormal(1, mean, std, IMSLS_RETURN_USER, &x, 0); return x; - #else - // CASE2_RANDOMNUMBERGENERATOR Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. + #else CASE2_RANDOMNUMBERGENERATOR //Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. fn_DisplayError(".../rand.c/LogNormalDouble(): NO defaul available for log normal draws"); return (0); #endif @@ -299,20 +324,30 @@ double LogNormalDouble(double mean, double std) double GammaDouble(const double a, const double b) { - //The probability density of x is of the form: ( x^(a-1) exp(-x/b) )/( Gamma(a) * b^a ). - //The same form as in the MATLAB (not Gelman et al's) notation. + //The probability density of x is of the form: ( x^(a-1) exp(-bx) )/( b^a /Gamma(a) ). + //The same form as in the Gelman et al's (not MATLAB) notation. #ifdef IMSL_RANDOMNUMBERGENERATOR // IMSL optimization routines. //The GFSR algorithm to generate random numbers. double x; imsls_d_random_gamma(1, a, IMSLS_RETURN_USER, &x, 0); - if (b != 1.0) x *= b; + if (b != 1.0) x /= b; return x; - #else - // CASE2_RANDOMNUMBERGENERATOR Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. - return ( (b==1.0) ? gammrnd(a) : b*gammrnd(a) ); + #else CASE2_RANDOMNUMBERGENERATOR //Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. + return ( (b==1.0) ? gammrnd(a) : gammrnd(a)/b ); #endif } +double InverseGammaDouble(const double a, const double b) +{ + //p(x) = ( b^a/Gamma(a) ) x^(-a-1) exp(-b/x) for a>0 and b>0. + // where a is shape and b is scale parameter. + //E(x) = b/(a-1) for a>1; var(x) = b^2/( (a-1)^2*(a-2) ) for a>2; + //Noninformative distribution: a,b -> 0. + //How to draw: (1) draw z from Gamma(a,b); (2) let x=1/z. + + return (1.0/GammaDouble(a,b)); +} + void UniformVector(TSdvector *x_dv) { @@ -419,8 +454,7 @@ void GammaMatrix(TSdmatrix *X_dm, TSdmatrix *A_dm, TSdmatrix *B_dm) { } X_dm->flag = M_GE; - #else - //CASE2_RANDOMNUMBERGENERATOR Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. + #else CASE2_RANDOMNUMBERGENERATOR //Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. int _i, nels, nrows, ncols; double *X, *A, *B; @@ -456,8 +490,7 @@ double ChisquareDouble(const double v) { double x; imsls_d_random_chi_squared(1, v, IMSLS_RETURN_USER, &x, 0); return x; - #else - // CASE2_RANDOMNUMBERGENERATOR Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. + #else CASE2_RANDOMNUMBERGENERATOR //Imported from the C recipe book -- Case 2 and my own (Iskander) code for generating a gamma distribution. return ( 2.0*gammrnd(0.5*v) ); #endif } -- GitLab