// $Id: betaUtilities.cpp 962 2006-11-07 15:13:34Z privmane $ #include "definitions.h" #include "betaUtilities.h" #include "gammaUtilities.h" #include "logFile.h" #include "errorMsg.h" #include /****************************** Computes the inverse of the beta CDF: given a prob. value, calculates the x for which the integral over 0 to x of beta CDF = prob. Adapted from: 1. Majumder and Bhattacharjee (1973) App. Stat. 22(3) 411-414 and the corrections: 2. Cran et al. (1977) App. Stat. 26(1) 111-114 3. Berry et al. (1990) App. Stat. 39(2) 309-310 and another adaptation made in the code of Yang (tools.c) ****************************/ MDOUBLE inverseCDFBeta(MDOUBLE a, MDOUBLE b, MDOUBLE prob){ if(a<0 || b<0 || prob<0 || prob>1) { errorMsg::reportError("error in inverseCDFBeta,illegal parameter"); } if (prob == 0 || prob == 1) return prob; int maxIter=100; MDOUBLE epsilonLow=1e-300; MDOUBLE fpu=3e-308; /****** changing the tail direction (prob=1-prob)*/ bool tail=false; MDOUBLE probA=prob; if (prob > 0.5) { prob = 1.0 - prob; tail = true; MDOUBLE tmp=a; a=b; b=tmp; } MDOUBLE lnBetaVal=betaln(a,b); MDOUBLE x; /****** calculating chi square evaluator */ MDOUBLE r = sqrt(-log(prob * prob)); MDOUBLE y = r - (2.30753+0.27061*r)/(1.+ (0.99229+0.04481*r) * r); MDOUBLE chiSquare = 1.0/(9.0 * b); chiSquare = b*2 * pow(1.0 - chiSquare + y * sqrt(chiSquare), 3.0); // MDOUBLE chiSquare2=gammq(b,prob/2.0); //chi square valued of prob with 2q df MDOUBLE T=(4.0*a+2.0*b-2)/chiSquare; /****** initializing x0 */ if (a > 1.0 && b > 1.0) { r = (y * y - 3.) / 6.; MDOUBLE s = 1. / (a*2. - 1.); MDOUBLE t = 1. / (b*2. - 1.); MDOUBLE h = 2. / (s + t); MDOUBLE w = y * sqrt(h + r) / h - (t - s) * (r + 5./6. - 2./(3.*h)); x = a / (a + b * exp(w + w)); } else { if (chiSquare<0){ x=exp((log(b*(1-prob))+lnBetaVal)/b); } else if (T<1){ x=exp((log(prob*a)+lnBetaVal)/a); } else { x=(T-1.0)/(T+1.0); } } if(x<=fpu || x>=1-2.22e-16) x=(prob+0.5)/2; // 0epsilonLow?eps:epsilonLow); for (int i=0; ifpu?fabs(adj):fpu); MDOUBLE g = 1; for (int j=0; j= 0. && newX <= 1.) { if (prev <= eps || fabs(y) <= eps) return(tail?1.0-x:x);; if (newX != 0. && newX != 1.0) break; } } g /= 3.; } if (fabs(newX-x)1) { LOG(5,<<"Error in function incompleteBeta : invalid x = "< ITMAX) LOG(5,<<"Error in function betacf : alpha || beta big ||MAXIT small"<