ncbi_math.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:16k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbi_math.c,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:08:20  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: ncbi_math.c,v 1000.2 2004/06/01 18:08:20 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Gish, Kans, Ostell, Schuler
  35.  *
  36.  * Version Creation Date:   10/23/91
  37.  *
  38.  * ==========================================================================
  39.  */
  40. /** @file ncbi_math.c
  41.  * Definitions for portable math library (ported from C Toolkit)
  42.  * @todo FIXME doxygen comments and formatting
  43.  */
  44. static char const rcsid[] = 
  45.     "$Id: ncbi_math.c,v 1000.2 2004/06/01 18:08:20 gouriano Exp $";
  46. #define THIS_MODULE g_corelib
  47. #define THIS_FILE _this_file
  48. #include <algo/blast/core/ncbi_math.h>
  49. #if 0
  50. extern char * g_corelib;
  51. static char * _this_file = __FILE__;
  52. #endif
  53. /*
  54.     BLAST_Expm1(x)
  55.     Return values accurate to approx. 16 digits for the quantity exp(x)-1
  56.     for all x.
  57. */
  58. extern double BLAST_Expm1(double x)
  59. {
  60.   double absx;
  61.   if ((absx = ABS(x)) > .33)
  62.     return exp(x) - 1.;
  63.   if (absx < 1.e-16)
  64.     return x;
  65.   return x * (1. + x *
  66.               (0.5 + x * (1./6. + x *
  67.                           (1./24. + x * (1./120. + x *
  68.                                          (1./720. + x * (1./5040. + x *
  69.                                                          (1./40320. + x * (1./362880. + x *
  70.                                                                            (1./3628800. + x * (1./39916800. + x *
  71.                                                                                                (1./479001600. + x/6227020800.)
  72.                                                                                                ))
  73.                                                                            ))
  74.                                                          ))
  75.                                          ))
  76.                           )));
  77. }
  78. #ifndef DBL_EPSILON
  79. #define DBL_EPSILON 2.2204460492503131e-16
  80. #endif
  81. /*
  82.     Log1p(x)
  83.     Return accurate values for the quantity log(x+1) for all x > -1.
  84. */
  85. extern double BLAST_Log1p(double x)
  86. {
  87. Int4 i;
  88. double sum, y;
  89. if (ABS(x) >= 0.2)
  90. return log(x+1.);
  91. /* Limit the loop to 500 terms. */
  92. for (i=0, sum=0., y=x; i<500 ; ) {
  93. sum += y/++i;
  94. if (ABS(y) < DBL_EPSILON)
  95. break;
  96. y *= x;
  97. sum -= y/++i;
  98. if (y < DBL_EPSILON)
  99. break;
  100. y *= x;
  101. }
  102. return sum;
  103. }
  104. static double LogDerivative(Int4 order, double* u) /* nth derivative of ln(u) */
  105.         /* order is order of the derivative */
  106.         /* u is values of u, u', u", etc. */
  107. {
  108.   Int4          i;
  109.   double   y[LOGDERIV_ORDER_MAX+1];
  110.   double  value, tmp;
  111.   if (order < 0 || order > LOGDERIV_ORDER_MAX) {
  112. InvalidOrder:
  113. /*
  114.     ErrPostEx(SEV_WARNING,E_Math,ERR_NCBIMATH_DOMAIN,"LogDerivative: unsupported derivative order");
  115. */
  116.     /**ERRPOST((CTX_NCBIMATH, ERR_NCBIMATH_DOMAIN, "unsupported derivative order"));**/
  117.     return HUGE_VAL;
  118.   }
  119.   if (order > 0 && u[0] == 0.) {
  120. /*
  121.     ErrPostEx(SEV_WARNING,E_Math,ERR_NCBIMATH_DOMAIN,"LogDerivative: divide by 0");
  122. */
  123.     /**ERRPOST((CTX_NCBIMATH, ERR_NCBIMATH_DOMAIN, "divide by 0"));**/
  124.     return HUGE_VAL;
  125.   }
  126.   for (i = 1; i <= order; i++)
  127.     y[i] = u[i] / u[0];
  128.   switch (order) {
  129.   case 0:
  130.     if (u[0] > 0.)
  131.       value = log(u[0]);
  132.     else {
  133. /*
  134.       ErrPostEx(SEV_WARNING,E_Math,ERR_NCBIMATH_DOMAIN,"LogDerivative: log(x<=0)");
  135. */
  136.       /**ERRPOST((CTX_NCBIMATH, ERR_NCBIMATH_DOMAIN, "log(x<=0)"));**/
  137.       return HUGE_VAL;
  138.     }
  139.     break;
  140.   case 1:
  141.     value = y[1];
  142.     break;
  143.   case 2:
  144.     value = y[2] - y[1] * y[1];
  145.     break;
  146.   case 3:
  147.     value = y[3] - 3. * y[2] * y[1] + 2. * y[1] * y[1] * y[1];
  148.     break;
  149.   case 4:
  150.     value = y[4] - 4. * y[3] * y[1] - 3. * y[2] * y[2]
  151.       + 12. * y[2] * (tmp = y[1] * y[1]);
  152.     value -= 6. * tmp * tmp;
  153.     break;
  154.   default:
  155.     goto InvalidOrder;
  156.   }
  157.   return value;
  158. }
  159. static double _default_gamma_coef [] = {
  160.          4.694580336184385e+04,
  161.         -1.560605207784446e+05,
  162.          2.065049568014106e+05,
  163.         -1.388934775095388e+05,
  164.          5.031796415085709e+04,
  165.         -9.601592329182778e+03,
  166.          8.785855930895250e+02,
  167.         -3.155153906098611e+01,
  168.          2.908143421162229e-01,
  169.         -2.319827630494973e-04,
  170.          1.251639670050933e-10
  171.          };
  172. static int      xgamma_dim = DIM(_default_gamma_coef);
  173. static double
  174. general_lngamma(double x, Int4 order)      /* nth derivative of ln[gamma(x)] */
  175.         /* x is 10-digit accuracy achieved only for 1 <= x */
  176.         /* order is order of the derivative, 0..POLYGAMMA_ORDER_MAX */
  177. {
  178.         Int4            i;
  179.         double     xx, tx;
  180.         double     y[POLYGAMMA_ORDER_MAX+1];
  181.         double    tmp, value;
  182. double    *coef;
  183.         xx = x - 1.;  /* normalize from gamma(x + 1) to xx! */
  184.         tx = xx + xgamma_dim;
  185.         for (i = 0; i <= order; ++i) {
  186.                 tmp = tx;
  187.                 /* sum the least significant terms first */
  188.                 coef = &_default_gamma_coef[xgamma_dim];
  189.                 if (i == 0) {
  190.                         value = *--coef / tmp;
  191.                         while (coef > _default_gamma_coef)
  192.                                 value += *--coef / --tmp;
  193.                 }
  194.                 else {
  195.                         value = *--coef / BLAST_Powi(tmp, i + 1);
  196.                         while (coef > _default_gamma_coef)
  197.                                 value += *--coef / BLAST_Powi(--tmp, i + 1);
  198.                         tmp = BLAST_Factorial(i);
  199.                         value *= (i%2 == 0 ? tmp : -tmp);
  200.                 }
  201.                 y[i] = value;
  202.         }
  203.         ++y[0];
  204.         value = LogDerivative(order, y);
  205.         tmp = tx + 0.5;
  206.         switch (order) {
  207.         case 0:
  208.                 value += ((NCBIMATH_LNPI+NCBIMATH_LN2) / 2.)
  209.                                         + (xx + 0.5) * log(tmp) - tmp;
  210.                 break;
  211.         case 1:
  212.                 value += log(tmp) - xgamma_dim / tmp;
  213.                 break;
  214.         case 2:
  215.                 value += (tmp + xgamma_dim) / (tmp * tmp);
  216.                 break;
  217.         case 3:
  218.                 value -= (1. + 2.*xgamma_dim / tmp) / (tmp * tmp);
  219.                 break;
  220.         case 4:
  221.                 value += 2. * (1. + 3.*xgamma_dim / tmp) / (tmp * tmp * tmp);
  222.                 break;
  223.         default:
  224.                 tmp = BLAST_Factorial(order - 2) * BLAST_Powi(tmp, 1 - order)
  225.                                 * (1. + (order - 1) * xgamma_dim / tmp);
  226.                 if (order % 2 == 0)
  227.                         value += tmp;
  228.                 else
  229.                         value -= tmp;
  230.                 break;
  231.         }
  232.         return value;
  233. }
  234. static double PolyGamma(double x, Int4 order) /* ln(ABS[gamma(x)]) - 10 digits of accuracy */
  235. /* x is and derivatives */
  236. /* order is order of the derivative */
  237. /* order = 0, 1, 2, ...  ln(gamma), digamma, trigamma, ... */
  238. /* CAUTION:  the value of order is one less than the suggested "di" and
  239. "tri" prefixes of digamma, trigamma, etc.  In other words, the value
  240. of order is truly the order of the derivative.  */
  241. {
  242. Int4 k;
  243. double value, tmp;
  244. double y[POLYGAMMA_ORDER_MAX+1], sx;
  245. if (order < 0 || order > POLYGAMMA_ORDER_MAX) {
  246. /*
  247. ErrPostEx(SEV_WARNING,E_Math,ERR_NCBIMATH_DOMAIN,"PolyGamma: unsupported derivative order");
  248. */
  249. /**ERRPOST((CTX_NCBIMATH, ERR_NCBIMATH_DOMAIN, "unsupported derivative order"));**/
  250. return HUGE_VAL;
  251. }
  252. if (x >= 1.)
  253. return general_lngamma(x, order);
  254. if (x < 0.) {
  255. value = general_lngamma(1. - x, order);
  256. value = ((order - 1) % 2 == 0 ? value : -value);
  257. if (order == 0) {
  258. sx = sin(NCBIMATH_PI * x);
  259. sx = ABS(sx);
  260. if ( (x < -0.1 && (ceil(x) == x || sx < 2.*DBL_EPSILON))
  261. || sx == 0.) {
  262. /*
  263. ErrPostEx(SEV_WARNING,E_Math,ERR_NCBIMATH_DOMAIN,"PolyGamma: log(0)");
  264. */
  265. /**ERRPOST((CTX_NCBIMATH, ERR_NCBIMATH_DOMAIN, "log(0)"));**/
  266. return HUGE_VAL;
  267. }
  268. value += NCBIMATH_LNPI - log(sx);
  269. }
  270. else {
  271. y[0] = sin(x *= NCBIMATH_PI);
  272. tmp = 1.;
  273. for (k = 1; k <= order; k++) {
  274. tmp *= NCBIMATH_PI;
  275. y[k] = tmp * sin(x += (NCBIMATH_PI/2.));
  276. }
  277. value -= LogDerivative(order, y);
  278. }
  279. }
  280. else {
  281. value = general_lngamma(1. + x, order);
  282. if (order == 0) {
  283. if (x == 0.) {
  284. /*
  285. ErrPostEx(SEV_WARNING,E_Math,ERR_NCBIMATH_DOMAIN,"PolyGamma: log(0)");
  286. */
  287. /**ERRPOST((CTX_NCBIMATH, ERR_NCBIMATH_DOMAIN, "log(0)"));**/
  288. return HUGE_VAL;
  289. }
  290. value -= log(x);
  291. }
  292. else {
  293. tmp = BLAST_Factorial(order - 1) * BLAST_Powi(x,  -order);
  294. value += (order % 2 == 0 ? tmp : - tmp);
  295. }
  296. }
  297. return value;
  298. }
  299. static double LnGamma(double x)               /* ln(ABS[gamma(x)]) - 10 dig
  300. its of accuracy */
  301. {
  302.         return PolyGamma(x, 0);
  303. }
  304. #define FACTORIAL_PRECOMPUTED   36
  305. extern double BLAST_Factorial(Int4 n)
  306. {
  307.         static double      precomputed[FACTORIAL_PRECOMPUTED]
  308.                 = { 1., 1., 2., 6., 24., 120., 720., 5040., 40320., 362880., 3628800.};
  309.         static Int4     nlim = 10;
  310.         Int4   m;
  311.         double    x;
  312.         if (n >= 0) {
  313.                 if (n <= nlim)
  314.                         return precomputed[n];
  315.                 if (n < DIM(precomputed)) {
  316.                         for (x = precomputed[m = nlim]; m < n; ) {
  317.                                 ++m;
  318.                                 precomputed[m] = (x *= m);
  319.                         }
  320.                         nlim = m;
  321.                         return x;
  322.                 }
  323.                 return exp(LnGamma((double)(n+1)));
  324.         }
  325.         return 0.0; /* Undefined! */
  326. }
  327. /* LnGammaInt(n) -- return log(Gamma(n)) for integral n */
  328. extern double BLAST_LnGammaInt(Int4 n)
  329. {
  330. static double precomputed[FACTORIAL_PRECOMPUTED];
  331. static Int4 nlim = 1; /* first two entries are 0 */
  332. Int4 m;
  333. if (n >= 0) {
  334. if (n <= nlim)
  335. return precomputed[n];
  336. if (n < DIM(precomputed)) {
  337. for (m = nlim; m < n; ++m) {
  338. precomputed[m+1] = log(BLAST_Factorial(m));
  339. }
  340. return precomputed[nlim = m];
  341. }
  342. }
  343. return LnGamma((double)n);
  344. }
  345. /*
  346. Romberg numerical integrator
  347. Author:  Dr. John Spouge, NCBI
  348. Received:  July 17, 1992
  349. Reference:
  350. Francis Scheid (1968)
  351. Schaum's Outline Series
  352. Numerical Analysis, p. 115
  353. McGraw-Hill Book Company, New York
  354. */
  355. #define F(x)  ((*f)((x), fargs))
  356. #define ROMBERG_ITMAX 20
  357. extern double BLAST_RombergIntegrate(double (*f) (double,void*), void* fargs, double p, double q, double eps, Int4 epsit, Int4 itmin)
  358. {
  359. double romb[ROMBERG_ITMAX]; /* present list of Romberg values */
  360. double h; /* mesh-size */
  361. Int4 i, j, k, npts;
  362. long n; /* 4^(error order in romb[i]) */
  363. Int4 epsit_cnt = 0, epsck;
  364. double y;
  365. double x;
  366. double sum;
  367. /* itmin = min. no. of iterations to perform */
  368. itmin = MAX(1, itmin);
  369. itmin = MIN(itmin, ROMBERG_ITMAX-1);
  370. /* epsit = min. no. of consecutive iterations that must satisfy epsilon */
  371. epsit = MAX(epsit, 1); /* default = 1 */
  372. epsit = MIN(epsit, 3); /* if > 3, the problem needs more prior analysis */
  373. epsck = itmin - epsit;
  374. npts = 1;
  375. h = q - p;
  376. x = F(p);
  377. if (ABS(x) == HUGE_VAL)
  378. return x;
  379. y = F(q);
  380. if (ABS(y) == HUGE_VAL)
  381. return y;
  382. romb[0] = 0.5 * h * (x + y); /* trapezoidal rule */
  383. for (i = 1; i < ROMBERG_ITMAX; ++i, npts *= 2, h *= 0.5) {
  384. sum = 0.; /* sum of ordinates for */
  385. /* x = p+0.5*h, p+1.5*h, ..., q-0.5*h */
  386. for (k = 0, x = p+0.5*h; k < npts; k++, x += h) {
  387. y = F(x);
  388. if (ABS(y) == HUGE_VAL)
  389. return y;
  390. sum += y;
  391. }
  392. romb[i] = 0.5 * (romb[i-1] + h*sum); /* new trapezoidal estimate */
  393. /* Update Romberg array with new column */
  394. for (n = 4, j = i-1; j >= 0; n *= 4, --j)
  395. romb[j] = (n*romb[j+1] - romb[j]) / (n-1);
  396. if (i > epsck) {
  397. if (ABS(romb[1] - romb[0]) > eps * ABS(romb[0])) {
  398. epsit_cnt = 0;
  399. continue;
  400. }
  401. ++epsit_cnt;
  402. if (i >= itmin && epsit_cnt >= epsit)
  403. return romb[0];
  404. }
  405. }
  406. /*
  407. ErrPostEx(SEV_WARNING,E_Math,ERR_NCBIMATH_ITER,"RombergIntegrate: iterations > ROMBERG_ITMAX");
  408. */
  409. /**ERRPOST((CTX_NCBIMATH, ERR_NCBIMATH_ITER, "iterations > ROMBERG_ITMAX"));**/
  410. return HUGE_VAL;
  411. }
  412. /*
  413. Gcd(a, b)
  414. Return the greatest common divisor of a and b.
  415. Adapted 8-15-90 by WRG from code by S. Altschul.
  416. */
  417. long BLAST_Gcd(long a, long b)
  418. {
  419. long c;
  420. b = ABS(b);
  421. if (b > a)
  422. c=a, a=b, b=c;
  423. while (b != 0) {
  424. c = a%b;
  425. a = b;
  426. b = c;
  427. }
  428. return a;
  429. }
  430. /* Round a floating point number to the nearest integer */
  431. long BLAST_Nint(double x) /* argument */
  432. {
  433. x += (x >= 0. ? 0.5 : -0.5);
  434. return (long)x;
  435. }
  436. /*
  437. integer power function
  438. Original submission by John Spouge, 6/25/90
  439. Added to shared library by WRG
  440. */
  441. extern double BLAST_Powi(double x, Int4 n) /* power */
  442. {
  443. double y;
  444. if (n == 0)
  445. return 1.;
  446. if (x == 0.) {
  447. if (n < 0) {
  448. /*
  449. ErrPostEx(SEV_WARNING,E_Math,ERR_NCBIMATH_DOMAIN,"Powi: divide by 0");
  450. */
  451. /**ERRPOST((CTX_NCBIMATH, ERR_NCBIMATH_DOMAIN, "divide by 0"));**/
  452. return HUGE_VAL;
  453. }
  454. return 0.;
  455. }
  456. if (n < 0) {
  457. x = 1./x;
  458. n = -n;
  459. }
  460. while (n > 1) {
  461. if (n&1) {
  462. y = x;
  463. goto Loop2;
  464. }
  465. n /= 2;
  466. x *= x;
  467. }
  468. return x;
  469. Loop2:
  470. n /= 2;
  471. x *= x;
  472. while (n > 1) {
  473. if (n&1)
  474. y *= x;
  475. n /= 2;
  476. x *= x;
  477. }
  478. return y * x;
  479. }
  480. extern double BLAST_LnFactorial (double x) {
  481.     if(x<=0.0)
  482.         return 0.0;
  483.     else
  484.         return LnGamma(x+1.0);
  485.         
  486. }
  487. /*
  488.  * ===========================================================================
  489.  *
  490.  * $Log: ncbi_math.c,v $
  491.  * Revision 1000.2  2004/06/01 18:08:20  gouriano
  492.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  493.  *
  494.  * Revision 1.8  2004/05/19 14:52:03  camacho
  495.  * 1. Added doxygen tags to enable doxygen processing of algo/blast/core
  496.  * 2. Standardized copyright, CVS $Id string, $Log and rcsid formatting and i
  497.  *    location
  498.  * 3. Added use of @todo doxygen keyword
  499.  *
  500.  * Revision 1.7  2003/12/05 16:03:57  camacho
  501.  * Remove compiler warnings
  502.  *
  503.  * Revision 1.6  2003/09/26 20:39:32  dondosha
  504.  * Rearranged code so it compiles
  505.  *
  506.  * Revision 1.5  2003/09/26 19:01:59  madden
  507.  * Prefix ncbimath functions with BLAST_
  508.  *
  509.  * Revision 1.4  2003/09/10 21:36:29  dondosha
  510.  * Removed Nlm_ prefix from math functions definitions
  511.  *
  512.  * Revision 1.3  2003/08/25 22:32:51  dondosha
  513.  * Added #ifndef for definition of DBL_EPSILON
  514.  *
  515.  * Revision 1.2  2003/08/11 15:02:00  dondosha
  516.  * Added algo/blast/core to all #included headers
  517.  *
  518.  * Revision 1.1  2003/08/02 16:31:48  camacho
  519.  * Moved ncbimath.c -> ncbi_math.c
  520.  *
  521.  * Revision 1.1  2003/08/01 21:03:46  madden
  522.  * Cleaned up version of file for C++ toolkit
  523.  *
  524.  * ===========================================================================
  525.  */