JWS C Library
C language utility library
|
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