JWS C Library
C language utility library
pdf.c
Go to the documentation of this file.
00001 /*
00002  * This work is licensed under a Creative Commons 
00003  * Attribution-Noncommercial-Share Alike 3.0 United States License.
00004  * 
00005  *    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
00006  * 
00007  * You are free:
00008  * 
00009  *    to Share - to copy, distribute, display, and perform the work
00010  *    to Remix - to make derivative works
00011  * 
00012  * Under the following conditions:
00013  * 
00014  *    Attribution. You must attribute the work in the manner specified by the
00015  *    author or licensor (but not in any way that suggests that they endorse you
00016  *    or your use of the work).
00017  * 
00018  *    Noncommercial. You may not use this work for commercial purposes.
00019  * 
00020  *    Share Alike. If you alter, transform, or build upon this work, you may
00021  *    distribute the resulting work only under the same or similar license to
00022  *    this one.
00023  * 
00024  * For any reuse or distribution, you must make clear to others the license
00025  * terms of this work. The best way to do this is by including this header.
00026  * 
00027  * Any of the above conditions can be waived if you get permission from the
00028  * copyright holder.
00029  * 
00030  * Apart from the remix rights granted under this license, nothing in this
00031  * license impairs or restricts the author's moral rights.
00032  */
00033 
00034 
00046 #include <jwsc/config.h>
00047 
00048 #include <stdlib.h>
00049 #include <stdio.h>
00050 #include <math.h>
00051 #include <assert.h>
00052 
00053 #include "jwsc/base/limits.h"
00054 #include "jwsc/math/constants.h"
00055 #include "jwsc/math/slatec.h"
00056 #include "jwsc/prob/pdf.h"
00057 
00058 
00060 #define  SQRT_2_PI_SINGLE      2.5066282746310004f
00061 
00063 #define  SQRT_2_PI_DOUBLE      2.50662827463100050241576528481103
00064 
00066 #define  INV_SQRT_2_PI_SINGLE  0.3989422804014326f
00067 
00069 #define  INV_SQRT_2_PI_DOUBLE  0.39894228040143267793994605993438
00070 
00072 #define  LOG_SQRT_2_PI_SINGLE  0.9189385332046727
00073 
00075 #define  LOG_SQRT_2_PI_DOUBLE  .91893853320467274178032973640561
00076 
00077 
00092 float standard_gaussian_pdf_f(float x)
00093 {
00094     return INV_SQRT_2_PI_SINGLE * exp(-0.5 * x * x);
00095 }
00096 
00102 double standard_gaussian_pdf_d(double x)
00103 {
00104     return INV_SQRT_2_PI_DOUBLE * exp(-0.5 * x * x);
00105 }
00106 
00124 float gaussian_pdf_f(float mu, float sigma, float x)
00125 {
00126     assert(sigma > 1.0e-8);
00127 
00128     return INV_SQRT_2_PI_SINGLE * (1 / sigma) * 
00129         exp(-0.5 * (x - mu)*(x - mu) / (sigma*sigma));
00130 }
00131 
00139 double gaussian_pdf_d(double mu, double sigma, double x)
00140 {
00141     assert(sigma > 1.0e-16);
00142 
00143     return INV_SQRT_2_PI_DOUBLE * (1 / sigma) * 
00144         exp(-0.5 * (x - mu)*(x - mu) / (sigma*sigma));
00145 }
00146 
00162 float log_standard_gaussian_pdf_f(float x)
00163 {
00164     return - LOG_SQRT_2_PI_SINGLE - 0.5*x*x;
00165 }
00166 
00172 double log_standard_gaussian_pdf_d(double x)
00173 {
00174     return - LOG_SQRT_2_PI_DOUBLE - 0.5*x*x;
00175 }
00176 
00194 float log_gaussian_pdf_f(float mu, float sigma, float x)
00195 {
00196     float log_sigma;
00197 
00198     assert(sigma > 1.0e-8);
00199 
00200     log_sigma = log(sigma);
00201 
00202     return - LOG_SQRT_2_PI_SINGLE - log_sigma - 
00203         (0.5*(x - mu)*(x - mu)) / (sigma*sigma);
00204 }
00205 
00213 double log_gaussian_pdf_d(double mu, double sigma, double x)
00214 {
00215     double log_sigma;
00216 
00217     assert(sigma > 1.0e-16);
00218 
00219     log_sigma = log(sigma);
00220 
00221     return - LOG_SQRT_2_PI_DOUBLE - log_sigma - 
00222         (0.5*(x - mu)*(x - mu)) / (sigma*sigma);
00223 }
00224 
00228 #if defined JWSC_HAVE_SLATEC || defined JWSC_HAVE_ERF
00229 
00244 float integrate_gaussian_pdf_f
00245 (
00246     float mu, 
00247     float sigma, 
00248     float a, 
00249     float b
00250 )
00251 {
00252     float x_1;
00253     float x_2;
00254     float div;
00255     float result;
00256 
00257     div = sqrt(2) * sigma;
00258 
00259     x_1 = (mu - b) / div;
00260     x_2 = (mu - a) / div;
00261 
00262 #if defined JWSC_HAVE_SLATEC
00263     result = 0.5 * (slatec_derf(x_2) - slatec_derf(x_1));
00264 #elif defined JWSC_HAVE_ERF
00265     result = 0.5 * (erf(x_2) - erf(x_1));
00266 #endif
00267 
00268     return result;
00269 }
00270 
00279 double integrate_gaussian_pdf_d
00280 (
00281     double mu, 
00282     double sigma, 
00283     double a, 
00284     double b
00285 )
00286 {
00287     double x_1;
00288     double x_2;
00289     double div;
00290     double result;
00291 
00292     div = sqrt(2) * sigma;
00293 
00294     x_1 = (mu - b) / div;
00295     x_2 = (mu - a) / div;
00296 
00297 #if defined JWSC_HAVE_SLATEC
00298     result = 0.5 * (slatec_derf(x_2) - slatec_derf(x_1));
00299 #elif defined JWSC_HAVE_ERF
00300     result = 0.5 * (erf(x_2) - erf(x_1));
00301 #endif
00302 
00303     return result;
00304 }
00305 
00307 #endif
00308 
00309 
00327 float sample_standard_gaussian_pdf_f(float a, float b)
00328 {
00329     int accept;
00330     float s, l, u;
00331 
00332     accept = 0;
00333 
00334     while (!accept)
00335     {
00336         s = sample_uniform_pdf_f(a, b);
00337         l = log_standard_gaussian_pdf_f(s);
00338         u = log(sample_uniform_pdf_f(0, 1));
00339 
00340         if (u <= l)
00341         {
00342             accept = 1;
00343         }
00344     }
00345 
00346     return s;
00347 }
00348 
00359 double sample_standard_gaussian_pdf_d(double a, double b)
00360 {
00361     int accept;
00362     double s, l, u;
00363 
00364     accept = 0;
00365 
00366     while (!accept)
00367     {
00368         s = sample_uniform_pdf_d(a, b);
00369         l = log_standard_gaussian_pdf_d(s);
00370         u = log(sample_uniform_pdf_d(JWSC_MIN_LOG_ARG, 1));
00371 
00372         if (u <= l)
00373         {
00374             accept = 1;
00375         }
00376     }
00377 
00378     return s;
00379 }
00380 
00403 float sample_gaussian_pdf_f
00404 (
00405     float mu, 
00406     float sigma, 
00407     float a, 
00408     float b
00409 )
00410 {
00411     int accept;
00412     float s, l, u;
00413     float max;
00414 
00415     max = gaussian_pdf_f(mu, sigma, mu);
00416     assert(JWSC_MIN_LOG_ARG <= max);
00417     accept = 0;
00418 
00419     while (!accept)
00420     {
00421         s = sample_uniform_pdf_f(a, b);
00422         l = log_gaussian_pdf_f(mu, sigma, s);
00423         u = log(sample_uniform_pdf_f(JWSC_MIN_LOG_ARG, max));
00424 
00425         if (u <= l)
00426         {
00427             accept = 1;
00428         }
00429     }
00430 
00431     return s;
00432 }
00433 
00446 double sample_gaussian_pdf_d
00447 (
00448     double mu, 
00449     double sigma, 
00450     double a, 
00451     double b
00452 )
00453 {
00454     int accept;
00455     double s, l, u;
00456     double max;
00457 
00458     max = gaussian_pdf_d(mu, sigma, mu);
00459     assert(JWSC_MIN_LOG_ARG <= max);
00460     accept = 0;
00461 
00462     while (!accept)
00463     {
00464         s = sample_uniform_pdf_d(a, b);
00465         l = log_gaussian_pdf_d(mu, sigma, s);
00466         u = log(sample_uniform_pdf_d(JWSC_MIN_LOG_ARG, max));
00467 
00468         if (u <= l)
00469         {
00470             accept = 1;
00471         }
00472     }
00473 
00474     return s;
00475 }
00476 
00480 #if defined JWSC_HAVE_TGAMMA
00481 extern double tgamma(double x);
00482 
00497 float gamma_pdf_f(float alpha, float beta, float x)
00498 {
00499     assert(x > 1.0e-8);
00500     assert(alpha > 1.0e-8);
00501     assert(beta > 1.0e-8);
00502 
00503     return pow(beta, alpha) / tgamma(alpha) * pow(x, alpha - 1) * exp(-beta*x);
00504 }
00505 
00513 double gamma_pdf_d(double alpha, double beta, double x)
00514 {
00515     assert(x > 1.0e-16);
00516     assert(alpha > 1.0e-16);
00517     assert(beta > 1.0e-16);
00518 
00519     return pow(beta, alpha) / tgamma(alpha) * pow(x, alpha - 1) * exp(-beta*x);
00520 }
00521 
00523 #endif
00524 
00525 
00526 #if defined JWSC_HAVE_LGAMMA
00527 
00541 float log_gamma_pdf_f(float alpha, float beta, float x)
00542 {
00543     assert(x > 1.0e-8);
00544     assert(alpha > 1.0e-8);
00545     assert(beta > 1.0e-8);
00546 
00547     return alpha*log(beta) - lgamma(alpha) + (alpha - 1)*log(x) - beta*x;
00548 }
00549 
00557 double log_gamma_pdf_d(double alpha, double beta, double x)
00558 {
00559     assert(x > 1.0e-16);
00560     assert(alpha > 1.0e-16);
00561     assert(beta > 1.0e-16);
00562 
00563     return alpha*log(beta) - lgamma(alpha) + (alpha - 1)*log(x) - beta*x;
00564 }
00565 
00567 #endif
00568 
00569 
00570 #if defined JWSC_HAVE_TGAMMA
00571 
00590 float sample_gamma_pdf_f
00591 (
00592     float alpha, 
00593     float beta, 
00594     float a, 
00595     float b
00596 )
00597 {
00598     int accept;
00599     float s, l, u;
00600     float max;
00601 
00602 
00603     if(alpha < 20 && beta < 20)
00604     {
00605         max = (alpha > 1) ? gamma_pdf_f(alpha, beta, (alpha - 1)/beta) : 1;
00606     }
00607     else
00608     {
00609         // for large alpha and beta, intermediate computations are 
00610         // more robust in the log space.
00611         max = exp(log_gamma_pdf_f(alpha, beta, (alpha - 1)/beta));
00612     }
00613 
00614     assert(JWSC_MIN_LOG_ARG <= max);
00615     accept = 0;
00616 
00617     while (!accept)
00618     {
00619         s = sample_uniform_pdf_f(a, b);
00620         l = log_gamma_pdf_f(alpha, beta, s);
00621         u = log(sample_uniform_pdf_f(JWSC_MIN_LOG_ARG, max));
00622 
00623         if (u <= l)
00624         {
00625             accept = 1;
00626         }
00627     }
00628 
00629     return s;
00630 }
00631 
00644 double sample_gamma_pdf_d
00645 (
00646     double alpha, 
00647     double beta, 
00648     double a, 
00649     double b
00650 )
00651 {
00652     int accept;
00653     double s, l, u;
00654     double max;
00655 
00656     if(alpha < 20 && beta < 20)
00657     {
00658         max = (alpha > 1) ? gamma_pdf_d(alpha, beta, (alpha - 1)/beta) : 1;
00659     }
00660     else
00661     {
00662         // for large alpha and beta, intermediate computations are 
00663         // more robust in the log space.
00664         max = exp(log_gamma_pdf_d(alpha, beta, (alpha - 1)/beta));
00665     }
00666 
00667     assert(JWSC_MIN_LOG_ARG <= max);
00668     accept = 0;
00669 
00670     while (!accept)
00671     {
00672         s = sample_uniform_pdf_d(a, b);
00673         l = log_gamma_pdf_d(alpha, beta, s);
00674         u = log(sample_uniform_pdf_d(JWSC_MIN_LOG_ARG, max));
00675 
00676         if (u <= l)
00677         {
00678             accept = 1;
00679         }
00680     }
00681 
00682     return s;
00683 }
00684 
00686 #endif
00687 
00688 
00706 float sample_uniform_pdf_f(float a, float b)
00707 {
00708     if (a == b)
00709     {
00710         return a;
00711     }
00712 
00713     return (b - a)*(rand()/(float)RAND_MAX) + a;
00714 }
00715 
00726 double sample_uniform_pdf_d(double a, double b)
00727 {
00728     if (a == b)
00729     {
00730         return a;
00731     }
00732 
00733     return (b - a)*(rand()/(double)RAND_MAX) + a;
00734 }
00735 
00753 float sample_sine_pdf_f()
00754 {
00755     int accept;
00756     float s, l, u;
00757 
00758     accept = 0;
00759 
00760     while (!accept)
00761     {
00762         s = sample_uniform_pdf_f(0, JWSC_PI_2);
00763         l = sin(s);
00764         u = sample_uniform_pdf_f(0, 1.0);
00765 
00766         if (u <= l)
00767         {
00768             accept = 1;
00769         }
00770     }
00771 
00772     return s;
00773 }
00774 
00782 double sample_sine_pdf_d()
00783 {
00784     int accept;
00785     double s, l, u;
00786 
00787     accept = 0;
00788 
00789     while (!accept)
00790     {
00791         s = sample_uniform_pdf_d(0, JWSC_PI_2);
00792         l = sin(s);
00793         u = sample_uniform_pdf_d(0, 1.0);
00794 
00795         if (u <= l)
00796         {
00797             accept = 1;
00798         }
00799     }
00800 
00801     return s;
00802 }
00803