STK++ 1.0
STK_Funct_betaRatio.cpp
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*  Copyright (C) 2004-2007  Serge Iovleff
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU Lesser General Public License as
00006     published by the Free Software Foundation; either version 2 of the
00007     License, or (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU Lesser General Public License for more details.
00013 
00014     You should have received a copy of the GNU Lesser General Public
00015     License along with this program; if not, write to the
00016     Free Software Foundation, Inc.,
00017     59 Temple Place,
00018     Suite 330,
00019     Boston, MA 02111-1307
00020     USA
00021 
00022     Contact : Serge.Iovleff@stkpp.org
00023 */
00024 
00025 /*
00026  * Project:  Analysis
00027  * Purpose:  Implementation of functions around the beta function ratio
00028  * Author:   Serge Iovleff, serge.iovleff@stkpp.org
00029  **/
00030 
00036 #include "../include/STK_Funct_betaRatio.h"
00037 #include "../include/STK_Funct_gammaRatio.h"
00038 #include "../include/STK_ISerie.h"
00039 #include "../include/STK_Algo.h"
00040 #include "../include/STK_Funct_gamma.h"
00041 #include "../include/STK_Funct_util.h"
00042 #include "../include/STK_Funct_raw.h"
00043 
00044 #include "../../Arrays/include/STK_Vector.h"
00045 
00046 namespace STK
00047 {
00048 
00049 namespace Funct
00050 {
00051 
00073 static Real betaRatio_cf( Real const& a
00074                         , Real const& b
00075                         , Real const& x
00076                         , bool lower_tail = true
00077                         , Integer const& iterMax = 1000
00078                         )
00079 {
00080   // Constants
00081   Real sum = a+b, y = (0.5 -x) + 0.5, res;
00082   /* Compute the Function:
00083    *  B(a,b,x,y) = \frac{\Gamma(a+b)}{\Gamma(a) \Gamma(b)} x^{a} (1-x)^{b}
00084    */
00085   Real bt = ( Const::_1_SQRT2PI_*sqrt((a*b)/sum)
00086         * exp( ( gammaLnStirlingError(sum)
00087                 -gammaLnStirlingError(a)
00088                 -gammaLnStirlingError(b)
00089                 )
00090               -(dev0(a, sum*x) + dev0(b, y*sum))
00091               )
00092         );
00093   if (bt == 0.) return lower_tail ? 0. : 1.;
00094 
00095   // initialize b_n
00096   Real bn = (1+a*y-b*x)/(a+1); // b_1
00097   // initialize numerator
00098   Real Nold = 0, Ncur = 1.; // = a_1 = 1
00099   // initialize denominator
00100   Real Dold = 1, Dcur = bn; // = b_1
00101 
00102   // normalize if necessary
00103   if (abs(Dcur) > 4294967296.0)
00104   {
00105     Ncur /= Dcur;
00106     Dold /= Dcur;
00107     Dcur = 1.;
00108   }
00109 
00110   // auxiliary constant variable
00111   const Real cte= (0.5-sum*x)+0.5;
00112   // dn (can be reused)
00113   Real dn = (a*sum*x)/(a+1);
00114   // result
00115   Real cf = 1/Dcur;
00116   // auxiliary variables
00117   Real ap2n = a+2, apn = a+1;
00118   // iterations
00119   for (Integer n=1; /*n<=iterMax*/; n++, apn++, ap2n += 2)
00120   {
00121     // compute auxiliaries variables
00122     Real nx = n*x, cn = n*(b*x-nx)/(ap2n-1);
00123     // compute a_n
00124     Real an = (cn/ap2n)*(dn/(ap2n-2));
00125     // check trivial case)
00126     if (an == 0.) break;
00127     // update d_n
00128     dn = apn*(sum*x+nx)/(ap2n+1);
00129     // compute bn
00130     bn = cte + cn + dn;
00131     // compute numerator and denominator
00132     Real anew = bn * Ncur + an * Nold;
00133     Nold = Ncur;
00134     Ncur = anew;
00135     anew = bn * Dcur + an * Dold;
00136     Dold = Dcur;
00137     Dcur = anew;
00138     // normalize if necessary
00139     if (abs(Dcur) > 4294967296.0)
00140     {
00141       Ncur /= Dcur;
00142       Nold /= Dcur;
00143       Dold /= Dcur;
00144       Dcur = 1.;
00145     }
00146     // normalize if necessary with 2^32
00147     if (abs(Ncur) > 4294967296.0)
00148     {
00149       Ncur /= 4294967296.0;
00150       Nold /= 4294967296.0;
00151       Dold /= 4294967296.0;
00152       Dcur /= 4294967296.0;
00153     }
00154     // test D_n not too small
00155     if (abs(Dcur) != 0)
00156     {
00157       Real cfold = cf;
00158       cf = Ncur/Dcur;
00159       // check cv
00160       if (abs(cf - cfold) < abs(cf)*Arithmetic<Real>::epsilon())
00161       {
00162         res = lower_tail ? bt*cf/a : 1-bt*cf/a;
00163         break;
00164       }
00165     }
00166   }
00167 #ifdef STK_DEBUG
00168   // result
00169   res = lower_tail ? bt*cf/a : 1-bt*cf/a;
00170   if (!Arithmetic<Real>::isFinite(res))
00171   {
00172     std::cout << "in cf : bt= " << bt
00173               << " cf = " << cf
00174               << " a  = " << a
00175               << "lt =  " << lower_tail
00176               << "\n";
00177   }
00178   return res;
00179 #else
00180   return lower_tail ? bt*cf/a : 1-bt*cf/a;
00181 #endif
00182 
00183 }
00184 
00185 /* @ingroup Analysis
00186  *  @brief compute the coefs of the beta Ratio function in
00187  *  its asymptotic expansion.
00188  *
00189  *  Given the n-1 first coefs, compute and return the n-th
00190  *  coefficient. The value is stored back to the Vector. The
00191  *  formula for computing the coefficient is
00192  *  \[
00193  *     a_{n}
00194  *      = \frac{b-1}{(2n+1)!}+\frac{1}{n}
00195  *        \sum_{k=1}^{n-1} \left[
00196  *                          \frac{kb-n}{(2k+1)!} p_{n-k}
00197  *                         \right]
00198  *  \f]
00199  *  @param A vector of dimension 1:(n-1), n>=2, of the coefs
00200  *  @param b second parameter of the beta function
00201  */
00202 //static Real coefs_ae(Real const& b, Vector &A)
00203 //{
00204 //  // get the number of exising coefs
00205 //  Integer n = A.size();
00206 //  // initialize the sum
00207 //  Real sum = 0.0;
00208 //  // update sum
00209 //  for (Integer k=1; k<n; k++)
00210 //  {
00211 //    sum += (k*b/n-1)*A[n-k]/(factorial(2*k+1));
00212 //  }
00213 //  // compute result
00214 //  sum += (b-1)/factorial(2*n+1);
00215 //  // save it in A
00216 //  A.push_back(sum);
00217 //  // and return it
00218 //  return sum;
00219 //}
00220 
00221 #define d1(z) (0.5)
00222 #define d2(z) (z/8. - 1./20.)
00223 #define d3(z) (z*(z/48.-1./40.)+1./105.)
00224 #define d4(z) (z*(z*(z/384.-1./160.)+101./16800.)-3./1400.)
00225 #define d5(z) (z*(z*(z*(z/3840.-1./960.)+61./33600.)-13./8400.) \
00226               +1./1925.)
00227 #define d6(z) (z*(z*(z*(z*(z/46080.-1./7680.)+143./403200.) \
00228               -59./112000.)+7999./19404000.)-691./5255250.)
00229 #define d7(z) (z*(z*(z*(z*(z*(z/645120.-1./76800.)+41./806400.) \
00230               -11./96000.)+5941./38808000.)-2357./21021000.)+6./175175.)
00231 #define d8(z) (z*(z*(z*(z*(z*(z*(z/10321920.-1./921600.)+37./6451200.) \
00232               -73./4032000.)+224137./6209280000.)-449747./10090080000.) \
00233               +52037./1681680000.)-10851./1191190000.)
00234 
00235 
00249 static inline Real betaRatio_ae( Real const& a
00250                                , Real const& b
00251                                , Real const& x
00252                                , bool xm1
00253                                , bool lower_tail
00254                                )
00255 {
00256   // Compute b-1
00257   Real bm1 = b-1;
00258   // compute \nu = a+(b-1)/2
00259   Real nu = a+bm1/2.;
00260   // compute D = -\nu*log(x)
00261   Real D = (xm1 ? -log1p(-x) : -log(x)) * nu;
00262   // check trivial case
00263   if (D == 0.) return lower_tail ? 1. : 0.;
00264   if (Arithmetic<Real>::isInfinite(D)) return lower_tail ? 0. : 1.;
00265   // compute 12*\nu^2
00266   nu *= 12*nu;
00267   // variables for the series
00268   Real term = 1.;
00269   Real ak_term = 1.;
00270   Real a_k = 1.;
00271   // numerator and denominator
00272   Real den = term;
00273   Real num = 0.;
00274   // update term
00275   term *= bm1;
00276   // Generalized bernouilli coefs
00277   // coef 1 (d_1 = 1/2)
00278   term *= (b)*(b+1)/nu;
00279   Real coef = term/2; // d_1 = 1/2
00280   den += coef;
00281   a_k += (ak_term *= D/(b+1));
00282   num += coef * a_k;
00283   // coef 2
00284   term *= (b+2)*(b+3)/nu;
00285   coef = d2(bm1)*term;
00286   den += coef;
00287   a_k += (ak_term *= D/(b+2));
00288   a_k += (ak_term *= D/(b+3));
00289   num += coef * a_k;
00290   // coef 3
00291   term *= (b+4)*(b+5)/nu;
00292   coef = d3(bm1)*term;
00293   den += coef;
00294   a_k += (ak_term *= D/(b+4));
00295   a_k += (ak_term *= D/(b+5));
00296   num += coef * a_k;
00297   // coef 4
00298   term *= (b+6)*(b+7)/nu;
00299   coef = d4(bm1)*term;
00300   den += coef;
00301   a_k += (ak_term *= D/(b+6));
00302   a_k += (ak_term *= D/(b+7));
00303   num += coef * a_k;
00304   // coef 5
00305   term *= (b+8)*(b+9)/nu;
00306   coef = d5(bm1)*term;
00307   den += coef;
00308   a_k += (ak_term *= D/(b+8));
00309   a_k += (ak_term *= D/(b+9));
00310   num += coef * a_k;
00311   // coef 6
00312   term *= (b+10)*(b+11)/nu;
00313   coef = d6(bm1)*term;
00314   den += coef;
00315   a_k += (ak_term *= D/(b+10));
00316   a_k += (ak_term *= D/(b+11));
00317   num += coef * a_k;
00318   // coef 7
00319   term *= (b+12)*(b+13)/nu;
00320   coef = d7(bm1)*term;
00321   den += coef;
00322   a_k += (ak_term *= D/(b+12));
00323   a_k += (ak_term *= D/(b+13));
00324   num += coef * a_k;
00325   // coef 8
00326   term *= (b+14)*(b+15)/nu;
00327   coef = d8(bm1)*term;
00328   den += coef;
00329   a_k += (ak_term *= D/(b+14));
00330   a_k += (ak_term *= D/(b+15));
00331   num += coef * a_k;
00332   // result (P or Q ?)
00333   return lower_tail ? gammaRatioQ(b, D)
00334                     + (num / den) * poisson_pdf_raw(b, D)
00335                     : gammaRatioP(b, D)
00336                     - (num / den) * poisson_pdf_raw(b, D);
00337 }
00338 
00351 static inline Real serie_up( Real const& s
00352                            , Real const& a
00353                            , Real const& x
00354                            , Integer const& n
00355                            )
00356 {
00357   // initilize d0 and sum
00358   Real sum = 1./a;
00359   Real di  = 1./a;
00360   // compute \sum_{i=0}^{n-1} \frac{d_i x^i}{a}
00361   for (Integer i=1; i<n; i++)
00362     sum += (di *= x*(s-1+i)/(a+i));
00363   // return result
00364   return sum;
00365 }
00366 
00380 static inline Real betaRatio_up( Real const& a
00381                                , Real const& b
00382                                , Real const& x
00383                                , bool xm1
00384                                , bool lower_tail
00385                                )
00386 {
00387   // number of iterations
00388   Integer n = Integer(a);
00389   // compute residual
00390   Real a0 = a-n;
00391   // zero case
00392   if (!a0) { --n; a0=1.;}
00393   // sum
00394   Real s= a0+b;
00395   // compute x and 1-x
00396   Real x0, y;
00397   if (xm1)
00398   { x0 = (0.5 -x) + 0.5; y =x;}
00399   else
00400   { x0 = x; y = (0.5 -x) + 0.5;}
00401   /* Compute the constant
00402    *  B(a,b,x,y) = \frac{\Gamma(a+b)}{\Gamma(a) \Gamma(b)} x^a (1-x)^b
00403    * using saddle-point expansion
00404    */
00405   Real bt = ( Const::_1_SQRT2PI_*sqrt((a0*b)/s)
00406             * exp( ( gammaLnStirlingError(s)
00407                     -gammaLnStirlingError(a0)
00408                     -gammaLnStirlingError(b)
00409                    )
00410                    -(dev0(a0, s*x0) + dev0(b, y*s))
00411                  )
00412             );
00413   // check trivial case
00414   if (!bt)
00415     return betaRatio_ae(b, a0, x, !xm1, !lower_tail);
00416   // compute serie
00417     bt *= serie_up(s, a0, x0, n);
00418   // general case
00419   return  lower_tail ? betaRatio_ae(b, a0, x, !xm1, !lower_tail) - bt
00420                      : betaRatio_ae(b, a0, x, !xm1, !lower_tail) + bt;
00421 }
00422 
00441 static Real betaRatio_sr( Real const& a
00442                         , Real const& b
00443                         , Real const& x
00444                         , bool lower_tail
00445                         )
00446 {
00447   // Constant
00448   Real sum = a+b;
00449   // compute B(a,b,x,y) = \frac{\Gamma(a+b)}{\Gamma(a) \Gamma(b)} x^{a}
00450   Real bt = ( Const::_1_SQRT2PI_*sqrt((a*b)/sum)
00451             * exp( sum*x
00452                  + ( gammaLnStirlingError(sum)
00453                     -(gammaLnStirlingError(a)+gammaLnStirlingError(b))
00454                    )
00455                  -(dev0(a, sum*x) + dev0(b, sum))
00456                  )
00457             );
00458   // check factor
00459   if (!bt) return lower_tail ? 0. : 1.;
00460   // parameters
00461   Real term, n= 1., c = 1.;
00462   // sum = \sum_{n=1}^\infty (1-b/n) x^n /(a+n)
00463   sum = 0.0;
00464   do
00465   {
00466     sum += (term =  (c *= (1-b/n)*x) / (a+n));
00467     ++n;
00468   }
00469   while (abs(term) > abs(sum) * Arithmetic<Real>::epsilon());
00470   // return result
00471   return lower_tail ? bt*(1/a + sum)
00472                     : (1-bt/a)-(bt*sum);
00473 }
00474 
00486 static Real coefs_odd_se( Real const& std, Real const& qmp, Vector &A)
00487 {
00488   // get the number of exising coefs (should be even)
00489   Integer n = A.size();
00490   Integer t = n/2;
00491   // know case
00492   if (t==1)
00493   {
00494     // compute result
00495     Real sum = (qmp/3+std)*(qmp/3-std)/(4*std);
00496     // save it in A
00497     A.push_back(sum);
00498     // and return it
00499     return sum;
00500   }
00501   // initialize the sums
00502   Real sum, sum1 =0, sum2 =0;
00503   // update sum
00504   for (Integer k=1, k1=2; k<t; k++, k1++)
00505   {
00506     sum1 += A[k1]*A[n+1-k];
00507     sum2 += A[k] *A[n-k];
00508   }
00509   // compute the result
00510   sum = ( ((qmp*A[n] - A[t]*A[t])/2 - sum2)/(t+1)
00511           - sum1- A[t+1]*A[t+1]/2
00512         )/std;
00513   // save it in A
00514   A.push_back(sum);
00515   // and return it
00516   return sum;
00517 }
00518 
00530 static Real coefs_even_se( Real const& std, Real const& qmp, Vector &A)
00531 {
00532   // get the number of exising coefs (should be odd)
00533   Integer n = A.size();
00534   Integer t = n/2;
00535   // know case
00536   if (t==1)
00537   {
00538     // compute result
00539     Real sum = -qmp*(1+A[3]/std)*2/15;
00540     // save it in A
00541     A.push_back(sum);
00542     // and return it
00543     return sum;
00544   }
00545   // initialize the sums
00546   Real sum, sum1 =0, sum2 =0;
00547   // update sum
00548   for (Integer k=1, k1=2; k<=t; k++, k1++)
00549   {
00550     sum1 += A[k1]*A[n+1-k];
00551     sum2 += A[k] *A[n-k];
00552   }
00553   // compute the result
00554   sum = ( (qmp*A[n] - 2*sum2)/(n+2) - sum1)/std;
00555   // save it in A
00556   A.push_back(sum);
00557   // and return it
00558   return sum;
00559 }
00560 
00574 static Real betaRatio_se( Real const& a
00575                         , Real const& b
00576                         , Real const& x
00577                         , bool xm1
00578                         , bool lower_tail
00579                         , Integer const& iterMax = 20
00580                         )
00581 {
00582   // parameters
00583   Real s  = a+b;
00584   Real p  = a/s, q  = b/s;
00585   Real sx = s*x;
00586   Real sy = s-sx;
00587   //Real D  = a*log(x/p)+b*log(y/q);
00588   Real D  = (xm1 ? dev0(a, sy)+dev0(b, sx) : dev0(a, sx)+dev0(b, sy));
00589 
00590   Real z2 = 2 * D;
00591   Real z  = (((x<p)&&!xm1)||((x>q)&&xm1)) ? -sqrt(z2) : sqrt(z2);
00592 
00593   //  Compute normal cdf
00594   Real pnorm = lower_tail ?  normal_cdf_raw( z) : normal_cdf_raw(-z);
00595 #ifdef STK_DEBUG
00596   if (!Arithmetic<Real>::isFinite(pnorm))
00597   {
00598     stk_cout << _T(" a= ") << a
00599              << _T(" b= ") << b
00600              << _T(" x= ") << x
00601              << _T(" p= ") << p
00602              << _T(" q= ") << q
00603              << _T(" D= ") << D
00604              << _T("\n");
00605   }
00606 #endif
00607   //  Compute normal pdf
00608   Real dnorm = Const::_1_SQRT2PI_ * exp(-D);
00609   // check large values of z
00610   if (!dnorm) return pnorm;
00611   // epsilon value for the serie
00612   Real eps = Arithmetic<Real>::epsilon()*pnorm;
00613 
00614   // auxiliary variables
00615   Real std = sqrt(a)*sqrt(b)/s, qmp = q - p;
00616 
00617   // serie coefs
00618   Vector A(2);
00619   A.reserve(iterMax); // reserve enough space
00620   A[1] = std;
00621   A[2] = qmp/3;
00622   // variables for the series
00623   Real odd_term  = 1;
00624   Real even_term = 2/sqrt(s);
00625 
00626   Real sum1_term = z, sum1 = z;
00627   Real sum2_term = 1, sum2 = 1;
00628 
00629   // variables for the numerator and the denominator
00630   Real num = qmp*even_term/3; // = A[2]*even_term;
00631   Real den = std;             // = A[1];
00632 
00633   // compute ratio
00634   Real res = num/den;
00635 
00636   // computation
00637   for (Integer k=1; k<iterMax; k++)
00638   {
00639     // odd_term : (2k+1)!!/(a+b)^k
00640     odd_term *= (2*k+1)/s;
00641     // even_term (2*k)!!/(a+b)^{k+1/2}
00642     even_term *= 2*(k+1)/s;
00643 
00644     // compute a_{2k+1}
00645     Real a_n = coefs_odd_se(std, qmp, A);
00646     // check result
00647     if (Arithmetic<Real>::isFinite(a_n))
00648     {
00649       // denominator \sum_0^k (2j+1)!!a_{2j+1}/(a+b)^j
00650       den += odd_term * a_n;
00651       // num+=\sum_1^k (2k+1)!!a_{2k+1}/(a+b)^k (\sum_1^k z^{2j-1}/(2j-1)!!)
00652       num += odd_term * a_n * sum1;
00653 
00654       // compute a_{2k+2}
00655       a_n = coefs_even_se(std, qmp, A);
00656       // check result
00657       if (Arithmetic<Real>::isFinite(a_n))
00658       {
00659         // update sum2_term = z^{2k}/(2k)!!
00660         // update sum2      = \sum_0^k z^{2j}/(2j)!!
00661         sum2 += (sum2_term *= z2/(2*k));
00662         // num+=\sum_0^k (2k+2)!!a_{2k+2}/(a+b)^k (\sum_1^k z^{2j}/(2j)!!)
00663         num += even_term * a_n * sum2;
00664       }
00665     }
00666     // test cv
00667     Real old_res = res;
00668     res = num/den;
00669     if (abs(old_res - res)*dnorm < eps)
00670     { break;}
00671 
00672     // update sum1_term = z^{2k+1}/(2k+1)!!
00673     // update sum1      = \sum_1^{k+1} z^{2j-1}/(2j-1)!!
00674     sum1 += (sum1_term *= z2/(2*k+1));
00675   }
00676 #ifdef STK_DEBUG
00677   // result
00678   Real result = lower_tail ? pnorm - res * dnorm
00679                            : pnorm + res * dnorm;
00680   if (!Arithmetic<Real>::isFinite(result))
00681   {
00682     std::cout << "Error in betRatio_se\n"
00683               << "pnorm = " << pnorm
00684               << " res = " << res
00685               << " dnorm  = " << dnorm
00686               << "lt =  " << lower_tail
00687               << "\n";
00688   }
00689   return result;
00690 #else
00691   // result
00692     return lower_tail ? pnorm - res * dnorm
00693                       : pnorm + res * dnorm;
00694 #endif
00695 }
00696 
00709 Real betaRatio( Real const& a, Real const& b, Real const& x
00710               , bool lower_tail)
00711 {
00712   // Check if a and x are available
00713   if (  Arithmetic<Real>::isNA(a)
00714      || Arithmetic<Real>::isNA(b)
00715      || Arithmetic<Real>::isNA(x)
00716      ) return Arithmetic<Real>::NA();
00717   // Negative parameter not allowed
00718   if ((a<=0)||(b<=0))
00719     throw domain_error("Funct::betaRatio(a,b,x) "
00720                             "Negative parameter a or b");
00721   // trivial case
00722   if (x<=0) return lower_tail ? 0. : 1.;
00723   if (x>=1) return lower_tail ? 1. : 0.;
00724   // compute 1-x
00725   Real y = (0.5 - x) + 0.5;
00726   // parameters
00727   Real p=a/(a+b);
00728   Real q=b/(a+b);
00729   // small a or b
00730   if (min(a,b)<=1)
00731   {
00732     // case b<=1 and a>=15
00733     if (a>=15)
00734       return betaRatio_ae(a, b, x, false, lower_tail);
00735     // case a<=1 and b>=15
00736     if (b>=15)
00737       return betaRatio_ae(b, a, x, true, !lower_tail);
00738     // ((a<15) and (b<15) and (min(a,b)<=1))
00739     return (x<=0.5) ? betaRatio_sr(a, b, x, lower_tail)
00740                     : betaRatio_sr(b, a, y, !lower_tail);
00741   }
00742   // (1<a<=15) and (1<b<=15)
00743   if (max(a,b)<=15)
00744   {
00745     // general case
00746     return (x < p) ? betaRatio_cf(a, b, x,  lower_tail)
00747                    : betaRatio_cf(b, a, y, !lower_tail);
00748   }
00749   // ((1<a<=15) and (15<b)) or ((15<a) and (1<b<=15))
00750   if (min(a,b)<=15)
00751   {
00752     return (a<=15) ? betaRatio_up(a, b, x, false, lower_tail)
00753                    : betaRatio_up(b, a, x, true, !lower_tail);
00754   }
00755 
00756 //  Real x0, y0, a0, b0, p0, q0;
00757 //  bool flag;
00758 //  if (x>p)
00759 //  { x0=y; y0=x; a0=b; b0=a; flag = !lower_tail; p0=q; q0=p;}
00760 //  else
00761 //  { x0=x; y0=y; a0=a; b0=b; p0=p; q0=q; flag = lower_tail;}
00762 //  // center region for x
00763 //  if ((x0>1.03*p0)&&(y0<0.97*q0))
00764 //    return betaRatio_se(a0-1, b0-1, x0, false, flag);
00765 //  return betaRatio_cf(a0, b0, x0, flag);
00766   // (a>15) and (b>15) and (a<b)
00767   if (a<b)
00768   {
00769     // center region for x in [p , q]
00770     if ((x>=p-0.01*(q-p))&&(y<=q+0.01*(q-p)))
00771       return betaRatio_se(a-1, b-1, x, false, lower_tail);
00772     // extreme values
00773     return (x<p) ? betaRatio_cf(a, b, x,  lower_tail)
00774                  : betaRatio_cf(b, a, y, !lower_tail);
00775   }
00776   // (a>15) and (b>15) and (b<a)
00777   // center region for x in [q, p]
00778   if ((x>=q-0.01*(p-q))&&(y<=p+0.01*(p-q)))
00779     return betaRatio_se(b-1, a-1, x, true, !lower_tail);
00780   // extreme values
00781   return (x<p) ? betaRatio_cf(a, b, x,  lower_tail)
00782                : betaRatio_cf(b, a, y, !lower_tail);
00783 }
00784 
00785 } // namespace Funct
00786 
00787 } // namespace STK