# include # include # include # include # include # include using namespace std; # include "prob.hpp" //****************************************************************************80 double angle_cdf ( double x, int n ) //****************************************************************************80 // // Purpose: // // ANGLE_CDF evaluates the Angle CDF. // // Modified: // // 19 November 2004 // // Author: // // John Burkardt // // Reference: // // Reuven Rubinstein, // Monte Carlo Optimization, Simulation and Sensitivity of Queueing Networks, // Wiley, 1986. // // Parameters: // // Input, double X, the argument of the PDF. // // Input, int N, the spatial dimension. // N must be at least 2. // // Output, real CDF, the value of the CDF. // { double cdf; const double pi = 3.14159265358979323; double zero = 0.0; if ( n < 2 ) { cerr << "\n"; cerr << "ANGLE_CDF - Fatal error!\n"; cerr << " N must be at least 2.\n"; cerr << " The input value of N = " << n << "\n"; exit ( 1 ); } if ( x < 0.0 ) { cdf = 0.0; } else if ( pi < x ) { cdf = 1.0; } else if ( n == 2 ) { cdf = x / pi; } else { cdf = sin_power_int ( zero, x, n-2 ) * r8_gamma ( ( double ) ( n ) / 2.0 ) / ( sqrt ( pi ) * r8_gamma ( ( double ) ( n - 1 ) / 2.0 ) ); } return cdf; } //****************************************************************************80 double angle_mean ( int n ) //****************************************************************************80 // // Purpose: // // ANGLE_MEAN returns the mean of the Angle PDF. // // Modified: // // 02 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the spatial dimension. // N must be at least 2. // // Output, double ANGLE_MEAN, the mean of the PDF. // { double mean; const double pi = 3.14159265358979323; mean = pi / 2.0; return mean; } //****************************************************************************80 double angle_pdf ( double x, int n ) //****************************************************************************80 // // Purpose: // // ANGLE_PDF evaluates the Angle PDF. // // Discussion: // // X is an angle between 0 and PI, corresponding to the angle // made in an N-dimensional space, between a fixed line passing // through the origin, and an arbitrary line that also passes // through the origin, which is specified by a choosing any point // on the N-dimensional sphere with uniform probability. // // Formula: // // PDF(X) = ( sin ( X ) )^(N-2) * Gamma ( N / 2 ) // / ( sqrt ( PI ) * Gamma ( ( N - 1 ) / 2 ) ) // // PDF(X) = 1 / PI if N = 2. // // Modified: // // 02 September 2004 // // Author: // // John Burkardt // // Reference: // // Reuven Rubinstein, // Monte Carlo Optimization, Simulation and Sensitivity of Queueing Networks, // Wiley, 1986. // // Parameters: // // Input, double X, the argument of the PDF. // // Input, int N, the spatial dimension. // N must be at least 2. // // Output, real PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; if ( n < 2 ) { cerr << "\n"; cerr << "ANGLE_PDF - Fatal error!\n"; cerr << " N must be at least 2.\n"; cerr << " The input value of N = " << n << "\n"; exit ( 1 ); } if ( x < 0.0 || pi < x ) { pdf = 0.0; } else if ( n == 2 ) { pdf = 1.0 / pi; } else { pdf = pow ( ( sin ( x ) ), ( n - 2 ) ) * r8_gamma ( ( double ) ( n ) / 2.0 ) / ( sqrt ( pi ) * r8_gamma ( ( double ) ( n - 1 ) / 2.0 ) ); } return pdf; } //****************************************************************************80 double anglit_cdf ( double x ) //****************************************************************************80 // // Purpose: // // ANGLIT_CDF evaluates the Anglit CDF. // // Modified: // // 29 December 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Output, double ANGLIT_CDF, the value of the CDF. // { double cdf; const double pi = 3.14159265358979323; if ( x < - 0.25 * pi ) { cdf = 0.0; } else if ( x < 0.25 * pi ) { cdf = 0.5 - 0.5 * cos ( 2.0 * x + pi / 2.0 ); } else { cdf = 1.0; } return cdf; } //****************************************************************************80 double anglit_cdf_inv ( double cdf ) //****************************************************************************80 // // Purpose: // // ANGLIT_CDF_INV inverts the Anglit CDF. // // Modified: // // 29 December 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Output, double ANGLIT_CDF_INV, the corresponding argument. // { const double pi = 3.14159265358979323; double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "ANGLIT_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = 0.5 * ( acos ( 1.0 - 2.0 * cdf ) - pi / 2.0 ); return x; } //****************************************************************************80 double anglit_mean ( ) //****************************************************************************80 // // Purpose: // // ANGLIT_MEAN returns the mean of the Anglit PDF. // // Modified: // // 28 December 1999 // // Author: // // John Burkardt // // Parameters: // // Output, double ANGLIT_MEAN, the mean of the PDF. // { return 0.0; } //****************************************************************************80 double anglit_pdf ( double x ) //****************************************************************************80 // // Purpose: // // ANGLIT_PDF evaluates the Anglit PDF. // // Formula: // // PDF(X) = SIN ( 2 * X + PI / 2 ) for -PI/4 <= X <= PI/4 // // Modified: // // 28 December 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Output, double ANGLIT_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; if ( x <= - 0.25 * pi || 0.25 * pi <= x ) { pdf = 0.0; } else { pdf = sin ( 2.0 * x + 0.25 * pi ); } return pdf; } //****************************************************************************80 double anglit_sample ( int &seed ) //****************************************************************************80 // // Purpose: // // ANGLIT_SAMPLE samples the Anglit PDF. // // Modified: // // 28 December 1999 // // Author: // // John Burkardt // // Parameters: // // Input/output, int &SEED, a seed for the random number generator. // // Output, double ANGLIT_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = anglit_cdf_inv ( cdf ); return x; } //****************************************************************************80 double anglit_variance ( ) //****************************************************************************80 // // Purpose: // // ANGLIT_VARIANCE returns the variance of the Anglit PDF. // // Discussion: // // Variance = // Integral ( -PI/4 <= X <= PI/4 ) X^2 * SIN ( 2 * X + PI / 2 ) // // Antiderivative = // 0.5 * X * SIN ( 2 * X + PI / 2 ) // + ( 0.25 - 0.5 * X^2 ) * COS ( 2 * X + PI / 2 ) // // Modified: // // 29 December 1999 // // Author: // // John Burkardt // // Parameters: // // Output, double ANGLIT_VARIANCE, the variance of the PDF. // { const double pi = 3.14159265358979323; double variance; variance = 0.0625 * pi * pi - 0.5; return variance; } //****************************************************************************80 double arcsin_cdf ( double x, double a ) //****************************************************************************80 // // Purpose: // // ARCSIN_CDF evaluates the Arcsin CDF. // // Modified: // // 20 March 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, the parameter of the CDF. // A must be positive. // // Output, double ARCSIN_CDF, the value of the CDF. // { double cdf; const double pi = 3.14159265358979323; if ( x <= -a ) { cdf = 0.0; } else if ( x < a ) { cdf = 0.5 + asin ( x / a ) / pi; } else { cdf = 1.0; } return cdf; } //****************************************************************************80 double arcsin_cdf_inv ( double cdf, double a ) //****************************************************************************80 // // Purpose: // // ARCSIN_CDF_INV inverts the Arcsin CDF. // // Modified: // // 20 March 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, the parameter of the CDF. // A must be positive. // // Output, double ARCSIN_CDF_INV, the corresponding argument. // { const double pi = 3.14159265358979323; double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "ARCSIN_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a * sin ( pi * ( cdf - 0.5 ) ); return x; } //****************************************************************************80 bool arcsin_check ( double a ) //****************************************************************************80 // // Purpose: // // ARCSIN_CHECK checks the parameter of the Arcsin CDF. // // Modified: // // 27 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 < A. // // Output, bool ARCSIN_CHECK, is TRUE if the data is acceptable. { if ( a <= 0.0 ) { return false; } else { return true; } } //****************************************************************************80 double arcsin_mean ( double a ) //****************************************************************************80 // // Purpose: // // ARCSIN_MEAN returns the mean of the Arcsin PDF. // // // Modified: // // 20 March 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the CDF. // A must be positive. // // Output, double MEAN, the mean of the PDF. // { double mean = 0.0; return mean; } //****************************************************************************80 double arcsin_pdf ( double x, double a ) //****************************************************************************80 // // Purpose: // // ARCSIN_PDF evaluates the Arcsin PDF. // // Discussion: // // The LOGISTIC EQUATION has the form: // // X(N+1) = 4.0 * LAMBDA * ( 1.0 - X(N) ). // // where 0 < LAMBDA <= 1. This nonlinear difference equation maps // the unit interval into itself, and is a simple example of a system // exhibiting chaotic behavior. Ulam and von Neumann studied the // logistic equation with LAMBDA = 1, and showed that iterates of the // function generated a sequence of pseudorandom numbers with // the Arcsin probability density function. // // The derived sequence // // Y(N) = ( 2 / PI ) * Arcsin ( SQRT ( X(N) ) ) // // is a pseudorandom sequence with the uniform probability density // function on [0,1]. For certain starting values, such as X(0) = 0, 0.75, // or 1.0, the sequence degenerates into a constant sequence, and for // values very near these, the sequence takes a while before becoming // chaotic. // // Formula: // // PDF(X) = 1 / ( PI * Sqrt ( A * A - X * X ) ) // // Reference: // // Daniel Zwillinger, Stephen Kokoska, // CRC Standard Probability and Statistics Tables and Formulae, // Chapman and Hall/CRC, 2000, pages 114-115. // // Modified: // // 20 March 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 < X < 1.0. // // Input, double A, the parameter of the CDF. // A must be positive. // // Output, double ARCSIN_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; if ( a <= 0 ) { cerr << "\n"; cerr << "ARCSIN_PDF - Fatal error!\n"; cerr << " Parameter A <= 0.\n"; exit ( 1 ); } if ( x <= -a || a <= x ) { pdf = 0.0; } else { pdf = 1.0 / ( pi * sqrt ( a * a - x * x ) ); } return pdf; } //****************************************************************************80 double arcsin_sample ( double a, int &seed ) //****************************************************************************80 // // Purpose: // // ARCSIN_SAMPLE samples the Arcsin PDF. // // Modified: // // 20 March 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the CDF. // A must be positive. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double ARCSIN_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = arcsin_cdf_inv ( cdf, a ); return x; } //****************************************************************************80 double arcsin_variance ( double a ) //****************************************************************************80 // // Purpose: // // ARCSIN_VARIANCE returns the variance of the Arcsin PDF. // // Modified: // // 20 March 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the CDF. // A must be positive. // // Output, double ARCSIN_VARIANCE, the variance of the PDF. // { double variance = a * a / 2.0; return variance; } //****************************************************************************80 double benford_pdf ( double x ) //****************************************************************************80 // // Purpose: // // BENFORD_PDF returns the Benford probability of one or more significant digits. // // Discussion: // // Benford's law is an empirical formula explaining the observed // distribution of initial digits in lists culled from newspapers, // tax forms, stock market prices, and so on. It predicts the observed // high frequency of the initial digit 1, for instance. // // Note that the probabilities of digits 1 through 9 are guaranteed // to add up to 1, since // LOG10 ( 2/1 ) + LOG10 ( 3/2) + LOG10 ( 4/3 ) + ... + LOG10 ( 10/9 ) // = LOG10 ( 2/1 * 3/2 * 4/3 * ... * 10/9 ) = LOG10 ( 10 ) = 1. // // Formula: // // PDF(X) = LOG10 ( ( X + 1 ) / X ). // // Reference: // // Frank Benford, // The Law of Anomalous Numbers, // Proceedings of the American Philosophical Society, // Volume 78, pages 551-572, 1938. // // Ted Hill, // The First Digit Phenomenon, // American Scientist, // Volume 86, July/August 1998, pages 358 - 363. // // R Raimi, // The Peculiar Distribution of First Digits, // Scientific American, // December 1969, pages 109-119. // // Modified: // // 13 August 1998 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the string of significant digits to be checked. // If X is 1, then we are asking for the Benford probability that // a value will have first digit 1. If X is 123, we are asking for // the probability that the first three digits will be 123, and so on. // // Output, double BENFORD_PDF, the Benford probability that an item taken // from a real world distribution will have the initial digits X. // { double pdf; if ( x <= 0 ) { pdf = 0.0; } else { pdf = log10 ( ( double ) ( x + 1 ) / ( double ) ( x ) ); } return pdf; } //****************************************************************************80 double bernoulli_cdf ( int x, double a ) //****************************************************************************80 // // Purpose: // // BERNOULLI_CDF evaluates the Bernoulli CDF. // // // Modified: // // 22 May 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the number of successes on a single trial. // X = 0 or 1. // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Output, double BERNOULLI_CDF, the value of the CDF. // { double cdf; if ( x < 0 ) { cdf = 0.0; } else if ( x == 0 ) { cdf = 1.0 - a; } else { cdf = 1.0; } return cdf; } //****************************************************************************80 int bernoulli_cdf_inv ( double cdf, double a ) //****************************************************************************80 // // Purpose: // // BERNOULLI_CDF_INV inverts the Bernoulli CDF. // // Modified: // // 22 May 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, the parameter of the PDF. // 0.0 <= A <= 1.0. // // Output, int BERNOULLI_CDF_INV, the corresponding argument. // { int x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "BERNOULLI_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf <= 1.0 - a ) { x = 0; } else { x = 1; } return x; } //****************************************************************************80 bool bernoulli_check ( double a ) //****************************************************************************80 // // Purpose: // // BERNOULLI_CHECK checks the parameter of the Bernoulli CDF. // // Modified: // // 22 May 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 <= A <= 1.0. // // Output, bool BERNOULLI_CHECK, is TRUE if the data is acceptable. { if ( a < 0.0 || 1.0 < a ) { return false; } else { return true; } } //****************************************************************************80 double bernoulli_mean ( double a ) //****************************************************************************80 // // Purpose: // // BERNOULLI_MEAN returns the mean of the Bernoulli PDF. // // Modified: // // 22 May 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of success. // 0.0 <= A <= 1.0. // // Output, double BERNOULLI_MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double bernoulli_pdf ( int x, double a ) //****************************************************************************80 // // Purpose: // // BERNOULLI_PDF evaluates the Bernoulli PDF. // // Formula: // // PDF(X)(A) = A^X * ( 1.0 - A )^( X - 1 ) // // X = 0 or 1. // // Discussion: // // The Bernoulli PDF describes the simple case in which a single trial // is carried out, with two possible outcomes, called "success" and // "failure"; the probability of success is A. // // Modified: // // 22 May 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the number of successes on a single trial. // X = 0 or 1. // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Output, double BERNOULLI_PDF, the value of the PDF. // { double pdf; if ( x < 0 ) { pdf = 0.0; } else if ( x == 0 ) { pdf = 1.0 - a; } else if ( x == 1 ) { pdf = a; } else { pdf = 0.0; } return pdf; } //****************************************************************************80 int bernoulli_sample ( double a, int &seed ) //****************************************************************************80 // // Purpose: // // BERNOULLI_SAMPLE samples the Bernoulli PDF. // // Modified: // // 22 May 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int BERNOULLI_SAMPLE, a sample of the PDF. // { double cdf; int x; cdf = r8_uniform_01 ( seed ); x = bernoulli_cdf_inv ( cdf, a ); return x; } //****************************************************************************80 double bernoulli_variance ( double a ) //****************************************************************************80 // // Purpose: // // BERNOULLI_VARIANCE returns the variance of the Bernoulli PDF. // // Modified: // // 22 May 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Output, double BERNOULLI_VARIANCE, the variance of the PDF. // { double variance; variance = a * ( 1.0 - a ); return variance; } //****************************************************************************80 double bessel_i0 ( double arg ) //****************************************************************************80 // // Purpose: // // BESSEL_I0 evaluates the modified Bessel function I0. // // Discussion: // // The main computation evaluates slightly modified forms of // minimax approximations generated by Blair and Edwards, Chalk // River (Atomic Energy of Canada Limited) Report AECL-4928, // October, 1974. This transportable program is patterned after // the machine dependent FUNPACK packet NATSI0, but cannot match // that version for efficiency or accuracy. This version uses // rational functions that theoretically approximate I-SUB-0(X) // to at least 18 significant decimal digits. // // Machine dependent constants: // // beta = Radix for the floating-point system // maxexp = Smallest power of beta that overflows // XSMALL = Positive argument such that 1.0 - X = 1.0 to // machine precision for all ABS(X) .LE. XSMALL. // XMAX = Largest argument acceptable to BESI0; Solution to // equation: // W(X) * (1+1/(8*X)+9/(128*X^2) = beta**maxexp // where W(X) = EXP(X)/sqrt(2*PI*X) // // Approximate values for some important machines are: // // beta maxexp XSMALL // // CRAY-1 (S.P.) 2 8191 3.55D-15 // Cyber 180/855 // under NOS (S.P.) 2 1070 3.55D-15 // IEEE (IBM/XT, // SUN, etc.) (S.P.) 2 128 2.98D-8 // IEEE (IBM/XT, // SUN, etc.) (D.P.) 2 1024 5.55D-17 // IBM 3033 (D.P.) 16 63 6.95D-18 // VAX (S.P.) 2 127 2.98D-8 // VAX D-Format (D.P.) 2 127 6.95D-18 // VAX G-Format (D.P.) 2 1023 5.55D-17 // // // XMAX // // CRAY-1 (S.P.) 5682.810 // Cyber 180/855 // under NOS (S.P.) 745.893 // IEEE (IBM/XT, // SUN, etc.) (S.P.) 91.900 // IEEE (IBM/XT, // SUN, etc.) (D.P.) 713.986 // IBM 3033 (D.P.) 178.182 // VAX (S.P.) 91.203 // VAX D-Format (D.P.) 91.203 // VAX G-Format (D.P.) 713.293 // // Author: // // Original FORTRAN77 version by W. J. Cody and L. Stoltz. // C++ version by John Burkardt. // // Parameters: // // Input, double ARG, the argument. // // Output, double BESSEL_I0, the value of the modified Bessel function // of the first kind. // { double a; double b; double exp40 = 2.353852668370199854E+17; int i; double p[15] = { -5.2487866627945699800E-18, -1.5982226675653184646E-14, -2.6843448573468483278E-11, -3.0517226450451067446E-08, -2.5172644670688975051E-05, -1.5453977791786851041E-02, -7.0935347449210549190, -2.4125195876041896775E+03, -5.9545626019847898221E+05, -1.0313066708737980747E+08, -1.1912746104985237192E+10, -8.4925101247114157499E+11, -3.2940087627407749166E+13, -5.5050369673018427753E+14, -2.2335582639474375249E+15 }; double pp[8] = { -3.9843750000000000000E-01, 2.9205384596336793945, -2.4708469169133954315, 4.7914889422856814203E-01, -3.7384991926068969150E-03, -2.6801520353328635310E-03, 9.9168777670983678974E-05, -2.1877128189032726730E-06 }; double q[5] = { -3.7277560179962773046E+03, 6.5158506418655165707E+06, -6.5626560740833869295E+09, 3.7604188704092954661E+12, -9.7087946179594019126E+14 }; double qq[7] = { -3.1446690275135491500E+01, 8.5539563258012929600E+01, -6.0228002066743340583E+01, 1.3982595353892851542E+01, -1.1151759188741312645, 3.2547697594819615062E-02, -5.5194330231005480228E-04 }; double rec15 = 6.6666666666666666666E-02; double sump; double sumq; double value; double x; double xmax = 91.9; double xsmall = 2.98E-08; double xx; x = r8_abs ( arg ); if ( x < xsmall ) { value = 1.0; } else if ( x < 15.0 ) { // // XSMALL <= ABS(ARG) < 15.0 // xx = x * x; sump = p[0]; for ( i = 1; i < 15; i++ ) { sump = sump * xx + p[i]; } xx = xx - 225.0; sumq = (((( xx + q[0] ) * xx + q[1] ) * xx + q[2] ) * xx + q[3] ) * xx + q[4]; value = sump / sumq; } else if ( 15.0 <= x ) { if ( xmax < x ) { value = r8_huge ( ); } else { // // 15.0 <= ABS(ARG) // xx = 1.0 / x - rec15; sump = (((((( pp[0] * xx + pp[1] ) * xx + pp[2] ) * xx + pp[3] ) * xx + pp[4] ) * xx + pp[5] ) * xx + pp[6] ) * xx + pp[7]; sumq = (((((( xx + qq[0] ) * xx + qq[1] ) * xx + qq[2] ) * xx + qq[3] ) * xx + qq[4] ) * xx + qq[5] ) * xx + qq[6]; value = sump / sumq; // // Calculation reformulated to avoid premature overflow. // if ( x <= xmax - 15.0 ) { a = exp ( x ); b = 1.0; } else { a = exp ( x - 40.0 ); b = exp40; } value = ( ( value * a - pp[0] * a ) / sqrt ( x ) ) * b; } } return value; } //****************************************************************************80 void bessel_i0_values ( int &n_data, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // BESSEL_I0_VALUES returns some values of the I0 Bessel function. // // Discussion: // // The modified Bessel functions In(Z) and Kn(Z) are solutions of // the differential equation // // Z^2 W'' + Z * W' - ( Z^2 + N^2 ) * W = 0. // // The modified Bessel function I0(Z) corresponds to N = 0. // // In Mathematica, the function can be evaluated by: // // BesselI[0,x] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 20 static double fx_vec[N_MAX] = { 0.1000000000000000E+01, 0.1010025027795146E+01, 0.1040401782229341E+01, 0.1092045364317340E+01, 0.1166514922869803E+01, 0.1266065877752008E+01, 0.1393725584134064E+01, 0.1553395099731217E+01, 0.1749980639738909E+01, 0.1989559356618051E+01, 0.2279585302336067E+01, 0.3289839144050123E+01, 0.4880792585865024E+01, 0.7378203432225480E+01, 0.1130192195213633E+02, 0.1748117185560928E+02, 0.2723987182360445E+02, 0.6723440697647798E+02, 0.4275641157218048E+03, 0.2815716628466254E+04 }; static double x_vec[N_MAX] = { 0.00E+00, 0.20E+00, 0.40E+00, 0.60E+00, 0.80E+00, 0.10E+01, 0.12E+01, 0.14E+01, 0.16E+01, 0.18E+01, 0.20E+01, 0.25E+01, 0.30E+01, 0.35E+01, 0.40E+01, 0.45E+01, 0.50E+01, 0.60E+01, 0.80E+01, 0.10E+02 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; x = 0.0; fx = 0.0; } else { x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double bessel_i1 ( double arg ) //****************************************************************************80 // // Purpose: // // BESSEL_I1 evaluates the Bessel I function of order I. // // Discussion: // // The main computation evaluates slightly modified forms of // minimax approximations generated by Blair and Edwards. // This transportable program is patterned after the machine-dependent // FUNPACK packet NATSI1, but cannot match that version for efficiency // or accuracy. This version uses rational functions that theoretically // approximate I-SUB-1(X) to at least 18 significant decimal digits. // The accuracy achieved depends on the arithmetic system, the compiler, // the intrinsic functions, and proper selection of the machine-dependent // constants. // // Machine-dependent constants: // // beta = Radix for the floating-point system. // maxexp = Smallest power of beta that overflows. // XMAX = Largest argument acceptable to BESI1; Solution to // equation: // EXP(X) * (1-3/(8*X)) / SQRT(2*PI*X) = beta**maxexp // // // Approximate values for some important machines are: // // beta maxexp XMAX // // CRAY-1 (S.P.) 2 8191 5682.810 // Cyber 180/855 // under NOS (S.P.) 2 1070 745.894 // IEEE (IBM/XT, // SUN, etc.) (S.P.) 2 128 91.906 // IEEE (IBM/XT, // SUN, etc.) (D.P.) 2 1024 713.987 // IBM 3033 (D.P.) 16 63 178.185 // VAX (S.P.) 2 127 91.209 // VAX D-Format (D.P.) 2 127 91.209 // VAX G-Format (D.P.) 2 1023 713.293 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 October 2004 // // Author: // // Original FORTRAN77 version by William Cody, Laura Stoltz, // C++ version by John Burkardt. // // Reference: // // Blair, Edwards, // Chalk River Report AECL-4928, // Atomic Energy of Canada, Limited, // October, 1974. // // Parameters: // // Input, double ARG, the argument. // // Output, double BESSEL_I1, the value of the Bessel // I1 function. // { double a; double b; double exp40 = 2.353852668370199854E+17; double forty = 40.0; double half = 0.5; int j; double one = 1.0; double one5 = 15.0; double p[15] = { -1.9705291802535139930E-19, -6.5245515583151902910E-16, -1.1928788903603238754E-12, -1.4831904935994647675E-09, -1.3466829827635152875E-06, -9.1746443287817501309E-04, -4.7207090827310162436E-01, -1.8225946631657315931E+02, -5.1894091982308017540E+04, -1.0588550724769347106E+07, -1.4828267606612366099E+09, -1.3357437682275493024E+11, -6.9876779648010090070E+12, -1.7732037840791591320E+14, -1.4577180278143463643E+15 }; double pbar = 3.98437500E-01; double pp[8] = { -6.0437159056137600000E-02, 4.5748122901933459000E-01, -4.2843766903304806403E-01, 9.7356000150886612134E-02, -3.2457723974465568321E-03, -3.6395264712121795296E-04, 1.6258661867440836395E-05, -3.6347578404608223492E-07 }; double q[5] = { -4.0076864679904189921E+03, 7.4810580356655069138E+06, -8.0059518998619764991E+09, 4.8544714258273622913E+12, -1.3218168307321442305E+15 }; double qq[6] = { -3.8806586721556593450, 3.2593714889036996297, -8.5017476463217924408E-01, 7.4212010813186530069E-02, -2.2835624489492512649E-03, 3.7510433111922824643E-05 }; double rec15 = 6.6666666666666666666E-02; double sump; double sumq; double two25 = 225.0; double value; double x; double xmax = 713.987; double xx; double zero = 0.0; x = r8_abs ( arg ); // // ABS(ARG) < EPSILON ( ARG ) // if ( x < r8_epsilon ( ) ) { value = half * x; } // // EPSILON ( ARG ) <= ABS(ARG) < 15.0 // else if ( x < one5 ) { xx = x * x; sump = p[0]; for ( j = 1; j < 15; j++ ) { sump = sump * xx + p[j]; } xx = xx - two25; sumq = (((( xx + q[0] ) * xx + q[1] ) * xx + q[2] ) * xx + q[3] ) * xx + q[4]; value = ( sump / sumq ) * x; } else if ( xmax < x ) { value = r8_huge ( ); } // // 15.0 <= ABS(ARG) // else { xx = one / x - rec15; sump = (((((( pp[0] * xx + pp[1] ) * xx + pp[2] ) * xx + pp[3] ) * xx + pp[4] ) * xx + pp[5] ) * xx + pp[6] ) * xx + pp[7]; sumq = ((((( xx + qq[0] ) * xx + qq[1] ) * xx + qq[2] ) * xx + qq[3] ) * xx + qq[4] ) * xx + qq[5]; value = sump / sumq; if ( xmax - one5 < x ) { a = exp ( x - forty ); b = exp40; } else { a = exp ( x ); b = one; } value = ( ( value * a + pbar * a ) / sqrt ( x ) ) * b; } if ( arg < zero ) { value = -value; } return value; } //****************************************************************************80 void bessel_i1_values ( int &n_data, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // BESSEL_I1_VALUES returns some values of the I1 Bessel function. // // Discussion: // // The modified Bessel functions In(Z) and Kn(Z) are solutions of // the differential equation // // Z^2 W'' + Z * W' - ( Z^2 + N^2 ) * W = 0. // // In Mathematica, the function can be evaluated by: // // BesselI[1,x] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 20 static double fx_vec[N_MAX] = { 0.0000000000000000E+00, 0.1005008340281251E+00, 0.2040267557335706E+00, 0.3137040256049221E+00, 0.4328648026206398E+00, 0.5651591039924850E+00, 0.7146779415526431E+00, 0.8860919814143274E+00, 0.1084810635129880E+01, 0.1317167230391899E+01, 0.1590636854637329E+01, 0.2516716245288698E+01, 0.3953370217402609E+01, 0.6205834922258365E+01, 0.9759465153704450E+01, 0.1538922275373592E+02, 0.2433564214245053E+02, 0.6134193677764024E+02, 0.3998731367825601E+03, 0.2670988303701255E+04 }; static double x_vec[N_MAX] = { 0.00E+00, 0.20E+00, 0.40E+00, 0.60E+00, 0.80E+00, 0.10E+01, 0.12E+01, 0.14E+01, 0.16E+01, 0.18E+01, 0.20E+01, 0.25E+01, 0.30E+01, 0.35E+01, 0.40E+01, 0.45E+01, 0.50E+01, 0.60E+01, 0.80E+01, 0.10E+02 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; x = 0.0; fx = 0.0; } else { x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 void bessel_ix_values ( int &n_data, double &nu, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // BESSEL_IX_VALUES returns some values of the Ix Bessel function. // // Discussion: // // This set of data considers the less common case in which the // index of the Bessel function In is actually not an integer. // We may suggest this case by occasionally replacing the symbol // "In" by "Ix". // // The modified Bessel functions In(Z) and Kn(Z) are solutions of // the differential equation // // Z^2 W'' + Z * W' - ( Z^2 + N^2 ) * W = 0. // // In Mathematica, the function can be evaluated by: // // BesselI[n,x] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 March 2007 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &NU, the order of the function. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 28 static double fx_vec[N_MAX] = { 0.3592084175833614E+00, 0.9376748882454876E+00, 2.046236863089055E+00, 3.053093538196718E+00, 4.614822903407601E+00, 26.47754749755907E+00, 2778.784603874571E+00, 4.327974627242893E+07, 0.2935253263474798E+00, 1.099473188633110E+00, 21.18444226479414E+00, 2500.906154942118E+00, 2.866653715931464E+20, 0.05709890920304825E+00, 0.3970270801393905E+00, 13.76688213868258E+00, 2028.512757391936E+00, 2.753157630035402E+20, 0.4139416015642352E+00, 1.340196758982897E+00, 22.85715510364670E+00, 2593.006763432002E+00, 2.886630075077766E+20, 0.03590910483251082E+00, 0.2931108636266483E+00, 11.99397010023068E+00, 1894.575731562383E+00, 2.716911375760483E+20 }; static double nu_vec[N_MAX] = { 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 1.50E+00, 1.50E+00, 1.50E+00, 1.50E+00, 1.50E+00, 2.50E+00, 2.50E+00, 2.50E+00, 2.50E+00, 2.50E+00, 1.25E+00, 1.25E+00, 1.25E+00, 1.25E+00, 1.25E+00, 2.75E+00, 2.75E+00, 2.75E+00, 2.75E+00, 2.75E+00 }; static double x_vec[N_MAX] = { 0.2E+00, 1.0E+00, 2.0E+00, 2.5E+00, 3.0E+00, 5.0E+00, 10.0E+00, 20.0E+00, 1.0E+00, 2.0E+00, 5.0E+00, 10.0E+00, 50.0E+00, 1.0E+00, 2.0E+00, 5.0E+00, 10.0E+00, 50.0E+00, 1.0E+00, 2.0E+00, 5.0E+00, 10.0E+00, 50.0E+00, 1.0E+00, 2.0E+00, 5.0E+00, 10.0E+00, 50.0E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; nu = 0.0; x = 0.0; fx = 0.0; } else { nu = nu_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double beta ( double x, double y ) //****************************************************************************80 // // Purpose: // // BETA returns the value of the Beta function. // // Discussion: // // BETA(X,Y) = ( GAMMA(X) * GAMMA(Y) ) / GAMMA(X+Y) // // BETA(X,Y) = BETA(Y,X). // BETA(X,Y) = Integral ( 0 <= T <= 1 ) T^(X-1) (1-T)^(Y-1) dT. // BETA(X,Y) = GAMMA(X) * GAMMA(Y) / GAMMA(X+Y) // // Both X and Y must be greater than 0. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 May 2003 // // Author: // // John Burkardt // // Parameters: // // Input, double X, Y, the two parameters that define the Beta function. // X and Y must be greater than 0. // // Output, double BETA, the value of the Beta function. // { if ( x <= 0.0 || y <= 0.0 ) { cerr << "\n"; cerr << "BETA - Fatal error!\n"; cerr << " Both X and Y must be greater than 0.\n"; exit ( 1 ); } return ( exp ( gamma_log ( x ) + gamma_log ( y ) - gamma_log ( x + y ) ) ); } //****************************************************************************80 double beta_binomial_cdf ( int x, double a, double b, int c ) //****************************************************************************80 // // Purpose: // // BETA_BINOMIAL_CDF evaluates the Beta Binomial CDF. // // Discussion: // // A simple summing approach is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the CDF. // // Input, double A, B, parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input, int C, a parameter of the PDF. // 0 <= C. // // Output, double BETA_BINOMIAL_CDF, the value of the CDF. // { double cdf; double pdf; int y; if ( x < 0 ) { cdf = 0.0; } else if ( x < c ) { cdf = 0.0; for ( y = 0; y <= x; y++ ) { pdf = beta ( a + ( double ) y, b + ( double ) ( c - y) ) / ( ( double ) ( c + 1 ) * beta ( ( double ) ( y + 1 ), ( double ) ( c - y + 1 ) ) * beta ( a, b ) ); cdf = cdf + pdf; } } else if ( c <= x ) { cdf = 1.0; } return cdf; } //****************************************************************************80 int beta_binomial_cdf_inv ( double cdf, double a, double b, int c ) //****************************************************************************80 // // Purpose: // // BETA_BINOMIAL_CDF_INV inverts the Beta Binomial CDF. // // Discussion: // // A simple discrete approach is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input, int C, a parameter of the PDF. // 0 <= C. // // Output, int BETA_BINOMIAL_CDF_INV, the smallest X whose cumulative // density function is greater than or equal to CDF. // { double cum; double pdf; int x; int y; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "BETA_BINOMIAL_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } cum = 0.0; for ( y = 0; y <= c; y++ ) { pdf = beta ( a + ( double ) ( y ), b + ( double ) ( c - y ) ) / ( ( double ) ( c + 1 ) * beta ( ( double ) ( y + 1 ), ( double ) ( c - y + 1 ) ) * beta ( a, b ) ); cum = cum + pdf; if ( cdf <= cum ) { x = y; return x; } } x = c; return x; } //****************************************************************************80 bool beta_binomial_check ( double a, double b, int c ) //****************************************************************************80 // // Purpose: // // BETA_BINOMIAL_CHECK checks the parameters of the Beta Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input, int C, a parameter of the PDF. // 0 <= C. // // Output, bool BETA_BINOMIAL_CHECK, is TRUE if the parameters are legal. // { if ( a <= 0.0 ) { cerr << "\n"; cerr << "BETA_BINOMIAL_CHECK - Fatal error!\n"; cerr << " A <= 0.\n"; return false; } if ( b <= 0.0 ) { cerr << "\n"; cerr << "BETA_BINOMIAL_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } if ( c < 0 ) { cerr << "\n"; cerr << "BETA_BINOMIAL_CHECK - Fatal error!\n"; cerr << " C < 0.\n"; return false; } return true; } //****************************************************************************80 double beta_binomial_mean ( double a, double b, int c ) //****************************************************************************80 // // Purpose: // // BETA_BINOMIAL_MEAN returns the mean of the Beta Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input, int C, a parameter of the PDF. // 0 <= N. // // Output, double BETA_BINOMIAL_MEAN, the mean of the PDF. // { double mean; mean = ( double ) ( c ) * a / ( a + b ); return mean; } //****************************************************************************80 double beta_binomial_pdf ( int x, double a, double b, int c ) //****************************************************************************80 // // Purpose: // // BETA_BINOMIAL_PDF evaluates the Beta Binomial PDF. // // Discussion: // // PDF(X)(A,B,C) = Beta(A+X,B+C-X) // / ( (C+1) * Beta(X+1,C-X+1) * Beta(A,B) ) for 0 <= X <= C. // // This PDF can be reformulated as: // // The beta binomial probability density function for X successes // out of N trials is // // PDF2(X)( N, MU, THETA ) = // C(N,X) * Product ( 0 <= R <= X - 1 ) ( MU + R * THETA ) // * Product ( 0 <= R <= N - X - 1 ) ( 1 - MU + R * THETA ) // / Product ( 0 <= R <= N - 1 ) ( 1 + R * THETA ) // // where // // C(N,X) is the combinatorial coefficient; // MU is the expectation of the underlying Beta distribution; // THETA is a shape parameter. // // A THETA value of 0 ( or A+B --> Infinity ) results in the binomial // distribution: // // PDF2(X) ( N, MU, 0 ) = C(N,X) * MU^X * ( 1 - MU )^(N-X) // // Given A, B, C for PDF, then the equivalent PDF2 has: // // N = C // MU = A / ( A + B ) // THETA = 1 / ( A + B ) // // Given N, MU, THETA for PDF2, the equivalent PDF has: // // A = MU / THETA // B = ( 1 - MU ) / THETA // C = N // // BETA_BINOMIAL_PDF(X)(1,1,C) = UNIFORM_DISCRETE_PDF(X)(0,C-1) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the PDF. // // Input, double A, B, parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input, int C, a parameter of the PDF. // 0 <= C. // // Output, double BETA_BINOMIAL_PDF, the value of the PDF. // { double pdf; if ( x < 0 ) { pdf = 0.0; } else if ( x <= c ) { pdf = beta ( a + ( double ) ( x ), b + ( double ) ( c - x ) ) / ( ( double ) ( c + 1 ) * beta ( ( double ) ( x + 1 ), ( double ) ( c - x + 1 ) ) * beta ( a, b ) ); } else if ( c < x ) { pdf = 0.0; } return pdf; } //****************************************************************************80 int beta_binomial_sample ( double a, double b, int c, int &seed ) //****************************************************************************80 // // Purpose: // // BETA_BINOMIAL_SAMPLE samples the Beta Binomial CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input, int C, a parameter of the PDF. // 0 <= C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int BETA_BINOMIAL_SAMPLE, a sample of the PDF. // { double cdf; int x; cdf = r8_uniform_01 ( seed ); x = beta_binomial_cdf_inv ( cdf, a, b, c ); return x; } //****************************************************************************80 double beta_binomial_variance ( double a, double b, int c ) //****************************************************************************80 // // Purpose: // // BETA_BINOMIAL_VARIANCE returns the variance of the Beta Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input, int C, a parameter of the PDF. // 0 <= C. // // Output, double BETA_BINOMIAL_VARIANCE, the variance of the PDF. // { double variance; variance = ( ( double ) ( c ) * a * b ) * ( a + b + ( double ) ( c ) ) / ( ( a + b ) * ( a + b ) * ( a + b + 1.0 ) ); return variance; } //****************************************************************************80 double beta_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // BETA_CDF evaluates the Beta CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double BETA_CDF, the value of the CDF. // { double cdf; if ( x <= 0.0 ) { cdf = 0.0; } else if ( x <= 1.0 ) { cdf = beta_inc ( a, b, x ); } else { cdf = 1.0; } return cdf; } //****************************************************************************80 double beta_cdf_inv ( double cdf, double p, double q ) //****************************************************************************80 // // Purpose: // // BETA_CDF_INV inverts the Beta CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 April 2013 // // Author: // // Original FORTRAN77 version by GW Cran, KJ Martin, GE Thomas. // C++ version by John Burkardt. // // Reference: // // GW Cran, KJ Martin, GE Thomas, // Remark AS R19 and Algorithm AS 109: // A Remark on Algorithms AS 63: The Incomplete Beta Integral // and AS 64: Inverse of the Incomplete Beta Integeral, // Applied Statistics, // Volume 26, Number 1, 1977, pages 111-114. // // Parameters: // // Input, double CDF, the value of the incomplete Beta // function. 0 <= CDF <= 1. // // Input, double P, Q, the parameters of the incomplete // Beta function. // // Output, double BETA_CDF_INV, the argument of the Beta CDF which // produces the value CDF. // // Local Parameters: // // Local, double SAE, the most negative decimal exponent // which does not cause an underflow. // { double a; double acu; double adj; double beta_log; double fpu; double g; double h; int iex; bool indx; double pp; double prev; double qq; double r; double s; double sae = -37.0; double sq; double t; double tx; double value; double w; double xin; double y; double yprev; fpu = pow ( 10.0, sae ); // // Test for admissibility of parameters. // if ( p <= 0.0 ) { cerr << "\n"; cerr << "BETA_CDF_INV - Fatal error!\n"; cerr << " P <= 0.0\n"; value = -1.0; return value; } if ( q <= 0.0 ) { cerr << "\n"; cerr << "BETA_CDF_INV - Fatal error!\n"; cerr << " Q <= 0.0\n"; value = -1.0; return value; } if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "BETA_CDF_INV - Fatal error!\n"; cerr << " CDF < 0.0 or 1.0 < CDF\n"; value = -1.0; return value; } // // Return immediately if the answer is easy. // if ( cdf == 0.0 ) { value = 0.0; return value; } if ( cdf == 1.0 ) { value = 1.0; return value; } // // Change tail if necessary. // if ( 0.5 < cdf ) { a = 1.0 - cdf; pp = q; qq = p; indx = true; } else { a = cdf; pp = p; qq = q; indx = false; } // // Calculate the initial approximation. // r = sqrt ( - log ( a * a ) ); y = r - ( 2.30753 + 0.27061 * r ) / ( 1.0 + ( 0.99229 + 0.04481 * r ) * r ); if ( 1.0 < pp && 1.0 < qq ) { r = ( y * y - 3.0 ) / 6.0; s = 1.0 / ( pp + pp - 1.0 ); t = 1.0 / ( qq + qq - 1.0 ); h = 2.0 / ( s + t ); w = y * sqrt ( h + r ) / h - ( t - s ) * ( r + 5.0 / 6.0 - 2.0 / ( 3.0 * h ) ); value = pp / ( pp + qq * exp ( w + w ) ); } else { r = qq + qq; t = 1.0 / ( 9.0 * qq ); t = r * pow ( 1.0 - t + y * sqrt ( t ), 3 ); if ( t <= 0.0 ) { value = 1.0 - exp ( ( log ( ( 1.0 - a ) * qq ) + beta_log ) / qq ); } else { t = ( 4.0 * pp + r - 2.0 ) / t; if ( t <= 1.0 ) { value = exp ( ( log ( a * pp ) + beta_log ) / pp ); } else { value = 1.0 - 2.0 / ( t + 1.0 ); } } } // // Solve for X by a modified Newton-Raphson method. // r = 1.0 - pp; t = 1.0 - qq; yprev = 0.0; sq = 1.0; prev = 1.0; if ( value < 0.0001 ) { value = 0.0001; } if ( 0.9999 < value ) { value = 0.9999; } iex = r8_max ( - 5.0 / pp / pp - 1.0 / pow ( a, 0.2 ) - 13.0, sae ); acu = pow ( 10.0, iex ); for ( ; ; ) { y = beta_inc ( pp, qq, value ); xin = value; y = ( y - a ) * exp ( beta_log + r * log ( xin ) + t * log ( 1.0 - xin ) ); if ( y * yprev <= 0.0 ) { prev = r8_max ( sq, fpu ); } g = 1.0; for ( ; ; ) { for ( ; ; ) { adj = g * y; sq = adj * adj; if ( sq < prev ) { tx = value - adj; if ( 0.0 <= tx && tx <= 1.0 ) { break; } } g = g / 3.0; } if ( prev <= acu ) { if ( indx ) { value = 1.0 - value; } return value; } if ( y * y <= acu ) { if ( indx ) { value = 1.0 - value; } return value; } if ( tx != 0.0 && tx != 1.0 ) { break; } g = g / 3.0; } if ( tx == value ) { break; } value = tx; yprev = y; } if ( indx ) { value = 1.0 - value; } return value; } //****************************************************************************80 double beta_cdf_inv_old ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // BETA_CDF_INV_OLD inverts the Beta CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 October 2004 // // Author: // // Original FORTRAN77 version by Abernathy and Smith. // C++ version by John Burkardt. // // Reference: // // Abernathy, Smith, // Algorithm 724, // ACM Transactions on Mathematical Software, // Volume 19, Number 4, December 1993, pages 481-483. // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double BETA_CDF_INV, the argument of the CDF. // { # define MAXK 20 double bcoeff; double cdf_x; double d[MAXK * (MAXK-1)]; double error = 0.0001; double errapp = 0.01; int i; int j; int k; int loopct; double pdf_x; double q; double s1; double s2; double sum2; double t; double tail; double x; double xold; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "BETA_CDF_INV_OLD - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } // // Estimate the solution. // x = a / ( a + b ); xold = 0.0; loopct = 2; while ( errapp <= r8_abs ( ( x - xold ) / x ) && loopct != 0 ) { xold = x; loopct = loopct - 1; // // CDF_X = PROB { BETA(A,B) <= X }. // Q = ( CDF - CDF_X ) / PDF_X. // cdf_x = beta_cdf ( x, a, b ); pdf_x = beta_pdf ( x, a, b ); q = ( cdf - cdf_x ) / pdf_x; // // D(N,K) = C(N,K) * Q**(N+K-1) / (N-1)! // t = 1.0 - x; s1 = q * ( b - 1.0 ) / t; s2 = q * ( 1.0 - a ) / x; d[2-1+0*MAXK] = s1 + s2; tail = d[2-1+0*MAXK] * q / 2.0; x = x + q + tail; k = 3; while ( error < r8_abs ( tail / x ) && k <= MAXK ) { // // Find D(2,K-2). // s1 = q * ( ( double ) ( k ) - 2.0 ) * s1 / t; s2 = q * ( 2.0 - ( double ) ( k ) ) * s2 / x; d[2-1+(k-2)*MAXK] = s1 + s2; // // Find D(3,K-3), D(4,K-4), D(5,K-5), ... , D(K-1,1). // for ( i = 3; i <= k-1; i++ ) { sum2 = d[2-1+0*MAXK] * d[i-2+(k-i)*MAXK]; bcoeff = 1.0; for ( j = 1; j <= k - i; j++ ) { bcoeff = ( bcoeff * ( double ) ( k - i - j + 1 ) ) / ( double ) ( j ); sum2 = sum2 + bcoeff * d[2-1+j*MAXK] * d[i-2+(k-i-j)*MAXK]; } d[i-1+(k-i)*MAXK] = sum2 + d[i-2+(k-i+1)*MAXK] / ( double ) ( i - 1 ); } // // Compute D(K,0) and use it to expand the series. // d[k-1+0*MAXK] = d[2-1+0*MAXK] * d[k-2+0*MAXK] + d[k-2+1*MAXK] / ( double ) ( k - 1 ); tail = d[k-1+0*MAXK] * q / ( double ) ( k ); x = x + tail; // // Check for divergence. // if ( x <= 0.0 || 1.0 <= x ) { cerr << " \n"; cerr << "BETA_CDF_INV_OLD - Fatal error!\n"; cerr << " The series has diverged.\n"; x = -1.0; return x; } k = k + 1; } } return x; # undef MAXK } //****************************************************************************80 bool beta_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // BETA_CHECK checks the parameters of the Beta PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, bool BETA_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cerr << "\n"; cerr << "BETA_CHECK - Fatal error!\n"; cerr << " A <= 0.\n"; return false; } if ( b <= 0.0 ) { cerr << "\n"; cerr << "BETA_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 void beta_cdf_values ( int &n_data, double &a, double &b, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // BETA_CDF_VALUES returns some values of the Beta CDF. // // Discussion: // // The incomplete Beta function may be written // // BETA_INC(A,B,X) = Integral (0 <= t <= X) T^(A-1) * (1-T)^(B-1) dT // / Integral (0 <= t <= 1) T^(A-1) * (1-T)^(B-1) dT // // Thus, // // BETA_INC(A,B,0.0) = 0.0; // BETA_INC(A,B,1.0) = 1.0 // // The incomplete Beta function is also sometimes called the // "modified" Beta function, or the "normalized" Beta function // or the Beta CDF (cumulative density function. // // In Mathematica, the function can be evaluated by: // // BETA[X,A,B] / BETA[A,B] // // The function can also be evaluated by using the Statistics package: // // Needs["Statistics`ContinuousDistributions`"] // dist = BetaDistribution [ a, b ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 April 2013 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Karl Pearson, // Tables of the Incomplete Beta Function, // Cambridge University Press, 1968. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &A, &B, the parameters of the function. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 45 static double a_vec[N_MAX] = { 0.5E+00, 0.5E+00, 0.5E+00, 1.0E+00, 1.0E+00, 1.0E+00, 1.0E+00, 1.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 5.5E+00, 10.0E+00, 10.0E+00, 10.0E+00, 10.0E+00, 20.0E+00, 20.0E+00, 20.0E+00, 20.0E+00, 20.0E+00, 30.0E+00, 30.0E+00, 40.0E+00, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.2E+01, 0.3E+01, 0.4E+01, 0.5E+01, 1.30625, 1.30625, 1.30625 }; static double b_vec[N_MAX] = { 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 1.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 5.0E+00, 0.5E+00, 5.0E+00, 5.0E+00, 10.0E+00, 5.0E+00, 10.0E+00, 10.0E+00, 20.0E+00, 20.0E+00, 10.0E+00, 10.0E+00, 20.0E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.2E+01, 0.3E+01, 0.4E+01, 0.5E+01, 0.2E+01, 0.2E+01, 0.2E+01, 0.2E+01, 11.7562, 11.7562, 11.7562 }; static double fx_vec[N_MAX] = { 0.6376856085851985E-01, 0.2048327646991335E+00, 0.1000000000000000E+01, 0.0000000000000000E+00, 0.5012562893380045E-02, 0.5131670194948620E-01, 0.2928932188134525E+00, 0.5000000000000000E+00, 0.2800000000000000E-01, 0.1040000000000000E+00, 0.2160000000000000E+00, 0.3520000000000000E+00, 0.5000000000000000E+00, 0.6480000000000000E+00, 0.7840000000000000E+00, 0.8960000000000000E+00, 0.9720000000000000E+00, 0.4361908850559777E+00, 0.1516409096347099E+00, 0.8978271484375000E-01, 0.1000000000000000E+01, 0.5000000000000000E+00, 0.4598773297575791E+00, 0.2146816102371739E+00, 0.9507364826957875E+00, 0.5000000000000000E+00, 0.8979413687105918E+00, 0.2241297491808366E+00, 0.7586405487192086E+00, 0.7001783247477069E+00, 0.5131670194948620E-01, 0.1055728090000841E+00, 0.1633399734659245E+00, 0.2254033307585166E+00, 0.3600000000000000E+00, 0.4880000000000000E+00, 0.5904000000000000E+00, 0.6723200000000000E+00, 0.2160000000000000E+00, 0.8370000000000000E-01, 0.3078000000000000E-01, 0.1093500000000000E-01, 0.918884684620518, 0.21052977489419, 0.1824130512500673 }; static double x_vec[N_MAX] = { 0.01E+00, 0.10E+00, 1.00E+00, 0.00E+00, 0.01E+00, 0.10E+00, 0.50E+00, 0.50E+00, 0.10E+00, 0.20E+00, 0.30E+00, 0.40E+00, 0.50E+00, 0.60E+00, 0.70E+00, 0.80E+00, 0.90E+00, 0.50E+00, 0.90E+00, 0.50E+00, 1.00E+00, 0.50E+00, 0.80E+00, 0.60E+00, 0.80E+00, 0.50E+00, 0.60E+00, 0.70E+00, 0.80E+00, 0.70E+00, 0.10E+00, 0.20E+00, 0.30E+00, 0.40E+00, 0.20E+00, 0.20E+00, 0.20E+00, 0.20E+00, 0.30E+00, 0.30E+00, 0.30E+00, 0.30E+00, 0.225609, 0.0335568, 0.0295222 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; a = 0.0; b = 0.0; x = 0.0; fx = 0.0; } else { a = a_vec[n_data-1]; b = b_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double beta_inc ( double a, double b, double x ) //****************************************************************************80 // // Purpose: // // BETA_INC returns the value of the incomplete Beta function. // // Discussion: // // This calculation requires an iteration. In some cases, the iteration // may not converge rapidly, or may become inaccurate. // // BETA_INC(A,B,X) // // = Integral ( 0 <= T <= X ) T^(A-1) (1-T)^(B-1) dT // / Integral ( 0 <= T <= 1 ) T^(A-1) (1-T)^(B-1) dT // // = Integral ( 0 <= T <= X ) T^(A-1) (1-T)^(B-1) dT // / BETA(A,B) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // Original FORTRAN77 version by Majumder, Bhattacharjee. // C++ version by John Burkardt. // // Reference: // // Majumder, Bhattacharjee, // Algorithm AS63, // Applied Statistics, // 1973, volume 22, number 3. // // Parameters: // // Input, double A, B, the parameters of the function. // 0.0 < A, // 0.0 < B. // // Input, double X, the argument of the function. // Normally, 0.0 <= X <= 1.0. // // Output, double BETA_INC, the value of the function. // { double cx; int i; int it; int it_max = 1000; bool indx; int ns; double pp; double psq; double qq; double rx; double temp; double term; double tol = 1.0E-07; double value; double xx; if ( a <= 0.0 ) { cerr << "\n"; cerr << "BETA_INC - Fatal error!\n"; cerr << " A <= 0.\n"; exit ( 1 ); } if ( b <= 0.0 ) { cerr << "\n"; cerr << "BETA_INC - Fatal error!\n"; cerr << " B <= 0.\n"; exit ( 1 ); } if ( x <= 0.0 ) { value = 0.0; return value; } else if ( 1.0 <= x ) { value = 1.0; return value; } // // Change tail if necessary and determine S. // psq = a + b; if ( a < ( a + b ) * x ) { xx = 1.0 - x; cx = x; pp = b; qq = a; indx = true; } else { xx = x; cx = 1.0 - x; pp = a; qq = b; indx = false; } term = 1.0; i = 1; value = 1.0; ns = ( int ) ( qq + cx * ( a + b ) ); // // Use Soper's reduction formulas. // rx = xx / cx; temp = qq - ( double ) i; if ( ns == 0 ) { rx = xx; } it = 0; for ( ; ; ) { it = it + 1; if ( it_max < it ) { cerr << "\n"; cerr << "BETA_INC - Fatal error!\n"; cerr << " Maximum number of iterations exceeded!\n"; cerr << " IT_MAX = " << it_max << "\n"; exit ( 1 ); } term = term * temp * rx / ( pp + ( double ) ( i ) ); value = value + term; temp = r8_abs ( term ); if ( temp <= tol && temp <= tol * value ) { break; } i = i + 1; ns = ns - 1; if ( 0 <= ns ) { temp = qq - ( double ) i; if ( ns == 0 ) { rx = xx; } } else { temp = psq; psq = psq + 1.0; } } // // Finish calculation. // value = value * exp ( pp * log ( xx ) + ( qq - 1.0 ) * log ( cx ) ) / ( beta ( a, b ) * pp ); if ( indx ) { value = 1.0 - value; } return value; } //****************************************************************************80 void beta_inc_values ( int &n_data, double &a, double &b, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // BETA_INC_VALUES returns some values of the incomplete Beta function. // // Discussion: // // The incomplete Beta function may be written // // BETA_INC(A,B,X) = Integral (0 <= t <= X) T^(A-1) * (1-T)^(B-1) dT // / Integral (0 <= t <= 1) T^(A-1) * (1-T)^(B-1) dT // // Thus, // // BETA_INC(A,B,0.0) = 0.0; // BETA_INC(A,B,1.0) = 1.0 // // The incomplete Beta function is also sometimes called the // "modified" Beta function, or the "normalized" Beta function // or the Beta CDF (cumulative density function. // // In Mathematica, the function can be evaluated by: // // BETA[X,A,B] / BETA[A,B] // // The function can also be evaluated by using the Statistics package: // // Needs["Statistics`ContinuousDistributions`"] // dist = BetaDistribution [ a, b ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 April 2013 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Karl Pearson, // Tables of the Incomplete Beta Function, // Cambridge University Press, 1968. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &A, &B, the parameters of the function. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 45 static double a_vec[N_MAX] = { 0.5E+00, 0.5E+00, 0.5E+00, 1.0E+00, 1.0E+00, 1.0E+00, 1.0E+00, 1.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 5.5E+00, 10.0E+00, 10.0E+00, 10.0E+00, 10.0E+00, 20.0E+00, 20.0E+00, 20.0E+00, 20.0E+00, 20.0E+00, 30.0E+00, 30.0E+00, 40.0E+00, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.2E+01, 0.3E+01, 0.4E+01, 0.5E+01, 1.30625, 1.30625, 1.30625 }; static double b_vec[N_MAX] = { 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 1.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 5.0E+00, 0.5E+00, 5.0E+00, 5.0E+00, 10.0E+00, 5.0E+00, 10.0E+00, 10.0E+00, 20.0E+00, 20.0E+00, 10.0E+00, 10.0E+00, 20.0E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.2E+01, 0.3E+01, 0.4E+01, 0.5E+01, 0.2E+01, 0.2E+01, 0.2E+01, 0.2E+01, 11.7562, 11.7562, 11.7562 }; static double fx_vec[N_MAX] = { 0.6376856085851985E-01, 0.2048327646991335E+00, 0.1000000000000000E+01, 0.0000000000000000E+00, 0.5012562893380045E-02, 0.5131670194948620E-01, 0.2928932188134525E+00, 0.5000000000000000E+00, 0.2800000000000000E-01, 0.1040000000000000E+00, 0.2160000000000000E+00, 0.3520000000000000E+00, 0.5000000000000000E+00, 0.6480000000000000E+00, 0.7840000000000000E+00, 0.8960000000000000E+00, 0.9720000000000000E+00, 0.4361908850559777E+00, 0.1516409096347099E+00, 0.8978271484375000E-01, 0.1000000000000000E+01, 0.5000000000000000E+00, 0.4598773297575791E+00, 0.2146816102371739E+00, 0.9507364826957875E+00, 0.5000000000000000E+00, 0.8979413687105918E+00, 0.2241297491808366E+00, 0.7586405487192086E+00, 0.7001783247477069E+00, 0.5131670194948620E-01, 0.1055728090000841E+00, 0.1633399734659245E+00, 0.2254033307585166E+00, 0.3600000000000000E+00, 0.4880000000000000E+00, 0.5904000000000000E+00, 0.6723200000000000E+00, 0.2160000000000000E+00, 0.8370000000000000E-01, 0.3078000000000000E-01, 0.1093500000000000E-01, 0.918884684620518, 0.21052977489419, 0.1824130512500673 }; static double x_vec[N_MAX] = { 0.01E+00, 0.10E+00, 1.00E+00, 0.00E+00, 0.01E+00, 0.10E+00, 0.50E+00, 0.50E+00, 0.10E+00, 0.20E+00, 0.30E+00, 0.40E+00, 0.50E+00, 0.60E+00, 0.70E+00, 0.80E+00, 0.90E+00, 0.50E+00, 0.90E+00, 0.50E+00, 1.00E+00, 0.50E+00, 0.80E+00, 0.60E+00, 0.80E+00, 0.50E+00, 0.60E+00, 0.70E+00, 0.80E+00, 0.70E+00, 0.10E+00, 0.20E+00, 0.30E+00, 0.40E+00, 0.20E+00, 0.20E+00, 0.20E+00, 0.20E+00, 0.30E+00, 0.30E+00, 0.30E+00, 0.30E+00, 0.225609, 0.0335568, 0.0295222 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; a = 0.0; b = 0.0; x = 0.0; fx = 0.0; } else { a = a_vec[n_data-1]; b = b_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double beta_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // BETA_MEAN returns the mean of the Beta PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double BETA_MEAN, the mean of the PDF. // { double mean; mean = a / ( a + b ); return mean; } //****************************************************************************80 double beta_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // BETA_PDF evaluates the Beta PDF. // // Discussion: // // PDF(A,B;X) = X^(A-1) * (1-X)^(B-1) / BETA(A,B). // // A = B = 1 yields the Uniform distribution on [0,1]. // A = B = 1/2 yields the Arcsin distribution. // B = 1 yields the power function distribution. // A = B -> Infinity tends to the Normal distribution. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double BETA_PDF, the value of the PDF. // { double pdf; if ( x < 0.0 || 1.0 < x ) { pdf = 0.0; } else { pdf = pow ( x, ( a - 1.0 ) ) * pow ( ( 1.0 - x ), ( b - 1.0 ) ) / beta ( a, b ); } return pdf; } //****************************************************************************80 double beta_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // BETA_SAMPLE samples the Beta PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Reference: // // William Kennedy, James Gentle, // Algorithm BN, // Statistical Computing, // Dekker, 1980. // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double BETA_SAMPLE, a sample of the PDF. // { double mu; double stdev; double test; double u; double x; double y; mu = ( a - 1.0 ) / ( a + b - 2.0 ); stdev = 0.5 / sqrt ( a + b - 2.0 ); for ( ; ; ) { y = normal_01_sample ( seed ); x = mu + stdev * y; if ( x < 0.0 || 1.0 < x ) { continue; } u = r8_uniform_01 ( seed ); test = ( a - 1.0 ) * log ( x / ( a - 1.0 ) ) + ( b - 1.0 ) * log ( ( 1.0 - x ) / ( b - 1.0 ) ) + ( a + b - 2.0 ) * log ( a + b - 2.0 ) + 0.5 * y * y; if ( log ( u ) <= test ) { break; } } return x; } //****************************************************************************80 double beta_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // BETA_VARIANCE returns the variance of the Beta PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double BETA_VARIANCE, the variance of the PDF. // { double variance; variance = ( a * b ) / ( ( a + b ) * ( a + b ) * ( 1.0 + a + b ) ); return variance; } //****************************************************************************80 double binomial_cdf ( double x, int a, double b ) //****************************************************************************80 // // Purpose: // // BINOMIAL_CDF evaluates the Binomial CDF. // // Discussion: // // CDF(X)(A,B) is the probability of at most X successes in A trials, // given that the probability of success on a single trial is B. // // A sequence of trials with fixed probability of success on // any trial is known as a sequence of Bernoulli trials. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the desired number of successes. // 0 <= X <= A. // // Input, int A, the number of trials. // 1 <= A. // // Input, double B, the probability of success on one trial. // 0.0 <= B <= 1.0. // // Output, double CDF, the value of the CDF. // { int cnk; double cdf; int j; double pr; if ( x < 0 ) { cdf = 0.0; } else if ( a <= x ) { cdf = 1.0; } else if ( b == 0.0 ) { cdf = 1.0; } else if ( b == 1.0 ) { cdf = 0.0; } else { cdf = 0.0; for ( j = 0; j <= x; j++ ) { cnk = binomial_coef ( a, j ); pr = ( double ) ( cnk ) * pow ( b, j ) * pow ( ( 1.0 - b ), ( a - j ) ); cdf = cdf + pr; } } return cdf; } //****************************************************************************80 void binomial_cdf_values ( int &n_data, int &a, double &b, int &x, double &fx ) //****************************************************************************80 // // Purpose: // // BINOMIAL_CDF_VALUES returns some values of the binomial CDF. // // Discussion: // // CDF(X)(A,B) is the probability of at most X successes in A trials, // given that the probability of success on a single trial is B. // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`DiscreteDistributions`] // dist = BinomialDistribution [ n, p ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Daniel Zwillinger, // CRC Standard Mathematical Tables and Formulae, // 30th Edition, CRC Press, 1996, pages 651-652. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, int &A, a parameter of the function. // // Output, double &B, a parameter of the function. // // Output, int &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 17 static int a_vec[N_MAX] = { 2, 2, 2, 2, 2, 4, 4, 4, 4, 10, 10, 10, 10, 10, 10, 10, 10 }; static double b_vec[N_MAX] = { 0.05E+00, 0.05E+00, 0.05E+00, 0.50E+00, 0.50E+00, 0.25E+00, 0.25E+00, 0.25E+00, 0.25E+00, 0.05E+00, 0.10E+00, 0.15E+00, 0.20E+00, 0.25E+00, 0.30E+00, 0.40E+00, 0.50E+00 }; static double fx_vec[N_MAX] = { 0.9025000000000000E+00, 0.9975000000000000E+00, 0.1000000000000000E+01, 0.2500000000000000E+00, 0.7500000000000000E+00, 0.3164062500000000E+00, 0.7382812500000000E+00, 0.9492187500000000E+00, 0.9960937500000000E+00, 0.9999363101685547E+00, 0.9983650626000000E+00, 0.9901259090013672E+00, 0.9672065024000000E+00, 0.9218730926513672E+00, 0.8497316674000000E+00, 0.6331032576000000E+00, 0.3769531250000000E+00 }; static int x_vec[N_MAX] = { 0, 1, 2, 0, 1, 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; a = 0; b = 0.0; x = 0; fx = 0.0; } else { a = a_vec[n_data-1]; b = b_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 int binomial_cdf_inv ( double cdf, int a, double b ) //****************************************************************************80 // // Purpose: // // BINOMIAL_CDF_INV inverts the Binomial CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, int A, the number of trials. // 1 <= A. // // Input, double B, the probability of success on one trial. // 0.0 <= B <= 1.0. // // Output, int BINOMIAL_CDF_INV, the corresponding argument. // { double cdf2; double pdf; int x; int x2; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "BINOMIAL_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } cdf2 = 0.0; for ( x2 = 0; x2 <= a; x2++ ) { pdf = binomial_pdf ( x2, a, b ); cdf2 = cdf2 + pdf; if ( cdf <= cdf2 ) { x = x2; return x; } } return x; } //****************************************************************************80 bool binomial_check ( int a, double b ) //****************************************************************************80 // // Purpose: // // BINOMIAL_CHECK checks the parameter of the Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of trials. // 1 <= A. // // Input, double B, the probability of success on one trial. // 0.0 <= B <= 1.0. // // Output, bool BINOMIAL_CHECK, is true if the parameters are legal. // { if ( a < 1 ) { cerr << "\n"; cerr << "BINOMIAL_CHECK - Fatal error!\n"; cerr << " A < 1.\n"; return false; } if ( b < 0.0 || 1.0 < b ) { cerr << "\n"; cerr << "BINOMIAL_CHECK - Fatal error!\n"; cerr << " B < 0 or 1 < B.\n"; return false; } return true; } //****************************************************************************80 int binomial_coef ( int n, int k ) //****************************************************************************80 // // Purpose: // // BINOMIAL_COEF computes the Binomial coefficient C(N,K). // // Discussion: // // The value is calculated in such a way as to avoid overflow and // roundoff. The calculation is done in integer arithmetic. // // CNK = C(N,K) = N! / ( K! * (N-K)! ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Reference: // // M L Wolfson, H V Wright, // Combinatorial of M Things Taken N at a Time, // ACM Algorithm 160, // Communications of the ACM, // April, 1963. // // Parameters: // // Input, int N, K, are the values of N and K. // // Output, int CNK, the number of combinations of N // things taken K at a time. // { int cnk; int i; int mn; int mx; mn = i4_min ( k, n-k ); if ( mn < 0 ) { cnk = 0; } else if ( mn == 0 ) { cnk = 1; } else { mx = i4_max ( k, n-k ); cnk = mx + 1; for ( i = 2; i <= mn; i++ ) { cnk = ( cnk * ( mx + i ) ) / i; } } return cnk; } //****************************************************************************80 double binomial_coef_log ( int n, int k ) //****************************************************************************80 // // Purpose: // // BINOMIAL_COEF_LOG computes the logarithm of the Binomial coefficient. // // Discussion: // // CNK_LOG = LOG ( C(N,K) ) = LOG ( N! / ( K! * (N-K)! ) ). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, K, are the values of N and K. // // Output, double CNK_LOG, the logarithm of C(N,K). // { double cnk_log; cnk_log = factorial_log ( n ) - factorial_log ( k ) - factorial_log ( n - k ); return cnk_log; } //****************************************************************************80 double binomial_mean ( int a, double b ) //****************************************************************************80 // // Purpose: // // BINOMIAL_MEAN returns the mean of the Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of trials. // 1 <= A. // // Input, double B, the probability of success on one trial. // 0.0 <= B <= 1.0. // // Output, double BINOMIAL_MEAN, the expected value of the number of // successes in A trials. // { double mean; mean = ( double ) ( a ) * b; return mean; } //****************************************************************************80 double binomial_pdf ( int x, int a, double b ) //****************************************************************************80 // // Purpose: // // BINOMIAL_PDF evaluates the Binomial PDF. // // Discussion: // // PDF(A,B;X) is the probability of exactly X successes in A trials, // given that the probability of success on a single trial is B. // // PDF(A,B;X) = C(N,X) * B^X * ( 1.0 - B )^( A - X ) // // Binomial_PDF(1,B;X) = Bernoulli_PDF(B;X). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the desired number of successes. // 0 <= X <= A. // // Input, int A, the number of trials. // 1 <= A. // // Input, double B, the probability of success on one trial. // 0.0 <= B <= 1.0. // // Output, double BINOMIAL_PDF, the value of the PDF. // { int cnk; double pdf; if ( a < 1 ) { pdf = 0.0; } else if ( x < 0 || a < x ) { pdf = 0.0; } else if ( b == 0.0 ) { if ( x == 0 ) { pdf = 1.0; } else { pdf = 0.0; } } else if ( b == 1.0 ) { if ( x == a ) { pdf = 1.0; } else { pdf = 0.0; } } else { cnk = binomial_coef ( a, x ); pdf = ( double ) ( cnk ) * pow ( b, x ) * pow ( ( 1.0 - b ), ( a - x ) ); } return pdf; } //****************************************************************************80 int binomial_sample ( int a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // BINOMIAL_SAMPLE samples the Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Reference: // // William Kennedy, James Gentle, // Algorithm BU, // Statistical Computing, // Dekker, 1980. // // Parameters: // // Input, int A, the number of trials. // 1 <= A. // // Input, double B, the probability of success on one trial. // 0.0 <= B <= 1.0. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int BINOMIAL_SAMPLE, a sample of the PDF. // { int i; double u; int x; x = 0; for ( i = 1; i <= a; i++ ) { u = r8_uniform_01 ( seed ); if ( u <= b ) { x = x + 1; } } return x; } //****************************************************************************80 double binomial_variance ( int a, double b ) //****************************************************************************80 // // Purpose: // // BINOMIAL_VARIANCE returns the variance of the Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 January 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of trials. // 1 <= A. // // Input, double B, the probability of success on one trial. // 0.0 <= B <= 1.0. // // Output, double BINOMIAL_VARIANCE, the variance of the PDF. // { double variance; variance = ( double ) ( a ) * b * ( 1.0 - b ); return variance; } //****************************************************************************80 double birthday_cdf ( int n ) //****************************************************************************80 // // Purpose: // // BIRTHDAY_CDF returns the Birthday Concurrence CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 August 2006 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of people whose birthdays have been // disclosed. // // Output, double BIRTHDAY_CDF, the probability that at least // two of the N people have matching birthays.. // { double cdf; int i; if ( n < 1 ) { cdf = 0.0; return cdf; } else if ( 365 < n ) { cdf = 1.0; return cdf; } // // Compute the probability that N people have distinct birthdays. // cdf = 1.0; for ( i = 1; i <= n; i++ ) { cdf = cdf * ( double ) ( 365 + 1 - i ) / 365.0; } // // Compute the probability that it is NOT the case that N people // have distinct birthdays. This is the cumulative probability // that person 2 matches person 1, or person 3 matches 1 or 2, // etc. // cdf = 1.0 - cdf; return cdf; } //****************************************************************************80 int birthday_cdf_inv ( double cdf ) //****************************************************************************80 // // Purpose: // // BIRTHDAY_CDF_INV inverts the Birthday Concurrence CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 August 2006 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the probability that at least // two of the N people have matching birthays.. // // Output, int BIRTHDAY_CDF_INV, the corresponding number of people whose // birthdays need to be disclosed. // { double cdf_not; int i; int n; if ( cdf <= 0.0 ) { n = 0; return n; } else if ( 1.0 <= cdf ) { n = 365; return n; } // // Compute the probability that N people have distinct birthdays. // cdf_not = 1.0; for ( i = 1; i <= 365; i++ ) { cdf_not = cdf_not * ( double ) ( 365 + 1 - i ) / 365.0; if ( cdf <= 1.0 - cdf_not ) { n = i; return n; } } n = 365; return n; } //****************************************************************************80 double birthday_pdf ( int n ) //****************************************************************************80 // // Purpose: // // BIRTHDAY_PDF returns the Birthday Concurrence PDF. // // Discussion: // // The probability is the probability that the N-th person is the // first one to match a birthday with someone earlier. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 August 2006 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of people whose birthdays have been // disclosed. // // Output, double BIRTHDAY_PDF, the probability that the N-th person // is the first to match a birthday with someone earlier. // { int i; double pdf; if ( n < 1 || 365 < n ) { pdf = 0.0; return pdf; } pdf = 1.0; // // Compute the probability that N-1 people have distinct birthdays. // for ( i = 1; i <= n-1; i++ ) { pdf = pdf * ( double ) ( 365 + 1 - i ) / 365.0; } // // Compute the probability that person N has one of those N-1 birthdays. // pdf = pdf * ( double ) ( n - 1 ) / 365.0; return pdf; } //****************************************************************************80 double bradford_cdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // BRADFORD_CDF evaluates the Bradford CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, C, the parameters of the PDF. // A < B, // 0.0 < C. // // Output, double BRADFORD_CDF, the value of the CDF. // { double cdf; if ( x <= a ) { cdf = 0.0; } else if ( x <= b ) { cdf = log ( 1.0 + c * ( x - a ) / ( b - a ) ) / log ( c + 1.0 ); } else if ( b < x ) { cdf = 1.0; } return cdf; } //****************************************************************************80 double bradford_cdf_inv ( double cdf, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // BRADFORD_CDF_INV inverts the Bradford CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, C, the parameters of the PDF. // A < B, // 0.0 < C. // // Output, double BRADFORD_CDF_INV, the corresponding argument of the CDF. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "BRADFORD_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf <= 0.0 ) { x = a; } else if ( cdf < 1.0 ) { x = a + ( b - a ) * ( pow ( ( c + 1.0 ), cdf ) - 1.0 ) / c; } else if ( 1.0 <= cdf ) { x = b; } return x; } //****************************************************************************80 bool bradford_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // BRADFORD_CHECK checks the parameters of the Bradford PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // A < B, // 0.0 < C. // // Output, bool BRADFORD_CHECK, is true if the parameters are legal. // { if ( b <= a ) { cerr << " \n"; cerr << "BRADFORD_CHECK - Fatal error!\n"; cerr << " B <= A.\n"; return false; } if ( c <= 0.0 ) { cerr << " \n"; cerr << "BRADFORD_CHECK - Fatal error!\n"; cerr << " C <= 0.\n"; return false; } return true; } //****************************************************************************80 double bradford_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // BRADFORD_MEAN returns the mean of the Bradford PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // A < B, // 0.0 < C. // // Output, double BRADFORD_MEAN, the mean of the PDF. // { double mean; mean = ( c * ( b - a ) + log ( c + 1.0 ) * ( a * ( c + 1.0 ) - b ) ) / ( c * log ( c + 1.0 ) ); return mean; } //****************************************************************************80 double bradford_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // BRADFORD_PDF evaluates the Bradford PDF. // // Discussion: // // PDF(A,B,C;X) = C / ( ( C * ( X - A ) + B - A ) * log ( C + 1 ) ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, C, the parameters of the PDF. // A < B, // 0.0 < C. // // Output, double BRADFORD_PDF, the value of the PDF. // { double pdf; if ( x <= a ) { pdf = 0.0; } else if ( x <= b ) { pdf = c / ( ( c * ( x - a ) + b - a ) * log ( c + 1.0 ) ); } else if ( b < x ) { pdf = 0.0; } return pdf; } //****************************************************************************80 double bradford_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // BRADFORD_SAMPLE samples the Bradford PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // A < B, // 0.0 < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double BRADFORD_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = a + ( b - a ) * ( pow ( ( c + 1.0 ), cdf ) - 1.0 ) / c; return x; } //****************************************************************************80 double bradford_variance ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // BRADFORD_VARIANCE returns the variance of the Bradford PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // A < B, // 0.0 < C. // // Output, double BRADFORD_VARIANCE, the variance of the PDF. // { double variance; variance = ( b - a ) * ( b - a ) * ( c * ( log ( c + 1.0 ) - 2.0 ) + 2.0 * log ( c + 1.0 ) ) / ( 2.0 * c * pow ( ( log ( c + 1.0 ) ), 2 ) ); return variance; } //****************************************************************************80 double buffon_laplace_pdf ( double a, double b, double l ) //****************************************************************************80 // // Purpose: // // BUFFON_LAPLACE_PDF evaluates the Buffon-Laplace PDF. // // Discussion: // // In the Buffon-Laplace needle experiment, we suppose that the plane has // been tiled into a grid of rectangles of width A and height B, and that a // needle of length L is dropped "at random" onto this grid. // // We may assume that one end, the "eye" of the needle falls at the point // (X1,Y1), taken uniformly at random in the cell [0,A]x[0,B]. // // ANGLE, the angle that the needle makes is taken to be uniformly random. // The point of the needle, (X2,Y2), therefore lies at // // (X2,Y2) = ( X1+L*cos(ANGLE), Y1+L*sin(ANGLE) ) // // The needle will have crossed at least one grid line if any of the // following are true: // // X2 <= 0, A <= X2, Y2 <= 0, B <= Y2. // // If L is larger than sqrt ( A*A + B*B ), then the needle will // cross every time, and the computation is uninteresting. However, if // L is smaller than this limit, then the probability of a crossing on // a single trial is // // P(L,A,B) = ( 2 * L * ( A + B ) - L * L ) / ( PI * A * B ) // // and therefore, a record of the number of hits for a given number of // trials can be used as a very roundabout way of estimating PI. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 February 2007 // // Author: // // John Burkardt // // Reference: // // Sudarshan Raghunathan, // Making a Supercomputer Do What You Want: High Level Tools for // Parallel Programming, // Computing in Science and Engineering, // Volume 8, Number 5, September/October 2006, pages 70-80. // // Parameters: // // Input, double A, B, the horizontal and vertical dimensions // of each cell of the grid. 0 <= A, 0 <= B. // // Input, double L, the length of the needle. // 0 <= L <= min ( A, B ). // // Output, double BUFFON_LAPLACE_PDF, the Buffon-Laplace PDF. // { double pdf; double pi = 3.141592653589793238462643; if ( a < 0.0 ) { cerr << "\n"; cerr << "BUFFON_LAPLACE_PDF - Fatal error!\n"; cerr << " Input A < 0.\n"; exit ( 1 ); } else if ( a == 0.0 ) { pdf = 1.0; return pdf; } if ( b < 0.0 ) { cerr << "\n"; cerr << "BUFFON_LAPLACE_PDF - Fatal error!\n"; cerr << " Input B < 0.\n"; exit ( 1 ); } else if ( b == 0.0 ) { pdf = 1.0; return pdf; } if ( l < 0.0 ) { cerr << "\n"; cerr << "BUFFON_LAPLACE_PDF - Fatal error!\n"; cerr << " Input L < 0.\n"; exit ( 1 ); } else if ( l == 0.0 ) { pdf = 0.0; return pdf; } else if ( r8_min ( a, b ) < l ) { cerr << "\n"; cerr << "BUFFON_LAPLACE_PDF - Fatal error!\n"; cerr << " min ( A, B ) < L.\n"; exit ( 1 ); } pdf = ( 2.0 * l * ( a + b ) - l * l ) / ( pi * a * b ); return pdf; } //****************************************************************************80 int buffon_laplace_simulate ( double a, double b, double l, int trial_num ) //****************************************************************************80 // // Purpose: // // BUFFON_LAPLACE_SIMULATE simulates a Buffon-Laplace needle experiment. // // Discussion: // // In the Buffon-Laplace needle experiment, we suppose that the plane has // been tiled into a grid of rectangles of width A and height B, and that a // needle of length L is dropped "at random" onto this grid. // // We may assume that one end, the "eye" of the needle falls at the point // (X1,Y1), taken uniformly at random in the cell [0,A]x[0,B]. // // ANGLE, the angle that the needle makes is taken to be uniformly random. // The point of the needle, (X2,Y2), therefore lies at // // (X2,Y2) = ( X1+L*cos(ANGLE), Y1+L*sin(ANGLE) ) // // The needle will have crossed at least one grid line if any of the // following are true: // // X2 <= 0, A <= X2, Y2 <= 0, B <= Y2. // // This routine simulates the tossing of the needle, and returns the number // of times that the needle crossed at least one grid line. // // If L is larger than sqrt ( A*A + B*B ), then the needle will // cross every time, and the computation is uninteresting. However, if // L is smaller than this limit, then the probability of a crossing on // a single trial is // // P(L,A,B) = ( 2 * L * ( A + B ) - L * L ) / ( PI * A * B ) // // and therefore, a record of the number of hits for a given number of // trials can be used as a very roundabout way of estimating PI. // (Particularly roundabout, since we actually will use a good value of // PI in order to pick the random angles//) // // Since this routine invokes the C++ random number generator, // the user should initialize the random number generator, particularly // if it is desired to control whether the sequence is to be varied // or repeated. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 February 2007 // // Author: // // John Burkardt // // Reference: // // Sudarshan Raghunathan, // Making a Supercomputer Do What You Want: High Level Tools for // Parallel Programming, // Computing in Science and Engineering, // Volume 8, Number 5, September/October 2006, pages 70-80. // // Parameters: // // Input, double A, B, the horizontal and vertical dimensions // of each cell of the grid. 0 <= A, 0 <= B. // // Input, double L, the length of the needle. // 0 <= L <= min ( A, B ). // // Input, int TRIAL_NUM, the number of times the needle is // to be dropped onto the grid. // // Output, int BUFFON_LAPLACE_SIMULATE, the number of times the needle // crossed at least one line of the grid of cells. // { double angle; int hits; double pi = 3.141592653589793238462643; int trial; double x1; double x2; double y1; double y2; hits = 0; for ( trial = 1; trial <= trial_num; trial++ ) { // // Randomly choose the location of the eye of the needle in [0,0]x[A,B], // and the angle the needle makes. // x1 = a * ( double ) rand ( ) / ( double ) RAND_MAX; y1 = b * ( double ) rand ( ) / ( double ) RAND_MAX; angle = 2.0 * pi * ( double ) rand ( ) / ( double ) RAND_MAX; // // Compute the location of the point of the needle. // x2 = x1 + l * cos ( angle ); y2 = y1 + l * sin ( angle ); // // Count the end locations that lie outside the cell. // if ( x2 <= 0.0 || a <= x2 || y2 <= 0.0 || b <= y2 ) { hits = hits + 1; } } return hits; } //****************************************************************************80 double buffon_pdf ( double a, double l ) //****************************************************************************80 // // Purpose: // // BUFFON_PDF evaluates the Buffon PDF. // // Discussion: // // In the Buffon needle experiment, we suppose that the plane has been // ruled by vertical lines with a spacing of A units, and that a // needle of length L is dropped "at random" onto this grid. // // Because of the various symmetries, we may assume that this eye of // this needle lands in the first infinite strip, and we may further // assume that its Y coordinate is 0. Thus, we have // the eye as (X1,Y1) with 0 <= X1 <= A and Y1 = 0. // // ANGLE, the angle that the needle makes is taken to be uniformly random. // The point of the needle, (X2,Y2), therefore lies at // // (X2,Y2) = ( X1+L*cos(ANGLE), Y1+L*sin(ANGLE) ) // // The needle will have crossed at least one grid line if any of the // following are true: // // X2 <= 0, A <= X2. // // The probability of a crossing on a single trial is // // P(A,L) = ( 2 * L ) / ( PI * A ) // // and therefore, a record of the number of hits for a given number of // trials can be used as a very roundabout way of estimating PI. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 March 2007 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the horizontal spacing between the // vertical grid lines. 0 <= A. // // Input, double L, the length of the needle. // // Output, double BUFFON_PDF, the Buffon PDF. // { double pdf; double pi = 3.141592653589793238462643; if ( a < 0.0 ) { cerr << "\n"; cerr << "BUFFON_PDF - Fatal error!\n"; cerr << " Input A < 0.\n"; exit ( 1 ); } else if ( a == 0.0 ) { pdf = 1.0; return pdf; } if ( l < 0.0 ) { cerr << "\n"; cerr << "BUFFON_PDF - Fatal error!\n"; cerr << " Input L < 0.\n"; exit ( 1 ); } else if ( l == 0.0 ) { pdf = 0.0; return pdf; } pdf = ( 2.0 * l ) / ( pi * a ); return pdf; } //****************************************************************************80 int buffon_simulate ( double a, double l, int trial_num ) //****************************************************************************80 // // Purpose: // // BUFFON_SIMULATE simulates a Buffon needle experiment. // // Discussion: // // In the Buffon needle experiment, we suppose that the plane has been // ruled by vertical lines with a spacing of A units, and that a // needle of length L is dropped "at random" onto this grid. // // Because of the various symmetries, we may assume that this eye of // this needle lands in the first infinite strip, and we may further // assume that its Y coordinate is 0. Thus, we have // the eye as (X1,Y1) with 0 <= X1 <= A and Y1 = 0. // // ANGLE, the angle that the needle makes is taken to be uniformly random. // The point of the needle, (X2,Y2), therefore lies at // // (X2,Y2) = ( X1+L*cos(ANGLE), Y1+L*sin(ANGLE) ) // // The needle will have crossed at least one grid line if any of the // following are true: // // X2 <= 0, A <= X2. // // The probability of a crossing on a single trial is // // P(A,L) = ( 2 * L ) / ( PI * A ) // // and therefore, a record of the number of hits for a given number of // trials can be used as a very roundabout way of estimating PI. // // Since this routine invokes the C++ random number generator, // the user should initialize the random number generator, particularly // if it is desired to control whether the sequence is to be varied // or repeated. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 March 2007 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the horizontal spacing between the // vertical grid lines. 0 <= A. // // Input, double L, the length of the needle. // // Input, int TRIAL_NUM, the number of times the needle is // to be dropped onto the grid. // // Output, int BUFFON_SIMULATE, the number of times the needle // crossed at least one line of the grid of cells. // { double angle; int hits; double pi = 3.141592653589793238462643; int trial; double x1; double x2; hits = 0; for ( trial = 1; trial <= trial_num; trial++ ) { // // Randomly choose the location (X1,Y1) of the eye of the needle // in [0,0]x[A,0], and the angle the needle makes. // x1 = a * ( double ) rand ( ) / ( double ) RAND_MAX; angle = 2.0 * pi * ( double ) rand ( ) / ( double ) RAND_MAX; // // Compute the location of the point of the needle. // We only need to know the value of X2, not Y2! // x2 = x1 + l * cos ( angle ); // // Count the end locations that lie outside the cell. // if ( x2 <= 0.0 || a <= x2 ) { hits = hits + 1; } } return hits; } //****************************************************************************80 double burr_cdf ( double x, double a, double b, double c, double d ) //****************************************************************************80 // // Purpose: // // BURR_CDF evaluates the Burr CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, C, D, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double BURR_CDF, the value of the CDF. // { double cdf; if ( x <= a ) { cdf = 0.0; } else { cdf = 1.0 / pow ( ( 1.0 + pow ( ( b / ( x - a ) ), c ) ), d ); } return cdf; } //****************************************************************************80 double burr_cdf_inv ( double cdf, double a, double b, double c, double d ) //****************************************************************************80 // // Purpose: // // BURR_CDF_INV inverts the Burr CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, C, D, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double BURR_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "BURR_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a + b / pow ( ( pow ( ( 1.0 / cdf ), (1.0 / d ) ) - 1.0 ), ( 1.0 / c ) ); return x; } //****************************************************************************80 bool burr_check ( double a, double b, double c, double d ) //****************************************************************************80 // // Purpose: // // BURR_CHECK checks the parameters of the Burr CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, D, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, bool BURR_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cerr << " \n"; cerr << "BURR_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } if ( c <= 0 ) { cerr << " \n"; cerr << "BURR_CHECK - Fatal error!\n"; cerr << " C <= 0.\n"; return false; } return true; } //****************************************************************************80 double burr_mean ( double a, double b, double c, double d ) //****************************************************************************80 // // Purpose: // // BURR_MEAN returns the mean of the Burr PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, D, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double BURR_MEAN, the mean of the PDF. // { double mean; mean = a + b * r8_gamma ( 1.0 - 1.0 / c ) * r8_gamma ( d + 1.0 / c ) / r8_gamma ( d ); return mean; } //****************************************************************************80 double burr_pdf ( double x, double a, double b, double c, double d ) //****************************************************************************80 // // Purpose: // // BURR_PDF evaluates the Burr PDF. // // Discussion: // // PDF(A,B,C,D;X) = ( C * D / B ) * ( ( X - A ) / B )^( - C - 1 ) // * ( 1 + ( ( X - A ) / B )^( - C ) )^( - D - 1 ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Reference: // // M E Johnson, // Multivariate Statistical Simulation, // Wiley, New York, 1987. // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, C, D, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double BURR_PDF, the value of the PDF. // { double pdf; double y; if ( x <= a ) { pdf = 0.0; } else { y = ( x - a ) / b; pdf = ( c * d / b ) * pow ( y, ( - c - 1.0 ) ) * pow ( ( 1.0 + pow ( y, ( - c ) ) ), ( - d - 1.0 ) ); } return pdf; } //****************************************************************************80 double burr_sample ( double a, double b, double c, double d, int &seed ) //****************************************************************************80 // // Purpose: // // BURR_SAMPLE samples the Burr PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, D, the parameters of the PDF. // 0 < B, // 0 < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double BURR_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = burr_cdf_inv ( cdf, a, b, c, d ); return x; } //****************************************************************************80 double burr_variance ( double a, double b, double c, double d ) //****************************************************************************80 // // Purpose: // // BURR_VARIANCE returns the variance of the Burr PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, D, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double BURR_VARIANCE, the variance of the PDF. // { double k; double variance; if ( c <= 2.0 ) { cout << " \n"; cout << "BURR_VARIANCE - Warning!\n"; cout << " Variance undefined for C <= 2.\n"; variance = r8_huge ( ); } else { k = r8_gamma ( d ) * r8_gamma ( 1.0 - 2.0 / c ) * r8_gamma ( d + 2.0 / c ) - pow ( ( r8_gamma ( 1.0 - 1.0 / c ) * r8_gamma ( d + 1.0 / c ) ), 2 ); variance = k * b * b / pow ( r8_gamma ( d ), 2 ); } return variance; } //****************************************************************************80 double cardioid_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // CARDIOID_CDF evaluates the Cardioid CDF. // // Discussion: // // The angle X is assumed to lie between A - PI and A + PI. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 <= B <= 0.5. // // Output, double CDF, the value of the PDF. // { double cdf; const double pi = 3.14159265358979323; if ( x <= a - pi ) { cdf = 0.0; } else if ( x < a + pi ) { cdf = ( pi + x - a + 2.0 * b * sin ( x - a ) ) / ( 2.0 * pi ); } else { cdf = 1.0; } return cdf; } //****************************************************************************80 double cardioid_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // CARDIOID_CDF_INV inverts the Cardioid CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0 <= CDF <= 1. // // Input, double A, B, the parameters. // 0.0 <= B <= 0.5. // // Output, double CARDIOD_CDF_INV, the argument with the given CDF. // A - PI <= X <= A + PI. // { double fp; double fx; int it; const double pi = 3.14159265358979323; double tol = 0.000001; double x; if ( cdf <= 0.0 ) { x = a - pi; } else if ( cdf < 1.0 ) { x = a; it = 0; for ( ; ; ) { fx = cdf - ( pi + x - a + 2.0 * b * sin ( x - a ) ) / ( 2.0 * pi ); if ( r8_abs ( fx ) < tol ) { break; } if ( 10 < it ) { cerr << "\n"; cerr << "CARDIOID_CDF_INV - Fatal error!\n"; cerr << " Too many iterations.\n"; exit ( 1 ); } fp = - ( 1.0 + 2.0 * b * cos ( x - a ) ) / ( 2.0 * pi ); x = x - fx / fp; x = r8_max ( x, a - pi ); x = r8_min ( x, a + pi ); it = it + 1; } } else { x = a + pi; } return x; } //****************************************************************************80 bool cardioid_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // CARDIOID_CHECK checks the parameters of the Cardioid CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // -0.5 <= B <= 0.5. // // Output, bool CARDIOID_CHECK, is true if the parameters are legal. // { bool value; if ( b < -0.5 || 0.5 < b ) { cerr << "\n"; cerr << "CARDIOID_CHECK - Fatal error!\n"; cerr << " B < -0.5 or 0.5 < B.\n"; value = false; return value; } value = true; return value; } //****************************************************************************80 double cardioid_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // CARDIOID_MEAN returns the mean of the Cardioid PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 <= B <= 0.5. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double cardioid_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // CARDIOID_PDF evaluates the Cardioid PDF. // // Discussion: // // The cardioid PDF can be thought of as being applied to points on // a circle. Compare this distribution with the "Cosine PDF". // // PDF(A,B;X) = ( 1 / ( 2 * PI ) ) * ( 1 + 2 * B * COS ( X - A ) ) // for 0 <= B <= 1/2. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 July 2005 // // Author: // // John Burkardt // // Reference: // // N I Fisher, // Statistical Analysis of Circular Data, // Cambridge, 1993. // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 <= B <= 0.5. // // Output, double CARDIOID_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; pdf = ( 1.0 + 2.0 * b * cos ( x - a ) ) / ( 2.0 * pi ); return pdf; } //****************************************************************************80 double cardioid_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // CARDIOID_SAMPLE samples the Cardioid PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 <= B <= 0.5. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double CARDIOD_SAMPLE, a sample of the PDF. // A - PI <= X <= A + PI. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = cardioid_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double cardioid_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // CARDIOID_VARIANCE returns the variance of the Cardioid PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 <= B <= 0.5. // // Output, double VARIANCE, the variance of the PDF. // { double variance; variance = 0.0; return variance; } //****************************************************************************80 double cauchy_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // CAUCHY_CDF evaluates the Cauchy CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double CDF, the value of the CDF. // { double cdf; const double pi = 3.14159265358979323; double y; y = ( x - a ) / b; cdf = 0.5 + atan ( y ) / pi; return cdf; } //****************************************************************************80 double cauchy_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // CAUCHY_CDF_INV inverts the Cauchy CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double CAUCHY_CDF_INV, the corresponding argument. // { const double pi = 3.14159265358979323; double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "CAUCHY_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a + b * tan ( pi * ( cdf - 0.5 ) ); return x; } //****************************************************************************80 void cauchy_cdf_values ( int &n_data, double &mu, double &sigma, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // CAUCHY_CDF_VALUES returns some values of the Cauchy CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = CauchyDistribution [ mu, sigma ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 September 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &MU, the mean of the distribution. // // Output, double &SIGMA, the variance of the distribution. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 12 static double fx_vec[N_MAX] = { 0.5000000000000000E+00, 0.8524163823495667E+00, 0.9220208696226307E+00, 0.9474315432887466E+00, 0.6475836176504333E+00, 0.6024163823495667E+00, 0.5779791303773693E+00, 0.5628329581890012E+00, 0.6475836176504333E+00, 0.5000000000000000E+00, 0.3524163823495667E+00, 0.2500000000000000E+00 }; static double mu_vec[N_MAX] = { 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01 }; static double sigma_vec[N_MAX] = { 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; static double x_vec[N_MAX] = { 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; mu = 0.0; sigma = 0.0; x = 0.0; fx = 0.0; } else { mu = mu_vec[n_data-1]; sigma = sigma_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool cauchy_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // CAUCHY_CHECK checks the parameters of the Cauchy CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, bool CAUCHY_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cerr << " \n"; cerr << "CAUCHY_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double cauchy_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // CAUCHY_MEAN returns the mean of the Cauchy PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double cauchy_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // CAUCHY_PDF evaluates the Cauchy PDF. // // Discussion: // // PDF(A,B;X) = 1 / ( PI * B * ( 1 + ( ( X - A ) / B )^2 ) ) // // The Cauchy PDF is also known as the Breit-Wigner PDF. It // has some unusual properties. In particular, the integrals for the // expected value and higher order moments are "singular", in the // sense that the limiting values do not exist. A result can be // obtained if the upper and lower limits of integration are set // equal to +T and -T, and the limit as T=>INFINITY is taken, but // this is a very weak and unreliable sort of limit. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; double y; y = ( x - a ) / b; pdf = 1.0 / ( pi * b * ( 1.0 + y * y ) ); return pdf; } //****************************************************************************80 double cauchy_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // CAUCHY_SAMPLE samples the Cauchy PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double CAUCHY_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = cauchy_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double cauchy_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // CAUCHY_VARIANCE returns the variance of the Cauchy PDF. // // Discussion: // // The variance of the Cauchy PDF is not well defined. This routine // is made available for completeness only, and simply returns // a "very large" number. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double VARIANCE, the mean of the PDF. // { double variance; variance = r8_huge ( ); return variance; } //****************************************************************************80 double chi_cdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // CHI_CDF evaluates the Chi CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, C, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double CDF, the value of the CDF. // { double cdf; double p2; double x2; double y; if ( x <= a ) { cdf = 0.0; } else { y = ( x - a ) / b; x2 = 0.5 * y * y; p2 = 0.5 * c; cdf = gamma_inc ( p2, x2 ); } return cdf; } //****************************************************************************80 double chi_cdf_inv ( double cdf, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // CHI_CDF_INV inverts the Chi CDF. // // Discussion: // // A simple bisection method is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, C, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double CHI_CDF_INV, the corresponding argument of the CDF. // { double cdf1; double cdf2; double cdf3; int it; int it_max = 100; double tol = 0.0001; double x; double x1; double x2; double x3; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "CHI_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = a; return x; } else if ( 1.0 == cdf ) { x = r8_huge ( ); return x; } x1 = a; cdf1 = 0.0; x2 = a + 1.0; for ( ; ; ) { cdf2 = chi_cdf ( x2, a, b, c ); if ( cdf < cdf2 ) { break; } x2 = a + 2.0 * ( x2 - a ); } // // Now use bisection. // it = 0; for ( ; ; ) { it = it + 1; x3 = 0.5 * ( x1 + x2 ); cdf3 = chi_cdf ( x3, a, b, c ); if ( r8_abs ( cdf3 - cdf ) < tol ) { x = x3; break; } if ( it_max < it ) { cerr << " \n"; cerr << "CHI_CDF_INV - Fatal error!\n"; cerr << " Iteration limit exceeded.\n"; return x; } if ( ( cdf3 <= cdf && cdf1 <= cdf ) || ( cdf <= cdf3 && cdf <= cdf1 ) ) { x1 = x3; cdf1 = cdf3; } else { x2 = x3; cdf2 = cdf3; } } return x; } //****************************************************************************80 bool chi_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // CHI_CHECK checks the parameters of the Chi CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, bool CHI_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cerr << " \n"; cerr << "CHI_CHECK - Fatal error!\n"; cerr << " B <= 0.0.\n"; return false; } if ( c <= 0.0 ) { cerr << " \n"; cerr << "CHI_CHECK - Fatal error!\n"; cerr << " C <= 0.0.\n"; return false; } return true; } //****************************************************************************80 double chi_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // CHI_MEAN returns the mean of the Chi PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double MEAN, the mean value. // { double mean; mean = a + sqrt ( 2.0 ) * b * r8_gamma ( 0.5 * ( c + 1.0 ) ) / r8_gamma ( 0.5 * c ); return mean; } //****************************************************************************80 double chi_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // CHI_PDF evaluates the Chi PDF. // // Discussion: // // PDF(A,B,C;X) = EXP ( - 0.5 * ( ( X - A ) / B )^2 ) // * ( ( X - A ) / B )^( C - 1 ) / // ( 2^( 0.5 * C - 1 ) * B * GAMMA ( 0.5 * C ) ) // // CHI(A,B,1) is the Half Normal PDF; // CHI(0,B,2) is the Rayleigh PDF; // CHI(0,B,3) is the Maxwell PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, C, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double PDF, the value of the PDF. // { double pdf; double y; if ( x <= a ) { pdf = 0.0; } else { y = ( x - a ) / b; pdf = exp ( - 0.5 * y * y ) * pow ( y, ( c - 1.0 ) ) / ( pow ( 2.0, ( 0.5 * c - 1.0 ) ) * b * r8_gamma ( 0.5 * c ) ); } return pdf; } //****************************************************************************80 double chi_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // CHI_SAMPLE samples the Chi PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0 < B, // 0 < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double CHI_SAMPLE, a sample of the PDF. // { double x; x = chi_square_sample ( c, seed ); x = a + b * sqrt ( x ); return x; } //****************************************************************************80 double chi_variance ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // CHI_VARIANCE returns the variance of the Chi PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0 < B, // 0 < C. // // Output, double VARIANCE, the variance of the PDF. // { double variance; variance = b * b * ( c - 2.0 * pow ( ( r8_gamma ( 0.5 * ( c + 1.0 ) ) / r8_gamma ( 0.5 * c ) ), 2 ) ); return variance; } //****************************************************************************80 double chi_square_cdf ( double x, double a ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_CDF evaluates the Chi squared CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the value of the random deviate. // // Input, double A, the parameter of the distribution, usually // the number of degrees of freedom. // // Output, double CDF, the value of the CDF. // { double a2; double b2; double c2; double cdf; double x2; x2 = 0.5 * x; a2 = 0.0; b2 = 1.0; c2 = 0.5 * a; cdf = gamma_cdf ( x2, a2, b2, c2 ); return cdf; } //****************************************************************************80 double chi_square_cdf_inv ( double cdf, double a ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_CDF_INV inverts the Chi squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // Original FORTRAN77 version by Best and Roberts. // C++ version by John Burkardt. // // Reference: // // Best, Roberts, // The Percentage Points of the Chi-Squared Distribution, // Algorithm AS 91, // Applied Statistics, // Volume 24, Number ?, pages 385-390, 1975. // // Parameters: // // Input, double CDF, a value of the chi-squared cumulative // probability density function. // 0.000002 <= CDF <= 0.999998. // // Input, double A, the parameter of the chi-squared // probability density function. 0 < A. // // Output, double CHI_SQUARE_CDF_INV, the value of the chi-squared random deviate // with the property that the probability that a chi-squared random // deviate with parameter A is less than or equal to X is CDF. // { double a2; double aa = 0.6931471806; double b; double c; double c1 = 0.01; double c2 = 0.222222; double c3 = 0.32; double c4 = 0.4; double c5 = 1.24; double c6 = 2.2; double c7 = 4.67; double c8 = 6.66; double c9 = 6.73; double c10 = 13.32; double c11 = 60.0; double c12 = 70.0; double c13 = 84.0; double c14 = 105.0; double c15 = 120.0; double c16 = 127.0; double c17 = 140.0; double c18 = 175.0; double c19 = 210.0; double c20 = 252.0; double c21 = 264.0; double c22 = 294.0; double c23 = 346.0; double c24 = 420.0; double c25 = 462.0; double c26 = 606.0; double c27 = 672.0; double c28 = 707.0; double c29 = 735.0; double c30 = 889.0; double c31 = 932.0; double c32 = 966.0; double c33 = 1141.0; double c34 = 1182.0; double c35 = 1278.0; double c36 = 1740.0; double c37 = 2520.0; double c38 = 5040.0; double cdf_max = 0.999998; double cdf_min = 0.000002; double ch; double e = 0.0000005; double g; int i; int it_max = 20; double p1; double p2; double q; double s1; double s2; double s3; double s4; double s5; double s6; double t; double x; double x2; double xx; // if ( cdf < cdf_min ) { x = -1.0; cerr << " \n"; cerr << "CHI_SQUARE_CDF_INV - Fatal error!\n"; cerr << " CDF < CDF_MIN.\n"; exit ( 1 ); } if ( cdf_max < cdf ) { x = -1.0; cerr << " \n"; cerr << "CHI_SQUARE_CDF_INV - Fatal error!\n"; cerr << " CDF_MAX < CDF.\n"; exit ( 1 ); } xx = 0.5 * a; c = xx - 1.0; // // Compute Log ( Gamma ( A/2 ) ). // g = gamma_log ( a / 2.0 ); // // Starting approximation for small chi-squared. // if ( a < -c5 * log ( cdf ) ) { ch = pow ( ( cdf * xx * exp ( g + xx * aa ) ), ( 1.0 / xx ) ); if ( ch < e ) { x = ch; return x; } } // // Starting approximation for A less than or equal to 0.32. // else if ( a <= c3 ) { ch = c4; a2 = log ( 1.0 - cdf ); for ( ; ; ) { q = ch; p1 = 1.0 + ch * ( c7 + ch ); p2 = ch * ( c9 + ch * ( c8 + ch ) ); t = - 0.5 + ( c7 + 2.0 * ch ) / p1 - ( c9 + ch * ( c10 + 3.0 * ch ) ) / p2; ch = ch - ( 1.0 - exp ( a2 + g + 0.5 * ch + c * aa ) * p2 / p1 ) / t; if ( r8_abs ( q / ch - 1.0 ) <= c1 ) { break; } } } // // Call to algorithm AS 111. // Note that P has been tested above. // AS 241 could be used as an alternative. // else { x2 = normal_01_cdf_inv ( cdf ); // // Starting approximation using Wilson and Hilferty estimate. // p1 = c2 / a; ch = a * pow ( ( x2 * sqrt ( p1 ) + 1.0 - p1 ), 3 ); // // Starting approximation for P tending to 1. // if ( c6 * a + 6.0 < ch ) { ch = - 2.0 * ( log ( 1.0 - cdf ) - c * log ( 0.5 * ch ) + g ); } } // // Call to algorithm AS 239 and calculation of seven term Taylor series. // for ( i = 1; i <= it_max; i++ ) { q = ch; p1 = 0.5 * ch; p2 = cdf - gamma_inc ( xx, p1 ); t = p2 * exp ( xx * aa + g + p1 - c * log ( ch ) ); b = t / ch; a2 = 0.5 * t - b * c; s1 = ( c19 + a2 * ( c17 + a2 * ( c14 + a2 * ( c13 + a2 * ( c12 + a2 * c11 ) ) ) ) ) / c24; s2 = ( c24 + a2 * ( c29 + a2 * ( c32 + a2 * ( c33 + a2 * c35 ) ) ) ) / c37; s3 = ( c19 + a2 * ( c25 + a2 * ( c28 + a2 * c31 ) ) ) / c37; s4 = ( c20 + a2 * ( c27 + a2 * c34 ) + c * ( c22 + a2 * ( c30 + a2 * c36 ) ) ) / c38; s5 = ( c13 + c21 * a2 + c * ( c18 + c26 * a2 ) ) / c37; s6 = ( c15 + c * ( c23 + c16 * c ) ) / c38; ch = ch + t * ( 1.0 + 0.5 * t * s1 - b * c * ( s1 - b * ( s2 - b * ( s3 - b * ( s4 - b * ( s5 - b * s6 ) ) ) ) ) ); if ( e < r8_abs ( q / ch - 1.0 ) ) { x = ch; return x; } } x = ch; cout << " \n"; cout << "CHI_SQUARE_CDF_INV - Warning!\n"; cout << " Convergence not reached.\n"; return x; } //****************************************************************************80 void chi_square_cdf_values ( int &n_data, int &a, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_CDF_VALUES returns some values of the Chi-Square CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = ChiSquareDistribution [ df ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, int &A, the parameter of the function. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { // # define N_MAX 21 static int a_vec[N_MAX] = { 1, 2, 1, 2, 1, 2, 3, 4, 1, 2, 3, 4, 5, 3, 3, 3, 3, 3, 10, 10, 10 }; static double fx_vec[N_MAX] = { 0.7965567455405796E-01, 0.4987520807317687E-02, 0.1124629160182849E+00, 0.9950166250831946E-02, 0.4729107431344619E+00, 0.1812692469220181E+00, 0.5975750516063926E-01, 0.1752309630642177E-01, 0.6826894921370859E+00, 0.3934693402873666E+00, 0.1987480430987992E+00, 0.9020401043104986E-01, 0.3743422675270363E-01, 0.4275932955291202E+00, 0.6083748237289110E+00, 0.7385358700508894E+00, 0.8282028557032669E+00, 0.8883897749052874E+00, 0.1721156299558408E-03, 0.3659846827343712E-02, 0.1857593622214067E-01 }; static double x_vec[N_MAX] = { 0.01E+00, 0.01E+00, 0.02E+00, 0.02E+00, 0.40E+00, 0.40E+00, 0.40E+00, 0.40E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 2.00E+00, 3.00E+00, 4.00E+00, 5.00E+00, 6.00E+00, 1.00E+00, 2.00E+00, 3.00E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; a = 0; x = 0.0; fx = 0.0; } else { a = a_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool chi_square_check ( double a ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_CHECK checks the parameter of the central Chi squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the distribution. // 1 <= A. // // Output, bool CHI_SQUARE_CHECK, is true if the parameters are legal. // { if ( a < 1.0 ) { cerr << " \n"; cerr << "CHI_SQUARE_CHECK - Fatal error!\n"; cerr << " A < 1.0.\n"; return false; } return true; } //****************************************************************************80 double chi_square_mean ( double a ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_MEAN returns the mean of the central Chi squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the distribution. // 1 <= A. // // Output, double MEAN, the mean value. // { double mean; mean = a; return mean; } //****************************************************************************80 double chi_square_pdf ( double x, double a ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_PDF evaluates the central Chi squared PDF. // // Discussion: // // PDF(A;X) = // EXP ( - X / 2 ) * X^((A-2)/2) / ( 2^(A/2) * GAMMA ( A/2 ) ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X // // Input, double A, the parameter of the PDF. // 1 <= A. // // Output, double PDF, the value of the PDF. // { double b; double pdf; if ( x < 0.0 ) { pdf = 0.0; } else { b = a / 2.0; pdf = exp ( -0.5 * x ) * pow ( x, ( b - 1.0 ) ) / ( pow ( 2.0, b ) * r8_gamma ( b ) ); } return pdf; } //****************************************************************************80 double chi_square_sample ( double a, int &seed ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_SAMPLE samples the central Chi squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 1 <= A. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double CHI_SQUARE_SAMPLE, a sample of the PDF. // { double a2; double b2; double c2; int i; int it_max = 100; int n; double x; double x2; n = ( int ) a; if ( ( double ) ( n ) == a && n <= it_max ) { x = 0.0; for ( i = 1; i <= n; i++ ) { x2 = normal_01_sample ( seed ); x = x + x2 * x2; } } else { a2 = 0.0; b2 = 1.0; c2 = a / 2.0; x = gamma_sample ( a2, b2, c2, seed ); x = 2.0 * x; } return x; } //****************************************************************************80 double chi_square_variance ( double a ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_VARIANCE returns the variance of the central Chi squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the distribution. // 1 <= A. // // Output, double VARIANCE, the variance of the PDF. // { double variance; variance = 2.0 * a; return variance; } //****************************************************************************80 void chi_square_noncentral_cdf_values ( int &n_data, int &df, double &lambda, double &x, double &cdf ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_NONCENTRAL_CDF_VALUES returns values of the noncentral chi CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = NoncentralChiSquareDistribution [ df, lambda ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 August 2004 // // Author: // // John Burkardt // // Reference: // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, int &DF, the number of degrees of freedom. // // Output, double &LAMBDA, the noncentrality parameter. // // Output, double &X, the argument of the function. // // Output, double &CDF, the noncentral chi CDF. // { # define N_MAX 28 static double cdf_vec[N_MAX] = { 0.8399444269398261E+00, 0.6959060300435139E+00, 0.5350879697078847E+00, 0.7647841496310313E+00, 0.6206436532195436E+00, 0.4691667375373180E+00, 0.3070884345937569E+00, 0.2203818092990903E+00, 0.1500251895581519E+00, 0.3071163194335791E-02, 0.1763982670131894E-02, 0.9816792594625022E-03, 0.1651753140866208E-01, 0.2023419573950451E-03, 0.4984476352854074E-06, 0.1513252400654827E-01, 0.2090414910614367E-02, 0.2465021206048452E-03, 0.2636835050342939E-01, 0.1857983220079215E-01, 0.1305736595486640E-01, 0.5838039534819351E-01, 0.4249784402463712E-01, 0.3082137716021596E-01, 0.1057878223400849E+00, 0.7940842984598509E-01, 0.5932010895599639E-01, 0.2110395656918684E+00 }; static int df_vec[N_MAX] = { 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 60, 80, 100, 1, 2, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 8 }; static double lambda_vec[N_MAX] = { 0.5E+00, 0.5E+00, 0.5E+00, 1.0E+00, 1.0E+00, 1.0E+00, 5.0E+00, 5.0E+00, 5.0E+00, 20.0E+00, 20.0E+00, 20.0E+00, 30.0E+00, 30.0E+00, 30.0E+00, 5.0E+00, 5.0E+00, 5.0E+00, 2.0E+00, 3.0E+00, 4.0E+00, 2.0E+00, 3.0E+00, 4.0E+00, 2.0E+00, 3.0E+00, 4.0E+00, 0.5E+00 }; static double x_vec[N_MAX] = { 3.000E+00, 3.000E+00, 3.000E+00, 3.000E+00, 3.000E+00, 3.000E+00, 3.000E+00, 3.000E+00, 3.000E+00, 3.000E+00, 3.000E+00, 3.000E+00, 60.000E+00, 60.000E+00, 60.000E+00, 0.050E+00, 0.050E+00, 0.050E+00, 4.000E+00, 4.000E+00, 4.000E+00, 5.000E+00, 5.000E+00, 5.000E+00, 6.000E+00, 6.000E+00, 6.000E+00, 5.000E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; x = 0.0; lambda = 0.0; df = 0; cdf = 0.0; } else { x = x_vec[n_data-1]; lambda = lambda_vec[n_data-1]; df = df_vec[n_data-1]; cdf = cdf_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double chi_square_noncentral_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_NONCENTRAL_CHECK checks the parameters of the noncentral Chi Squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the parameter of the PDF. // 1.0 <= A. // // Input, double B, the noncentrality parameter of the PDF. // 0.0 <= B. // // Output, bool CHI_SQUARE_NONCENTRAL_CHECK, is true if the parameters // are legal. // { if ( a < 1.0 ) { cerr << " \n"; cerr << "CHI_SQUARE_NONCENTRAL_CHECK - Fatal error!\n"; cerr << " A < 1.\n"; return false; } if ( b < 0.0 ) { cerr << " \n"; cerr << "CHI_SQUARE_NONCENTRAL_CHECK - Fatal error!\n"; cerr << " B < 0.\n"; return false; } return true; } //****************************************************************************80 double chi_square_noncentral_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_NONCENTRAL_MEAN returns the mean of the noncentral Chi squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the parameter of the PDF. // 1.0 <= A. // // Input, double B, the noncentrality parameter of the PDF. // 0.0 <= B. // // Output, double MEAN, the mean value. // { double mean; mean = a + b; return mean; } //****************************************************************************80 double chi_square_noncentral_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_NONCENTRAL_SAMPLE samples the noncentral Chi squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 November 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the parameter of the PDF. // 1.0 <= A. // // Input, double B, the noncentrality parameter of the PDF. // 0.0 <= B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double CHI_SQUARE_NONCENTRAL_SAMPLE, a sample of the PDF. // { double a1; double a2; double b2; double x; double x1; double x2; a1 = a - 1.0; x1 = chi_square_sample ( a1, seed ); a2 = sqrt ( b ); b2 = 1.0; x2 = normal_sample ( a2, b2, seed ); x = x1 + x2 * x2; return x; } //****************************************************************************80 double chi_square_noncentral_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // CHI_SQUARE_NONCENTRAL_VARIANCE: variance of the noncentral Chi squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 1 <= A. // // Input, double B, the noncentrality parameter of the PDF. // 0.0 <= B. // // Output, double VARIANCE, the variance value. // { double variance; variance = 2.0 * ( a + 2.0 * b ); return variance; } //****************************************************************************80 double *circle_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // CIRCLE_SAMPLE samples points from a circle. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the circle. // The circle is centered at (A,B) and has radius C. // 0.0 < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double CIRCLE_SAMPLE[2], a sampled point of the circle. // { double angle; const double pi = 3.14159265358979323; double radius_frac; double *x; x = new double[2]; radius_frac = sqrt ( r8_uniform_01 ( seed ) ); angle = 2.0 * pi * r8_uniform_01 ( seed ); x[0] = a + c * radius_frac * cos ( angle ); x[1] = b + c * radius_frac * sin ( angle ); return x; } //****************************************************************************80 double *circular_normal_01_mean ( ) //****************************************************************************80 // // Purpose: // // CIRCULAR_NORMAL_01_MEAN returns the mean of the Circular Normal 01 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double CIRCULAR_01_MEAN[2], the mean of the PDF. // { double *mean; mean = new double[2]; mean[0] = 0.0; mean[1] = 0.0; return mean; } //****************************************************************************80 double circular_normal_01_pdf ( double x[2] ) //****************************************************************************80 // // Purpose: // // CIRCULAR_NORMAL_01_PDF evaluates the Circular Normal 01 PDF. // // Discussion: // // PDF(X) = EXP ( - 0.5 * ( X(1)^2 + X(2)^2 ) ) / ( 2 * PI ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X[2], the argument of the PDF. // // Output, double CIRCULAR_NORMAL_01_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; pdf = exp ( - 0.5 * ( x[0] * x[0] + x[1] * x[1] ) ) / ( 2.0 * pi ); return pdf; } //****************************************************************************80 double *circular_normal_01_sample ( int &seed ) //****************************************************************************80 // // Purpose: // // CIRCULAR_NORMAL_01_SAMPLE samples the Circular Normal 01 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input/output, int &SEED, a seed for the random number generator. // // Output, double CIRCULAR_NORMAL_01_SAMPLE[2], a sample of the PDF. // { const double pi = 3.14159265358979323; double v1; double v2; double *x; x = new double[2]; v1 = r8_uniform_01 ( seed ); v2 = r8_uniform_01 ( seed ); x[0] = sqrt ( - 2.0 * log ( v1 ) ) * cos ( 2.0 * pi * v2 ); x[1] = sqrt ( - 2.0 * log ( v1 ) ) * sin ( 2.0 * pi * v2 ); return x; } //****************************************************************************80 double *circular_normal_01_variance ( ) //****************************************************************************80 // // Purpose: // // CIRCULAR_NORMAL_01_VARIANCE returns the variance of the Circular Normal 01 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double CIRCULAR_NORMAL_01_VARIANCE[2], the variance of the PDF. // { double *variance; variance = new double[2]; variance[0] = 1.0; variance[1] = 1.0; return variance; } //****************************************************************************80 double *circular_normal_mean ( double a[2], double b ) //****************************************************************************80 // // Purpose: // // CIRCULAR_NORMAL_MEAN returns the mean of the Circular Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 January 2011 // // Author: // // John Burkardt // // Parameters: // // Input, double A[2], a parameter of the PDF, the mean value. // // Input, double B, a parameter of the PDF, the standard deviation. // // Output, double CIRCULAR_MEAN[2], the mean of the PDF. // { double *mean; mean = new double[2]; mean[0] = a[0]; mean[1] = a[1]; return mean; } //****************************************************************************80 double circular_normal_pdf ( double x[2], double a[2], double b ) //****************************************************************************80 // // Purpose: // // CIRCULAR_NORMAL_PDF evaluates the Circular Normal PDF. // // Discussion: // // PDF(X) = EXP ( - 0.5D+00 * ( ( (X(1)-A(1))^2 + (X(2)-A(2))^2 ) / B^2 ) // / ( 2 * PI * B^2 ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 January 2011 // // Author: // // John Burkardt // // Parameters: // // Input, double X[2], the argument of the PDF. // // Input, double A[2], a parameter of the PDF, the mean value. // // Input, double B, a parameter of the PDF, the standard deviation. // // Output, double CIRCULAR_NORMAL_PDF, the value of the PDF. // { double d; double pdf; const double pi = 3.14159265358979323; d = ( pow ( x[0] - a[0], 2 ) + pow ( x[1] - a[1], 2 ) ) / pow ( b, 2 ); pdf = exp ( - 0.5 * d ) / ( 2.0 * b * b * pi ); return pdf; } //****************************************************************************80 double *circular_normal_sample ( double a[2], double b, int &seed ) //****************************************************************************80 // // Purpose: // // CIRCULAR_NORMAL_SAMPLE samples the Circular Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 January 2011 // // Author: // // John Burkardt // // Parameters: // // Input, double A[2], a parameter of the PDF, the mean value. // // Input, double B, a parameter of the PDF, the standard deviation. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double CIRCULAR_NORMAL_SAMPLE[2], a sample of the PDF. // { const double pi = 3.14159265358979323; double r; double v1; double v2; double *x; x = new double[2]; v1 = r8_uniform_01 ( seed ); v2 = r8_uniform_01 ( seed ); r = sqrt ( - 2.0 * log ( v1 ) ); x[0] = a[0] + b * r * cos ( 2.0 * pi * v2 ); x[1] = a[1] + b * r * sin ( 2.0 * pi * v2 ); return x; } //****************************************************************************80 double *circular_normal_variance ( double a[2], double b ) //****************************************************************************80 // // Purpose: // // CIRCULAR_NORMAL_VARIANCE returns the variance of the Circular Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 January 2011 // // Author: // // John Burkardt // // Parameters: // // Input, double A[2], a parameter of the PDF, the mean value. // // Input, double B, a parameter of the PDF, the standard deviation. // // Output, double CIRCULAR_NORMAL_VARIANCE[2], the variance of the PDF. // { double *variance; variance = new double[2]; variance[0] = b; variance[1] = b; return variance; } //****************************************************************************80 int combinatorial ( int n, int k ) //****************************************************************************80 // // Purpose: // // COMBINATORIAL computes the binomial coefficient C(N,K). // // Discussion: // // The value is calculated in such a way as to avoid overflow and // roundoff. The calculation is done in integer arithmetic. // // The formula used is: // // C(N,K) = N! / ( K! * (N-K)! ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 January 2007 // // Author: // // John Burkardt // // Reference: // // ML Wolfson, HV Wright, // Algorithm 160: // Combinatorial of M Things Taken N at a Time, // Communications of the ACM, // April, 1963. // // Parameters: // // Input, int N, K, are the values of N and K. // // Output, int COMBINATORIAL, the number of combinations of N // things taken K at a time. // { int i; int mn; int mx; int value; mn = i4_min ( k, n - k ); if ( mn < 0 ) { value = 0; } else if ( mn == 0 ) { value = 1; } else { mx = i4_max ( k, n - k ); value = mx + 1; for ( i = 2; i <= mn; i++ ) { value = ( value * ( mx + i ) ) / i; } } return value; } //****************************************************************************80 double cosine_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // COSINE_CDF evaluates the Cosine CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameter of the PDF. // 0.0 < B. // // Output, double CDF, the value of the CDF. // { double cdf; const double pi = 3.14159265358979323; double y; if ( x <= a - pi * b ) { cdf = 0.0; } else if ( x <= a + pi * b ) { y = ( x - a ) / b; cdf = 0.5 + ( y + sin ( y ) ) / ( 2.0 * pi ); } else if ( a + pi * b < x ) { cdf = 1.0; } return cdf; } //****************************************************************************80 double cosine_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // COSINE_CDF_INV inverts the Cosine CDF. // // Discussion: // // A simple bisection method is used on the interval // [ A - PI * B, A + PI * B ]. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double COSINE_CDF_INV, the corresponding argument of the CDF. // { double cdf1; double cdf2; double cdf3; int it; int it_max = 100; const double pi = 3.14159265358979323; double tol = 0.0001; double x; double x1; double x2; double x3; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "COSINE_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = a - pi * b; return x; } else if ( 1.0 == cdf ) { x = a + pi * b; return x; } x1 = a - pi * b; cdf1 = 0.0; x2 = a + pi * b; cdf2 = 1.0; // // Now use bisection. // it = 0; for ( it = 1; it <= it_max; it++ ) { x3 = 0.5 * ( x1 + x2 ); cdf3 = cosine_cdf ( x3, a, b ); if ( r8_abs ( cdf3 - cdf ) < tol ) { x = x3; return x; } if ( ( cdf3 <= cdf && cdf1 <= cdf ) || ( cdf <= cdf3 && cdf <= cdf1 ) ) { x1 = x3; cdf1 = cdf3; } else { x2 = x3; cdf2 = cdf3; } } cerr << " \n"; cerr << "COSINE_CDF_INV - Fatal error!\n"; cerr << " Iteration limit exceeded.\n"; exit ( 1 ); } //****************************************************************************80 bool cosine_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // COSINE_CHECK checks the parameters of the Cosine CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameter of the PDF. // 0.0 < B. // // Output, bool COSINE_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cerr << " \n"; cerr << "COSINE_CHECK - Fatal error!\n"; cerr << " B <= 0.0\n"; return false; } return true; } //****************************************************************************80 double cosine_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // COSINE_MEAN returns the mean of the Cosine PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double cosine_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // COSINE_PDF evaluates the Cosine PDF. // // Discussion: // // PDF(A,B;X) = ( 1 / ( 2 * PI * B ) ) * COS ( ( X - A ) / B ) // for A - PI * B <= X <= A + PI * B // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; double y; if ( x < a - pi * b ) { pdf = 0.0; } else if ( x <= a + pi * b ) { y = ( x - a ) / b; pdf = 1.0 / ( 2.0 * pi * b ) * cos ( y ); } else if ( a + pi * b < x ) { pdf = 0.0; } return pdf; } //****************************************************************************80 double cosine_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // COSINE_SAMPLE samples the Cosine PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double COSINE_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = cosine_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double cosine_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // COSINE_VARIANCE returns the variance of the Cosine PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double VARIANCE, the variance of the PDF. // { const double pi = 3.14159265358979323; double variance; variance = ( pi * pi / 3.0 - 2.0 ) * b * b; return variance; } //****************************************************************************80 double coupon_complete_pdf ( int type_num, int box_num ) //****************************************************************************80 // // Purpose: // // COUPON_COMPLETE_PDF evaluates the Complete Coupon Collection PDF. // // Discussion: // // PDF(TYPE_NUM;BOX_NUM) is the probability that, given an inexhaustible // supply of boxes, inside each of which there is one of TYPE_NUM distinct // coupons, which are uniformly distributed among the boxes, that it will // require opening exactly BOX_NUM boxes to achieve at least one of each // kind of coupon. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 August 2006 // // Author: // // John Burkardt // // Reference: // // Herbert Wilf, // Some New Aspects of the Coupon Collector's Problem, // SIAM Review, // Volume 48, Number 3, September 2006, pages 549-565. // // Parameters: // // Input, int BOX_NUM, the number of boxes that had to be opened // in order to just get at least one of each coupon. // 0 <= BOX_NUM. If BOX_NUM < TYPE_NUM, then PDF is surely 0. // // Input, int TYPE_NUM, the number of distinct coupons. // 1 <= TYPE_NUM. // // Output, double COUPON_COMPLETE_PDF, the value of the PDF. // { double factor; int i; double pdf; // // Nonsense cases. // if ( box_num < 0 ) { pdf = 0.0; } else if ( type_num < 1 ) { pdf = 0.0; } // // Degenerate but meaningful case. // else if ( type_num == 1 ) { if ( box_num == 1 ) { pdf = 1.0; } else { pdf = 0.0; } } // // Easy cases. // else if ( box_num < type_num ) { pdf = 0.0; } // // General case. // else { factor = 1.0; for ( i = 1; i <= type_num; i++ ) { factor = factor * ( double ) ( i ) / ( double ) ( type_num ); } for ( i = type_num+1; i <= box_num; i++ ) { factor = factor / ( double ) ( type_num ); } pdf = factor * ( double ) ( stirling2_value ( box_num-1, type_num-1 ) ); } return pdf; } //****************************************************************************80 double coupon_mean ( int j, int type_num ) //****************************************************************************80 // // Purpose: // // COUPON_MEAN returns the mean of the Coupon PDF. // // Discussion: // // In this version of the coupon collector's problem, we assume // that each box contains 1 coupon, that there are TYPE_NUM distinct types // of coupon, uniformly distributed among an inexhaustible supply // of boxes, and that the collector's goal is to get J distinct // types of coupons by opening one box after another. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int J, the number of distinct coupons to be collected. // J must be between 1 and N. // // Input, int TYPE_NUM, the number of distinct coupons. // // Output, double COUPON_MEAN, the mean number of boxes that // must be opened in order to just get J distinct kinds. // { int i; double mean; if ( type_num < j ) { cerr << " \n"; cerr << "COUPON_MEAN - Fatal error!\n"; cerr << " Number of distinct coupons desired must be no more\n"; cerr << " than the total number of boxes opened.\n"; exit ( 1 ); } mean = 0.0; for ( i = 1; i <= j; i++ ) { mean = mean + 1.0 / ( double ) ( type_num - i + 1 ); } mean = mean * ( double ) ( type_num ); return mean; } //****************************************************************************80 void coupon_simulate ( int type_num, int &seed, int coupon[], int *box_num ) //****************************************************************************80 // // Purpose: // // COUPON_SIMULATE simulates the coupon collector's problem. // // Discussion: // // The coupon collector needs to collect one of each of TYPE_NUM // coupons. The collector may draw one coupon (or, in some settings, // open one box) on each trial, and takes as many trials as necessary // to complete the task. On each trial, the probability of picking // any particular type of coupon is always 1 / TYPE_NUM. // // Interesting questions include; // // * what is the expected number of drawings necessary to complete // the collection? // // * How does the expected number of drawings necessary to complete // the collection vary as TYPE_NUM increases? // // * What is the distribution of the numbers of each type of coupon // in a typical collection when it is just completed? // // As TYPE_NUM increases, the number of coupons necessary to be // collected in order to get a complete set in any simulation // strongly tends to the value TYPE_NUM * LOG ( TYPE_NUM ). // // If TYPE_NUM is 1, the simulation ends with a single drawing. // // If TYPE_NUM is 2, then we may call the coupon taken on the first drawing // a "Head", say, and the process then is similar to the question of the // length, plus one, of a run of Heads or Tails in coin flipping. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int TYPE_NUM, the number of types of coupons. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int COUPON[TYPE_NUM], the number of coupons of each type // that were collected during the simulation. // // Output, int *BOX_NUM, the total number of boxes opened. // { int i; int box_max = 2000; int straight; for ( i = 0; i < type_num; i++ ) { coupon[i] = 0; } straight = 0; *box_num = 0; // // Draw another coupon. // while ( *box_num < box_max ) { i = i4_uniform_ab ( 1, type_num, seed ); // // Increment the number of I coupons. // coupon[i-1] = coupon[i-1] + 1; *box_num = *box_num + 1; // // If I is the next one we needed, increase STRAIGHT by 1. // if ( i == straight + 1 ) { for ( ; ; ) { straight = straight + 1; // // If STRAIGHT = TYPE_NUM, we have all of them. // if ( type_num <= straight ) { return; } // // If the next coupon has not been collected, our straight is over. // if ( coupon[straight] <= 0 ) { break; } } } } cerr << " \n"; cerr << "COUPON_SIMULATE - Fatal error!\n"; cerr << " Maximum number of coupons drawn without success.\n"; exit ( 1 ); } //****************************************************************************80 double coupon_variance ( int j, int type_num ) //****************************************************************************80 // // Purpose: // // COUPON_VARIANCE returns the variance of the Coupon PDF. // // Discussion: // // In this version of the coupon collector's problem, we assume // that each box contains 1 coupon, that there are TYPE_NUM distinct types // of coupon, uniformly distributed among an inexhaustible supply // of boxes, and that the collector's goal is to get J distinct // types of coupons by opening one box after another. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 June 2013 // // Author: // // John Burkardt // // Parameters: // // Input, int J, the number of distinct coupons to be collected. // J must be between 1 and N. // // Input, int TYPE_NUM, the number of distinct coupons. // // Output, double COUPON_VARIANCE, the variance of the number of // boxes that must be opened in order to just get J distinct kinds. // { int i; double variance; if ( type_num < j ) { cerr << " \n"; cerr << "COUPON_VARIANCE - Fatal error!\n"; cerr << " Number of distinct coupons desired must be no more\n"; cerr << " than the total number of distinct coupons.\n"; exit ( 1 ); } variance = 0.0; for ( i = 1; i <= j; i++ ) { variance = variance + ( double ) ( i - 1 ) / pow ( ( double ) ( type_num - i + 1 ), 2 ); } variance = variance * ( double ) ( type_num ); return variance; } //****************************************************************************80 double deranged_cdf ( int x, int a ) //****************************************************************************80 // // Purpose: // // DERANGED_CDF evaluates the Deranged CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the maximum number of items in their correct places. // 0 <= X <= A. // // Input, int A, the number of items. // 1 <= A. // // Output, double CDF, the value of the CDF. // { double cdf; int cnk; int dnmk; int sum2; int x2; if ( x < 0 || a < x ) { cdf = 0.0; } else { sum2 = 0; for ( x2 = 0; x2 <= x; x2++ ) { cnk = binomial_coef ( a, x2 ); dnmk = deranged_enum ( a - x2 ); sum2 = sum2 + cnk * dnmk; } cdf = ( double ) ( sum2 ) / i4_factorial ( a ); } return cdf; } //****************************************************************************80 int deranged_cdf_inv ( double cdf, int a ) //****************************************************************************80 // // Purpose: // // DERANGED_CDF_INV inverts the Deranged CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, int A, the number of items. // 1 <= A. // // Output, int DERANGED_CDF_INV, the corresponding argument. // { double cdf2; double pdf; int x; int x2; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "DERANGED_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } cdf2 = 0.0; for ( x2 = 0; x2 <= a; x2++ ) { pdf = deranged_pdf ( x2, a ); cdf2 = cdf2 + pdf; if ( cdf <= cdf2 ) { x = x2; return x; } } x = a; return x; } //****************************************************************************80 bool deranged_check ( int a ) //****************************************************************************80 // // Purpose: // // DERANGED_CHECK checks the parameter of the Deranged PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the total number of items. // 1 <= A. // // Output, bool DERANGED_CHECK, is true if the parameters are legal. // { if ( a < 1 ) { cerr << " \n"; cerr << "DERANGED_CHECK - Fatal error!\n"; cerr << " A < 1.\n"; return false; } return true; } //****************************************************************************80 int deranged_enum ( int n ) //****************************************************************************80 // // Purpose: // // DERANGED_ENUM returns the number of derangements of N objects. // // Discussion: // // A derangement of N objects is a permutation with no fixed // points. If we symbolize the permutation operation by "P", // then for a derangment, P(I) is never equal to I. // // Recursion: // // D(0) = 1 // D(1) = 0 // D(2) = 1 // D(N) = (N-1) * ( D(N-1) + D(N-2) ) // // or // // D(0) = 1 // D(1) = 0 // D(N) = N * D(N-1) + (-1)^N // // D(N) = N! * ( 1 - 1/1! + 1/2! - 1/3! ... 1/N! ) // // Based on the inclusion/exclusion law. // // D(N) is the number of ways of placing N non-attacking rooks on // an N by N chessboard with one diagonal deleted. // // Limit ( N -> Infinity ) D(N)/N! = 1 / e. // // The number of permutations with exactly K items in the right // place is COMB(N,K) * D(N-K). // // First values: // // N D(N) // 0 1 // 1 0 // 2 1 // 3 2 // 4 9 // 5 44 // 6 265 // 7 1854 // 8 14833 // 9 133496 // 10 1334961 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of objects to be permuted. // // Output, int DERANGED_ENUM, the number of derangements of N objects. // { int dn; int dnm1; int dnm2; int i; if ( n < 0 ) { dn = 0; } else if ( n == 0 ) { dn = 1; } else if ( n == 1 ) { dn = 0; } else if ( n == 2 ) { dn = 1; } else { dnm1 = 0; dn = 1; for ( i = 3; i <= n; i++ ) { dnm2 = dnm1; dnm1 = dn; dn = ( i - 1 ) * ( dnm1 + dnm2 ); } } return dn; } //****************************************************************************80 double deranged_mean ( int a ) //****************************************************************************80 // // Purpose: // // DERANGED_MEAN returns the mean of the Deranged CDF. // // Discussion: // // The mean is computed by straightforward summation. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of items. // 1 <= A. // // Output, double MEAN, the mean of the PDF. // { double mean; double pdf; int x; mean = 0.0; for ( x = 1; x <= a; x++ ) { pdf = deranged_pdf ( x, a ); mean = mean + pdf * x; } return mean; } //****************************************************************************80 double deranged_pdf ( int x, int a ) //****************************************************************************80 // // Purpose: // // DERANGED_PDF evaluates the Deranged PDF. // // Discussion: // // PDF(A;X) is the probability that exactly X items will occur in // their proper place after a random permutation of A items. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the number of items in their correct places. // 0 <= X <= A. // // Input, int A, the total number of items. // 1 <= A. // // Output, double PDF, the value of the PDF. // { int cnk; int dnmk; double pdf; if ( x < 0 || a < x ) { pdf = 0.0; } else { cnk = binomial_coef ( a, x ); dnmk = deranged_enum ( a-x ); pdf = ( double ) ( cnk * dnmk ) / i4_factorial ( a ); } return pdf; } //****************************************************************************80 int deranged_sample ( int a, int &seed ) //****************************************************************************80 // // Purpose: // // DERANGED_SAMPLE samples the Deranged PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of items. // 1 <= A. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int DERANGED_SAMPLE, a sample of the PDF. // { double cdf; int x; cdf = r8_uniform_01 ( seed ); x = deranged_cdf_inv ( cdf, a ); return x; } //****************************************************************************80 double deranged_variance ( int a ) //****************************************************************************80 // // Purpose: // // DERANGED_VARIANCE returns the variance of the Deranged CDF. // // Discussion: // // The variance is computed by straightforward summation. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of items. // 1 <= A. // // Output, double VARIANCE, the variance of the PDF. // { double mean; double pdf; int x; double variance; mean = deranged_mean ( a ); variance = 0.0; for ( x = 1; x <= a; x++ ) { pdf = deranged_pdf ( x, a ); variance = variance + pdf * pow ( ( x - mean ), 2 ); } return variance; } //****************************************************************************80 double digamma ( double x ) //****************************************************************************80 // // Purpose: // // DIGAMMA calculates the digamma or Psi function. // // Discussion: // // DiGamma ( X ) = d ( log ( Gamma ( X ) ) ) / dX // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // Original FORTRAN77 by J Bernardo. // C++ version by John Burkardt. // // Reference: // // J Bernardo, // Algorithm AS 103: // Psi ( Digamma ) Function, // Applied Statistics, // Volume 25, Number 3, pages 315-317, 1976. // // Parameters: // // Input, double X, the argument of the digamma function. // 0 < X. // // Output, double DIGAMMA, the value of the digamma function at X. // { double c = 8.5; double d1 = -0.5772156649; double r; double s = 0.00001; double s3 = 0.08333333333; double s4 = 0.0083333333333; double s5 = 0.003968253968; double value; double y; // // The argument must be positive. // if ( x <= 0.0 ) { value = 0.0; cerr << " \n"; cerr << "DIGAMMA - Fatal error!\n"; cerr << " X <= 0.\n"; exit ( 1 ); } // // Use approximation if argument <= S. // else if ( x <= s ) { value = d1 - 1.0 / x; } // // Reduce the argument to DIGAMMA(X + N) where C <= (X + N). // else { value = 0.0; y = x; while ( y < c ) { value = value - 1.0 / y; y = y + 1.0; } // // Use Stirling's (actually de Moivre's) expansion if C < argument. // r = 1.0 / ( y * y ); value = value + log ( y ) - 0.5 / y - r * ( s3 - r * ( s4 - r * s5 ) ); } return value; } //****************************************************************************80 double dipole_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // DIPOLE_CDF evaluates the Dipole CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // A is arbitrary, but represents an angle, so only 0 <= A <= 2 * PI // is interesting, and -1.0 <= B <= 1.0. // // Output, double DIPOLE_CDF, the value of the CDF. // { double cdf; const double pi = 3.14159265358979323; cdf = 0.5 + ( 1.0 / pi ) * atan ( x ) + b * b * ( x * cos ( 2.0 * a ) - sin ( 2.0 * a ) ) / ( pi * ( 1.0 + x * x ) ); return cdf; } //****************************************************************************80 double dipole_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // DIPOLE_CDF_INV inverts the Dipole CDF. // // Discussion: // // A simple bisection method is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, the parameters of the PDF. // -1.0 <= B <= 1.0. // // Output, double DIPOLE_CDF_INV, the corresponding argument of the CDF. // { double cdf1; double cdf2; double cdf3; int it; int it_max = 100; double tol = 0.0001; double x; double x1; double x2; double x3; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "DIPOLE_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = - r8_huge ( ); return x; } else if ( 1.0 == cdf ) { x = r8_huge ( ); return x; } // // Seek X1 < X < X2. // x1 = - 1.0; for ( ; ; ) { cdf1 = dipole_cdf ( x1, a, b ); if ( cdf1 <= cdf ) { break; } x1 = 2.0 * x1; } x2 = 1.0; for ( ; ; ) { cdf2 = dipole_cdf ( x2, a, b ); if ( cdf <= cdf2 ) { break; } x2 = 2.0 * x2; } // // Now use bisection. // it = 0; for ( ; ; ) { it = it + 1; x3 = 0.5 * ( x1 + x2 ); cdf3 = dipole_cdf ( x3, a, b ); if ( r8_abs ( cdf3 - cdf ) < tol ) { x = x3; break; } if ( it_max < it ) { cerr << " \n"; cerr << "DIPOLE_CDF_INV - Fatal error!\n"; cerr << " Iteration limit exceeded.\n"; exit ( 1 ); } if ( ( cdf3 <= cdf && cdf1 <= cdf ) || ( cdf <= cdf3 && cdf <= cdf1 ) ) { x1 = x3; cdf1 = cdf3; } else { x2 = x3; cdf2 = cdf3; } } return x; } //****************************************************************************80 bool dipole_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // DIPOLE_CHECK checks the parameters of the Dipole CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // A is arbitrary, but represents an angle, so only 0 <= A <= 2 * PI // is interesting, and -1.0 <= B <= 1.0. // // Output, bool DIPOLE_CHECK, is true if the parameters are legal. // { if ( b < -1.0 || 1.0 < b ) { cerr << " \n"; cerr << "DIPOLE_CHECK - Fatal error!\n"; cerr << " -1.0 <= B <= 1.0 is required.\n"; cerr << " The input B = " << b << "\n"; return false; } return true; } //****************************************************************************80 double dipole_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // DIPOLE_PDF evaluates the Dipole PDF. // // Discussion: // // PDF(A,B;X) = // 1 / ( PI * ( 1 + X^2 ) ) // + B^2 * ( ( 1 - X^2 ) * cos ( 2 * A ) + 2.0 * X * sin ( 2 * A ) ) // / ( PI * ( 1 + X )^2 ) // // Densities of this kind commonly occur in the analysis of resonant // scattering of elementary particles. // // DIPOLE_PDF(A,0;X) = CAUCHY_PDF(A;X) // A = 0, B = 1 yields the single channel dipole distribution. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Reference: // // Robert Knop, // Algorithm 441, // ACM Transactions on Mathematical Software. // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // A is arbitrary, but represents an angle, so only 0 <= A <= 2 * PI // is interesting, // and -1.0 <= B <= 1.0. // // Output, double DIPOLE_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; pdf = 1.0 / ( pi * ( 1.0 + x * x ) ) + b * b * ( ( 1.0 - x * x ) * cos ( 2.0 * a ) + 2.0 * x * sin ( 2.0 * x ) ) / ( pi * ( 1.0 + x * x ) * ( 1.0 + x * x ) ); return pdf; } //****************************************************************************80 double dipole_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // DIPOLE_SAMPLE samples the Dipole PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Reference: // // Robert Knop, // Algorithm 441, // ACM Transactions on Mathematical Software. // // Parameters: // // Input, double A, B, the parameters of the PDF. // A is arbitrary, but represents an angle, so only 0 <= A <= 2 * PI // is interesting, // and -1.0 <= B <= 1.0. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double DIPOLE_SAMPLE, a sample of the PDF. // { double a2; double b2; double c2; double x; double *xc; // // Find (X1,X2) at random in a circle. // a2 = b * sin ( a ); b2 = b * cos ( a ); c2 = 1.0; xc = circle_sample ( a2, b2, c2, seed ); // // The dipole variate is the ratio X1 / X2. // x = xc[0] / xc[1]; delete [] xc; return x; } //****************************************************************************80 bool dirichlet_check ( int n, double a[] ) //****************************************************************************80 // // Purpose: // // DIRICHLET_CHECK checks the parameters of the Dirichlet PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of components. // // Input, double A[N], the probabilities for each component. // Each A[I] should be positive. // // Output, bool DIRICHLET_CHECK, is true if the parameters are legal. // { int i; bool positive; positive = false; for ( i = 0; i < n; i++ ) { if ( a[i] <= 0.0 ) { cerr << " \n"; cerr << "DIRICHLET_CHECK - Fatal error!\n"; cerr << " A[" << i << "] <= 0.\n"; cerr << " A[" << i << "] = " << a[i] << ".\n"; return false; } else if ( 0.0 < a[i] ) { positive = true; } } if ( !positive ) { cerr << " \n"; cerr << "DIRICHLET_CHECK - Fatal error!\n"; cerr << " All parameters are zero!\n"; return false; } return true; } //****************************************************************************80 double *dirichlet_mean ( int n, double a[] ) //****************************************************************************80 // // Purpose: // // DIRICHLET_MEAN returns the means of the Dirichlet PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of components. // // Input, double A[N], the probabilities for each component. // Each A[I] should be positive. // // Output, double DIRICHLET_MEAN[N], the means of the PDF. // { int i; double *mean; mean = new double[n]; for ( i = 0; i < n; i++ ) { mean[i] = a[i]; } r8vec_unit_sum ( n, mean ); return mean; } //****************************************************************************80 double *dirichlet_moment2 ( int n, double a[] ) //****************************************************************************80 // // Purpose: // // DIRICHLET_MOMENT2 returns the second moments of the Dirichlet PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of components. // // Input, double A[N], the probabilities for each component. // Each A(I) should be positive. // // Output, double DIRICHLET_MOMENT[N*N], the second moments of the PDF. // { double a_sum; double *m2; int i; int j; m2 = new double[n*n]; a_sum = r8vec_sum ( n, a ); for ( i = 0; i < n; i++ ) { for ( j = 0; j < n; j++ ) { if ( i == j ) { m2[i+j*n] = a[i] * ( a[i] + 1.0 ) / ( a_sum * ( a_sum + 1.0 ) ); } else { m2[i+j*n] = a[i] * a[j] / ( a_sum * ( a_sum + 1.0 ) ); } } } return m2; } //****************************************************************************80 double dirichlet_pdf ( double x[], int n, double a[] ) //****************************************************************************80 // // Purpose: // // DIRICHLET_PDF evaluates the Dirichlet PDF. // // Discussion: // // PDF(N,A;X) = Product ( 1 <= I <= N ) X(I)^( A(I) - 1 ) // * Gamma ( A_SUM ) / A_PROD // // where // // 0 < A(I) for all I; // 0 <= X(I) for all I; // Sum ( 1 <= I <= N ) X(I) = 1; // A_SUM = Sum ( 1 <= I <= N ) A(I). // A_PROD = Product ( 1 <= I <= N ) Gamma ( A(I) ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X(N), the argument of the PDF. Each X(I) should // be greater than 0.0, and the X(I)'s must add up to 1.0. // // Input, int N, the number of components. // // Input, double A(N), the probabilities for each component. // Each A(I) should be positive. // // Output, double PDF, the value of the PDF. // { double a_prod; double a_sum; int i; double pdf; double tol = 0.0001; double x_sum; for ( i = 0; i < n; i++ ) { if ( x[i] <= 0.0 ) { cerr << " \n"; cerr << "DIRICHLET_PDF - Fatal error!\n"; cerr << " X(I) <= 0.\n"; exit ( 1 ); } } x_sum = r8vec_sum ( n, x ); if ( tol < r8_abs ( x_sum - 1.0 ) ) { cerr << " \n"; cerr << "DIRICHLET_PDF - Fatal error!\n"; cerr << " SUM X(I) =/= 1.\n"; exit ( 1 ); } a_sum = r8vec_sum ( n, a ); a_prod = 1.0; for ( i = 0; i < n; i++ ) { a_prod = a_prod * r8_gamma ( a[i] ); } pdf = r8_gamma ( a_sum ) / a_prod; for ( i = 0; i < n; i++ ) { pdf = pdf * pow ( x[i], a[i] - 1.0 ); } return pdf; } //****************************************************************************80 double *dirichlet_sample ( int n, double a[], int &seed ) //****************************************************************************80 // // Purpose: // // DIRICHLET_SAMPLE samples the Dirichlet PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Reference: // // Jerry Banks, editor, // Handbook of Simulation, // Engineering and Management Press Books, 1998, page 169. // // Parameters: // // Input, int N, the number of components. // // Input, double A(N), the probabilities for each component. // Each A(I) should be positive. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double DIRICHLET_SAMPLE[N], a sample of the PDF. The entries // of X should sum to 1. // { double a2; double b2; double c2; int i; double *x; x = new double[n]; a2 = 0.0; b2 = 1.0; for ( i = 0; i < n; i++ ) { c2 = a[i]; x[i] = gamma_sample ( a2, b2, c2, seed ); } // // Rescale the vector to have unit sum. // r8vec_unit_sum ( n, x ); return x; } //****************************************************************************80 double *dirichlet_variance ( int n, double a[] ) //****************************************************************************80 // // Purpose: // // DIRICHLET_VARIANCE returns the variances of the Dirichlet PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of components. // // Input, double A(N), the probabilities for each component. // Each A(I) should be positive. // // Output, double DIRICHLET_VARIANCE(N), the variances of the PDF. // { double a_sum; int i; double *variance; variance = new double[n]; a_sum = r8vec_sum ( n, a ); for ( i = 0; i < n; i++ ) { variance[i] = a[i] * ( a_sum - a[i] ) / ( a_sum * a_sum * ( a_sum + 1.0 ) ); } return variance; } //****************************************************************************80 bool dirichlet_mix_check ( int comp_num, int elem_num, double a[], double comp_weight[] ) //****************************************************************************80 // // Purpose: // // DIRICHLET_MIX_CHECK checks the parameters of a Dirichlet mixture PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int COMP_NUM, the number of components in the Dirichlet // mixture density, that is, the number of distinct Dirichlet PDF's // that are mixed together. // // Input, int ELEM_NUM, the number of elements of an observation. // // Input, double A[ELEM_NUM*COMP_NUM], the probabilities // for element ELEM_NUM in component COMP_NUM. // Each A[I,J] should be positive. // // Input, double COMP_WEIGHT[COMP_NUM], the mixture weights of the densities. // These do not need to be normalized. The weight of a given component is // the relative probability that that component will be used to generate // the sample. // // Output, bool DIRICHLET_MIX_CHECK, is true if the parameters are legal. // { int comp_i; int elem_i; bool positive; for ( comp_i = 0; comp_i < comp_num; comp_i++ ) { for ( elem_i = 0; elem_i < elem_num; elem_i++ ) { if ( a[elem_i+comp_i*elem_num] <= 0.0 ) { cerr << " \n"; cerr << "DIRICHLET_MIX_CHECK - Fatal error!\n"; cerr << " A(ELEM,COMP) <= 0.\n"; cerr << " COMP = " << comp_i << "\n"; cerr << " ELEM = " << elem_i << "\n"; cerr << " A(COMP,ELEM) = " << a[elem_i+comp_i*elem_num] << "\n"; return false; } } } positive = false; for ( comp_i = 0; comp_i < comp_num; comp_i++ ) { if ( comp_weight[comp_i] < 0.0 ) { cerr << " \n"; cerr << "DIRICHLET_MIX_CHECK - Fatal error!\n"; cerr << " COMP_WEIGHT(COMP) < 0.\n"; cerr << " COMP = " << comp_i << "\n"; cerr << " COMP_WEIGHT(COMP) = " << comp_weight[comp_i] << "\n"; return false; } else if ( 0.0 < comp_weight[comp_i] ) { positive = true; } } if ( !positive ) { cerr << " \n"; cerr << "DIRICHLET_MIX_CHECK - Fatal error!\n"; cerr << " All component weights are zero.\n"; return false; } return true; } //****************************************************************************80 double *dirichlet_mix_mean ( int comp_num, int elem_num, double a[], double comp_weight[] ) //****************************************************************************80 // // Purpose: // // DIRICHLET_MIX_MEAN returns the means of a Dirichlet mixture PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 November 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int COMP_NUM, the number of components in the Dirichlet // mixture density, that is, the number of distinct Dirichlet PDF's // that are mixed together. // // Input, int ELEM_NUM, the number of elements of an observation. // // Input, double A[ELEM_NUM*COMP_NUM], the probabilities for // element ELEM_NUM in component COMP_NUM. // Each A[I,J] should be positive. // // Input, double COMP_WEIGHT[COMP_NUM], the mixture weights of the densities. // These do not need to be normalized. The weight of a given component is // the relative probability that that component will be used to generate // the sample. // // Output, double DIRICHLET_MIX_MEAN[ELEM_NUM], the means for each element. // { double *a_vec; int comp_i; double *comp_mean; double comp_weight_sum; int elem_i; double *mean; a_vec = new double[elem_num]; mean = new double[elem_num]; comp_weight_sum = 0.0; for ( comp_i = 0; comp_i < comp_num; comp_i++ ) { comp_weight_sum = comp_weight_sum + comp_weight[comp_i]; } for ( elem_i = 0; elem_i < elem_num; elem_i++ ) { mean[elem_i] = 0.0; } for ( comp_i = 0; comp_i < comp_num; comp_i++ ) { for ( elem_i = 0; elem_i < elem_num; elem_i++ ) { a_vec[elem_i] = a[elem_i+comp_i*elem_num]; } comp_mean = dirichlet_mean ( elem_num, a_vec ); for ( elem_i = 0; elem_i < elem_num; elem_i++ ) { mean[elem_i] = mean[elem_i] + comp_weight[comp_i] * comp_mean[elem_i]; } delete [] comp_mean; } for ( elem_i = 0; elem_i < elem_num; elem_i++ ) { mean[elem_i] = mean[elem_i] / comp_weight_sum; } delete [] a_vec; return mean; } //****************************************************************************80 double dirichlet_mix_pdf ( double x[], int comp_num, int elem_num, double a[], double comp_weight[] ) //****************************************************************************80 // // Purpose: // // DIRICHLET_MIX_PDF evaluates a Dirichlet mixture PDF. // // Discussion: // // The PDF is a weighted sum of Dirichlet PDF's. Each PDF is a // "component", with an associated weight. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X[ELEM_NUM], the argument of the PDF. // // Input, int COMP_NUM, the number of components in the Dirichlet // mixture density, that is, the number of distinct Dirichlet PDF's // that are mixed together. // // Input, int ELEM_NUM, the number of elements of an observation. // // Input, double A[ELEM_NUM*COMP_NUM], the probabilities for // element ELEM_NUM in component COMP_NUM. // Each A[I,J] should be positive. // // Input, double COMP_WEIGHT[COMP_NUM], the mixture weights of the densities. // These do not need to be normalized. The weight of a given component is // the relative probability that that component will be used to generate // the sample. // // Output, double DIRICHLET_MIX_PDF, the value of the PDF. // { double *a_vec; double comp_pdf; double comp_weight_sum; int i; int j; double pdf; a_vec = new double[elem_num]; comp_weight_sum = 0.0; for ( j = 0; j < comp_num; j++ ) { comp_weight_sum = comp_weight_sum + comp_weight[j]; } pdf = 0.0; for ( j = 0; j < comp_num; j++ ) { for ( i = 0; i < elem_num; i++ ) { a_vec[i] = a[i+j*elem_num]; } comp_pdf = dirichlet_pdf ( x, elem_num, a_vec ); pdf = pdf + comp_weight[j] * comp_pdf / comp_weight_sum; } delete [] a_vec; return pdf; } //****************************************************************************80 double *dirichlet_mix_sample ( int comp_num, int elem_num, double a[], double comp_weight[], int &seed, int *comp ) //****************************************************************************80 // // Purpose: // // DIRICHLET_MIX_SAMPLE samples a Dirichlet mixture PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int COMP_NUM, the number of components in the Dirichlet // mixture density, that is, the number of distinct Dirichlet PDF's // that are mixed together. // // Input, int ELEM_NUM, the number of elements of an observation. // // Input, double A[ELEM_NUM*COMP_NUM], the probabilities for // element ELEM_NUM in component COMP_NUM. // Each A[I,J] should be positive. // // Input, double COMP_WEIGHT[COMP_NUM], the mixture weights of the densities. // These do not need to be normalized. The weight of a given component is // the relative probability that that component will be used to generate // the sample. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int *COMP, the index of the component of the Dirichlet // mixture that was chosen to generate the sample. // // Output, double DIRICHLET_MIX_SAMPLE[ELEM_NUM], a sample of the PDF. // { double *a_vec; int elem_i; double *x; a_vec = new double[elem_num]; // // Choose a particular density component COMP. // *comp = discrete_sample ( comp_num, comp_weight, seed ); // // Sample the density number COMP. // for ( elem_i = 0; elem_i < elem_num; elem_i++ ) { a_vec[elem_i] = a[elem_i+(*comp-1)*elem_num]; } x = dirichlet_sample ( elem_num, a_vec, seed ); delete [] a_vec; return x; } //****************************************************************************80 double dirichlet_multinomial_pdf ( int x[], int a, int b, double c[] ) //****************************************************************************80 // // Purpose: // // DIRICHLET_MULTINOMIAL_PDF evaluates a Dirichlet Multinomial PDF. // // Formula: // // PDF(A,B,C;X) = Comb(A,B,X) * ( Gamma(C_Sum) / Gamma(C_Sum+A) ) // Product ( 1 <= I <= B ) Gamma(C(I)+X(I)) / Gamma(C(I)) // // where: // // Comb(A,B,X) is the multinomial coefficient C( A; X(1), X(2), ..., X(B) ), // C_Sum = Sum ( 1 <= I <= B ) C(I) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 October 2004 // // Author: // // John Burkardt // // Reference: // // Kenneth Lange, // Mathematical and Statistical Methods for Genetic Analysis, // Springer, 1997, page 45. // // Parameters: // // Input, int X[B]; X[I] counts the number of occurrences of // outcome I, out of the total of A trials. // // Input, int A, the total number of trials. // // Input, int B, the number of different possible outcomes on // one trial. // // Input, double C[B]; C[I] is the Dirichlet parameter associated // with outcome I. // // Output, double DIRICHLET_MULTINOMIAL_PDF, the value of the Dirichlet // multinomial PDF. // { double c_sum; int i; double pdf; double pdf_log; c_sum = r8vec_sum ( b, c ); pdf_log = - gamma_log ( c_sum + ( double ) ( a ) ) + gamma_log ( c_sum ) + gamma_log ( ( double ) ( a + 1 ) ); for ( i = 0; i < b; i++ ) { pdf_log = pdf_log + gamma_log ( c[i] + ( double ) ( x[i] ) ) - gamma_log ( c[i] ) - gamma_log ( ( double ) ( x[i] + 1 ) ); } pdf = exp ( pdf_log ); return pdf; } //****************************************************************************80 double discrete_cdf ( int x, int a, double b[] ) //****************************************************************************80 // // Purpose: // // DISCRETE_CDF evaluates the Discrete CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the item whose probability is desired. // // Input, int A, the number of probabilities assigned. // // Input, double B[A], the relative probabilities of outcomes // 1 through A. Each entry must be nonnegative. // // Output, double DISCRETE_CDF, the value of the CDF. // { double cdf; if ( x < 1 ) { cdf = 0.0; } else if ( x < a ) { cdf = r8vec_sum ( x, b ) / r8vec_sum ( a, b ); } else if ( a <= x ) { cdf = 1.0; } return cdf; } //****************************************************************************80 int discrete_cdf_inv ( double cdf, int a, double b[] ) //****************************************************************************80 // // Purpose: // // DISCRETE_CDF_INV inverts the Discrete CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, int A, the number of probabilities assigned. // // Input, double B[A], the relative probabilities of outcomes // 1 through A. Each entry must be nonnegative. // // Output, int DISCRETE_CDF_INV, the corresponding argument for which // CDF(X-1) < CDF <= CDF(X) // { double b_sum; double cum; int j; int x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "DISCRETE_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } b_sum = r8vec_sum ( a, b ); cum = 0.0; for ( j = 1; j <= a; j++ ) { cum = cum + b[j-1] / b_sum; if ( cdf <= cum ) { x = j; return x; } } x = a; return x; } //****************************************************************************80 bool discrete_check ( int a, double b[] ) //****************************************************************************80 // // Purpose: // // DISCRETE_CHECK checks the parameters of the Discrete CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of probabilities assigned. // // Input, double B[A], the relative probabilities of // outcomes 1 through A. Each entry must be nonnegative. // // Output, bool DISCRETE_CHECK, is true if the parameters are legal. // { double b_sum; int j; for ( j = 0; j < a; j++ ) { if ( b[j] < 0.0 ) { cerr << " \n"; cerr << "DISCRETE_CHECK - Fatal error!\n"; cerr << " Negative probabilities not allowed.\n"; return false; } } b_sum = r8vec_sum ( a, b ); if ( b_sum == 0.0 ) { cerr << " \n"; cerr << "DISCRETE_CHECK - Fatal error!\n"; cerr << " Total probablity is zero.\n"; return false; } return true; } //****************************************************************************80 double discrete_mean ( int a, double b[] ) //****************************************************************************80 // // Purpose: // // DISCRETE_MEAN evaluates the mean of the Discrete PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of probabilities assigned. // // Input, double B[A], the relative probabilities of // outcomes 1 through A. Each entry must be nonnegative. // // Output, double DISCRETE_MEAN, the mean of the PDF. // { double b_sum; int j; double mean; b_sum = r8vec_sum ( a, b ); mean = 0.0; for ( j = 0; j < a; j++ ) { mean = mean + ( double ) ( j + 1 ) * b[j]; } mean = mean / b_sum; return mean; } //****************************************************************************80 double discrete_pdf ( int x, int a, double b[] ) //****************************************************************************80 // // Purpose: // // DISCRETE_PDF evaluates the Discrete PDF. // // Discusion: // // PDF(A,B;X) = B(X) if 1 <= X <= A // = 0 otherwise // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the item whose probability is desired. // // Input, int A, the number of probabilities assigned. // // Input, double B[A], the relative probabilities of // outcomes 1 through A. Each entry must be nonnegative. // // Output, double DISCRETE_PDF, the value of the PDF. // { double b_sum; double pdf; b_sum = r8vec_sum ( a, b ); if ( 1 <= x && x <= a ) { pdf = b[x-1] / b_sum; } else { pdf = 0.0; } return pdf; } //****************************************************************************80 int discrete_sample ( int a, double b[], int &seed ) //****************************************************************************80 // // Purpose: // // DISCRETE_SAMPLE samples the Discrete PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of probabilities assigned. // // Input, double B[A], the relative probabilities of // outcomes 1 through A. Each entry must be nonnegative. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int DISCRETE_SAMPLE, a sample of the PDF. // { double b_sum; double cdf; int x; b_sum = r8vec_sum ( a, b ); cdf = r8_uniform_01 ( seed ); x = discrete_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double discrete_variance ( int a, double b[] ) //****************************************************************************80 // // Purpose: // // DISCRETE_VARIANCE evaluates the variance of the Discrete PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of probabilities assigned. // // Input, double B[A], the relative probabilities of // outcomes 1 through A. Each entry must be nonnegative. // // Output, double DISCRETE_VARIANCE, the variance of the PDF. // { double b_sum; int j; double mean; double variance; b_sum = r8vec_sum ( a, b ); mean = 0.0; for ( j = 1; j <= a; j++ ) { mean = mean + ( double ) ( j ) * b[j-1]; } mean = mean / b_sum; variance = 0.0; for ( j = 1; j <= a; j++ ) { variance = variance + b[j-1] * pow ( ( double ) j - mean, 2 ); } variance = variance / b_sum; return variance; } //****************************************************************************80 double e_constant ( ) //****************************************************************************80 // // Purpose: // // E_CONSTANT returns the value of E. // // Discussion: // // "E" was named in honor of Euler, but is known as Napier's constant. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 April 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double E_CONSTANT, the base of the natural logarithm system. // { double value = 2.71828182845904523536028747135266249775724709369995; return value; } //****************************************************************************80 double empirical_discrete_cdf ( double x, int a, double b[], double c[] ) //****************************************************************************80 // // Purpose: // // EMPIRICAL_DISCRETE_CDF evaluates the Empirical Discrete CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, int A, the number of values. // 0 < A. // // Input, double B[A], the weights of each value. // 0 <= B(1:A) and at least one value is nonzero. // // Input, double C[A], the values. // The values must be distinct and in ascending order. // // Output, double EMPIRICAL_DISCRETE_CDF, the value of the CDF. // { double bsum; double cdf; int i; cdf = 0.0; bsum = r8vec_sum ( a, b ); for ( i = 1; i <= a; i++ ) { if ( x < c[i-1] ) { return cdf; } cdf = cdf + b[i-1] / bsum; } return cdf; } //****************************************************************************80 double empirical_discrete_cdf_inv ( double cdf, int a, double b[], double c[] ) //****************************************************************************80 // // Purpose: // // EMPIRICAL_DISCRETE_CDF_INV inverts the Empirical Discrete CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, int A, the number of values. // 0 < A. // // Input, double B(A), the weights of each value. // 0 <= B(1:A) and at least one value is nonzero. // // Input, double C(A), the values. // The values must be distinct and in ascending order. // // Output, double EMPIRICAL_DISCRETE_CDF_INV, the smallest argument // whose CDF is greater than or equal to CDF. // { double bsum; double cdf2; int i; double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "EMPIRICAL_DISCRETE_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } bsum = r8vec_sum ( a, b ); x = c[0]; cdf2 = b[0] / bsum; for ( i = 1; i < a; i++ ) { if ( cdf <= cdf2 ) { return x; } x = c[i]; cdf2 = cdf2 + b[i] / bsum; } return x; } //****************************************************************************80 bool empirical_discrete_check ( int a, double b[], double c[] ) //****************************************************************************80 // // Purpose: // // EMPIRICAL_DISCRETE_CHECK checks the parameters of the Empirical Discrete CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of values. // 0 < A. // // Input, double B[A], the weights of each value. // 0 <= B(1:A) and at least one value is nonzero. // // Input, double C[A], the values. // The values must be distinct and in ascending order. // // Output, bool EMPIRICAL_DISCRETE_CHECK, is true if the parameters // are legal. // { int i; int j; bool positive; if ( a <= 0 ) { cerr << " \n"; cerr << "EMPIRICAL_DISCRETE_CHECK - Fatal error!\n"; cerr << " A must be positive.\n"; cerr << " Input A = " << a << "\n"; cerr << " A is the number of weights.\n"; return false; } for ( i = 0; i < a; i++ ) { if ( b[i] < 0.0 ) { cerr << " \n"; cerr << "EMPIRICAL_DISCRETE_CHECK - Fatal error!\n"; cerr << " B[" << i << "] < 0.\n"; cerr << " But all B values must be nonnegative.\n"; return false; } } positive = false; for ( i = 0; i < a; i++ ) { if ( 0.0 < b[i] ) { positive = true; } } if ( !positive ) { cerr << " \n"; cerr << "EMPIRICAL_DISCRETE_CHECK - Fatal error!\n"; cerr << " All B(*) = 0.\n"; cerr << " But at least one B values must be nonzero.\n"; return false; } for ( i = 0; i < a; i++ ) { for ( j = i+1; j < a; j++ ) { if ( c[i] == c[j] ) { cerr << " \n"; cerr << "EMPIRICAL_DISCRETE_CHECK - Fatal error!\n"; cerr << " All values C must be unique.\n"; cerr << " But at least two values are identical.\n"; return false; } } } for ( i = 0; i < a-1; i++ ) { if ( c[i+1] < c[i] ) { cerr << " \n"; cerr << "EMPIRICAL_DISCRETE_CHECK - Fatal error!\n"; cerr << " The values in C must be in ascending order.\n"; return false; } } return true; } //****************************************************************************80 double empirical_discrete_mean ( int a, double b[], double c[] ) //****************************************************************************80 // // Purpose: // // EMPIRICAL_DISCRETE_MEAN returns the mean of the Empirical Discrete PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of values. // 0 < A. // // Input, double B(A), the weights of each value. // 0 <= B(1:A) and at least one value is nonzero. // // Input, double C(A), the values. // The values must be distinct and in ascending order. // // Output, double EMPIRICAL_DISCRETE_MEAN, the mean of the PDF. // { int i; double mean; mean = 0.0; for ( i = 0; i < a; i++ ) { mean = mean + b[i] * c[i]; } mean = mean / r8vec_sum ( a, b ); return mean; } //****************************************************************************80 double empirical_discrete_pdf ( double x, int a, double b[], double c[] ) //****************************************************************************80 // // Purpose: // // EMPIRICAL_DISCRETE_PDF evaluates the Empirical Discrete PDF. // // Discussion: // // A set of A values C(1:A) are assigned nonnegative weights B(1:A), // with at least one B nonzero. The probability of C(I) is the // value of B(I) divided by the sum of the weights. // // The C's must be distinct, and given in ascending order. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, int A, the number of values. // 0 < A. // // Input, double B(A), the weights of each value. // 0 <= B(1:A) and at least one value is nonzero. // // Input, double C(A), the values. // The values must be distinct and in ascending order. // // Output, double EMPIRICAL_DISCRETE_PDF, the value of the PDF. // { int i; double pdf; for ( i = 0; i <= a; i++ ) { if ( x == c[i] ) { pdf = b[i] / r8vec_sum ( a, b ); return pdf; } } pdf = 0.0; return pdf; } //****************************************************************************80 double empirical_discrete_sample ( int a, double b[], double c[], int &seed ) //****************************************************************************80 // // Purpose: // // EMPIRICAL_DISCRETE_SAMPLE samples the Empirical Discrete PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of values. // 0 < A. // // Input, double B(A), the weights of each value. // 0 <= B(1:A) and at least one value is nonzero. // // Input, double C(A), the values. // The values must be distinct and in ascending order. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double EMPIRICAL_DISCRETE_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = empirical_discrete_cdf_inv ( cdf, a, b, c ); return x; } //****************************************************************************80 double empirical_discrete_variance ( int a, double b[], double c[] ) //****************************************************************************80 // // Purpose: // // EMPIRICAL_DISCRETE_VARIANCE returns the variance of the Empirical Discrete PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of values. // 0 < A. // // Input, double B(A), the weights of each value. // 0 <= B(1:A) and at least one value is nonzero. // // Input, double C(A), the values. // The values must be distinct and in ascending order. // // Output, double EMPIRICAL_DISCRETE_VARIANCE, the variance of the PDF. // { double bsum; int i; double mean; double variance; bsum = r8vec_sum ( a, b ); mean = empirical_discrete_mean ( a, b, c ); variance = 0.0; for ( i = 0; i < a; i++ ) { variance = variance + ( b[i] / bsum ) * pow ( c[i] - mean, 2 ); } return variance; } //****************************************************************************80 double english_sentence_length_cdf ( int x ) //****************************************************************************80 // // Purpose: // // ENGLISH_SENTENCE_LENGTH_CDF evaluates the English Sentence Length CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 August 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Input, int X, the sentence length whose CDF is desired. // // Output, double ENGLISH_SENTENCE_LENGTH_CDF, the value of the CDF. // { # define SENTENCE_LENGTH_MAX 79 double cdf; int i; double pdf_vec[SENTENCE_LENGTH_MAX] = { 0.00806, 0.01370, 0.01862, 0.02547, 0.03043, 0.03189, 0.03516, 0.03545, 0.03286, 0.03533, 0.03562, 0.03788, 0.03669, 0.03751, 0.03518, 0.03541, 0.03434, 0.03305, 0.03329, 0.03103, 0.02867, 0.02724, 0.02647, 0.02526, 0.02086, 0.02178, 0.02128, 0.01801, 0.01690, 0.01556, 0.01512, 0.01326, 0.01277, 0.01062, 0.01051, 0.00901, 0.00838, 0.00764, 0.00683, 0.00589, 0.00624, 0.00488, 0.00477, 0.00406, 0.00390, 0.00350, 0.00318, 0.00241, 0.00224, 0.00220, 0.00262, 0.00207, 0.00174, 0.00174, 0.00128, 0.00121, 0.00103, 0.00117, 0.00124, 0.00082, 0.00088, 0.00061, 0.00061, 0.00075, 0.00063, 0.00056, 0.00052, 0.00057, 0.00031, 0.00029, 0.00021, 0.00017, 0.00021, 0.00034, 0.00031, 0.00011, 0.00011, 0.00008, 0.00006 }; double pdf_sum = 0.99768; if ( x < 1 ) { cdf = 0.0; } else if ( x < SENTENCE_LENGTH_MAX ) { cdf = 0.0; for ( i = 0; i < x; i++ ) { cdf = cdf + pdf_vec[i]; } cdf = cdf / pdf_sum; } else if ( SENTENCE_LENGTH_MAX <= x ) { cdf = 1.0; } return cdf; # undef SENTENCE_LENGTH_MAX } //****************************************************************************80 int english_sentence_length_cdf_inv ( double cdf ) //****************************************************************************80 // // Purpose: // // ENGLISH_SENTENCE_LENGTH_CDF_INV inverts the English Sentence Length CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 August 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Output, int ENGLISH_SENTENCE_LENGTH_CDF_INV, the corresponding sentence // length for which CDF(X-1) < CDF <= CDF(X) // { # define SENTENCE_LENGTH_MAX 79 double cum; int j; double pdf_vec[SENTENCE_LENGTH_MAX] = { 0.00806, 0.01370, 0.01862, 0.02547, 0.03043, 0.03189, 0.03516, 0.03545, 0.03286, 0.03533, 0.03562, 0.03788, 0.03669, 0.03751, 0.03518, 0.03541, 0.03434, 0.03305, 0.03329, 0.03103, 0.02867, 0.02724, 0.02647, 0.02526, 0.02086, 0.02178, 0.02128, 0.01801, 0.01690, 0.01556, 0.01512, 0.01326, 0.01277, 0.01062, 0.01051, 0.00901, 0.00838, 0.00764, 0.00683, 0.00589, 0.00624, 0.00488, 0.00477, 0.00406, 0.00390, 0.00350, 0.00318, 0.00241, 0.00224, 0.00220, 0.00262, 0.00207, 0.00174, 0.00174, 0.00128, 0.00121, 0.00103, 0.00117, 0.00124, 0.00082, 0.00088, 0.00061, 0.00061, 0.00075, 0.00063, 0.00056, 0.00052, 0.00057, 0.00031, 0.00029, 0.00021, 0.00017, 0.00021, 0.00034, 0.00031, 0.00011, 0.00011, 0.00008, 0.00006 }; double pdf_sum = 0.99768; int x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "ENGLISH_SENTENCE_LENGTH_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } cum = 0.0; for ( j = 0; j < SENTENCE_LENGTH_MAX; j++ ) { cum = cum + pdf_vec[j]; if ( cdf <= cum / pdf_sum ) { x = j + 1; return x; } } x = SENTENCE_LENGTH_MAX; return x; # undef SENTENCE_LENGTH_MAX } //****************************************************************************80 double english_sentence_length_mean ( ) //****************************************************************************80 // // Purpose: // // ENGLISH_SENTENCE_LENGTH_MEAN evaluates the mean of the English Sentence Length PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 August 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Output, double ENGLISH_SENTENCE_LENGTH_MEAN, the mean of the PDF. // { # define SENTENCE_LENGTH_MAX 79 int j; double mean; double pdf_vec[SENTENCE_LENGTH_MAX] = { 0.00806, 0.01370, 0.01862, 0.02547, 0.03043, 0.03189, 0.03516, 0.03545, 0.03286, 0.03533, 0.03562, 0.03788, 0.03669, 0.03751, 0.03518, 0.03541, 0.03434, 0.03305, 0.03329, 0.03103, 0.02867, 0.02724, 0.02647, 0.02526, 0.02086, 0.02178, 0.02128, 0.01801, 0.01690, 0.01556, 0.01512, 0.01326, 0.01277, 0.01062, 0.01051, 0.00901, 0.00838, 0.00764, 0.00683, 0.00589, 0.00624, 0.00488, 0.00477, 0.00406, 0.00390, 0.00350, 0.00318, 0.00241, 0.00224, 0.00220, 0.00262, 0.00207, 0.00174, 0.00174, 0.00128, 0.00121, 0.00103, 0.00117, 0.00124, 0.00082, 0.00088, 0.00061, 0.00061, 0.00075, 0.00063, 0.00056, 0.00052, 0.00057, 0.00031, 0.00029, 0.00021, 0.00017, 0.00021, 0.00034, 0.00031, 0.00011, 0.00011, 0.00008, 0.00006 }; double pdf_sum = 0.99768; mean = 0.0; for ( j = 1; j <= SENTENCE_LENGTH_MAX; j++ ) { mean = mean + ( double ) ( j ) * pdf_vec[j-1]; } mean = mean / pdf_sum; return mean; # undef SENTENCE_LENGTH_MAX } //****************************************************************************80 double english_sentence_length_pdf ( int x ) //****************************************************************************80 // // Purpose: // // ENGLISH_SENTENCE_LENGTH_PDF evaluates the English Sentence Length PDF. // // Discussion: // // PDF(A,B;X) = B(X) if 1 <= X <= A // = 0 otherwise // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 August 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Input, int X, the sentence length whose probability is desired. // // Output, double ENGLISH_SENTENCE_LENGTH_PDF, the value of the PDF. // { # define SENTENCE_LENGTH_MAX 79 double pdf; double pdf_vec[SENTENCE_LENGTH_MAX] = { 0.00806, 0.01370, 0.01862, 0.02547, 0.03043, 0.03189, 0.03516, 0.03545, 0.03286, 0.03533, 0.03562, 0.03788, 0.03669, 0.03751, 0.03518, 0.03541, 0.03434, 0.03305, 0.03329, 0.03103, 0.02867, 0.02724, 0.02647, 0.02526, 0.02086, 0.02178, 0.02128, 0.01801, 0.01690, 0.01556, 0.01512, 0.01326, 0.01277, 0.01062, 0.01051, 0.00901, 0.00838, 0.00764, 0.00683, 0.00589, 0.00624, 0.00488, 0.00477, 0.00406, 0.00390, 0.00350, 0.00318, 0.00241, 0.00224, 0.00220, 0.00262, 0.00207, 0.00174, 0.00174, 0.00128, 0.00121, 0.00103, 0.00117, 0.00124, 0.00082, 0.00088, 0.00061, 0.00061, 0.00075, 0.00063, 0.00056, 0.00052, 0.00057, 0.00031, 0.00029, 0.00021, 0.00017, 0.00021, 0.00034, 0.00031, 0.00011, 0.00011, 0.00008, 0.00006 }; double pdf_sum = 0.99768; if ( 1 <= x && x <= SENTENCE_LENGTH_MAX ) { pdf = pdf_vec[x-1] / pdf_sum; } else { pdf = 0.0; } return pdf; # undef SENTENCE_LENGTH_MAX } //****************************************************************************80 int english_sentence_length_sample ( int &seed ) //****************************************************************************80 // // Purpose: // // ENGLISH_SENTENCE_LENGTH_SAMPLE samples the English Sentence Length PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 August 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Input/output, int &SEED, a seed for the random number generator. // // Output, int ENGLISH_SENTENCE_LENGTH_SAMPLE, a sample of the PDF. // { double cdf; int x; cdf = r8_uniform_01 ( seed ); x = english_sentence_length_cdf_inv ( cdf ); return x; # undef SENTENCE_LENGTH_MAX } //****************************************************************************80 double english_sentence_length_variance ( ) //****************************************************************************80 // // Purpose: // // ENGLISH_SENTENCE_LENGTH_VARIANCE: variance of the English Sentence Length PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 August 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Output, double ENGLISH_SENTENCE_LENGTH_VARIANCE, the variance of the PDF. // { # define SENTENCE_LENGTH_MAX 79 int j; double mean; double pdf_vec[SENTENCE_LENGTH_MAX] = { 0.00806, 0.01370, 0.01862, 0.02547, 0.03043, 0.03189, 0.03516, 0.03545, 0.03286, 0.03533, 0.03562, 0.03788, 0.03669, 0.03751, 0.03518, 0.03541, 0.03434, 0.03305, 0.03329, 0.03103, 0.02867, 0.02724, 0.02647, 0.02526, 0.02086, 0.02178, 0.02128, 0.01801, 0.01690, 0.01556, 0.01512, 0.01326, 0.01277, 0.01062, 0.01051, 0.00901, 0.00838, 0.00764, 0.00683, 0.00589, 0.00624, 0.00488, 0.00477, 0.00406, 0.00390, 0.00350, 0.00318, 0.00241, 0.00224, 0.00220, 0.00262, 0.00207, 0.00174, 0.00174, 0.00128, 0.00121, 0.00103, 0.00117, 0.00124, 0.00082, 0.00088, 0.00061, 0.00061, 0.00075, 0.00063, 0.00056, 0.00052, 0.00057, 0.00031, 0.00029, 0.00021, 0.00017, 0.00021, 0.00034, 0.00031, 0.00011, 0.00011, 0.00008, 0.00006 }; double pdf_sum = 0.99768; double variance; mean = 0.0; for ( j = 1; j <= SENTENCE_LENGTH_MAX; j++ ) { mean = mean + ( double ) ( j ) * pdf_vec[j-1]; } mean = mean / pdf_sum; variance = 0.0; for ( j = 1; j <= SENTENCE_LENGTH_MAX; j++ ) { variance = variance + pdf_vec[j-1] * pow ( ( double ) j - mean, 2 ); } variance = variance / pdf_sum; return variance; # undef SENTENCE_LENGTH_MAX } //****************************************************************************80 double english_word_length_cdf ( int x ) //****************************************************************************80 // // Purpose: // // ENGLISH_WORD_LENGTH_CDF evaluates the English Word Length CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 July 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Input, int X, the word length whose CDF is desired. // // Output, double ENGLISH_WORD_LENGTH_CDF, the value of the CDF. // { # define WORD_LENGTH_MAX 27 double cdf; int i; double pdf_vec[WORD_LENGTH_MAX] = { 0.03160, 0.16975, 0.21192, 0.15678, 0.10852, 0.08524, 0.07724, 0.05623, 0.04032, 0.02766, 0.01582, 0.00917, 0.00483, 0.00262, 0.00099, 0.00050, 0.00027, 0.00022, 0.00011, 0.00006, 0.00005, 0.00002, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001 }; double pdf_sum = 0.99997; if ( x < 1 ) { cdf = 0.0; } else if ( x < WORD_LENGTH_MAX ) { cdf = 0.0; for ( i = 0; i < x; i++ ) { cdf = cdf + pdf_vec[i]; } cdf = cdf / pdf_sum; } else if ( WORD_LENGTH_MAX <= x ) { cdf = 1.0; } return cdf; # undef WORD_LENGTH_MAX } //****************************************************************************80 int english_word_length_cdf_inv ( double cdf ) //****************************************************************************80 // // Purpose: // // ENGLISH_WORD_LENGTH_CDF_INV inverts the English Word Length CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 July 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Output, int ENGLISH_WORD_LENGTH_CDF_INV, the corresponding word // length for which CDF(X-1) < CDF <= CDF(X) // { # define WORD_LENGTH_MAX 27 double cum; int j; double pdf_vec[WORD_LENGTH_MAX] = { 0.03160, 0.16975, 0.21192, 0.15678, 0.10852, 0.08524, 0.07724, 0.05623, 0.04032, 0.02766, 0.01582, 0.00917, 0.00483, 0.00262, 0.00099, 0.00050, 0.00027, 0.00022, 0.00011, 0.00006, 0.00005, 0.00002, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001 }; double pdf_sum = 0.99997; int x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "ENGLISH_WORD_LENGTH_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } cum = 0.0; for ( j = 0; j < WORD_LENGTH_MAX; j++ ) { cum = cum + pdf_vec[j]; if ( cdf <= cum / pdf_sum ) { x = j + 1; return x; } } x = WORD_LENGTH_MAX; return x; # undef WORD_LENGTH_MAX } //****************************************************************************80 double english_word_length_mean ( ) //****************************************************************************80 // // Purpose: // // ENGLISH_WORD_LENGTH_MEAN evaluates the mean of the English Word Length PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 July 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Output, double ENGLISH_WORD_LENGTH_MEAN, the mean of the PDF. // { # define WORD_LENGTH_MAX 27 int j; double mean; double pdf_vec[WORD_LENGTH_MAX] = { 0.03160, 0.16975, 0.21192, 0.15678, 0.10852, 0.08524, 0.07724, 0.05623, 0.04032, 0.02766, 0.01582, 0.00917, 0.00483, 0.00262, 0.00099, 0.00050, 0.00027, 0.00022, 0.00011, 0.00006, 0.00005, 0.00002, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001 }; double pdf_sum = 0.99997; mean = 0.0; for ( j = 1; j <= WORD_LENGTH_MAX; j++ ) { mean = mean + ( double ) ( j ) * pdf_vec[j-1]; } mean = mean / pdf_sum; return mean; # undef WORD_LENGTH_MAX } //****************************************************************************80 double english_word_length_pdf ( int x ) //****************************************************************************80 // // Purpose: // // ENGLISH_WORD_LENGTH_PDF evaluates the English Word Length PDF. // // Discussion: // // PDF(A,B;X) = B(X) if 1 <= X <= A // = 0 otherwise // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 July 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Input, int X, the word length whose probability is desired. // // Output, double ENGLISH_WORD_LENGTH_PDF, the value of the PDF. // { # define WORD_LENGTH_MAX 27 double pdf; double pdf_vec[WORD_LENGTH_MAX] = { 0.03160, 0.16975, 0.21192, 0.15678, 0.10852, 0.08524, 0.07724, 0.05623, 0.04032, 0.02766, 0.01582, 0.00917, 0.00483, 0.00262, 0.00099, 0.00050, 0.00027, 0.00022, 0.00011, 0.00006, 0.00005, 0.00002, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001 }; double pdf_sum = 0.99997; if ( 1 <= x && x <= WORD_LENGTH_MAX ) { pdf = pdf_vec[x-1] / pdf_sum; } else { pdf = 0.0; } return pdf; # undef WORD_LENGTH_MAX } //****************************************************************************80 int english_word_length_sample ( int &seed ) //****************************************************************************80 // // Purpose: // // ENGLISH_WORD_LENGTH_SAMPLE samples the English Word Length PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 July 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Input/output, int &SEED, a seed for the random number generator. // // Output, int ENGLISH_WORD_LENGTH_SAMPLE, a sample of the PDF. // { double cdf; int x; cdf = r8_uniform_01 ( seed ); x = english_word_length_cdf_inv ( cdf ); return x; # undef WORD_LENGTH_MAX } //****************************************************************************80 double english_word_length_variance ( ) //****************************************************************************80 // // Purpose: // // ENGLISH_WORD_LENGTH_VARIANCE: variance of the English Word Length PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 July 2006 // // Author: // // John Burkardt // // Reference: // // Henry Kucera, Winthrop Francis, // Computational Analysis of Present-Day American English, // Brown University Press, 1967. // // Parameters: // // Output, double ENGLISH_WORD_LENGTH_VARIANCE, the variance of the PDF. // { # define WORD_LENGTH_MAX 27 int j; double mean; double pdf_vec[WORD_LENGTH_MAX] = { 0.03160, 0.16975, 0.21192, 0.15678, 0.10852, 0.08524, 0.07724, 0.05623, 0.04032, 0.02766, 0.01582, 0.00917, 0.00483, 0.00262, 0.00099, 0.00050, 0.00027, 0.00022, 0.00011, 0.00006, 0.00005, 0.00002, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001 }; double pdf_sum = 0.99997; double variance; mean = 0.0; for ( j = 1; j <= WORD_LENGTH_MAX; j++ ) { mean = mean + ( double ) ( j ) * pdf_vec[j-1]; } mean = mean / pdf_sum; variance = 0.0; for ( j = 1; j <= WORD_LENGTH_MAX; j++ ) { variance = variance + pdf_vec[j-1] * pow ( ( double ) j - mean, 2 ); } variance = variance / pdf_sum; return variance; # undef WORD_LENGTH_MAX } //****************************************************************************80 double erlang_cdf ( double x, double a, double b, int c ) //****************************************************************************80 // // Purpose: // // ERLANG_CDF evaluates the Erlang CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, int C, the parameters of the PDF. // 0.0 < B. // 0 < C. // // Output, double ERLANG_CDF, the value of the CDF. // { double cdf; double p2; double x2; if ( x < a ) { cdf = 0.0; } else { x2 = ( x - a ) / b; p2 = ( double ) ( c ); cdf = gamma_inc ( p2, x2 ); } return cdf; } //****************************************************************************80 double erlang_cdf_inv ( double cdf, double a, double b, int c ) //****************************************************************************80 // // Purpose: // // ERLANG_CDF_INV inverts the Erlang CDF. // // Discussion: // // A simple bisection method is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, int C, the parameters of the PDF. // 0.0 < B. // 0 < C. // // Output, double ERLANG_CDF_INV, the corresponding argument of the CDF. // { double cdf1; double cdf2; double cdf3; int it; int it_max = 100; double tol = 0.0001; double x; double x1; double x2; double x3; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "ERLANG_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = a; return x; } else if ( 1.0 == cdf ) { x = r8_huge ( ); return x; } x1 = a; cdf1 = 0.0; x2 = a + 1.0; for ( ; ; ) { cdf2 = erlang_cdf ( x2, a, b, c ); if ( cdf < cdf2 ) { break; } x2 = a + 2.0 * ( x2 - a ); } // // Now use bisection. // it = 0; for ( ; ; ) { it = it + 1; x3 = 0.5 * ( x1 + x2 ); cdf3 = erlang_cdf ( x3, a, b, c ); if ( r8_abs ( cdf3 - cdf ) < tol ) { x = x3; break; } if ( it_max < it ) { cout << " \n"; cout << "ERLANG_CDF_INV - Warning!\n"; cout << " Iteration limit exceeded.\n"; return x; } if ( ( cdf3 <= cdf && cdf1 <= cdf ) || ( cdf <= cdf3 && cdf <= cdf1 ) ) { x1 = x3; cdf1 = cdf3; } else { x2 = x3; cdf2 = cdf3; } } return x; } //****************************************************************************80 bool erlang_check ( double a, double b, int c ) //****************************************************************************80 // // Purpose: // // ERLANG_CHECK checks the parameters of the Erlang PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, int C, the parameters of the PDF. // 0.0 < B. // 0 < C. // // Output, bool ERLANG_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cerr << " \n"; cerr << "ERLANG_CHECK - Fatal error!\n"; cerr << " B <= 0.0\n"; return false; } if ( c <= 0 ) { cerr << " \n"; cerr << "ERLANG_CHECK - Fatal error!\n"; cerr << " C <= 0.\n"; return false; } return true; } //****************************************************************************80 double erlang_mean ( double a, double b, int c ) //****************************************************************************80 // // Purpose: // // ERLANG_MEAN returns the mean of the Erlang PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, int C, the parameters of the PDF. // 0.0 < B. // 0 < C. // // Output, double ERLANG_MEAN, the mean of the PDF. // { double mean; mean = a + b * ( double ) ( c ); return mean; } //****************************************************************************80 double erlang_pdf ( double x, double a, double b, int c ) //****************************************************************************80 // // Purpose: // // ERLANG_PDF evaluates the Erlang PDF. // // Discussion: // // PDF(A,B,C;X) = ( ( X - A ) / B )^( C - 1 ) // / ( B * Gamma ( C ) * EXP ( ( X - A ) / B ) ) // // for 0 < B, 0 < C integer, A <= X. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, int C, the parameters of the PDF. // 0.0 < B. // 0 < C. // // Output, double ERLANG_PDF, the value of the PDF. // { double pdf; double y; if ( x <= a ) { pdf = 0.0; } else { y = ( x - a ) / b; pdf = pow ( y, c - 1 ) / ( b * i4_factorial ( c - 1 ) * exp ( y ) ); } return pdf; } //****************************************************************************80 double erlang_sample ( double a, double b, int c, int &seed ) //****************************************************************************80 // // Purpose: // // ERLANG_SAMPLE samples the Erlang PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, int C, the parameters of the PDF. // 0.0 < B. // 0 < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double ERLANG_SAMPLE, a sample of the PDF. // { double a2; double b2; int i; double x; double x2; a2 = 0.0; b2 = b; x = a; for ( i = 1; i <= c; i++ ) { x2 = exponential_sample ( a2, b2, seed ); x = x + x2; } return x; } //****************************************************************************80 double erlang_variance ( double a, double b, int c ) //****************************************************************************80 // // Purpose: // // ERLANG_VARIANCE returns the variance of the Erlang PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, int C, the parameters of the PDF. // 0.0 < B. // 0 < C. // // Output, double ERLANG_VARIANCE, the variance of the PDF. // { double variance; variance = b * b * ( double ) ( c ); return variance; } //****************************************************************************80 double error_f ( double x ) //****************************************************************************80 // // Purpose: // // ERROR_F evaluates the error function ERF. // // Discussion: // // Since some compilers already supply a routine named ERF which evaluates // the error function, this routine has been given a distinct, if // somewhat unnatural, name. // // The function is defined by: // // ERF(X) = ( 2 / sqrt ( PI ) ) * Integral ( 0 <= T <= X ) EXP ( - T^2 ) dT. // // Properties of the function include: // // Limit ( X -> -Infinity ) ERF(X) = -1.0; // ERF(0) = 0.0; // ERF(0.476936...) = 0.5; // Limit ( X -> +Infinity ) ERF(X) = +1.0. // // 0.5 * ( ERF(X/sqrt(2)) + 1 ) = Normal_01_CDF(X) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 November 2006 // // Author: // // Original FORTRAN77 versino by William Cody. // C++ version by John Burkardt. // // Reference: // // William Cody, // "Rational Chebyshev Approximations for the Error Function", // Mathematics of Computation, // 1969, pages 631-638. // // Parameters: // // Input, double X, the argument of the error function. // // Output, double ERROR_F, the value of the error function. // { double a[5] = { 3.16112374387056560, 1.13864154151050156E+02, 3.77485237685302021E+02, 3.20937758913846947E+03, 1.85777706184603153E-01 }; double b[4] = { 2.36012909523441209E+01, 2.44024637934444173E+02, 1.28261652607737228E+03, 2.84423683343917062E+03 }; double c[9] = { 5.64188496988670089E-01, 8.88314979438837594, 6.61191906371416295E+01, 2.98635138197400131E+02, 8.81952221241769090E+02, 1.71204761263407058E+03, 2.05107837782607147E+03, 1.23033935479799725E+03, 2.15311535474403846E-08 }; double d[8] = { 1.57449261107098347E+01, 1.17693950891312499E+02, 5.37181101862009858E+02, 1.62138957456669019E+03, 3.29079923573345963E+03, 4.36261909014324716E+03, 3.43936767414372164E+03, 1.23033935480374942E+03 }; double del; double erfxd; int i; double p[6] = { 3.05326634961232344E-01, 3.60344899949804439E-01, 1.25781726111229246E-01, 1.60837851487422766E-02, 6.58749161529837803E-04, 1.63153871373020978E-02 }; double q[5] = { 2.56852019228982242, 1.87295284992346047, 5.27905102951428412E-01, 6.05183413124413191E-02, 2.33520497626869185E-03 }; double sqrpi = 0.56418958354775628695; double thresh = 0.46875; double xabs; double xbig = 26.543; double xden; double xnum; double xsmall = 1.11E-16; double xsq; xabs = r8_abs ( ( x ) ); // // Evaluate ERF(X) for |X| <= 0.46875. // if ( xabs <= thresh ) { if ( xsmall < xabs ) { xsq = xabs * xabs; } else { xsq = 0.0; } xnum = a[4] * xsq; xden = xsq; for ( i = 0; i < 3; i++ ) { xnum = ( xnum + a[i] ) * xsq; xden = ( xden + b[i] ) * xsq; } erfxd = x * ( xnum + a[3] ) / ( xden + b[3] ); } // // Evaluate ERFC(X) for 0.46875 <= |X| <= 4.0. // else if ( xabs <= 4.0 ) { xnum = c[8] * xabs; xden = xabs; for ( i = 0; i < 7; i++ ) { xnum = ( xnum + c[i] ) * xabs; xden = ( xden + d[i] ) * xabs; } erfxd = ( xnum + c[7] ) / ( xden + d[7] ); xsq = ( ( double ) ( ( int ) ( xabs * 16.0 ) ) ) / 16.0; del = ( xabs - xsq ) * ( xabs + xsq ); erfxd = exp ( - xsq * xsq ) * exp ( -del ) * erfxd; erfxd = ( 0.5 - erfxd ) + 0.5; if ( x < 0.0 ) { erfxd = -erfxd; } } // // Evaluate ERFC(X) for 4.0 < |X|. // else { if ( xbig <= xabs ) { if ( 0.0 < x ) { erfxd = 1.0; } else { erfxd = - 1.0; } } else { xsq = 1.0 / ( xabs * xabs ); xnum = p[5] * xsq; xden = xsq; for ( i = 0; i < 4; i++ ) { xnum = ( xnum + p[i] ) * xsq; xden = ( xden + q[i] ) * xsq; } erfxd = xsq * ( xnum + p[4] ) / ( xden + q[4] ); erfxd = ( sqrpi - erfxd ) / xabs; xsq = ( ( double ) ( ( int ) ( xabs * 16.0 ) ) ) / 16.0; del = ( xabs - xsq ) * ( xabs + xsq ); erfxd = exp ( - xsq * xsq ) * exp ( - del ) * erfxd; erfxd = ( 0.5 - erfxd ) + 0.5; if ( x < 0.0 ) { erfxd = -erfxd; } } } return erfxd; } //****************************************************************************80 double error_f_inverse ( double y ) //****************************************************************************80 // // Purpose: // // ERROR_F_INVERSE inverts the error function ERF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 August 2010 // // Author: // // John Burkardt // // Parameters: // // Input, double Y, the value of the error function. // // Output, double ERROR_F_INVERSE, the value X such that // ERROR_F(X) = Y. // { double value; double x; double z; z = ( y + 1.0 ) / 2.0; x = normal_01_cdf_inv ( z ); value = x / sqrt ( 2.0 ); return value; } //****************************************************************************80 double euler_constant ( ) //****************************************************************************80 // // Purpose: // // EULER_CONSTANT returns the value of the Euler-Mascheroni constant. // // Discussion: // // The Euler-Mascheroni constant is often denoted by a lower-case // Gamma. Gamma is defined as // // Gamma = limit ( M -> Infinity ) // ( Sum ( 1 <= N <= M ) 1 / N ) - Log ( M ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double EULER_CONSTANT, the value of the // Euler-Mascheroni constant. // { double value = 0.577215664901532860606512090082402431042; return value; } //****************************************************************************80 double exponential_01_cdf ( double x ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_01_CDF evaluates the Exponential 01 CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Output, double EXPONENTIAL_01_CDF, the value of the CDF. // { double cdf; if ( x <= 0.0 ) { cdf = 0.0; } else { cdf = 1.0 - exp ( - x ); } return cdf; } //****************************************************************************80 double exponential_01_cdf_inv ( double cdf ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_01_CDF_INV inverts the Exponential 01 CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Output, double EXPONENTIAL_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "EXPONENTIAL_01_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = - log ( 1.0 - cdf ); return x; } //****************************************************************************80 double exponential_01_mean ( ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_01_MEAN returns the mean of the Exponential 01 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double EXPONENTIAL_MEAN, the mean of the PDF. // { double mean; mean = 1.0; return mean; } //****************************************************************************80 double exponential_01_pdf ( double x ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_01_PDF evaluates the Exponential 01 PDF. // // Discussion: // // PDF(X) = EXP ( - X ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X // // Output, double PDF, the value of the PDF. // { double pdf; if ( x < 0.0 ) { pdf = 0.0; } else { pdf = exp ( - x ); } return pdf; } //****************************************************************************80 double exponential_01_sample ( int &seed ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_01_SAMPLE samples the Exponential PDF with parameter 1. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input/output, int &SEED, a seed for the random number generator. // // Output, double EXPONENTIAL_01_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = - log ( 1.0 - cdf ); return x; } //****************************************************************************80 double exponential_01_variance ( ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_01_VARIANCE returns the variance of the Exponential 01 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double VARIANCE, the variance of the PDF. // { double variance; variance = 1.0; return variance; } //****************************************************************************80 double exponential_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_CDF evaluates the Exponential CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameter of the PDF. // 0.0 < B. // // Output, double EXPONENTIAL_CDF, the value of the CDF. // { double cdf; if ( x <= a ) { cdf = 0.0; } else { cdf = 1.0 - exp ( ( a - x ) / b ); } return cdf; } //****************************************************************************80 double exponential_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_CDF_INV inverts the Exponential CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double EXPONENTIAL_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "EXPONENTIAL_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a - b * log ( 1.0 - cdf ); return x; } //****************************************************************************80 void exponential_cdf_values ( int &n_data, double &lambda, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_CDF_VALUES returns some values of the Exponential CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = ExponentialDistribution [ lambda ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &LAMBDA, the parameter of the distribution. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 9 static double fx_vec[N_MAX] = { 0.3934693402873666E+00, 0.6321205588285577E+00, 0.7768698398515702E+00, 0.8646647167633873E+00, 0.8646647167633873E+00, 0.9816843611112658E+00, 0.9975212478233336E+00, 0.9996645373720975E+00, 0.9999546000702375E+00 }; static double lambda_vec[N_MAX] = { 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01 }; static double x_vec[N_MAX] = { 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; lambda = 0.0; x = 0.0; fx = 0.0; } else { lambda = lambda_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool exponential_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_CHECK checks the parameters of the Exponential CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameter of the PDF. // 0.0 < B. // // Output, bool EXPONENTIAL_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cerr << " \n"; cerr << "EXPONENTIAL_CHECK - Fatal error!\n"; cerr << " B <= 0.0\n"; return false; } return true; } //****************************************************************************80 double exponential_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_MEAN returns the mean of the Exponential PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double EXPONENTIAL_MEAN, the mean of the PDF. // { double mean; mean = a + b; return mean; } //****************************************************************************80 double exponential_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_PDF evaluates the Exponential PDF. // // Discussion: // // PDF(A,B;X) = ( 1 / B ) * EXP ( ( A - X ) / B ) // // The time interval between two Poisson events is a random // variable with the Exponential PDF. The parameter B is the // average interval between events. // // In another context, the Exponential PDF is related to // the Boltzmann distribution, which describes the relative // probability of finding a system, which is in thermal equilibrium // at absolute temperature T, in a given state having energy E. // The relative probability is // // Boltzmann_Relative_Probability(E,T) = exp ( - E / ( k * T ) ), // // where k is the Boltzmann constant, // // k = 1.38 * 10**(-23) joules / degree Kelvin // // and normalization requires a determination of the possible // energy states of the system. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double EXPONENTIAL_PDF, the value of the PDF. // { double pdf; if ( x < a ) { pdf = 0.0; } else { pdf = ( 1.0 / b ) * exp ( ( a - x ) / b ); } return pdf; } //****************************************************************************80 double exponential_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_SAMPLE samples the Exponential PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double EXPONENTIAL_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = exponential_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double exponential_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // EXPONENTIAL_VARIANCE returns the variance of the Exponential PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double EXPONENTIAL_VARIANCE, the variance of the PDF. // { double variance; variance = b * b; return variance; } //****************************************************************************80 double extreme_values_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // EXTREME_VALUES_CDF evaluates the Extreme Values CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double EXTREME_VALUES_CDF, the value of the CDF. // { double cdf; double y; y = ( x - a ) / b; cdf = exp ( - exp ( - y ) ); return cdf; } //****************************************************************************80 double extreme_values_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // EXTREME_VALUES_CDF_INV inverts the Extreme Values CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double EXTREME_VALUES_CDF_INV, the corresponding argument of the CDF. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "EXTREME_VALUES_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a - b * log ( - log ( cdf ) ); return x; } //****************************************************************************80 void extreme_values_cdf_values ( int &n_data, double &alpha, double &beta, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // EXTREME_VALUES_CDF_VALUES returns some values of the Extreme Values CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = ExtremeValuesDistribution [ alpha, beta ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 September 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &ALPHA, the first parameter of the distribution. // // Output, double &BETA, the second parameter of the distribution. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 12 static double alpha_vec[N_MAX] = { 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01 }; static double beta_vec[N_MAX] = { 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; static double fx_vec[N_MAX] = { 0.3678794411714423E+00, 0.8734230184931166E+00, 0.9818510730616665E+00, 0.9975243173927525E+00, 0.5452392118926051E+00, 0.4884435800065159E+00, 0.4589560693076638E+00, 0.4409910259429826E+00, 0.5452392118926051E+00, 0.3678794411714423E+00, 0.1922956455479649E+00, 0.6598803584531254E-01 }; static double x_vec[N_MAX] = { 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; alpha = 0.0; beta = 0.0; x = 0.0; fx = 0.0; } else { alpha = alpha_vec[n_data-1]; beta = beta_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool extreme_values_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // EXTREME_VALUES_CHECK checks the parameters of the Extreme Values CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, bool EXTREME_VALUES_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cerr << " \n"; cerr << "EXTREME_VALUES_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double extreme_values_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // EXTREME_VALUES_MEAN returns the mean of the Extreme Values PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double EXTREME_VALUES_MEAN, the mean of the PDF. // { double mean; mean = a + b * euler_constant ( ); return mean; } //****************************************************************************80 double extreme_values_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // EXTREME_VALUES_PDF evaluates the Extreme Values PDF. // // Discussion: // // PDF(A,B;X) = // ( 1 / B ) * exp ( ( A - X ) / B - exp ( ( A - X ) / B ) ). // // The Extreme Values PDF is also known as the Fisher-Tippet PDF // and the Log-Weibull PDF. // // The special case A = 0 and B = 1 is the Gumbel PDF. // // The Extreme Values PDF is the limiting distribution for the // smallest or largest value in a large sample drawn from // any of a great variety of distributions. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Reference: // // Eric Weisstein, editor, // CRC Concise Encylopedia of Mathematics, // CRC Press, 1998. // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double EXTREME_VALUES_PDF, the value of the PDF. // { double pdf; pdf = ( 1.0 / b ) * exp ( ( a - x ) / b - exp ( ( a - x ) / b ) ); return pdf; } //****************************************************************************80 double extreme_values_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // EXTREME_VALUES_SAMPLE samples the Extreme Values PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double EXTREME_VALUES_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = extreme_values_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double extreme_values_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // EXTREME_VALUES_VARIANCE returns the variance of the Extreme Values PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double EXTREME_VALUES_VARIANCE, the variance of the PDF. // { const double pi = 3.14159265358979323; double variance; variance = pi * pi * b * b / 6.0; return variance; } //****************************************************************************80 double f_cdf ( double x, int m, int n ) //****************************************************************************80 // // Purpose: // // F_CDF evaluates the F central CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Parameters: // // Input, double X, the argument of the CDF. // // Input, int M, N, the parameters of the PDF. // 1 <= M, // 1 <= N. // // Output, double F_CDF, the value of the CDF. // { double arg1; double arg2; double arg3; double cdf; if ( x <= 0.0 ) { cdf = 0.0; } else { arg1 = 0.5 * ( double ) ( n ); arg2 = 0.5 * ( double ) ( m ); arg3 = ( double ) ( n ) / ( ( double ) ( n ) + ( double ) ( m ) * x ); cdf = 1.0 - beta_inc ( arg1, arg2, arg3 ); } return cdf; } //****************************************************************************80 void f_cdf_values ( int &n_data, int &a, int &b, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // F_CDF_VALUES returns some values of the F CDF test function. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = FRatioDistribution [ dfn, dfd ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, int &A, int &B, the parameters of the function. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 20 static int a_vec[N_MAX] = { 1, 1, 5, 1, 2, 4, 1, 6, 8, 1, 3, 6, 1, 1, 1, 1, 2, 3, 4, 5 }; static int b_vec[N_MAX] = { 1, 5, 1, 5, 10, 20, 5, 6, 16, 5, 10, 12, 5, 5, 5, 5, 5, 5, 5, 5 }; static double fx_vec[N_MAX] = { 0.5000000000000000E+00, 0.4999714850534485E+00, 0.4996034370170990E+00, 0.7496993658293228E+00, 0.7504656462757382E+00, 0.7514156325324275E+00, 0.8999867031372156E+00, 0.8997127554259699E+00, 0.9002845660853669E+00, 0.9500248817817622E+00, 0.9500574946122442E+00, 0.9501926400000000E+00, 0.9750133887312993E+00, 0.9900022327445249E+00, 0.9949977837872073E+00, 0.9989999621122122E+00, 0.5687988496283079E+00, 0.5351452100063650E+00, 0.5143428032407864E+00, 0.5000000000000000E+00 }; static double x_vec[N_MAX] = { 1.00E+00, 0.528E+00, 1.89E+00, 1.69E+00, 1.60E+00, 1.47E+00, 4.06E+00, 3.05E+00, 2.09E+00, 6.61E+00, 3.71E+00, 3.00E+00, 10.01E+00, 16.26E+00, 22.78E+00, 47.18E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; a = 0; b = 0; x = 0.0; fx = 0.0; } else { a = a_vec[n_data-1]; b = b_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool f_check ( int m, int n ) //****************************************************************************80 // // Purpose: // // F_CHECK checks the parameters of the F PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the parameters of the PDF. // 1 <= M, // 1 <= N. // // Output, bool F_CHECK, is true if the parameters are legal. // { if ( m <= 0 ) { cerr << "\n"; cerr << "F_CHECK - Fatal error!\n"; cerr << " M <= 0.\n"; return false; } if ( n <= 0 ) { cerr << "\n"; cerr << "F_CHECK - Fatal error!\n"; cerr << " N <= 0.\n"; return false; } return true; } //****************************************************************************80 double f_mean ( int m, int n ) //****************************************************************************80 // // Purpose: // // F_MEAN returns the mean of the F central PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the parameters of the PDF. // 1 <= M, // 1 <= N. // Note, however, that the mean is not defined unless 3 <= N. // // Output, double F_MEAN, the mean of the PDF. // { double mean; if ( n < 3 ) { cerr << " \n"; cerr << "F_MEAN - Fatal error!\n"; cerr << " The mean is not defined for N < 3.\n"; exit ( 1 ); } mean = ( double ) ( n ) / ( double ) ( n - 2 ); return mean; } //****************************************************************************80 double f_pdf ( double x, int m, int n ) //****************************************************************************80 // // Purpose: // // F_PDF evaluates the F central PDF. // // Discussion: // // PDF(M,N;X) = M^(M/2) * X^((M-2)/2) // / ( Beta(M/2,N/2) * N^(M/2) * ( 1 + (M/N) * X )^((M+N)/2) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X // // Input, int M, N, the parameters of the PDF. // 1 <= M, // 1 <= N. // // Output, double F_PDF, the value of the PDF. // { double a; double b; double bot1; double bot2; double pdf; double top; if ( x < 0.0 ) { pdf = 0.0; } else { a = ( double ) ( m ); b = ( double ) ( n ); top = sqrt ( pow ( a, m ) * pow ( b, n ) * pow ( x, m - 2 ) ); bot1 = beta ( a / 2.0, b / 2.0 ) ; bot2 = sqrt ( pow ( b + a * x, m + n ) ); pdf = top / ( bot1 * bot2 ); } return pdf; } //****************************************************************************80 double f_sample ( int m, int n, int &seed ) //****************************************************************************80 // // Purpose: // // F_SAMPLE samples the F central PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the parameters of the PDF. // 1 <= M, // 1 <= N. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double F_SAMPLE, a sample of the PDF. // { double a; double x; double xm; double xn; a = ( double ) ( m ); xm = chi_square_sample ( a, seed ); a = ( double ) ( n ); xn = chi_square_sample ( a, seed ); x = ( double ) ( n ) * xm / ( ( double ) ( m ) * xn ); return x; } //****************************************************************************80 double f_variance ( int m, int n ) //****************************************************************************80 // // Purpose: // // F_VARIANCE returns the variance of the F central PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the parameters of the PDF. // 1 <= M, // 1 <= N. // Note, however, that the variance is not defined unless 5 <= N. // // Output, double F_VARIANCE, the variance of the PDF. // { double variance; if ( n < 5 ) { cerr << " \n"; cerr << "F_VARIANCE - Fatal error!\n"; cerr << " The variance is not defined for N < 5.\n"; exit ( 1 ); } variance = ( double ) ( 2 * n * n * ( m + n - 2 ) ) / ( double ) ( m * ( n - 2 ) * ( n - 2 ) * ( n - 4 ) ); return variance; } //****************************************************************************80 void f_noncentral_cdf_values ( int &n_data, int &n1, int &n2, double &lambda, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // F_NONCENTRAL_CDF_VALUES returns some values of the F CDF test function. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = NoncentralFRatioDistribution [ n1, n2, lambda ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, int &N1, int &N2, the numerator and denominator // degrees of freedom. // // Output, double &LAMBDA, the noncentrality parameter. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 22 static double fx_vec[N_MAX] = { 0.5000000000000000E+00, 0.6367825323508774E+00, 0.5840916116305482E+00, 0.3234431872392788E+00, 0.4501187879813550E+00, 0.6078881441188312E+00, 0.7059275551414605E+00, 0.7721782003263727E+00, 0.8191049017635072E+00, 0.3170348430749965E+00, 0.4327218008454471E+00, 0.4502696915707327E+00, 0.4261881186594096E+00, 0.6753687206341544E+00, 0.4229108778879005E+00, 0.6927667261228938E+00, 0.3632174676491226E+00, 0.4210054012695865E+00, 0.4266672258818927E+00, 0.4464016600524644E+00, 0.8445888579504827E+00, 0.4339300273343604E+00 }; static double lambda_vec[N_MAX] = { 0.00E+00, 0.00E+00, 0.25E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 2.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 2.00E+00, 1.00E+00, 1.00E+00, 0.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00 }; static int n1_vec[N_MAX] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 16 }; static int n2_vec[N_MAX] = { 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 5, 5, 5, 5, 1, 5, 6, 12, 16, 8 }; static double x_vec[N_MAX] = { 1.00E+00, 1.00E+00, 1.00E+00, 0.50E+00, 1.00E+00, 2.00E+00, 3.00E+00, 4.00E+00, 5.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 2.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 2.00E+00, 2.00E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; n1 = 0; n2 = 0; lambda = 0.0; x = 0.0; fx = 0.0; } else { n1 = n1_vec[n_data-1]; n2 = n2_vec[n_data-1]; lambda = lambda_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool f_noncentral_check ( double a, int m, int n ) //****************************************************************************80 // // Purpose: // // F_NONCENTRAL_CHECK checks the parameters of the F noncentral PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, a parameter of the PDF. // // Input, int M, N, the parameters of the PDF. // 1 <= M, // 1 <= N. // // Output, bool F_NONCENTRAL_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cerr << " \n"; cerr << "F_NONCENTRAL_CHECK - Fatal error!\n"; cerr << " A <= 0.\n"; exit ( 1 ); } if ( m <= 0 ) { cerr << "\n"; cerr << "F_NONCENTRAL_CHECK - Fatal error!\n"; cerr << " M <= 0.\n"; return false; } if ( n <= 0 ) { cerr << "\n"; cerr << "F_NONCENTRAL_CHECK - Fatal error!\n"; cerr << " N <= 0.\n"; return false; } return true; } //****************************************************************************80 double f_noncentral_mean ( double a, int m, int n ) //****************************************************************************80 // // Purpose: // // F_NONCENTRAL_MEAN returns the mean of the F noncentral PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double A, a parameter of the PDF. // // Input, int M, N, parameters of the PDF. // 1 <= M, // 1 <= N. // Note, however, that the mean is not defined unless 3 <= N. // // Output, double F_NONCENTAL_MEAN, the mean of the PDF. // { double mean; if ( n < 3 ) { cerr << " \n"; cerr << "F_NONCENTRAL_MEAN - Fatal error!\n"; cerr << " The mean is not defined for N < 3.\n"; exit ( 1 ); } mean = ( ( double ) ( m ) + a ) * ( double ) ( n ) / ( ( double ) ( m ) * ( double ) ( n - 2 ) ); return mean; } //****************************************************************************80 double f_noncentral_variance ( double a, int m, int n ) //****************************************************************************80 // // Purpose: // // F_NONCENTRAL_VARIANCE returns the variance of the F noncentral PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, a parameter of the PDF. // // Input, int M, N, parameters of the PDF. // 1 <= M, // 1 <= N. // Note, however, that the variance is not defined unless 5 <= N. // // Output, double F_NONCENTRAL_VARIANCE, the variance of the PDF. // { double mr; double nr; double variance; if ( n < 5 ) { cerr << " \n"; cerr << "F_NONCENTRAL_VARIANCE - Fatal error!\n"; cerr << " The variance is not defined for N < 5.\n"; exit ( 1 ); } mr = ( double ) ( m ); nr = ( double ) ( n ); variance = ( ( mr + a ) * ( mr + a ) + 2.0 * ( mr + a ) * nr * nr ) / ( ( nr - 2.0 ) * ( nr - 4.0 ) * mr * mr ) - ( mr + a ) * ( mr + a ) * nr * nr / ( ( nr - 2.0 ) * ( nr - 2.0 ) * mr * mr ); return variance; } //****************************************************************************80 double factorial_log ( int n ) //****************************************************************************80 // // Purpose: // // FACTORIAL_LOG returns the logarithm of N!. // // Discussion: // // N! = Product ( 1 <= I <= N ) I // // N! = Gamma(N+1). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the argument of the function. // 0 <= N. // // Output, double FACTORIAL_LOG, the logarithm of N!. // { int i; double value; if ( n < 0 ) { cerr << "\n"; cerr << "FACTORIAL_LOG - Fatal error!\n"; cerr << " N < 0.\n"; exit ( 1 ); } value = 0.0; for ( i = 2; i <= n; i++ ) { value = value + log ( ( double ) ( i ) ); } return value; } //****************************************************************************80 double factorial_stirling ( int n ) //****************************************************************************80 // // Purpose: // // FACTORIAL_STIRLING computes Stirling's approximation to N!. // // Discussion: // // N! = Product ( 1 <= I <= N ) I // // Stirling ( N ) = sqrt ( 2 * PI * N ) * ( N / E )^N * E^(1/(12*N) ) // // This routine returns the raw approximation for all nonnegative // values of N. If N is less than 0, the value is returned as 0, // and if N is 0, the value of 1 is returned. In all other cases, // Stirling's formula is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the argument of the function. // // Output, double FACTORIAL_STIRLING, an approximation to N!. // { const double e_natural = 2.71828182845904523536028747135266249775724709369995; const double pi = 3.14159265358979323; double value; if ( n < 0 ) { value = 0.0; } else if ( n == 0 ) { value = 1.0; } else { value = sqrt ( 2.0 * pi * ( double ) ( n ) ) * pow ( ( double ) ( n ) / e_natural, n ) * exp ( 1.0 / ( double ) ( 12 * n ) ); } return value; } //****************************************************************************80 double fisher_pdf ( double x[3], double kappa, double mu[3] ) //****************************************************************************80 // // Purpose: // // FISHER_PDF evaluates the Fisher PDF. // // Discussion: // // The formula for the PDF is: // // PDF(KAPPA,MU;X) = C(KAPPA) * exp ( KAPPA * MU' * X ) // // where: // // 0 <= KAPPA is the concentration parameter, // MU is a point on the unit sphere, the mean direction, // X is any point on the unit sphere, // and C(KAPPA) is a normalization factor: // // C(KAPPA) = sqrt ( KAPPA ) / ( ( 2 * pi )^(3/2) * I(0.5,KAPPA) ) // // where // // I(nu,X) is the Bessel function of order NU and argument X. // // For a fixed value of MU, the value of KAPPA determines the // tendency of sample points to tend to be near MU. In particular, // KAPPA = 0 corresponds to a uniform distribution of points on the // sphere, but as KAPPA increases, the sample points will tend to // cluster more closely to MU. // // The Fisher distribution for points on the unit sphere is // analogous to the normal distribution of points on a line, // and, more precisely, to the von Mises distribution on a circle. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 March 2007 // // Author: // // John Burkardt // // Reference: // // Kanti Mardia, Peter Jupp, // Directional Statistics, // Wiley, 2000, // LC: QA276.M335 // // Parameters: // // Input, double X[3], the argument of the PDF. // X should have unit Euclidean norm, but this routine will // automatically work with a normalized version of X. // // Input, double KAPPA, the concentration parameter. // 0 <= KAPPA is required. // // Input, double MU[3], the mean direction. // MU should have unit Euclidean norm, but this routine will // automatically work with a normalized version of MU. // // Output, double FISHER_PDF, the value of the PDF. // { # define NB 1 double alpha; double arg; double b[NB]; double cf; int ize; double mu_norm; int ncalc; double pdf; double pi = 3.141592653589793; double x_norm; if ( kappa < 0.0 ) { cerr << "\n"; cerr << "FISHER_PDF - Fatal error!\n"; cerr << " KAPPA must be nonnegative.\n"; cerr << " Input KAPPA = " << kappa << "\n"; exit ( 1 ); } if ( kappa == 0.0 ) { pdf = 1.0 / ( 4.0 * pi ); return pdf; } alpha = 0.5; ize = 1; ncalc = ribesl ( kappa, alpha, NB, ize, b ); cf = sqrt ( kappa ) / ( sqrt ( pow ( 2.0 * pi, 3 ) ) * b[0] ); mu_norm = r8vec_length ( 3, mu ); if ( mu_norm == 0.0 ) { pdf = cf; return pdf; } x_norm = r8vec_length ( 3, x ); if ( x_norm == 0.0 ) { pdf = cf; return pdf; } arg = kappa * r8vec_dot ( 3, x, mu ) / ( x_norm * mu_norm ); pdf = cf * exp ( arg ); return pdf; # undef NB } //****************************************************************************80 double *fisher_sample ( double kappa, double mu[], int n, int &seed ) //****************************************************************************80 // // Purpose: // // FISHER_SAMPLE samples the Fisher distribution. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 06 March 2007 // // Author: // // John Burkardt // // Reference: // // Nicholas Fisher, Toby Lewis, Brian Embleton, // Statistical Analysis of Spherical Data, // Cambridge, 2003, // ISBN13: 978-0521456999, // LC: QA276.F489. // // Parameters: // // Input, double KAPPA, the concentration parameter. // // Input, double MU[3], the mean direction. // MU should have unit Euclidean norm, but this routine will // automatically work with a normalized version of MU. // // Input, int N, the number of samples to choose. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double FISHER_SAMPLE[3*N], a sample of the Fisher distribution. // // Local Parameters: // // Local, double ALPHA, BETA, the colatitude (theta) and // longitude (phi) of the mean direction. // { double a[3*3]; double alpha; double beta; int i; int j; int k; double lambda; double mu_norm; double *phi; double pi = 3.141592653589793; double rst[3]; double *theta; double *xyz; mu_norm = r8vec_length ( 3, mu ); if ( mu_norm == 0.0 ) { cerr << "\n"; cerr << "FISHER_SAMPLE - Fatal error!\n"; cerr << " MU = 0.\n"; exit ( 1 ); } alpha = - acos ( mu[2] / mu_norm ); beta = atan2 ( mu[1], mu[0] ); lambda = exp ( - 2.0 * kappa ); theta = r8vec_uniform_01 ( n, seed ); for ( k = 0; k < n; k++ ) { if ( kappa == 0.0 ) { theta[k] = 2.0 * asin ( sqrt ( 1.0 - theta[k] ) ); } else { theta[k] = 2.0 * asin ( sqrt ( - log ( theta[k] * ( 1.0 - lambda ) + lambda ) / ( 2.0 * kappa ) ) ); } } phi = r8vec_uniform_01 ( n, seed ); for ( k = 0; k < n; k++ ) { phi[k] = 2.0 * pi * phi[k]; } // // Compute the rotation matrix. // a[0+0*3] = cos ( alpha ) * cos ( beta ); a[1+0*3] = - sin ( beta ); a[2+0*3] = sin ( alpha ) * cos ( beta ); a[0+1*3] = cos ( alpha ) * sin ( beta ); a[1+1*3] = + cos ( beta ); a[2+1*3] = sin ( alpha ) * sin ( beta ); a[0+2*3] = - sin ( alpha ); a[1+2*3] = 0.0; a[2+2*3] = cos ( alpha ); // // Compute the unrotated points. // xyz = new double[3*n]; for ( k = 0; k < n; k++ ) { rst[0] = sin ( theta[k] ) * cos ( phi[k] ); rst[1] = sin ( theta[k] ) * sin ( phi[k] ); rst[2] = cos ( theta[k] ); // // Rotate the points. // for ( i = 0; i < 3; i++ ) { xyz[i+k*3] = 0.0; for ( j = 0; j < 3; j++ ) { xyz[i+k*3] = xyz[i+k*3] + a[i+j*3] * rst[j]; } } } delete [] theta; delete [] phi; return xyz; } //****************************************************************************80 double fisk_cdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // FISK_CDF evaluates the Fisk CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double FISK_CDF, the value of the CDF. // { double cdf; if ( x <= a ) { cdf = 0.0; } else { cdf = 1.0 / ( 1.0 + pow ( ( b / ( x - a ) ), c ) ); } return cdf; } //****************************************************************************80 double fisk_cdf_inv ( double cdf, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // FISK_CDF_INV inverts the Fisk CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double FISK_CDF_INV, the corresponding argument of the CDF. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "FISK_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf <= 0.0 ) { x = a; } else if ( cdf < 1.0 ) { x = a + b * pow ( cdf / ( 1.0 - cdf ), 1.0 / c ); } else if ( 1.0 <= cdf ) { x = r8_huge ( ); } return x; } //****************************************************************************80 bool fisk_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // FISK_CHECK checks the parameters of the Fisk PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, bool FISK_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cerr << " \n"; cerr << "FISK_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } if ( c <= 0.0 ) { cerr << " \n"; cerr << "FISK_CHECK - Fatal error!\n"; cerr << " C <= 0.\n"; return false; } return true; } //****************************************************************************80 double fisk_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // FISK_MEAN returns the mean of the Fisk PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double FISK_MEAN, the mean of the PDF. // { double mean; const double pi = 3.14159265358979323; if ( c <= 1.0 ) { cerr << " \n"; cerr << "FISK_MEAN - Fatal error!\n"; cerr << " No mean defined for C <= 1.0\n"; exit ( 1 ); } mean = a + pi * ( b / c ) * r8_csc ( pi / c ); return mean; } //****************************************************************************80 double fisk_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // FISK_PDF evaluates the Fisk PDF. // // Discussion: // // PDF(A,B,C;X) = // ( C / B ) * ( ( X - A ) / B )^( C - 1 ) / // ( 1 + ( ( X - A ) / B )^C )^2 // // The Fisk PDF is also known as the Log Logistic PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double FISK_PDF, the value of the PDF. // { double pdf; double y; if ( x <= a ) { pdf = 0.0; } else { y = ( x - a ) / b; pdf = ( c / b ) * pow ( y, ( c - 1.0 ) ) / pow ( ( 1.0 + pow ( y, c ) ), 2 ); } return pdf; } //****************************************************************************80 double fisk_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // FISK_SAMPLE samples the Fisk PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double FISK_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = fisk_cdf_inv ( cdf, a, b, c ); return x; } //****************************************************************************80 double fisk_variance ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // FISK_VARIANCE returns the variance of the Fisk PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double FISK_VARIANCE, the variance of the PDF. // { double g; const double pi = 3.14159265358979323; double variance; if ( c <= 2.0 ) { cerr << " \n"; cerr << "FISK_VARIANCE - Fatal error!\n"; cerr << " No variance defined for C <= 2.0\n"; exit ( 1 ); } g = pi / c; variance = b * b * ( 2.0 * g * r8_csc ( 2.0 * g ) - pow ( ( g * r8_csc ( g ) ), 2 ) ); return variance; } //****************************************************************************80 double folded_normal_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // FOLDED_NORMAL_CDF evaluates the Folded Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // 0.0 <= X. // // Input, double A, B, the parameters of the PDF. // 0.0 <= A, // 0.0 < B. // // Output, double FOLDED_NORMAL_CDF, the value of the CDF. // { double cdf; double cdf1; double cdf2; double x1; double x2; if ( x < 0.0 ) { cdf = 0.0; } else { x1 = ( x - a ) / b; cdf1 = normal_01_cdf ( x1 ); x2 = ( - x - a ) / b; cdf2 = normal_01_cdf ( x2 ); cdf = cdf1 - cdf2; } return cdf; } //****************************************************************************80 double folded_normal_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // FOLDED_NORMAL_CDF_INV inverts the Folded Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 <= A, // 0.0 < B. // // Output, double FOLDED_NORMAL_CDF_INV, the argument of the CDF. // 0.0 <= X. // { double cdf1; double cdf2; double cdf3; int it; int it_max = 100; double tol = 0.0001; double x; double x1; double x2; double x3; double xa; double xb; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "FOLDED_NORMAL_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = 0.0; return x; } else if ( 1.0 == cdf ) { x = r8_huge ( ); return x; } // // Find X1, for which the value of CDF will be too small. // if ( 0.0 <= a ) { x1 = normal_cdf_inv ( cdf, a, b ); } else { x1 = normal_cdf_inv ( cdf, -a, b ); } x1 = r8_max ( x1, 0.0 ); cdf1 = folded_normal_cdf ( x1, a, b ); // // Find X2, for which the value of CDF will be too big. // cdf2 = ( 1.0 - cdf ) / 2.0; xa = normal_cdf_inv ( cdf2, a, b ); xb = normal_cdf_inv ( cdf2, -a, b ); x2 = r8_max ( r8_abs ( xa ), r8_abs ( xb ) ); cdf2 = folded_normal_cdf ( x2, a, b ); // // Now use bisection. // it = 0; for ( ; ; ) { it = it + 1; x3 = 0.5 * ( x1 + x2 ); cdf3 = folded_normal_cdf ( x3, a, b ); if ( r8_abs ( cdf3 - cdf ) < tol ) { x = x3; break; } if ( it_max < it ) { cerr << " \n"; cerr << "FOLDED_NORMAL_CDF_INV - Fatal error!\n"; cerr << " Iteration limit exceeded.\n"; exit ( 1 ); } if ( ( cdf3 <= cdf && cdf1 <= cdf ) || ( cdf <= cdf3 && cdf <= cdf1 ) ) { x1 = x3; cdf1 = cdf3; } else { x2 = x3; cdf2 = cdf3; } } return x; } //****************************************************************************80 bool folded_normal_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // FOLDED_NORMAL_CHECK checks the parameters of the Folded Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 <= A, // 0.0 < B. // // Output, bool FOLDED_NORMAL_CHECK, is true if the parameters are legal. // { if ( a < 0.0 ) { cerr << " \n"; cerr << "FOLDED_NORMAL_CHECK - Fatal error!\n"; cerr << " A < 0.\n"; return false; } if ( b <= 0.0 ) { cerr << " \n"; cerr << "FOLDED_NORMAL_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double folded_normal_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // FOLDED_NORMAL_MEAN returns the mean of the Folded Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 <= A, // 0.0 < B. // // Output, double FOLDED_NORMAL_MEAN, the mean of the PDF. // { double a2; double cdf; double mean; const double pi = 3.14159265358979323; a2 = a / b; cdf = normal_01_cdf ( a2 ); mean = b * sqrt ( 2.0 / pi ) * exp ( - 0.5 * a2 * a2 ) - a * ( 1.0 - 2.0 * cdf ); return mean; } //****************************************************************************80 double folded_normal_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // FOLDED_NORMAL_PDF evaluates the Folded Normal PDF. // // Discussion: // // PDF(A;X) = sqrt ( 2 / PI ) * ( 1 / B ) * COSH ( A * X / B^2 ) // * EXP ( - 0.5 * ( X^2 + A^2 ) / B^2 ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X // // Input, double A, B, the parameters of the PDF. // 0.0 <= A, // 0.0 < B. // // Output, double FOLDED_NORMAL_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; if ( x < 0.0 ) { pdf = 0.0; } else { pdf = sqrt ( 2.0 / pi ) * ( 1.0 / b ) * cosh ( a * x / b / b ) * exp ( - 0.5 * ( x * x + a * a ) / b / b ); } return pdf; } //****************************************************************************80 double folded_normal_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // FOLDED_NORMAL_SAMPLE samples the Folded Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 <= A, // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double FOLDED_NORMAL_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = folded_normal_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double folded_normal_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // FOLDED_NORMAL_VARIANCE returns the variance of the Folded Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 <= A, // 0.0 < B. // // Output, double FOLDED_NORMAL_VARIANCE, the variance of the PDF. // { double mean; double variance; mean = folded_normal_mean ( a, b ); variance = a * a + b * b - mean * mean; return variance; } //****************************************************************************80 double frechet_cdf ( double x, double alpha ) //****************************************************************************80 // // Purpose: // // FRECHET_CDF evaluates the Frechet CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 September 2008 // // Author: // // John Burkardt // // Parameters: // // Input, double ALPHA, the parameter. // It is required that 0.0 < ALPHA. // // Input, double X, the argument of the CDF. // // Output, double CDF, the value of the CDF. // { double cdf; if ( alpha <= 0.0 ) { cerr << "\n"; cerr << "FRECHET_CDF - Fatal error!\n"; cerr << " ALPHA <= 0.0.\n"; exit ( 1 ); } if ( x <= 0.0 ) { cdf = 0.0; } else { cdf = exp ( - 1.0 / pow ( x, alpha ) ); } return cdf; } //****************************************************************************80 double frechet_cdf_inv ( double cdf, double alpha ) //****************************************************************************80 // // Purpose: // // FRECHET_CDF_INV inverts the Frechet CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 September 2008 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double ALPHA, the parameter. // It is required that 0.0 < ALPHA. // // Output, double FRECHET_CDF_INV, the corresponding argument of the CDF. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "FRECHET_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( alpha <= 0.0 ) { cerr << "\n"; cerr << "FRECHET_CDF_INV - Fatal error!\n"; cerr << " ALPHA <= 0.0.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = 0.0; } else { x = pow ( - 1.0 / log ( cdf ), 1.0 / alpha ); } return x; } //****************************************************************************80 double frechet_mean ( double alpha ) //****************************************************************************80 // // Purpose: // // FRECHET_MEAN returns the mean of the Frechet PDF. // // Discussion: // // The distribution does not have a mean value unless 1 < ALPHA. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 September 2008 // // Author: // // John Burkardt // // Parameters: // // Input, double ALPHA, the parameter. // It is required that 1.0 < ALPHA. // // Output, double MEAN, the mean of the PDF. // { double mean; if ( alpha <= 1.0 ) { cerr << "\n"; cerr << "FRECHET_MEAN - Fatal error!\n"; cerr << " Mean does not exist if ALPHA <= 1.\n"; exit ( 1 ); } mean = r8_gamma ( ( alpha - 1.0 ) / alpha ); return mean; } //****************************************************************************80 double frechet_pdf ( double x, double alpha ) //****************************************************************************80 // // Purpose: // // FRECHET_PDF evaluates the Frechet PDF. // // Discussion: // // PDF(X) = ALPHA * exp ( -1 / X^ALPHA ) / X^(ALPHA+1) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 September 2008 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double ALPHA, the parameter. // It is required that 0.0 < ALPHA. // // Output, double PDF, the value of the PDF. // { double pdf; if ( alpha <= 0.0 ) { cerr << "\n"; cerr << "FRECHET_PDF - Fatal error!\n"; cerr << " ALPHA <= 0.0.\n"; exit ( 1 ); } pdf = alpha * exp ( - 1.0 / pow ( x, alpha ) ) / pow ( x, alpha + 1.0 ); return pdf; } //****************************************************************************80 double frechet_sample ( double alpha, int &seed ) //****************************************************************************80 // // Purpose: // // FRECHET_SAMPLE samples the Frechet PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 September 2008 // // Author: // // John Burkardt // // Parameters: // // Input, double ALPHA, the parameter. // It is required that 0.0 < ALPHA. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double FRECHET_SAMPLE, a sample of the PDF. // { double cdf; double x; if ( alpha <= 0.0 ) { cerr << "\n"; cerr << "FRECHET_SAMPLE - Fatal error!\n"; cerr << " ALPHA <= 0.0.\n"; exit ( 1 ); } cdf = r8_uniform_01 ( seed ); x = frechet_cdf_inv ( cdf, alpha ); return x; } //****************************************************************************80 double frechet_variance ( double alpha ) //****************************************************************************80 // // Purpose: // // FRECHET_VARIANCE returns the variance of the Frechet PDF. // // Discussion: // // The PDF does not have a variance unless 2 < ALPHA. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 September 2008 // // Author: // // John Burkardt // // Parameters: // // Input, double ALPHA, the parameter. // It is required that 2.0 < ALPHA. // // Output, double VARIANCE, the variance of the PDF. // { double mean; double variance; if ( alpha <= 2.0 ) { cerr << "\n"; cerr << "FRECHET_VARIANCE - Fatal error!\n"; cerr << " Variance does not exist if ALPHA <= 2.\n"; exit ( 1 ); } mean = r8_gamma ( ( alpha - 1.0 ) / alpha ); variance = r8_gamma ( ( alpha - 2.0 ) / alpha ) - mean * mean; return variance; } //****************************************************************************80 double gamma_cdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GAMMA_CDF evaluates the Gamma CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double GAMMA_CDF, the value of the CDF. // { double cdf; double p2; double x2; x2 = ( x - a ) / b; p2 = c; cdf = gamma_inc ( p2, x2 ); return cdf; } //****************************************************************************80 void gamma_cdf_values ( int &n_data, double &mu, double &sigma, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // GAMMA_CDF_VALUES returns some values of the Gamma CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = GammaDistribution [ mu, sigma ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 September 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &MU, the mean of the distribution. // // Output, double &SIGMA, the variance of the distribution. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 12 static double fx_vec[N_MAX] = { 0.8646647167633873E+00, 0.9816843611112658E+00, 0.9975212478233336E+00, 0.9996645373720975E+00, 0.6321205588285577E+00, 0.4865828809674080E+00, 0.3934693402873666E+00, 0.3296799539643607E+00, 0.4421745996289254E+00, 0.1911531694619419E+00, 0.6564245437845009E-01, 0.1857593622214067E-01 }; static double mu_vec[N_MAX] = { 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01 }; static double sigma_vec[N_MAX] = { 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; static double x_vec[N_MAX] = { 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; mu = 0.0; sigma = 0.0; x = 0.0; fx = 0.0; } else { mu = mu_vec[n_data-1]; sigma = sigma_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool gamma_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GAMMA_CHECK checks the parameters of the Gamma PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, bool GAMMA_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cerr << " \n"; cerr << "GAMMA_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; cerr << " B = " << b << "\n"; return false; } if ( c <= 0.0 ) { cerr << " \n"; cerr << "GAMMA_CHECK - Fatal error!\n"; cerr << " C <= 0.\n"; cerr << " C = " << c << "\n"; return false; } return true; } //****************************************************************************80 double gamma_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GAMMA_MEAN returns the mean of the Gamma PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double GAMMA_MEAN, the mean of the PDF. // { double mean; mean = a + b * c; return mean; } //****************************************************************************80 double gamma_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GAMMA_PDF evaluates the Gamma PDF. // // Discussion: // // PDF(A,B,C;X) = EXP ( - ( X - A ) / B ) * ( ( X - A ) / B )^(C-1) // / ( B * GAMMA ( C ) ) // // GAMMA_PDF(A,B,C;X), where C is an integer, is the Erlang PDF. // GAMMA_PDF(A,B,1;X) is the Exponential PDF. // GAMMA_PDF(0,2,C/2;X) is the Chi Squared PDF with C degrees of freedom. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, C, the parameters of the PDF. // A controls the location of the peak; A is often chosen to be 0.0. // B is the "scale" parameter; 0.0 < B, and is often 1.0. // C is the "shape" parameter; 0.0 < C, and is often 1.0. // // Output, double GAMMA_PDF, the value of the PDF. // { double pdf; double y; if ( x <= a ) { pdf = 0.0; } else { y = ( x - a ) / b; pdf = pow ( y, c - 1.0 ) / ( b * r8_gamma ( c ) * exp ( y ) ); } return pdf; } //****************************************************************************80 double gamma_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // GAMMA_SAMPLE samples the Gamma PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // Original FORTRAN77 version by Ahrens and U Dieter. // C++ version by John Burkardt. // // Reference: // // Joachim Ahrens, Ulrich Dieter, // Generating Gamma variates by a modified rejection technique, // Communications of the ACM, // Volume 25, Number 1, January 1982, pages 47-54. // // Joachim Ahrens, Ulrich Dieter, // Computer methods for sampling from Gamma, Beta, Poisson and // binomial distributions, // Computing, // Volume 12, Number 3, September 1974, pages 223-246. // // Joachim Ahrens, Klaus-Dieter Kohrt, Ulrich Dieter,
// Algorithm 599: // Sampling from Gamma and Poisson Distributions,
// ACM Transactions on Mathematical Software,
// Volume 9, Number 2, June 1983, pages 255-257. // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double GAMMA_SAMPLE, a sample of the PDF. // { double a1 = 0.3333333; double a2 = - 0.2500030; double a3 = 0.2000062; double a4 = - 0.1662921; double a5 = 0.1423657; double a6 = - 0.1367177; double a7 = 0.1233795; double bcoef; double co; double d; double e; double e1 = 1.0; double e2 = 0.4999897; double e3 = 0.1668290; double e4 = 0.0407753; double e5 = 0.0102930; double euler = 2.71828182845904; double p; double q; double q0; double q1 = 0.04166669; double q2 = 0.02083148; double q3 = 0.00801191; double q4 = 0.00144121; double q5 = -0.00007388; double q6 = 0.00024511; double q7 = 0.00024240; double r; double s; double si; double s2; double t; double u; double v; double w; double x; // // Allow C = 0. // if ( c == 0.0 ) { x = a; return x; } // // C < 1. // if ( c < 1.0 ) { for ( ; ; ) { u = r8_uniform_01 ( seed ); t = 1.0 + c / euler; p = u * t; s = exponential_01_sample ( seed ); if ( p < 1.0 ) { x = exp ( log ( p ) / c ); if ( x <= s ) { break; } } else { x = - log ( ( t - p ) / c ); if ( ( 1.0 - c ) * log ( x ) <= s ) { break; } } } x = a + b * x; return x; } // // 1 <= C. // else { s2 = c - 0.5; s = sqrt ( c - 0.5 ); d = sqrt ( 32.0 ) - 12.0 * sqrt ( c - 0.5 ); t = normal_01_sample ( seed ); x = pow ( ( sqrt ( c - 0.5 ) + 0.5 * t ), 2 ); if ( 0.0 <= t ) { x = a + b * x; return x; } u = r8_uniform_01 ( seed ); if ( d * u <= t * t * t ) { x = a + b * x; return x; } r = 1.0 / c; q0 = ( ( ( ( ( ( q7 * r + q6 ) * r + q5 ) * r + q4 ) * r + q3 ) * r + q2 ) * r + q1 ) * r; if ( c <= 3.686 ) { bcoef = 0.463 + s - 0.178 * s2; si = 1.235; co = 0.195 / s - 0.079 + 0.016 * s; } else if ( c <= 13.022 ) { bcoef = 1.654 + 0.0076 * s2; si = 1.68 / s + 0.275; co = 0.062 / s + 0.024; } else { bcoef = 1.77; si = 0.75; co = 0.1515 / s; } if ( 0.0 < sqrt ( c - 0.5 ) + 0.5 * t ) { v = 0.5 * t / s; if ( 0.25 < r8_abs ( v ) ) { q = q0 - s * t + 0.25 * t * t + 2.0 * s2 * log ( 1.0 + v ); } else { q = q0 + 0.5 * t * t * ( ( ( ( ( ( a7 * v + a6 ) * v + a5 ) * v + a4 ) * v + a3 ) * v + a2 ) * v + a1 ) * v; } if ( log ( 1.0 - u ) <= q ) { x = a + b * x; return x; } } for ( ; ; ) { e = exponential_01_sample ( seed ); u = r8_uniform_01 ( seed ); u = 2.0 * u - 1.0; t = bcoef + r8_abs ( si * e ) * r8_sign ( u ); if ( -0.7187449 <= t ) { v = 0.5 * t / s; if ( 0.25 < r8_abs ( v ) ) { q = q0 - s * t + 0.25 * t * t + 2.0 * s2 * log ( 1.0 + v ); } else { q = q0 + 0.5 * t * t * ( ( ( ( ( ( a7 * v + a6 ) * v + a5 ) * v + a4 ) * v + a3 ) * v + a2 ) * v + a1 ) * v; } if ( 0.0 < q ) { if ( 0.5 < q ) { w = exp ( q ) - 1.0; } else { w = ( ( ( ( e5 * q + e4 ) * q + e3 ) * q + e2 ) * q + e1 ) * q; } if ( co * r8_abs ( u ) <= w * exp ( e - 0.5 * t * t ) ) { x = a + b * pow ( s + 0.5 * t, 2 ); return x; } } } } } } //****************************************************************************80 double gamma_variance ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GAMMA_VARIANCE returns the variance of the Gamma PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double VARIANCE, the variance of the PDF. // { double variance; variance = b * b * c; return variance; } //****************************************************************************80 double gamma_inc ( double p, double x ) //****************************************************************************80 // // Purpose: // // GAMMA_INC computes the incomplete Gamma function. // // Discussion: // // GAMMA_INC(P, 0) = 0, // GAMMA_INC(P,Infinity) = 1. // // GAMMA_INC(P,X) = Integral ( 0 <= T <= X ) T**(P-1) EXP(-T) DT / GAMMA(P). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // Original FORTRAN77 version by B L Shea. // C++ version by John Burkardt. // // Reference: // // B L Shea, // Chi-squared and Incomplete Gamma Integral, // Algorithm AS239, // Applied Statistics, // Volume 37, Number 3, 1988, pages 466-473. // // Parameters: // // Input, double P, the exponent parameter. // 0.0 < P. // // Input, double X, the integral limit parameter. // If X is less than or equal to 0, GAMMA_INC is returned as 0. // // Output, double GAMMA_INC, the value of the function. // { double a; double arg; double b; double c; double exp_arg_min = -88.0; double overflow = 1.0E+37; double plimit = 1000.0; double pn1; double pn2; double pn3; double pn4; double pn5; double pn6; double rn; double value; double tol = 1.0E-07; double xbig = 1.0E+08; value = 0.0; if ( p <= 0.0 ) { cout << " \n"; cout << "GAMMA_INC - Fatal error!\n"; cout << " Parameter P <= 0.\n"; exit ( 1 ); } if ( x <= 0.0 ) { value = 0.0; return value; } // // Use a normal approximation if PLIMIT < P. // if ( plimit < p ) { pn1 = 3.0 * sqrt ( p ) * ( pow ( x / p, 1.0 / 3.0 ) + 1.0 / ( 9.0 * p ) - 1.0 ); value = normal_01_cdf ( pn1 ); return value; } // // Is X extremely large compared to P? // if ( xbig < x ) { value = 1.0; return value; } // // Use Pearson's series expansion. // (P is not large enough to force overflow in the log of Gamma. // if ( x <= 1.0 || x < p ) { arg = p * log ( x ) - x - gamma_log ( p + 1.0 ); c = 1.0; value = 1.0; a = p; for ( ; ; ) { a = a + 1.0; c = c * x / a; value = value + c; if ( c <= tol ) { break; } } arg = arg + log ( value ); if ( exp_arg_min <= arg ) { value = exp ( arg ); } else { value = 0.0; } } // // Use a continued fraction expansion. // else { arg = p * log ( x ) - x - gamma_log ( p ); a = 1.0 - p; b = a + x + 1.0; c = 0.0; pn1 = 1.0; pn2 = x; pn3 = x + 1.0; pn4 = x * b; value = pn3 / pn4; for ( ; ; ) { a = a + 1.0; b = b + 2.0; c = c + 1.0; pn5 = b * pn3 - a * c * pn1; pn6 = b * pn4 - a * c * pn2; if ( 0.0 < r8_abs ( pn6 ) ) { rn = pn5 / pn6; if ( r8_abs ( value - rn ) <= r8_min ( tol, tol * rn ) ) { arg = arg + log ( value ); if ( exp_arg_min <= arg ) { value = 1.0 - exp ( arg ); } else { value = 1.0; } return value; } value = rn; } pn1 = pn3; pn2 = pn4; pn3 = pn5; pn4 = pn6; // // Rescale terms in continued fraction if terms are large. // if ( overflow <= r8_abs ( pn5 ) ) { pn1 = pn1 / overflow; pn2 = pn2 / overflow; pn3 = pn3 / overflow; pn4 = pn4 / overflow; } } } return value; } //****************************************************************************80 void gamma_inc_values ( int &n_data, double &a, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // GAMMA_INC_VALUES returns some values of the incomplete Gamma function. // // Discussion: // // The incomplete Gamma function is defined as: // // Integral ( X <= T < oo ) T^(A-1) * exp(-T) dT. // // In Mathematica, the function can be evaluated by: // // Gamma[A,X] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 April 2010 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &A, the parameter of the function. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 20 static double a_vec[N_MAX] = { 0.10E+00, 0.10E+00, 0.10E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.10E+01, 0.10E+01, 0.10E+01, 0.11E+01, 0.11E+01, 0.11E+01, 0.20E+01, 0.20E+01, 0.20E+01, 0.60E+01, 0.60E+01, 0.11E+02, 0.26E+02, 0.41E+02 }; static double fx_vec[N_MAX] = { 2.490302836300570E+00, 0.8718369702247978E+00, 0.1079213896175866E+00, 1.238121685818417E+00, 0.3911298052193973E+00, 0.01444722098952533E+00, 0.9048374180359596E+00, 0.3678794411714423E+00, 0.006737946999085467E+00, 0.8827966752611692E+00, 0.3908330082003269E+00, 0.008051456628620993E+00, 0.9898141728888165E+00, 0.5578254003710746E+00, 0.007295055724436130E+00, 114.9574754165633E+00, 2.440923530031405E+00, 280854.6620274718E+00, 8.576480283455533E+24, 2.085031346403364E+47 }; static double x_vec[N_MAX] = { 0.30E-01, 0.30E+00, 0.15E+01, 0.75E-01, 0.75E+00, 0.35E+01, 0.10E+00, 0.10E+01, 0.50E+01, 0.10E+00, 0.10E+01, 0.50E+01, 0.15E+00, 0.15E+01, 0.70E+01, 0.25E+01, 0.12E+02, 0.16E+02, 0.25E+02, 0.45E+02 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; a = 0.0; x = 0.0; fx = 0.0; } else { a = a_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double gamma_log ( double x ) //****************************************************************************80 // // Purpose: // // GAMMA_LOG calculates the natural logarithm of GAMMA ( X ) for positive X. // // Discussion: // // The program uses rational functions that theoretically approximate // LOG(GAMMA(X)) to at least 18 significant decimal digits. The // approximation for 12 < X is from Hart et al, while approximations // for X < 12.0 are similar to those in Cody and Hillstrom, but are // unpublished. // // The accuracy achieved depends on the arithmetic system, the compiler, // intrinsic functions, and proper selection of the machine-dependent // constants. // // Modified: // // 12 May 2003 // // Author: // // Original FORTRAN77 version by William Cody, Laura Stoltz. // C++ version by John Burkardt. // // Reference: // // William Cody, Kenneth Hillstrom, // Chebyshev Approximations for the Natural Logarithm of the Gamma Function, // Mathematics of Computation, // Volume 21, 1967, pages 198-203. // // Kenneth Hillstrom, // ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, // May 1969. // // Hart, Ward Cheney, Charles Lawson, Maehly, // Charles Mesztenyi, John Rice, Thacher, Witzgall, // Computer Approximations, // Wiley and sons, New York, 1968. // // Parameters: // // Input, double X, the argument of the Gamma function. X must be positive. // // Output, double GAMMA_LOG, the logarithm of the Gamma function of X. // If X <= 0.0, or if overflow would occur, the program returns the // value XINF, the largest representable floating point number. // // Machine-dependent constants: // // BETA - radix for the floating-point representation. // // MAXEXP - the smallest positive power of BETA that overflows. // // XBIG - largest argument for which LN(GAMMA(X)) is representable // in the machine, i.e., the solution to the equation // LN(GAMMA(XBIG)) = BETA**MAXEXP. // // FRTBIG - Rough estimate of the fourth root of XBIG // // // Approximate values for some important machines are: // // BETA MAXEXP XBIG // // CRAY-1 (S.P.) 2 8191 9.62E+2461 // Cyber 180/855 // under NOS (S.P.) 2 1070 1.72E+319 // IEEE (IBM/XT, // SUN, etc.) (S.P.) 2 128 4.08E+36 // IEEE (IBM/XT, // SUN, etc.) (D.P.) 2 1024 2.55D+305 // IBM 3033 (D.P.) 16 63 4.29D+73 // VAX D-Format (D.P.) 2 127 2.05D+36 // VAX G-Format (D.P.) 2 1023 1.28D+305 // // // FRTBIG // // CRAY-1 (S.P.) 3.13E+615 // Cyber 180/855 // under NOS (S.P.) 6.44E+79 // IEEE (IBM/XT, // SUN, etc.) (S.P.) 1.42E+9 // IEEE (IBM/XT, // SUN, etc.) (D.P.) 2.25D+76 // IBM 3033 (D.P.) 2.56D+18 // VAX D-Format (D.P.) 1.20D+9 // VAX G-Format (D.P.) 1.89D+76 // { double c[7] = { -1.910444077728E-03, 8.4171387781295E-04, -5.952379913043012E-04, 7.93650793500350248E-04, -2.777777777777681622553E-03, 8.333333333333333331554247E-02, 5.7083835261E-03 }; double corr; double d1 = - 5.772156649015328605195174E-01; double d2 = 4.227843350984671393993777E-01; double d4 = 1.791759469228055000094023; double frtbig = 1.42E+09; int i; double p1[8] = { 4.945235359296727046734888, 2.018112620856775083915565E+02, 2.290838373831346393026739E+03, 1.131967205903380828685045E+04, 2.855724635671635335736389E+04, 3.848496228443793359990269E+04, 2.637748787624195437963534E+04, 7.225813979700288197698961E+03 }; double p2[8] = { 4.974607845568932035012064, 5.424138599891070494101986E+02, 1.550693864978364947665077E+04, 1.847932904445632425417223E+05, 1.088204769468828767498470E+06, 3.338152967987029735917223E+06, 5.106661678927352456275255E+06, 3.074109054850539556250927E+06 }; double p4[8] = { 1.474502166059939948905062E+04, 2.426813369486704502836312E+06, 1.214755574045093227939592E+08, 2.663432449630976949898078E+09, 2.940378956634553899906876E+010, 1.702665737765398868392998E+011, 4.926125793377430887588120E+011, 5.606251856223951465078242E+011 }; double pnt68 = 0.6796875; double q1[8] = { 6.748212550303777196073036E+01, 1.113332393857199323513008E+03, 7.738757056935398733233834E+03, 2.763987074403340708898585E+04, 5.499310206226157329794414E+04, 6.161122180066002127833352E+04, 3.635127591501940507276287E+04, 8.785536302431013170870835E+03 }; double q2[8] = { 1.830328399370592604055942E+02, 7.765049321445005871323047E+03, 1.331903827966074194402448E+05, 1.136705821321969608938755E+06, 5.267964117437946917577538E+06, 1.346701454311101692290052E+07, 1.782736530353274213975932E+07, 9.533095591844353613395747E+06 }; double q4[8] = { 2.690530175870899333379843E+03, 6.393885654300092398984238E+05, 4.135599930241388052042842E+07, 1.120872109616147941376570E+09, 1.488613728678813811542398E+010, 1.016803586272438228077304E+011, 3.417476345507377132798597E+011, 4.463158187419713286462081E+011 }; double res; double sqrtpi = 0.9189385332046727417803297; double xbig = 4.08E+36; double xden; double xm1; double xm2; double xm4; double xnum; double xsq; // // Return immediately if the argument is out of range. // if ( x <= 0.0 || xbig < x ) { return r8_huge ( ); } if ( x <= r8_epsilon ( ) ) { res = - log ( x ); } else if ( x <= 1.5 ) { if ( x < pnt68 ) { corr = - log ( x ); xm1 = x; } else { corr = 0.0; xm1 = ( x - 0.5 ) - 0.5; } if ( x <= 0.5 || pnt68 <= x ) { xden = 1.0; xnum = 0.0; for ( i = 0; i < 8; i++ ) { xnum = xnum * xm1 + p1[i]; xden = xden * xm1 + q1[i]; } res = corr + ( xm1 * ( d1 + xm1 * ( xnum / xden ) ) ); } else { xm2 = ( x - 0.5 ) - 0.5; xden = 1.0; xnum = 0.0; for ( i = 0; i < 8; i++ ) { xnum = xnum * xm2 + p2[i]; xden = xden * xm2 + q2[i]; } res = corr + xm2 * ( d2 + xm2 * ( xnum / xden ) ); } } else if ( x <= 4.0 ) { xm2 = x - 2.0; xden = 1.0; xnum = 0.0; for ( i = 0; i < 8; i++ ) { xnum = xnum * xm2 + p2[i]; xden = xden * xm2 + q2[i]; } res = xm2 * ( d2 + xm2 * ( xnum / xden ) ); } else if ( x <= 12.0 ) { xm4 = x - 4.0; xden = - 1.0; xnum = 0.0; for ( i = 0; i < 8; i++ ) { xnum = xnum * xm4 + p4[i]; xden = xden * xm4 + q4[i]; } res = d4 + xm4 * ( xnum / xden ); } else { res = 0.0; if ( x <= frtbig ) { res = c[6]; xsq = x * x; for ( i = 0; i < 6; i++ ) { res = res / xsq + c[i]; } } res = res / x; corr = log ( x ); res = res + sqrtpi - 0.5 * corr; res = res + x * ( corr - 1.0 ); } return res; } //****************************************************************************80 double gamma_log_int ( int n ) //****************************************************************************80 // // Purpose: // // GAMMA_LOG_INT computes the logarithm of Gamma of an integer N. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the argument of the logarithm of the Gamma function. // 0 < N. // // Output, double GAMMA_LOG_INT, the logarithm of // the Gamma function of N. // { double value; if ( n <= 0 ) { cout << " \n"; cout << "GAMMA_LOG_INT - Fatal error!\n"; cout << " Illegal input value of N = " << n << "\n"; cout << " But N must be strictly positive.\n"; exit ( 1 ); } value = gamma_log ( ( double ) ( n ) ); return value; } //****************************************************************************80 double genlogistic_cdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GENLOGISTIC_CDF evaluates the Generalized Logistic CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double CDF, the value of the CDF. // { double cdf; double y; y = ( x - a ) / b; cdf = 1.0 / pow ( ( 1.0 + exp ( - y ) ), c ); return cdf; } //****************************************************************************80 double genlogistic_cdf_inv ( double cdf, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GENLOGISTIC_CDF_INV inverts the Generalized Logistic CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double GENLOGISTIC_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "GENLOGISTIC_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = - r8_huge ( ); } else if ( cdf < 1.0 ) { x = a - b * log ( pow ( cdf, - 1.0 / c ) - 1.0 ); } else if ( 1.0 == cdf ) { x = r8_huge ( ); } return x; } //****************************************************************************80 bool genlogistic_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GENLOGISTIC_CHECK checks the parameters of the Generalized Logistic CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, bool GENLOGISTIC_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << " \n"; cout << "GENLOGISTIC_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } if ( c <= 0.0 ) { cout << " \n"; cout << "GENLOGISTIC_CHECK - Fatal error!\n"; cout << " C <= 0.\n"; return false; } return true; } //****************************************************************************80 double genlogistic_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GENLOGISTIC_MEAN returns the mean of the Generalized Logistic PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = a + b * ( euler_constant ( ) + digamma ( c ) ); return mean; } //****************************************************************************80 double genlogistic_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GENLOGISTIC_PDF evaluates the Generalized Logistic PDF. // // Discussion: // // PDF(A,B,C;X) = ( C / B ) * EXP ( ( A - X ) / B ) / // ( ( 1 + EXP ( ( A - X ) / B ) )^(C+1) ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double PDF, the value of the PDF. // { double pdf; double y; y = ( x - a ) / b; pdf = ( c / b ) * exp ( - y ) / pow ( 1.0 + exp ( - y ), c + 1.0 ); return pdf; } //****************************************************************************80 double genlogistic_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // GENLOGISTIC_SAMPLE samples the Generalized Logistic PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double GENLOGISTIC_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = genlogistic_cdf_inv ( cdf, a, b, c ); return x; } //****************************************************************************80 double genlogistic_variance ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // GENLOGISTIC_VARIANCE returns the variance of the Generalized Logistic PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double VARIANCE, the variance of the PDF. // { const double pi = 3.14159265358979323; double variance; variance = b * b * ( pi * pi / 6.0 + trigamma ( c ) ); return variance; } //****************************************************************************80 double geometric_cdf ( int x, double a ) //****************************************************************************80 // // Purpose: // // GEOMETRIC_CDF evaluates the Geometric CDF. // // Discussion: // // CDF(X,P) is the probability that there will be at least one // successful trial in the first X Bernoulli trials, given that // the probability of success in a single trial is P. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 January 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the maximum number of trials. // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Output, double GEOMETRIC_CDF, the value of the CDF. // { double cdf; if ( x <= 0 ) { cdf = 0.0; } else if ( a == 0.0 ) { cdf = 0.0; } else if ( a == 1.0 ) { cdf = 1.0; } else { cdf = 1.0 - pow ( ( 1.0 - a ), x ); } return cdf; } //****************************************************************************80 int geometric_cdf_inv ( double cdf, double a ) //****************************************************************************80 // // Purpose: // // GEOMETRIC_CDF_INV inverts the Geometric CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 June 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0 // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Output, int GEOMETRIC_CDF_INV, the corresponding value of X. // { int x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "GEOMETRIC_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( a == 1.0 ) { x = 1; } else if ( a == 0.0 ) { x = i4_huge ( ); } else { x = 1 + ( int ) ( log ( 1.0 - cdf ) / log ( 1.0 - a ) ); } return x; } //****************************************************************************80 void geometric_cdf_values ( int &n_data, int &x, double &p, double &cdf ) //****************************************************************************80 // // Purpose: // // GEOMETRIC_CDF_VALUES returns values of the geometric CDF. // // Discussion: // // The geometric or Pascal probability density function gives the // probability that the first success will happen on the X-th Bernoulli // trial, given that the probability of a success on a single trial is P. // // The value of CDF ( X, P ) is the probability that the first success // will happen on or before the X-th trial. // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`DiscreteDistributions`] // dist = GeometricDistribution [ p ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2004 // // Author: // // John Burkardt // // Reference: // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Daniel Zwillinger and Stephen Kokoska, // CRC Standard Probability and Statistics Tables and Formulae, // Chapman and Hall / CRC Press, 2000. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, int &X, the number of trials. // // Output, double &P, the probability of success // on one trial. // // Output, double &CDF, the cumulative density function. // { # define N_MAX 14 static double cdf_vec[N_MAX] = { 0.1900000000000000E+00, 0.2710000000000000E+00, 0.3439000000000000E+00, 0.6861894039100000E+00, 0.3600000000000000E+00, 0.4880000000000000E+00, 0.5904000000000000E+00, 0.9141006540800000E+00, 0.7599000000000000E+00, 0.8704000000000000E+00, 0.9375000000000000E+00, 0.9843750000000000E+00, 0.9995117187500000E+00, 0.9999000000000000E+00 }; static double p_vec[N_MAX] = { 0.1E+00, 0.1E+00, 0.1E+00, 0.1E+00, 0.2E+00, 0.2E+00, 0.2E+00, 0.2E+00, 0.3E+00, 0.4E+00, 0.5E+00, 0.5E+00, 0.5E+00, 0.9E+00 }; static int x_vec[N_MAX] = { 1, 2, 3, 10, 1, 2, 3, 10, 3, 3, 3, 5, 10, 3 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; x = 0; p = 0.0; cdf = 0.0; } else { x = x_vec[n_data-1]; p = p_vec[n_data-1]; cdf = cdf_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool geometric_check ( double a ) //****************************************************************************80 // // Purpose: // // GEOMETRIC_CHECK checks the parameter of the Geometric CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Output, bool GEOMETRIC_CHECK, is true if the parameters are legal. // { if ( a < 0.0 || 1.0 < a ) { cout << " \n"; cout << "GEOMETRIC_CHECK - Fatal error!\n"; cout << " A < 0 or 1 < A.\n"; return false; } return true; } //****************************************************************************80 double geometric_mean ( double a ) //****************************************************************************80 // // Purpose: // // GEOMETRIC_MEAN returns the mean of the Geometric PDF. // // Discussion: // // MEAN is the expected value of the number of trials required // to obtain a single success. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = 1.0 / a; return mean; } //****************************************************************************80 double geometric_pdf ( int x, double a ) //****************************************************************************80 // // Purpose: // // GEOMETRIC_PDF evaluates the Geometric PDF. // // Discussion: // // PDF(A;X) = A * ( 1 - A )^(X-1) // // PDF(A;X) is the probability that exactly X Bernoulli trials, each // with probability of success A, will be required to achieve // a single success. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the number of trials. // 0 < X // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Output, double PDF, the value of the PDF. // { double pdf; // // Special cases. // if ( x < 1 ) { pdf = 0.0; } else if ( a == 0.0 ) { pdf = 0.0; } else if ( a == 1.0 ) { if ( x == 1 ) { pdf = 1.0; } else { pdf = 0.0; } } else { pdf = a * pow ( ( 1.0 - a ), ( x - 1 ) ); } return pdf; } //****************************************************************************80 int geometric_sample ( double a, int &seed ) //****************************************************************************80 // // Purpose: // // GEOMETRIC_SAMPLE samples the Geometric PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int GEOMETRIC_SAMPLE, a sample of the PDF. // { double cdf; int x; cdf = r8_uniform_01 ( seed ); x = geometric_cdf_inv ( cdf, a ); return x; } //****************************************************************************80 double geometric_variance ( double a ) //****************************************************************************80 // // Purpose: // // GEOMETRIC_VARIANCE returns the variance of the Geometric PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of success on one trial. // 0.0 <= A <= 1.0. // // Output, double GEOMETRIC_VARIANCE, the variance of the PDF. // { double variance; variance = ( 1.0 - a ) / ( a * a ); return variance; } //****************************************************************************80 int get_seed ( ) //****************************************************************************80 // // Purpose: // // GET_SEED returns a random seed for the random number generator. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 September 2003 // // Author: // // John Burkardt // // Parameters: // // Output, int GET_SEED, a random seed value. // { # define I_MAX 2147483647 time_t clock; int ihour; int imin; int isec; int seed; struct tm *lt; time_t tloc; // // If the internal seed is 0, generate a value based on the time. // clock = time ( &tloc ); lt = localtime ( &clock ); // // Hours is 1, 2, ..., 12. // ihour = lt->tm_hour; if ( 12 < ihour ) { ihour = ihour - 12; } // // Move Hours to 0, 1, ..., 11 // ihour = ihour - 1; imin = lt->tm_min; isec = lt->tm_sec; seed = isec + 60 * ( imin + 60 * ihour ); // // We want values in [1,43200], not [0,43199]. // seed = seed + 1; // // Remap SEED from [1,43200] to [1,IMAX]. // seed = ( int ) ( ( ( double ) seed ) * ( ( double ) I_MAX ) / ( 60.0 * 60.0 * 12.0 ) ); // // Never use a seed of 0. // if ( seed == 0 ) { seed = 1; } return seed; #undef I_MAX } //****************************************************************************80 double gompertz_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // GOMPERTZ_CDF evaluates the Gompertz CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // Johnson, Kotz, and Balakrishnan, // Continuous Univariate Distributions, Volume 2, second edition, // Wiley, 1994, pages 25-26. // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 1 < A, 0 < B. // // Output, double GOMPERTZ_CDF, the value of the CDF. // { double cdf; if ( x <= 0.0 ) { cdf = 0.0; } else { cdf = 1.0 - exp ( - b * ( pow ( a, x ) - 1.0 ) / log ( a ) ); } return cdf; } //****************************************************************************80 double gompertz_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // GOMPERTZ_CDF_INV inverts the Gompertz CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // Johnson, Kotz, and Balakrishnan, // Continuous Univariate Distributions, Volume 2, second edition, // Wiley, 1994, pages 25-26. // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, the parameters of the PDF. // 1 < A, 0 < B. // // Output, double GOMPERTZ_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "GOMPERTZ_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf < 1.0 ) { x = log ( 1.0 - log ( 1.0 - cdf ) * log ( a ) / b ) / log ( a ); } else { x = r8_huge ( ); } return x; } //****************************************************************************80 bool gompertz_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // GOMPERTZ_CHECK checks the parameters of the Gompertz PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Reference: // // Johnson, Kotz, and Balakrishnan, // Continuous Univariate Distributions, Volume 2, second edition, // Wiley, 1994, pages 25-26. // // Parameters: // // Input, double A, B, the parameters of the PDF. // 1 < A, 0 < B. // // Output, bool GOMPERTZ_CHECK, is true if the parameters are legal. // { if ( a <= 1.0 ) { cout << " \n"; cout << "GOMPERTZ_CHECK - Fatal error!\n"; cout << " A <= 1.0!\n"; return false; } if ( b <= 0.0 ) { cout << " \n"; cout << "GOMPERTZ_CHECK - Fatal error!\n"; cout << " B <= 0.0!\n"; return false; } return true; } //****************************************************************************80 double gompertz_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // GOMPERTZ_PDF evaluates the Gompertz PDF. // // Discussion: // // PDF(A,B;X) = B * A**X / exp ( B * ( A**X - 1 ) / log ( A ) ) // // for // // 0.0 <= X // 1.0 < A // 0.0 < B // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // Johnson, Kotz, and Balakrishnan, // Continuous Univariate Distributions, Volume 2, second edition, // Wiley, 1994, pages 25-26. // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 1 < A, 0 < B. // // Output, double GOMPERTZ_PDF, the value of the PDF. // { double pdf; if ( x < 0.0 ) { pdf = 0.0; } else if ( 1.0 < a ) { pdf = exp ( log ( b ) + x * log ( a ) - ( b / log ( a ) ) * ( pow ( a, x ) - 1.0 ) ); } return pdf; } //****************************************************************************80 double gompertz_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // GOMPERTZ_SAMPLE samples the Gompertz PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 1 < A, 0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double GOMPERTZ_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = gompertz_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double gumbel_cdf ( double x ) //****************************************************************************80 // // Purpose: // // GUMBEL_CDF evaluates the Gumbel CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Output, double GUMBEL_CDF, the value of the CDF. // { double cdf; cdf = exp ( - exp ( - x ) ); return cdf; } //****************************************************************************80 double gumbel_cdf_inv ( double cdf ) //****************************************************************************80 // // Purpose: // // GUMBEL_CDF_INV inverts the Gumbel CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Output, double GUMBEL_CDF_INV, the corresponding argument of the CDF. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "GUMBEL_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = - log ( - log ( cdf ) ); return x; } //****************************************************************************80 double gumbel_mean ( ) //****************************************************************************80 // // Purpose: // // GUMBEL_MEAN returns the mean of the Gumbel PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double GUMBEL_MEAN, the mean of the PDF. // { double mean; mean = euler_constant ( ); return mean; } //****************************************************************************80 double gumbel_pdf ( double x ) //****************************************************************************80 // // Purpose: // // GUMBEL_PDF evaluates the Gumbel PDF. // // Discussion: // // PDF(X) = EXP ( - X - EXP ( - X ) ). // // GUMBEL_PDF(X) = EXTREME_PDF(0,1;X) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // Eric Weisstein, editor, // CRC Concise Encylopedia of Mathematics, // CRC Press, 1998. // // Parameters: // // Input, double X, the argument of the PDF. // // Output, double GUMBEL_PDF, the value of the PDF. // { double pdf; pdf = exp ( - x - exp ( - x ) ); return pdf; } //****************************************************************************80 double gumbel_sample ( int &seed ) //****************************************************************************80 // // Purpose: // // GUMBEL_SAMPLE samples the Gumbel PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input/output, int &SEED, a seed for the random number generator. // // Output, double GUMBEL_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = gumbel_cdf_inv ( cdf ); return x; } //****************************************************************************80 double gumbel_variance ( ) //****************************************************************************80 // // Purpose: // // GUMBEL_VARIANCE returns the variance of the Gumbel PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double GUMBEL_VARIANCE, the variance of the PDF. // { const double pi = 3.14159265358979323; double variance; variance = pi * pi / 6.0; return variance; } //****************************************************************************80 double half_normal_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // HALF_NORMAL_CDF evaluates the Half Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double HALF_NORMAL_CDF, the value of the CDF. // { double cdf; double cdf2; if ( x <= a ) { cdf = 0.0; } else { cdf2 = normal_cdf ( x, a, b ); cdf = 2.0 * cdf2 - 1.0; } return cdf; } //****************************************************************************80 double half_normal_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // HALF_NORMAL_CDF_INV inverts the Half Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double HALF_NORMAL_CDF_INV, the corresponding argument. // { double cdf2; double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "HALF_NORMAL_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } cdf2 = 0.5 * ( cdf + 1.0 ); x = normal_cdf_inv ( cdf2, a, b ); return x; } //****************************************************************************80 bool half_normal_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // HALF_NORMAL_CHECK checks the parameters of the Half Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, bool HALF_NORMAL_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << " \n"; cout << "HALF_NORMAL_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double half_normal_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // HALF_NORMAL_MEAN returns the mean of the Half Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double HALF_NORMAL_MEAN, the mean of the PDF. // { double mean; const double pi = 3.14159265358979323; mean = a + b * sqrt ( 2.0 / pi ); return mean; } //****************************************************************************80 double half_normal_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // HALF_NORMAL_PDF evaluates the Half Normal PDF. // // Discussion: // // PDF(A,B;X) = // sqrt ( 2 / PI ) * ( 1 / B ) * exp ( - 0.5 * ( ( X - A ) / B )^2 ) // // for A <= X // // The Half Normal PDF is a special case of both the Chi PDF and the // Folded Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double HALF_NORMAL_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; double y; if ( x <= a ) { pdf = 0.0; } else { y = ( x - a ) / b; pdf = sqrt ( 2.0 / pi ) * ( 1.0 / b ) * exp ( - 0.5 * y * y ); } return pdf; } //****************************************************************************80 double half_normal_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // HALF_NORMAL_SAMPLE samples the Half Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double HALF_NORMAL_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = half_normal_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double half_normal_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // HALF_NORMAL_VARIANCE returns the variance of the Half Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double HALF_NORMAL_VARIANCE, the variance of the PDF. // { const double pi = 3.14159265358979323; double variance; variance = b * b * ( 1.0 - 2.0 / pi ); return variance; } //****************************************************************************80 double hypergeometric_cdf ( int x, int n, int m, int l ) //****************************************************************************80 // // Purpose: // // HYPERGEOMETRIC_CDF evaluates the Hypergeometric CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the CDF. // // Input, int N, the number of balls selected. // 0 <= N <= L. // // Input, int M, the number of white balls in the population. // 0 <= M <= L. // // Input, int L, the number of balls to select from. // 0 <= L. // // Output, double HYPERGEOMETRIC_CDF, the value of the CDF. // { double cdf; double c1_log; double c2_log; double pdf; int x2; c1_log = binomial_coef_log ( l - m, n ); c2_log = binomial_coef_log ( l, n ); pdf = exp ( c1_log - c2_log ); cdf = pdf; for ( x2 = 0; x2 <= x - 1; x2++ ) { pdf = pdf * ( double ) ( ( m - x2 ) * ( n - x2 ) ) / ( double ) ( ( x2 + 1 ) * ( l - m - n + x2 + 1 ) ); cdf = cdf + pdf; } return cdf; } //****************************************************************************80 void hypergeometric_cdf_values ( int &n_data, int &sam, int &suc, int &pop, int &n, double &fx ) //****************************************************************************80 // // Purpose: // // HYPERGEOMETRIC_CDF_VALUES returns some values of the hypergeometric CDF. // // Discussion: // // CDF(X)(A,B) is the probability of at most X successes in A trials, // given that the probability of success on a single trial is B. // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`DiscreteDistributions`] // dist = HypergeometricDistribution [ sam, suc, pop ] // CDF [ dist, n ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 September 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Daniel Zwillinger, // CRC Standard Mathematical Tables and Formulae, // 30th Edition, CRC Press, 1996, pages 651-652. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, int &SAM, int &SUC, int &POP, the sample size, // success size, and population parameters of the function. // // Output, int &N, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 16 static double fx_vec[N_MAX] = { 0.6001858177500578E-01, 0.2615284665839845E+00, 0.6695237889132748E+00, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.5332595856827856E+00, 0.1819495964117640E+00, 0.4448047017527730E-01, 0.9999991751316731E+00, 0.9926860896560750E+00, 0.8410799901444538E+00, 0.3459800113391901E+00, 0.0000000000000000E+00, 0.2088888139634505E-02, 0.3876752992448843E+00, 0.9135215248834896E+00 }; static int n_vec[N_MAX] = { 7, 8, 9, 10, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0 }; static int pop_vec[N_MAX] = { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 90, 200, 1000, 10000 }; static int sam_vec[N_MAX] = { 10, 10, 10, 10, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10 }; static int suc_vec[N_MAX] = { 90, 90, 90, 90, 90, 90, 90, 90, 10, 30, 50, 70, 90, 90, 90, 90 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; sam = 0; suc = 0; pop = 0; n = 0; fx = 0.0; } else { sam = sam_vec[n_data-1]; suc = suc_vec[n_data-1]; pop = pop_vec[n_data-1]; n = n_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool hypergeometric_check ( int n, int m, int l ) //****************************************************************************80 // // Purpose: // // HYPERGEOMETRIC_CHECK checks the parameters of the Hypergeometric CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of balls selected. // 0 <= N <= L. // // Input, int M, the number of white balls in the population. // 0 <= M <= L. // // Input, int L, the number of balls to select from. // 0 <= L. // // Output, bool HYPERGEOMETRIC_CHECK, is true if the parameters are legal. // { if ( n < 0 || l < n ) { cout << " \n"; cout << "HYPERGEOMETRIC_CHECK - Fatal error!\n"; cout << " Input N is out of range.\n"; return false; } if ( m < 0 || l < m ) { cout << " \n"; cout << "HYPERGEOMETRIC_CHECK - Fatal error!\n"; cout << " Input M is out of range.\n"; return false; } if ( l < 0 ) { cout << " \n"; cout << "HYPERGEOMETRIC_CHECK - Fatal error!\n"; cout << " Input L is out of range.\n"; return false; } return true; } //****************************************************************************80 double hypergeometric_mean ( int n, int m, int l ) //****************************************************************************80 // // Purpose: // // HYPERGEOMETRIC_MEAN returns the mean of the Hypergeometric PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of balls selected. // 0 <= N <= L. // // Input, int M, the number of white balls in the population. // 0 <= M <= L. // // Input, int L, the number of balls to select from. // 0 <= L. // // Output, double HYPERGEOMETRIC_MEAN, the mean of the PDF. // { double mean; mean = ( double ) ( n * m ) / ( double ) ( l ); return mean; } //****************************************************************************80 double hypergeometric_pdf ( int x, int n, int m, int l ) //****************************************************************************80 // // Purpose: // // HYPERGEOMETRIC_PDF evaluates the Hypergeometric PDF. // // Discussion: // // PDF(N,M,L;X) = C(M,X) * C(L-M,N-X) / C(L,N). // // PDF(N,M,L;X) is the probability of drawing X white balls in a // single random sample of size N from a population containing // M white balls and a total of L balls. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the desired number of white balls. // 0 <= X <= N, usually, although any value of X can be given. // // Input, int N, the number of balls selected. // 0 <= N <= L. // // Input, int M, the number of white balls in the population. // 0 <= M <= L. // // Input, int L, the number of balls to select from. // 0 <= L. // // Output, double HYPERGEOMETRIC_PDF, the probability of exactly K white balls. // { double c1; double c2; double c3; double pdf; double pdf_log; // // Special cases. // if ( x < 0 ) { pdf = 1.0; } else if ( n < x ) { pdf = 0.0; } else if ( m < x ) { pdf = 0.0; } else if ( l < x ) { pdf = 0.0; } else if ( n == 0 ) { if ( x == 0 ) { pdf = 1.0; } else { pdf = 0.0; } } else { c1 = binomial_coef_log ( m, x ); c2 = binomial_coef_log ( l-m, n-x ); c3 = binomial_coef_log ( l, n ); pdf_log = c1 + c2 - c3; pdf = exp ( pdf_log ); } return pdf; } //****************************************************************************80 int hypergeometric_sample ( int n, int m, int l, int &seed ) //****************************************************************************80 // // Purpose: // // HYPERGEOMETRIC_SAMPLE samples the Hypergeometric PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // Jerry Banks, editor, // Handbook of Simulation, // Engineering and Management Press Books, 1998, page 165. // // Parameters: // // Input, int N, the number of balls selected. // 0 <= N <= L. // // Input, int M, the number of white balls in the population. // 0 <= M <= L. // // Input, int L, the number of balls to select from. // 0 <= L. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int HYPERGEOMETRIC_SAMPLE, a sample of the PDF. // { double a; double b; double c1_log; double c2_log; double u; int x; c1_log = binomial_coef_log ( l - m, n ); c2_log = binomial_coef_log ( l, n ); a = exp ( c1_log - c2_log ); b = a; u = r8_uniform_01 ( seed ); x = 0; while ( a < u ) { b = b * ( double ) ( ( m - x ) * ( n - x ) ) / ( double ) ( ( x + 1 ) * ( l - m - n + x + 1 ) ); a = a + b; x = x + 1; } return x; } //****************************************************************************80 double hypergeometric_variance ( int n, int m, int l ) //****************************************************************************80 // // Purpose: // // HYPERGEOMETRIC_VARIANCE returns the variance of the Hypergeometric PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of balls selected. // 0 <= N <= L. // // Input, int M, the number of white balls in the population. // 0 <= M <= L. // // Input, int L, the number of balls to select from. // 0 <= L. // // Output, double HYPERGEOMETRIC_VARIANCE, the variance of the PDF. // { double variance; variance = ( double ) ( n * m * ( l - m ) * ( l - n ) ) / ( double ) ( l * l * ( l - 1 ) ); return variance; } //****************************************************************************80 double i4_factorial ( int n ) //****************************************************************************80 // // Purpose: // // I4_FACTORIAL returns N!. // // Discussion: // // N! = Product ( 1 <= I <= N ) I // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the argument of the factorial function. // 0 <= N. // // Output, double I4_FACTORIAL, the factorial of N. // { double fact; int i; // // Check. // if ( n < 0 ) { cout << "\n"; cout << "I4_FACTORIAL - Fatal error!\n"; cout << " N < 0.\n"; return 0; } fact = 1.0; for ( i = 2; i <= n; i++ ) { fact = fact * ( double ) i; } return fact; } //****************************************************************************80 int i4_huge ( ) //****************************************************************************80 // // Purpose: // // I4_HUGE returns a "huge" I4 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 May 2003 // // Author: // // John Burkardt // // Parameters: // // Output, int I4_HUGE, a "huge" integer. // { return 2147483647; } //****************************************************************************80 int i4_max ( int i1, int i2 ) //****************************************************************************80 // // Purpose: // // I4_MAX returns the maximum of two I4's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 1998 // // Author: // // John Burkardt // // Parameters: // // Input, int I1, I2, are two integers to be compared. // // Output, int I4_MAX, the larger of I1 and I2. // // { if ( i2 < i1 ) { return i1; } else { return i2; } } //****************************************************************************80 int i4_min ( int i1, int i2 ) //****************************************************************************80 // // Purpose: // // I4_MIN returns the smaller of two I4's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 1998 // // Author: // // John Burkardt // // Parameters: // // Input, int I1, I2, two integers to be compared. // // Output, int I4_MIN, the smaller of I1 and I2. // { if ( i1 < i2 ) { return i1; } else { return i2; } } //****************************************************************************80 int i4_uniform_ab ( int a, int b, int &seed ) //****************************************************************************80 // // Purpose: // // I4_UNIFORM_AB returns a scaled pseudorandom I4. // // Discussion: // // The pseudorandom number should be uniformly distributed // between A and B. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 November 2006 // // Author: // // John Burkardt // // Reference: // // Paul Bratley, Bennett Fox, Linus Schrage, // A Guide to Simulation, // Springer Verlag, pages 201-202, 1983. // // Pierre L'Ecuyer, // Random Number Generation, // in Handbook of Simulation, // edited by Jerry Banks, // Wiley Interscience, page 95, 1998. // // Bennett Fox, // Algorithm 647: // Implementation and Relative Efficiency of Quasirandom // Sequence Generators, // ACM Transactions on Mathematical Software, // Volume 12, Number 4, pages 362-376, 1986. // // Peter Lewis, Allen Goodman, James Miller // A Pseudo-Random Number Generator for the System/360, // IBM Systems Journal, // Volume 8, pages 136-143, 1969. // // Parameters: // // Input, int A, B, the limits of the interval. // // Input/output, int &SEED, the "seed" value, which should NOT be 0. // On output, SEED has been updated. // // Output, int I4_UNIFORM_AB, a number between A and B. // { int k; float r; int value; if ( seed == 0 ) { cerr << "\n"; cerr << "I4_UNIFORM_AB - Fatal error!\n"; cerr << " Input value of SEED = 0.\n"; exit ( 1 ); } k = seed / 127773; seed = 16807 * ( seed - k * 127773 ) - k * 2836; if ( seed < 0 ) { seed = seed + 2147483647; } r = ( float ) ( seed ) * 4.656612875E-10; // // Scale R to lie between A-0.5 and B+0.5. // r = ( 1.0 - r ) * ( ( float ) ( i4_min ( a, b ) ) - 0.5 ) + r * ( ( float ) ( i4_max ( a, b ) ) + 0.5 ); // // Use rounding to convert R to an integer between A and B. // value = r4_nint ( r ); value = i4_max ( value, i4_min ( a, b ) ); value = i4_min ( value, i4_max ( a, b ) ); return value; } //****************************************************************************80 int *i4row_max ( int m, int n, int a[] ) //****************************************************************************80 // // Purpose: // // I4ROW_MAX returns the maximums of an I4ROW. // // Example: // // A = // 1 2 3 // 2 6 7 // // MAX = // 3 // 7 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the number of rows and columns in the array. // // Input, int A[M*N], the array to be examined. // // Output, int I4ROW_AMAX[M], the maximums of the rows. // { int i; int j; int *amax; amax = new int[m]; for ( i = 0; i < m; i++ ) { amax[i] = a[i+0*m]; for ( j = 1; j < n; j++ ) { if ( amax[i] < a[i+j*m] ) { amax[i] = a[i+j*m]; } } } return amax; } //****************************************************************************80 double *i4row_mean ( int m, int n, int a[] ) //****************************************************************************80 // // Purpose: // // I4ROW_MEAN returns the means of an I4ROW. // // Example: // // A = // 1 2 3 // 2 6 7 // // MEAN = // 2 // 5 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the number of rows and columns in the array. // // Input, int A[M*N], the array to be examined. // // Output, double I4ROW_MEAN[M], the means, or averages, of the rows. // { int i; int j; double *mean; mean = new double[m]; for ( i = 0; i < m; i++ ) { mean[i] = 0.0; for ( j = 0; j < n; j++ ) { mean[i] = mean[i] + ( double ) a[i+j*m]; } mean[i] = mean[i] / ( double ) ( n ); } return mean; } //****************************************************************************80 int *i4row_min ( int m, int n, int a[] ) //****************************************************************************80 // // Purpose: // // I4ROW_MIN returns the minimums of an I4ROW. // // Example: // // A = // 1 2 3 // 2 6 7 // // MIN = // 1 // 2 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the number of rows and columns in the array. // // Input, int A[M*N], the array to be examined. // // Output, int I4ROW_AMIN[M], the minimums of the rows. // { int i; int j; int *amin; amin = new int[m]; for ( i = 0; i < m; i++ ) { amin[i] = a[i+0*m]; for ( j = 1; j < n; j++ ) { if ( a[i+j*m] < amin[i] ) { amin[i] = a[i+j*m]; } } } return amin; } //****************************************************************************80 double *i4row_variance ( int m, int n, int a[] ) //****************************************************************************80 // // Purpose: // // I4ROW_VARIANCE returns the variances of an I4ROW. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the number of rows and columns in the array. // // Input, int A[M*N], the array whose variances are desired. // // Output, double I4ROW_VARIANCE[M], the variances of the rows. // { int i; int j; double mean; double *variance; variance = new double[m]; for ( i = 0; i < m; i++ ) { mean = 0.0; for ( j = 0; j < n; j++ ) { mean = mean + ( double ) a[i+j*m]; } mean = mean / ( double ) ( n ); variance[i] = 0.0; for ( j = 0; j < n; j++ ) { variance[i] = variance[i] + pow ( ( ( double ) a[i+j*m] - mean ), 2 ); } if ( 1 < n ) { variance[i] = variance[i] / ( double ) ( n - 1 ); } else { variance[i] = 0.0; } } return variance; } //****************************************************************************80 int i4vec_max ( int n, int x[] ) //****************************************************************************80 // // Purpose: // // I4VEC_MAX returns the maximum of an I4VEC // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 May 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, int X[N], the vector whose maximum is desired. // // Output, int I4VEC_MAX, the maximum of the vector entries. // { int i; int value; value = x[0]; for ( i = 1; i < n; i++ ) { if ( value < x[i] ) { value = x[i]; } } return value; } //****************************************************************************80 double i4vec_mean ( int n, int x[] ) //****************************************************************************80 // // Purpose: // // I4VEC_MEAN returns the mean of an I4VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 May 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, int X[N], the vector whose mean is desired. // // Output, double I4VEC_MEAN, the mean, or average, of the vector entries. // { int i; double mean; mean = 0.0; for ( i = 0; i < n; i++ ) { mean = mean + ( double ) x[i]; } mean = mean / ( double ) n; return mean; } //****************************************************************************80 int i4vec_min ( int n, int x[] ) //****************************************************************************80 // // Purpose: // // I4VEC_MIN returns the minimum of an I4VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 May 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, int X[N], the vector whose minimum is desired. // // Output, int I4VEC_MIN, the minimum of the vector entries. // { int i; int value; value = x[0]; for ( i = 1; i < n; i++ ) { if ( x[i] < value ) { value = x[i]; } } return value; } //****************************************************************************80 void i4vec_print ( int n, int a[], char *title ) //****************************************************************************80 // // Purpose: // // I4VEC_PRINT prints an I4VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 February 2003 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of components of the vector. // // Input, int A[N], the vector to be printed. // // Input, char *TITLE, a title to be printed first. // TITLE may be blank. // { int i; if ( s_len_trim ( title ) != 0 ) { cout << "\n"; cout << title << "\n"; } cout << "\n"; for ( i = 0; i <= n-1; i++ ) { cout << setw(6) << i << " " << setw(8) << a[i] << "\n"; } return; } //****************************************************************************80 int i4vec_run_count ( int n, int a[] ) //****************************************************************************80 // // Purpose: // // I4VEC_RUN_COUNT counts runs of equal values in an I4VEC. // // Discussion: // // An I4VEC is a vector of integer values. // // A run is a sequence of equal values. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 January 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, int A[N], the vector to be examined. // // Output, int I4VEC_RUN_COUNT, the number of runs. // { int i; int run_count; int test; run_count = 0; if ( n < 1 ) { return run_count; } test = 0; for ( i = 0; i < n; i++ ) { if ( i == 0 || a[i] != test ) { run_count = run_count + 1; test = a[i]; } } return run_count; } //****************************************************************************80 int i4vec_sum ( int n, int a[] ) //****************************************************************************80 // // Purpose: // // I4VEC_SUM sums the entries of an I4VEC. // // Example: // // Input: // // A = ( 1, 2, 3, 4 ) // // Output: // // I4VEC_SUM = 10 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 May 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, int A[N], the vector to be summed. // // Output, int I4VEC_SUM, the sum of the entries of A. // { int i; int sum; sum = 0; for ( i = 0; i < n; i++ ) { sum = sum + a[i]; } return sum; } //****************************************************************************80 double i4vec_variance ( int n, int x[] ) //****************************************************************************80 // // Purpose: // // I4VEC_VARIANCE returns the variance of an I4VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 May 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, int X[N], the vector whose variance is desired. // // Output, double I4VEC_VARIANCE, the variance of the vector entries. // { int i; double mean; double variance; mean = i4vec_mean ( n, x ); variance = 0.0; for ( i = 0; i < n; i++ ) { variance = variance + ( ( double ) x[i] - mean ) * ( ( double ) x[i] - mean ); } if ( 1 < n ) { variance = variance / ( double ) ( n - 1 ); } else { variance = 0.0; } return variance; } //****************************************************************************80 double inverse_gaussian_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // INVERSE_GAUSSIAN_CDF evaluates the Inverse Gaussian CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // 0.0 < X. // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double INVERSE_GAUSSIAN_CDF, the value of the CDF. // { double cdf; double cdf1; double cdf2; double x1; double x2; if ( x <= 0.0 ) { cdf = 0.0; } else { x1 = sqrt ( b / x ) * ( x - a ) / a; cdf1 = normal_01_cdf ( x1 ); x2 = - sqrt ( b / x ) * ( x + a ) / a; cdf2 = normal_01_cdf ( x2 ); cdf = cdf1 + exp ( 2.0 * b / a ) * cdf2; } return cdf; } //****************************************************************************80 bool inverse_gaussian_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // INVERSE_GAUSSIAN_CHECK checks the parameters of the Inverse Gaussian CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, bool INVERSE_GAUSSIAN_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cout << " \n"; cout << "INVERSE_GAUSSIAN_CHECK - Fatal error!\n"; cout << " A <= 0.\n"; return false; } if ( b <= 0.0 ) { cout << " \n"; cout << "INVERSE_GAUSSIAN_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double inverse_gaussian_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // INVERSE_GAUSSIAN_MEAN returns the mean of the Inverse Gaussian PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double INVERSE_GAUSSIAN_MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double inverse_gaussian_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // INVERSE_GAUSSIAN_PDF evaluates the Inverse Gaussian PDF. // // Discussion: // // The Inverse Gaussian PDF is also known as the Wald PDF // and the Inverse Normal PDF. // // PDF(A,B;X) // = sqrt ( B / ( 2 * PI * X^3 ) ) // * exp ( - B * ( X - A )^2 / ( 2.0 * A^2 * X ) ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 < X // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double INVERSE_GAUSSIAN_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; if ( x <= 0.0 ) { pdf = 0.0; } else { pdf = sqrt ( b / ( 2.0 * pi * pow ( x, 3 ) ) ) * exp ( - b * ( x - a ) * ( x - a ) / ( 2.0 * a * a * x ) ); } return pdf; } //****************************************************************************80 double inverse_gaussian_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // INVERSE_GAUSSIAN_SAMPLE samples the Inverse Gaussian PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double INVERSE_GAUSSIAN_SAMPLE, a sample of the PDF. // { double phi; double t; double u; double x; double y; double z; phi = b / a; z = normal_01_sample ( seed ); y = z * z; t = 1.0 + 0.5 * ( y - sqrt ( 4.0 * phi * y + y * y ) ) / phi; u = r8_uniform_01 ( seed ); if ( u * ( 1.0 + t ) <= 1.0 ) { x = a * t; } else { x = a / t; } return x; } //****************************************************************************80 double inverse_gaussian_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // INVERSE_GAUSSIAN_VARIANCE returns the variance of the Inverse Gaussian PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double INVERSE_GAUSSIAN_VARIANCE, the variance of the PDF. // { double variance; variance = a * a * a / b; return variance; } //****************************************************************************80 void laplace_cdf_values ( int &n_data, double &mu, double &beta, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // LAPLACE_CDF_VALUES returns some values of the Laplace CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = LaplaceDistribution [ mu, beta ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &MU, the mean of the distribution. // // Output, double &BETA, the shape parameter. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 12 static double beta_vec[N_MAX] = { 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; static double fx_vec[N_MAX] = { 0.5000000000000000E+00, 0.8160602794142788E+00, 0.9323323583816937E+00, 0.9751064658160680E+00, 0.6967346701436833E+00, 0.6417343447131054E+00, 0.6105996084642976E+00, 0.5906346234610091E+00, 0.5000000000000000E+00, 0.3032653298563167E+00, 0.1839397205857212E+00, 0.1115650800742149E+00 }; static double mu_vec[N_MAX] = { 0.0000000000000000E+01, 0.0000000000000000E+01, 0.0000000000000000E+01, 0.0000000000000000E+01, 0.0000000000000000E+01, 0.0000000000000000E+01, 0.0000000000000000E+01, 0.0000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01 }; static double x_vec[N_MAX] = { 0.0000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; mu = 0.0; beta = 0.0; x = 0.0; fx = 0.0; } else { mu = mu_vec[n_data-1]; beta = beta_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double laplace_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LAPLACE_CDF evaluates the Laplace CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LAPLACE_CDF, the value of the PDF. // { double cdf; double y; y = ( x - a ) / b; if ( x <= a ) { cdf = 0.5 * exp ( y ); } else { cdf = 1.0 - 0.5 * exp ( - y ); } return cdf; } //****************************************************************************80 double laplace_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // LAPLACE_CDF_INV inverts the Laplace CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LAPLACE_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "LAPLACE_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf <= 0.5 ) { x = a + b * log ( 2.0 * cdf ); } else { x = a - b * log ( 2.0 * ( 1.0 - cdf ) ); } return x; } //****************************************************************************80 bool laplace_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // LAPLACE_CHECK checks the parameters of the Laplace PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, bool LAPLACE_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << " \n"; cout << "LAPLACE_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double laplace_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // LAPLACE_MEAN returns the mean of the Laplace PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LAPLACE_MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double laplace_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LAPLACE_PDF evaluates the Laplace PDF. // // Discussion: // // PDF(A,B;X) = exp ( - abs ( X - A ) / B ) / ( 2 * B ) // // Discussion: // // The Laplace PDF is also known as the Double Exponential PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LAPLACE_PDF, the value of the PDF. // { double pdf; pdf = exp ( - r8_abs ( x - a ) / b ) / ( 2.0 * b ); return pdf; } //****************************************************************************80 double laplace_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // LAPLACE_SAMPLE samples the Laplace PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double LAPLACE_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = laplace_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double laplace_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // LAPLACE_VARIANCE returns the variance of the Laplace PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LAPLACE_VARIANCE, the variance of the PDF. // { double variance; variance = 2.0 * b * b; return variance; } //****************************************************************************80 double lerch ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // LERCH estimates the Lerch transcendent function. // // Discussion: // // The Lerch transcendent function is defined as: // // LERCH ( A, B, C ) = Sum ( 0 <= K < Infinity ) A^K / ( C + K )^B // // excluding any term with ( C + K ) = 0. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Reference: // // Eric Weisstein, editor, // CRC Concise Encylopedia of Mathematics, // CRC Press, 1998. // // Thanks: // // Oscar van Vlijmen // // Parameters: // // Input, double A, B, C, the parameters of the function. // // Output, double LERCH, an approximation to the Lerch // transcendent function. // { double a_k; int k; double sum2; double sum2_old; sum2 = 0.0; k = 0; a_k = 1.0; for ( ; ; ) { sum2_old = sum2; if ( c + ( double ) ( k ) == 0.0 ) { k = k + 1; a_k = a_k * a; continue; } sum2 = sum2 + a_k / pow ( c + ( double ) ( k ), b ); if ( sum2 <= sum2_old ) { break; } k = k + 1; a_k = a_k * a; } return sum2; } //****************************************************************************80 double levy_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LEVY_CDF evaluates the Levy CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 23 April 2007 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // Normally, A <= X. // // Input, double A, B, the parameters of the PDF. // 0 < B. // // Output, double LEVY_CDF, the value of the PDF. // { double cdf; if ( b <= 0.0 ) { cout << "\n"; cout << "LEVY_CDF - Fatal error!\n"; cout << " B <= 0.0.\n"; exit ( 1 ); } if ( x <= a ) { cdf = 0.0; } else { cdf = 1.0 - error_f ( sqrt ( b / ( 2.0 * ( x - a ) ) ) ); } return cdf; } //****************************************************************************80 double levy_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // LEVY_CDF_INV inverts the Levy CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 April 2007 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0 < B. // // Output, double LEVY_CDF_INV, the corresponding argument. // { double cdf1; double x; double x1; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "LEVY_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( b <= 0.0 ) { cout << "\n"; cout << "LEVY_CDF_INV - Fatal error!\n"; cout << " B <= 0.0.\n"; exit ( 1 ); } cdf1 = 1.0 - 0.5 * cdf; x1 = normal_01_cdf_inv ( cdf1 ); x = a + b / ( x1 * x1 ); return x; } //****************************************************************************80 double levy_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LEVY_PDF evaluates the Levy PDF. // // Discussion: // // PDF(A,B;X) = sqrt ( B / ( 2 * PI ) ) // * exp ( - B / ( 2 * ( X - A ) ) // / ( X - A )^(3/2) // // for A <= X. // // Note that the Levy PDF does not have a finite mean or variance. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 April 2007 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // Normally, A <= X. // // Input, double A, B, the parameters of the PDF. // 0 < B. // // Output, double LEVY_PDF, the value of the PDF. // { double pdf; double pi = 3.141592653589793; if ( b <= 0.0 ) { cout << "\n"; cout << "LEVY_PDF - Fatal error!\n"; cout << " B <= 0.0.\n"; exit ( 1 ); } if ( x <= a ) { pdf = 0.0; } else { pdf = sqrt ( b / ( 2.0 * pi ) ) * exp ( - b / ( 2.0 * ( x - a ) ) ) / sqrt ( pow ( x - a, 3 ) ); } return pdf; } //****************************************************************************80 double levy_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // LEVY_SAMPLE samples the Levy PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 April 2007 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double LEVY_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = levy_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double log_normal_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_NORMAL_CDF evaluates the Lognormal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 < X. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double CDF, the value of the CDF. // { double cdf; double logx; if ( x <= 0.0 ) { cdf = 0.0; } else { logx = log ( x ); cdf = normal_cdf ( logx, a, b ); } return cdf; } //****************************************************************************80 double log_normal_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_NORMAL_CDF_INV inverts the Lognormal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input, double LOG_NORMAL_CDF_INV, the corresponding argument. // { double logx; double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << "\n"; cout << "LOG_NORMAL_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } logx = normal_cdf_inv ( cdf, a, b ); x = exp ( logx ); return x; } //****************************************************************************80 void log_normal_cdf_values ( int &n_data, double &mu, double &sigma, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // LOG_NORMAL_CDF_VALUES returns some values of the Log Normal CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = LogNormalDistribution [ mu, sigma ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &MU, the mean of the distribution. // // Output, double &SIGMA, the shape parameter of the distribution. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 12 static double fx_vec[N_MAX] = { 0.2275013194817921E-01, 0.2697049307349095E+00, 0.5781741008028732E+00, 0.7801170895122241E+00, 0.4390310097476894E+00, 0.4592655190218048E+00, 0.4694258497695908E+00, 0.4755320473858733E+00, 0.3261051056816658E+00, 0.1708799040927608E+00, 0.7343256357952060E-01, 0.2554673736161761E-01 }; static double mu_vec[N_MAX] = { 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01 }; static double sigma_vec[N_MAX] = { 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; static double x_vec[N_MAX] = { 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; mu = 0.0; sigma = 0.0; x = 0.0; fx = 0.0; } else { mu = mu_vec[n_data-1]; sigma = sigma_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool log_normal_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_NORMAL_CHECK checks the parameters of the Lognormal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, bool LOG_NORMAL_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << "\n"; cout << "LOG_NORMAL_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double log_normal_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_NORMAL_MEAN returns the mean of the Lognormal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = exp ( a + 0.5 * b * b ); return mean; } //****************************************************************************80 double log_normal_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_NORMAL_PDF evaluates the Lognormal PDF. // // Discussion: // // PDF(A,B;X) // = exp ( - 0.5 * ( ( log ( X ) - A ) / B )^2 ) // / ( B * X * sqrt ( 2 * PI ) ) // // The Lognormal PDF is also known as the Cobb-Douglas PDF, // and as the Antilog_normal PDF. // // The Lognormal PDF describes a variable X whose logarithm // is normally distributed. // // The special case A = 0, B = 1 is known as Gilbrat's PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 < X // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; double y; if ( x <= 0.0 ) { pdf = 0.0; } else { y = ( log ( x ) - a ) / b; pdf = exp ( -0.5 * y * y ) / ( b * x * sqrt ( 2.0 * pi ) ); } return pdf; } //****************************************************************************80 double log_normal_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // LOG_NORMAL_SAMPLE samples the Lognormal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double LOG_NORMAL_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = log_normal_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double log_normal_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_NORMAL_VARIANCE returns the variance of the Lognormal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double VARIANCE, the variance of the PDF. // { double variance; variance = exp ( 2.0 * a + b * b ) * ( exp ( b * b ) - 1.0 ); return variance; } //****************************************************************************80 double log_series_cdf ( double x, double a ) //****************************************************************************80 // // Purpose: // // LOG_SERIES_CDF evaluates the Logarithmic Series CDF. // // Discussion: // // Simple summation is used, with a recursion to generate successive // values of the PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Thanks: // // Oscar van Vlijmen // // Parameters: // // Input, int X, the argument of the PDF. // 0 < X // // Input, double A, the parameter of the PDF. // 0.0 < A < 1.0. // // Output, double LOG_SERIES_CDF, the value of the CDF. // { double cdf; double pdf; int x2; cdf = 0.0; for ( x2 = 1; x2 <= x; x2++ ) { if ( x2 == 1 ) { pdf = - a / log ( 1.0 - a ); } else { pdf = ( double ) ( x2 - 1 ) * a * pdf / ( double ) ( x2 ); } cdf = cdf + pdf; } return cdf; } //****************************************************************************80 int log_series_cdf_inv ( double cdf, double a ) //****************************************************************************80 // // Purpose: // // LOG_SERIES_CDF_INV inverts the Logarithmic Series CDF. // // Discussion: // // Simple summation is used. The only protection against an // infinite loop caused by roundoff is that X cannot be larger // than 1000. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, the parameter of the PDF. // 0.0 < A < 1.0. // // Output, double LOG_SERIES_CDF_INV, the argument X of the CDF for which // CDF(X-1) <= CDF <= CDF(X). // { double cdf2; double pdf; int x; int xmax = 1000; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "LOG_SERIES_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } cdf2 = 0.0; x = 1; while ( cdf2 < cdf && x < xmax ) { if ( x == 1 ) { pdf = - a / log ( 1.0 - a ); } else { pdf = ( double ) ( x - 1 ) * a * pdf / ( double ) ( x ); } cdf2 = cdf2 + pdf; x = x + 1; } return x; } //****************************************************************************80 void log_series_cdf_values ( int &n_data, double &t, int &n, double &fx ) //****************************************************************************80 // // Purpose: // // LOG_SERIES_CDF_VALUES returns some values of the log series CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`DiscreteDistributions`] // dist = LogSeriesDistribution [ t ] // CDF [ dist, n ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 27 August 2004 // // Author: // // John Burkardt // // Reference: // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &T, the parameter of the function. // // Output, int &N, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 29 static double fx_vec[N_MAX] = { 0.9491221581029903E+00, 0.9433541128559735E+00, 0.9361094611773272E+00, 0.9267370278044118E+00, 0.9141358246245129E+00, 0.8962840235449100E+00, 0.8690148741955517E+00, 0.8221011541254772E+00, 0.7213475204444817E+00, 0.6068261510845583E+00, 0.5410106403333613E+00, 0.4970679476476894E+00, 0.4650921887927060E+00, 0.4404842934597863E+00, 0.4207860535926143E+00, 0.4045507673897055E+00, 0.3908650337129266E+00, 0.2149757685421097E+00, 0.0000000000000000E+00, 0.2149757685421097E+00, 0.3213887739704539E+00, 0.3916213575531612E+00, 0.4437690508633213E+00, 0.4850700239649681E+00, 0.5191433267738267E+00, 0.5480569580144867E+00, 0.5731033910767085E+00, 0.5951442521714636E+00, 0.6147826594068904E+00 }; static int n_vec[N_MAX] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; static double t_vec[N_MAX] = { 0.1000000000000000E+00, 0.1111111111111111E+00, 0.1250000000000000E+00, 0.1428571428571429E+00, 0.1666666666666667E+00, 0.2000000000000000E+00, 0.2500000000000000E+00, 0.3333333333333333E+00, 0.5000000000000000E+00, 0.6666666666666667E+00, 0.7500000000000000E+00, 0.8000000000000000E+00, 0.8333333333333333E+00, 0.8571485714857149E+00, 0.8750000000000000E+00, 0.8888888888888889E+00, 0.9000000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00, 0.9900000000000000E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; t = 0.0; n = 0; fx = 0.0; } else { t = t_vec[n_data-1]; n = n_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool log_series_check ( double a ) //****************************************************************************80 // // Purpose: // // LOG_SERIES_CHECK checks the parameter of the Logarithmic Series PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 < A < 1.0. // // Output, bool LOG_SERIES_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 || 1.0 <= a ) { cout << " \n"; cout << "LOG_SERIES_CHECK - Fatal error!\n"; cout << " A <= 0.0 or 1.0 <= A\n"; return false; } return true; } //****************************************************************************80 double log_series_mean ( double a ) //****************************************************************************80 // // Purpose: // // LOG_SERIES_MEAN returns the mean of the Logarithmic Series PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 < A < 1.0. // // Output, double LOG_SERIES_MEAN, the mean of the PDF. // { double mean; mean = - a / ( ( 1.0 - a ) * log ( 1.0 - a ) ); return mean; } //****************************************************************************80 double log_series_pdf ( int x, double a ) //****************************************************************************80 // // Purpose: // // LOG_SERIES_PDF evaluates the Logarithmic Series PDF. // // Discussion: // // PDF(A;X) = - A^X / ( X * log ( 1 - A ) ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the PDF. // 0 < X // // Input, double A, the parameter of the PDF. // 0.0 < A < 1.0. // // Output, double LOG_SERIES_PDF, the value of the PDF. // { double pdf; if ( x <= 0 ) { pdf = 0.0; } else { pdf = - pow ( a, x ) / ( ( double ) ( x ) * log ( 1.0 - a ) ); } return pdf; } //****************************************************************************80 int log_series_sample ( double a, int &seed ) //****************************************************************************80 // // Purpose: // // LOG_SERIES_SAMPLE samples the Logarithmic Series PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // Luc Devroye, // Non-Uniform Random Variate Generation, // Springer-Verlag, New York, 1986, page 547. // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 < A < 1.0. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int LOG_SERIES_SAMPLE, a sample of the PDF. // { double u; double v; int x; u = r8_uniform_01 ( seed ); v = r8_uniform_01 ( seed ); x = ( int ) ( 1.0 + log ( v ) / ( log ( 1.0 - pow ( 1.0 - a, u ) ) ) ); return x; } //****************************************************************************80 double log_series_variance ( double a ) //****************************************************************************80 // // Purpose: // // LOG_SERIES_VARIANCE returns the variance of the Logarithmic Series PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 < A < 1.0. // // Output, double LOG_SERIES_VARIANCE, the variance of the PDF. // { double alpha; double variance; alpha = - 1.0 / log ( 1.0 - a ); variance = a * alpha * ( 1.0 - alpha * a ) / pow ( ( 1.0 - a ), 2 ); return variance; } //****************************************************************************80 double log_uniform_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_UNIFORM_CDF evaluates the Log Uniform CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double CDF, the value of the CDF. // { double cdf; if ( x <= a ) { cdf = 0.0; } else if ( x < b ) { cdf = ( log ( x ) - log ( a ) ) / ( log ( b ) - log ( a ) ); } else { cdf = 1.0; } return cdf; } //****************************************************************************80 double log_uniform_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_UNIFORM_CDF_INV inverts the Log Uniform CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LOG_UNIFORM_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << "\n"; cout << "LOG_UNIFORM_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a * exp ( ( log ( b ) - log ( a ) ) * cdf ); return x; } //****************************************************************************80 bool log_uniform_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_UNIFORM_CHECK checks the parameters of the Log Uniform CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 1.0 < A < B. // // Output, bool LOG_UNIFORM_CHECK, is true if the parameters are legal. // { if ( a <= 1.0 ) { cout << "\n"; cout << "LOG_UNIFORM_CHECK - Fatal error!\n"; cout << " A <= 1.\n"; return false; } if ( b <= a ) { cout << "\n"; cout << "LOG_UNIFORM_CHECK - Fatal error!\n"; cout << " B <= A.\n"; return false; } return true; } //****************************************************************************80 double log_uniform_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_UNIFORM_MEAN returns the mean of the Log Uniform PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 1.0 < A < B. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = ( b - a ) / ( log ( b ) - log ( a ) ); return mean; } //****************************************************************************80 double log_uniform_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_UNIFORM_PDF evaluates the Log Uniform PDF. // // Discussion: // // PDF(A,B;X) = ( log ( B ) - log ( A ) ) / X for A <= X <= B // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 1.0 < A < B. // // Output, double PDF, the value of the PDF. // { double pdf; if ( x < a ) { pdf = 0.0; } else if ( x <= b ) { pdf = 1.0 / ( x * ( log ( b ) - log ( a ) ) ); } else { pdf = 0.0; } return pdf; } //****************************************************************************80 double log_uniform_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // LOG_UNIFORM_SAMPLE samples the Log Uniform PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 1.0 < A < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double LOG_UNIFORM_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = log_uniform_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double log_uniform_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // LOG_UNIFORM_VARIANCE returns the variance of the Log Uniform PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 November 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 1.0 < A < B. // // Output, double LOG_UNIFORM_VARIANCE, the variance of the PDF. // { double mean; double variance; mean = log_uniform_mean ( a, b ); variance = ( ( 0.5 * b * b - 2.0 * mean * b + mean * mean * log ( b ) ) - ( 0.5 * a * a - 2.0 * mean * a + mean * mean * log ( a ) ) ) / ( log ( b ) - log ( a ) ); return variance; } //****************************************************************************80 double logistic_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LOGISTIC_CDF evaluates the Logistic CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LOGISTIC_CDF, the value of the CDF. // { double cdf; cdf = 1.0 / ( 1.0 + exp ( ( a - x ) / b ) ); return cdf; } //****************************************************************************80 double logistic_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // LOGISTIC_CDF_INV inverts the Logistic CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LOGISTIC_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "LOGISTIC_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a - b * log ( ( 1.0 - cdf ) / cdf ); return x; } //****************************************************************************80 void logistic_cdf_values ( int &n_data, double &mu, double &beta, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // LOGISTIC_CDF_VALUES returns some values of the Logistic CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = LogisticDistribution [ mu, beta ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 30 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &MU, the mean of the distribution. // // Output, double &BETA, the shape parameter of the distribution. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 12 static double beta_vec[N_MAX] = { 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; static double fx_vec[N_MAX] = { 0.5000000000000000E+00, 0.8807970779778824E+00, 0.9820137900379084E+00, 0.9975273768433652E+00, 0.6224593312018546E+00, 0.5825702064623147E+00, 0.5621765008857981E+00, 0.5498339973124779E+00, 0.6224593312018546E+00, 0.5000000000000000E+00, 0.3775406687981454E+00, 0.2689414213699951E+00 }; static double mu_vec[N_MAX] = { 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01 }; static double x_vec[N_MAX] = { 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; mu = 0.0; beta = 0.0; x = 0.0; fx = 0.0; } else { mu = mu_vec[n_data-1]; beta = beta_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool logistic_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // LOGISTIC_CHECK checks the parameters of the Logistic CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, bool LOGISTIC_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << " \n"; cout << "LOGISTIC_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double logistic_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // LOGISTIC_MEAN returns the mean of the Logistic PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LOGISTIC_MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double logistic_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // LOGISTIC_PDF evaluates the Logistic PDF. // // Discussion: // // PDF(A,B;X) = exp ( ( A - X ) / B ) / // ( B * ( 1 + exp ( ( A - X ) / B ) )^2 ) // // The Logistic PDF is also known as the Sech-Squared PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LOGISTIC_PDF, the value of the PDF. // { double pdf; double temp; temp = exp ( ( a - x ) / b ); pdf = temp / ( b * ( 1.0 + temp ) * ( 1.0 + temp ) ); return pdf; } //****************************************************************************80 double logistic_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // LOGISTIC_SAMPLE samples the Logistic PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double LOGISTIC_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = logistic_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double logistic_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // LOGISTIC_VARIANCE returns the variance of the Logistic PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double LOGISTIC_VARIANCE, the variance of the PDF. // { const double pi = 3.14159265358979323; double variance; variance = pi * pi * b * b / 3.0; return variance; } //****************************************************************************80 double lorentz_cdf ( double x ) //****************************************************************************80 // // Purpose: // // LORENTZ_CDF evaluates the Lorentz CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Output, double LORENTZ_CDF, the value of the CDF. // { double cdf; const double pi = 3.14159265358979323; cdf = 0.5 + atan ( x ) / pi; return cdf; } //****************************************************************************80 double lorentz_cdf_inv ( double cdf ) //****************************************************************************80 // // Purpose: // // LORENTZ_CDF_INV inverts the Lorentz CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Output, double LORENTZ_CDF_INV, the corresponding argument. // { const double pi = 3.14159265358979323; double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "LORENTZ_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = tan ( pi * ( cdf - 0.5 ) ); return x; } //****************************************************************************80 double lorentz_mean ( ) //****************************************************************************80 // // Purpose: // // LORENTZ_MEAN returns the mean of the Lorentz PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double LORENTZ_MEAN, the mean of the PDF. // { double mean; mean = 0.0; return mean; } //****************************************************************************80 double lorentz_pdf ( double x ) //****************************************************************************80 // // Purpose: // // LORENTZ_PDF evaluates the Lorentz PDF. // // Discussion: // // PDF(X) = 1 / ( PI * ( 1 + X^2 ) ) // // The chief interest of the Lorentz PDF is that it is easily // inverted, and can be used to dominate other PDF's in an // acceptance/rejection method. // // LORENTZ_PDF(X) = CAUCHY_PDF(0,1;X) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Output, double LORENTZ_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; pdf = 1.0 / ( pi * ( 1.0 + x * x ) ); return pdf; } //****************************************************************************80 double lorentz_sample ( int &seed ) //****************************************************************************80 // // Purpose: // // LORENTZ_SAMPLE samples the Lorentz PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input/output, int &SEED, a seed for the random number generator. // // Output, double LORENTZ_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = lorentz_cdf_inv ( cdf ); return x; } //****************************************************************************80 double lorentz_variance ( ) //****************************************************************************80 // // Purpose: // // LORENTZ_VARIANCE returns the variance of the Lorentz PDF. // // Discussion: // // The variance of the Lorentz PDF is not well defined. This routine // is made available for completeness only, and simply returns // a "very large" number. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double LORENTZ_VARIANCE, the mean of the PDF. // { double variance; variance = r8_huge ( ); return variance; } //****************************************************************************80 double maxwell_cdf ( double x, double a ) //****************************************************************************80 // // Purpose: // // MAXWELL_CDF evaluates the Maxwell CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double MAXWELL_CDF, the value of the CDF. // { double cdf; double p2; double x2; if ( x <= 0.0 ) { cdf = 0.0; } else { x2 = x / a; p2 = 1.5; cdf = gamma_inc ( p2, x2 ); } return cdf; } //****************************************************************************80 double maxwell_cdf_inv ( double cdf, double a ) //****************************************************************************80 // // Purpose: // // MAXWELL_CDF_INV inverts the Maxwell CDF. // // Discussion: // // A simple bisection method is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double MAXWELL_CDF_INV, the corresponding argument of the CDF. // { double cdf1; double cdf2; double cdf3; int it; int it_max = 100; double tol = 0.0001; double x; double x1; double x2; double x3; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "MAXWELL_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = 0.0; return x; } else if ( 1.0 == cdf ) { x = r8_huge ( ); return x; } x1 = 0.0; cdf1 = 0.0; x2 = 1.0; for ( ; ; ) { cdf2 = maxwell_cdf ( x2, a ); if ( cdf < cdf2 ) { break; } x2 = 2.0 * x2; if ( 1000000.0 < x2 ) { cout << " \n"; cout << "MAXWELL_CDF_INV - Fatal error!\n"; cout << " Initial bracketing effort fails.\n"; exit ( 1 ); } } // // Now use bisection. // it = 0; for ( ; ; ) { it = it + 1; x3 = 0.5 * ( x1 + x2 ); cdf3 = maxwell_cdf ( x3, a ); if ( r8_abs ( cdf3 - cdf ) < tol ) { x = x3; break; } if ( it_max < it ) { cout << " \n"; cout << "MAXWELL_CDF_INV - Fatal error!\n"; cout << " Iteration limit exceeded.\n"; exit ( 1 ); } if ( ( cdf3 <= cdf && cdf1 <= cdf ) || ( cdf <= cdf3 && cdf <= cdf1 ) ) { x1 = x3; cdf1 = cdf3; } else { x2 = x3; cdf2 = cdf3; } } return x; } //****************************************************************************80 bool maxwell_check ( double a ) //****************************************************************************80 // // Purpose: // // MAXWELL_CHECK checks the parameters of the Maxwell CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, bool MAXWELL_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cout << " \n"; cout << "MAXWELL_CHECK - Fatal error!\n"; cout << " A <= 0.0.\n"; return false; } return true; } //****************************************************************************80 double maxwell_mean ( double a ) //****************************************************************************80 // // Purpose: // // MAXWELL_MEAN returns the mean of the Maxwell PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double MAXWELL_MEAN, the mean value. // { double mean; mean = sqrt ( 2.0 ) * a * r8_gamma ( 2.0 ) / r8_gamma ( 1.5 ); return mean; } //****************************************************************************80 double maxwell_pdf ( double x, double a ) //****************************************************************************80 // // Purpose: // // MAXWELL_PDF evaluates the Maxwell PDF. // // Discussion: // // PDF(A;X) = EXP ( - 0.5 * ( X / A )^2 ) * ( X / A )^2 / // ( sqrt ( 2 ) * A * GAMMA ( 1.5 ) ) // // MAXWELL_PDF(A;X) = CHI_PDF(0,A,3;X) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0 < X // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double MAXWELL_PDF, the value of the PDF. // { double pdf; double y; if ( x <= 0.0 ) { pdf = 0.0; } else { y = x / a; pdf = exp ( - 0.5 * y * y ) * y * y / ( sqrt ( 2.0 ) * a * r8_gamma ( 1.5 ) ); } return pdf; } //****************************************************************************80 double maxwell_sample ( double a, int &seed ) //****************************************************************************80 // // Purpose: // // MAXWELL_SAMPLE samples the Maxwell PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0 < A. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double MAXWELL_SAMPLE, a sample of the PDF. // { double a2; double x; a2 = 3.0; x = chi_square_sample ( a2, seed ); x = a * sqrt ( x ); return x; } //****************************************************************************80 double maxwell_variance ( double a ) //****************************************************************************80 // // Purpose: // // MAXWELL_VARIANCE returns the variance of the Maxwell PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double MAXWELL_VARIANCE, the variance of the PDF. // { double temp; double variance; temp = r8_gamma ( 2.0 ) / r8_gamma ( 1.5 ); variance = a * a * ( 3.0 - 2.0 * temp * temp ); return variance; } //****************************************************************************80 bool multicoef_check ( int nfactor, int factor[] ) //****************************************************************************80 // // Purpose: // // MULTICOEF_CHECK checks the parameters of the multinomial coefficient. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int NFACTOR, the number of factors. // 1 <= NFACTOR. // // Input, int FACTOR(NFACTOR), contains the factors. // 0.0 <= FACTOR(I). // // Output, bool MULTICOEF_CHECK, is true if the parameters are legal. // { int i; if ( nfactor < 1 ) { cout << " \n"; cout << "MULTICOEF_CHECK - Fatal error!\n"; cout << " NFACTOR < 1.\n"; return false; } for ( i = 0; i < nfactor; i++ ) { if ( factor[i] < 0 ) { cout << " \n"; cout << "MULTICOEF_CHECK - Fatal error\n"; cout << " Factor[" << i << "] = " << factor[i] << "\n"; cout << " But this value must be nonnegative.\n"; return false; } } return true; } //****************************************************************************80 int multinomial_coef1 ( int nfactor, int factor[] ) //****************************************************************************80 // // Purpose: // // MULTINOMIAL_COEF1 computes a Multinomial coefficient. // // Discussion: // // The multinomial coefficient is a generalization of the binomial // coefficient. It may be interpreted as the number of combinations of // N objects, where FACTOR(1) objects are indistinguishable of type 1, // ... and FACTOR(NFACTOR) are indistinguishable of type NFACTOR, // and N is the sum of FACTOR(1) through FACTOR(NFACTOR). // // NCOMB = N! / ( FACTOR(1)! FACTOR(2)! ... FACTOR(NFACTOR)! ) // // The log of the gamma function is used, to avoid overflow. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int NFACTOR, the number of factors. // 1 <= NFACTOR. // // Input, int FACTOR(NFACTOR), contains the factors. // 0.0 <= FACTOR(I). // // Output, int MULTINOMIAL_COEF1, the value of the multinomial coefficient. // { double facn; int i; int n; int ncomb; if ( !multicoef_check ( nfactor, factor ) ) { cout << " \n"; cout << "MULTINOMIAL_COEF1 - Fatal error!\n"; cout << " MULTICOEF_CHECK failed.\n"; ncomb = -i4_huge ( ); return ncomb; } // // The factors sum to N. // n = i4vec_sum ( nfactor, factor ); facn = factorial_log ( n ); for ( i = 0; i < nfactor; i++ ) { facn = facn - factorial_log ( factor[i] ); } ncomb = r8_nint ( exp ( facn ) ); return ncomb; } //****************************************************************************80 int multinomial_coef2 ( int nfactor, int factor[] ) //****************************************************************************80 // // Purpose: // // MULTINOMIAL_COEF2 computes a Multinomial coefficient. // // Discussion: // // The multinomial coefficient is a generalization of the binomial // coefficient. It may be interpreted as the number of combinations of // N objects, where FACTOR(1) objects are indistinguishable of type 1, // ... and FACTOR(NFACTOR) are indistinguishable of type NFACTOR, // and N is the sum of FACTOR(1) through FACTOR(NFACTOR). // // NCOMB = N! / ( FACTOR(1)! FACTOR(2)! ... FACTOR(NFACTOR)! ) // // A direct method is used, which should be exact. However, there // is a possibility of intermediate overflow of the result. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int NFACTOR, the number of factors. // 1 <= NFACTOR. // // Input, int FACTOR[NFACTOR], contains the factors. // 0 <= FACTOR(I). // // Output, int MULTINOMIAL_COEF2, the value of the multinomial coefficient. // { int i; int j; int k; int ncomb; if ( !multicoef_check ( nfactor, factor ) ) { cout << " \n"; cout << "MULTINOMIAL_COEF2 - Fatal error!\n"; cout << " MULTICOEF_CHECK failed.\n"; ncomb = - i4_huge ( ); return ncomb; } ncomb = 1; k = 0; for ( i = 0; i < nfactor; i++ ) { for ( j = 1; j <= factor[i]; j++ ) { k = k + 1; ncomb = ( ncomb * k ) / j; } } return ncomb; } //****************************************************************************80 bool multinomial_check ( int a, int b, double c[] ) //****************************************************************************80 // // Purpose: // // MULTINOMIAL_CHECK checks the parameters of the Multinomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of trials. // // Input, int B, the number of outcomes possible on one trial. // 1 <= B. // // Input, double C(B). C(I) is the probability of outcome I on // any trial. // 0.0 <= C(I) <= 1.0, // Sum ( 1 <= I <= B ) C(I) = 1.0. // // Output, bool MULTINOMIAL_CHECK, is true if the parameters are legal. // { double c_sum; int i; if ( b < 1 ) { cout << " \n"; cout << "MULTINOMIAL_CHECK - Fatal error!\n"; cout << " B < 1.\n"; return false; } for ( i = 0; i < b; i++ ) { if ( c[i] < 0.0 || 1.0 < c[i] ) { cout << " \n"; cout << "MULTINOMIAL_CHECK - Fatal error!\n"; cout << " Input C(I) is out of range.\n"; return false; } } c_sum = r8vec_sum ( b, c ); if ( 0.0001 < r8_abs ( 1.0 - c_sum ) ) { cout << " \n"; cout << "MULTINOMIAL_CHECK - Fatal error!\n"; cout << " The probabilities do not sum to 1.\n"; return false; } return true; } //****************************************************************************80 double *multinomial_covariance ( int a, int b, double c[] ) //****************************************************************************80 // // Purpose: // // MULTINOMIAL_COVARIANCE returns the covariances of the Multinomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of trials. // // Input, int B, the number of outcomes possible on one trial. // 1 <= B. // // Input, double C(B). C(I) is the probability of outcome I on // any trial. // 0.0 <= C(I) <= 1.0, // SUM ( 1 <= I <= B) C(I) = 1.0. // // Output, double MULTINOMIAL_COVARIANCE[B*B], the covariance matrix. // { double *covariance; int i; int j; covariance = new double[b*b]; for ( i = 0; i < b; i++) { for ( j = 0; j < b; j++ ) { if ( i == j ) { covariance[i+j*b] = ( double ) ( a ) * c[i] * ( 1.0 - c[i] ); } else { covariance[i+j*b] = - ( double ) ( a ) * c[i] * c[j]; } } } return covariance; } //****************************************************************************80 double *multinomial_mean ( int a, int b, double c[] ) //****************************************************************************80 // // Purpose: // // MULTINOMIAL_MEAN returns the means of the Multinomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of trials. // // Input, int B, the number of outcomes possible on one trial. // 1 <= B. // // Input, double C(B). C(I) is the probability of outcome I on // any trial. // 0.0 <= C(I) <= 1.0, // SUM ( 1 <= I <= B) C(I) = 1.0. // // Output, double MEAN(B), MEAN(I) is the expected value of the // number of outcome I in N trials. // { int i; double *mean; mean = new double[b]; for ( i = 0; i < b; i++ ) { mean[i] = ( double ) ( a ) * c[i]; } return mean; } //****************************************************************************80 double multinomial_pdf ( int x[], int a, int b, double c[] ) //****************************************************************************80 // // Purpose: // // MULTINOMIAL_PDF computes a Multinomial PDF. // // Discussion: // // PDF(A,B,C;X) = Comb(A,B,X) * Product ( 1 <= I <= B ) C(I)^X(I) // // where Comb(A,B,X) is the multinomial coefficient // C( A; X(1), X(2), ..., X(B) ) // // PDF(A,B,C;X) is the probability that in A trials there // will be exactly X(I) occurrences of event I, whose probability // on one trial is C(I), for I from 1 to B. // // As soon as A or B gets large, the number of possible X's explodes, // and the probability of any particular X can become extremely small. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X[B]; X(I) counts the number of occurrences of // outcome I, out of the total of A trials. // // Input, int A, the total number of trials. // // Input, int B, the number of different possible outcomes on // one trial. // // Input, double C[B]; C(I) is the probability of outcome I on // any one trial. // // Output, double MULTINOMIAL_PDF, the value of the multinomial PDF. // { int i; double pdf; double pdf_log; // // To try to avoid overflow, do the calculation in terms of logarithms. // Note that Gamma(A+1) = A factorial. // pdf_log = gamma_log ( ( double ) ( a + 1 ) ); for ( i = 0; i < b; i++ ) { pdf_log = pdf_log + x[i] * log ( c[i] ) - gamma_log ( ( double ) ( x[i] + 1 ) ); } pdf = exp ( pdf_log ); return pdf; } //****************************************************************************80 int *multinomial_sample ( int a, int b, double c[], int &seed ) //****************************************************************************80 // // Purpose: // // MULTINOMIAL_SAMPLE samples the Multinomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 November 2004 // // Author: // // John Burkardt // // Reference: // // Luc Devroye, // Non-Uniform Random Variate Generation, // Springer-Verlag, New York, 1986, page 559. // // Parameters: // // Input, int A, the total number of trials. // 0 <= A. // // Input, int B, the number of outcomes possible on one trial. // 1 <= B. // // Input, double C[B]. C(I) is the probability of outcome I on // any trial. // 0.0 <= C(I) <= 1.0, // SUM ( 1 <= I <= B) C(I) = 1.0. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int MULTINOMIAL_SAMPLE[B]; The Ith entry is the number of // occurrences of event I during the N trials. // { int i; int ifactor; int ntot; double prob; double sum2; int *x; x = new int[b]; ntot = a; sum2 = 1.0; for ( i = 0; i < b; i++ ) { x[i] = 0; } for ( ifactor = 0; ifactor < b-1; ifactor++ ) { prob = c[ifactor] / sum2; // // Generate a binomial random deviate for NTOT trials with // single trial success probability PROB. // x[ifactor] = binomial_sample ( ntot, prob, seed ); ntot = ntot - x[ifactor]; if ( ntot <= 0 ) { return x; } sum2 = sum2 - c[ifactor]; } // // The last factor gets what's left. // x[b-1] = ntot; return x; } //****************************************************************************80 double *multinomial_variance ( int a, int b, double c[] ) //****************************************************************************80 // // Purpose: // // MULTINOMIAL_VARIANCE returns the variances of the Multinomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, the number of trials. // // Input, int B, the number of outcomes possible on one trial. // 1 <= B. // // Input, double C[B]. C(I) is the probability of outcome I on // any trial. // 0.0 <= C(I) <= 1.0, // SUM ( 1 <= I <= B ) C(I) = 1.0. // // Output, double VARIANCE(B), VARIANCE(I) is the variance of the // total number of events of type I. // { int i; double *variance; variance = new double[b]; for ( i = 0; i < b; i++ ) { variance[i] = ( double ) ( a ) * c[i] * ( 1.0 - c[i] ); } return variance; } //****************************************************************************80 double *multivariate_normal_sample ( int n, double mean[], double covar_factor[], int &seed ) //****************************************************************************80 // // Purpose: // // MULTIVARIATE_NORMAL_SAMPLE samples the Multivariate Normal PDF. // // Discussion: // // PDF ( Mean(1:N), S(1:N,1:N); X(1:N) ) = // 1 / ( 2 * pi ) ^ ( N / 2 ) * 1 / det ( S ) // * exp ( - ( X - Mean )' * inverse ( S ) * ( X - Mean ) / 2 ) // // Here, // // X is the argument vector of length N, // Mean is the mean vector of length N, // S is an N by N positive definite symmetric covariance matrix. // // The properties of S guarantee that it has a lower triangular // matrix L, the Cholesky factor, such that S = L * L'. It is the // matrix L, rather than S, that is required by this routine. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Reference: // // Jerry Banks, editor, // Handbook of Simulation, // Engineering and Management Press Books, 1998, page 167. // // Parameters: // // Input, int N, the spatial dimension. // // Input, double MEAN[N], the mean vector. // // Input, double COVAR_FACTOR[N*N], the lower triangular Cholesky // factor L of the covariance matrix S. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double MULTIVARIATE_NORMAL_SAMPLE[N], a sample point // of the distribution. // { int i; int j; double *x; double z; x = new double[n]; for ( i = 0; i < n; i++ ) { z = normal_01_sample ( seed ); x[i] = mean[i]; for ( j = 0; j <= i; j++ ) { x[i] = x[i] + covar_factor[i+j*n] * z; } } return x; } //****************************************************************************80 double nakagami_cdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // NAKAGAMI_CDF evaluates the Nakagami CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B // 0.0 < C. // // Output, double NAKAGAMI_CDF, the value of the CDF. // { double cdf; double p2; double x2; double y; if ( x <= 0.0 ) { cdf = 0.0; } else if ( 0.0 < x ) { y = ( x - a ) / b; x2 = c * y * y; p2 = c; cdf = gamma_inc ( p2, x2 ); } return cdf; } //****************************************************************************80 bool nakagami_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // NAKAGAMI_CHECK checks the parameters of the Nakagami PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, bool NAKAGAMI_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << " \n"; cout << "NAKAGAMI_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } if ( c <= 0.0 ) { cout << " \n"; cout << "NAKAGAMI_CHECK - Fatal error!\n"; cout << " C <= 0.\n"; return false; } return true; } //****************************************************************************80 double nakagami_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // NAKAGAMI_MEAN returns the mean of the Nakagami PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B // 0.0 < C // // Output, double NAKAGAMI_MEAN, the mean of the PDF. // { double mean; mean = a + b * r8_gamma ( c + 0.5 ) / ( sqrt ( c ) * r8_gamma ( c ) ); return mean; } //****************************************************************************80 double nakagami_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // NAKAGAMI_PDF evaluates the Nakagami PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B // 0.0 < C. // // Output, double NAKAGAMI_PDF, the value of the PDF. // { double pdf; double y; if ( x <= 0.0 ) { pdf = 0.0; } else if ( 0.0 < x ) { y = ( x - a ) / b; pdf = 2.0 * pow ( c, c ) / ( b * r8_gamma ( c ) ) * pow ( y, ( 2.0 * c - 1.0 ) ) * exp ( - c * y * y ); } return pdf; } //****************************************************************************80 double nakagami_variance ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // NAKAGAMI_VARIANCE returns the variance of the Nakagami PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B // 0.0 < C // // Output, double NAKAGAMI_VARIANCE, the variance of the PDF. // { double t1; double t2; double variance; t1 = r8_gamma ( c + 0.5 ); t2 = r8_gamma ( c ); variance = b * b * ( 1.0 - t1 * t1 / ( c * t2 * t2 ) ); return variance; } //****************************************************************************80 double negative_binomial_cdf ( int x, int a, double b ) //****************************************************************************80 // // Purpose: // // NEGATIVE_BINOMIAL_CDF evaluates the Negative Binomial CDF. // // Discussion: // // A simple summing approach is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the CDF. // // Input, int A, double B, parameters of the PDF. // 0 <= A, // 0 < B <= 1. // // Output, double NEGATIVE_BINOMIAL_CDF, the value of the CDF. // { double cdf; int cnk; double pdf; int y; cdf = 0.0; for ( y = a; y <= x; y++ ) { cnk = binomial_coef ( y-1, a-1 ); pdf = ( double ) ( cnk ) * pow ( b, a ) * pow ( 1.0 - b, y - a ); cdf = cdf + pdf; } return cdf; } //****************************************************************************80 int negative_binomial_cdf_inv ( double cdf, int a, double b ) //****************************************************************************80 // // Purpose: // // NEGATIVE_BINOMIAL_CDF_INV inverts the Negative Binomial CDF. // // Discussion: // // A simple discrete approach is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, int A, double B, parameters of the PDF. // 0 <= A, // 0 < B <= 1. // // Output, int NEGATIVE_BINOMIAL_CDF_INV, the smallest X whose cumulative // density function is greater than or equal to CDF. // { double cum; double pdf; int x; int x_max = 1000; // if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "NEGATIVE_BINOMIAL_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } cum = 0.0; x = a; for ( ; ; ) { pdf = negative_binomial_pdf ( x, a, b ); cum = cum + pdf; if ( cdf <= cum || x_max <= x ) { break; } x = x + 1; } return x; } //****************************************************************************80 void negative_binomial_cdf_values ( int &n_data, int &f, int &s, double &p, double &cdf ) //****************************************************************************80 // // Purpose: // // NEGATIVE_BINOMIAL_CDF_VALUES returns values of the negative binomial CDF. // // Discussion: // // Assume that a coin has a probability P of coming up heads on // any one trial. Suppose that we plan to flip the coin until we // achieve a total of S heads. If we let F represent the number of // tails that occur in this process, then the value of F satisfies // a negative binomial PDF: // // PDF(F,S,P) = Choose ( F from F+S-1 ) * P^S * (1-P)^F // // The negative binomial CDF is the probability that there are F or // fewer failures upon the attainment of the S-th success. Thus, // // CDF(F,S,P) = sum ( 0 <= G <= F ) PDF(G,S,P) // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`DiscreteDistributions`] // dist = NegativeBinomialDistribution [ s, p ] // CDF [ dist, f ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 August 2004 // // Author: // // John Burkardt // // Reference: // // F C Powell, // Statistical Tables for Sociology, Biology and Physical Sciences, // Cambridge University Press, 1982. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, int &F, the maximum number of failures. // // Output, int &S, the number of successes. // // Output, double &P, the probability of a success on one trial. // // Output, double &CDF, the probability of at most F failures // before the S-th success. // { # define N_MAX 27 static double cdf_vec[N_MAX] = { 0.6367187500000000E+00, 0.3632812500000000E+00, 0.1445312500000000E+00, 0.5000000000000000E+00, 0.2265625000000000E+00, 0.6250000000000000E-01, 0.3437500000000000E+00, 0.1093750000000000E+00, 0.1562500000000000E-01, 0.1792000000000000E+00, 0.4096000000000000E-01, 0.4096000000000000E-02, 0.7047000000000000E-01, 0.1093500000000000E-01, 0.7290000000000000E-03, 0.9861587127990000E+00, 0.9149749500510000E+00, 0.7471846521450000E+00, 0.8499053647030009E+00, 0.5497160941090026E+00, 0.2662040052146710E+00, 0.6513215599000000E+00, 0.2639010709000000E+00, 0.7019082640000000E-01, 0.1000000000000000E+01, 0.1990000000000000E-01, 0.1000000000000000E-03 }; static int f_vec[N_MAX] = { 4, 3, 2, 3, 2, 1, 2, 1, 0, 2, 1, 0, 2, 1, 0, 11, 10, 9, 17, 16, 15, 9, 8, 7, 2, 1, 0 }; static double p_vec[N_MAX] = { 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.50E+00, 0.40E+00, 0.40E+00, 0.40E+00, 0.30E+00, 0.30E+00, 0.30E+00, 0.30E+00, 0.30E+00, 0.30E+00, 0.10E+00, 0.10E+00, 0.10E+00, 0.10E+00, 0.10E+00, 0.10E+00, 0.10E-01, 0.10E-01, 0.10E-01 }; static int s_vec[N_MAX] = { 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, 1, 2, 3, 1, 2, 3, 1, 2, 3, 0, 1, 2 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; f = 0; s = 0; p = 0.0; cdf = 0.0; } else { f = f_vec[n_data-1]; s = s_vec[n_data-1]; p = p_vec[n_data-1]; cdf = cdf_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool negative_binomial_check ( int a, double b ) //****************************************************************************80 // // Purpose: // // NEGATIVE_BINOMIAL_CHECK checks parameters of the Negative Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, double B, parameters of the PDF. // 0 <= A, // 0 < B <= 1. // // Output, bool NEGATIVE_BINOMIAL_CHECK, is true if the // parameters are legal. // { if ( a < 0 ) { cout << " \n"; cout << "NEGATIVE_BINOMIAL_CHECK - Fatal error!\n"; cout << " A < 0.\n"; return false; } if ( b <= 0.0 || 1.0 < b ) { cout << " \n"; cout << "NEGATIVE_BINOMIAL_CHECK - Fatal error!\n"; cout << " B <= 0 or 1 < B.\n"; return false; } return true; } //****************************************************************************80 double negative_binomial_mean ( int a, double b ) //****************************************************************************80 // // Purpose: // // NEGATIVE_BINOMIAL_MEAN returns the mean of the Negative Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, double B, parameters of the PDF. // 0 <= A, // 0 < B <= 1. // // Output, double NEGATIVE_BINOMIAL_MEAN, the mean of the PDF. // { double mean; mean = ( double ) ( a ) / b; return mean; } //****************************************************************************80 double negative_binomial_pdf ( int x, int a, double b ) //****************************************************************************80 // // Purpose: // // NEGATIVE_BINOMIAL_PDF evaluates the Negative Binomial PDF. // // Discussion: // // PDF(A,B;X) = C(X-1,A-1) * B^A * ( 1 - B )^(X-A) // // PDF(A,B;X) is the probability that the A-th success will // occur on the X-th trial, given that the probability // of a success on a single trial is B. // // The Negative Binomial PDF is also known as the Pascal PDF or // the "Polya" PDF. // // NEGATIVE_BINOMIAL_PDF(1,B;X) = GEOMETRIC_PDF(B;X) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the number of trials. // A <= X. // // Input, int A, the number of successes required. // 0 <= A <= X, normally. // // Input, double B, the probability of a success on a single trial. // 0.0 < B <= 1.0. // // Output, double NEGATIVE_BINOMIAL_PDF, the value of the PDF. // { int cnk; double pdf; if ( x < a ) { pdf = 0.0; } else { cnk = binomial_coef ( x-1, a-1 ); pdf = ( double ) ( cnk ) * pow ( b, a ) * pow ( 1.0 - b, x - a ); } return pdf; } //****************************************************************************80 int negative_binomial_sample ( int a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // NEGATIVE_BINOMIAL_SAMPLE samples the Negative Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, double B, parameters of the PDF. // 0 <= A, // 0 < B <= 1. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int NEGATIVE_BINOMIAL_SAMPLE, a sample of the PDF. // { int num_success; double r; int x; if ( b == 1.0 ) { x = a; return x; } else if ( b == 0.0 ) { x = i4_huge ( ); return x; } x = 0; num_success = 0; while ( num_success < a ) { x = x + 1; r = r8_uniform_01 ( seed ); if ( r <= b ) { num_success = num_success + 1; } } return x; } //****************************************************************************80 double negative_binomial_variance ( int a, double b ) //****************************************************************************80 // // Purpose: // // NEGATIVE_BINOMIAL_VARIANCE returns the variance of the Negative Binomial PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, double B, parameters of the PDF. // 0 <= A, // 0 < B <= 1. // // Output, double NEGATIVE_BINOMIAL_VARIANCE, the variance of the PDF. // { double variance; variance = ( double ) ( a ) * ( 1.0 - b ) / ( b * b ); return variance; } //****************************************************************************80 double normal_01_cdf ( double x ) //****************************************************************************80 // // Purpose: // // NORMAL_01_CDF evaluates the Normal 01 CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 February 1999 // // Author: // // John Burkardt // // Reference: // // A G Adams, // Areas Under the Normal Curve, // Algorithm 39, // Computer j., // Volume 12, pages 197-198, 1969. // // Parameters: // // Input, double X, the argument of the CDF. // // Output, double CDF, the value of the CDF. // { double a1 = 0.398942280444; double a2 = 0.399903438504; double a3 = 5.75885480458; double a4 = 29.8213557808; double a5 = 2.62433121679; double a6 = 48.6959930692; double a7 = 5.92885724438; double b0 = 0.398942280385; double b1 = 3.8052E-08; double b2 = 1.00000615302; double b3 = 3.98064794E-04; double b4 = 1.98615381364; double b5 = 0.151679116635; double b6 = 5.29330324926; double b7 = 4.8385912808; double b8 = 15.1508972451; double b9 = 0.742380924027; double b10 = 30.789933034; double b11 = 3.99019417011; double cdf; double q; double y; // // |X| <= 1.28. // if ( r8_abs ( x ) <= 1.28 ) { y = 0.5 * x * x; q = 0.5 - r8_abs ( x ) * ( a1 - a2 * y / ( y + a3 - a4 / ( y + a5 + a6 / ( y + a7 ) ) ) ); // // 1.28 < |X| <= 12.7 // } else if ( r8_abs ( x ) <= 12.7 ) { y = 0.5 * x * x; q = exp ( - y ) * b0 / ( r8_abs ( x ) - b1 + b2 / ( r8_abs ( x ) + b3 + b4 / ( r8_abs ( x ) - b5 + b6 / ( r8_abs ( x ) + b7 - b8 / ( r8_abs ( x ) + b9 + b10 / ( r8_abs ( x ) + b11 ) ) ) ) ) ); // // 12.7 < |X| // } else { q = 0.0; } // // Take account of negative X. // if ( x < 0.0 ) { cdf = q; } else { cdf = 1.0 - q; } return cdf; } //****************************************************************************80 double normal_01_cdf_inv ( double p ) //****************************************************************************80 // // Purpose: // // NORMAL_01_CDF_INV inverts the standard normal CDF. // // Discussion: // // The result is accurate to about 1 part in 10**16. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 27 December 2004 // // Author: // // Original FORTRAN77 version by Michael Wichura. // C++ version by John Burkardt. // // Reference: // // Michael Wichura, // The Percentage Points of the Normal Distribution, // Algorithm AS 241, // Applied Statistics, // Volume 37, Number 3, pages 477-484, 1988. // // Parameters: // // Input, double P, the value of the cumulative probability // densitity function. 0 < P < 1. If P is outside this range, an // "infinite" value is returned. // // Output, double NORMAL_01_CDF_INV, the normal deviate value // with the property that the probability of a standard normal deviate being // less than or equal to this value is P. // { double a[8] = { 3.3871328727963666080, 1.3314166789178437745e+2, 1.9715909503065514427e+3, 1.3731693765509461125e+4, 4.5921953931549871457e+4, 6.7265770927008700853e+4, 3.3430575583588128105e+4, 2.5090809287301226727e+3 }; double b[8] = { 1.0, 4.2313330701600911252e+1, 6.8718700749205790830e+2, 5.3941960214247511077e+3, 2.1213794301586595867e+4, 3.9307895800092710610e+4, 2.8729085735721942674e+4, 5.2264952788528545610e+3 }; double c[8] = { 1.42343711074968357734, 4.63033784615654529590, 5.76949722146069140550, 3.64784832476320460504, 1.27045825245236838258, 2.41780725177450611770e-1, 2.27238449892691845833e-2, 7.74545014278341407640e-4 }; double const1 = 0.180625; double const2 = 1.6; double d[8] = { 1.0, 2.05319162663775882187, 1.67638483018380384940, 6.89767334985100004550e-1, 1.48103976427480074590e-1, 1.51986665636164571966e-2, 5.47593808499534494600e-4, 1.05075007164441684324e-9 }; double e[8] = { 6.65790464350110377720, 5.46378491116411436990, 1.78482653991729133580, 2.96560571828504891230e-1, 2.65321895265761230930e-2, 1.24266094738807843860e-3, 2.71155556874348757815e-5, 2.01033439929228813265e-7 }; double f[8] = { 1.0, 5.99832206555887937690e-1, 1.36929880922735805310e-1, 1.48753612908506148525e-2, 7.86869131145613259100e-4, 1.84631831751005468180e-5, 1.42151175831644588870e-7, 2.04426310338993978564e-15 }; double q; double r; double split1 = 0.425; double split2 = 5.0; double value; if ( p <= 0.0 ) { value = -r8_huge ( ); return value; } if ( 1.0 <= p ) { value = r8_huge ( ); return value; } q = p - 0.5; if ( r8_abs ( q ) <= split1 ) { r = const1 - q * q; value = q * r8poly_value ( 8, a, r ) / r8poly_value ( 8, b, r ); } else { if ( q < 0.0 ) { r = p; } else { r = 1.0 - p; } if ( r <= 0.0 ) { value = r8_huge ( ); } else { r = sqrt ( - log ( r ) ); if ( r <= split2 ) { r = r - const2; value = r8poly_value ( 8, c, r ) / r8poly_value ( 8, d, r ); } else { r = r - split2; value = r8poly_value ( 8, e, r ) / r8poly_value ( 8, f, r ); } } if ( q < 0.0 ) { value = - value; } } return value; } //****************************************************************************80 void normal_01_cdf_values ( int &n_data, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // NORMAL_01_CDF_VALUES returns some values of the Normal 01 CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = NormalDistribution [ 0, 1 ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 17 static double fx_vec[N_MAX] = { 0.5000000000000000E+00, 0.5398278372770290E+00, 0.5792597094391030E+00, 0.6179114221889526E+00, 0.6554217416103242E+00, 0.6914624612740131E+00, 0.7257468822499270E+00, 0.7580363477769270E+00, 0.7881446014166033E+00, 0.8159398746532405E+00, 0.8413447460685429E+00, 0.9331927987311419E+00, 0.9772498680518208E+00, 0.9937903346742239E+00, 0.9986501019683699E+00, 0.9997673709209645E+00, 0.9999683287581669E+00 }; static double x_vec[N_MAX] = { 0.0000000000000000E+00, 0.1000000000000000E+00, 0.2000000000000000E+00, 0.3000000000000000E+00, 0.4000000000000000E+00, 0.5000000000000000E+00, 0.6000000000000000E+00, 0.7000000000000000E+00, 0.8000000000000000E+00, 0.9000000000000000E+00, 0.1000000000000000E+01, 0.1500000000000000E+01, 0.2000000000000000E+01, 0.2500000000000000E+01, 0.3000000000000000E+01, 0.3500000000000000E+01, 0.4000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; x = 0.0; fx = 0.0; } else { x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double normal_01_mean ( ) //****************************************************************************80 // // Purpose: // // NORMAL_01_MEAN returns the mean of the Normal 01 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double MEAN, the mean of the PDF. // { double mean; mean = 0.0; return mean; } //****************************************************************************80 double normal_01_pdf ( double x ) //****************************************************************************80 // // Purpose: // // NORMAL_01_PDF evaluates the Normal 01 PDF. // // Discussion: // // The Normal 01 PDF is also called the "Standard Normal" PDF, or // the Normal PDF with 0 mean and variance 1. // // PDF(X) = exp ( - 0.5 * X^2 ) / sqrt ( 2 * PI ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Output, double PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; pdf = exp ( -0.5 * x * x ) / sqrt ( 2.0 * pi ); return pdf; } //****************************************************************************80 double normal_01_sample ( int &seed ) //****************************************************************************80 // // Purpose: // // NORMAL_01_SAMPLE samples the standard normal probability distribution. // // Discussion: // // The standard normal probability distribution function (PDF) has // mean 0 and standard deviation 1. // // The Box-Muller method is used, which is efficient, but // generates two values at a time. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input/output, int &SEED, a seed for the random number generator. // // Output, double NORMAL_01_SAMPLE, a normally distributed random value. // { const double pi = 3.14159265358979323; double r1; double r2; double x; r1 = r8_uniform_01 ( seed ); r2 = r8_uniform_01 ( seed ); x = sqrt ( -2.0 * log ( r1 ) ) * cos ( 2.0 * pi * r2 ); return x; } //****************************************************************************80 double normal_01_variance ( ) //****************************************************************************80 // // Purpose: // // NORMAL_01_VARIANCE returns the variance of the Normal 01 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double VARIANCE, the variance of the PDF. // { double variance; variance = 1.0; return variance; } //****************************************************************************80 double *normal_01_vector ( int n, int &seed ) //****************************************************************************80 // // Purpose: // // NORMAL_01_VECTOR samples the standard normal probability distribution. // // Discussion: // // The standard normal probability distribution function (PDF) has // mean 0 and standard deviation 1. // // This routine can generate a vector of values on one call. It // has the feature that it should provide the same results // in the same order no matter how we break up the task. // // Before calling this routine, the user may call RANDOM_SEED // in order to set the seed of the random number generator. // // The Box-Muller method is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of values desired. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double X(N), a sample of the standard normal PDF. // // Local parameters: // // Local, real R(N+1), is used to store some uniform random values. // Its dimension is N+1, but really it is only needed to be the // smallest even number greater than or equal to N. // // Local, int X_LO, X_HI, records the range of entries of // X that we need to compute. This starts off as 1:N, but is adjusted // if we have a saved value that can be immediately stored in X(1), // and so on. // { int i; int m; const double pi = 3.14159265358979323; double *r; double *x; int x_hi; int x_lo; x = new double[n]; // // Record the range of X we need to fill in. // x_lo = 1; x_hi = n; // // If we need just one new value, do that here to avoid null arrays. // if ( x_hi - x_lo + 1 == 1 ) { r = r8vec_uniform_01 ( 2, seed ); x[x_hi-1] = sqrt ( -2.0 * log ( r[0] ) ) * cos ( 2.0 * pi * r[1] ); delete [] r; } // // If we require an even number of values, that's easy. // else if ( ( x_hi - x_lo + 1 ) % 2 == 0 ) { m = ( x_hi - x_lo + 1 ) / 2; r = r8vec_uniform_01 ( 2*m, seed ); for ( i = 0; i <= 2*m-2; i = i + 2 ) { x[x_lo+i-1] = sqrt ( -2.0 * log ( r[i] ) ) * cos ( 2.0 * pi * r[i+1] ); x[x_lo+i ] = sqrt ( -2.0 * log ( r[i] ) ) * sin ( 2.0 * pi * r[i+1] ); } delete [] r; } // // If we require an odd number of values, we generate an even number, // and handle the last pair specially, storing one in X(N). // else { x_hi = x_hi - 1; m = ( x_hi - x_lo + 1 ) / 2 + 1; r = r8vec_uniform_01 ( 2*m, seed ); for ( i = 0; i <= 2*m-4; i = i + 2 ) { x[x_lo+i-1] = sqrt ( -2.0 * log ( r[i] ) ) * cos ( 2.0 * pi * r[i+1] ); x[x_lo+i ] = sqrt ( -2.0 * log ( r[i] ) ) * sin ( 2.0 * pi * r[i+1] ); } i = 2*m - 2; x[x_lo+i-1] = sqrt ( -2.0 * log ( r[i] ) ) * cos ( 2.0 * pi * r[i+1] ); delete [] r; } return x; } //****************************************************************************80 double normal_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_CDF evaluates the Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double CDF, the value of the CDF. // { double cdf; double y; y = ( x - a ) / b; cdf = normal_01_cdf ( y ); return cdf; } //****************************************************************************80 double normal_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_CDF_INV inverts the Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Reference: // // Algorithm AS 111, // Applied Statistics, // Volume 26, pages 118-121, 1977. // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double NORMAL_CDF_INV, the corresponding argument. // { double x; double x2; if ( cdf < 0.0 || 1.0 < cdf ) { cout << "\n"; cout << "NORMAL_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x2 = normal_01_cdf_inv ( cdf ); x = a + b * x2; return x; } //****************************************************************************80 void normal_cdf_values ( int &n_data, double &mu, double &sigma, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // NORMAL_CDF_VALUES returns some values of the Normal CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = NormalDistribution [ mu, sigma ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &MU, the mean of the distribution. // // Output, double &SIGMA, the variance of the distribution. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 12 static double fx_vec[N_MAX] = { 0.5000000000000000E+00, 0.9772498680518208E+00, 0.9999683287581669E+00, 0.9999999990134124E+00, 0.6914624612740131E+00, 0.6305586598182364E+00, 0.5987063256829237E+00, 0.5792597094391030E+00, 0.6914624612740131E+00, 0.5000000000000000E+00, 0.3085375387259869E+00, 0.1586552539314571E+00 }; static double mu_vec[N_MAX] = { 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01 }; static double sigma_vec[N_MAX] = { 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; static double x_vec[N_MAX] = { 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; mu = 0.0; sigma = 0.0; x = 0.0; fx = 0.0; } else { mu = mu_vec[n_data-1]; sigma = sigma_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool normal_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_CHECK checks the parameters of the Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, bool NORMAL_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << "\n"; cout << "NORMAL_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double normal_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_MEAN returns the mean of the Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double normal_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_PDF evaluates the Normal PDF. // // Discussion: // // PDF(A,B;X) // = exp ( - 0.5 * ( ( X - A ) / B )^2 ) // / ( B * SQRT ( 2 * PI ) ) // // The normal PDF is also known as the Gaussian PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; double y; y = ( x - a ) / b; pdf = exp ( -0.5 * y * y ) / ( b * sqrt ( 2.0 * pi ) ); return pdf; } //****************************************************************************80 double normal_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // NORMAL_SAMPLE samples the Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 November 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double NORMAL_SAMPLE, a sample of the PDF. // { double x; x = normal_01_sample ( seed ); x = a + b * x; return x; } //****************************************************************************80 double normal_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_VARIANCE returns the variance of the Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double VARIANCE, the variance of the PDF. // { double variance; variance = b * b; return variance; } //****************************************************************************80 double *normal_vector ( int n, double mean, double dev, int &seed ) //****************************************************************************80 // // Purpose: // // NORMAL_VECTOR samples the normal probability distribution. // // Discussion: // // The normal probability distribution function (PDF) has // a user-specified mean and standard deviation. // // This routine can generate a vector of values on one call. It // has the feature that it should provide the same results // in the same order no matter how we break up the task. // // Before calling this routine, the user may call RANDOM_SEED // in order to set the seed of the random number generator. // // The Box-Muller method is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of values desired. If N is negative, // then the code will flush its internal memory; in particular, // if there is a saved value to be used on the next call, it is // instead discarded. This is useful if the user has reset the // random number seed, for instance. // // Input, double MEAN, the desired mean value. // // Input, double DEV, the desired standard deviation. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double NORMAL_VECTOR[N], a sample of the normal PDF. // { int i; double *x; x = normal_01_vector ( n, seed ); for ( i = 0; i < n; i++ ) { x[i] = mean + dev * x[i]; } return x; } //****************************************************************************80 double normal_truncated_ab_cdf ( double x, double mu, double s, double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_AB_CDF evaluates the truncated Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, B, the lower and upper truncation limits. // // Output, double NORMAL_TRUNCATED_AB_CDF, the value of the CDF. // { double alpha; double alpha_cdf; double beta; double beta_cdf; double cdf; double xi; double xi_cdf; alpha = ( a - mu ) / s; beta = ( b - mu ) / s; xi = ( x - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); beta_cdf = normal_01_cdf ( beta ); xi_cdf = normal_01_cdf ( xi ); cdf = ( xi_cdf - alpha_cdf ) / ( beta_cdf - alpha_cdf ); return cdf; } //****************************************************************************80 double normal_truncated_ab_cdf_inv ( double cdf, double mu, double s, double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_AB_CDF_INV inverts the truncated Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, B, the lower and upper truncation limits. // // Output, double NORMAL_TRUNCATED_AB_CDF_INV, the corresponding argument. // { double alpha; double alpha_cdf; double beta; double beta_cdf; double x; double xi; double xi_cdf; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "NORMAL_TRUNCATED_AB_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } alpha = ( a - mu ) / s; beta = ( b - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); beta_cdf = normal_01_cdf ( beta ); xi_cdf = ( beta_cdf - alpha_cdf ) * cdf + alpha_cdf; xi = normal_01_cdf_inv ( xi_cdf ); x = mu + s * xi; return x; } //****************************************************************************80 double normal_truncated_ab_mean ( double mu, double s, double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_AB_MEAN returns the mean of the truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double MU, S, the mean and standard deviatione of the // parent Normal distribution. // // Input, double A, B, the lower and upper truncation limits. // // Output, double NORMAL_TRUNCATED_AB_MEAN, the mean of the PDF. // { double alpha; double alpha_cdf; double alpha_pdf; double beta; double beta_cdf; double beta_pdf; double mean; alpha = ( a - mu ) / s; beta = ( b - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); beta_cdf = normal_01_cdf ( beta ); alpha_pdf = normal_01_pdf ( alpha ); beta_pdf = normal_01_pdf ( beta ); mean = mu + s * ( alpha_pdf - beta_pdf ) / ( beta_cdf - alpha_cdf ); return mean; } //****************************************************************************80 double normal_truncated_ab_pdf ( double x, double mu, double s, double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_AB_PDF evaluates the truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, B, the lower and upper truncation limits. // // Output, double NORMAL_TRUNCATED_AB_PDF, the value of the PDF. // { double alpha; double alpha_cdf; double beta; double beta_cdf; double pdf; double xi; double xi_pdf; alpha = ( a - mu ) / s; beta = ( b - mu ) / s; xi = ( x - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); beta_cdf = normal_01_cdf ( beta ); xi_pdf = normal_01_pdf ( xi ); pdf = xi_pdf / ( beta_cdf - alpha_cdf ) / s; return pdf; } //****************************************************************************80 double normal_truncated_ab_sample ( double mu, double s, double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_AB_SAMPLE samples the truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, B, the lower and upper truncation limits. // // Input/output, int &SEED, a seed for the random number // generator. // // Output, double NORMAL_TRUNCATED_AB_SAMPLE, a sample of the PDF. // { double alpha; double alpha_cdf; double beta; double beta_cdf; double u; double x; double xi; double xi_cdf; alpha = ( a - mu ) / s; beta = ( b - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); beta_cdf = normal_01_cdf ( beta ); u = r8_uniform_01 ( seed ); xi_cdf = alpha_cdf + u * ( beta_cdf - alpha_cdf ); xi = normal_01_cdf_inv ( xi_cdf ); x = mu + s * xi; return x; } //****************************************************************************80 double normal_truncated_ab_variance ( double mu, double s, double a, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_AB_VARIANCE returns the variance of the truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, B, the lower and upper truncation limits. // // Output, double NORMAL_TRUNCATED_AB_VARIANCE, the variance of the PDF. // { double alpha; double alpha_cdf; double alpha_pdf; double beta; double beta_cdf; double beta_pdf; double variance; alpha = ( a - mu ) / s; beta = ( b - mu ) / s; alpha_pdf = normal_01_pdf ( alpha ); beta_pdf = normal_01_pdf ( beta ); alpha_cdf = normal_01_cdf ( alpha ); beta_cdf = normal_01_cdf ( beta ); variance = s * s * ( 1.0 + ( alpha * alpha_pdf - beta * beta_pdf ) / ( beta_cdf - alpha_cdf ) - pow ( ( alpha_pdf - beta_pdf ) / ( beta_cdf - alpha_cdf ), 2 ) ); return variance; } //****************************************************************************80 double normal_truncated_a_cdf ( double x, double mu, double s, double a ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_A_CDF evaluates the lower truncated Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, the lower truncation limit. // // Output, double NORMAL_TRUNCATED_A_CDF, the value of the CDF. // { double alpha; double alpha_cdf; double cdf; double xi; double xi_cdf; alpha = ( a - mu ) / s; xi = ( x - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); xi_cdf = normal_01_cdf ( xi ); cdf = ( xi_cdf - alpha_cdf ) / ( 1.0 - alpha_cdf ); return cdf; } //****************************************************************************80 double normal_truncated_a_cdf_inv ( double cdf, double mu, double s, double a ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_A_CDF_INV inverts the lower truncated Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, the lower truncation limit. // // Output, double NORMAL_TRUNCATED_A_CDF_INV, the corresponding argument. // { double alpha; double alpha_cdf; double x; double xi; double xi_cdf; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "NORMAL_TRUNCATED_A_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } alpha = ( a - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); xi_cdf = ( 1.0 - alpha_cdf ) * cdf + alpha_cdf; xi = normal_01_cdf_inv ( xi_cdf ); x = mu + s * xi; return x; } //****************************************************************************80 double normal_truncated_a_mean ( double mu, double s, double a ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_A_MEAN returns the mean of the lower truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double MU, S, the mean and standard deviatione of the // parent Normal distribution. // // Input, double A, the lower truncation limit. // // Output, double NORMAL_TRUNCATED_A_MEAN, the mean of the PDF. // { double alpha; double alpha_cdf; double alpha_pdf; double mean; alpha = ( a - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); alpha_pdf = normal_01_pdf ( alpha ); mean = mu + s * alpha_pdf / ( 1.0 - alpha_cdf ); return mean; } //****************************************************************************80 double normal_truncated_a_pdf ( double x, double mu, double s, double a ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_A_PDF evaluates the lower truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, the lower truncation limit. // // Output, double NORMAL_TRUNCATED_A_PDF, the value of the PDF. // { double alpha; double alpha_cdf; double pdf; double xi; double xi_pdf; alpha = ( a - mu ) / s; xi = ( x - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); xi_pdf = normal_01_pdf ( xi ); pdf = xi_pdf / ( 1.0 - alpha_cdf ) / s; return pdf; } //****************************************************************************80 double normal_truncated_a_sample ( double mu, double s, double a, int &seed ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_A_SAMPLE samples the lower truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, the lower truncation limit. // // Input/output, int &SEED, a seed for the random number // generator. // // Output, double NORMAL_TRUNCATED_A_SAMPLE, a sample of the PDF. // { double alpha; double alpha_cdf; double u; double x; double xi; double xi_cdf; alpha = ( a - mu ) / s; alpha_cdf = normal_01_cdf ( alpha ); u = r8_uniform_01 ( seed ); xi_cdf = alpha_cdf + u * ( 1.0 - alpha_cdf ); xi = normal_01_cdf_inv ( xi_cdf ); x = mu + s * xi; return x; } //****************************************************************************80 double normal_truncated_a_variance ( double mu, double s, double a ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_A_VARIANCE: variance of the lower truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double A, the lower truncation limit. // // Output, double NORMAL_TRUNCATED_A_VARIANCE, the variance of the PDF. // { double alpha; double alpha_cdf; double alpha_pdf; double variance; alpha = ( a - mu ) / s; alpha_pdf = normal_01_pdf ( alpha ); alpha_cdf = normal_01_cdf ( alpha ); variance = s * s * ( 1.0 + alpha * alpha_pdf / ( 1.0 - alpha_cdf ) - pow ( alpha_pdf / ( 1.0 - alpha_cdf ), 2 ) ); return variance; } //****************************************************************************80 double normal_truncated_b_cdf ( double x, double mu, double s, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_B_CDF evaluates the upper truncated Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double B, the upper truncation limit. // // Output, double NORMAL_TRUNCATED_B_CDF, the value of the CDF. // { double beta; double beta_cdf; double cdf; double xi; double xi_cdf; beta = ( b - mu ) / s; xi = ( x - mu ) / s; beta_cdf = normal_01_cdf ( beta ); xi_cdf = normal_01_cdf ( xi ); cdf = xi_cdf / beta_cdf; return cdf; } //****************************************************************************80 double normal_truncated_b_cdf_inv ( double cdf, double mu, double s, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_B_CDF_INV inverts the upper truncated Normal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double B, the upper truncation limit. // // Output, double NORMAL_TRUNCATED_B_CDF_INV, the corresponding argument. // { double beta; double beta_cdf; double x; double xi; double xi_cdf; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "NORMAL_TRUNCATED_B_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } beta = ( b - mu ) / s; beta_cdf = normal_01_cdf ( beta ); xi_cdf = beta_cdf * cdf; xi = normal_01_cdf_inv ( xi_cdf ); x = mu + s * xi; return x; } //****************************************************************************80 double normal_truncated_b_mean ( double mu, double s, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_B_MEAN returns the mean of the upper truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double MU, S, the mean and standard deviatione of the // parent Normal distribution. // // Input, double B, the upper truncation limit. // // Output, double NORMAL_TRUNCATED_B_MEAN, the mean of the PDF. // { double beta; double beta_cdf; double beta_pdf; double mean; beta = ( b - mu ) / s; beta_cdf = normal_01_cdf ( beta ); beta_pdf = normal_01_pdf ( beta ); mean = mu - s * beta_pdf / beta_cdf; return mean; } //****************************************************************************80 double normal_truncated_b_pdf ( double x, double mu, double s, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_B_PDF evaluates the upper truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double B, the upper truncation limit. // // Output, double NORMAL_TRUNCATED_B_PDF, the value of the PDF. // { double beta; double beta_cdf; double pdf; double xi; double xi_pdf; beta = ( b - mu ) / s; xi = ( x - mu ) / s; beta_cdf = normal_01_cdf ( beta ); xi_pdf = normal_01_pdf ( xi ); pdf = xi_pdf / beta_cdf / s; return pdf; } //****************************************************************************80 double normal_truncated_b_sample ( double mu, double s, double b, int &seed ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_B_SAMPLE samples the upper truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double B, the upper truncation limit. // // Input/output, int &SEED, a seed for the random number // generator. // // Output, double NORMAL_TRUNCATED_B_SAMPLE, a sample of the PDF. // { double beta; double beta_cdf; double u; double x; double xi; double xi_cdf; beta = ( b - mu ) / s; beta_cdf = normal_01_cdf ( beta ); u = r8_uniform_01 ( seed ); xi_cdf = u * beta_cdf; xi = normal_01_cdf_inv ( xi_cdf ); x = mu + s * xi; return x; } //****************************************************************************80 double normal_truncated_b_variance ( double mu, double s, double b ) //****************************************************************************80 // // Purpose: // // NORMAL_TRUNCATED_B_VARIANCE: variance of the upper truncated Normal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 August 2013 // // Author: // // John Burkardt // // Parameters: // // Input, double MU, S, the mean and standard deviation of the // parent Normal distribution. // // Input, double B, the upper truncation limit. // // Output, double NORMAL_TRUNCATED_B_VARIANCE, the variance of the PDF. // { double beta; double beta_cdf; double beta_pdf; double variance; beta = ( b - mu ) / s; beta_pdf = normal_01_pdf ( beta ); beta_cdf = normal_01_cdf ( beta ); variance = s * s * ( 1.0 - beta * beta_pdf / beta_cdf - pow ( beta_pdf / beta_cdf, 2 ) ); return variance; } //****************************************************************************80 void owen_values ( int &n_data, double &h, double &a, double &t ) //****************************************************************************80 // // Purpose: // // OWEN_VALUES returns some values of Owen's T function. // // Discussion: // // Owen's T function is useful for computation of the bivariate normal // distribution and the distribution of a skewed normal distribution. // // Although it was originally formulated in terms of the bivariate // normal function, the function can be defined more directly as // // T(H,A) = 1 / ( 2 * pi ) * // Integral ( 0 <= X <= A ) e^(H^2*(1+X^2)/2) / (1+X^2) dX // // In Mathematica, the function can be evaluated by: // // fx = 1/(2*Pi) * Integrate [ E^(-h^2*(1+x^2)/2)/(1+x^2), {x,0,a} ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 May 2009 // // Author: // // John Burkardt // // Reference: // // Mike Patefield, David Tandy, // Fast and Accurate Calculation of Owen's T Function, // Journal of Statistical Software, // Volume 5, Number 5, 2000, pages 1-25. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &H, a parameter. // // Output, double &A, the upper limit of the integral. // // Output, double &T, the value of the function. // { # define N_MAX 28 static double a_vec[N_MAX] = { 0.2500000000000000E+00, 0.4375000000000000E+00, 0.9687500000000000E+00, 0.0625000000000000E+00, 0.5000000000000000E+00, 0.9999975000000000E+00, 0.5000000000000000E+00, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.5000000000000000E+00, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.5000000000000000E+00, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.5000000000000000E+00, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.5000000000000000E+00, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.1000000000000000E+02, 0.1000000000000000E+03 }; static double h_vec[N_MAX] = { 0.0625000000000000E+00, 6.5000000000000000E+00, 7.0000000000000000E+00, 4.7812500000000000E+00, 2.0000000000000000E+00, 1.0000000000000000E+00, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.2500000000000000E+00, 0.2500000000000000E+00, 0.2500000000000000E+00, 0.2500000000000000E+00, 0.1250000000000000E+00, 0.1250000000000000E+00, 0.1250000000000000E+00, 0.1250000000000000E+00, 0.7812500000000000E-02, 0.7812500000000000E-02, 0.7812500000000000E-02, 0.7812500000000000E-02, 0.7812500000000000E-02, 0.7812500000000000E-02 }; static double t_vec[N_MAX] = { 3.8911930234701366E-02, 2.0005773048508315E-11, 6.3990627193898685E-13, 1.0632974804687463E-07, 8.6250779855215071E-03, 6.6741808978228592E-02, 0.4306469112078537E-01, 0.6674188216570097E-01, 0.7846818699308410E-01, 0.7929950474887259E-01, 0.6448860284750376E-01, 0.1066710629614485E+00, 0.1415806036539784E+00, 0.1510840430760184E+00, 0.7134663382271778E-01, 0.1201285306350883E+00, 0.1666128410939293E+00, 0.1847501847929859E+00, 0.7317273327500385E-01, 0.1237630544953746E+00, 0.1737438887583106E+00, 0.1951190307092811E+00, 0.7378938035365546E-01, 0.1249951430754052E+00, 0.1761984774738108E+00, 0.1987772386442824E+00, 0.2340886964802671E+00, 0.2479460829231492E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; h = 0.0; a = 0.0; t = 0.0; } else { h = h_vec[n_data-1]; a = a_vec[n_data-1]; t = t_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double pareto_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // PARETO_CDF evaluates the Pareto CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double PARETO_CDF, the value of the CDF. // { double cdf; if ( x < a ) { cdf = 0.0; } else { cdf = 1.0 - pow ( ( a / x ), b ); } return cdf; } //****************************************************************************80 double pareto_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // PARETO_CDF_INV inverts the Pareto CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double PARETO_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "PARETO_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a / pow ( 1.0 - cdf, 1.0 / b ); return x; } //****************************************************************************80 bool pareto_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // PARETO_CHECK checks the parameters of the Pareto CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, bool PARETO_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cerr << " \n"; cerr << "PARETO_CHECK - Fatal error!\n"; cerr << " A <= 0.\n"; return false; } if ( b <= 0.0 ) { cerr << " \n"; cerr << "PARETO_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double pareto_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // PARETO_MEAN returns the mean of the Pareto PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double PARETO_MEAN, the mean of the PDF. // { double mean; if ( b <= 1.0 ) { cerr << " \n"; cerr << "PARETO_MEAN - Fatal error!\n"; cerr << " For B <= 1, the mean does not exist.\n"; mean = 0.0; return mean; } mean = b * a / ( b - 1.0 ); return mean; } //****************************************************************************80 double pareto_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // PARETO_PDF evaluates the Pareto PDF. // // Discussion: // // PDF(A,B;X) = B * A^B / X^(B+1). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, the parameters of the PDF. // 0.0 < A. // 0.0 < B. // // Output, double PARETO_PDF, the value of the PDF. // { double pdf; if ( x < a ) { pdf = 0.0; } else { pdf = b * pow ( a, b ) / pow ( x, ( b + 1.0 ) ); } return pdf; } //****************************************************************************80 double pareto_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // PARETO_SAMPLE samples the Pareto PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double PARETO_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = pareto_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double pareto_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // PARETO_VARIANCE returns the variance of the Pareto PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double PARETO_VARIANCE, the variance of the PDF. // { double variance; if ( b <= 2.0 ) { cout << " \n"; cout << "PARETO_VARIANCE - Warning!\n"; cout << " For B <= 2, the variance does not exist.\n"; variance = 0.0; return variance; } variance = a * a * b / ( pow ( ( b - 1.0 ), 2 ) * ( b - 2.0 ) ); return variance; } //****************************************************************************80 bool pearson_05_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // PEARSON_05_CHECK checks the parameters of the Pearson 5 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Output, bool PEARSON_05_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cerr << " \n"; cerr << "PEARSON_05_CHECK - Fatal error!\n"; cerr << " A <= 0.\n"; return false; } if ( b <= 0.0 ) { cerr << " \n"; cerr << "PEARSON_05_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double pearson_05_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // PEARSON_05_MEAN evaluates the mean of the Pearson 5 PDF. // // Discussion: // // The mean is undefined for B <= 1. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Output, double PEARSON_05_MEAN, the mean of the PDF. // { double mean; if ( b <= 1.0 ) { cout << " \n"; cout << "PEARSON_05_MEAN - Warning!\n"; cout << " MEAN undefined for B <= 1.\n"; mean = c; return mean; } mean = c + a / ( b - 1.0 ); return mean; } //****************************************************************************80 double pearson_05_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // PEARSON_05_PDF evaluates the Pearson 5 PDF. // // Discussion: // // PDF(A,B;X) = A^B * ( X - C )^(-B-1) // * exp ( - A / ( X - C ) ) / Gamma ( B ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // C < X // // Input, double A, B, C, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Output, double PDF, the value of the PDF. // { double pdf; if ( x <= c ) { pdf = 0.0; } else { pdf = pow ( a, b ) * pow ( x - c, - b - 1.0 ) * exp ( - a / ( x - c ) ) / r8_gamma ( b ); } return pdf; } //****************************************************************************80 double pearson_05_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // PEARSON_05_SAMPLE samples the Pearson 5 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double PEARSON_05_SAMPLE, a sample of the PDF. // { double a2; double b2; double c2; double x; double x2; a2 = 0.0; b2 = b; c2 = 1.0 / a; x2 = gamma_sample ( a2, b2, c2, seed ); x = c + 1.0 / x2; return x; } //****************************************************************************80 bool planck_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // PLANCK_CHECK checks the parameters of the Planck PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, bool PLANCK_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cerr << "\n"; cerr << "PLANCK_CHECK - Fatal error!\n"; cerr << " A <= 0.\n"; return false; } if ( b <= 0.0 ) { cerr << "\n"; cerr << "PLANCK_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double planck_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // PLANCK_MEAN returns the mean of the Planck PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double PLANCK_MEAN, the mean of the PDF. // { double mean; mean = ( b + 1.0 ) * zeta ( b + 2.0 ) / zeta ( b + 1.0 ); return mean; } //****************************************************************************80 double planck_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // PLANCK_PDF evaluates the Planck PDF. // // Discussion: // // The Planck PDF has the form // // PDF(A,B;X) = A^(B+1) * X^B / ( exp ( A * X ) - 1 ) / K // // where K is the normalization constant, and has the value // // K = Gamma ( B + 1 ) * Zeta ( B + 1 ). // // The original Planck distribution governed the frequencies in // blackbody radiation at a given temperature T, and has the form // // PDF(A;X) = K * X^3 / ( exp ( A * X ) - 1 ) // // where // // K = 15 / PI^4. // // Thus, in terms of the Planck PDF, the original Planck distribution // has A = 1, B = 3. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double PLANCK_PDF, the value of the PDF. // { double k; double pdf; if ( x < 0.0 ) { pdf = 0.0; } else { k = r8_gamma ( b + 1.0 ) * zeta ( b + 1.0 ); pdf = pow ( a, b + 1.0 ) * pow ( x, b ) / ( exp ( a * x ) - 1.0 ) / k; } return pdf; } //****************************************************************************80 double planck_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // PLANCK_SAMPLE samples the Planck PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 October 2004 // // Author: // // John Burkardt // // Reference: // // Luc Devroye, // Non-Uniform Random Variate Generation, // Springer Verlag, 1986, pages 552. // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double PLANCK_SAMPLE, a sample of the PDF. // { double a2; double b2; double c2; double g; double x; int z; // a2 = 0.0; b2 = 1.0; c2 = b + 1.0; g = gamma_sample ( a2, b2, c2, seed ); z = zipf_sample ( c2, seed ); x = g / ( a * ( double ) ( z ) ); return x; } //****************************************************************************80 double planck_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // PLANCK_VARIANCE returns the variance of the Planck PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Output, double PLANCK_VARIANCE, the variance of the PDF. // { double variance; variance = 0.0; return variance; } //****************************************************************************80 double point_distance_1d_pdf ( double x, int a, double b ) //****************************************************************************80 // // Purpose: // // POINT_DISTANCE_1D_PDF evaluates the point distance PDF in 1D. // // Discussion: // // It is assumed that a set of points has been generated in 1D // according to a Poisson process. The number of points in a region // of size LENGTH is a Poisson variate with mean value B * LENGTH. // // For a point chosen at random, we may now find the nearest // Poisson point, the second nearest and so on. We are interested // in the PDF that governs the expected behavior of the distances // of rank A = 1, 2, 3, ... with Poisson density B. // // Note that this PDF is a form of the Gamma PDF.??? // // PDF(A,B;X) = B^A * X^( A - 1 ) * EXP ( - B * X ) / ( A - 1 )! // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X. // // Input, int A, indicates the degree of nearness of the point. // A = 1 means the nearest point, A = 2 the second nearest, and so on. // 0 < A. // // Input, double B, the point density. 0.0 < B. // // Output, double PDF, the value of the PDF. // { double pdf; if ( a < 1 ) { cerr << " \n"; cerr << "POINT_DISTANCE_1D_PDF - Fatal error!\n"; cerr << " Input parameter A < 1.\n"; exit ( 1 ); } if ( b <= 0.0 ) { cerr << " \n"; cerr << "POINT_DISTANCE_1D_PDF - Fatal error!\n"; cerr << " Input parameter B <= 0.0.\n"; exit ( 1 ); } if ( x < 0.0 ) { pdf = 0.0; } else { pdf = pow ( b, a ) * pow ( x, a - 1 ) * exp ( - b * x ) / i4_factorial ( a - 1 ); } return pdf; } //****************************************************************************80 double point_distance_2d_pdf ( double x, int a, double b ) //****************************************************************************80 // // Purpose: // // POINT_DISTANCE_2D_PDF evaluates the point distance PDF in 2D. // // Discussion: // // It is assumed that a set of points has been generated in 2D // according to a Poisson process. The number of points in a region // of size AREA is a Poisson variate with mean value B * AREA. // // For a point chosen at random, we may now find the nearest // Poisson point, the second nearest and so on. We are interested // in the PDF that governs the expected behavior of the distances // of rank A = 1, 2, 3, ... with Poisson density B. // // PDF(A,B;X) = 2 * ( B * PI )^A * X^( 2 * A - 1 ) // * EXP ( - B * PI * X * X ) / ( A - 1 )! // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // Daniel Zwillinger, editor, // CRC Standard Mathematical Tables and Formulae, // 30th Edition, // CRC Press, 1996, pages 579. // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X. // // Input, int A, indicates the degree of nearness of the point. // A = 1 means the nearest point, A = 2 the second nearest, and so on. // 0 < A. // // Input, double B, the point density. 0.0 < B. // // Output, double PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; if ( a < 1 ) { cerr << " \n"; cerr << "POINT_DISTANCE_2D_PDF - Fatal error!\n"; cerr << " Input parameter A < 1.\n"; exit ( 1 ); } if ( b <= 0.0 ) { cerr << " \n"; cerr << "POINT_DISTANCE_2D_PDF - Fatal error!\n"; cerr << " Input parameter B <= 0.0.\n"; exit ( 1 ); } if ( x < 0.0 ) { pdf = 0.0; } else { pdf = 2.0 * pow ( b * pi, a ) * pow ( x, 2 * a - 1 ) * exp ( - b * pi * x * x ) / i4_factorial ( a - 1 ); } return pdf; } //****************************************************************************80 double point_distance_3d_pdf ( double x, int a, double b ) //****************************************************************************80 // // Purpose: // // POINT_DISTANCE_3D_PDF evaluates the point distance PDF in the 3D. // // Discussion: // // It is assumed that a set of points has been generated in 3D // according to a Poisson process. The number of points in a region // of size VOLUME is a Poisson variate with mean value B * VOLUME. // // For a point chosen at random, we may now find the nearest // Poisson point, the second nearest and so on. We are interested // in the PDF that governs the expected behavior of the distances // of rank A = 1, 2, 3, ... with Poisson density B. // // PDF(A,B;X) = 3 * ( (4/3) * B * PI )^A * X^( 3 * A - 1 ) // * EXP ( - (4/3) * B * PI * X * X * X ) / ( A - 1 )! // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // Daniel Zwillinger, editor, // CRC Standard Mathematical Tables and Formulae, // 30th Edition, // CRC Press, 1996, pages 580. // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X. // // Input, int A, indicates the degree of nearness of the point. // A = 1 means the nearest point, A = 2 the second nearest, and so on. // 0 < A. // // Input, double B, the Poisson point density. 0.0 < B. // // Output, double PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; if ( a < 1 ) { cerr << " \n"; cerr << "POINT_DISTANCE_3D_PDF - Fatal error!\n"; cerr << " Input parameter A < 1.\n"; exit ( 1 ); } if ( b <= 0.0 ) { cerr << " \n"; cerr << "POINT_DISTANCE_3D_PDF - Fatal error!\n"; cerr << " Input parameter B <= 0.0.\n"; exit ( 1 ); } if ( x < 0.0 ) { pdf = 0.0; } else { pdf = 3.0 * pow ( ( ( 4.0 / 3.0 ) * b * pi ), a ) * pow ( x, 3 * a - 1 ) * exp ( - ( 4.0 / 3.0 ) * b * pi * x * x * x ) / i4_factorial ( a - 1 ); } return pdf; } //****************************************************************************80 double poisson_cdf ( int k, double a ) //****************************************************************************80 // // Purpose: // // POISSON_CDF evaluates the Poisson CDF. // // Discussion: // // CDF(K,A) is the probability that the number of events observed // in a unit time period will be no greater than K, given that the // expected number of events in a unit time period is A. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 January 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int K, the argument of the CDF. // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double POISSON_CDF, the value of the CDF. // { double cdf; int i; double last; double next; // // Check. // if ( a <= 0.0 ) { cerr << "\n"; cerr << "POISSON_CDF - Fatal error!\n"; cerr << " A <= 0.\n"; return 0; } // // Special cases. // if ( k < 0 ) { cdf = 0.0; return cdf; } // // General case. // next = exp ( - a ); cdf = next; for ( i = 1; i <= k; i++ ) { last = next; next = last * a / ( double ) i; cdf = cdf + next; } return cdf; } //****************************************************************************80 int poisson_cdf_inv ( double cdf, double a ) //****************************************************************************80 // // Purpose: // // POISSON_CDF_INV inverts the Poisson CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, a value of the CDF. // 0 <= CDF < 1. // // Input, double A, the parameter of the PDF. // 0.0 < A. // // Output, int POISSON_CDF_INV, the corresponding argument. // { int i; double last; double newval; double sum2; double sumold; int x; int xmax = 100; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "POISSON_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } // // Now simply start at X = 0, and find the first value for which // CDF(X-1) <= CDF <= CDF(X). // sum2 = 0.0; for ( i = 0; i <= xmax; i++ ) { sumold = sum2; if ( i == 0 ) { newval = exp ( - a ); sum2 = newval; } else { last = newval; newval = last * a / ( double ) ( i ); sum2 = sum2 + newval; } if ( sumold <= cdf && cdf <= sum2 ) { x = i; return x; } } cout << " \n"; cout << "POISSON_CDF_INV - Warning!\n"; cout << " Exceeded XMAX = " << xmax << "\n"; x = xmax; return x; } //****************************************************************************80 void poisson_cdf_values ( int &n_data, double &a, int &x, double &fx ) //****************************************************************************80 // // Purpose: // // POISSON_CDF_VALUES returns some values of the Poisson CDF. // // Discussion: // // CDF(X)(A) is the probability of at most X successes in unit time, // given that the expected mean number of successes is A. // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`DiscreteDistributions`] // dist = PoissonDistribution [ a ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Daniel Zwillinger, // CRC Standard Mathematical Tables and Formulae, // 30th Edition, CRC Press, 1996, pages 653-658. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &A, the parameter of the function. // // Output, int *X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 21 static double a_vec[N_MAX] = { 0.02E+00, 0.10E+00, 0.10E+00, 0.50E+00, 0.50E+00, 0.50E+00, 1.00E+00, 1.00E+00, 1.00E+00, 1.00E+00, 2.00E+00, 2.00E+00, 2.00E+00, 2.00E+00, 5.00E+00, 5.00E+00, 5.00E+00, 5.00E+00, 5.00E+00, 5.00E+00, 5.00E+00 }; static double fx_vec[N_MAX] = { 0.9801986733067553E+00, 0.9048374180359596E+00, 0.9953211598395555E+00, 0.6065306597126334E+00, 0.9097959895689501E+00, 0.9856123220330293E+00, 0.3678794411714423E+00, 0.7357588823428846E+00, 0.9196986029286058E+00, 0.9810118431238462E+00, 0.1353352832366127E+00, 0.4060058497098381E+00, 0.6766764161830635E+00, 0.8571234604985470E+00, 0.6737946999085467E-02, 0.4042768199451280E-01, 0.1246520194830811E+00, 0.2650259152973617E+00, 0.4404932850652124E+00, 0.6159606548330631E+00, 0.7621834629729387E+00 }; static int x_vec[N_MAX] = { 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; a = 0.0; x = 0; fx = 0.0; } else { a = a_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool poisson_check ( double a ) //****************************************************************************80 // // Purpose: // // POISSON_CHECK checks the parameter of the Poisson PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 < A. // // Output, bool POISSON_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cerr << " \n"; cerr << "POISSON_CHECK - Fatal error!\n"; cerr << " A <= 0.\n"; return false; } return true; } //****************************************************************************80 double poisson_kernel ( double r, int n, double c[], double x[], double y[] ) //****************************************************************************80 // // Purpose: // // POISSON_KERNEL evaluates the Poisson kernel. // // Discussion: // // P(X,Y) = ( R^2 - |X-C|^2 ) / ( R * A * |X-Y|^N ) // // where the N-dimensional ball has radius R and center C, // and A is the area of the unit sphere. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 November 2011 // // Author: // // John Burkardt // // Parameters: // // Input, double R, the radius of the ball. // // Input, int N, the spatial dimension. // // Input, double C(N), the center of the ball. // // Input, double X(N), a point inside the ball. // // Input, double Y(N), a point on the surface of the ball. // // Output, double POISSON_KERNEL, the Poisson kernel function P(X,Y). // { double area; double b; double p; double t; double xc_diff_norm; double xy_diff_norm; xc_diff_norm = r8vec_diff_norm ( n, x, c ); xy_diff_norm = r8vec_diff_norm ( n, x, y ); area = sphere_unit_area_nd ( n ); t = ( r + xc_diff_norm ) * ( r - xc_diff_norm ); b = r * area * pow ( xy_diff_norm, n ); p = t / b; return p; } //****************************************************************************80 double poisson_mean ( double a ) //****************************************************************************80 // // Purpose: // // POISSON_MEAN returns the mean of the Poisson PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double POISSON_MEAN, the mean of the PDF. // { if ( a <= 0.0 ) { cerr << "\n"; cerr << "POISSON_MEAN - Fatal error!\n" ; cerr << " A <= 0.\n"; return 0; } return a; } //****************************************************************************80 double poisson_pdf ( int k, double a ) //****************************************************************************80 // // Purpose: // // POISSON_PDF evaluates the Poisson PDF. // // Discussion: // // PDF(K,A) is the probability that the number of events observed // in a unit time period will be K, given the expected number // of events in a unit time. // // The parameter A is the expected number of events per unit time. // // The Poisson PDF is a discrete version of the exponential PDF. // // The time interval between two Poisson events is a random // variable with the exponential PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int K, the argument of the PDF. // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double POISSON_PDF, the value of the PDF. // { double pdf; // // Check. // if ( a <= 0.0 ) { cerr << "\n"; cerr << "POISSON_PDF - Fatal error!\n"; cerr << " A <= 0.\n"; pdf = 0.0; return pdf; } pdf = exp ( -a ) * pow ( a, ( double ) k ) / i4_factorial ( k ); return pdf; } //****************************************************************************80 int poisson_sample ( double a, int &seed ) //****************************************************************************80 // // Purpose: // // POISSON_SAMPLE samples the Poisson PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0 < A. // // Input/output, int &SEED, the random number generator seed. // // Output, int POISSON_SAMPLE, a sample of the PDF. // { double cdf; int i; int KMAX = 100; double last; double next; double sum; double sumold; // // Check. // if ( a <= 0.0 ) { cerr << "\n"; cerr << "POISSON_SAMPLE - Fatal error!\n"; cerr << " A <= 0.\n"; return 0; } // // Pick a random value of CDF. // cdf = uniform_01_sample ( seed ); // // Now simply start at K = 0, and find the first value for which // CDF(K-1) <= CDF <= CDF(K). // sum = 0.0; for ( i = 0; i <= KMAX; i++ ) { sumold = sum; if ( i == 0 ) { next = exp ( -a ); sum = next; } else { last = next; next = last * a / ( double ) i; sum = sum + next; } if ( sumold <= cdf && cdf <= sum ) { return i; } } cout << "\n"; cout << "POISSON_SAMPLE - Warning!\n"; cout << " Exceeded KMAX = " << KMAX << "\n"; return KMAX; } //****************************************************************************80 double poisson_variance ( double a ) //****************************************************************************80 // // Purpose: // // POISSON_VARIANCE returns the variance of the Poisson PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 February 1999 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double POISSON_VARIANCE, the variance of the PDF. // { // // Check. // if ( a <= 0.0 ) { cerr << "\n"; cerr << "POISSON_VARIANCE - Fatal error!\n"; cerr << " A <= 0.\n"; return (0.0); } return a; } //****************************************************************************80 double power_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // POWER_CDF evaluates the Power CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < A, 0.0 < B, // // Output, double POWER_CDF, the value of the CDF. // { double cdf; if ( x <= 0.0 ) { cdf = 0.0; } else if ( x <= b ) { cdf = pow ( ( x / b ), a ); } else { cdf = 1.0; } return cdf; } //****************************************************************************80 double power_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // POWER_CDF_INV inverts the Power CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Output, double POWER_CDF_INV, the argument of the CDF. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << " \n"; cerr << "POWER_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = 0.0; } else if ( cdf < 1.0 ) { x = b * exp ( log ( cdf ) / a ); } else { x = b; } return x; } //****************************************************************************80 bool power_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // POWER_CHECK checks the parameter of the Power PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Output, bool POWER_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cerr << " \n"; cerr << "POWER_CHECK - Fatal error!\n"; cerr << " A <= 0.\n"; return false; } if ( b <= 0.0 ) { cerr << " \n"; cerr << "POWER_CHECK - Fatal error!\n"; cerr << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double power_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // POWER_MEAN returns the mean of the Power PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Output, double POWER_MEAN, the mean of the PDF. // { double mean; mean = a * b / ( a + 1.0 ); return mean; } //****************************************************************************80 double power_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // POWER_PDF evaluates the Power PDF. // // Discussion: // // PDF(A;X) = (A/B) * (X/B)^(A-1) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // Daniel Zwillinger and Stephen Kokoska, // CRC Standard Probability and Statistics Tables and Formulae, // Chapman and Hall/CRC, 2000, pages 152-153. // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X <= B. // // Input, double A, B, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Output, double POWER_PDF, the value of the PDF. // { double pdf; if ( x < 0.0 || b < x ) { pdf = 0.0; } else { pdf = ( a / b ) * pow ( x / b, a - 1.0 ); } return pdf; } //****************************************************************************80 double power_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // POWER_SAMPLE samples the Power PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double POWER_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = power_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double power_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // POWER_VARIANCE returns the variance of the Power PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, 0.0 < B. // // Output, double POWER_VARIANCE, the variance of the PDF. // { double variance; variance = b * b * a / ( ( a + 1.0 ) * ( a + 1.0 ) * ( a + 2.0 ) ); return variance; } //****************************************************************************80 void psi_values ( int &n_data, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // PSI_VALUES returns some values of the Psi or Digamma function. // // Discussion: // // In Mathematica, the function can be evaluated by: // // PolyGamma[x] // // or // // Polygamma[0,x] // // PSI(X) = d ln ( Gamma ( X ) ) / d X = Gamma'(X) / Gamma(X) // // PSI(1) = -Euler's constant. // // PSI(X+1) = PSI(X) + 1 / X. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 June 2013 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 20 static double fx_vec[N_MAX] = { -10.42375494041108E+00, -5.289039896592188E+00, -3.502524222200133E+00, -2.561384544585116E+00, -1.963510026021423E+00, -1.540619213893190E+00, -1.220023553697935E+00, -0.9650085667061385E+00, -0.7549269499470514E+00, -0.5772156649015329E+00, -0.4237549404110768E+00, -0.2890398965921883E+00, -0.1691908888667997E+00, -0.6138454458511615E-01, 0.3648997397857652E-01, 0.1260474527734763E+00, 0.2085478748734940E+00, 0.2849914332938615E+00, 0.3561841611640597E+00, 0.4227843350984671E+00 }; static double x_vec[N_MAX] = { 0.1E+00, 0.2E+00, 0.3E+00, 0.4E+00, 0.5E+00, 0.6E+00, 0.7E+00, 0.8E+00, 0.9E+00, 1.0E+00, 1.1E+00, 1.2E+00, 1.3E+00, 1.4E+00, 1.5E+00, 1.6E+00, 1.7E+00, 1.8E+00, 1.9E+00, 2.0E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; x = 0.0; fx = 0.0; } else { x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double quasigeometric_cdf ( int x, double a, double b ) //****************************************************************************80 // // Purpose: // // QUASIGEOMETRIC_CDF evaluates the Quasigeometric CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 January 2009 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the maximum number of trials. // // Input, double A, the probability of 0 successes. // 0.0 <= A <= 1.0. // // Input, double B, the depreciation constant. // 0.0 <= B < 1.0. // // Output, double QUASIGEOMETRIC_CDF, the value of the CDF. // { double cdf; if ( x < 0 ) { cdf = 0.0; } else if ( x == 0 ) { cdf = a; } else if ( b == 0.0 ) { cdf = 1.0; } else { cdf = a + ( 1.0 - a ) * ( 1.0 - pow ( b, x ) ); } return cdf; } //****************************************************************************80 int quasigeometric_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // QUASIGEOMETRIC_CDF_INV inverts the Quasigeometric CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 January 2009 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0 // // Input, double A, the probability of 0 successes. // 0.0 <= A <= 1.0. // // Input, double B, the depreciation constant. // 0.0 <= B < 1.0. // // Output, int QUASIGEOMETRIC_CDF_INV, the corresponding value of X. // { int x; if ( cdf < 0.0 || 1.0 < cdf ) { cerr << "\n"; cerr << "QUASIGEOMETRIC_CDF_INV - Fatal error!\n"; cerr << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf < a ) { x = 0; } else if ( b == 0.0 ) { x = 1; } else { x = 1 + ( int ) ( ( log ( 1.0 - cdf ) - log ( 1.0 - a ) ) / log ( b ) ); } return x; } //****************************************************************************80 bool quasigeometric_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // QUASIGEOMETRIC_CHECK checks the parameters of the Quasigeometric CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 January 2009 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of 0 successes. // 0.0 <= A <= 1.0. // // Input, double B, the depreciation constant. // 0.0 <= B < 1.0. // // Output, bool QUASIGEOMETRIC_CHECK, is true if the parameters are legal. // { bool check; if ( a < 0.0 || 1.0 < a ) { cerr << "\n"; cerr << "QUASIGEOMETRIC_CHECK - Fatal error!\n"; cerr << " A < 0 or 1 < A.\n"; check = false; exit ( 1 ); } if ( b < 0.0 || 1.0 <= b ) { cerr << "\n"; cerr << "QUASIGEOMETRIC_CHECK - Fatal error!\n"; cerr << " B < 0 or 1 <= B.\n"; check = false; exit ( 1 ); } check = true; return check; } //****************************************************************************80 double quasigeometric_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // QUASIGEOMETRIC_MEAN returns the mean of the Quasigeometric PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 January 2009 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of 0 successes. // 0.0 <= A <= 1.0. // // Input, double B, the depreciation constant. // 0.0 <= B < 1.0. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = ( 1.0 - a ) / ( 1.0 - b ); return mean; } //****************************************************************************80 double quasigeometric_pdf ( int x, double a, double b ) //****************************************************************************80 // // Purpose: // // QUASIGEOMETRIC_PDF evaluates the Quasigeometric PDF. // // Discussion: // // PDF(A,B;X) = A if 0 = X; // = (1-A) * (1-B) * B^(X-1) if 1 <= X. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 January 2009 // // Author: // // John Burkardt // // Reference: // // Darren Glass, Philip Lowry, // Quasiquasigeometric Distributions and Extra Inning Baseball Games, // Mathematics Magazine, // Volume 81, Number 2, April 2008, pages 127-137. // // Paul Nahin, // Digital Dice: Computational Solutions to Practical Probability Problems, // Princeton University Press, 2008, // ISBN13: 978-0-691-12698-2, // LC: QA273.25.N34. // // Parameters: // // Input, int X, the independent variable. // 0 <= X // // Input, double A, the probability of 0 successes. // 0.0 <= A <= 1.0. // // Input, double B, the depreciation constant. // 0.0 <= B < 1.0. // // Output, double PDF, the value of the PDF. // { double pdf; if ( x < 0 ) { pdf = 0.0; } else if ( x == 0 ) { pdf = a; } else if ( b == 0.0 ) { if ( x == 1 ) { pdf = 1.0; } else { pdf = 0.0; } } else { pdf = ( 1.0 - a ) * ( 1.0 - b ) * pow ( b, x - 1 ); } return pdf; } //****************************************************************************80 int quasigeometric_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // QUASIGEOMETRIC_SAMPLE samples the Quasigeometric PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 January 2009 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of 0 successes. // 0.0 <= A <= 1.0. // // Input, double B, the depreciation constant. // 0.0 <= B < 1.0. // // Input/output, int &SEED, a seed for the random // number generator. // // Output, int QUASIGEOMETRIC_SAMPLE, a sample of the PDF. // { double cdf; int x; cdf = r8_uniform_01 ( seed ); x = quasigeometric_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double quasigeometric_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // QUASIGEOMETRIC_VARIANCE returns the variance of the Quasigeometric PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 January 2009 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the probability of 0 successes. // 0.0 <= A <= 1.0. // // Input, double B, the depreciation constant. // 0.0 <= B < 1.0. // // Output, double QUASIGEOMETRIC_VARIANCE, the variance of the PDF. // { double variance; variance = ( 1.0 - a ) * ( a + b ) / ( 1.0 - b ) / ( 1.0 - b ); return variance; } //****************************************************************************80 float r4_abs ( float x ) //****************************************************************************80 // // Purpose: // // R4_ABS returns the absolute value of an R4. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 December 2006 // // Author: // // John Burkardt // // Parameters: // // Input, float X, the quantity whose absolute value is desired. // // Output, float R4_ABS, the absolute value of X. // { float value; if ( 0.0 <= x ) { value = x; } else { value = -x; } return value; } //****************************************************************************80 int r4_nint ( float x ) //****************************************************************************80 // // Purpose: // // R4_NINT returns the nearest integer to an R4. // // Example: // // X R4_NINT // // 1.3 1 // 1.4 1 // 1.5 1 or 2 // 1.6 2 // 0.0 0 // -0.7 -1 // -1.1 -1 // -1.6 -2 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 November 2006 // // Author: // // John Burkardt // // Parameters: // // Input, float X, the value. // // Output, int R4_NINT, the nearest integer to X. // { int value; if ( x < 0.0 ) { value = - ( int ) ( r4_abs ( x ) + 0.5 ); } else { value = ( int ) ( r4_abs ( x ) + 0.5 ); } return value; } //****************************************************************************80 float r4_uniform_01 ( int &seed ) //****************************************************************************80 // // Purpose: // // R4_UNIFORM_01 returns a real pseudorandom number. // // Discussion: // // This routine implements the recursion // // seed = 16807 * seed mod ( 2^31 - 1 ) // r4_uniform_01 = seed / ( 2^31 - 1 ) // // The integer arithmetic never requires more than 32 bits, // including a sign bit. // // If the initial seed is 12345, then the first three computations are // // Input Output R4_UNIFORM_01 // SEED SEED // // 12345 207482415 0.096616 // 207482415 1790989824 0.833995 // 1790989824 2035175616 0.947702 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 November 2004 // // Author: // // John Burkardt // // Reference: // // Paul Bratley, Bennett Fox, Linus Schrage, // A Guide to Simulation, // Springer Verlag, pages 201-202, 1983. // // Pierre L'Ecuyer, // Random Number Generation, // in Handbook of Simulation // edited by Jerry Banks, // Wiley Interscience, page 95, 1998. // // Bennett Fox, // Algorithm 647: // Implementation and Relative Efficiency of Quasirandom // Sequence Generators, // ACM Transactions on Mathematical Software, // Volume 12, Number 4, pages 362-376, 1986. // // Peter Lewis, Allen Goodman, James Miller, // A Pseudo-Random Number Generator for the System/360, // IBM Systems Journal, // Volume 8, pages 136-143, 1969. // // Parameters: // // Input/output, int &SEED, the "seed" value. Normally, this // value should not be 0. On output, SEED has been updated. // // Output, float R4_UNIFORM_01, a new pseudorandom variate, strictly between // 0 and 1. // { int k; float r; k = seed / 127773; seed = 16807 * ( seed - k * 127773 ) - k * 2836; if ( seed < 0 ) { seed = seed + 2147483647; } // // Although SEED can be represented exactly as a 32 bit integer, // it generally cannot be represented exactly as a 32 bit real number! // r = ( float ) ( seed ) * 4.656612875E-10; return r; } //****************************************************************************80 double r8_abs ( double x ) //****************************************************************************80 // // Purpose: // // R8_ABS returns the absolute value of an R8. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 November 2006 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the quantity whose absolute value is desired. // // Output, double R8_ABS, the absolute value of X. // { double value; if ( 0.0 <= x ) { value = x; } else { value = -x; } return value; } //****************************************************************************80 int r8_ceiling ( double r ) //****************************************************************************80 // // Purpose: // // R8_CEILING rounds an R8 "up" to the nearest integer. // // Example: // // R R8_CEILING // // -1.1 -1 // -1.0 -1 // -0.9 0 // 0.0 0 // 5.0 5 // 5.1 6 // 5.9 6 // 6.0 6 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double R, the real value to be rounded up. // // Output, int R8_CEILING, the rounded value. // { int value; value = ( int ) ( r ); if ( ( double ) value < r ) { value = value + 1; } return value; } //****************************************************************************80 double r8_csc ( double theta ) //****************************************************************************80 // // Purpose: // // R8_CSC returns the cosecant of X. // // Discussion: // // R8_CSC ( THETA ) = 1.0 / SIN ( THETA ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 March 2012 // // Author: // // John Burkardt // // Parameters: // // Input, double THETA, the angle, in radians, whose cosecant is desired. // It must be the case that SIN ( THETA ) is not zero. // // Output, double R8_CSC, the cosecant of THETA. // { double value; value = sin ( theta ); if ( value == 0.0 ) { cout << " \n"; cout << "R8_CSC - Fatal error!\n"; cout << " Cosecant undefined for THETA = " << theta << "\n"; exit ( 1 ); } value = 1.0 / value; return value; } //****************************************************************************80 double r8_epsilon ( ) //****************************************************************************80 // // Purpose: // // R8_EPSILON returns the R8 roundoff unit. // // Discussion: // // The roundoff unit is a number R which is a power of 2 with the // property that, to the precision of the computer's arithmetic, // 1 < 1 + R // but // 1 = ( 1 + R / 2 ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 September 2012 // // Author: // // John Burkardt // // Parameters: // // Output, double R8_EPSILON, the R8 round-off unit. // { const double value = 2.220446049250313E-016; return value; } //****************************************************************************80 double r8_gamma ( double x ) //****************************************************************************80 // // Purpose: // // R8_GAMMA evaluates Gamma(X) for a real argument. // // Discussion: // // This routine calculates the gamma function for a real argument X. // // Computation is based on an algorithm outlined in reference 1. // The program uses rational functions that approximate the gamma // function to at least 20 significant decimal digits. Coefficients // for the approximation over the interval (1,2) are unpublished. // Those for the approximation for 12 <= X are from reference 2. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 January 2008 // // Author: // // Original FORTRAN77 version by William Cody, Laura Stoltz. // C++ version by John Burkardt. // // Reference: // // William Cody, // An Overview of Software Development for Special Functions, // in Numerical Analysis Dundee, 1975, // edited by GA Watson, // Lecture Notes in Mathematics 506, // Springer, 1976. // // John Hart, Ward Cheney, Charles Lawson, Hans Maehly, // Charles Mesztenyi, John Rice, Henry Thatcher, // Christoph Witzgall, // Computer Approximations, // Wiley, 1968, // LC: QA297.C64. // // Parameters: // // Input, double X, the argument of the function. // // Output, double R8_GAMMA, the value of the function. // { // // Coefficients for minimax approximation over (12, INF). // double c[7] = { -1.910444077728E-03, 8.4171387781295E-04, -5.952379913043012E-04, 7.93650793500350248E-04, -2.777777777777681622553E-03, 8.333333333333333331554247E-02, 5.7083835261E-03 }; double eps = 2.22E-16; double fact; double half = 0.5; int i; int n; double one = 1.0; double p[8] = { -1.71618513886549492533811E+00, 2.47656508055759199108314E+01, -3.79804256470945635097577E+02, 6.29331155312818442661052E+02, 8.66966202790413211295064E+02, -3.14512729688483675254357E+04, -3.61444134186911729807069E+04, 6.64561438202405440627855E+04 }; bool parity; double pi = 3.1415926535897932384626434; double q[8] = { -3.08402300119738975254353E+01, 3.15350626979604161529144E+02, -1.01515636749021914166146E+03, -3.10777167157231109440444E+03, 2.25381184209801510330112E+04, 4.75584627752788110767815E+03, -1.34659959864969306392456E+05, -1.15132259675553483497211E+05 }; double res; double sqrtpi = 0.9189385332046727417803297; double sum; double twelve = 12.0; double two = 2.0; double value; double xbig = 171.624; double xden; double xinf = 1.79E+308; double xminin = 2.23E-308; double xnum; double y; double y1; double ysq; double z; double zero = 0.0;; parity = false; fact = one; n = 0; y = x; // // Argument is negative. // if ( y <= zero ) { y = - x; y1 = ( double ) ( int ) ( y ); res = y - y1; if ( res != zero ) { if ( y1 != ( double ) ( int ) ( y1 * half ) * two ) { parity = true; } fact = - pi / sin ( pi * res ); y = y + one; } else { res = xinf; value = res; return value; } } // // Argument is positive. // if ( y < eps ) { // // Argument < EPS. // if ( xminin <= y ) { res = one / y; } else { res = xinf; value = res; return value; } } else if ( y < twelve ) { y1 = y; // // 0.0 < argument < 1.0. // if ( y < one ) { z = y; y = y + one; } // // 1.0 < argument < 12.0. // Reduce argument if necessary. // else { n = ( int ) ( y ) - 1; y = y - ( double ) ( n ); z = y - one; } // // Evaluate approximation for 1.0 < argument < 2.0. // xnum = zero; xden = one; for ( i = 0; i < 8; i++ ) { xnum = ( xnum + p[i] ) * z; xden = xden * z + q[i]; } res = xnum / xden + one; // // Adjust result for case 0.0 < argument < 1.0. // if ( y1 < y ) { res = res / y1; } // // Adjust result for case 2.0 < argument < 12.0. // else if ( y < y1 ) { for ( i = 1; i <= n; i++ ) { res = res * y; y = y + one; } } } else { // // Evaluate for 12.0 <= argument. // if ( y <= xbig ) { ysq = y * y; sum = c[6]; for ( i = 0; i < 6; i++ ) { sum = sum / ysq + c[i]; } sum = sum / y - y + sqrtpi; sum = sum + ( y - half ) * log ( y ); res = exp ( sum ); } else { res = xinf; value = res; return value; } } // // Final adjustments and return. // if ( parity ) { res = - res; } if ( fact != one ) { res = fact / res; } value = res; return value; } //****************************************************************************80 double r8_huge ( ) //****************************************************************************80 // // Purpose: // // R8_HUGE returns a "huge" R8. // // Discussion: // // HUGE_VAL is the largest representable legal real number, and is usually // defined in math.h, or sometimes in stdlib.h. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 08 May 2003 // // Author: // // John Burkardt // // Parameters: // // Output, double R8_HUGE, a "huge" real value. // { return HUGE_VAL; } //****************************************************************************80 double r8_max ( double x, double y ) //****************************************************************************80 // // Purpose: // // R8_MAX returns the maximum of two R8's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, Y, the quantities to compare. // // Output, double R8_MAX, the maximum of X and Y. // { if ( y < x ) { return x; } else { return y; } } //****************************************************************************80 double r8_min ( double x, double y ) //****************************************************************************80 // // Purpose: // // R8_MIN returns the minimum of two R8's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, Y, the quantities to compare. // // Output, double R8_MIN, the minimum of X and Y. // { if ( y < x ) { return y; } else { return x; } } //****************************************************************************80 double r8_modp ( double x, double y ) //****************************************************************************80 // // Purpose: // // R8_MODP returns the nonnegative remainder of R8 division. // // Discussion: // // If // REM = R8_MODP ( X, Y ) // RMULT = ( X - REM ) / Y // then // X = Y * RMULT + REM // where REM is always nonnegative. // // The MOD function computes a result with the same sign as the // quantity being divided. Thus, suppose you had an angle A, // and you wanted to ensure that it was between 0 and 360. // Then mod(A,360.0) would do, if A was positive, but if A // was negative, your result would be between -360 and 0. // // On the other hand, R8_MODP(A,360.0) is between 0 and 360, always. // // Example: // // I J MOD R8_MODP R8_MODP Factorization // // 107 50 7 7 107 = 2 * 50 + 7 // 107 -50 7 7 107 = -2 * -50 + 7 // -107 50 -7 43 -107 = -3 * 50 + 43 // -107 -50 -7 43 -107 = 3 * -50 + 43 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the number to be divided. // // Input, double Y, the number that divides X. // // Output, double R8_MODP, the nonnegative remainder when X is divided by Y. // { double value; if ( y == 0.0 ) { cout << "\n"; cout << "R8_MODP - Fatal error!\n"; cout << " R8_MODP ( X, Y ) called with Y = " << y << "\n"; exit ( 1 ); } value = x - ( ( double ) ( ( int ) ( x / y ) ) ) * y; if ( value < 0.0 ) { value = value + r8_abs ( y ); } return value; } //****************************************************************************80 int r8_nint ( double x ) //****************************************************************************80 // // Purpose: // // R8_NINT returns the nearest integer to an R8. // // Example: // // X R8_NINT // // 1.3 1 // 1.4 1 // 1.5 1 or 2 // 1.6 2 // 0.0 0 // -0.7 -1 // -1.1 -1 // -1.6 -2 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the value. // // Output, int R8_NINT, the nearest integer to X. // { int s; if ( x < 0.0 ) { s = -1; } else { s = 1; } return ( s * ( int ) ( r8_abs ( x ) + 0.5 ) ); } //****************************************************************************80 double r8_pi ( ) //****************************************************************************80 // // Purpose: // // R8_PI returns the value of PI. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 06 May 2003 // // Author: // // John Burkardt // // Parameters: // // Output, double R8_PI, the value of PI. // { const double pi = 3.14159265358979323; return pi; } //****************************************************************************80 double r8_random ( double rlo, double rhi, int &seed ) //****************************************************************************80 // // Purpose: // // R8_RANDOM returns a scaled pseudorandom R8. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 February 2000 // // Author: // // John Burkardt // // Parameters: // // Input, double RLO, RHI, the minimum and maximum values. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double R8_RANDOM, the randomly chosen value. // { double t; t = r8_uniform_01 ( seed ); return ( 1.0 - t ) * rlo + t * rhi; } //****************************************************************************80 double r8_sign ( double x ) //****************************************************************************80 // // Purpose: // // R8_SIGN returns the sign of an R8. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the number whose sign is desired. // // Output, double R8_SIGN, the sign of X. // { if ( x < 0.0 ) { return ( -1.0 ); } else { return ( 1.0 ); } } //****************************************************************************80 double r8_uniform_01 ( int &seed ) //****************************************************************************80 // // Purpose: // // R8_UNIFORM_01 returns a unit pseudorandom R8. // // Discussion: // // This routine implements the recursion // // seed = 16807 * seed mod ( 2^31 - 1 ) // unif = seed / ( 2^31 - 1 ) // // The integer arithmetic never requires more than 32 bits, // including a sign bit. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 August 2004 // // Author: // // John Burkardt // // Reference: // // Paul Bratley, Bennett Fox, Linus Schrage, // A Guide to Simulation, // Springer Verlag, pages 201-202, 1983. // // Bennett Fox, // Algorithm 647: // Implementation and Relative Efficiency of Quasirandom // Sequence Generators, // ACM Transactions on Mathematical Software, // Volume 12, Number 4, pages 362-376, 1986. // // Parameters: // // Input/output, int &SEED, the "seed" value. Normally, this // value should not be 0. On output, SEED has been updated. // // Output, double R8_UNIFORM_01, a new pseudorandom variate, strictly between // 0 and 1. // { int k; double r; k = seed / 127773; seed = 16807 * ( seed - k * 127773 ) - k * 2836; if ( seed < 0 ) { seed = seed + 2147483647; } r = ( double ) ( seed ) * 4.656612875E-10; return r; } //****************************************************************************80 void r8mat_print ( int m, int n, double a[], char *title ) //****************************************************************************80 // // Purpose: // // R8MAT_PRINT prints an R8MAT, with an optional title. // // Discussion: // // The doubly dimensioned array A is treated as a one dimensional vector, // stored by COLUMNS. Entry A(I,J) is stored as A[I+J*M] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 August 2003 // // Author: // // John Burkardt // // Parameters: // // Input, int M, the number of rows in A. // // Input, int N, the number of columns in A. // // Input, double A[M*N], the M by N matrix. // // Input, char *TITLE, a title. // { r8mat_print_some ( m, n, a, 1, 1, m, n, title ); return; } //****************************************************************************80 void r8mat_print_some ( int m, int n, double a[], int ilo, int jlo, int ihi, int jhi, char *title ) //****************************************************************************80 // // Purpose: // // R8MAT_PRINT_SOME prints some of an R8MAT. // // Modified: // // 09 April 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, the number of rows of the matrix. // M must be positive. // // Input, int N, the number of columns of the matrix. // N must be positive. // // Input, double A[M*N], the matrix. // // Input, int ILO, JLO, IHI, JHI, designate the first row and // column, and the last row and column to be printed. // // Input, char *TITLE, a title. { # define INCX 5 int i; int i2hi; int i2lo; int j; int j2hi; int j2lo; cout << "\n"; cout << title << "\n"; // // Print the columns of the matrix, in strips of 5. // for ( j2lo = jlo; j2lo <= jhi; j2lo = j2lo + INCX ) { j2hi = j2lo + INCX - 1; j2hi = i4_min ( j2hi, n ); j2hi = i4_min ( j2hi, jhi ); cout << "\n"; // // For each column J in the current range... // // Write the header. // cout << " Col: "; for ( j = j2lo; j <= j2hi; j++ ) { cout << setw(7) << j << " "; } cout << "\n"; cout << " Row\n"; cout << " ---\n"; // // Determine the range of the rows in this strip. // i2lo = i4_max ( ilo, 1 ); i2hi = i4_min ( ihi, m ); for ( i = i2lo; i <= i2hi; i++ ) { // // Print out (up to) 5 entries in row I, that lie in the current strip. // cout << setw(5) << i << " "; for ( j = j2lo; j <= j2hi; j++ ) { cout << setw(12) << a[i-1+(j-1)*m] << " "; } cout << "\n"; } } return; # undef INCX } //****************************************************************************80 double r8poly_value ( int n, double a[], double x ) //****************************************************************************80 // // Purpose: // // R8POLY_VALUE evaluates a double precision polynomial. // // Discussion: // // For sanity's sake, the value of N indicates the NUMBER of // coefficients, or more precisely, the ORDER of the polynomial, // rather than the DEGREE of the polynomial. The two quantities // differ by 1, but cause a great deal of confusion. // // Given N and A, the form of the polynomial is: // // p(x) = a[0] + a[1] * x + ... + a[n-2] * x^(n-2) + a[n-1] * x^(n-1) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the order of the polynomial. // // Input, double A[N], the coefficients of the polynomial. // A[0] is the constant term. // // Input, double X, the point at which the polynomial is to be evaluated. // // Output, double R8POLY_VALUE, the value of the polynomial at X. // { int i; double value; value = 0.0; for ( i = n-1; 0 <= i; i-- ) { value = value * x + a[i]; } return value; } //****************************************************************************80 double *r8row_max ( int m, int n, double a[] ) //****************************************************************************80 // // Purpose: // // R8ROW_MAX returns the maximums of an R8ROW. // // Example: // // A = // 1 2 3 // 2 6 7 // // MAX = // 3 // 7 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the number of rows and columns in the array. // // Input, double A[M*N], the array to be examined. // // Output, double R8ROW_MAX[M], the maximums of the rows. // { int i; int j; double *amax; amax = new double[m]; for ( i = 0; i < m; i++ ) { amax[i] = a[i+0*m]; for ( j = 1; j < n; j++ ) { if ( amax[i] < a[i+j*m] ) { amax[i] = a[i+j*m]; } } } return amax; } //****************************************************************************80 double *r8row_mean ( int m, int n, double a[] ) //****************************************************************************80 // // Purpose: // // R8ROW_MEAN returns the means of an R8ROW. // // Example: // // A = // 1 2 3 // 2 6 7 // // MEAN = // 2 // 5 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the number of rows and columns in the array. // // Input, double A[M*N], the array to be examined. // // Output, double R8ROW_MEAN[M], the means, or averages, of the rows. // { int i; int j; double *mean; mean = new double[m]; for ( i = 0; i < m; i++ ) { mean[i] = 0.0; for ( j = 0; j < n; j++ ) { mean[i] = mean[i] + a[i+j*m]; } mean[i] = mean[i] / ( double ) ( n ); } return mean; } //****************************************************************************80 double *r8row_min ( int m, int n, double a[] ) //****************************************************************************80 // // Purpose: // // R8ROW_MIN returns the minimums of an R8ROW. // // Example: // // A = // 1 2 3 // 2 6 7 // // MIN = // 1 // 2 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the number of rows and columns in the array. // // Input, double A[M*N], the array to be examined. // // Output, double R8ROW_MIN[M], the minimums of the rows. // { int i; int j; double *amin; amin = new double[m]; for ( i = 0; i < m; i++ ) { amin[i] = a[i+0*m]; for ( j = 1; j < n; j++ ) { if ( a[i+j*m] < amin[i] ) { amin[i] = a[i+j*m]; } } } return amin; } //****************************************************************************80 double *r8row_variance ( int m, int n, double a[] ) //****************************************************************************80 // // Purpose: // // R8ROW_VARIANCE returns the variances of an R8ROW. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the number of rows and columns in the array. // // Input, double A[M*N], the array whose variances are desired. // // Output, double R8ROW_VARIANCE[M], the variances of the rows. // { int i; int j; double mean; double *variance; variance = new double[m]; for ( i = 0; i < m; i++ ) { mean = 0.0; for ( j = 0; j < n; j++ ) { mean = mean + a[i+j*m]; } mean = mean / ( double ) ( n ); variance[i] = 0.0; for ( j = 0; j < n; j++ ) { variance[i] = variance[i] + pow ( ( a[i+j*m] - mean ), 2 ); } if ( 1 < n ) { variance[i] = variance[i] / ( double ) ( n - 1 ); } else { variance[i] = 0.0; } } return variance; } //****************************************************************************80 double r8vec_circular_variance ( int n, double x[] ) //****************************************************************************80 // // Purpose: // // R8VEC_CIRCULAR_VARIANCE returns the circular variance of an R8VEC // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 December 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, double X(N), the vector whose variance is desired. // // Output, double R8VEC_CIRCULAR VARIANCE, the circular variance // of the vector entries. // { int i; double mean; double sum_c; double sum_s; double value; mean = r8vec_mean ( n, x ); sum_c = 0.0; for ( i = 0; i < n; i++ ) { sum_c = sum_c + cos ( x[i] - mean ); } sum_s = 0.0; for ( i = 0; i < n; i++ ) { sum_s = sum_s + sin ( x[i] - mean ); } value = sqrt ( sum_c * sum_c + sum_s * sum_s ) / ( double ) n; value = 1.0 - value; return value; } //****************************************************************************80 double r8vec_diff_norm ( int n, double a[], double b[] ) //****************************************************************************80 // // Purpose: // // R8VEC_DIFF_NORM returns the L2 norm of the difference of R8VEC's. // // Discussion: // // An R8VEC is a vector of R8's. // // The vector L2 norm is defined as: // // R8VEC_NORM_L2 = sqrt ( sum ( 1 <= I <= N ) A(I)^2 ). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 June 2011 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in A. // // Input, double A[N], B[N], the vectors. // // Output, double R8VEC_DIFF_NORM, the L2 norm of A - B. // { int i; double value; value = 0.0; for ( i = 0; i < n; i++ ) { value = value + ( a[i] - b[i] ) * ( a[i] - b[i] ); } value = sqrt ( value ); return value; } //****************************************************************************80 double r8vec_dot ( int n, double a1[], double a2[] ) //****************************************************************************80 // // Purpose: // // R8VEC_DOT computes the dot product of a pair of R8VEC's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vectors. // // Input, double A1[N], A2[N], the two vectors to be considered. // // Output, double R8VEC_DOT, the dot product of the vectors. // { int i; double value; value = 0.0; for ( i = 0; i < n; i++ ) { value = value + a1[i] * a2[i]; } return value; } //****************************************************************************80 double r8vec_length ( int dim_num, double x[] ) //****************************************************************************80 // // Purpose: // // R8VEC_LENGTH returns the Euclidean length of an R8VEC // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 08 August 2005 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the spatial dimension. // // Input, double X[DIM_NUM], the vector. // // Output, double R8VEC_LENGTH, the Euclidean length of the vector. // { int i; double value; value = 0.0; for ( i = 0; i < dim_num; i++ ) { value = value + pow ( x[i], 2 ); } value = sqrt ( value ); return value; } //****************************************************************************80 double r8vec_max ( int n, double *dvec ) //****************************************************************************80 // // Purpose: // // R8VEC_MAX returns the value of the maximum element in an R8VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 1998 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the array. // // Input, double *RVEC, a pointer to the first entry of the array. // // Output, double R8VEC_MAX, the value of the maximum element. This // is set to 0.0 if N <= 0. // { int i; double rmax; double *r8vec_pointer; if ( n <= 0 ) { return 0.0; } for ( i = 0; i < n; i++ ) { if ( i == 0 ) { rmax = *dvec; r8vec_pointer = dvec; } else { r8vec_pointer++; if ( rmax < *r8vec_pointer ) { rmax = *r8vec_pointer; } } } return rmax; } //****************************************************************************80 double r8vec_mean ( int n, double x[] ) //****************************************************************************80 // // Purpose: // // R8VEC_MEAN returns the mean of an R8VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 May 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, double X[N], the vector whose mean is desired. // // Output, double R8VEC_MEAN, the mean, or average, of the vector entries. // { int i; double mean; mean = 0.0; for ( i = 0; i < n; i++ ) { mean = mean + x[i]; } mean = mean / ( double ) n; return mean; } //****************************************************************************80 double r8vec_min ( int n, double *dvec ) //****************************************************************************80 // // Purpose: // // R8VEC_MIN returns the value of the minimum element in an R8VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 1998 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the array. // // Input, double *RVEC, a pointer to the first entry of the array. // // Output, double R8VEC_MIN, the value of the minimum element. This // is set to 0.0 if N <= 0. // { int i; double rmin; double *r8vec_pointer; if ( n <= 0 ) { return 0.0; } for ( i = 0; i < n; i++ ) { if ( i == 0 ) { rmin = *dvec; r8vec_pointer = dvec; } else { r8vec_pointer++; if ( *r8vec_pointer < rmin ) { rmin = *r8vec_pointer; } } } return rmin; } //****************************************************************************80 void r8vec_print ( int n, double a[], char *title ) //****************************************************************************80 // // Purpose: // // R8VEC_PRINT prints an R8VEC // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of components of the vector. // // Input, double A[N], the vector to be printed. // // Input, char *TITLE, a title. // { int i; cout << "\n"; cout << title << "\n"; cout << "\n"; for ( i = 0; i <= n-1; i++ ) { cout << setw(6) << i + 1 << " " << setw(14) << a[i] << "\n"; } return; } //****************************************************************************80 double *r8vec_random ( int n, double alo, double ahi, int &seed ) //****************************************************************************80 // // Purpose: // // R8VEC_RANDOM returns a scaled pseudorandom R8VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, double ALO, AHI, the range allowed for the entries. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double R8VEC_RANDOM[N], the vector of randomly chosen integers. // { double *a; int i; a = new double[n]; for ( i = 0; i < n; i++ ) { a[i] = r8_random ( alo, ahi, seed ); } return a; } //****************************************************************************80 double r8vec_sum ( int n, double a[] ) //****************************************************************************80 // // Purpose: // // R8VEC_SUM returns the sum of an R8VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, double A[N], the vector. // // Output, double R8VEC_SUM, the sum of the vector. // { int i; float sum; sum = 0.0; for ( i = 0; i < n; i++ ) { sum = sum + a[i]; } return sum; } //****************************************************************************80 double *r8vec_uniform_01 ( int n, int &seed ) //****************************************************************************80 // // Purpose: // // R8VEC_UNIFORM_01 returns a unit pseudorandom R8VEC // // Discussion: // // This routine implements the recursion // // seed = 16807 * seed mod ( 2^31 - 1 ) // unif = seed / ( 2^31 - 1 ) // // The integer arithmetic never requires more than 32 bits, // including a sign bit. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 August 2004 // // Author: // // John Burkardt // // Reference: // // Paul Bratley, Bennett Fox, Linus Schrage, // A Guide to Simulation, // Springer Verlag, pages 201-202, 1983. // // Bennett Fox, // Algorithm 647: // Implementation and Relative Efficiency of Quasirandom // Sequence Generators, // ACM Transactions on Mathematical Software, // Volume 12, Number 4, pages 362-376, 1986. // // Parameters: // // Input, int N, the number of entries in the vector. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double R8VEC_UNIFORM_01[N], the vector of pseudorandom values. // { int i; int k; double *r; r = new double[n]; for ( i = 0; i < n; i++ ) { k = seed / 127773; seed = 16807 * ( seed - k * 127773 ) - k * 2836; if ( seed < 0 ) { seed = seed + 2147483647; } r[i] = ( double ) ( seed ) * 4.656612875E-10; } return r; } //****************************************************************************80 void r8vec_unit_sum ( int n, double a[] ) //****************************************************************************80 // // Purpose: // // R8VEC_UNIT_SUM normalizes an R8VEC to have unit sum. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input/output, double A[N], the vector to be normalized. // On output, the entries of A should have unit sum. However, if // the input vector has zero sum, the routine halts. // { double a_sum; int i; a_sum = 0.0; for ( i = 0; i < n; i++ ) { a_sum = a_sum + a[i]; } if ( a_sum == 0.0 ) { cout << "\n"; cout << "R8VEC_UNIT_SUM - Fatal error!\n"; cout << " The vector entries sum to 0.\n"; exit ( 1 ); } for ( i = 0; i < n; i++ ) { a[i] = a[i] / a_sum; } return; } //****************************************************************************80 double r8vec_variance ( int n, double x[] ) //****************************************************************************80 // // Purpose: // // R8VEC_VARIANCE returns the variance of an R8VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 May 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, double X[N], the vector whose variance is desired. // // Output, double R8VEC_VARIANCE, the variance of the vector entries. // { int i; double mean; double variance; mean = r8vec_mean ( n, x ); variance = 0.0; for ( i = 0; i < n; i++ ) { variance = variance + ( x[i] - mean ) * ( x[i] - mean ); } if ( 1 < n ) { variance = variance / ( double ) ( n - 1 ); } else { variance = 0.0; } return variance; } //****************************************************************************80 double rayleigh_cdf ( double x, double a ) //****************************************************************************80 // // Purpose: // // RAYLEIGH_CDF evaluates the Rayleigh CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // 0.0 <= X. // // Input, double A, the parameter of the PDF. // 0.0 < A. // // Output, double RAYLEIGH_CDF, the value of the CDF. // { double cdf; if ( x < 0.0 ) { cdf = 0.0; } else { cdf = 1.0 - exp ( - x * x / ( 2.0 * a * a ) ); } return cdf; } //****************************************************************************80 double rayleigh_cdf_inv ( double cdf, double a ) //****************************************************************************80 // // Purpose: // // RAYLEIGH_CDF_INV inverts the Rayleigh CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, the parameter of the PDF. // 0.0 < A. // // Output, double RAYLEIGH_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "RAYLEIGH_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = sqrt ( - 2.0 * a * a * log ( 1.0 - cdf ) ); return x; } //****************************************************************************80 void rayleigh_cdf_values ( int &n_data, double &sigma, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // RAYLEIGH_CDF_VALUES returns some values of the Rayleigh CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = RayleighDistribution [ sigma ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 September 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &SIGMA, the shape parameter of the distribution. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 9 static double fx_vec[N_MAX] = { 0.8646647167633873E+00, 0.9996645373720975E+00, 0.9999999847700203E+00, 0.999999999999987E+00, 0.8646647167633873E+00, 0.3934693402873666E+00, 0.1992625970831920E+00, 0.1175030974154046E+00, 0.7688365361336422E-01 }; static double sigma_vec[N_MAX] = { 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01 }; static double x_vec[N_MAX] = { 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; sigma = 0.0; x = 0.0; fx = 0.0; } else { sigma = sigma_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool rayleigh_check ( double a ) //****************************************************************************80 // // Purpose: // // RAYLEIGH_CHECK checks the parameter of the Rayleigh PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 < A. // // Output, bool RAYLEIGH_CHECK, is true if the parameter is legal. // { if ( a <= 0.0 ) { cout << " \n"; cout << "RAYLEIGH_CHECK - Fatal error!\n"; cout << " A <= 0.\n"; return false; } return true; } //****************************************************************************80 double rayleigh_mean ( double a ) //****************************************************************************80 // // Purpose: // // RAYLEIGH_MEAN returns the mean of the Rayleigh PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 < A. // // Output, double RAYLEIGH_MEAN, the mean of the PDF. // { double mean; const double pi = 3.14159265358979323; mean = a * sqrt ( 0.5 * pi ); return mean; } //****************************************************************************80 double rayleigh_pdf ( double x, double a ) //****************************************************************************80 // // Purpose: // // RAYLEIGH_PDF evaluates the Rayleigh PDF. // // Discussion: // // PDF(A;X) = ( X / A^2 ) * EXP ( - X^2 / ( 2 * A^2 ) ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X // // Input, double A, the parameter of the PDF. // 0 < A. // // Output, double RAYLEIGH_PDF, the value of the PDF. // { double pdf; if ( x < 0.0 ) { pdf = 0.0; } else { pdf = ( x / ( a * a ) ) * exp ( - x * x / ( 2.0 * a * a ) ); } return pdf; } //****************************************************************************80 double rayleigh_sample ( double a, int &seed ) //****************************************************************************80 // // Purpose: // // RAYLEIGH_SAMPLE samples the Rayleigh PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 0.0 < A. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double RAYLEIGH_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = rayleigh_cdf_inv ( cdf, a ); return x; } //****************************************************************************80 double rayleigh_variance ( double a ) //****************************************************************************80 // // Purpose: // // RAYLEIGH_VARIANCE returns the variance of the Rayleigh PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameters of the PDF. // 0.0 < A. // // Output, double RAYLEIGH_VARIANCE, the variance of the PDF. // { const double pi = 3.14159265358979323; double variance; variance = 2.0 * a * a * ( 1.0 - 0.25 * pi ); return variance; } //****************************************************************************80 double reciprocal_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // RECIPROCAL_CDF evaluates the Reciprocal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < A <= B. // // Output, double RECIPROCAL_CDF, the value of the CDF. // { double cdf; if ( x <= 0.0 ) { cdf = 0.0; } else if ( 0.0 < x ) { cdf = log ( a / x ) / log ( a / b ); } return cdf; } //****************************************************************************80 double reciprocal_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // RECIPROCAL_CDF_INV inverts the Reciprocal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < A <= B. // // Output, double RECIPROCAL_CDF_INV, the corresponding argument of the CDF. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "RECIPROCAL_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = 0.0; } else if ( 0.0 < cdf ) { x = pow ( b, cdf ) / pow ( a, ( cdf - 1.0 ) ); } return x; } //****************************************************************************80 bool reciprocal_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // RECIPROCAL_CHECK checks the parameters of the Reciprocal CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A <= B. // // Output, bool RECIPROCAL_CHECK, is true if the parameters are legal. // { if ( a <= 0.0 ) { cout << " \n"; cout << "RECIPROCAL_CHECK - Fatal error!\n"; cout << " A <= 0.0\n"; return false; } if ( b < a ) { cout << " \n"; cout << "RECIPROCAL_CHECK - Fatal error!\n"; cout << " B < A\n"; return false; } return true; } //****************************************************************************80 double reciprocal_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // RECIPROCAL_MEAN returns the mean of the Reciprocal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A <= B. // // Output, double RECIPROCAL_MEAN, the mean of the PDF. // { double mean; mean = ( a - b ) / log ( a / b ); return mean; } //****************************************************************************80 double reciprocal_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // RECIPROCAL_PDF evaluates the Reciprocal PDF. // // Discussion: // // PDF(A,B;X) = 1.0 / ( X * LOG ( B / A ) ) // for 0.0 <= X // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < A <= B. // // Output, double RECIPROCAL_PDF, the value of the PDF. // { double pdf; if ( x <= 0.0 ) { pdf = 0.0; } else if ( 0.0 < x ) { pdf = 1.0 / ( x * log ( b / a ) ); } return pdf; } //****************************************************************************80 double reciprocal_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // RECIPROCAL_SAMPLE samples the Reciprocal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A <= B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double RECIPROCAL_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = pow ( b, cdf ) / pow ( a, ( cdf - 1.0 ) ); return x; } //****************************************************************************80 double reciprocal_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // RECIPROCAL_VARIANCE returns the variance of the Reciprocal PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A <= B. // // Output, double RECIPROCAL_VARIANCE, the variance of the PDF. // { double d; double variance; d = log ( a / b ); variance = ( a - b )* ( a * ( d - 2.0 ) + b * ( d + 2.0 ) ) / ( 2.0 * d * d ); return variance; } //****************************************************************************80 int ribesl ( double x, double alpha, int nb, int ize, double b[] ) //****************************************************************************80 // // Purpose: // // RIBESL calculates I Bessel function with non-integer orders. // // Discussion: // // This routine calculates Bessel functions I SUB(N+ALPHA) (X) // for non-negative argument X, and non-negative order N+ALPHA, // with or without exponential scaling. // // This program is based on a program written by David // Sookne that computes values of the Bessel functions J or // I of real argument and integer order. Modifications include // the restriction of the computation to the I Bessel function // of non-negative real argument, the extension of the computation // to arbitrary positive order, the inclusion of optional // exponential scaling, and the elimination of most underflow. // // In case of an error, NCALC will not equal NB, and not all I's are // calculated to the desired accuracy. // // If NCALC < 0: An argument is out of range. For example, // NB <= 0, IZE is not 1 or 2, or IZE = 1 and EXPARG <= ABS(X) // In this case, the B-vector is not calculated, and NCALC is // set to MIN(NB,0)-1 so that NCALC /= NB. // // If 0 < NCALC < NB, then not all requested function values could // be calculated accurately. This usually occurs because NB is // much larger than ABS(X). In this case, B(N) is calculated // to the desired accuracy for N <= NCALC, but precision // is lost for NCALC < N <= NB. If B(N) does not vanish // for NCALC < N (because it is too small to be represented), // and B(N)/B(NCALC) = 10**(-K), then only the first NSIG-K // significant figures of B(N) can be trusted. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 March 2007 // // Author: // // Original FORTRAN77 version by William Cody. // C++ version by John Burkardt. // // Reference: // // Frank Olver, David Sookne, // A Note on Backward Recurrence Algorithms, // Mathematics of Computation, // Volume 26, 1972, pages 941-947. // // David Sookne, // Bessel Functions of Real Argument and Integer Order, // NBS Journal of Research B, // Volume 77B, 1973, pages 125-132. // // William Cody, // Algorithm 597: // Sequence of Modified Bessel Functions of the First Kind, // ACM Transactions of Mathematical Software, // Volume 9, Number 2, June 1983, pages 242-245. // // Parameters: // // Input, double X, the argument for which the functions // are to be calculated. // // Input, double ALPHA,the fractional part of the order // for which the functions are to be calculated. // 0 <= ALPHA < 1.0. // // Input, int NB, the number of functions to be calculated. // The first function calculated is of order ALPHA, and the // last is of order (NB - 1 + ALPHA). 1 <= NB. // // Input, int IZE, scaling option. // 1, unscaled I's are to calculated, // 2, exponentially scaled I's are to be calculated. // // Output, double B[NB], the values of the functions // I(ALPHA,X) through I(NB-1+ALPHA,X), with scaling if requested. // // Output, int RIBESL, the value of NCALC, the error indicator. // If NCALC = NB, then all the requested values were calculated // to the desired accuracy. // // Local Parameeters: // // BETA, the radix for the floating-point system. // // MINEXP, smallest representable power of BETA. // // MAXEXP, smallest power of BETA that overflows // // IT, number of bits in the mantissa of a working precision variable. // // NSIG, decimal significance desired. Should be set to // INT(LOG10(2)*IT+1). Setting NSIG lower will result // in decreased accuracy while setting NSIG higher will // increase CPU time without increasing accuracy. The // truncation error is limited to a relative error of // T=.5*10^(-NSIG). // // ENTEN, 10.0^K, where K is the largest integer such that // ENTEN is machine-representable in working precision // // ENSIG, 10.0^NSIG // // RTNSIG, 10.0^(-K) for the smallest integer K such that // NSIG/4 <= K. // // ENMTEN, smallest ABS(X) such that X/4 does not underflow // // XLARGE, upper limit on the magnitude of X when IZE=2. Bear // in mind that if ABS(X)=N, then at least N iterations // of the backward recursion will be executed. The value // of 10.0^4 is used on every machine. // // EXPARG, largest working precision argument that the library // EXP routine can handle and upper limit on the // magnitude of X when IZE=1; approximately log(BETA^MAXEXP). // // Approximate values for some important machines are: // // beta minexp maxexp it // // CRAY-1 (S.P.) 2 -8193 8191 48 // Cyber 180/855 // under NOS (S.P.) 2 -975 1070 48 // IEEE (IBM/XT, // SUN, etc.) (S.P.) 2 -126 128 24 // IEEE (IBM/XT, // SUN, etc.) (D.P.) 2 -1022 1024 53 // IBM 3033 (D.P.) 16 -65 63 14 // VAX (S.P.) 2 -128 127 24 // VAX D-Format (D.P.) 2 -128 127 56 // VAX G-Format (D.P.) 2 -1024 1023 53 // // // NSIG ENTEN ENSIG RTNSIG // // CRAY-1 (S.P.) 15 1.0E+2465 1.0E+15 1.0E-4 // Cyber 180/855 // under NOS (S.P.) 15 1.0E+322 1.0E+15 1.0E-4 // IEEE (IBM/XT, // SUN, etc.) (S.P.) 8 1.0E+38 1.0E+8 1.0E-2 // IEEE (IBM/XT, // SUN, etc.) (D.P.) 16 1.0D+308 1.0D+16 1.0D-4 // IBM 3033 (D.P.) 5 1.0D+75 1.0D+5 1.0D-2 // VAX (S.P.) 8 1.0E+38 1.0E+8 1.0E-2 // VAX D-Format (D.P.) 17 1.0D+38 1.0D+17 1.0D-5 // VAX G-Format (D.P.) 16 1.0D+307 1.0D+16 1.0D-4 // // // ENMTEN XLARGE EXPARG // // CRAY-1 (S.P.) 1.84E-2466 1.0E+4 5677 // Cyber 180/855 // under NOS (S.P.) 1.25E-293 1.0E+4 741 // IEEE (IBM/XT, // SUN, etc.) (S.P.) 4.70E-38 1.0E+4 88 // IEEE (IBM/XT, // SUN, etc.) (D.P.) 8.90D-308 1.0D+4 709 // IBM 3033 (D.P.) 2.16D-78 1.0D+4 174 // VAX (S.P.) 1.17E-38 1.0E+4 88 // VAX D-Format (D.P.) 1.17D-38 1.0D+4 88 // VAX G-Format (D.P.) 2.22D-308 1.0D+4 709 // { double constant = 1.585; double em; double empal; double emp2al; double en; double enmten = 8.9E-308; double ensig = 1.0E+16; double enten = 1.0E+308; double exparg = 709.0; bool flag; double half = 0.5; double halfx; int i; int k; int l; int magx; int n; int nbmx; int ncalc; int nend; int nsig = 16; int nstart; double one = 1.0; double p; double plast; double pold; double psave; double psavel; double rtnsig = 1.0E-04; double tempa; double tempb; double tempc; double test; double total; double tover; double two = 2.0; double xlarge = 1.0E+04; double zero = 0.0; // // Check for X, NB, OR IZE out of range. // if ( nb <= 0 ) { ncalc = i4_min ( nb, 0 ) - 1; return ncalc; } if ( x < 0.0 ) { ncalc = i4_min ( nb, 0 ) - 1; return ncalc; } if ( alpha < 0.0 ) { ncalc = i4_min ( nb, 0 ) - 1; return ncalc; } if ( 1.0 <= alpha ) { ncalc = i4_min ( nb, 0 ) - 1; return ncalc; } if ( ize == 1 && exparg < x ) { ncalc = i4_min ( nb, 0 ) - 1; return ncalc; } if ( ize == 2 && xlarge < x ) { ncalc = i4_min ( nb, 0 ) - 1; return ncalc; } // // Use 2-term ascending series for small X. // ncalc = nb; magx = ( int ) ( x ); // // Initialize the forward sweep, the P-sequence of Olver. // if ( rtnsig <= x ) { nbmx = nb - magx; n = magx + 1; en = ( double ) ( n + n ) + ( alpha + alpha ); plast = one; p = en / x; // // Calculate general significance test. // test = ensig + ensig; if ( 5 * nsig < 2 * magx ) { test = sqrt ( test * p ); } else { test = test / pow ( constant, magx ); } // // Calculate P-sequence until N = NB-1. Check for possible overflow. // flag = false; if ( 3 <= nbmx ) { tover = enten / ensig; nstart = magx + 2; nend = nb - 1; for ( k = nstart; k <= nend; k++ ) { n = k; en = en + two; pold = plast; plast = p; p = en * plast / x + pold; // // To avoid overflow, divide P-sequence by TOVER. Calculate // P-sequence until 1 < ABS(P). // if ( tover < p ) { tover = enten; p = p / tover; plast = plast / tover; psave = p; psavel = plast; nstart = n + 1; for ( ; ; ) { n = n + 1; en = en + two; pold = plast; plast = p; p = en * plast / x + pold; if ( 1.0 < p ) { break; } } tempb = en / x; // // Calculate backward test, and find NCALC, the highest N // such that the test is passed. // test = pold * plast / ensig; test = test * ( half - half / ( tempb * tempb ) ); p = plast * tover; n = n - 1; en = en - two; nend = i4_min ( nb, n ); ncalc = nend + 1; for ( l = nstart; l <= nend; l++ ) { pold = psavel; psavel = psave; psave = en * psavel / x + pold; if ( test < psave * psavel ) { ncalc = l; break; } } ncalc = ncalc - 1; flag = true; break; } } if ( !flag ) { n = nend; en = ( double ) ( n + n ) + ( alpha + alpha ); // // Calculate special significance test for 2 < NBMX. // test = r8_max ( test, sqrt ( plast * ensig ) * sqrt ( p + p ) ); } } // // Calculate P-sequence until significance test passed. // if ( !flag ) { for ( ; ; ) { n = n + 1; en = en + two; pold = plast; plast = p; p = en * plast / x + pold; if ( test <= p ) { break; } } } // // Initialize the backward recursion and the normalization sum. // n = n + 1; en = en + two; tempb = zero; tempa = one / p; em = ( double ) ( n ) - one; empal = em + alpha; emp2al = ( em - one ) + ( alpha + alpha ); total = tempa * empal * emp2al / em; nend = n - nb; // // N < NB, so store B(N) and set higher orders to zero. // if ( nend < 0 ) { b[n-1] = tempa; nend = -nend; for ( l = 1; l <= nend; l++ ) { b[n+l-1] = zero; } nend = n - 2; // // Calculate via difference equation and store B(N), until N = 2. // if ( 0 < nend ) { for ( l = 1; l <= nend; l++ ) { n = n - 1; en = en - two; b[n-1] = ( en * b[n] ) / x + b[n+1]; em = em - one; emp2al = emp2al - one; if ( n == 2 ) { emp2al = one; } empal = empal - one; total = ( total + b[n-1] * empal ) * emp2al / em; } } // // Calculate B(1). // b[0] = two * empal * b[1] / x + b[2]; total = ( total + total ) + b[0]; } // // Recur backward via difference equation, calculating (but // not storing) B(N), until N = NB. // else { if ( 0 < nend ) { for ( l = 1; l <= nend; l++ ) { n = n - 1; en = en - two; tempc = tempb; tempb = tempa; tempa = ( en * tempb ) / x + tempc; em = em - one; emp2al = emp2al - one; if ( n == 1 ) { break; } if ( n == 2 ) { emp2al = one; } empal = empal - one; total = ( total + tempa * empal ) * emp2al / em; } } // // Store B(NB). // b[n-1] = tempa; if ( nb <= 1 ) { total = ( total + total ) + tempa; } // // Calculate and Store B(NB-1). // else { n = n - 1; en = en - two; b[n-1] = ( en * tempa ) / x + tempb; if ( 1 < n ) { em = em - one; emp2al = emp2al - one; if ( n == 2 ) { emp2al = one; } empal = empal - one; total = ( total + b[n-1] * empal ) * emp2al / em; nend = n - 2; // // Calculate via difference equation and store B(N), until N = 2. // if ( 0 < nend ) { for ( l = 1; l <= nend; l++ ) { n = n - 1; en = en - two; b[n-1] = ( en * b[n] ) / x + b[n+1]; em = em - one; emp2al = emp2al - one; if ( n == 2 ) { emp2al = one; } empal = empal - one; total = ( total + b[n-1] * empal ) * emp2al / em; } } // // Calculate B(1). // b[0] = two * empal * b[1] / x + b[2]; } total = ( total + total ) + b[0]; } } // // Normalize. Divide all B(N) by TOTAL. // if ( alpha != zero ) { total = total * r8_gamma ( one + alpha ) * pow ( x * half, -alpha ); } if ( ize == 1 ) { total = total * exp ( -x ); } tempa = enmten; if ( 1.0 < total ) { tempa = tempa * total; } for ( n = 1; n <= nb; n++ ) { if ( b[n-1] < tempa ) { b[n-1] = zero; } b[n-1] = b[n-1] / total; } return ncalc; } // // Two-term ascending series for small X. // else { tempa = one; empal = one + alpha; halfx = zero; if ( enmten < x ) { halfx = half * x; } if ( alpha != zero ) { tempa = pow ( halfx, alpha ) / r8_gamma ( empal ); } if ( ize == 2 ) { tempa = tempa * exp ( - x ); } tempb = zero; if ( one < x + one ) { tempb = halfx * halfx; } b[0] = tempa + tempa * tempb / empal; if ( x != zero && b[0] == zero ) { ncalc = 0; } if ( 1 < nb ) { if ( x == zero ) { for ( i = 1; i < nb; i++ ) { b[i] = zero; } } // // Calculate higher-order functions. // else { tempc = halfx; tover = ( enmten + enmten ) / x; if ( tempb != zero ) { tover = enmten / tempb; } for ( n = 2; n <= nb; n++ ) { tempa = tempa / empal; empal = empal + one; tempa = tempa * tempc; if ( tempa <= tover * empal ) { tempa = zero; } b[n-1] = tempa + tempa * tempb / empal; if ( b[n-1] == zero && n < ncalc ) { ncalc = n - 1; } } } } } return ncalc; } //****************************************************************************80 double runs_mean ( int m, int n ) //****************************************************************************80 // // Purpose: // // RUNS_MEAN returns the mean of the Runs PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 23 January 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the parameters of the PDF. // // Output, double RUNS_MEAN, the mean of the PDF. // { double mean; mean = ( double ) ( m + 2 * m * n + n ) / ( double ) ( m + n ); return mean; } //****************************************************************************80 double runs_pdf ( int m, int n, int r ) //****************************************************************************80 // // Purpose: // // RUNS_PDF evaluates the Runs PDF. // // Discussion: // // Suppose we have M symbols of one type and N of another, and we consider // the various possible permutations of these symbols. // // Let "R" be the number of runs in a given permutation. By a "run", we // mean a maximal sequence of identical symbols. Thus, for instance, // the permutation // // ABBBAAAAAAAA // // has three runs. // // The probability that a permutation of M+N symbols, with M of one kind // and N of another, will have exactly R runs is: // // PDF(M,N)(R) = 2 * C(M-1,R/2-1) * C(N-1,R/2-1) // / C(M+N,N) for R even; // // = ( C(M-1,(R-1)/2) * C(N-1,(R-3)/2 ) // + C(M-1,(R-3)/2) * C(N-1,(R-1)/2 ) // ) / C(M+N,N) for R odd. // // Note that the maximum number of runs for a given M and N is: // // M + N, if M = N // 2 * min ( M, N ) + 1 otherwise // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 23 January 2007 // // Author: // // John Burkardt // // Reference: // // Kalimutha Krishnamoorthy, // Handbook of Statistical Distributions with Applications, // Chapman and Hall, 2006, // ISBN: 1-58488-635-8, // LC: QA273.6.K75. // // Parameters: // // Input, int M, N, the parameters of the PDF. // // Input, int R, the number of runs. // // Output, double PDF, the value of the PDF. // { double pdf; if ( m < 0 ) { cout << "\n"; cout << "RUN_PDF - Fatal error!\n"; cout << " M must be at least 0.\n"; cout << " The input value of M = " << m << "\n"; exit ( 1 ); } if ( n < 0 ) { cout << "\n"; cout << "RUN_PDF - Fatal error!\n"; cout << " N must be at least 0.\n"; cout << " The input value of N = " << n << "\n"; exit ( 1 ); } if ( n + m <= 0 ) { cout << "\n"; cout << "RUN_PDF - Fatal error!\n"; cout << " M+N must be at least 1.\n"; cout << " The input value of M+N = " << m + n << "\n"; exit ( 1 ); } // // If all the symbols are of one type, there is always 1 run. // if ( m == 0 || n == 0 ) { if ( r == 1 ) { pdf = 1.0; } else { pdf = 0.0; } return pdf; } // // Take care of extreme values of R. // if ( r < 2 || m + n < r ) { pdf = 0.0; return pdf; } // // The normal cases. // if ( ( r % 2 ) == 0 ) { pdf = ( double ) ( 2 * combinatorial ( m - 1, ( r / 2 ) - 1 ) * combinatorial ( n - 1, ( r / 2 ) - 1 ) ) / ( double ) ( combinatorial ( m + n, n ) ); } else { pdf = ( double ) ( combinatorial ( m - 1, ( r - 1 ) / 2 ) * combinatorial ( n - 1, ( r - 3 ) / 2 ) + combinatorial ( m - 1, ( r - 3 ) / 2 ) * combinatorial ( n - 1, ( r - 1 ) / 2 ) ) / ( double ) ( combinatorial ( m + n, n ) ); } return pdf; } //****************************************************************************80 int runs_sample ( int m, int n, int &seed ) //****************************************************************************80 // // Purpose: // // RUNS_SAMPLE samples the Runs PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 27 January 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the parameters of the PDF. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int RUNS_SAMPLE, the number of runs. // { int *a; int r; a = runs_simulate ( m, n, seed ); r = i4vec_run_count ( m+n, a ); delete [] a; return r; } //****************************************************************************80 int *runs_simulate ( int m, int n, int &seed ) //****************************************************************************80 // // Purpose: // // RUNS_SIMULATE simulates a case governed by the Runs PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 27 January 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the parameters of the PDF. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int RUNS_SIMULATE[M+N], a sequence of M 0's and N 1's chosen // uniformly at random. // { int *a; int i; int j; int k; a = new int[m+n]; for ( i = 0; i < m; i++ ) { a[i] = 0; } for ( i = m; i < m + n; i++ ) { a[i] = 1; } for ( i = 1; i <= m + n - 1; i++ ) { j = i4_uniform_ab ( i, m + n, seed ); k = a[i-1]; a[i-1] = a[j-1]; a[j-1] = k; } return a; } //****************************************************************************80 double runs_variance ( int m, int n ) //****************************************************************************80 // // Purpose: // // RUNS_VARIANCE returns the variance of the Runs PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 23 January 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the parameters of the PDF. // // Output, double RUNS_VARIANCE, the variance of the PDF. // { double variance; variance = ( double ) ( 2 * m * n * ( 2 * m * n - m - n ) ) / ( double ) ( ( m + n ) * ( m + n ) * ( m + n - 1 ) ); return variance; } //****************************************************************************80 int s_len_trim ( char *s ) //****************************************************************************80 // // Purpose: // // S_LEN_TRIM returns the length of a string to the last nonblank. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 April 2003 // // Author: // // John Burkardt // // Parameters: // // Input, char *S, a pointer to a string. // // Output, int S_LEN_TRIM, the length of the string to the last nonblank. // If S_LEN_TRIM is 0, then the string is entirely blank. // { int n; char* t; n = strlen ( s ); t = s + strlen ( s ) - 1; while ( 0 < n ) { if ( *t != ' ' ) { return n; } t--; n--; } return n; } //****************************************************************************80 double sech ( double x ) //****************************************************************************80 // // Purpose: // // SECH returns the hyperbolic secant. // // Discussion: // // SECH ( X ) = 1.0 / COSH ( X ) = 2.0 / ( EXP ( X ) + EXP ( - X ) ) // // SECH is not a built-in function in FORTRAN, and occasionally it // is handier, or more concise, to be able to refer to it directly // rather than through its definition in terms of the sine function. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument. // // Output, double SECH, the hyperbolic secant of X. // { double value; value = 1.0 / cosh ( x ); return value; } //****************************************************************************80 double sech_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // SECH_CDF evaluates the Hyperbolic Secant CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameter of the PDF. // 0.0 < B. // // Output, double SECH_CDF, the value of the CDF. // { double cdf; const double pi = 3.14159265358979323; double y; y = ( x - a ) / b; cdf = 2.0 * atan ( exp ( y ) ) / pi; return cdf; } //****************************************************************************80 double sech_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // SECH_CDF_INV inverts the Hyperbolic Secant CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double SECH_CDF_INV, the corresponding argument of the CDF. // { const double pi = 3.14159265358979323; double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "SECH_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = - r8_huge ( ); } else if ( cdf < 1.0 ) { x = a + b * log ( tan ( 0.5 * pi * cdf ) ); } else if ( 1.0 == cdf ) { x = r8_huge ( ); } return x; } //****************************************************************************80 bool sech_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // SECH_CHECK checks the parameters of the Hyperbolic Secant CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameter of the PDF. // 0.0 < B. // // Output, bool SECH_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << " \n"; cout << "SECH_CHECK - Fatal error!\n"; cout << " B <= 0.0\n"; return false; } return true; } //****************************************************************************80 double sech_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // SECH_MEAN returns the mean of the Hyperbolic Secant PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double SECH_MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double sech_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // SECH_PDF evaluates the Hypebolic Secant PDF. // // Discussion: // // PDF(A,B;X) = sech ( ( X - A ) / B ) / ( PI * B ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double SECH_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; double y; y = ( x - a ) / b; pdf = sech ( y ) / ( pi * b ); return pdf; } //****************************************************************************80 double sech_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // SECH_SAMPLE samples the Hyperbolic Secant PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double SECH_SAMPLE, a sample of the PDF. // { double cdf; const double pi = 3.14159265358979323; double x; cdf = r8_uniform_01 ( seed ); x = a + b * log ( tan ( 0.5 *pi * cdf ) ); return x; } //****************************************************************************80 double sech_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // SECH_VARIANCE returns the variance of the Hyperbolic Secant PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double SECH_VARIANCE, the variance of the PDF. // { const double pi = 3.14159265358979323; double variance; variance = 0.25 * pi * pi * b * b; return variance; } //****************************************************************************80 double semicircular_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // SEMICIRCULAR_CDF evaluates the Semicircular CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameter of the PDF. // 0.0 < B. // // Output, double SEMICIRCULAR_CDF, the value of the CDF. // { double cdf; const double pi = 3.14159265358979323; double y; if ( x <= a - b ) { cdf = 0.0; } else if ( x <= a + b ) { y = ( x - a ) / b; cdf = 0.5 + ( y * sqrt ( 1.0 - y * y ) + asin ( y ) ) / pi; } else if ( a + b < x ) { cdf = 1.0; } return cdf; } //****************************************************************************80 double semicircular_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // SEMICIRCULAR_CDF_INV inverts the Semicircular CDF. // // Discussion: // // A simple bisection method is used on the interval [ A - B, A + B ]. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double SEMICIRCULAR_CDF_INV, the corresponding argument // of the CDF. // { double cdf1; double cdf2; double cdf3; int it; int it_max = 100; double tol = 0.0001; double x; double x1; double x2; double x3; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "SEMICIRCULAR_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = a - b; return x; } else if ( 1.0 == cdf ) { x = a + b; return x; } x1 = a - b; cdf1 = 0.0; x2 = a + b; cdf2 = 1.0; // // Now use bisection. // it = 0; for ( ; ; ) { it = it + 1; x3 = 0.5 * ( x1 + x2 ); cdf3 = semicircular_cdf ( x3, a, b ); if ( r8_abs ( cdf3 - cdf ) < tol ) { x = x3; break; } if ( it_max < it ) { cout << " \n"; cout << "SEMICIRCULAR_CDF_INV - Fatal error!\n"; cout << " Iteration limit exceeded.\n"; exit ( 1 ); } if ( ( cdf3 <= cdf && cdf1 <= cdf ) || ( cdf <= cdf3 && cdf <= cdf1 ) ) { x1 = x3; cdf1 = cdf3; } else { x2 = x3; cdf2 = cdf3; } } return x; } //****************************************************************************80 bool semicircular_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // SEMICIRCULAR_CHECK checks the parameters of the Semicircular CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameter of the PDF. // 0.0 < B. // // Output, bool SEMICIRCULAR_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << " \n"; cout << "SEMICIRCULAR_CHECK - Fatal error!\n"; cout << " B <= 0.0\n"; return false; } return true; } //****************************************************************************80 double semicircular_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // SEMICIRCULAR_MEAN returns the mean of the Semicircular PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double SEMICIRCULAR_MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double semicircular_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // SEMICIRCULAR_PDF evaluates the Semicircular PDF. // // Discussion: // // PDF(A,B;X) = ( 2 / ( B * PI ) ) * SQRT ( 1 - ( ( X - A ) / B )^2 ) // for A - B <= X <= A + B // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double SEMICIRCULAR_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; double y; if ( x < a - b ) { pdf = 0.0; } else if ( x <= a + b ) { y = ( x - a ) / b; pdf = 2.0 / ( b * pi ) * sqrt ( 1.0 - y * y ); } else if ( a + b < x ) { pdf = 0.0; } return pdf; } //****************************************************************************80 double semicircular_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // SEMICIRCULAR_SAMPLE samples the Semicircular PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double SEMICIRCULAR_SAMPLE, a sample of the PDF. // { double angle; const double pi = 3.14159265358979323; double radius; double x; radius = r8_uniform_01 ( seed ); radius = b * sqrt ( radius ); angle = pi * r8_uniform_01 ( seed ); x = a + radius * cos ( angle ); return x; } //****************************************************************************80 double semicircular_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // SEMICIRCULAR_VARIANCE returns the variance of the Semicircular PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < B. // // Output, double SEMICIRCULAR_VARIANCE, the variance of the PDF. // { double variance; variance = b * b / 4.0; return variance; } //****************************************************************************80 double sin_power_int ( double a, double b, int n ) //****************************************************************************80 // // Purpose: // // SIN_POWER_INT evaluates the sine power integral. // // Discussion: // // The function is defined by // // SIN_POWER_INT(A,B,N) = Integral ( A <= T <= B ) ( sin ( t ))^n dt // // The algorithm uses the following fact: // // Integral sin^n ( t ) = (1/n) * ( // sin^(n-1)(t) * cos(t) + ( n-1 ) * Integral sin^(n-2) ( t ) dt ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 September 2004 // // Author: // // John Burkardt // // Parameters // // Input, double A, B, the limits of integration. // // Input, int N, the power of the sine function. // // Output, double SIN_POWER_INT, the value of the integral. // { double ca; double cb; int m; int mlo; double sa; double sb; double value; // if ( n < 0 ) { cout << "\n"; cout << "SIN_POWER_INT - Fatal error!\n"; cout << " Power N < 0.\n"; value = 0.0; exit ( 1 ); } sa = sin ( a ); sb = sin ( b ); ca = cos ( a ); cb = cos ( b ); if ( ( n % 2 ) == 0 ) { value = b - a; mlo = 2; } else { value = ca - cb; mlo = 3; } for ( m = mlo; m <= n; m = m + 2 ) { value = ( ( double ) ( m - 1 ) * value + pow ( sa, (m-1) ) * ca - pow ( sb, (m-1) ) * cb ) / ( double ) ( m ); } return value; } //****************************************************************************80 double sphere_unit_area_nd ( int dim_num ) //****************************************************************************80 // // Purpose: // // SPHERE_UNIT_AREA_ND computes the surface area of a unit sphere in ND. // // Discussion: // // The unit sphere in ND satisfies the equation: // // Sum ( 1 <= I <= DIM_NUM ) X(I) * X(I) = 1 // // DIM_NUM Area // // 2 2 * PI // 3 4 * PI // 4 ( 2 / 1) * PI^2 // 5 ( 8 / 3) * PI^2 // 6 ( 1 / 1) * PI^3 // 7 (16 / 15) * PI^3 // 8 ( 1 / 3) * PI^4 // 9 (32 / 105) * PI^4 // 10 ( 1 / 12) * PI^5 // // For the unit sphere, Area(DIM_NUM) = DIM_NUM * Volume(DIM_NUM) // // Sphere_Unit_Area ( DIM_NUM ) = 2 * PI^(DIM_NUM/2) / Gamma ( DIM_NUM / 2 ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 September 2003 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the dimension of the space. // // Output, double SPHERE_UNIT_AREA_ND, the area of the sphere. // { double area; int i; int m; double pi = 3.141592653589793; if ( ( dim_num % 2 ) == 0 ) { m = dim_num / 2; area = 2.0 * pow ( pi, m ); for ( i = 1; i <= m-1; i++ ) { area = area / ( ( double ) i ); } } else { m = ( dim_num - 1 ) / 2; area = pow ( 2.0, dim_num ) * pow ( pi, m ); for ( i = m+1; i <= 2*m; i++ ) { area = area / ( ( double ) i ); } } return area; } //****************************************************************************80 int stirling2_value ( int n, int m ) //****************************************************************************80 // // Purpose: // // STIRLING2_VALUE computes a Stirling number of the second kind. // // Discussion: // // S2(N,M) represents the number of distinct partitions of N elements // into M nonempty sets. For a fixed N, the sum of the Stirling // numbers S2(N,M) is represented by B(N), called "Bell's number", // and represents the number of distinct partitions of N elements. // // For example, with 4 objects, there are: // // 1 partition into 1 set: // // (A,B,C,D) // // 7 partitions into 2 sets: // // (A,B,C) (D) // (A,B,D) (C) // (A,C,D) (B) // (A) (B,C,D) // (A,B) (C,D) // (A,C) (B,D) // (A,D) (B,C) // // 6 partitions into 3 sets: // // (A,B) (C) (D) // (A) (B,C) (D) // (A) (B) (C,D) // (A,C) (B) (D) // (A,D) (B) (C) // (A) (B,D) (C) // // 1 partition into 4 sets: // // (A) (B) (C) (D) // // So S2(4,1) = 1, S2(4,2) = 7, S2(4,3) = 6, S2(4,4) = 1, and B(4) = 15. // // // First terms: // // N/M: 1 2 3 4 5 6 7 8 // // 1 1 0 0 0 0 0 0 0 // 2 1 1 0 0 0 0 0 0 // 3 1 3 1 0 0 0 0 0 // 4 1 7 6 1 0 0 0 0 // 5 1 15 25 10 1 0 0 0 // 6 1 31 90 65 15 1 0 0 // 7 1 63 301 350 140 21 1 0 // 8 1 127 966 1701 1050 266 28 1 // // Recursion: // // S2(N,1) = 1 for all N. // S2(I,I) = 1 for all I. // S2(I,J) = 0 if I < J. // // S2(N,M) = M * S2(N-1,M) + S2(N-1,M-1) // // Properties: // // sum ( 1 <= K <= M ) S2(I,K) * S1(K,J) = Delta(I,J) // // X^N = sum ( 0 <= K <= N ) S2(N,K) X_K // where X_K is the falling factorial function. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of rows of the table. // // Input, int M, the number of columns of the table. // // Output, int STIRLING2_VALUE, the value of S2(N,M). // { int i; int j; int *s2; int value; s2 = new int[n*m]; if ( n <= 0 ) { value = 0; return value; } if ( m <= 0 ) { value = 0; return value; } s2[0+0*n] = 1; for ( j = 2; j <= m; j++ ) { s2[0+(j-1)*n] = 0; } for ( i = 2; i <= n; i++ ) { s2[i-1+0*n] = 1; for ( j = 2; j <= m; j++ ) { s2[i-1+(j-1)*n] = j * s2[i-2+(j-1)*n] + s2[i-2+(j-2)*n]; } } value = s2[n-1+(m-1)*n]; delete [] s2; return value; } //****************************************************************************80 double student_cdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // STUDENT_CDF evaluates the central Student T CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 November 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, shape parameters of the PDF, // used to transform the argument X to a shifted and scaled // value Y = ( X - A ) / B. It is required that B be nonzero. // For the standard distribution, A = 0 and B = 1. // // Input, double C, is usually called the number of // degrees of freedom of the distribution. C is typically an // integer, but that is not essential. It is required that // C be strictly positive. // // Output, double STUDENT_CDF, the value of the CDF. // { double a2; double b2; double c2; double cdf; double y; y = ( x - a ) / b; a2 = 0.5 * c; b2 = 0.5; c2 = c / ( c + y * y ); if ( y <= 0.0 ) { cdf = 0.5 * beta_inc ( a2, b2, c2 ); } else { cdf = 1.0 - 0.5 * beta_inc ( a2, b2, c2 ); } return cdf; } //****************************************************************************80 void student_cdf_values ( int &n_data, double &c, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // STUDENT_CDF_VALUES returns some values of the Student CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = StudentTDistribution [ c ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 November 2005 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &C, is usually called the number of // degrees of freedom of the distribution. C is typically an // integer, but that is not essential. It is required that // C be strictly positive. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 13 static double c_vec[N_MAX] = { 1.0, 2.0, 3.0, 4.0, 5.0, 2.0, 5.0, 2.0, 5.0, 2.0, 3.0, 4.0, 5.0 }; static double fx_vec[N_MAX] = { 0.6000231200328521, 0.6001080279134390, 0.6001150934648930, 0.6000995134721354, 0.5999341989834830, 0.7498859393137811, 0.7500879487671045, 0.9500004222186464, 0.9499969138365968, 0.9900012348724744, 0.9900017619355059, 0.9900004567580596, 0.9900007637471291 }; static double x_vec[N_MAX] = { 0.325, 0.289, 0.277, 0.271, 0.267, 0.816, 0.727, 2.920, 2.015, 6.965, 4.541, 3.747, 3.365 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; c = 0.0; x = 0.0; fx = 0.0; } else { c = c_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool student_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // STUDENT_CHECK checks the parameter of the central Student T CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 November 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, shape parameters of the PDF, // used to transform the argument X to a shifted and scaled // value Y = ( X - A ) / B. It is required that B be nonzero. // For the standard distribution, A = 0 and B = 1. // // Input, double C, is usually called the number of // degrees of freedom of the distribution. C is typically an // integer, but that is not essential. It is required that // C be strictly positive. // { if ( b == 0.0 ) { cout << " \n"; cout << "STUDENT_CHECK - Fatal error!\n"; cout << " B must be nonzero.\n"; return false; } if ( c <= 0.0 ) { cout << " \n"; cout << "STUDENT_CHECK - Fatal error!\n"; cout << " C must be greater than 0.\n"; return false; } return true; } //****************************************************************************80 double student_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // STUDENT_MEAN returns the mean of the central Student T PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 November 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, shape parameters of the PDF, // used to transform the argument X to a shifted and scaled // value Y = ( X - A ) / B. It is required that B be nonzero. // For the standard distribution, A = 0 and B = 1. // // Input, double C, is usually called the number of // degrees of freedom of the distribution. C is typically an // integer, but that is not essential. It is required that // C be strictly positive. // // Output, double STUDENT_MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double student_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // STUDENT_PDF evaluates the central Student T PDF. // // Discussion: // // PDF(A,B,C;X) = Gamma ( (C+1)/2 ) / // ( Gamma ( C / 2 ) * Sqrt ( PI * C ) // * ( 1 + ((X-A)/B)^2/C )^(C + 1/2 ) ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 November 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, shape parameters of the PDF, // used to transform the argument X to a shifted and scaled // value Y = ( X - A ) / B. It is required that B be nonzero. // For the standard distribution, A = 0 and B = 1. // // Input, double C, is usually called the number of // degrees of freedom of the distribution. C is typically an // integer, but that is not essential. It is required that // C be strictly positive. // // Output, double STUDENT_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; double y; y = ( x - a ) / b; pdf = r8_gamma ( 0.5 * ( c + 1.0 ) ) / ( sqrt ( pi * c ) * r8_gamma ( 0.5 * c ) * sqrt ( pow ( ( 1.0 + y * y / c ), ( 2 * c + 1.0 ) ) ) ); return pdf; } //****************************************************************************80 double student_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // STUDENT_SAMPLE samples the central Student T PDF. // // Discussion: // // For the sampling algorithm, it is necessary that 2 < C. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 November 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, shape parameters of the PDF, // used to transform the argument X to a shifted and scaled // value Y = ( X - A ) / B. It is required that B be nonzero. // For the standard distribution, A = 0 and B = 1. // // Input, double C, is usually called the number of // degrees of freedom of the distribution. C is typically an // integer, but that is not essential. It is required that // C be strictly positive. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double STUDENT_SAMPLE, a sample of the PDF. // { double a2; double b2; double x; double x2; double x3; if ( c <= 2.0 ) { cout << " \n"; cout << "STUDENT_SAMPLE - Fatal error!\n"; cout << " Sampling fails for C <= 2.\n"; exit ( 1 ); } a2 = 0.0; b2 = c / ( c - 2.0 ); x2 = normal_sample ( a2, b2, seed ); x3 = chi_square_sample ( c, seed ); x3 = x3 * c / ( c - 2.0 ); x = a + b * x2 * sqrt ( c ) / x3; return x; } //****************************************************************************80 double student_variance ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // STUDENT_VARIANCE returns the variance of the central Student T PDF. // // Discussion: // // The variance is not defined unless 2 < C. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 November 2005 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, shape parameters of the PDF, // used to transform the argument X to a shifted and scaled // value Y = ( X - A ) / B. It is required that B be nonzero. // For the standard distribution, A = 0 and B = 1. // // Input, double C, is usually called the number of // degrees of freedom of the distribution. C is typically an // integer, but that is not essential. It is required that // C be strictly positive. // // Output, double STUDENT_VARIANCE, the variance of the PDF. // { double variance; if ( c <= 2.0 ) { cout << " \n"; cout << "STUDENT_VARIANCE - Fatal error!\n"; cout << " Variance not defined for C <= 2.\n"; exit ( 1 ); } variance = b * b * c / ( c - 2.0 ); return variance; } //****************************************************************************80 double student_noncentral_cdf ( double x, int idf, double d ) //****************************************************************************80 // // Purpose: // // STUDENT_NONCENTRAL_CDF evaluates the noncentral Student T CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // Original FORTRAN77 version by B E Cooper. // C++ version by John Burkardt // // Reference: // // BE Cooper, // The Integral of the Noncentral T-Distribution, // Algorithm AS 5, // Applied Statistics, // Volume 17, 1968, page 193. // // Parameters: // // Input, double X, the argument of the CDF. // // Input, int IDF, the number of degrees of freedom. // // Input, double D, the noncentrality parameter. // // Output, double STUDENT_NONCENTRAL_CDF, the value of the CDF. // { double a; int a_max = 100; double ak; double b; double cdf; double cdf2; double drb; double emin = 12.5; double f; double fk; double fmkm1; double fmkm2; int k; const double pi = 3.14159265358979323; double sum2; double temp; f = ( double ) idf; if ( idf == 1 ) { a = x / sqrt ( f ); b = f / ( f + x * x ); drb = d * sqrt ( b ); cdf2 = normal_01_cdf ( drb ); cdf = 1.0 - cdf2 + 2.0 * tfn ( drb, a ); } else if ( idf <= a_max ) { a = x / sqrt ( f ); b = f / ( f + x * x ); drb = d * sqrt ( b ); sum2 = 0.0; fmkm2 = 0.0; if ( r8_abs ( drb ) < emin ) { cdf2 = normal_01_cdf ( a * drb ); fmkm2 = a * sqrt ( b ) * exp ( - 0.5 * drb * drb ) * cdf2 / sqrt ( 2.0 * pi ); } fmkm1 = b * d * a * fmkm2; if ( r8_abs ( d ) < emin ) { fmkm1 = fmkm1 + 0.5 * b * a * exp ( - 0.5 * d * d ) / pi; } if ( idf % 2 == 0 ) { sum2 = fmkm2; } else { sum2 = fmkm1; } ak = 1.0; for ( k = 2; k <= idf - 2; k = k + 2 ) { fk = ( double ) ( k ); fmkm2 = b * ( d * a * ak * fmkm1 + fmkm2 ) * ( fk - 1.0 ) / fk; ak = 1.0 / ( ak * ( fk - 1.0 ) ); fmkm1 = b * ( d * a * ak * fmkm2 + fmkm1 ) * fk / ( fk + 1.0 ); if ( idf % 2 == 0 ) { sum2 = sum2 + fmkm2; } else { sum2 = sum2 + fmkm1; } ak = 1.0 / ( ak * fk ); } if ( idf % 2 == 0 ) { cdf2 = normal_01_cdf ( d ); cdf = 1.0 - cdf2 + sum2 * sqrt ( 2.0 * pi ); } else { cdf2 = normal_01_cdf ( drb ); cdf = 1.0 - cdf2 + 2.0 * ( sum2 + tfn ( drb, a ) ); } } // // Normal approximation. // else { a = sqrt ( 0.5 * f ) * exp ( gamma_log ( 0.5 * ( f - 1.0 ) ) - gamma_log ( 0.5 * f ) ) * d; temp = ( x - a ) / sqrt ( f * ( 1.0 + d * d ) / ( f - 2.0 ) - a * a ); cdf2 = normal_01_cdf ( temp ); cdf = cdf2; } return cdf; } //****************************************************************************80 void student_noncentral_cdf_values ( int &n_data, int &df, double &lambda, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // STUDENT_NONCENTRAL_CDF_VALUES returns values of the noncentral Student CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = NoncentralStudentTDistribution [ df, lambda ] // CDF [ dist, x ] // // Mathematica seems to have some difficulty computing this function // to the desired number of digits. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 September 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, int &DF, double &LAMBDA, the parameters of the // function. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 30 static int df_vec[N_MAX] = { 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 15, 20, 25, 1, 2, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10 }; static double fx_vec[N_MAX] = { 0.8975836176504333E+00, 0.9522670169E+00, 0.9711655571887813E+00, 0.8231218864E+00, 0.9049021510E+00, 0.9363471834E+00, 0.7301025986E+00, 0.8335594263E+00, 0.8774010255E+00, 0.5248571617E+00, 0.6293856597E+00, 0.6800271741E+00, 0.20590131975E+00, 0.2112148916E+00, 0.2074730718E+00, 0.9981130072E+00, 0.9994873850E+00, 0.9998391562E+00, 0.168610566972E+00, 0.16967950985E+00, 0.1701041003E+00, 0.9247683363E+00, 0.7483139269E+00, 0.4659802096E+00, 0.9761872541E+00, 0.8979689357E+00, 0.7181904627E+00, 0.9923658945E+00, 0.9610341649E+00, 0.8688007350E+00 }; static double lambda_vec[N_MAX] = { 0.0E+00, 0.0E+00, 0.0E+00, 0.5E+00, 0.5E+00, 0.5E+00, 1.0E+00, 1.0E+00, 1.0E+00, 2.0E+00, 2.0E+00, 2.0E+00, 4.0E+00, 4.0E+00, 4.0E+00, 7.0E+00, 7.0E+00, 7.0E+00, 1.0E+00, 1.0E+00, 1.0E+00, 2.0E+00, 3.0E+00, 4.0E+00, 2.0E+00, 3.0E+00, 4.0E+00, 2.0E+00, 3.0E+00, 4.0E+00 }; static double x_vec[N_MAX] = { 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 3.00E+00, 15.00E+00, 15.00E+00, 15.00E+00, 0.05E+00, 0.05E+00, 0.05E+00, 4.00E+00, 4.00E+00, 4.00E+00, 5.00E+00, 5.00E+00, 5.00E+00, 6.00E+00, 6.00E+00, 6.00E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; df = 0; lambda = 0.0; x = 0.0; fx = 0.0; } else { df = df_vec[n_data-1]; lambda = lambda_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 double tfn ( double h, double a ) //****************************************************************************80 // // Purpose: // // TFN calculates the T function of Owen. // // Discussion: // // Owen's T function is useful for computation of the bivariate normal // distribution and the distribution of a skewed normal distribution. // // Although it was originally formulated in terms of the bivariate // normal function, the function can be defined more directly as // // T(H,A) = 1 / ( 2 * PI ) * // Integral ( 0 <= X <= A ) e^( -H^2 * (1+X^2) / 2 ) / (1+X^2) dX // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 December 2004 // // Author: // // FORTRAN77 original version by J C Young, C E Minder. // C++ version by John Burkardt. // // Reference: // // D B Owen, // Tables for computing the bivariate normal distribution, // Annals of Mathematical Statistics, // Volume 27, pages 1075-1090, 1956. // // J C Young, C E Minder, // Algorithm AS 76, // An Algorithm Useful in Calculating Non-Central T and // Bivariate Normal Distributions, // Applied Statistics, // Volume 23, Number 3, 1974, pages 455-457. // // Parameters: // // Input, double H, A, the arguments of the T function. // // Output, double TFN, the value of the T function. // { # define NGAUSS 10 double as; double h1; double h2; double hs; int i; double rt; double two_pi_inverse = 0.1591549430918953; double tv1 = 1.0E-35; double tv2 = 15.0; double tv3 = 15.0; double tv4 = 1.0E-05; double value; double weight[NGAUSS] = { 0.666713443086881375935688098933E-01, 0.149451349150580593145776339658, 0.219086362515982043995534934228, 0.269266719309996355091226921569, 0.295524224714752870173892994651, 0.295524224714752870173892994651, 0.269266719309996355091226921569, 0.219086362515982043995534934228, 0.149451349150580593145776339658, 0.666713443086881375935688098933E-01 }; double x; double xtab[NGAUSS] = { -0.973906528517171720077964012084, -0.865063366688984510732096688423, -0.679409568299024406234327365115, -0.433395394129247190799265943166, -0.148874338981631210884826001130, 0.148874338981631210884826001130, 0.433395394129247190799265943166, 0.679409568299024406234327365115, 0.865063366688984510732096688423, 0.973906528517171720077964012084 }; // // Test for H near zero. // if ( r8_abs ( h ) < tv1 ) { value = atan ( a ) * two_pi_inverse; } // // Test for large values of abs(H). // else if ( tv2 < r8_abs ( h ) ) { value = 0.0; } // // Test for A near zero. // else if ( r8_abs ( a ) < tv1 ) { value = 0.0; } // // Test whether abs(A) is so large that it must be truncated. // If so, the truncated value is H2. // else { hs = - 0.5 * h * h; h2 = a; as = a * a; // // Computation of truncation point by Newton iteration. // if ( tv3 <= log ( 1.0 + as ) - hs * as ) { h1 = 0.5 * a; as = 0.25 * as; for ( ; ; ) { rt = as + 1.0; h2 = h1 + ( hs * as + tv3 - log ( rt ) ) / ( 2.0 * h1 * ( 1.0 / rt - hs ) ); as = h2 * h2; if ( r8_abs ( h2 - h1 ) < tv4 ) { break; } h1 = h2; } } // // Gaussian quadrature on the interval [0,H2]. // rt = 0.0; for ( i = 0; i < NGAUSS; i++ ) { x = 0.5 * h2 * ( xtab[i] + 1.0 ); rt = rt + weight[i] * exp ( hs * ( 1.0 + x * x ) ) / ( 1.0 + x * x ); } value = rt * 0.5 * h2 * two_pi_inverse; } return value; # undef NGAUSS } //****************************************************************************80 void timestamp ( ) //****************************************************************************80 // // Purpose: // // TIMESTAMP prints the current YMDHMS date as a time stamp. // // Example: // // 31 May 2001 09:45:54 AM // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 08 July 2009 // // Author: // // John Burkardt // // Parameters: // // None // { # define TIME_SIZE 40 static char time_buffer[TIME_SIZE]; const struct std::tm *tm_ptr; size_t len; std::time_t now; now = std::time ( NULL ); tm_ptr = std::localtime ( &now ); len = std::strftime ( time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm_ptr ); std::cout << time_buffer << "\n"; return; # undef TIME_SIZE } //****************************************************************************80 double triangle_cdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // TRIANGLE_CDF evaluates the Triangle CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, C, the parameters of the PDF. // A <= B <= C and A < C. // // Output, double TRIANGLE_CDF, the value of the CDF. // { double cdf; if ( x <= a ) { cdf = 0.0; } else if ( x <= b ) { if ( a == b ) { cdf = 0.0; } else { cdf = ( x - a ) * ( x - a ) / ( b - a ) / ( c - a ); } } else if ( x <= c ) { cdf = ( b - a ) / ( c - a ) + ( 2.0 * c - b - x ) * ( x - b ) / ( c - b ) / ( c - a ); } else { cdf = 1.0; } return cdf; } //****************************************************************************80 double triangle_cdf_inv ( double cdf, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // TRIANGLE_CDF_INV inverts the Triangle CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, C, the parameters of the PDF. // A <= B <= C and A < C. // // Output, double TRIANGLE_CDF_INV, the corresponding argument. // { double cdf_mid; double d; double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << "\n"; cout << "TRIANGLE_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } d = 2.0 / ( c - a ); cdf_mid = 0.5 * d * ( b - a ); if ( cdf <= cdf_mid ) { x = a + sqrt ( cdf * ( b - a ) * ( c - a ) ); } else { x = c - sqrt ( ( c - b ) * ( ( c - b ) - ( cdf - cdf_mid ) * ( c - a ) ) ); } return x; } //****************************************************************************80 bool triangle_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // TRIANGLE_CHECK checks the parameters of the Triangle CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // A <= B <= C and A < C. // // Output, bool TRIANGLE_CHECK, is true if the parameters are legal. // { if ( b < a ) { cout << "\n"; cout << "TRIANGLE_CHECK - Fatal error!\n"; cout << " B < A.\n"; return false; } if ( c < b ) { cout << "\n"; cout << "TRIANGLE_CHECK - Fatal error!\n"; cout << " C < B.\n"; return false; } if ( a == c ) { cout << "\n"; cout << "TRIANGLE_CHECK - Fatal error!\n"; cout << " A == C.\n"; return false; } return true; } //****************************************************************************80 double triangle_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // TRIANGLE_MEAN returns the mean of the Triangle PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // A <= B <= C and A < C. // // Output, double TRIANGLE_MEAN, the mean of the discrete uniform PDF. // { double mean; mean = a + ( c + b - 2.0 * a ) / 3.0; return mean; } //****************************************************************************80 double triangle_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // TRIANGLE_PDF evaluates the Triangle PDF. // // Discussion: // // Given points A <= B <= C, the probability is 0 to the left of A, // rises linearly to a maximum of 2/(C-A) at B, drops linearly to zero // at C, and is zero for all values greater than C. // // PDF(A,B,C;X) // = 2 * ( X - A ) / ( B - A ) / ( C - A ) for A <= X <= B // = 2 * ( C - X ) / ( C - B ) / ( C - A ) for B <= X <= C. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, C, the parameters of the PDF. // A <= B <= C and A < C. // // Output, double TRIANGLE_PDF, the value of the PDF. // { double pdf; if ( x <= a ) { pdf = 0.0; } else if ( x <= b ) { if ( a == b ) { pdf = 0.0; } else { pdf = 2.0 * ( x - a ) / ( b - a ) / ( c - a ); } } else if ( x <= c ) { if ( b == c ) { pdf = 0.0; } else { pdf = 2.0 * ( c - x ) / ( c - b ) / ( c - a ); } } else { pdf = 0.0; } return pdf; } //****************************************************************************80 double triangle_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // TRIANGLE_SAMPLE samples the Triangle PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // A <= B <= C and A < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double TRIANGLE_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = triangle_cdf_inv ( cdf, a, b, c ); return x; } //****************************************************************************80 double triangle_variance ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // TRIANGLE_VARIANCE returns the variance of the Triangle PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // A <= B <= C and A < C. // // Output, double VARIANCE, the variance of the PDF. // { double variance; variance = ( ( c - a ) * ( c - a ) - ( c - a ) * ( b - a ) + ( b - a ) * ( b - a ) ) / 18.0; return variance; } //****************************************************************************80 double triangular_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // TRIANGULAR_CDF evaluates the Triangular CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double TRIANGULAR_CDF, the value of the CDF. // { double cdf; if ( x <= a ) { cdf = 0.0; } else if ( x <= 0.5 * ( a + b ) ) { cdf = 2.0 * ( x * x - 2.0 * a * x + a * a ) / pow ( ( b - a ), 2 ); } else if ( x <= b ) { cdf = 0.5 + ( - 2.0 * x * x + 4.0 * b * x + 0.5 * a * a - a * b - 1.5 * b * b ) / pow ( ( b - a ), 2 ); } else { cdf = 1.0; } return cdf; } //****************************************************************************80 double triangular_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // TRIANGULAR_CDF_INV inverts the Triangular CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double TRIANGULAR_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "TRIANGULAR_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf <= 0.5 ) { x = a + 0.5 * ( b - a ) * sqrt ( 2.0 * cdf ); } else { x = b - 0.5 * ( b - a ) * sqrt ( 2.0 * ( 1.0 - cdf ) ); } return x; } //****************************************************************************80 bool triangular_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // TRIANGULAR_CHECK checks the parameters of the Triangular CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, bool TRIANGULAR_CHECK, is true if the parameters are legal. // { if ( b <= a ) { cout << " \n"; cout << "TRIANGULAR_CHECK - Fatal error!\n"; cout << " B <= A.\n"; return false; } return true; } //****************************************************************************80 double triangular_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // TRIANGULAR_MEAN returns the mean of the Triangular PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double TRIANGULAR_MEAN, the mean of the discrete PDF. // { double mean; mean = 0.5 * ( a + b ); return mean; } //****************************************************************************80 double triangular_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // TRIANGULAR_PDF evaluates the Triangular PDF. // // Discussion: // // PDF(A,B;X) = 4 * ( X - A ) / ( B - A )^2 for A <= X <= (A+B)/2 // = 4 * ( B - X ) / ( B - A )^2 for (A+B)/2 <= X <= B. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double TRIANGULAR_PDF, the value of the PDF. // { double pdf; if ( x <= a ) { pdf = 0.0; } else if ( x <= 0.5 * ( a + b ) ) { pdf = 4.0 * ( x - a ) / ( b - a ) / ( b - a ); } else if ( x <= b ) { pdf = 4.0 * ( b - x ) / ( b - a ) / ( b - a ); } else { pdf = 0.0; } return pdf; } //****************************************************************************80 double triangular_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // TRIANGULAR_SAMPLE samples the Triangular PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // A < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double TRIANGULAR_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = triangular_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double triangular_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // TRIANGULAR_VARIANCE returns the variance of the Triangular PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double TRIANGULAR_VARIANCE, the variance of the PDF. // { double variance; variance = ( b - a ) * ( b - a ) / 24.0; return variance; } //****************************************************************************80 double trigamma ( double x ) //****************************************************************************80 // // Purpose: // // TRIGAMMA calculates the TriGamma function. // // Discussion: // // TriGamma(x) = d^2 log ( Gamma ( x ) ) / dx^2. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 January 2000 // // Author: // // Original FORTRAN77 version by B Schneider // C++ version by John Burkardt // // Reference: // // B Schneider, // Trigamma Function, // Algorithm AS 121, // Applied Statistics, // Volume 27, Number 1, page 97-99, 1978. // // Parameters: // // Input, double X, the argument of the trigamma function. // 0 < X. // // Output, double TRIGAMMA, the value of the // trigamma function at X. // { double a = 0.0001; double b = 5.0; double b2 = 1.0 / 6.0; double b4 = - 1.0 / 30.0; double b6 = 1.0 / 42.0; double b8 = - 1.0 / 30.0; double value; double y; double z; // // 1): If X is not positive, fail. // if ( x <= 0.0 ) { value = 0.0; cout << " \n"; cout << "TRIGAMMA - Fatal error!\n"; cout << " X <= 0.\n"; exit ( 1 ); } // // 2): If X is smaller than A, use a small value approximation. // else if ( x <= a ) { value = 1.0 / x / x; } // // 3): Otherwise, increase the argument to B <= ( X + I ). // else { z = x; value = 0.0; while ( z < b ) { value = value + 1.0 / z / z; z = z + 1.0; } // // ...and then apply an asymptotic formula. // y = 1.0 / z / z; value = value + 0.5 * y + ( 1.0 + y * ( b2 + y * ( b4 + y * ( b6 + y * b8 )))) / z; } return value; } //****************************************************************************80 double uniform_01_cdf ( double x ) //****************************************************************************80 // // Purpose: // // UNIFORM_01_CDF evaluates the Uniform 01 CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Output, double UNIFORM_01_CDF, the value of the CDF. // { double cdf; if ( x < 0.0 ) { cdf = 0.0; } else if ( 1.0 < x ) { cdf = 1.0; } else { cdf = x; } return cdf; } //****************************************************************************80 double uniform_01_cdf_inv ( double cdf ) //****************************************************************************80 // // Purpose: // // UNIFORM_01_CDF_INV inverts the Uniform 01 CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Output, double UNIFORM_01_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "UNIFORM_01_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = cdf; return x; } //****************************************************************************80 double uniform_01_mean ( ) //****************************************************************************80 // // Purpose: // // UNIFORM_01_MEAN returns the mean of the Uniform 01 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double UNIFORM_01_MEAN, the mean of the discrete uniform PDF. // { double mean; mean = 0.5; return mean; } //****************************************************************************80 double uniform_01_pdf ( double x ) //****************************************************************************80 // // Purpose: // // UNIFORM_01_PDF evaluates the Uniform 01 PDF. // // Discussion: // // PDF(X) = 1 for 0 <= X <= 1 // = 0 otherwise // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // 0.0 <= X <= 1.0. // // Output, double PDF, the value of the PDF. // { double pdf; if ( x < 0.0 || 1.0 < x ) { pdf = 0.0; } else { pdf = 1.0; } return pdf; } //****************************************************************************80 double uniform_01_sample ( int &seed ) //****************************************************************************80 // // Purpose: // // UNIFORM_01_SAMPLE is a random number generator. // // Discussion: // // SEED = SEED * (7^5) mod (2^31 - 1) // UNIFORM_01_SAMPLE = SEED * / ( 2^31 - 1 ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2008 // // Author: // // John Burkardt // // Parameters: // // Input/output, int &SEED, the integer "seed" used to generate // the output random number, and updated in preparation for the // next one. SEED should not be zero. // // Output, double UNIFORM_01_SAMPLE, a random value between 0 and 1. // // Local Parameters: // // Local, int IA = 7^5. // // Local, int IB = 2^15. // // Local, int IB16 = 2^16. // // Local, int IP = 2^31 - 1. // { static int ia = 16807; static int ib15 = 32768; static int ib16 = 65536; static int ip = 2147483647; int iprhi; int ixhi; int k; int leftlo; int loxa; double temp; // // Don't let SEED be 0. // if ( seed == 0 ) { seed = ip; } // // Get the 15 high order bits of SEED. // ixhi = seed / ib16; // // Get the 16 low bits of SEED and form the low product. // loxa = ( seed - ixhi * ib16 ) * ia; // // Get the 15 high order bits of the low product. // leftlo = loxa / ib16; // // Form the 31 highest bits of the full product. // iprhi = ixhi * ia + leftlo; // // Get overflow past the 31st bit of full product. // k = iprhi / ib15; // // Assemble all the parts and presubtract IP. The parentheses are essential. // seed = ( ( ( loxa - leftlo * ib16 ) - ip ) + ( iprhi - k * ib15 ) * ib16 ) + k; // // Add IP back in if necessary. // if ( seed < 0 ) { seed = seed + ip; } // // Multiply by 1 / (2^31-1). // temp = ( ( double ) seed ) * 4.656612875E-10; return temp; } //****************************************************************************80 double uniform_01_variance ( ) //****************************************************************************80 // // Purpose: // // UNIFORM_01_VARIANCE returns the variance of the Uniform 01 PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Output, double UNIFORM_01_VARIANCE, the variance of the PDF. // { double variance; variance = 1.0 / 12.0; return variance; } //****************************************************************************80 double *uniform_01_order_sample ( int n, int &seed ) //****************************************************************************80 // // Purpose: // // UNIFORM_01_ORDER_SAMPLE samples the Uniform 01 Order PDF. // // Discussion: // // In effect, this routine simply generates N samples of the // Uniform 01 PDF; but it generates them in order. (Actually, // it generates them in descending order, but stores them in // the array in ascending order). This saves the work of // sorting the results. Moreover, if the order statistics // for another PDF are desired, and the inverse CDF is available, // then the desired values may be generated, presorted, by // calling this routine and using the results as input to the // inverse CDF routine. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 27 October 2004 // // Author: // // John Burkardt // // Reference: // // Jerry Banks, editor, // Handbook of Simulation, // Engineering and Management Press Books, 1998, page 168. // // Parameters: // // Input, int N, the number of elements in the sample. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double UNIFORM_01_ORDER_SAMPLE[N], N samples of the Uniform 01 PDF, in // ascending order. // { int i; double u; double v; double *x; x = new double[n]; v = 1.0; for ( i = n-1; 0 <= i; i-- ) { u = r8_uniform_01 ( seed ); v = v * pow ( u, 1.0 / ( double ) ( i + 1 ) ); x[i] = v; } return x; } //****************************************************************************80 double uniform_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // UNIFORM_CDF evaluates the Uniform CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double UNIFORM_CDF, the value of the CDF. // { double cdf; if ( x < a ) { cdf = 0.0; } else if ( b < x ) { cdf = 1.0; } else { cdf = ( x - a ) / ( b - a ); } return cdf; } //****************************************************************************80 double uniform_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // UNIFORM_CDF_INV inverts the Uniform CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double UNIFORM_CDF_INV, the corresponding argument. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "UNIFORM_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a + ( b - a ) * cdf; return x; } //****************************************************************************80 bool uniform_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // UNIFORM_CHECK checks the parameters of the Uniform CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, bool UNIFORM_CHECK, is true if the parameters are legal. // { if ( b <= a ) { cout << " \n"; cout << "UNIFORM_CHECK - Fatal error!\n"; cout << " B <= A.\n"; return false; } return true; } //****************************************************************************80 double uniform_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // UNIFORM_MEAN returns the mean of the Uniform PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double UNIFORM_MEAN, the mean of the discrete uniform PDF. // { double mean; mean = 0.5 * ( a + b ); return mean; } //****************************************************************************80 double uniform_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // UNIFORM_PDF evaluates the Uniform PDF. // // Discussion: // // The Uniform PDF is also known as the "Rectangular" or "de Moivre" PDF. // // PDF(A,B;X) = 1 / ( B - A ) for A <= X <= B // = 0 otherwise // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double UNIFORM_PDF, the value of the PDF. // { double pdf; if ( x < a || b < x ) { pdf = 0.0; } else { pdf = 1.0 / ( b - a ); } return pdf; } //****************************************************************************80 double uniform_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // UNIFORM_SAMPLE samples the Uniform PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // A < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double UNIFORM_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = uniform_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double uniform_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // UNIFORM_VARIANCE returns the variance of the Uniform PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // A < B. // // Output, double UNIFORM_VARIANCE, the variance of the PDF. // { double variance; variance = ( b - a ) * ( b - a ) / 12.0; return variance; } //****************************************************************************80 double uniform_discrete_cdf ( int x, int a, int b ) //****************************************************************************80 // // Purpose: // // UNIFORM_DISCRETE_CDF evaluates the Uniform Discrete CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the CDF. // // Input, int A, B, the parameters of the PDF. // A <= B. // // Output, double UNIFORM_DISCRETE_CDF, the value of the CDF. // { double cdf; if ( x < a ) { cdf = 0.0; } else if ( b < x ) { cdf = 1.0; } else { cdf = ( double ) ( x + 1 - a ) / ( double ) ( b + 1 - a ); } return cdf; } //****************************************************************************80 int uniform_discrete_cdf_inv ( double cdf, int a, int b ) //****************************************************************************80 // // Purpose: // // UNIFORM_DISCRETE_CDF_INV inverts the Uniform Discrete CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 November 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, int A, B, the parameters of the PDF. // A <= B. // // Output, int UNIFORM_DISCRETE_CDF_INV, the smallest argument whose // CDF is greater than or equal to CDF. // { double a2; double b2; int x; double x2; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "UNIFORM_DISCRETE_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } a2 = ( double ) ( a ) - 0.5; b2 = ( double ) ( b ) + 0.5; x2 = a + cdf * ( b2 - a2 ); x = r8_nint ( x2 ); x = i4_max ( x, a ); x = i4_min ( x, b ); return x; } //****************************************************************************80 bool uniform_discrete_check ( int a, int b ) //****************************************************************************80 // // Purpose: // // UNIFORM_DISCRETE_CHECK checks the parameters of the Uniform discrete CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, B, the parameters of the PDF. // A <= B. // // Output, bool UNIFORM_DISCRETE_CHECK, is true if the parameters // are legal. // { if ( b < a ) { cout << " \n"; cout << "UNIFORM_DISCRETE_CHECK - Fatal error!\n"; cout << " B < A.\n"; return false; } return true; } //****************************************************************************80 double uniform_discrete_mean ( int a, int b ) //****************************************************************************80 // // Purpose: // // UNIFORM_DISCRETE_MEAN returns the mean of the Uniform discrete PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, B, the parameters of the PDF. // A <= B. // // Output, double UNIFORM_DISCRETE_MEAN, the mean of the PDF. // { double mean; mean = 0.5 * ( double ) ( a + b ); return mean; } //****************************************************************************80 double uniform_discrete_pdf ( int x, int a, int b ) //****************************************************************************80 // // Purpose: // // UNIFORM_DISCRETE_PDF evaluates the Uniform discrete PDF. // // Discussion: // // The Uniform Discrete PDF is also known as the "Rectangular" // Discrete PDF. // // PDF(A,B;X) = 1 / ( B + 1 - A ) for A <= X <= B. // // The parameters define the interval of integers // for which the PDF is nonzero. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the PDF. // // Input, int A, B, the parameters of the PDF. // A <= B. // // Output, double UNIFORM_DISCRETE_PDF, the value of the PDF. // { double pdf; if ( x < a || b < x ) { pdf = 0.0; } else { pdf = 1.0 / ( double ) ( b + 1 - a ); } return pdf; } //****************************************************************************80 int uniform_discrete_sample ( int a, int b, int &seed ) //****************************************************************************80 // // Purpose: // // UNIFORM_DISCRETE_SAMPLE samples the Uniform discrete PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, B, the parameters of the PDF. // A <= B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int UNIFORM_DISCRETE_SAMPLE, a sample of the PDF. // { double cdf; int x; cdf = r8_uniform_01 ( seed ); x = uniform_discrete_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double uniform_discrete_variance ( int a, int b ) //****************************************************************************80 // // Purpose: // // UNIFORM_DISCRETE_VARIANCE returns the variance of the Uniform discrete PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int A, B, the parameters of the PDF. // A <= B. // // Output, double UNIFORM_DISCRETE_VARIANCE, the variance of the PDF. // { double variance; variance = ( double ) ( ( b + 1 - a ) * ( b + 1 - a ) - 1 ) / 12.0; return variance; } //****************************************************************************80 double *uniform_nsphere_sample ( int n, int &seed ) //****************************************************************************80 // // Purpose: // // UNIFORM_NSPHERE_SAMPLE samples the Uniform Unit Sphere PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Reference: // // Jerry Banks, editor, // Handbook of Simulation, // Engineering and Management Press Books, 1998, page 168. // // Parameters: // // Input, int N, the dimension of the sphere. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double UNIFORM_NSPHERE_SAMPLE[N], a point on the unit N // sphere, chosen with a uniform probability. // { int i; double sum; double *x; x = new double[n]; for ( i = 0; i < n; i++ ) { x[i] = normal_01_sample ( seed ); } sum = 0.0; for ( i = 0; i < n; i++ ) { sum = sum + x[i] * x[i]; } sum = sqrt ( sum ); for ( i = 0; i < n; i++ ) { x[i] = x[i] / sum; } return x; } //****************************************************************************80 double von_mises_cdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // VON_MISES_CDF evaluates the von Mises CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 November 2006 // // Author: // // Original FORTRAN77 version by Geoffrey Hill // C++ version by John Burkardt // // Reference: // // Geoffrey Hill, // ACM TOMS Algorithm 518, // Incomplete Bessel Function I0: The von Mises Distribution, // ACM Transactions on Mathematical Software, // Volume 3, Number 3, September 1977, pages 279-284. // // Kanti Mardia, Peter Jupp, // Directional Statistics, // Wiley, 2000, QA276.M335 // // Parameters: // // Input, double X, the argument of the CDF. // A - PI <= X <= A + PI. // // Input, double A, B, the parameters of the PDF. // -PI <= A <= PI, // 0.0 < B. // // Output, double VON_MISES_CDF, the value of the CDF. // { double a1 = 12.0; double a2 = 0.8; double a3 = 8.0; double a4 = 1.0; double arg; double c; double c1 = 56.0; double cdf; double ck = 10.5; double cn; double erfx; int ip; int n; double p; const double pi = 3.14159265358979323; double r; double s; double sn; double u; double v; double y; double z; // // We expect -PI <= X - A <= PI. // if ( x - a <= -pi ) { cdf = 0.0; return cdf; } if ( pi <= x - a ) { cdf = 1.0; return cdf; } // // Convert the angle (X - A) modulo 2 PI to the range ( 0, 2 * PI ). // z = b; u = r8_modp ( x - a + pi, 2.0 * pi ); if ( u < 0.0 ) { u = u + 2.0 * pi; } y = u - pi; // // For small B, sum IP terms by backwards recursion. // if ( z <= ck ) { v = 0.0; if ( 0.0 < z ) { ip = ( int ) ( z * a2 - a3 / ( z + a4 ) + a1 ); p = ( double ) ( ip ); s = sin ( y ); c = cos ( y ); y = p * y; sn = sin ( y ); cn = cos ( y ); r = 0.0; z = 2.0 / z; for ( n = 2; n <= ip; n++ ) { p = p - 1.0; y = sn; sn = sn * c - cn * s; cn = cn * c + y * s; r = 1.0 / ( p * z + r ); v = ( sn / p + v ) * r; } } cdf = ( u * 0.5 + v ) / pi; } // // For large B, compute the normal approximation and left tail. // else { c = 24.0 * z; v = c - c1; r = sqrt ( ( 54.0 / ( 347.0 / v + 26.0 - c ) - 6.0 + c ) / 12.0 ); z = sin ( 0.5 * y ) * r; s = 2.0 * z * z; v = v - s + 3.0; y = ( c - s - s - 16.0 ) / 3.0; y = ( ( s + 1.75 ) * s + 83.5 ) / v - y; arg = z * ( 1.0 - s / y / y ); erfx = error_f ( arg ); cdf = 0.5 * erfx + 0.5; } cdf = r8_max ( cdf, 0.0 ); cdf = r8_min ( cdf, 1.0 ); return cdf; } //****************************************************************************80 double von_mises_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // VON_MISES_CDF_INV inverts the von Mises CDF. // // Discussion: // // A simple bisection method is used on the interval [ A - PI, A + PI ]. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // // Input, double A, B, the parameters of the PDF. // -PI <= A <= PI, // 0.0 < B. // // Output, double VON_MISES_CDF_INV, the corresponding argument of the CDF. // A - PI <= X <= A + PI. // { double cdf1; double cdf2; double cdf3; int it; int it_max = 100; const double pi = 3.14159265358979323; double tol = 0.0001; double x; double x1; double x2; double x3; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "VON_MISES_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } if ( cdf == 0.0 ) { x = a - pi; return x; } else if ( 1.0 == cdf ) { x = a + pi; return x; } x1 = a - pi; cdf1 = 0.0; x2 = a + pi; cdf2 = 1.0; // // Now use bisection. // it = 0; for ( ; ; ) { it = it + 1; x3 = 0.5 * ( x1 + x2 ); cdf3 = von_mises_cdf ( x3, a, b ); if ( r8_abs ( cdf3 - cdf ) < tol ) { x = x3; break; } if ( it_max < it ) { cout << " \n"; cout << "VON_MISES_CDF_INV - Fatal error!\n"; cout << " Iteration limit exceeded.\n"; exit ( 1 ); } if ( ( cdf3 <= cdf && cdf1 <= cdf ) || ( cdf <= cdf3 && cdf <= cdf1 ) ) { x1 = x3; cdf1 = cdf3; } else { x2 = x3; cdf2 = cdf3; } } return x; } //****************************************************************************80 void von_mises_cdf_values ( int &n_data, double &a, double &b, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // VON_MISES_CDF_VALUES returns some values of the von Mises CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 08 December 2004 // // Author: // // John Burkardt // // Reference: // // Kanti Mardia, Peter Jupp, // Directional Statistics, // Wiley, 2000, QA276.M335 // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &A, &B, the parameters of the function. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 23 static double a_vec[N_MAX] = { 0.0E+00, 0.0E+00, 0.0E+00, 0.0E+00, 0.0E+00, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, -0.2E+01, -0.1E+01, 0.0E+01, 0.1E+01, 0.2E+01, 0.3E+01, 0.0E+00, 0.0E+00, 0.0E+00, 0.0E+00, 0.0E+00, 0.0E+00 }; static double b_vec[N_MAX] = { 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.1E+01, 0.2E+01, 0.2E+01, 0.2E+01, 0.2E+01, 0.2E+01, 0.2E+01, 0.3E+01, 0.3E+01, 0.3E+01, 0.3E+01, 0.3E+01, 0.3E+01, 0.0E+00, 0.1E+01, 0.2E+01, 0.3E+01, 0.4E+01, 0.5E+01 }; static double fx_vec[N_MAX] = { 0.2535089956281180E-01, 0.1097539041177346E+00, 0.5000000000000000E+00, 0.8043381312498558E+00, 0.9417460124555197E+00, 0.5000000000000000E+00, 0.6018204118446155E+00, 0.6959356933122230E+00, 0.7765935901304593E+00, 0.8410725934916615E+00, 0.8895777369550366E+00, 0.9960322705517925E+00, 0.9404336090170247E+00, 0.5000000000000000E+00, 0.5956639098297530E-01, 0.3967729448207649E-02, 0.2321953958111930E-03, 0.6250000000000000E+00, 0.7438406999109122E+00, 0.8369224904294019E+00, 0.8941711407897124E+00, 0.9291058600568743E+00, 0.9514289900655436E+00 }; static double x_vec[N_MAX] = { -0.2617993977991494E+01, -0.1570796326794897E+01, 0.0000000000000000E+00, 0.1047197551196598E+01, 0.2094395102393195E+01, 0.1000000000000000E+01, 0.1200000000000000E+01, 0.1400000000000000E+01, 0.1600000000000000E+01, 0.1800000000000000E+01, 0.2000000000000000E+01, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.7853981633974483E+00, 0.7853981633974483E+00, 0.7853981633974483E+00, 0.7853981633974483E+00, 0.7853981633974483E+00, 0.7853981633974483E+00 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; a = 0.0; b = 0.0; x = 0.0; fx = 0.0; } else { a = a_vec[n_data-1]; b = b_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool von_mises_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // VON_MISES_CHECK checks the parameters of the von Mises PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // -PI <= A <= PI, // 0.0 < B. // // Output, bool VON_MISES_CHECK, is true if the parameters are legal. // { const double pi = 3.14159265358979323; if ( a < - pi || pi < a ) { cout << " \n"; cout << "VON_MISES_CHECK - Fatal error!\n"; cout << " A < -PI or PI < A.\n"; return false; } if ( b <= 0.0 ) { cout << " \n"; cout << "VON_MISES_CHECK - Fatal error!\n"; cout << " B <= 0.0\n"; return false; } return true; # } //****************************************************************************80 double von_mises_circular_variance ( double a, double b ) //****************************************************************************80 // // Purpose: // // VON_MISES_CIRCULAR_VARIANCE returns the circular variance of the von Mises PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 December 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // -PI <= A <= PI, // 0.0 < B. // // Output, double VON_MISES_CIRCULAR_VARIANCE, the circular variance of the PDF. // { double value; value = 1.0 - bessel_i1 ( b ) / bessel_i0 ( b ); return value; } //****************************************************************************80 double von_mises_mean ( double a, double b ) //****************************************************************************80 // // Purpose: // // VON_MISES_MEAN returns the mean of the von Mises PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // -PI <= A <= PI, // 0.0 < B. // // Output, double VON_MISES_MEAN, the mean of the PDF. // { double mean; mean = a; return mean; } //****************************************************************************80 double von_mises_pdf ( double x, double a, double b ) //****************************************************************************80 // // Purpose: // // VON_MISES_PDF evaluates the von Mises PDF. // // Discussion: // // PDF(A,B;X) = EXP ( B * COS ( X - A ) ) / ( 2 * PI * I0(B) ) // // where: // // I0(*) is the modified Bessel function of the first // kind of order 0. // // The von Mises distribution for points on the unit circle is // analogous to the normal distribution of points on a line. // The variable X is interpreted as a deviation from the angle A, // with B controlling the amount of dispersion. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 27 October 2004 // // Author: // // John Burkardt // // Reference: // // Jerry Banks, editor, // Handbook of Simulation, // Engineering and Management Press Books, 1998, page 160. // // D J Best, N I Fisher, // Efficient Simulation of the von Mises Distribution, // Applied Statistics, // Volume 28, Number 2, pages 152-157. // // Kanti Mardia, Peter Jupp, // Directional Statistics, // Wiley, 2000, QA276.M335 // // Parameters: // // Input, double X, the argument of the PDF. // A - PI <= X <= A + PI. // // Input, double A, B, the parameters of the PDF. // -PI <= A <= PI, // 0.0 < B. // // Output, double VON_MISES_PDF, the value of the PDF. // { double pdf; const double pi = 3.14159265358979323; if ( x < a - pi ) { pdf = 0.0; } else if ( x <= a + pi ) { pdf = exp ( b * cos ( x - a ) ) / ( 2.0 * pi * bessel_i0 ( b ) ); } else { pdf = 0.0; } return pdf; } //****************************************************************************80 double von_mises_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // VON_MISES_SAMPLE samples the von Mises PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 17 October 2004 // // Author: // // John Burkardt // // Reference: // // D J Best, N I Fisher, // Efficient Simulation of the von Mises Distribution, // Applied Statistics, // Volume 28, Number 2, pages 152-157. // // Parameters: // // Input, double A, B, the parameters of the PDF. // -PI <= A <= PI, // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double VON_MISES_SAMPLE, a sample of the PDF. // { double c; double f; const double pi = 3.14159265358979323; double r; double rho; double tau; double u1; double u2; double u3; double x; double z; tau = 1.0 + sqrt ( 1.0 + 4.0 * b * b ); rho = ( tau - sqrt ( 2.0 * tau ) ) / ( 2.0 * b ); r = ( 1.0 + rho * rho ) / ( 2.0 * rho ); for ( ; ; ) { u1 = r8_uniform_01 ( seed ); z = cos ( pi * u1 ); f = ( 1.0 + r * z ) / ( r + z ); c = b * ( r - f ); u2 = r8_uniform_01 ( seed ); if ( u2 < c * ( 2.0 - c ) ) { break; } if ( c <= log ( c / u2 ) + 1.0 ) { break; } } u3 = r8_uniform_01 ( seed ); x = a + r8_sign ( u3 - 0.5 ) * acos ( f ); return x; } //****************************************************************************80 double weibull_cdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // WEIBULL_CDF evaluates the Weibull CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the CDF. // A <= X. // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double CDF, the value of the CDF. // { double cdf; double y; if ( x < a ) { cdf = 0.0; } else { y = ( x - a ) / b; cdf = 1.0 - 1.0 / exp ( pow ( y, c ) ); } return cdf; } //****************************************************************************80 double weibull_cdf_inv ( double cdf, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // WEIBULL_CDF_INV inverts the Weibull CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 < CDF < 1.0. // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double WEIBULL_CDF_INV, the corresponding argument of the CDF. // { double x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << "\n"; cout << "WEIBULL_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = a + b * pow ( ( - log ( 1.0 - cdf ) ), ( 1.0 / c ) ); return x; } //****************************************************************************80 void weibull_cdf_values ( int &n_data, double &alpha, double &beta, double &x, double &fx ) //****************************************************************************80 // // Purpose: // // WEIBULL_CDF_VALUES returns some values of the Weibull CDF. // // Discussion: // // In Mathematica, the function can be evaluated by: // // Needs["Statistics`ContinuousDistributions`"] // dist = WeibullDistribution [ alpha, beta ] // CDF [ dist, x ] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 August 2004 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Stephen Wolfram, // The Mathematica Book, // Fourth Edition, // Cambridge University Press, 1999, // ISBN: 0-521-64314-7, // LC: QA76.95.W65. // // Parameters: // // Input/output, int &N_DATA. The user sets N_DATA to 0 before the // first call. On each call, the routine increments N_DATA by 1, and // returns the corresponding data; when there is no more data, the // output value of N_DATA will be 0 again. // // Output, double &ALPHA, the first parameter of the distribution. // // Output, double &BETA, the second parameter of the distribution. // // Output, double &X, the argument of the function. // // Output, double &FX, the value of the function. // { # define N_MAX 12 static double alpha_vec[N_MAX] = { 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01 }; static double beta_vec[N_MAX] = { 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.5000000000000000E+00, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.5000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01 }; static double fx_vec[N_MAX] = { 0.8646647167633873E+00, 0.9816843611112658E+00, 0.9975212478233336E+00, 0.9996645373720975E+00, 0.6321205588285577E+00, 0.4865828809674080E+00, 0.3934693402873666E+00, 0.3296799539643607E+00, 0.8946007754381357E+00, 0.9657818816883340E+00, 0.9936702845725143E+00, 0.9994964109502630E+00 }; static double x_vec[N_MAX] = { 0.1000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.4000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.2000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01, 0.3000000000000000E+01 }; if ( n_data < 0 ) { n_data = 0; } n_data = n_data + 1; if ( N_MAX < n_data ) { n_data = 0; alpha = 0.0; beta = 0.0; x = 0.0; fx = 0.0; } else { alpha = alpha_vec[n_data-1]; beta = beta_vec[n_data-1]; x = x_vec[n_data-1]; fx = fx_vec[n_data-1]; } return; # undef N_MAX } //****************************************************************************80 bool weibull_check ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // WEIBULL_CHECK checks the parameters of the Weibull CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, bool WEIBULL_CHECK, is true if the parameters are legal. // { if ( b <= 0.0 ) { cout << "\n"; cout << "WEIBULL_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } if ( c <= 0.0 ) { cout << "\n"; cout << "WEIBULL_CHECK - Fatal error!\n"; cout << " C <= 0.\n"; return false; } return true; } //****************************************************************************80 double weibull_mean ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // WEIBULL_MEAN returns the mean of the Weibull PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double MEAN, the mean of the PDF. // { double mean; mean = b * r8_gamma ( ( c + 1.0 ) / c ) + a; return mean; } //****************************************************************************80 double weibull_pdf ( double x, double a, double b, double c ) //****************************************************************************80 // // Purpose: // // WEIBULL_PDF evaluates the Weibull PDF. // // Discussion: // // PDF(A,B,C;X) = ( C / B ) * ( ( X - A ) / B )^( C - 1 ) // * EXP ( - ( ( X - A ) / B )^C ). // // The Weibull PDF is also known as the Frechet PDF. // // WEIBULL_PDF(A,B,1;X) is the Exponential PDF. // // WEIBULL_PDF(0,1,2;X) is the Rayleigh PDF. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the argument of the PDF. // A <= X // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double PDF, the value of the PDF. // { double pdf; double y; if ( x < a ) { pdf = 0.0; } else { y = ( x - a ) / b; pdf = ( c / b ) * pow ( y, ( c - 1.0 ) ) / exp ( pow ( y, c ) ); } return pdf; } //****************************************************************************80 double weibull_sample ( double a, double b, double c, int &seed ) //****************************************************************************80 // // Purpose: // // WEIBULL_SAMPLE samples the Weibull PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double WEIBULL_SAMPLE, a sample of the PDF. // { double cdf; double x; cdf = r8_uniform_01 ( seed ); x = weibull_cdf_inv ( cdf, a, b, c ); return x; } //****************************************************************************80 double weibull_variance ( double a, double b, double c ) //****************************************************************************80 // // Purpose: // // WEIBULL_VARIANCE returns the variance of the Weibull PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 September 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, C, the parameters of the PDF. // 0.0 < B, // 0.0 < C. // // Output, double VARIANCE, the variance of the PDF. // { double g1; double g2; double variance; g1 = r8_gamma ( ( c + 2.0 ) / c ); g2 = r8_gamma ( ( c + 1.0 ) / c ); variance = b * b * ( g1 - g2 * g2 ); return variance; } //****************************************************************************80 double weibull_discrete_cdf ( int x, double a, double b ) //****************************************************************************80 // // Purpose: // // WEIBULL_DISCRETE_CDF evaluates the Discrete Weibull CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the CDF. // 0 <= X. // // Input, double A, B, the parameters of the PDF. // 0.0 <= A <= 1.0, // 0.0 < B. // // Output, double WEIBULL_DISCRETE_CDF, the value of the CDF. // { double cdf; if ( x < 0 ) { cdf = 0.0; } else { cdf = 1.0 - pow ( 1.0 - a, pow ( x + 1, b ) ); } return cdf; } //****************************************************************************80 int weibull_discrete_cdf_inv ( double cdf, double a, double b ) //****************************************************************************80 // // Purpose: // // WEIBULL_DISCRETE_CDF_INV inverts the Discrete Weibull CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double CDF, the value of the CDF. // 0.0 <= CDF <= 1.0. // // Input, double A, B, the parameters of the PDF. // 0.0 <= A <= 1.0, // 0.0 < B. // // Output, int WEIBULL_DISCRETE_CDF_INV, the corresponding argument. // { int x; if ( cdf < 0.0 || 1.0 < cdf ) { cout << " \n"; cout << "WEIBULL_DISCRETE_CDF_INV - Fatal error!\n"; cout << " CDF < 0 or 1 < CDF.\n"; exit ( 1 ); } x = r8_ceiling ( pow ( log ( 1.0 - cdf ) / log ( 1.0 - a ), 1.0 / b ) - 1.0 ); return x; } //****************************************************************************80 bool weibull_discrete_check ( double a, double b ) //****************************************************************************80 // // Purpose: // // WEIBULL_DISCRETE_CHECK checks the parameters of the discrete Weibull CDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 <= A <= 1.0, // 0.0 < B. // // Output, bool WEIBULL_DISCRETE_CHECK, is true if the parameters // are legal. // { if ( a < 0.0 || 1.0 < a ) { cout << " \n"; cout << "WEIBULL_DISCRETE_CHECK - Fatal error!\n"; cout << " A < 0 or 1 < A.\n"; return false; } if ( b <= 0.0 ) { cout << " \n"; cout << "WEIBULL_DISCRETE_CHECK - Fatal error!\n"; cout << " B <= 0.\n"; return false; } return true; } //****************************************************************************80 double weibull_discrete_pdf ( int x, double a, double b ) //****************************************************************************80 // // Purpose: // // WEIBULL_DISCRETE_PDF evaluates the discrete Weibull PDF. // // Discussion: // // PDF(A,B;X) = ( 1 - A )^X^B - ( 1 - A )^(X+1)^B. // // WEIBULL_DISCRETE_PDF(A,1;X) = GEOMETRIC_PDF(A;X) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the PDF. // 0 <= X // // Input, double A, B, the parameters that define the PDF. // 0 <= A <= 1, // 0 < B. // // Output, double WEIBULL_DISCRETE_PDF, the value of the PDF. // { double pdf; if ( x < 0 ) { pdf = 0.0; } else { pdf = pow ( 1.0 - a , pow ( x, b ) ) - pow ( 1.0 - a, pow ( x + 1, b ) ); } return pdf; } //****************************************************************************80 int weibull_discrete_sample ( double a, double b, int &seed ) //****************************************************************************80 // // Purpose: // // WEIBULL_DISCRETE_SAMPLE samples the discrete Weibull PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 <= A <= 1.0, // 0.0 < B. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int WEIBULL_DISCRETE_SAMPLE, a sample of the PDF. // { double cdf; int x; cdf = r8_uniform_01 ( seed ); x = weibull_discrete_cdf_inv ( cdf, a, b ); return x; } //****************************************************************************80 double zeta ( double p ) //****************************************************************************80 // // Purpose: // // ZETA estimates the Riemann Zeta function. // // Discussion: // // For 1 < P, the Riemann Zeta function is defined as: // // ZETA ( P ) = Sum ( 1 <= N < Infinity ) 1 / N**P // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Reference: // // Daniel Zwillinger, editor, // CRC Standard Mathematical Tables and Formulae, // 30th Edition, // CRC Press, 1996. // // Parameters: // // Input, double P, the power to which the integers are raised. // P must be greater than 1. For integral P up to 20, a // precomputed value of ZETA is returned; otherwise the infinite // sum is approximated. // // Output, double ZETA, an approximation to the Riemann // Zeta function. // { int n; const double pi = 3.14159265358979323; double value; double zsum; double zsum_old; if ( p <= 1.0 ) { cout << " \n"; cout << "ZETA - Fatal error!\n"; cout << " Exponent P <= 1.0.\n"; exit ( 1 ); } else if ( p == 2.0 ) { value = pow ( pi, 2 ) / 6.0; } else if ( p == 3.0 ) { value = 1.2020569032; } else if ( p == 4.0 ) { value = pow ( pi, 4 ) / 90.0; } else if ( p == 5.0 ) { value = 1.0369277551; } else if ( p == 6.0 ) { value = pow ( pi, 6 ) / 945.0; } else if ( p == 7.0 ) { value = 1.0083492774; } else if ( p == 8.0 ) { value = pow ( pi, 8 ) / 9450.0; } else if ( p == 9.0 ) { value = 1.0020083928; } else if ( p == 10.0 ) { value = pow ( pi, 10 ) / 93555.0; } else if ( p == 11.0 ) { value = 1.0004941886; } else if ( p == 12.0 ) { value = 1.0002460866; } else if ( p == 13.0 ) { value = 1.0001227133; } else if ( p == 14.0 ) { value = 1.0000612482; } else if ( p == 15.0 ) { value = 1.0000305882; } else if ( p == 16.0 ) { value = 1.0000152823; } else if ( p == 17.0 ) { value = 1.0000076372; } else if ( p == 18.0 ) { value = 1.0000038173; } else if ( p == 19.0 ) { value = 1.0000019082; } else if ( p == 20.0 ) { value = 1.0000009540; } else { zsum = 0.0; n = 0; for ( ; ; ) { n = n + 1; zsum_old = zsum; zsum = zsum + 1.0 / pow ( ( double ) n, p ); if ( zsum <= zsum_old ) { break; } } value = zsum; } return value; } //****************************************************************************80 double zipf_cdf ( int x, double a ) //****************************************************************************80 // // Purpose: // // ZIPF_CDF evaluates the Zipf CDF. // // Discussion: // // Simple summation is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int X, the argument of the PDF. // 1 <= N // // Input, double A, the parameter of the PDF. // 1.0 < A. // // Output, double CDF, the value of the CDF. // { double c; double cdf; double pdf; int y; if ( x < 1 ) { cdf = 0.0; } else { c = zeta ( a ); cdf = 0.0; for ( y = 1; y <= x; y++ ) { pdf = 1.0 / pow ( y, a ) / c; cdf = cdf + pdf; } } return cdf; } //****************************************************************************80 bool zipf_check ( double a ) //****************************************************************************80 // // Purpose: // // ZIPF_CHECK checks the parameter of the Zipf PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 1.0 < A. // // Output, bool ZIPF_CHECK, is true if the parameters are legal. // { if ( a <= 1.0 ) { cout << " \n"; cout << "ZIPF_CHECK - Fatal error!\n"; cout << " A <= 1.\n"; return false; } return true; } //****************************************************************************80 double zipf_mean ( double a ) //****************************************************************************80 // // Purpose: // // ZIPF_MEAN returns the mean of the Zipf PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 1.0 < A. // // Output, double ZIPF_MEAN, the mean of the PDF. // The mean is only defined for 2 < A. // { double mean; if ( a <= 2.0 ) { cout << " \n"; cout << "ZIPF_MEAN - Fatal error!\n"; cout << " No mean defined for A <= 2.\n"; exit ( 1 ); } mean = zeta ( a - 1.0 ) / zeta ( a ); return mean; } //****************************************************************************80 double zipf_pdf ( int x, double a ) //****************************************************************************80 // // Purpose: // // ZIPF_PDF evaluates the Zipf PDF. // // Discussion: // // PDF(A;X) = ( 1 / X^A ) / C // // where the normalizing constant is chosen so that // // C = Sum ( 1 <= I < Infinity ) 1 / I^A. // // From observation, the frequency of different words in long // sequences of text seems to follow the Zipf PDF, with // parameter A slightly greater than 1. The Zipf PDF is sometimes // known as the "discrete Pareto" PDF. // // Lotka's law is a version of the Zipf PDF in which A is 2 or approximately // 2. Lotka's law describes the frequency of publications by authors in a // given field, and estimates that the number of authors with X papers is // about 1/X^A of the number of authors with 1 paper. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Reference: // // Alfred Lotka, // The frequency distribution of scientific productivity, // Journal of the Washington Academy of Sciences, // Volume 16, Number 12, 1926, pages 317-324. // // Parameters: // // Input, int X, the argument of the PDF. // 1 <= N // // Input, double A, the parameter of the PDF. // 1.0 < A. // // Output, double PDF, the value of the PDF. // { double pdf; if ( x < 1 ) { pdf = 0.0; } else { pdf = 1.0 / pow ( x, a ) / zeta ( a ); } return pdf; } //****************************************************************************80 int zipf_sample ( double a, int &seed ) //****************************************************************************80 // // Purpose: // // ZIPF_SAMPLE samples the Zipf PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Reference: // // Luc Devroye, // Non-Uniform Random Variate Generation, // Springer Verlag, 1986, pages 550-551. // // Parameters: // // Input, double A, the parameter of the PDF. // 1.0 < A. // // Input/output, int &SEED, a seed for the random number generator. // // Output, int ZIPF_SAMPLE, a sample of the PDF. // { double b; double t; double u; double v; double w; int x; b = pow ( 2.0, ( a - 1.0 ) ); for ( ; ; ) { u = r8_uniform_01 ( seed ); v = r8_uniform_01 ( seed ); w = ( int ) ( 1.0 / pow ( u, 1.0 / ( a - 1.0 ) ) ); t = pow ( ( w + 1.0 ) / w, a - 1.0 ); if ( v * w * ( t - 1.0 ) * b <= t * ( b - 1.0 ) ) { break; } } x = ( int ) w; return x; } //****************************************************************************80 double zipf_variance ( double a ) //****************************************************************************80 // // Purpose: // // ZIPF_VARIANCE returns the variance of the Zipf PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 October 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double A, the parameter of the PDF. // 1.0 < A. // // Output, double ZIPF_VARIANCE, the variance of the PDF. // The variance is only defined for 3 < A. // { double mean; double variance; if ( a <= 3.0 ) { cerr << " \n"; cerr << "ZIPF_VARIANCE - Fatal error!\n"; cerr << " No variance defined for A <= 3.0.\n"; exit ( 1 ); } mean = zipf_mean ( a ); variance = zeta ( a - 2.0 ) / zeta ( a ) - mean * mean; return variance; }