2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

Initial math-toolkit commit.

Includes all code and tests, but no docs yet.

[SVN r39792]
This commit is contained in:
John Maddock
2007-10-08 16:58:15 +00:00
569 changed files with 144381 additions and 1119 deletions

79
example/Jamfile.v2 Normal file
View File

@@ -0,0 +1,79 @@
# \math_toolkit\libs\math\example\jamfile.v2
# Runs statistics examples
# Copyright 2007 John Maddock and Paul A. Bristow.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# bring in the rules for testing
import testing ;
project
: requirements
<toolset>gcc:<cxxflags>-Wno-missing-braces
<toolset>darwin:<cxxflags>-Wno-missing-braces
<toolset>acc:<cxxflags>+W2068,2461,2236,4070
<toolset>intel:<cxxflags>-Qwd264,239
<toolset>msvc:<warnings>all
<toolset>msvc:<asynch-exceptions>on
<toolset>msvc:<cxxflags>/wd4996
<toolset>msvc:<cxxflags>/wd4512
<toolset>msvc:<cxxflags>/wd4610
<toolset>msvc:<cxxflags>/wd4510
<toolset>msvc:<cxxflags>/wd4127
<toolset>msvc:<cxxflags>/wd4701
<toolset>msvc:<cxxflags>/wd4127
<toolset>msvc:<cxxflags>/wd4305
<include>../../..
;
run binomial_confidence_limits.cpp ;
run binomial_example3.cpp ;
run binomial_sample_sizes.cpp ;
run binomial_example_nag.cpp ;
run c_error_policy_example.cpp ;
run chi_square_std_dev_test.cpp ;
run distribution_construction.cpp ;
run error_handling_example.cpp ;
run error_policies_example.cpp ;
run error_policy_example.cpp ;
run f_test.cpp ;
run neg_binom_confidence_limits.cpp ;
run neg_binomial_sample_sizes.cpp ;
# run negative_binomial_construction_examples.cpp ; delete for now
run negative_binomial_example1.cpp ;
run negative_binomial_example2.cpp ;
# run negative_binomial_example3.cpp ;
run policy_eg_1.cpp ;
run policy_eg_2.cpp ;
run policy_eg_3.cpp ;
run policy_eg_4.cpp ;
run policy_eg_5.cpp ;
run policy_eg_6.cpp ;
run policy_eg_7.cpp ;
run policy_eg_8.cpp ;
run policy_eg_9.cpp ;
run policy_eg_10.cpp ;
run policy_ref_snip1.cpp ;
run policy_ref_snip10.cpp ;
run policy_ref_snip11.cpp ;
run policy_ref_snip12.cpp ;
run policy_ref_snip13.cpp ;
run policy_ref_snip2.cpp ;
run policy_ref_snip3.cpp ;
run policy_ref_snip4.cpp ;
run policy_ref_snip5.cpp ;
run policy_ref_snip6.cpp ;
run policy_ref_snip7.cpp ;
run policy_ref_snip8.cpp ;
run policy_ref_snip9.cpp ;
#run statistics_functions_example1.cpp ;
run students_t_example1.cpp ;
run students_t_example2.cpp ;
run students_t_example3.cpp ;
run students_t_single_sample.cpp ;
run students_t_two_samples.cpp ;

View File

@@ -0,0 +1,237 @@
// Copyright Paul A. 2007
// Copyright John Maddock 2006
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Simple example of computing probabilities and quantiles for
// a Bernoulli random variable representing the flipping of a coin.
// http://mathworld.wolfram.com/CoinTossing.html
// http://en.wikipedia.org/wiki/Bernoulli_trial
// Weisstein, Eric W. "Dice." From MathWorld--A Wolfram Web Resource.
// http://mathworld.wolfram.com/Dice.html
// http://en.wikipedia.org/wiki/Bernoulli_distribution
// http://mathworld.wolfram.com/BernoulliDistribution.html
//
// An idealized coin consists of a circular disk of zero thickness which,
// when thrown in the air and allowed to fall, will rest with either side face up
// ("heads" H or "tails" T) with equal probability. A coin is therefore a two-sided die.
// Despite slight differences between the sides and nonzero thickness of actual coins,
// the distribution of their tosses makes a good approximation to a p==1/2 Bernoulli distribution.
//[binomial_coinflip_example1
/*`An example of a [@http://en.wikipedia.org/wiki/Bernoulli_process Bernoulli process]
is coin flipping.
A variable in such a sequence may be called a Bernoulli variable.
This example shows using the Binomial distribution to predict the probability
of heads and tails when throwing a coin.
The number of correct answers (say heads),
X, is distributed as a binomial random variable
with binomial distribution parameters number of trials (flips) n = 10 and probability (success_fraction) of getting a head p = 0.5 (a 'fair' coin).
(Our coin is assumed fair, but we could easily change the success_fraction parameter p
from 0.5 to some other value to simulate an unfair coin,
say 0.6 for one with chewing gum on the tail,
so it is more likely to fall tails down and heads up).
First we need some includes and using statements to be able to use the binomial distribution, some std input and output, and get started:
*/
#include <boost/math/distributions/binomial.hpp>
using boost::math::binomial;
#include <iostream>
using std::cout; using std::endl; using std::left;
#include <iomanip>
using std::setw;
int main()
{
cout << "Using Binomial distribution to predict how many heads and tails." << endl;
try
{
/*`
See note [link coinflip_eg_catch with the catch block]
about why a try and catch block is always a good idea.
First, construct a binomial distribution with parameters success_fraction
1/2, and how many flips.
*/
const double success_fraction = 0.5; // = 50% = 1/2 for a 'fair' coin.
int flips = 10;
binomial flip(flips, success_fraction);
cout.precision(4);
/*`
Then some examples of using Binomial moments (and echoing the parameters).
*/
cout << "From " << flips << " one can expect to get on average "
<< mean(flip) << " heads (or tails)." << endl;
cout << "Mode is " << mode(flip) << endl;
cout << "Standard deviation is " << standard_deviation(flip) << endl;
cout << "So about 2/3 will lie within 1 standard deviation and get between "
<< ceil(mean(flip) - standard_deviation(flip)) << " and "
<< floor(mean(flip) + standard_deviation(flip)) << " correct." << endl;
cout << "Skewness is " << skewness(flip) << endl;
// Skewness of binomial distributions is only zero (symmetrical)
// if success_fraction is exactly one half,
// for example, when flipping 'fair' coins.
cout << "Skewness if success_fraction is " << flip.success_fraction()
<< " is " << skewness(flip) << endl << endl; // Expect zero for a 'fair' coin.
/*`
Now we show a variety of predictions on the probability of heads:
*/
cout << "For " << flip.trials() << " coin flips: " << endl;
cout << "Probability of getting no heads is " << pdf(flip, 0) << endl;
cout << "Probability of getting at least one head is " << 1. - pdf(flip, 0) << endl;
/*`
When we want to calculate the probability for a range or values we can sum the PDF's:
*/
cout << "Probability of getting 0 or 1 heads is "
<< pdf(flip, 0) + pdf(flip, 1) << endl; // sum of exactly == probabilities
/*`
Or we can use the cdf.
*/
cout << "Probability of getting 0 or 1 (<= 1) heads is " << cdf(flip, 1) << endl;
cout << "Probability of getting 9 or 10 heads is " << pdf(flip, 9) + pdf(flip, 10) << endl;
/*`
Note that using
*/
cout << "Probability of getting 9 or 10 heads is " << 1. - cdf(flip, 8) << endl;
/*`
is less accurate than using the complement
*/
cout << "Probability of getting 9 or 10 heads is " << cdf(complement(flip, 8)) << endl;
/*`
Since the subtraction may involve
[@http://docs.sun.com/source/806-3568/ncg_goldberg.html cancellation error],
where as `cdf(complement(flip, 8))`
does not use such a subtraction internally, and so does not exhibit the problem.
To get the probability for a range of heads, we can either add the pdfs for each number of heads
*/
cout << "Probability of between 4 and 6 heads (4 or 5 or 6) is "
// P(X == 4) + P(X == 5) + P(X == 6)
<< pdf(flip, 4) + pdf(flip, 5) + pdf(flip, 6) << endl;
/*`
But this is probably less efficient than using the cdf
*/
cout << "Probability of between 4 and 6 heads (4 or 5 or 6) is "
// P(X <= 6) - P(X <= 3) == P(X < 4)
<< cdf(flip, 6) - cdf(flip, 3) << endl;
/*`
Certainly for a bigger range like, 3 to 7
*/
cout << "Probability of between 3 and 7 heads (3, 4, 5, 6 or 7) is "
// P(X <= 7) - P(X <= 2) == P(X < 3)
<< cdf(flip, 7) - cdf(flip, 2) << endl;
cout << endl;
/*`
Finally, print two tables of probability for the /exactly/ and /at least/ a number of heads.
*/
// Print a table of probability for the exactly a number of heads.
cout << "Probability of getting exactly (==) heads" << endl;
for (int successes = 0; successes <= flips; successes++)
{ // Say success means getting a head (or equally success means getting a tail).
double probability = pdf(flip, successes);
cout << left << setw(2) << successes << " " << setw(10)
<< probability << " or 1 in " << 1. / probability
<< ", or " << probability * 100. << "%" << endl;
} // for i
cout << endl;
// Tabulate the probability of getting between zero heads and 0 upto 10 heads.
cout << "Probability of getting upto (<=) heads" << endl;
for (int successes = 0; successes <= flips; successes++)
{ // Say success means getting a head
// (equally success could mean getting a tail).
double probability = cdf(flip, successes); // P(X <= heads)
cout << setw(2) << successes << " " << setw(10) << left
<< probability << " or 1 in " << 1. / probability << ", or "
<< probability * 100. << "%"<< endl;
} // for i
/*`
The last (0 to 10 heads) must, of course, be 100% probability.
*/
}
catch(const std::exception& e)
{
//
/*`
[#coinflip_eg_catch]
It is always essential to include try & catch blocks because
default policies are to throw exceptions on arguments that
are out of domain or cause errors like numeric-overflow.
Lacking try & catch blocks, the program will abort, whereas the
message below from the thrown exception will give some helpful
clues as to the cause of the problem.
*/
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
//] [binomial_coinflip_example1]
return 0;
} // int main()
// Output:
//[binomial_coinflip_example_output
/*`
[pre
Using Binomial distribution to predict how many heads and tails.
From 10 one can expect to get on average 5 heads (or tails).
Mode is 5
Standard deviation is 1.581
So about 2/3 will lie within 1 standard deviation and get between 4 and 6 correct.
Skewness is 0
Skewness if success_fraction is 0.5 is 0
For 10 coin flips:
Probability of getting no heads is 0.0009766
Probability of getting at least one head is 0.999
Probability of getting 0 or 1 heads is 0.01074
Probability of getting 0 or 1 (<= 1) heads is 0.01074
Probability of getting 9 or 10 heads is 0.01074
Probability of getting 9 or 10 heads is 0.01074
Probability of getting 9 or 10 heads is 0.01074
Probability of between 4 and 6 heads (4 or 5 or 6) is 0.6562
Probability of between 4 and 6 heads (4 or 5 or 6) is 0.6563
Probability of between 3 and 7 heads (3, 4, 5, 6 or 7) is 0.8906
Probability of getting exactly (==) heads
0 0.0009766 or 1 in 1024, or 0.09766%
1 0.009766 or 1 in 102.4, or 0.9766%
2 0.04395 or 1 in 22.76, or 4.395%
3 0.1172 or 1 in 8.533, or 11.72%
4 0.2051 or 1 in 4.876, or 20.51%
5 0.2461 or 1 in 4.063, or 24.61%
6 0.2051 or 1 in 4.876, or 20.51%
7 0.1172 or 1 in 8.533, or 11.72%
8 0.04395 or 1 in 22.76, or 4.395%
9 0.009766 or 1 in 102.4, or 0.9766%
10 0.0009766 or 1 in 1024, or 0.09766%
Probability of getting upto (<=) heads
0 0.0009766 or 1 in 1024, or 0.09766%
1 0.01074 or 1 in 93.09, or 1.074%
2 0.05469 or 1 in 18.29, or 5.469%
3 0.1719 or 1 in 5.818, or 17.19%
4 0.377 or 1 in 2.653, or 37.7%
5 0.623 or 1 in 1.605, or 62.3%
6 0.8281 or 1 in 1.208, or 82.81%
7 0.9453 or 1 in 1.058, or 94.53%
8 0.9893 or 1 in 1.011, or 98.93%
9 0.999 or 1 in 1.001, or 99.9%
10 1 or 1 in 1, or 100%
]
*/
//][/binomial_coinflip_example_output]

View File

@@ -0,0 +1,159 @@
// Copyright John Maddock 2006
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifdef _MSC_VER
# pragma warning(disable: 4512) // assignment operator could not be generated.
# pragma warning(disable: 4510) // default constructor could not be generated.
# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required.
#endif
#include <iostream>
#include <iomanip>
#include <boost/math/distributions/binomial.hpp>
void confidence_limits_on_frequency(unsigned trials, unsigned successes)
{
//
// trials = Total number of trials.
// successes = Total number of observed successes.
//
// Calculate confidence limits for an observed
// frequency of occurrence that follows a binomial
// distribution.
//
using namespace std;
using namespace boost::math;
// Print out general info:
cout <<
"___________________________________________\n"
"2-Sided Confidence Limits For Success Ratio\n"
"___________________________________________\n\n";
cout << setprecision(7);
cout << setw(40) << left << "Number of Observations" << "= " << trials << "\n";
cout << setw(40) << left << "Number of successes" << "= " << successes << "\n";
cout << setw(40) << left << "Sample frequency of occurrence" << "= " << double(successes) / trials << "\n";
//
// Define a table of significance levels:
//
double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
//
// Print table header:
//
cout << "\n\n"
"_______________________________________________________________________\n"
"Confidence Lower CP Upper CP Lower JP Upper JP\n"
" Value (%) Limit Limit Limit Limit\n"
"_______________________________________________________________________\n";
//
// Now print out the data for the table rows.
//
for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
{
// Confidence value:
cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]);
// Calculate Clopper Pearson bounds:
double l = binomial_distribution<>::find_lower_bound_on_p(trials, successes, alpha[i]/2);
double u = binomial_distribution<>::find_upper_bound_on_p(trials, successes, alpha[i]/2);
// Print Clopper Pearson Limits:
cout << fixed << setprecision(5) << setw(15) << right << l;
cout << fixed << setprecision(5) << setw(15) << right << u;
// Calculate Jeffreys Prior Bounds:
l = binomial_distribution<>::find_lower_bound_on_p(trials, successes, alpha[i]/2, binomial_distribution<>::jeffreys_prior_interval);
u = binomial_distribution<>::find_upper_bound_on_p(trials, successes, alpha[i]/2, binomial_distribution<>::jeffreys_prior_interval);
// Print Jeffreys Prior Limits:
cout << fixed << setprecision(5) << setw(15) << right << l;
cout << fixed << setprecision(5) << setw(15) << right << u << std::endl;
}
cout << endl;
} // void confidence_limits_on_frequency()
int main()
{
confidence_limits_on_frequency(20, 4);
confidence_limits_on_frequency(200, 40);
confidence_limits_on_frequency(2000, 400);
return 0;
} // int main()
/*
------ Build started: Project: binomial_confidence_limits, Configuration: Debug Win32 ------
Compiling...
binomial_confidence_limits.cpp
Linking...
Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\binomial_confidence_limits.exe"
___________________________________________
2-Sided Confidence Limits For Success Ratio
___________________________________________
Number of Observations = 20
Number of successes = 4
Sample frequency of occurrence = 0.2
_______________________________________________________________________
Confidence Lower CP Upper CP Lower JP Upper JP
Value (%) Limit Limit Limit Limit
_______________________________________________________________________
50.000 0.12840 0.29588 0.14974 0.26916
75.000 0.09775 0.34633 0.11653 0.31861
90.000 0.07135 0.40103 0.08734 0.37274
95.000 0.05733 0.43661 0.07152 0.40823
99.000 0.03576 0.50661 0.04655 0.47859
99.900 0.01905 0.58632 0.02634 0.55960
99.990 0.01042 0.64997 0.01530 0.62495
99.999 0.00577 0.70216 0.00901 0.67897
___________________________________________
2-Sided Confidence Limits For Success Ratio
___________________________________________
Number of Observations = 200
Number of successes = 40
Sample frequency of occurrence = 0.2000000
_______________________________________________________________________
Confidence Lower CP Upper CP Lower JP Upper JP
Value (%) Limit Limit Limit Limit
_______________________________________________________________________
50.000 0.17949 0.22259 0.18190 0.22001
75.000 0.16701 0.23693 0.16934 0.23429
90.000 0.15455 0.25225 0.15681 0.24956
95.000 0.14689 0.26223 0.14910 0.25951
99.000 0.13257 0.28218 0.13468 0.27940
99.900 0.11703 0.30601 0.11902 0.30318
99.990 0.10489 0.32652 0.10677 0.32366
99.999 0.09492 0.34485 0.09670 0.34197
___________________________________________
2-Sided Confidence Limits For Success Ratio
___________________________________________
Number of Observations = 2000
Number of successes = 400
Sample frequency of occurrence = 0.2000000
_______________________________________________________________________
Confidence Lower CP Upper CP Lower JP Upper JP
Value (%) Limit Limit Limit Limit
_______________________________________________________________________
50.000 0.19382 0.20638 0.19406 0.20613
75.000 0.18965 0.21072 0.18990 0.21047
90.000 0.18537 0.21528 0.18561 0.21503
95.000 0.18267 0.21821 0.18291 0.21796
99.000 0.17745 0.22400 0.17769 0.22374
99.900 0.17150 0.23079 0.17173 0.23053
99.990 0.16658 0.23657 0.16681 0.23631
99.999 0.16233 0.24169 0.16256 0.24143
*/

View File

@@ -0,0 +1,91 @@
// Copyright Paul A. 2006
// Copyright John Maddock 2006
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Simple example of computing probabilities for a binomial random variable.
// Replication of source nag_binomial_dist (g01bjc).
// Shows how to replace NAG C library calls by Boost Math Toolkit C++ calls.
#ifdef _MSC_VER
# pragma warning(disable: 4512) // assignment operator could not be generated.
# pragma warning(disable: 4510) // default constructor could not be generated.
# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required.
#endif
#include <iostream>
using std::cout;
using std::endl;
using std::ios;
using std::showpoint;
#include <iomanip>
using std::fixed;
using std::setw;
#include <boost/math/distributions/binomial.hpp>
int main()
{
cout << "Example 3 of using the binomial distribution to replicate a NAG library call." << endl;
using boost::math::binomial_distribution;
// This replicates the computation of the examples of using nag-binomial_dist
// using g01bjc in section g01 Sample Calculations on Statistical Data.
// http://www.nag.co.uk/numeric/cl/manual/pdf/G01/g01bjc.pdf
// Program results section 8.3 page 3.g01bjc.3
//8.2. Program Data
//g01bjc Example Program Data
//4 0.50 2 : n, p, k
//19 0.44 13
//100 0.75 67
//2000 0.33 700
//8.3. Program Results
//g01bjc Example Program Results
//n p k plek pgtk peqk
//4 0.500 2 0.68750 0.31250 0.37500
//19 0.440 13 0.99138 0.00862 0.01939
//100 0.750 67 0.04460 0.95540 0.01700
//2000 0.330 700 0.97251 0.02749 0.00312
cout.setf(ios::showpoint); // Trailing zeros to show significant decimal digits.
cout.precision(5); // Should be able to calculate this?
cout << fixed;
// Binomial distribution.
// Note that cdf(dist, k) is equivalent to NAG library plek probability of <= k
// cdf(complement(dist, k)) is equivalent to NAG library pgtk probability of > k
// pdf(dist, k) is equivalent to NAG library peqk probability of == k
cout << " n p k plek pgtk peqk " << endl;
binomial_distribution<>my_dist(4, 0.5);
cout << setw(4) << (int)my_dist.trials() << " " << my_dist.success_fraction() << " "<< 2 << " "
<< cdf(my_dist, 2) << " " << cdf(complement(my_dist, 2)) << " " << pdf(my_dist, 2) << endl;
binomial_distribution<>two(19, 0.440);
cout << setw(4) << (int)two.trials() << " " << two.success_fraction() << " " << 13 << " "
<< cdf(two, 13) << " " << cdf(complement(two, 13)) << " " << pdf(two, 13) << endl;
binomial_distribution<>three(100, 0.750);
cout << setw(4) << (int)three.trials() << " " << three.success_fraction() << " " << 67 << " "
<< cdf(three, 67) << " " << cdf(complement(three, 67)) << " " << pdf(three, 67) << endl;
binomial_distribution<>four(2000, 0.330);
cout << setw(4) << (int)four.trials() << " " << four.success_fraction() << " " << 700 << " "
<< cdf(four, 700) << " " << cdf(complement(four, 700)) << " " << pdf(four, 700) << endl;
return 0;
} // int main()
/*
Autorun "i:\boost-sandbox\math_toolkit\libs\math\test\msvc80\debug\binomial_example3.exe"
Example 3 of using the binomial distribution.
n p k plek pgtk peqk
4 0.50000 2 0.68750 0.31250 0.37500
19 0.44000 13 0.99138 0.00862 0.01939
100 0.75000 67 0.04460 0.95540 0.01700
2000 0.33000 700 0.97251 0.02749 0.00312
*/

View File

@@ -0,0 +1,91 @@
// Copyright Paul A. 2007
// Copyright John Maddock 2007
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Simple example of computing probabilities for a binomial random variable.
// Replication of source nag_binomial_dist (g01bjc).
// Shows how to replace NAG C library calls by Boost Math Toolkit C++ calls.
// Note that the default policy does not replicate the way that NAG
// library calls handle 'bad' arguments, but you can define policies that do,
// as well as other policies that may suit your application even better.
// See the examples of changing default policies for details.
#include <boost/math/distributions/binomial.hpp>
#include <iostream>
using std::cout; using std::endl; using std::ios; using std::showpoint;
#include <iomanip>
using std::fixed; using std::setw;
int main()
{
cout << "Using the binomial distribution to replicate a NAG library call." << endl;
using boost::math::binomial_distribution;
// This replicates the computation of the examples of using nag-binomial_dist
// using g01bjc in section g01 Somple Calculations on Statistical Data.
// http://www.nag.co.uk/numeric/cl/manual/pdf/G01/g01bjc.pdf
// Program results section 8.3 page 3.g01bjc.3
//8.2. Program Data
//g01bjc Example Program Data
//4 0.50 2 : n, p, k
//19 0.44 13
//100 0.75 67
//2000 0.33 700
//8.3. Program Results
//g01bjc Example Program Results
//n p k plek pgtk peqk
//4 0.500 2 0.68750 0.31250 0.37500
//19 0.440 13 0.99138 0.00862 0.01939
//100 0.750 67 0.04460 0.95540 0.01700
//2000 0.330 700 0.97251 0.02749 0.00312
cout.setf(ios::showpoint); // Trailing zeros to show significant decimal digits.
cout.precision(5); // Might calculate this from trials in distribution?
cout << fixed;
// Binomial distribution.
// Note that cdf(dist, k) is equivalent to NAG library plek probability of <= k
// cdf(complement(dist, k)) is equivalent to NAG library pgtk probability of > k
// pdf(dist, k) is equivalent to NAG library peqk probability of == k
cout << " n p k plek pgtk peqk " << endl;
binomial_distribution<>my_dist(4, 0.5);
cout << setw(4) << (int)my_dist.trials() << " " << my_dist.success_fraction()
<< " " << 2 << " " << cdf(my_dist, 2) << " "
<< cdf(complement(my_dist, 2)) << " " << pdf(my_dist, 2) << endl;
binomial_distribution<>two(19, 0.440);
cout << setw(4) << (int)two.trials() << " " << two.success_fraction()
<< " " << 13 << " " << cdf(two, 13) << " "
<< cdf(complement(two, 13)) << " " << pdf(two, 13) << endl;
binomial_distribution<>three(100, 0.750);
cout << setw(4) << (int)three.trials() << " " << three.success_fraction()
<< " " << 67 << " " << cdf(three, 67) << " " << cdf(complement(three, 67))
<< " " << pdf(three, 67) << endl;
binomial_distribution<>four(2000, 0.330);
cout << setw(4) << (int)four.trials() << " " << four.success_fraction()
<< " " << 700 << " "
<< cdf(four, 700) << " " << cdf(complement(four, 700))
<< " " << pdf(four, 700) << endl;
return 0;
} // int main()
/*
Example of using the binomial distribution to replicate a NAG library call.
n p k plek pgtk peqk
4 0.50000 2 0.68750 0.31250 0.37500
19 0.44000 13 0.99138 0.00862 0.01939
100 0.75000 67 0.04460 0.95540 0.01700
2000 0.33000 700 0.97251 0.02749 0.00312
*/

View File

@@ -0,0 +1,520 @@
// Copyright Paul A. Bristow 2007
// Copyright John Maddock 2006
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// binomial_examples_quiz.cpp
// Simple example of computing probabilities and quantiles for a binomial random variable
// representing the correct guesses on a multiple-choice test.
// source http://www.stat.wvu.edu/SRS/Modules/Binomial/test.html
//[binomial_quiz_example1
/*`
A multiple choice test has four possible answers to each of 16 questions.
A student guesses the answer to each question,
so the probability of getting a correct answer on any given question is
one in four, a quarter, 1/4, 25% or fraction 0.25.
The conditions of the binomial experiment are assumed to be met:
n = 16 questions constitute the trials;
each question results in one of two possible outcomes (correct or incorrect);
the probability of being correct is 0.25 and is constant if no knowledge about the subject is assumed;
the questions are answered independently if the student's answer to a question
in no way influences his/her answer to another question.
First, we need to be able to use the binomial distribution constructor
(and some std input/output, of course).
*/
#include <boost/math/distributions/binomial.hpp>
using boost::math::binomial;
#include <iostream>
using std::cout; using std::endl;
using std::ios; using std::flush; using std::left; using std::right; using std::fixed;
#include <iomanip>
using std::setw; using std::setprecision;
//][/binomial_quiz_example1]
int main()
{
try
{
cout << "Binomial distribution example - guessing in a quiz." << endl;
//[binomial_quiz_example2
/*`
The number of correct answers, X, is distributed as a binomial random variable
with binomial distribution parameters: questions n = 16 and success fraction probability p = 0.25.
So we construct a binomial distribution:
*/
int questions = 16; // All the questions in the quiz.
int answers = 4; // Possible answers to each question.
double success_fraction = (double)answers / (double)questions; // If a random guess.
// Caution: = answers / questions would be zero (because they are integers)!
binomial quiz(questions, success_fraction);
/*`
and display the distribution parameters we used thus:
*/
cout << "In a quiz with " << quiz.trials()
<< " questions and with a probability of guessing right of "
<< quiz.success_fraction() * 100 << " %"
<< " or 1 in " << static_cast<int>(1. / quiz.success_fraction()) << endl;
/*`
Show a few probabilities of just guessing:
*/
cout << "Probability of getting none right is " << pdf(quiz, 0) << endl; // 0.010023
cout << "Probability of getting exactly one right is " << pdf(quiz, 1) << endl;
cout << "Probability of getting exactly two right is " << pdf(quiz, 2) << endl;
int pass_score = 11;
cout << "Probability of getting exactly " << pass_score << " answers right by chance is "
<< pdf(quiz, questions) << endl;
/*`
[pre
Probability of getting none right is 0.0100226
Probability of getting exactly one right is 0.0534538
Probability of getting exactly two right is 0.133635
Probability of getting exactly 11 answers right by chance is 2.32831e-010
]
These don't give any encouragement to guessers!
We can tabulate the 'getting exactly right' ( == ) probabilities thus:
*/
cout << "\n" "Guessed Probability" << right << endl;
for (int successes = 0; successes <= questions; successes++)
{
double probability = pdf(quiz, successes);
cout << setw(2) << successes << " " << probability << endl;
}
cout << endl;
/*`
[pre
Guessed Probability
0 0.0100226
1 0.0534538
2 0.133635
3 0.207876
4 0.225199
5 0.180159
6 0.110097
7 0.0524273
8 0.0196602
9 0.00582526
10 0.00135923
11 0.000247132
12 3.43239e-005
13 3.5204e-006
14 2.51457e-007
15 1.11759e-008
16 2.32831e-010
]
Then we can add the probabilities of some 'exactly right' like this:
*/
cout << "Probability of getting none or one right is " << pdf(quiz, 0) + pdf(quiz, 1) << endl;
/*`
[pre
Probability of getting none or one right is 0.0634764
]
But if more than a couple of scores are involved, it is more convenient (and may be more accurate)
to use the Cumulative Distribution Function (cdf) instead:
*/
cout << "Probability of getting none or one right is " << cdf(quiz, 1) << endl;
/*`
[pre
Probability of getting none or one right is 0.0634764
]
Since the cdf is inclusive, we can get the probability of getting up to 10 right ( <= )
*/
cout << "Probability of getting <= 10 right (to fail) is " << cdf(quiz, 10) << endl;
/*`
[pre
Probability of getting <= 10 right (to fail) is 0.999715
]
To get the probability of getting 11 or more right (to pass),
it is tempting to use ``1 - cdf(quiz, 10)`` to get the probability of > 10
*/
cout << "Probability of getting > 10 right (to pass) is " << 1 - cdf(quiz, 10) << endl;
/*`
[pre
Probability of getting > 10 right (to pass) is 0.000285239
]
But this should be resisted in favor of using the complement function. [link why_complements Why complements?]
*/
cout << "Probability of getting > 10 right (to pass) is " << cdf(complement(quiz, 10)) << endl;
/*`
[pre
Probability of getting > 10 right (to pass) is 0.000285239
]
And we can check that these two, <= 10 and > 10, add up to unity.
*/
BOOST_ASSERT((cdf(quiz, 10) + cdf(complement(quiz, 10))) == 1.);
/*`
If we want a < rather than a <= test, because the CDF is inclusive, we must subtract one from the score.
*/
cout << "Probability of getting less than " << pass_score
<< " (< " << pass_score << ") answers right by guessing is "
<< cdf(quiz, pass_score -1) << endl;
/*`
[pre
Probability of getting less than 11 (< 11) answers right by guessing is 0.999715
]
and similarly to get a >= rather than a > test
we also need to subtract one from the score (and can again check the sum is unity).
This is because if the cdf is /inclusive/,
then its complement must be /exclusive/ otherwise there would be one possible
outcome counted twice!
*/
cout << "Probability of getting at least " << pass_score
<< "(>= " << pass_score << ") answers right by guessing is "
<< cdf(complement(quiz, pass_score-1))
<< ", only 1 in " << 1/cdf(complement(quiz, pass_score-1)) << endl;
BOOST_ASSERT((cdf(quiz, pass_score -1) + cdf(complement(quiz, pass_score-1))) == 1);
/*`
[pre
Probability of getting at least 11 (>= 11) answers right by guessing is 0.000285239, only 1 in 3505.83
]
Finally we can tabulate some probabilities:
*/
cout << "\n" "At most (<=)""\n""Guessed OK Probability" << right << endl;
for (int score = 0; score <= questions; score++)
{
cout << setw(2) << score << " " << setprecision(10)
<< cdf(quiz, score) << endl;
}
cout << endl;
/*`
[pre
At most (<=)
Guessed OK Probability
0 0.01002259576
1 0.0634764398
2 0.1971110499
3 0.4049871101
4 0.6301861752
5 0.8103454274
6 0.9204427481
7 0.9728700437
8 0.9925302796
9 0.9983555346
10 0.9997147608
11 0.9999618928
12 0.9999962167
13 0.9999997371
14 0.9999999886
15 0.9999999998
16 1
]
*/
cout << "\n" "At least (>)""\n""Guessed OK Probability" << right << endl;
for (int score = 0; score <= questions; score++)
{
cout << setw(2) << score << " " << setprecision(10)
<< cdf(complement(quiz, score)) << endl;
}
/*`
[pre
At least (>)
Guessed OK Probability
0 0.9899774042
1 0.9365235602
2 0.8028889501
3 0.5950128899
4 0.3698138248
5 0.1896545726
6 0.07955725188
7 0.02712995629
8 0.00746972044
9 0.001644465374
10 0.0002852391917
11 3.810715862e-005
12 3.783265129e-006
13 2.628657967e-007
14 1.140870154e-008
15 2.328306437e-010
16 0
]
We now consider the probabilities of *ranges* of correct guesses.
First, calculate the probability of getting a range of guesses right,
by adding the exact probabilities of each from low ... high.
*/
int low = 3; // Getting at least 3 right.
int high = 5; // Getting as most 5 right.
double sum = 0.;
for (int i = low; i <= high; i++)
{
sum += pdf(quiz, i);
}
cout.precision(4);
cout << "Probability of getting between "
<< low << " and " << high << " answers right by guessing is "
<< sum << endl; // 0.61323
/*`
[pre
Probability of getting between 3 and 5 answers right by guessing is 0.6132
]
Or, usually better, we can use the difference of cdfs instead:
*/
cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is "
<< cdf(quiz, high) - cdf(quiz, low - 1) << endl; // 0.61323
/*`
[pre
Probability of getting between 3 and 5 answers right by guessing is 0.6132
]
And we can also try a few more combinations of high and low choices:
*/
low = 1; high = 6;
cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is "
<< cdf(quiz, high) - cdf(quiz, low - 1) << endl; // 1 and 6 P= 0.91042
low = 1; high = 8;
cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is "
<< cdf(quiz, high) - cdf(quiz, low - 1) << endl; // 1 <= x 8 P = 0.9825
low = 4; high = 4;
cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is "
<< cdf(quiz, high) - cdf(quiz, low - 1) << endl; // 4 <= x 4 P = 0.22520
/*`
[pre
Probability of getting between 1 and 6 answers right by guessing is 0.9104
Probability of getting between 1 and 8 answers right by guessing is 0.9825
Probability of getting between 4 and 4 answers right by guessing is 0.2252
]
[h4 Using Binomial distribution moments]
Using moments of the distribution, we can say more about the spread of results from guessing.
*/
cout << "By guessing, on average, one can expect to get " << mean(quiz) << " correct answers." << endl;
cout << "Standard deviation is " << standard_deviation(quiz) << endl;
cout << "So about 2/3 will lie within 1 standard deviation and get between "
<< ceil(mean(quiz) - standard_deviation(quiz)) << " and "
<< floor(mean(quiz) + standard_deviation(quiz)) << " correct." << endl;
cout << "Mode (the most frequent) is " << mode(quiz) << endl;
cout << "Skewness is " << skewness(quiz) << endl;
/*`
[pre
By guessing, on average, one can expect to get 4 correct answers.
Standard deviation is 1.732
So about 2/3 will lie within 1 standard deviation and get between 3 and 5 correct.
Mode (the most frequent) is 4
Skewness is 0.2887
]
[h4 Quantiles]
The quantiles (percentiles or percentage points) for a few probability levels:
*/
cout << "Quartiles " << quantile(quiz, 0.25) << " to "
<< quantile(complement(quiz, 0.25)) << endl; // Quartiles
cout << "1 standard deviation " << quantile(quiz, 0.33) << " to "
<< quantile(quiz, 0.67) << endl; // 1 sd
cout << "Deciles " << quantile(quiz, 0.1) << " to "
<< quantile(complement(quiz, 0.1))<< endl; // Deciles
cout << "5 to 95% " << quantile(quiz, 0.05) << " to "
<< quantile(complement(quiz, 0.05))<< endl; // 5 to 95%
cout << "2.5 to 97.5% " << quantile(quiz, 0.025) << " to "
<< quantile(complement(quiz, 0.025)) << endl; // 2.5 to 97.5%
cout << "2 to 98% " << quantile(quiz, 0.02) << " to "
<< quantile(complement(quiz, 0.02)) << endl; // 2 to 98%
cout << "If guessing then percentiles 1 to 99% will get " << quantile(quiz, 0.01)
<< " to " << quantile(complement(quiz, 0.01)) << " right." << endl;
/*`
Notice that these output integral values because the default policy is `integer_round_outwards`.
[pre
Quartiles 2 to 5
1 standard deviation 2 to 5
Deciles 1 to 6
5 to 95% 0 to 7
2.5 to 97.5% 0 to 8
2 to 98% 0 to 8
]
*/
//] [/binomial_quiz_example2]
//[discrete_quantile_real
/*`
Quantiles values are controlled by the
[link math_toolkit.policy.pol_ref.discrete_quant_ref discrete quantile policy]
chosen.
The default is `integer_round_outwards`,
so the lower quantile is rounded down, and the upper quantile is rounded up.
But we might believe that the real values tell us a little more - see
[link math_toolkit.policy.pol_tutorial.understand_dis_quant Understanding Discrete Quantile Policy].
We could control the policy for *all* distributions by
#define BOOST_MATH_DISCRETE_QUANTILE_POLICY real
at the head of the program would make this policy apply
to this *one, and only*, translation unit.
Or we can now create a (typedef for) policy that has discrete quantiles real
(here avoiding any 'using namespaces ...' statements):
*/
using boost::math::policies::policy;
using boost::math::policies::discrete_quantile;
using boost::math::policies::real;
using boost::math::policies::integer_round_outwards; // Default.
typedef boost::math::policies::policy<discrete_quantile<real> > real_quantile_policy;
/*`
Add a custom binomial distribution called ``real_quantile_binomial`` that uses ``real_quantile_policy``
*/
using boost::math::binomial_distribution;
typedef binomial_distribution<double, real_quantile_policy> real_quantile_binomial;
/*`
Construct an object of this custom distribution:
*/
real_quantile_binomial quiz_real(questions, success_fraction);
/*`
And use this to show some quantiles - that now have real rather than integer values.
*/
cout << "Quartiles " << quantile(quiz, 0.25) << " to "
<< quantile(complement(quiz_real, 0.25)) << endl; // Quartiles 2 to 4.6212
cout << "1 standard deviation " << quantile(quiz_real, 0.33) << " to "
<< quantile(quiz_real, 0.67) << endl; // 1 sd 2.6654 4.194
cout << "Deciles " << quantile(quiz_real, 0.1) << " to "
<< quantile(complement(quiz_real, 0.1))<< endl; // Deciles 1.3487 5.7583
cout << "5 to 95% " << quantile(quiz_real, 0.05) << " to "
<< quantile(complement(quiz_real, 0.05))<< endl; // 5 to 95% 0.83739 6.4559
cout << "2.5 to 97.5% " << quantile(quiz_real, 0.025) << " to "
<< quantile(complement(quiz_real, 0.025)) << endl; // 2.5 to 97.5% 0.42806 7.0688
cout << "2 to 98% " << quantile(quiz_real, 0.02) << " to "
<< quantile(complement(quiz_real, 0.02)) << endl; // 2 to 98% 0.31311 7.7880
cout << "If guessing, then percentiles 1 to 99% will get " << quantile(quiz_real, 0.01)
<< " to " << quantile(complement(quiz_real, 0.01)) << " right." << endl;
/*`
[pre
Real Quantiles
Quartiles 2 to 4.621
1 standard deviation 2.665 to 4.194
Deciles 1.349 to 5.758
5 to 95% 0.8374 to 6.456
2.5 to 97.5% 0.4281 to 7.069
2 to 98% 0.3131 to 7.252
If guessing then percentiles 1 to 99% will get 0 to 7.788 right.
]
*/
//] [/discrete_quantile_real]
}
catch(const std::exception& e)
{ // Always useful to include try & catch blocks because
// default policies are to throw exceptions on arguments that cause
// errors like underflow, overflow.
// Lacking try & catch blocks, the program will abort without a message below,
// which may give some helpful clues as to the cause of the exception.
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
return 0;
} // int main()
/*
Output is:
Binomial distribution example - guessing in a quiz.
In a quiz with 16 questions and with a probability of guessing right of 25 % or 1 in 4
Probability of getting none right is 0.0100226
Probability of getting exactly one right is 0.0534538
Probability of getting exactly two right is 0.133635
Probability of getting exactly 11 answers right by chance is 2.32831e-010
Guessed Probability
0 0.0100226
1 0.0534538
2 0.133635
3 0.207876
4 0.225199
5 0.180159
6 0.110097
7 0.0524273
8 0.0196602
9 0.00582526
10 0.00135923
11 0.000247132
12 3.43239e-005
13 3.5204e-006
14 2.51457e-007
15 1.11759e-008
16 2.32831e-010
Probability of getting none or one right is 0.0634764
Probability of getting none or one right is 0.0634764
Probability of getting <= 10 right (to fail) is 0.999715
Probability of getting > 10 right (to pass) is 0.000285239
Probability of getting > 10 right (to pass) is 0.000285239
Probability of getting less than 11 (< 11) answers right by guessing is 0.999715
Probability of getting at least 11(>= 11) answers right by guessing is 0.000285239, only 1 in 3505.83
At most (<=)
Guessed OK Probability
0 0.01002259576
1 0.0634764398
2 0.1971110499
3 0.4049871101
4 0.6301861752
5 0.8103454274
6 0.9204427481
7 0.9728700437
8 0.9925302796
9 0.9983555346
10 0.9997147608
11 0.9999618928
12 0.9999962167
13 0.9999997371
14 0.9999999886
15 0.9999999998
16 1
At least (>=)
Guessed OK Probability
0 0.9899774042
1 0.9365235602
2 0.8028889501
3 0.5950128899
4 0.3698138248
5 0.1896545726
6 0.07955725188
7 0.02712995629
8 0.00746972044
9 0.001644465374
10 0.0002852391917
11 3.810715862e-005
12 3.783265129e-006
13 2.628657967e-007
14 1.140870154e-008
15 2.328306437e-010
16 0
Probability of getting between 3 and 5 answers right by guessing is 0.6132
Probability of getting between 3 and 5 answers right by guessing is 0.6132
Probability of getting between 1 and 6 answers right by guessing is 0.9104
Probability of getting between 1 and 8 answers right by guessing is 0.9825
Probability of getting between 4 and 4 answers right by guessing is 0.2252
By guessing, on average, one can expect to get 4 correct answers.
Standard deviation is 1.732
So about 2/3 will lie within 1 standard deviation and get between 3 and 5 correct.
Mode (the most frequent) is 4
Skewness is 0.2887
Quartiles 2 to 5
1 standard deviation 2 to 5
Deciles 1 to 6
5 to 95% 0 to 7
2.5 to 97.5% 0 to 8
2 to 98% 0 to 8
If guessing then percentiles 1 to 99% will get 0 to 8 right.
Quartiles 2 to 4.621
1 standard deviation 2.665 to 4.194
Deciles 1.349 to 5.758
5 to 95% 0.8374 to 6.456
2.5 to 97.5% 0.4281 to 7.069
2 to 98% 0.3131 to 7.252
If guessing, then percentiles 1 to 99% will get 0 to 7.788 right.
*/

View File

@@ -0,0 +1,76 @@
// (C) Copyright John Maddock 2006
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifdef _MSC_VER
# pragma warning(disable: 4512) // assignment operator could not be generated.
# pragma warning(disable: 4510) // default constructor could not be generated.
# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required.
#endif
#include <iostream>
#include <iomanip>
#include <boost/math/distributions/binomial.hpp>
void find_max_sample_size(double p, unsigned successes)
{
//
// p = success ratio.
// successes = Total number of observed successes.
//
// Calculate how many trials we can have to ensure the
// maximum number of successes does not exceed "successes".
// A typical use would be failure analysis, where you want
// zero or fewer "successes" with some probability.
//
using namespace std;
using namespace boost::math;
// Print out general info:
cout <<
"________________________\n"
"Maximum Number of Trials\n"
"________________________\n\n";
cout << setprecision(7);
cout << setw(40) << left << "Success ratio" << "= " << p << "\n";
cout << setw(40) << left << "Maximum Number of \"successes\" permitted" << "= " << successes << "\n";
//
// Define a table of confidence intervals:
//
double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
//
// Print table header:
//
cout << "\n\n"
"____________________________\n"
"Confidence Max Number\n"
" Value (%) Of Trials \n"
"____________________________\n";
//
// Now print out the data for the table rows.
//
for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
{
// Confidence value:
cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]);
// calculate trials:
double t = binomial_distribution<>::find_maximum_number_of_trials(successes, p, alpha[i]);
t = floor(t);
// Print Trials:
cout << fixed << setprecision(0) << setw(15) << right << t << endl;
}
cout << endl;
}
int main()
{
find_max_sample_size(1.0/1000, 0);
find_max_sample_size(1.0/10000, 0);
find_max_sample_size(1.0/100000, 0);
find_max_sample_size(1.0/1000000, 0);
return 0;
}

View File

@@ -0,0 +1,74 @@
// C_error_policy_example.cpp
// Copyright Paul A. Bristow 2007.
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Suppose we want a call to tgamma to behave in a C-compatible way
// and set global ::errno rather than throw an exception.
#include <boost/math/special_functions/gamma.hpp>
using boost::math::tgamma;
using boost::math::policies::policy;
// Possible errors
using boost::math::policies::overflow_error;
using boost::math::policies::underflow_error;
using boost::math::policies::domain_error;
using boost::math::policies::pole_error;
using boost::math::policies::denorm_error;
using boost::math::policies::evaluation_error;
using boost::math::policies::errno_on_error;
//using boost::math::policies::ignore_error;
//using namespace boost::math::policies;
//using namespace boost::math;
// Define a policy:
typedef policy<
domain_error<errno_on_error>, // 'bad' arguments.
pole_error<errno_on_error>, // argument is pole value.
overflow_error<errno_on_error>, // argument value causes overflow.
evaluation_error<errno_on_error> // evaluation does not converge and may be inaccurate, or worse.
> C_error_policy;
// std
#include <iostream>
using std::cout;
using std::endl;
int main()
{
// We can achieve this at the function call site
// with the previously defined policy C_error_policy.
double t = tgamma(4., C_error_policy());
cout << "tgamma(4., C_error_policy() = " << t << endl; // 6
// Alternatively we could use the function make_policy,
// provided for convenience,
// and define everything at the call site:
t = tgamma(4., make_policy(
domain_error<errno_on_error>(),
pole_error<errno_on_error>(),
overflow_error<errno_on_error>(),
evaluation_error<errno_on_error>()
));
cout << "tgamma(4., make_policy( ...) = " << t << endl; // 6
return 0;
} // int main()
/*
Output
Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\c_error_policy_example.exe"
tgamma(4., C_error_policy() = 6
tgamma(4., make_policy( ...) = 6
*/

View File

@@ -0,0 +1,552 @@
// Copyright John Maddock 2006, 2007
// Copyright Paul A. Bristow 2007
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>
using std::cout; using std::endl;
using std::left; using std::fixed; using std::right; using std::scientific;
#include <iomanip>
using std::setw;
using std::setprecision;
#include <boost/math/distributions/chi_squared.hpp>
void confidence_limits_on_std_deviation(
double Sd, // Sample Standard Deviation
unsigned N) // Sample size
{
// Calculate confidence intervals for the standard deviation.
// For example if we set the confidence limit to
// 0.95, we know that if we repeat the sampling
// 100 times, then we expect that the true standard deviation
// will be between out limits on 95 occations.
// Note: this is not the same as saying a 95%
// confidence interval means that there is a 95%
// probability that the interval contains the true standard deviation.
// The interval computed from a given sample either
// contains the true standard deviation or it does not.
// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda358.htm
// using namespace boost::math;
using boost::math::chi_squared;
using boost::math::quantile;
using boost::math::complement;
// Print out general info:
cout <<
"________________________________________________\n"
"2-Sided Confidence Limits For Standard Deviation\n"
"________________________________________________\n\n";
cout << setprecision(7);
cout << setw(40) << left << "Number of Observations" << "= " << N << "\n";
cout << setw(40) << left << "Standard Deviation" << "= " << Sd << "\n";
//
// Define a table of significance/risk levels:
double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
//
// Start by declaring the distribution we'll need:
chi_squared dist(N - 1);
//
// Print table header:
//
cout << "\n\n"
"_____________________________________________\n"
"Confidence Lower Upper\n"
" Value (%) Limit Limit\n"
"_____________________________________________\n";
//
// Now print out the data for the table rows.
for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
{
// Confidence value:
cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]);
// Calculate limits:
double lower_limit = sqrt((N - 1) * Sd * Sd / quantile(complement(dist, alpha[i] / 2)));
double upper_limit = sqrt((N - 1) * Sd * Sd / quantile(dist, alpha[i] / 2));
// Print Limits:
cout << fixed << setprecision(5) << setw(15) << right << lower_limit;
cout << fixed << setprecision(5) << setw(15) << right << upper_limit << endl;
}
cout << endl;
} // void confidence_limits_on_std_deviation
void confidence_limits_on_std_deviation_alpha(
double Sd, // Sample Standard Deviation
double alpha // confidence
)
{ // Calculate confidence intervals for the standard deviation.
// for the alpha parameter, for a range number of observations,
// from a mere 2 up to a million.
// O. L. Davies, Statistical Methods in Research and Production, ISBN 0 05 002437 X,
// 4.33 Page 68, Table H, pp 452 459.
// using namespace std;
// using namespace boost::math;
using boost::math::chi_squared;
using boost::math::quantile;
using boost::math::complement;
// Define a table of numbers of observations:
unsigned int obs[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 30, 40 , 50, 60, 100, 120, 1000, 10000, 50000, 100000, 1000000};
cout << // Print out heading:
"________________________________________________\n"
"2-Sided Confidence Limits For Standard Deviation\n"
"________________________________________________\n\n";
cout << setprecision(7);
cout << setw(40) << left << "Confidence level (two-sided) " << "= " << alpha << "\n";
cout << setw(40) << left << "Standard Deviation" << "= " << Sd << "\n";
cout << "\n\n" // Print table header:
"_____________________________________________\n"
"Observations Lower Upper\n"
" Limit Limit\n"
"_____________________________________________\n";
for(unsigned i = 0; i < sizeof(obs)/sizeof(obs[0]); ++i)
{
unsigned int N = obs[i]; // Observations
// Start by declaring the distribution with the appropriate :
chi_squared dist(N - 1);
// Now print out the data for the table row.
cout << fixed << setprecision(3) << setw(10) << right << N;
// Calculate limits: (alpha /2 because it is a two-sided (upper and lower limit) test.
double lower_limit = sqrt((N - 1) * Sd * Sd / quantile(complement(dist, alpha / 2)));
double upper_limit = sqrt((N - 1) * Sd * Sd / quantile(dist, alpha / 2));
// Print Limits:
cout << fixed << setprecision(4) << setw(15) << right << lower_limit;
cout << fixed << setprecision(4) << setw(15) << right << upper_limit << endl;
}
cout << endl;
}// void confidence_limits_on_std_deviation_alpha
void chi_squared_test(
double Sd, // Sample std deviation
double D, // True std deviation
unsigned N, // Sample size
double alpha) // Significance level
{
//
// A Chi Squared test applied to a single set of data.
// We are testing the null hypothesis that the true
// standard deviation of the sample is D, and that any variation is down
// to chance. We can also test the alternative hypothesis
// that any difference is not down to chance.
// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda358.htm
//
// using namespace boost::math;
using boost::math::chi_squared;
using boost::math::quantile;
using boost::math::complement;
using boost::math::cdf;
// Print header:
cout <<
"______________________________________________\n"
"Chi Squared test for sample standard deviation\n"
"______________________________________________\n\n";
cout << setprecision(5);
cout << setw(55) << left << "Number of Observations" << "= " << N << "\n";
cout << setw(55) << left << "Sample Standard Deviation" << "= " << Sd << "\n";
cout << setw(55) << left << "Expected True Standard Deviation" << "= " << D << "\n\n";
//
// Now we can calculate and output some stats:
//
// test-statistic:
double t_stat = (N - 1) * (Sd / D) * (Sd / D);
cout << setw(55) << left << "Test Statistic" << "= " << t_stat << "\n";
//
// Finally define our distribution, and get the probability:
//
chi_squared dist(N - 1);
double p = cdf(dist, t_stat);
cout << setw(55) << left << "CDF of test statistic: " << "= "
<< setprecision(3) << scientific << p << "\n";
double ucv = quantile(complement(dist, alpha));
double ucv2 = quantile(complement(dist, alpha / 2));
double lcv = quantile(dist, alpha);
double lcv2 = quantile(dist, alpha / 2);
cout << setw(55) << left << "Upper Critical Value at alpha: " << "= "
<< setprecision(3) << scientific << ucv << "\n";
cout << setw(55) << left << "Upper Critical Value at alpha/2: " << "= "
<< setprecision(3) << scientific << ucv2 << "\n";
cout << setw(55) << left << "Lower Critical Value at alpha: " << "= "
<< setprecision(3) << scientific << lcv << "\n";
cout << setw(55) << left << "Lower Critical Value at alpha/2: " << "= "
<< setprecision(3) << scientific << lcv2 << "\n\n";
//
// Finally print out results of alternative hypothesis:
//
cout << setw(55) << left <<
"Results for Alternative Hypothesis and alpha" << "= "
<< setprecision(4) << fixed << alpha << "\n\n";
cout << "Alternative Hypothesis Conclusion\n";
cout << "Standard Deviation != " << setprecision(3) << fixed << D << " ";
if((ucv2 < t_stat) || (lcv2 > t_stat))
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Standard Deviation < " << setprecision(3) << fixed << D << " ";
if(lcv > t_stat)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Standard Deviation > " << setprecision(3) << fixed << D << " ";
if(ucv < t_stat)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << endl << endl;
} // void chi_squared_test
void chi_squared_sample_sized(
double diff, // difference from variance to detect
double variance) // true variance
{
using namespace std;
// using boost::math;
using boost::math::chi_squared;
using boost::math::quantile;
using boost::math::complement;
using boost::math::cdf;
try
{
cout << // Print out general info:
"_____________________________________________________________\n"
"Estimated sample sizes required for various confidence levels\n"
"_____________________________________________________________\n\n";
cout << setprecision(5);
cout << setw(40) << left << "True Variance" << "= " << variance << "\n";
cout << setw(40) << left << "Difference to detect" << "= " << diff << "\n";
//
// Define a table of significance levels:
//
double alpha[] = { 0.5, 0.33333333333333333333333, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
//
// Print table header:
//
cout << "\n\n"
"_______________________________________________________________\n"
"Confidence Estimated Estimated\n"
" Value (%) Sample Size Sample Size\n"
" (lower one- (upper one-\n"
" sided test) sided test)\n"
"_______________________________________________________________\n";
//
// Now print out the data for the table rows.
//
for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
{
// Confidence value:
cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]);
// calculate df for a lower single-sided test:
double df = chi_squared::find_degrees_of_freedom(
-diff, alpha[i], alpha[i], variance);
// convert to sample size:
double size = ceil(df) + 1;
// Print size:
cout << fixed << setprecision(0) << setw(16) << right << size;
// calculate df for an upper single-sided test:
df = chi_squared::find_degrees_of_freedom(
diff, alpha[i], alpha[i], variance);
// convert to sample size:
size = ceil(df) + 1;
// Print size:
cout << fixed << setprecision(0) << setw(16) << right << size << endl;
}
cout << endl;
}
catch(const std::exception& e)
{ // Always useful to include try & catch blocks because default policies
// are to throw exceptions on arguments that cause errors like underflow, overflow.
// Lacking try & catch blocks, the program will abort without a message below,
// which may give some helpful clues as to the cause of the exception.
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
} // chi_squared_sample_sized
int main()
{
// Run tests for Gear data
// see http://www.itl.nist.gov/div898/handbook/eda/section3/eda3581.htm
// Tests measurements of gear diameter.
//
confidence_limits_on_std_deviation(0.6278908E-02, 100);
chi_squared_test(0.6278908E-02, 0.1, 100, 0.05);
chi_squared_sample_sized(0.1 - 0.6278908E-02, 0.1);
//
// Run tests for silicon wafer fabrication data.
// see http://www.itl.nist.gov/div898/handbook/prc/section2/prc23.htm
// A supplier of 100 ohm.cm silicon wafers claims that his fabrication
// process can produce wafers with sufficient consistency so that the
// standard deviation of resistivity for the lot does not exceed
// 10 ohm.cm. A sample of N = 10 wafers taken from the lot has a
// standard deviation of 13.97 ohm.cm
//
confidence_limits_on_std_deviation(13.97, 10);
chi_squared_test(13.97, 10.0, 10, 0.05);
chi_squared_sample_sized(13.97 * 13.97 - 100, 100);
chi_squared_sample_sized(55, 100);
chi_squared_sample_sized(1, 100);
// List confidence interval multipliers for standard deviation
// for a range of numbers of observations from 2 to a million,
// and for a few alpha values, 0.1, 0.05, 0.01 for condfidences 90, 95, 99 %
confidence_limits_on_std_deviation_alpha(1., 0.1);
confidence_limits_on_std_deviation_alpha(1., 0.05);
confidence_limits_on_std_deviation_alpha(1., 0.01);
return 0;
}
/*
________________________________________________
2-Sided Confidence Limits For Standard Deviation
________________________________________________
Number of Observations = 100
Standard Deviation = 0.006278908
_____________________________________________
Confidence Lower Upper
Value (%) Limit Limit
_____________________________________________
50.000 0.00601 0.00662
75.000 0.00582 0.00685
90.000 0.00563 0.00712
95.000 0.00551 0.00729
99.000 0.00530 0.00766
99.900 0.00507 0.00812
99.990 0.00489 0.00855
99.999 0.00474 0.00895
______________________________________________
Chi Squared test for sample standard deviation
______________________________________________
Number of Observations = 100
Sample Standard Deviation = 0.00628
Expected True Standard Deviation = 0.10000
Test Statistic = 0.39030
CDF of test statistic: = 1.438e-099
Upper Critical Value at alpha: = 1.232e+002
Upper Critical Value at alpha/2: = 1.284e+002
Lower Critical Value at alpha: = 7.705e+001
Lower Critical Value at alpha/2: = 7.336e+001
Results for Alternative Hypothesis and alpha = 0.0500
Alternative Hypothesis Conclusion
Standard Deviation != 0.100 NOT REJECTED
Standard Deviation < 0.100 NOT REJECTED
Standard Deviation > 0.100 REJECTED
_____________________________________________________________
Estimated sample sizes required for various confidence levels
_____________________________________________________________
True Variance = 0.10000
Difference to detect = 0.09372
_______________________________________________________________
Confidence Estimated Estimated
Value (%) Sample Size Sample Size
(lower one- (upper one-
sided test) sided test)
_______________________________________________________________
50.000 2 2
66.667 2 5
75.000 2 10
90.000 4 32
95.000 5 52
99.000 8 102
99.900 13 178
99.990 18 257
99.999 23 337
________________________________________________
2-Sided Confidence Limits For Standard Deviation
________________________________________________
Number of Observations = 10
Standard Deviation = 13.9700000
_____________________________________________
Confidence Lower Upper
Value (%) Limit Limit
_____________________________________________
50.000 12.41880 17.25579
75.000 11.23084 19.74131
90.000 10.18898 22.98341
95.000 9.60906 25.50377
99.000 8.62898 31.81825
99.900 7.69466 42.51593
99.990 7.04085 55.93352
99.999 6.54517 73.00132
______________________________________________
Chi Squared test for sample standard deviation
______________________________________________
Number of Observations = 10
Sample Standard Deviation = 13.97000
Expected True Standard Deviation = 10.00000
Test Statistic = 17.56448
CDF of test statistic: = 9.594e-001
Upper Critical Value at alpha: = 1.692e+001
Upper Critical Value at alpha/2: = 1.902e+001
Lower Critical Value at alpha: = 3.325e+000
Lower Critical Value at alpha/2: = 2.700e+000
Results for Alternative Hypothesis and alpha = 0.0500
Alternative Hypothesis Conclusion
Standard Deviation != 10.000 REJECTED
Standard Deviation < 10.000 REJECTED
Standard Deviation > 10.000 NOT REJECTED
_____________________________________________________________
Estimated sample sizes required for various confidence levels
_____________________________________________________________
True Variance = 100.00000
Difference to detect = 95.16090
_______________________________________________________________
Confidence Estimated Estimated
Value (%) Sample Size Sample Size
(lower one- (upper one-
sided test) sided test)
_______________________________________________________________
50.000 2 2
66.667 2 5
75.000 2 10
90.000 4 32
95.000 5 51
99.000 7 99
99.900 11 174
99.990 15 251
99.999 20 330
_____________________________________________________________
Estimated sample sizes required for various confidence levels
_____________________________________________________________
True Variance = 100.00000
Difference to detect = 55.00000
_______________________________________________________________
Confidence Estimated Estimated
Value (%) Sample Size Sample Size
(lower one- (upper one-
sided test) sided test)
_______________________________________________________________
50.000 2 2
66.667 4 10
75.000 8 21
90.000 23 71
95.000 36 115
99.000 71 228
99.900 123 401
99.990 177 580
99.999 232 762
_____________________________________________________________
Estimated sample sizes required for various confidence levels
_____________________________________________________________
True Variance = 100.00000
Difference to detect = 1.00000
_______________________________________________________________
Confidence Estimated Estimated
Value (%) Sample Size Sample Size
(lower one- (upper one-
sided test) sided test)
_______________________________________________________________
50.000 2 2
66.667 14696 14993
75.000 36033 36761
90.000 130079 132707
95.000 214283 218612
99.000 428628 437287
99.900 756333 771612
99.990 1095435 1117564
99.999 1440608 1469711
________________________________________________
2-Sided Confidence Limits For Standard Deviation
________________________________________________
Confidence level (two-sided) = 0.1000000
Standard Deviation = 1.0000000
_____________________________________________
Observations Lower Upper
Limit Limit
_____________________________________________
2 0.5102 15.9472
3 0.5778 4.4154
4 0.6196 2.9200
5 0.6493 2.3724
6 0.6720 2.0893
7 0.6903 1.9154
8 0.7054 1.7972
9 0.7183 1.7110
10 0.7293 1.6452
15 0.7688 1.4597
20 0.7939 1.3704
30 0.8255 1.2797
40 0.8454 1.2320
50 0.8594 1.2017
60 0.8701 1.1805
100 0.8963 1.1336
120 0.9045 1.1203
1000 0.9646 1.0383
10000 0.9885 1.0118
50000 0.9948 1.0052
100000 0.9963 1.0037
1000000 0.9988 1.0012
________________________________________________
2-Sided Confidence Limits For Standard Deviation
________________________________________________
Confidence level (two-sided) = 0.0500000
Standard Deviation = 1.0000000
_____________________________________________
Observations Lower Upper
Limit Limit
_____________________________________________
2 0.4461 31.9102
3 0.5207 6.2847
4 0.5665 3.7285
5 0.5991 2.8736
6 0.6242 2.4526
7 0.6444 2.2021
8 0.6612 2.0353
9 0.6755 1.9158
10 0.6878 1.8256
15 0.7321 1.5771
20 0.7605 1.4606
30 0.7964 1.3443
40 0.8192 1.2840
50 0.8353 1.2461
60 0.8476 1.2197
100 0.8780 1.1617
120 0.8875 1.1454
1000 0.9580 1.0459
10000 0.9863 1.0141
50000 0.9938 1.0062
100000 0.9956 1.0044
1000000 0.9986 1.0014
________________________________________________
2-Sided Confidence Limits For Standard Deviation
________________________________________________
Confidence level (two-sided) = 0.0100000
Standard Deviation = 1.0000000
_____________________________________________
Observations Lower Upper
Limit Limit
_____________________________________________
2 0.3562 159.5759
3 0.4344 14.1244
4 0.4834 6.4675
5 0.5188 4.3960
6 0.5464 3.4848
7 0.5688 2.9798
8 0.5875 2.6601
9 0.6036 2.4394
10 0.6177 2.2776
15 0.6686 1.8536
20 0.7018 1.6662
30 0.7444 1.4867
40 0.7718 1.3966
50 0.7914 1.3410
60 0.8065 1.3026
100 0.8440 1.2200
120 0.8558 1.1973
1000 0.9453 1.0609
10000 0.9821 1.0185
50000 0.9919 1.0082
100000 0.9943 1.0058
1000000 0.9982 1.0018
*/

View File

@@ -0,0 +1,201 @@
// distribution_construction.cpp
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Caution: this file contains Quickbook markup as well as code
// and comments, don't change any of the special comment markups!
//[distribution_construction1
/*`
The structure of distributions is rather different from some other statistical libraries,
for example in less object-oriented language like FORTRAN and C,
that provide a few arguments to each free function.
This library provides each distribution as a template C++ class.
A distribution is constructed with a few arguments, and then
member and non-member functions are used to find values of the
distribution, often a function of a random variate.
First we need some includes to access the negative binomial distribution
(and the binomial, beta and gamma too).
*/
#include <boost/math/distributions/negative_binomial.hpp> // for negative_binomial_distribution
using boost::math::negative_binomial_distribution; // default type is double.
using boost::math::negative_binomial; // typedef provides default type is double.
#include <boost/math/distributions/binomial.hpp> // for binomial_distribution.
#include <boost/math/distributions/beta.hpp> // for beta_distribution.
#include <boost/math/distributions/gamma.hpp> // for gamma_distribution.
#include <boost/math/distributions/normal.hpp> // for normal_distribution.
/*`
Several examples of constructing distributions follow:
*/
//] [/distribution_construction1 end of Quickbook in C++ markup]
int main()
{
//[distribution_construction2
/*`
First, a negative binomial distribution with 8 successes
and a success fraction 0.25, 25% or 1 in 4, is constructed like this:
*/
boost::math::negative_binomial_distribution<double> mydist0(8., 0.25);
/*`
But this is inconveniently long, so by writing
*/
using namespace boost::math;
/*`
or
*/
using boost::math::negative_binomial_distribution;
/*`
we can reduce typing.
Since the vast majority of applications use will be using double precision,
the template argument to the distribution (RealType) defaults
to type double, so we can also write:
*/
negative_binomial_distribution<> mydist9(8., 0.25); // Uses default RealType = double.
/*`
But the name "negative_binomial_distribution" is still inconveniently long,
so for most distributions, a convenience typedef is provided, for example:
typedef negative_binomial_distribution<double> negative_binomial; // Reserved name of type double.
[caution
This convenience typedef is /not/ provided if a clash would occur
with the name of a function: currently only "beta" and "gamma"
fall into this category.
]
So, after a using statement,
*/
using boost::math::negative_binomial;
/*`
we have a convenient typedef to `negative_binomial_distribution<double>`:
*/
negative_binomial mydist(8., 0.25);
/*`
Some more examples using the convenience typedef:
*/
negative_binomial mydist10(5., 0.4); // Both arguments double.
/*`
And automatic conversion takes place, so you can use integers and floats:
*/
negative_binomial mydist11(5, 0.4); // Using provided typedef double, int and double arguments.
/*`
This is probably the most common usage.
*/
negative_binomial mydist12(5., 0.4F); // Double and float arguments.
negative_binomial mydist13(5, 1); // Both arguments integer.
/*`
Similarly for most other distributions like the binomial.
*/
binomial mybinomial(1, 0.5); // is more concise than
binomial_distribution<> mybinomd1(1, 0.5);
/*`
For cases when the typdef distribution name would clash with a math special function
(currently only beta and gamma)
the typedef is deliberately not provided, and the longer version of the name
must be used. For example do not use:
using boost::math::beta;
beta mybetad0(1, 0.5); // Error beta is a math FUNCTION!
Which produces the error messages:
[pre
error C2146: syntax error : missing ';' before identifier 'mybetad0'
warning C4551: function call missing argument list
error C3861: 'mybetad0': identifier not found
]
Instead you should use:
*/
using boost::math::beta_distribution;
beta_distribution<> mybetad1(1, 0.5);
/*`
or for the gamma distribution:
*/
gamma_distribution<> mygammad1(1, 0.5);
/*`
We can, of course, still provide the type explicitly thus:
*/
// Explicit double precision:
negative_binomial_distribution<double> mydist1(8., 0.25);
// Explicit float precision, double arguments are truncated to float:
negative_binomial_distribution<float> mydist2(8., 0.25);
// Explicit float precision, integer & double arguments converted to float.
negative_binomial_distribution<float> mydist3(8, 0.25);
// Explicit float precision, float arguments, so no conversion:
negative_binomial_distribution<float> mydist4(8.F, 0.25F);
// Explicit float precision, integer arguments promoted to float.
negative_binomial_distribution<float> mydist5(8, 1);
// Explicit double precision:
negative_binomial_distribution<double> mydist6(8., 0.25);
// Explicit long double precision:
negative_binomial_distribution<long double> mydist7(8., 0.25);
/*`
And if you have your own RealType called MyFPType,
for example NTL RR (an arbitrary precision type), then we can write:
negative_binomial_distribution<MyFPType> mydist6(8, 1); // Integer arguments -> MyFPType.
[heading Default arguments to distribution constructors.]
Note that default constructor arguments are only provided for some distributions.
So if you wrongly assume a default argument you will get an error message, for example:
negative_binomial_distribution<> mydist8;
[pre error C2512 no appropriate default constructor available.]
No default constructors are provided for the negative binomial,
because it is difficult to chose any sensible default values for this distribution.
For other distributions, like the normal distribution,
it is obviously very useful to provide 'standard'
defaults for the mean and standard deviation thus:
normal_distribution(RealType mean = 0, RealType sd = 1);
So in this case we can write:
*/
using boost::math::normal;
normal norm1; // Standard normal distribution.
normal norm2(2); // Mean = 2, std deviation = 1.
normal norm3(2, 3); // Mean = 2, std deviation = 3.
return 0;
} // int main()
/*`There is no useful output from this program, of course. */
//] [/end of distribution_construction2]

View File

@@ -0,0 +1,143 @@
// example_error_handling.cpp
// Copyright Paul A. Bristow 2007.
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook markup as well as code
// and comments, don't change any of the special comment markups!
//[error_handling_example
/*`
The following example demonstrates the effect of
setting the macro BOOST_MATH_DOMAIN_ERROR_POLICY
when an invalid argument is encountered. For the
purposes of this example, we'll pass a negative
degrees of freedom parameter to the student's t
distribution.
Since we know that this is a single file program we could
just add:
#define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error
to the top of the source file to change the default policy
to one that simply returns a NaN when a domain error occurs.
Alternatively we could use:
#define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error
To ensure the `::errno` is set when a domain error occurs
as well as returning a NaN.
This is safe provided the program consists of a single
translation unit /and/ we place the define /before/ any
#includes. Note that should we add the define after the includes
then it will have no effect! A warning such as:
[pre warning C4005: 'BOOST_MATH_OVERFLOW_ERROR_POLICY' : macro redefinition]
is a certain sign that it will /not/ have the desired effect.
We'll begin our sample program with the needed includes:
*/
// Boost
#include <boost/math/distributions/students_t.hpp>
using boost::math::students_t; // Probability of students_t(df, t).
// std
#include <iostream>
using std::cout;
using std::endl;
#include <stdexcept>
using std::exception;
/*`
Next we'll define the program's main() to call the student's t
distribution with an invalid degrees of freedom parameter, the program
is set up to handle either an exception or a NaN:
*/
int main()
{
cout << "Example error handling using Student's t function. " << endl;
cout << "BOOST_MATH_DOMAIN_ERROR_POLICY is set to: "
<< BOOST_STRINGIZE(BOOST_MATH_DOMAIN_ERROR_POLICY) << endl;
double degrees_of_freedom = -1; // A bad argument!
double t = 10;
try
{
errno = 0;
students_t dist(degrees_of_freedom); // exception is thrown here if enabled
double p = cdf(dist, t);
// test for error reported by other means:
if((boost::math::isnan)(p))
{
cout << "cdf returned a NaN!" << endl;
cout << "errno is set to: " << errno << endl;
}
else
cout << "Probability of Student's t is " << p << endl;
}
catch(const std::exception& e)
{
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
return 0;
} // int main()
/*`
Here's what the program output looks like with a default build
(one that does throw exceptions):
[pre
Example error handling using Student's t function.
BOOST_MATH_DOMAIN_ERROR_POLICY is set to: throw_on_error
Message from thrown exception was:
Error in function boost::math::students_t_distribution<double>::students_t_distribution:
Degrees of freedom argument is -1, but must be > 0 !
]
Alternatively let's build with:
#define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error
Now the program output is:
[pre
Example error handling using Student's t function.
BOOST_MATH_DOMAIN_ERROR_POLICY is set to: ignore_error
cdf returned a NaN!
errno is set to: 0
]
And finally let's build with:
#define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error
Which gives the output:
[pre
Example error handling using Student's t function.
BOOST_MATH_DOMAIN_ERROR_POLICY is set to: errno_on_error
cdf returned a NaN!
errno is set to: 33
]
*/
//] [error_handling_eg end quickbook markup]

View File

@@ -0,0 +1,97 @@
// error_policies_example.cpp
// Copyright Paul A. Bristow 2007.
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/math/distributions/normal.hpp>
using boost::math::normal_distribution;
#include <boost/math/distributions/students_t.hpp>
using boost::math::students_t; // Probability of students_t(df, t).
using boost::math::students_t_distribution;
// using namespace boost::math;
//.\error_policy_normal.cpp(30) : error C2872: 'policy' : ambiguous symbol
// could be 'I:\Boost-sandbox\math_toolkit\boost/math/policies/policy.hpp(392) : boost::math::policies::policy'
// or 'boost::math::policies'
// So can't use this using namespace command.
// Suppose we want a statistical distribution to return infinities,
// rather than throw exceptions (the default policy), then we can use:
// std
#include <iostream>
using std::cout;
using std::endl;
using boost::math::policies::policy;
// Possible errors
using boost::math::policies::overflow_error;
using boost::math::policies::underflow_error;
using boost::math::policies::domain_error;
using boost::math::policies::pole_error;
using boost::math::policies::denorm_error;
using boost::math::policies::evaluation_error;
using boost::math::policies::ignore_error;
// Define a custom policy to ignore just overflow:
typedef policy<
overflow_error<ignore_error>
> my_policy;
// Define another custom policy (perhaps ill-advised?)
// to ignore all errors: domain, pole, overflow, underflow, denorm & evaluation:
typedef policy<
domain_error<ignore_error>,
pole_error<ignore_error>,
overflow_error<ignore_error>,
underflow_error<ignore_error>,
denorm_error<ignore_error>,
evaluation_error<ignore_error>
> my_ignoreall_policy;
// Define a new distribution with a custom policy to ignore_error
// (& thus perhaps return infinity for some arguments):
typedef boost::math::normal_distribution<double, my_policy> my_normal;
// Note: uses default parameters zero mean and unit standard deviation.
// We could also do the same for another distribution, for example:
using boost::math::students_t_distribution;
typedef students_t_distribution<double, my_ignoreall_policy> my_students_t;
int main()
{
cout << "quantile(my_normal(), 0.05); = " << quantile(my_normal(), 0.05) << endl; // 0.05 is argument within normal range.
cout << "quantile(my_normal(), 0.); = " << quantile(my_normal(), 0.) << endl; // argument zero, so expect infinity.
cout << "quantile(my_normal(), 0.); = " << quantile(my_normal(), 0.F) << endl; // argument zero, so expect infinity.
cout << "quantile(my_students_t(), 0.); = " << quantile(my_students_t(-1), 0.F) << endl; // 'bad' argument negative, so expect NaN.
// Construct a (0, 1) normal distribution that ignores all errors,
// returning NaN, infinity, zero, or best guess,
// and NOT setting errno.
normal_distribution<long double, my_ignoreall_policy> my_normal2(0.L, 1.L); // explicit parameters for distribution.
cout << "quantile(my_normal2(), 0.); = " << quantile(my_normal2, 0.01) << endl; // argument 0.01, so result finite.
cout << "quantile(my_normal2(), 0.); = " << quantile(my_normal2, 0.) << endl; // argument zero, so expect infinity.
return 0;
}
/*
Output:
quantile(my_normal(), 0.05); = -1.64485
quantile(my_normal(), 0.); = -1.#INF
quantile(my_normal(), 0.); = -1.#INF
quantile(my_students_t(), 0.); = 1.#QNAN
quantile(my_normal2(), 0.); = -2.32635
quantile(my_normal2(), 0.); = -1.#INF
*/

View File

@@ -0,0 +1,88 @@
// example_policy_handling.cpp
// Copyright Paul A. Bristow 2007.
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// See error_handling_example.cpp for use of
// macro definition to change policy for
// domain_error - negative degrees of freedom argument
// for student's t distribution CDF,
// and catching the exception.
// See error_handling_policies for more examples.
// Boost
#include <boost/math/distributions/students_t.hpp>
using boost::math::students_t_distribution; // Probability of students_t(df, t).
using boost::math::students_t; // Probability of students_t(df, t) convenience typedef for double.
// std
#include <iostream>
using std::cout;
using std::endl;
#include <stdexcept>
using std::exception;
using boost::math::policies::policy;
using boost::math::policies::domain_error;
using boost::math::policies::ignore_error;
// Define a (bad?) policy to ignore domain errors ('bad' arguments):
typedef policy<
domain_error<ignore_error>
> my_policy;
// Define my distribution with this different domain error policy:
typedef students_t_distribution<double, my_policy> my_students_t;
int main()
{ // Example of error handling of bad argument(s) to a distribution.
cout << "Example error handling using Student's t function. " << endl;
double degrees_of_freedom = -1; double t = -1.; // Two 'bad' arguments!
try
{
cout << "Probability of ignore_error Student's t is " << cdf(my_students_t(degrees_of_freedom), t) << endl;
cout << "Probability of default error policy Student's t is " << endl;
// BY contrast the students_t distribution default domain error policy is to throw,
cout << cdf(students_t(-1), -1) << endl; // so this will throw.
/*`
Message from thrown exception was:
Error in function boost::math::students_t_distribution<double>::students_t_distribution:
Degrees of freedom argument is -1, but must be > 0 !
*/
// We could also define a 'custom' distribution
// with an "ignore overflow error policy" in a single statement:
using boost::math::policies::overflow_error;
students_t_distribution<double, policy<overflow_error<ignore_error> > > students_t_no_throw(-1);
}
catch(const std::exception& e)
{
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
return 0;
} // int main()
/*
Output:
Example error handling using Student's t function.
Probability of ignore_error Student's t is 1.#QNAN
Probability of default error policy Student's t is
Message from thrown exception was:
Error in function boost::math::students_t_distribution<double>::students_t_distribution:
Degrees of freedom argument is -1, but must be > 0 !
*/

184
example/f_test.cpp Normal file
View File

@@ -0,0 +1,184 @@
// Copyright John Maddock 2006
// Copyright Paul A. Bristow 2007
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifdef _MSC_VER
# pragma warning(disable: 4512) // assignment operator could not be generated.
# pragma warning(disable: 4510) // default constructor could not be generated.
# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required.
#endif
#include <iostream>
#include <iomanip>
#include <boost/math/distributions/fisher_f.hpp>
void f_test(
double sd1, // Sample 1 std deviation
double sd2, // Sample 2 std deviation
double N1, // Sample 1 size
double N2, // Sample 2 size
double alpha) // Significance level
{
//
// An F test applied to two sets of data.
// We are testing the null hypothesis that the
// standard deviation of the samples is equal, and
// that any variation is down to chance. We can
// also test the alternative hypothesis that any
// difference is not down to chance.
// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda359.htm
//
using namespace std;
using namespace boost::math;
// Print header:
cout <<
"____________________________________\n"
"F test for equal standard deviations\n"
"____________________________________\n\n";
cout << setprecision(5);
cout << "Sample 1:\n";
cout << setw(55) << left << "Number of Observations" << "= " << N1 << "\n";
cout << setw(55) << left << "Sample Standard Deviation" << "= " << sd1 << "\n\n";
cout << "Sample 2:\n";
cout << setw(55) << left << "Number of Observations" << "= " << N2 << "\n";
cout << setw(55) << left << "Sample Standard Deviation" << "= " << sd2 << "\n\n";
//
// Now we can calculate and output some stats:
//
// F-statistic:
double F = (sd1 / sd2);
F *= F;
cout << setw(55) << left << "Test Statistic" << "= " << F << "\n\n";
//
// Finally define our distribution, and get the probability:
//
fisher_f dist(N1 - 1, N2 - 1);
double p = cdf(dist, F);
cout << setw(55) << left << "CDF of test statistic: " << "= "
<< setprecision(3) << scientific << p << "\n";
double ucv = quantile(complement(dist, alpha));
double ucv2 = quantile(complement(dist, alpha / 2));
double lcv = quantile(dist, alpha);
double lcv2 = quantile(dist, alpha / 2);
cout << setw(55) << left << "Upper Critical Value at alpha: " << "= "
<< setprecision(3) << scientific << ucv << "\n";
cout << setw(55) << left << "Upper Critical Value at alpha/2: " << "= "
<< setprecision(3) << scientific << ucv2 << "\n";
cout << setw(55) << left << "Lower Critical Value at alpha: " << "= "
<< setprecision(3) << scientific << lcv << "\n";
cout << setw(55) << left << "Lower Critical Value at alpha/2: " << "= "
<< setprecision(3) << scientific << lcv2 << "\n\n";
//
// Finally print out results of null and alternative hypothesis:
//
cout << setw(55) << left <<
"Results for Alternative Hypothesis and alpha" << "= "
<< setprecision(4) << fixed << alpha << "\n\n";
cout << "Alternative Hypothesis Conclusion\n";
cout << "Standard deviations are unequal (two sided test) ";
if((ucv2 < F) || (lcv2 > F))
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Standard deviation 1 is less than standard deviation 2 ";
if(lcv > F)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Standard deviation 1 is greater than standard deviation 2 ";
if(ucv < F)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << endl << endl;
}
int main()
{
//
// Run tests for ceramic strength data:
// see http://www.itl.nist.gov/div898/handbook/eda/section4/eda42a1.htm
// The data for this case study were collected by Said Jahanmir of the
// NIST Ceramics Division in 1996 in connection with a NIST/industry
// ceramics consortium for strength optimization of ceramic strength.
//
f_test(65.54909, 61.85425, 240, 240, 0.05);
//
// And again for the process change comparison:
// see http://www.itl.nist.gov/div898/handbook/prc/section3/prc32.htm
// A new procedure to assemble a device is introduced and tested for
// possible improvement in time of assembly. The question being addressed
// is whether the standard deviation of the new assembly process (sample 2) is
// better (i.e., smaller) than the standard deviation for the old assembly
// process (sample 1).
//
f_test(4.9082, 2.5874, 11, 9, 0.05);
return 0;
}
/*
Output:
____________________________________
F test for equal standard deviations
____________________________________
Sample 1:
Number of Observations = 240
Sample Standard Deviation = 65.549
Sample 2:
Number of Observations = 240
Sample Standard Deviation = 61.854
Test Statistic = 1.123
CDF of test statistic: = 8.148e-001
Upper Critical Value at alpha: = 1.238e+000
Upper Critical Value at alpha/2: = 1.289e+000
Lower Critical Value at alpha: = 8.080e-001
Lower Critical Value at alpha/2: = 7.756e-001
Results for Alternative Hypothesis and alpha = 0.0500
Alternative Hypothesis Conclusion
Standard deviations are unequal (two sided test) REJECTED
Standard deviation 1 is less than standard deviation 2 REJECTED
Standard deviation 1 is greater than standard deviation 2 REJECTED
____________________________________
F test for equal standard deviations
____________________________________
Sample 1:
Number of Observations = 11.00000
Sample Standard Deviation = 4.90820
Sample 2:
Number of Observations = 9.00000
Sample Standard Deviation = 2.58740
Test Statistic = 3.59847
CDF of test statistic: = 9.589e-001
Upper Critical Value at alpha: = 3.347e+000
Upper Critical Value at alpha/2: = 4.295e+000
Lower Critical Value at alpha: = 3.256e-001
Lower Critical Value at alpha/2: = 2.594e-001
Results for Alternative Hypothesis and alpha = 0.0500
Alternative Hypothesis Conclusion
Standard deviations are unequal (two sided test) REJECTED
Standard deviation 1 is less than standard deviation 2 REJECTED
Standard deviation 1 is greater than standard deviation 2 NOT REJECTED
*/

View File

@@ -0,0 +1,170 @@
// find_location.cpp
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Example of finding location (mean)
// for normal (Gaussian) & Cauchy distribution.
// Note that this file contains Quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[find_location1
/*`
First we need some includes to access the normal distribution,
the algorithms to find location (and some std output of course).
*/
#include <boost/math/distributions/normal.hpp> // for normal_distribution
using boost::math::normal; // typedef provides default type is double.
#include <boost/math/distributions/cauchy.hpp> // for cauchy_distribution
using boost::math::cauchy; // typedef provides default type is double.
#include <boost/math/distributions/find_location.hpp>
using boost::math::find_location;
using boost::math::complement; // Needed if you want to use the complement version.
using boost::math::policies::policy;
#include <iostream>
using std::cout; using std::endl;
#include <iomanip>
using std::setw; using std::setprecision;
#include <limits>
using std::numeric_limits;
//] [/find_location1]
int main()
{
cout << "Example: Find location (mean)." << endl;
try
{
//[find_location2
/*`
For this example, we will use the standard normal distribution,
with mean (location) zero and standard deviation (scale) unity.
This is also the default for this implementation.
*/
normal N01; // Default 'standard' normal distribution with zero mean and
double sd = 1.; // normal default standard deviation is 1.
/*`Suppose we want to find a different normal distribution whose mean is shifted
so that only fraction p (here 0.001 or 0.1%) are below a certain chosen limit
(here -2, two standard deviations).
*/
double z = -2.; // z to give prob p
double p = 0.001; // only 0.1% below z
cout << "Normal distribution with mean = " << N01.location()
<< ", standard deviation " << N01.scale()
<< ", has " << "fraction <= " << z
<< ", p = " << cdf(N01, z) << endl;
cout << "Normal distribution with mean = " << N01.location()
<< ", standard deviation " << N01.scale()
<< ", has " << "fraction > " << z
<< ", p = " << cdf(complement(N01, z)) << endl; // Note: uses complement.
/*`
[pre
Normal distribution with mean = 0, standard deviation 1, has fraction <= -2, p = 0.0227501
Normal distribution with mean = 0, standard deviation 1, has fraction > -2, p = 0.97725
]
We can now use ''find_location'' to give a new offset mean.
*/
double l = find_location<normal>(z, p, sd);
cout << "offset location (mean) = " << l << endl;
/*`
that outputs:
[pre
offset location (mean) = 1.09023
]
showing that we need to shift the mean just over one standard deviation from its previous value of zero.
Then we can check that we have achieved our objective
by constructing a new distribution
with the offset mean (but same standard deviation):
*/
normal np001pc(l, sd); // Same standard_deviation (scale) but with mean (location) shifted.
/*`
And re-calculating the fraction below our chosen limit.
*/
cout << "Normal distribution with mean = " << l
<< " has " << "fraction <= " << z
<< ", p = " << cdf(np001pc, z) << endl;
cout << "Normal distribution with mean = " << l
<< " has " << "fraction > " << z
<< ", p = " << cdf(complement(np001pc, z)) << endl;
/*`
[pre
Normal distribution with mean = 1.09023 has fraction <= -2, p = 0.001
Normal distribution with mean = 1.09023 has fraction > -2, p = 0.999
]
[h4 Controlling Error Handling from find_location]
We can also control the policy for handling various errors.
For example, we can define a new (possibly unwise)
policy to ignore domain errors ('bad' arguments).
Unless we are using the boost::math namespace, we will need:
*/
using boost::math::policies::policy;
using boost::math::policies::domain_error;
using boost::math::policies::ignore_error;
/*`
Using a typedef is often convenient, especially if it is re-used,
although it is not required, as the various examples below show.
*/
typedef policy<domain_error<ignore_error> > ignore_domain_policy;
// find_location with new policy, using typedef.
l = find_location<normal>(z, p, sd, ignore_domain_policy());
// Default policy policy<>, needs "using boost::math::policies::policy;"
l = find_location<normal>(z, p, sd, policy<>());
// Default policy, fully specified.
l = find_location<normal>(z, p, sd, boost::math::policies::policy<>());
// A new policy, ignoring domain errors, without using a typedef.
l = find_location<normal>(z, p, sd, policy<domain_error<ignore_error> >());
/*`
If we want to use a probability that is the
[link complements complement of our probability],
we should not even think of writing `find_location<normal>(z, 1 - p, sd)`,
but, [link why_complements to avoid loss of accuracy], use the complement version.
*/
z = 2.;
double q = 0.95; // = 1 - p; // complement.
l = find_location<normal>(complement(z, q, sd));
normal np95pc(l, sd); // Same standard_deviation (scale) but with mean(location) shifted
cout << "Normal distribution with mean = " << l << " has "
<< "fraction <= " << z << " = " << cdf(np95pc, z) << endl;
cout << "Normal distribution with mean = " << l << " has "
<< "fraction > " << z << " = " << cdf(complement(np95pc, z)) << endl;
//] [/find_location2]
}
catch(const std::exception& e)
{ // Always useful to include try & catch blocks because default policies
// are to throw exceptions on arguments that cause errors like underflow, overflow.
// Lacking try & catch blocks, the program will abort without a message below,
// which may give some helpful clues as to the cause of the exception.
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
return 0;
} // int main()
//[find_location_example_output
/*`
[pre
Example: Find location (mean).
Normal distribution with mean = 0, standard deviation 1, has fraction <= -2, p = 0.0227501
Normal distribution with mean = 0, standard deviation 1, has fraction > -2, p = 0.97725
offset location (mean) = 1.09023
Normal distribution with mean = 1.09023 has fraction <= -2, p = 0.001
Normal distribution with mean = 1.09023 has fraction > -2, p = 0.999
Normal distribution with mean = 0.355146 has fraction <= 2 = 0.95
Normal distribution with mean = 0.355146 has fraction > 2 = 0.05
]
*/
//] [/find_location_example_output]

View File

@@ -0,0 +1,408 @@
// find_mean_and_sd_normal.cpp
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Example of finding mean or sd for normal distribution.
// Note that this file contains Quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[normal_std
/*`
First we need some includes to access the normal distribution,
the algorithms to find location and scale
(and some std output of course).
*/
#include <boost/math/distributions/normal.hpp> // for normal_distribution
using boost::math::normal; // typedef provides default type is double.
#include <boost/math/distributions/cauchy.hpp> // for cauchy_distribution
using boost::math::cauchy; // typedef provides default type is double.
#include <boost/math/distributions/find_location.hpp>
using boost::math::find_location;
#include <boost/math/distributions/find_scale.hpp>
using boost::math::find_scale;
using boost::math::complement;
using boost::math::policies::policy;
#include <iostream>
using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint;
#include <iomanip>
using std::setw; using std::setprecision;
#include <limits>
using std::numeric_limits;
//] [/normal_std Quickbook]
int main()
{
cout << "Find_location (mean) and find_scale (standard deviation) examples." << endl;
try
{
//[normal_find_location_and_scale_eg
/*`
[h4 Using find_location and find_scale to meet dispensing and measurement specifications]
Consider an example from K Krishnamoorthy,
Handbook of Statistical Distributions with Applications,
ISBN 1-58488-635-8, (2006) p 126, example 10.3.7.
"A machine is set to pack 3 kg of ground beef per pack.
Over a long period of time it is found that the average packed was 3 kg
with a standard deviation of 0.1 kg.
Assume the packing is normally distributed."
We start by constructing a normal distribution with the given parameters:
*/
double mean = 3.; // kg
double standard_deviation = 0.1; // kg
normal packs(mean, standard_deviation);
/*`We can then find the fraction (or %) of packages that weigh more than 3.1 kg.
*/
double max_weight = 3.1; // kg
cout << "Percentage of packs > " << max_weight << " is "
<< cdf(complement(packs, max_weight)) * 100. << endl; // P(X > 3.1)
/*`We might want to ensure that 95% of packs are over a minimum weight specification,
then we want the value of the mean such that P(X < 2.9) = 0.05.
Using the mean of 3 kg, we can estimate
the fraction of packs that fail to meet the specification of 2.9 kg.
*/
double minimum_weight = 2.9;
cout <<"Fraction of packs <= " << minimum_weight << " with a mean of " << mean
<< " is " << cdf(complement(packs, minimum_weight)) << endl;
// fraction of packs <= 2.9 with a mean of 3 is 0.841345
/*`This is 0.84 - more than the target fraction of 0.95.
If we want 95% to be over the minimum weight,
what should we set the mean weight to be?
Using the KK StatCalc program supplied with the book and the method given on page 126 gives 3.06449.
We can confirm this by constructing a new distribution which we call 'xpacks'
with a safety margin mean of 3.06449 thus:
*/
double over_mean = 3.06449;
normal xpacks(over_mean, standard_deviation);
cout << "Fraction of packs >= " << minimum_weight
<< " with a mean of " << xpacks.mean()
<< " is " << cdf(complement(xpacks, minimum_weight)) << endl;
// fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005
/*`Using this Math Toolkit, we can calculate the required mean directly thus:
*/
double under_fraction = 0.05; // so 95% are above the minimum weight mean - sd = 2.9
double low_limit = standard_deviation;
double offset = mean - low_limit - quantile(packs, under_fraction);
double nominal_mean = mean + offset;
// mean + (mean - low_limit - quantile(packs, under_fraction));
normal nominal_packs(nominal_mean, standard_deviation);
cout << "Setting the packer to " << nominal_mean << " will mean that "
<< "fraction of packs >= " << minimum_weight
<< " is " << cdf(complement(nominal_packs, minimum_weight)) << endl;
// Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95
/*`
This calculation is generalized as the free function called
[link math_toolkit.dist.dist_ref.dist_algorithms find_location].
To use this we will need to
*/
#include <boost/math/distributions/find_location.hpp>
using boost::math::find_location;
/*`and then use find_location function to find safe_mean,
& construct a new normal distribution called 'goodpacks'.
*/
double safe_mean = find_location<normal>(minimum_weight, under_fraction, standard_deviation);
normal good_packs(safe_mean, standard_deviation);
/*`with the same confirmation as before:
*/
cout << "Setting the packer to " << nominal_mean << " will mean that "
<< "fraction of packs >= " << minimum_weight
<< " is " << cdf(complement(good_packs, minimum_weight)) << endl;
// Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95
/*`
[h4 Using Cauchy-Lorentz instead of normal distribution]
After examining the weight distribution of a large number of packs, we might decide that,
after all, the assumption of a normal distribution is not really justified.
We might find that the fit is better to a __cauchy_distrib.
This distribution has wider 'wings', so that whereas most of the values
are closer to the mean than the normal, there are also more values than 'normal'
that lie further from the mean than the normal.
This might happen because a larger than normal lump of meat is either included or excluded.
We first create a __cauchy_distrib with the original mean and standard deviation,
and estimate the fraction that lie below our minimum weight specification.
*/
cauchy cpacks(mean, standard_deviation);
cout << "Cauchy Setting the packer to " << mean << " will mean that "
<< "fraction of packs >= " << minimum_weight
<< " is " << cdf(complement(cpacks, minimum_weight)) << endl;
// Cauchy Setting the packer to 3 will mean that fraction of packs >= 2.9 is 0.75
/*`Note that far fewer of the packs meet the specification, only 75% instead of 95%.
Now we can repeat the find_location, using the cauchy distribution as template parameter,
in place of the normal used above.
*/
double lc = find_location<cauchy>(minimum_weight, under_fraction, standard_deviation);
cout << "find_location<cauchy>(minimum_weight, over fraction, standard_deviation); " << lc << endl;
// find_location<cauchy>(minimum_weight, over fraction, packs.standard_deviation()); 3.53138
/*`Note that the safe_mean setting needs to be much higher, 3.53138 instead of 3.06449,
so we will make rather less profit.
And again confirm that the fraction meeting specification is as expected.
*/
cauchy goodcpacks(lc, standard_deviation);
cout << "Cauchy Setting the packer to " << lc << " will mean that "
<< "fraction of packs >= " << minimum_weight
<< " is " << cdf(complement(goodcpacks, minimum_weight)) << endl;
// Cauchy Setting the packer to 3.53138 will mean that fraction of packs >= 2.9 is 0.95
/*`Finally we could estimate the effect of a much tighter specification,
that 99% of packs met the specification.
*/
cout << "Cauchy Setting the packer to "
<< find_location<cauchy>(minimum_weight, 0.99, standard_deviation)
<< " will mean that "
<< "fraction of packs >= " << minimum_weight
<< " is " << cdf(complement(goodcpacks, minimum_weight)) << endl;
/*`Setting the packer to 3.13263 will mean that fraction of packs >= 2.9 is 0.99,
but will more than double the mean loss from 0.0644 to 0.133 kg per pack.
Of course, this calculation is not limited to packs of meat, it applies to dispensing anything,
and it also applies to a 'virtual' material like any measurement.
The only caveat is that the calculation assumes that the standard deviation (scale) is known with
a reasonably low uncertainty, something that is not so easy to ensure in practice.
And that the distribution is well defined, __normal_distrib or __cauchy_distrib, or some other.
If one is simply dispensing a very large number of packs,
then it may be feasible to measure the weight of hundreds or thousands of packs.
With a healthy 'degrees of freedom', the confidence intervals for the standard deviation
are not too wide, typically about + and - 10% for hundreds of observations.
For other applications, where it is more difficult or expensive to make many observations,
the confidence intervals are depressingly wide.
See [link math_toolkit.dist.stat_tut.weg.cs_eg.chi_sq_intervals Confidence Intervals on the standard deviation]
for a worked example
[@../../example/chi_square_std_dev_test.cpp chi_square_std_dev_test.cpp]
of estimating these intervals.
[h4 Changing the scale or standard deviation]
Alternatively, we could invest in a better (more precise) packer
(or measuring device) with a lower standard deviation, or scale.
This might cost more, but would reduce the amount we have to 'give away'
in order to meet the specification.
To estimate how much better (how much smaller standard deviation) it would have to be,
we need to get the 5% quantile to be located at the under_weight limit, 2.9
*/
double p = 0.05; // wanted p th quantile.
cout << "Quantile of " << p << " = " << quantile(packs, p)
<< ", mean = " << packs.mean() << ", sd = " << packs.standard_deviation() << endl;
/*`
Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1
With the current packer (mean = 3, sd = 0.1), the 5% quantile is at 2.8551 kg,
a little below our target of 2.9 kg.
So we know that the standard deviation is going to have to be smaller.
Let's start by guessing that it (now 0.1) needs to be halved, to a standard deviation of 0.05 kg.
*/
normal pack05(mean, 0.05);
cout << "Quantile of " << p << " = " << quantile(pack05, p)
<< ", mean = " << pack05.mean() << ", sd = " << pack05.standard_deviation() << endl;
// Quantile of 0.05 = 2.91776, mean = 3, sd = 0.05
cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean
<< " and standard deviation of " << pack05.standard_deviation()
<< " is " << cdf(complement(pack05, minimum_weight)) << endl;
// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.97725
/*`
So 0.05 was quite a good guess, but we are a little over the 2.9 target,
so the standard deviation could be a tiny bit more. So we could do some
more guessing to get closer, say by increasing standard deviation to 0.06 kg,
constructing another new distribution called pack06.
*/
normal pack06(mean, 0.06);
cout << "Quantile of " << p << " = " << quantile(pack06, p)
<< ", mean = " << pack06.mean() << ", sd = " << pack06.standard_deviation() << endl;
// Quantile of 0.05 = 2.90131, mean = 3, sd = 0.06
cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean
<< " and standard deviation of " << pack06.standard_deviation()
<< " is " << cdf(complement(pack06, minimum_weight)) << endl;
// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.95221
/*`
Now we are getting really close, but to do the job properly,
we might need to use root finding method, for example the tools provided,
and used elsewhere, in the Math Toolkit, see
[link math_toolkit.toolkit.internals1.roots2 Root Finding Without Derivatives].
But in this (normal) distribution case, we can and should be even smarter
and make a direct calculation.
*/
/*`Our required limit is minimum_weight = 2.9 kg, often called the random variate z.
For a standard normal distribution, then probability p = N((minimum_weight - mean) / sd).
We want to find the standard deviation that would be required to meet this limit,
so that the p th quantile is located at z (minimum_weight).
In this case, the 0.05 (5%) quantile is at 2.9 kg pack weight, when the mean is 3 kg,
ensuring that 0.95 (95%) of packs are above the minimum weight.
Rearranging, we can directly calculate the required standard deviation:
*/
normal N01; // standard normal distribution with meamn zero and unit standard deviation.
p = 0.05;
double qp = quantile(N01, p);
double sd95 = (minimum_weight - mean) / qp;
cout << "For the "<< p << "th quantile to be located at "
<< minimum_weight << ", would need a standard deviation of " << sd95 << endl;
// For the 0.05th quantile to be located at 2.9, would need a standard deviation of 0.0607957
/*`We can now construct a new (normal) distribution pack95 for the 'better' packer,
and check that our distribution will meet the specification.
*/
normal pack95(mean, sd95);
cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean
<< " and standard deviation of " << pack95.standard_deviation()
<< " is " << cdf(complement(pack95, minimum_weight)) << endl;
// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95
/*`This calculation is generalized in the free function find_scale,
as shown below, giving the same standard deviation.
*/
double ss = find_scale<normal>(minimum_weight, under_fraction, packs.mean());
cout << "find_scale<normal>(minimum_weight, under_fraction, packs.mean()); " << ss << endl;
// find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957
/*`If we had defined an over_fraction, or percentage that must pass specification
*/
double over_fraction = 0.95;
/*`And (wrongly) written
double sso = find_scale<normal>(minimum_weight, over_fraction, packs.mean());
With the default policy, we would get a message like
[pre
Message from thrown exception was:
Error in function boost::math::find_scale<Dist, Policy>(double, double, double, Policy):
Computed scale (-0.060795683191176959) is <= 0! Was the complement intended?
]
But this would return a *negative* standard deviation - obviously impossible.
The probability should be 1 - over_fraction, not over_fraction, thus:
*/
double ss1o = find_scale<normal>(minimum_weight, 1 - over_fraction, packs.mean());
cout << "find_scale<normal>(minimum_weight, under_fraction, packs.mean()); " << ss1o << endl;
// find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957
/*`But notice that using '1 - over_fraction' - will lead to a
[link why_complements loss of accuracy, especially if over_fraction was close to unity.]
In this (very common) case, we should instead use the __complements,
giving the most accurate result.
*/
double ssc = find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean()));
cout << "find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean())); " << ssc << endl;
// find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean())); 0.0607957
/*`Note that our guess of 0.06 was close to the accurate value of 0.060795683191176959.
We can again confirm our prediction thus:
*/
normal pack95c(mean, ssc);
cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean
<< " and standard deviation of " << pack95c.standard_deviation()
<< " is " << cdf(complement(pack95c, minimum_weight)) << endl;
// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95
/*`Notice that these two deceptively simple questions:
* Do we over-fill to make sure we meet a minimum specification (or under-fill to avoid an overdose)?
and/or
* Do we measure better?
are actually extremely common.
The weight of beef might be replaced by a measurement of more or less anything,
from drug tablet content, Apollo landing rocket firing, X-ray treatment doses...
The scale can be variation in dispensing or uncertainty in measurement.
*/
//] [/normal_find_location_and_scale_eg Quickbook end]
}
catch(const std::exception& e)
{ // Always useful to include try & catch blocks because default policies
// are to throw exceptions on arguments that cause errors like underflow, overflow.
// Lacking try & catch blocks, the program will abort without a message below,
// which may give some helpful clues as to the cause of the exception.
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
return 0;
} // int main()
/*
Output is:
Find_location and find_scale examples.
Percentage of packs > 3.1 is 15.8655
Fraction of packs <= 2.9 with a mean of 3 is 0.841345
Fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005
Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95
Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95
Cauchy Setting the packer to 3 will mean that fraction of packs >= 2.9 is 0.75
find_location<cauchy>(minimum_weight, over fraction, standard_deviation); 3.53138
Cauchy Setting the packer to 3.53138 will mean that fraction of packs >= 2.9 is 0.95
Cauchy Setting the packer to -0.282052 will mean that fraction of packs >= 2.9 is 0.95
Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1
Quantile of 0.05 = 2.91776, mean = 3, sd = 0.05
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.97725
Quantile of 0.05 = 2.90131, mean = 3, sd = 0.06
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.95221
For the 0.05th quantile to be located at 2.9, would need a standard deviation of 0.0607957
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95
find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957
find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957
find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean())); 0.0607957
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95
*/

View File

@@ -0,0 +1,239 @@
// find_root_example.cpp
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Example of using root finding.
// Note that this file contains Quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[root_find1
/*`
First we need some includes to access the normal distribution
(and some std output of course).
*/
#include <boost/math/tools/roots.hpp> // root finding.
#include <boost/math/distributions/normal.hpp> // for normal_distribution
using boost::math::normal; // typedef provides default type is double.
#include <iostream>
using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint;
#include <iomanip>
using std::setw; using std::setprecision;
#include <limits>
using std::numeric_limits;
//] //[/root_find1]
namespace boost{ namespace math { namespace tools
{
template <class F, class T, class Tol>
inline std::pair<T, T> bracket_and_solve_root(F f, // functor
const T& guess,
const T& factor,
bool rising,
Tol tol, // binary functor specifying termination when tol(min, max) becomes true.
// eps_tolerance most suitable for this continuous function
boost::uintmax_t& max_iter); // explicit (rather than default) max iterations.
// return interval as a pair containing result.
namespace detail
{
// Functor for finding standard deviation:
template <class RealType, class Policy>
struct standard_deviation_functor
{
standard_deviation_functor(RealType m, RealType s, RealType d)
: mean(m), standard_deviation(s)
{
}
RealType operator()(const RealType& sd)
{ // Unary functor - the function whose root is to be found.
if(sd <= tools::min_value<RealType>())
{ //
return 1;
}
normal_distribution<RealType, Policy> t(mean, sd);
RealType qa = quantile(complement(t, alpha));
RealType qb = quantile(complement(t, beta));
qa += qb;
qa *= qa;
qa *= ratio;
qa -= (df + 1);
return qa;
} // operator()
RealType mean;
RealType standard_deviation;
}; // struct standard_deviation_functor
} // namespace detail
template <class RealType, class Policy>
RealType normal_distribution<RealType, Policy>::find_standard_deviation(
RealType difference_from_mean,
RealType mean,
RealType sd,
RealType hint) // Best guess available - current sd if none better?
{
static const char* function = "boost::math::normal_distribution<%1%>::find_standard_deviation";
// Check for domain errors:
RealType error_result;
if(false == detail::check_probability(
function, sd, &error_result, Policy())
)
return error_result;
if(hint <= 0)
{ // standard deviation can never be negative.
hint = 1;
}
detail::standard_deviation_functor<RealType, Policy> f(mean, sd, difference_from_mean);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = 100;
std::pair<RealType, RealType> r = tools::bracket_and_solve_root(f, hint, RealType(2), false, tol, max_iter, Policy());
RealType result = r.first + (r.second - r.first) / 2;
if(max_iter == 100)
{
policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" either there is no answer to how many degrees of freedom are required"
" or the answer is infinite. Current best guess is %1%", result, Policy());
}
return result;
} // find_standard_deviation
} // namespace tools
} // namespace math
} // namespace boost
int main()
{
cout << "Example: Normal distribution, root finding.";
try
{
//[root_find2
/*`A machine is set to pack 3 kg of ground beef per pack.
Over a long period of time it is found that the average packed was 3 kg
with a standard deviation of 0.1 kg.
Assuming the packing is normally distributed,
we can find the fraction (or %) of packages that weigh more than 3.1 kg.
*/
double mean = 3.; // kg
double standard_deviation = 0.1; // kg
normal packs(mean, standard_deviation);
double max_weight = 3.1; // kg
cout << "Percentage of packs > " << max_weight << " is "
<< cdf(complement(packs, max_weight)) << endl; // P(X > 3.1)
double under_weight = 2.9;
cout <<"fraction of packs <= " << under_weight << " with a mean of " << mean
<< " is " << cdf(complement(packs, under_weight)) << endl;
// fraction of packs <= 2.9 with a mean of 3 is 0.841345
// This is 0.84 - more than the target 0.95
// Want 95% to be over this weight, so what should we set the mean weight to be?
// KK StatCalc says:
double over_mean = 3.0664;
normal xpacks(over_mean, standard_deviation);
cout << "fraction of packs >= " << under_weight
<< " with a mean of " << xpacks.mean()
<< " is " << cdf(complement(xpacks, under_weight)) << endl;
// fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005
double under_fraction = 0.05; // so 95% are above the minimum weight mean - sd = 2.9
double low_limit = standard_deviation;
double offset = mean - low_limit - quantile(packs, under_fraction);
double nominal_mean = mean + offset;
normal nominal_packs(nominal_mean, standard_deviation);
cout << "Setting the packer to " << nominal_mean << " will mean that "
<< "fraction of packs >= " << under_weight
<< " is " << cdf(complement(nominal_packs, under_weight)) << endl;
/*`
Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95.
Setting the packer to 3.13263 will mean that fraction of packs >= 2.9 is 0.99,
but will more than double the mean loss from 0.0644 to 0.133.
Alternatively, we could invest in a better (more precise) packer with a lower standard deviation.
To estimate how much better (how much smaller standard deviation) it would have to be,
we need to get the 5% quantile to be located at the under_weight limit, 2.9
*/
double p = 0.05; // wanted p th quantile.
cout << "Quantile of " << p << " = " << quantile(packs, p)
<< ", mean = " << packs.mean() << ", sd = " << packs.standard_deviation() << endl; //
/*`
Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1
With the current packer (mean = 3, sd = 0.1), the 5% quantile is at 2.8551 kg,
a little below our target of 2.9 kg.
So we know that the standard deviation is going to have to be smaller.
Let's start by guessing that it (now 0.1) needs to be halved, to a standard deviation of 0.05
*/
normal pack05(mean, 0.05);
cout << "Quantile of " << p << " = " << quantile(pack05, p)
<< ", mean = " << pack05.mean() << ", sd = " << pack05.standard_deviation() << endl;
cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean
<< " and standard deviation of " << pack05.standard_deviation()
<< " is " << cdf(complement(pack05, under_weight)) << endl;
//
/*`
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.9772
So 0.05 was quite a good guess, but we are a little over the 2.9 target,
so the standard deviation could be a tiny bit more. So we could do some
more guessing to get closer, say by increasing to 0.06
*/
normal pack06(mean, 0.06);
cout << "Quantile of " << p << " = " << quantile(pack06, p)
<< ", mean = " << pack06.mean() << ", sd = " << pack06.standard_deviation() << endl;
cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean
<< " and standard deviation of " << pack06.standard_deviation()
<< " is " << cdf(complement(pack06, under_weight)) << endl;
/*`
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.9522
Now we are getting really close, but to do the job properly,
we could use root finding method, for example the tools provided, and used elsewhere,
in the Math Toolkit, see
[link math_toolkit.toolkit.internals1.roots2 Root Finding Without Derivatives].
But in this normal distribution case, we could be even smarter and make a direct calculation.
*/
//] [/root_find2]
}
catch(const std::exception& e)
{ // Always useful to include try & catch blocks because default policies
// are to throw exceptions on arguments that cause errors like underflow, overflow.
// Lacking try & catch blocks, the program will abort without a message below,
// which may give some helpful clues as to the cause of the exception.
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
return 0;
} // int main()
/*
Output is:
*/

View File

@@ -0,0 +1,180 @@
// find_scale.cpp
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Example of finding scale (standard deviation) for normal (Gaussian).
// Note that this file contains Quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[find_scale1
/*`
First we need some includes to access the __normal_distrib,
the algorithms to find scale (and some std output of course).
*/
#include <boost/math/distributions/normal.hpp> // for normal_distribution
using boost::math::normal; // typedef provides default type is double.
#include <boost/math/distributions/find_scale.hpp>
using boost::math::find_scale;
using boost::math::complement; // Needed if you want to use the complement version.
using boost::math::policies::policy; // Needed to specify the error handling policy.
#include <iostream>
using std::cout; using std::endl;
#include <iomanip>
using std::setw; using std::setprecision;
#include <limits>
using std::numeric_limits;
//] [/find_scale1]
int main()
{
cout << "Example: Find scale (standard deviation)." << endl;
try
{
//[find_scale2
/*`
For this example, we will use the standard __normal_distrib,
with location (mean) zero and standard deviation (scale) unity.
Conveniently, this is also the default for this implementation's constructor.
*/
normal N01; // Default 'standard' normal distribution with zero mean
double sd = 1.; // and standard deviation is 1.
/*`Suppose we want to find a different normal distribution with standard deviation
so that only fraction p (here 0.001 or 0.1%) are below a certain chosen limit
(here -2. standard deviations).
*/
double z = -2.; // z to give prob p
double p = 0.001; // only 0.1% below z = -2
cout << "Normal distribution with mean = " << N01.location() // aka N01.mean()
<< ", standard deviation " << N01.scale() // aka N01.standard_deviation()
<< ", has " << "fraction <= " << z
<< ", p = " << cdf(N01, z) << endl;
cout << "Normal distribution with mean = " << N01.location()
<< ", standard deviation " << N01.scale()
<< ", has " << "fraction > " << z
<< ", p = " << cdf(complement(N01, z)) << endl; // Note: uses complement.
/*`
[pre
Normal distribution with mean = 0 has fraction <= -2, p = 0.0227501
Normal distribution with mean = 0 has fraction > -2, p = 0.97725
]
Noting that p = 0.02 instead of our target of 0.001,
we can now use `find_scale` to give a new standard deviation.
*/
double l = N01.location();
double s = find_scale<normal>(z, p, l);
cout << "scale (standard deviation) = " << s << endl;
/*`
that outputs:
[pre
scale (standard deviation) = 0.647201
]
showing that we need to reduce the standard deviation from 1. to 0.65.
Then we can check that we have achieved our objective
by constructing a new distribution
with the new standard deviation (but same zero mean):
*/
normal np001pc(N01.location(), s);
/*`
And re-calculating the fraction below (and above) our chosen limit.
*/
cout << "Normal distribution with mean = " << l
<< " has " << "fraction <= " << z
<< ", p = " << cdf(np001pc, z) << endl;
cout << "Normal distribution with mean = " << l
<< " has " << "fraction > " << z
<< ", p = " << cdf(complement(np001pc, z)) << endl;
/*`
[pre
Normal distribution with mean = 0 has fraction <= -2, p = 0.001
Normal distribution with mean = 0 has fraction > -2, p = 0.999
]
[h4 Controlling how Errors from find_scale are handled]
We can also control the policy for handling various errors.
For example, we can define a new (possibly unwise)
policy to ignore domain errors ('bad' arguments).
Unless we are using the boost::math namespace, we will need:
*/
using boost::math::policies::policy;
using boost::math::policies::domain_error;
using boost::math::policies::ignore_error;
/*`
Using a typedef is convenient, especially if it is re-used,
although it is not required, as the various examples below show.
*/
typedef policy<domain_error<ignore_error> > ignore_domain_policy;
// find_scale with new policy, using typedef.
l = find_scale<normal>(z, p, l, ignore_domain_policy());
// Default policy policy<>, needs using boost::math::policies::policy;
l = find_scale<normal>(z, p, l, policy<>());
// Default policy, fully specified.
l = find_scale<normal>(z, p, l, boost::math::policies::policy<>());
// New policy, without typedef.
l = find_scale<normal>(z, p, l, policy<domain_error<ignore_error> >());
/*`
If we want to express a probability, say 0.999, that is a complement, `1 - p`
we should not even think of writing `find_scale<normal>(z, 1 - p, l)`,
but [link why_complements instead], use the __complements version.
*/
z = -2.;
double q = 0.999; // = 1 - p; // complement of 0.001.
sd = find_scale<normal>(complement(z, q, l));
normal np95pc(l, sd); // Same standard_deviation (scale) but with mean(scale) shifted
cout << "Normal distribution with mean = " << l << " has "
<< "fraction <= " << z << " = " << cdf(np95pc, z) << endl;
cout << "Normal distribution with mean = " << l << " has "
<< "fraction > " << z << " = " << cdf(complement(np95pc, z)) << endl;
/*`
Sadly, it is all too easy to get probabilities the wrong way round,
when you may get a warning like this:
[pre
Message from thrown exception was:
Error in function boost::math::find_scale<Dist, Policy>(complement(double, double, double, Policy)):
Computed scale (-0.48043523852179076) is <= 0! Was the complement intended?
]
The default error handling policy is to throw an exception with this message,
but if you chose a policy to ignore the error,
the (impossible) negative scale is quietly returned.
*/
//] [/find_scale2]
}
catch(const std::exception& e)
{ // Always useful to include try & catch blocks because default policies
// are to throw exceptions on arguments that cause errors like underflow, overflow.
// Lacking try & catch blocks, the program will abort without a message below,
// which may give some helpful clues as to the cause of the exception.
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
return 0;
} // int main()
//[find_scale_example_output
/*`
[pre
Example: Find scale (standard deviation).
Normal distribution with mean = 0, standard deviation 1, has fraction <= -2, p = 0.0227501
Normal distribution with mean = 0, standard deviation 1, has fraction > -2, p = 0.97725
scale (standard deviation) = 0.647201
Normal distribution with mean = 0 has fraction <= -2, p = 0.001
Normal distribution with mean = 0 has fraction > -2, p = 0.999
Normal distribution with mean = 0.946339 has fraction <= -2 = 0.001
Normal distribution with mean = 0.946339 has fraction > -2 = 0.999
]
*/
//] [/find_scale_example_output]

View File

@@ -0,0 +1,179 @@
// neg_binomial_confidence_limits.cpp
// Copyright John Maddock 2006
// Copyright Paul A. Bristow 2007
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Caution: this file contains quickbook markup as well as code
// and comments, don't change any of the special comment markups!
//[neg_binomial_confidence_limits
/*`
First we need some includes to access the negative binomial distribution
(and some basic std output of course).
*/
#include <boost/math/distributions/negative_binomial.hpp>
using boost::math::negative_binomial;
#include <iostream>
using std::cout; using std::endl;
#include <iomanip>
using std::setprecision;
using std::setw; using std::left; using std::fixed; using std::right;
/*`
First define a table of significance levels: these are the
probabilities that the true occurrence frequency lies outside the calculated
interval:
*/
double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
/*`
Confidence value as % is (1 - alpha) * 100, so alpha 0.05 == 95% confidence
that the true occurence frequency lies *inside* the calculated interval.
We need a function to calculate and print confidence limits
for an observed frequency of occurrence
that follows a negative binomial distribution.
*/
void confidence_limits_on_frequency(unsigned trials, unsigned successes)
{
// trials = Total number of trials.
// successes = Total number of observed successes.
// failures = trials - successes.
// success_fraction = successes /trials.
// Print out general info:
cout <<
"______________________________________________\n"
"2-Sided Confidence Limits For Success Fraction\n"
"______________________________________________\n\n";
cout << setprecision(7);
cout << setw(40) << left << "Number of trials" << " = " << trials << "\n";
cout << setw(40) << left << "Number of successes" << " = " << successes << "\n";
cout << setw(40) << left << "Number of failures" << " = " << trials - successes << "\n";
cout << setw(40) << left << "Observed frequency of occurrence" << " = " << double(successes) / trials << "\n";
// Print table header:
cout << "\n\n"
"___________________________________________\n"
"Confidence Lower Upper\n"
" Value (%) Limit Limit\n"
"___________________________________________\n";
/*`
And now for the important part - the bounds themselves.
For each value of /alpha/, we call `find_lower_bound_on_p` and
`find_upper_bound_on_p` to obtain lower and upper bounds respectively.
Note that since we are calculating a two-sided interval,
we must divide the value of alpha in two. Had we been calculating a
single-sided interval, for example: ['"Calculate a lower bound so that we are P%
sure that the true occurrence frequency is greater than some value"]
then we would *not* have divided by two.
*/
// Now print out the upper and lower limits for the alpha table values.
for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
{
// Confidence value:
cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]);
// Calculate bounds:
double lower = negative_binomial::find_lower_bound_on_p(trials, successes, alpha[i]/2);
double upper = negative_binomial::find_upper_bound_on_p(trials, successes, alpha[i]/2);
// Print limits:
cout << fixed << setprecision(5) << setw(15) << right << lower;
cout << fixed << setprecision(5) << setw(15) << right << upper << endl;
}
cout << endl;
} // void confidence_limits_on_frequency(unsigned trials, unsigned successes)
/*`
And then call confidence_limits_on_frequency with increasing numbers of trials,
but always the same success fraction 0.1, or 1 in 10.
*/
int main()
{
confidence_limits_on_frequency(20, 2); // 20 trials, 2 successes, 2 in 20, = 1 in 10 = 0.1 success fraction.
confidence_limits_on_frequency(200, 20); // More trials, but same 0.1 success fraction.
confidence_limits_on_frequency(2000, 200); // Many more trials, but same 0.1 success fraction.
return 0;
} // int main()
//] [/negative_binomial_confidence_limits_eg end of Quickbook in C++ markup]
/*
______________________________________________
2-Sided Confidence Limits For Success Fraction
______________________________________________
Number of trials = 20
Number of successes = 2
Number of failures = 18
Observed frequency of occurrence = 0.1
___________________________________________
Confidence Lower Upper
Value (%) Limit Limit
___________________________________________
50.000 0.04812 0.13554
75.000 0.03078 0.17727
90.000 0.01807 0.22637
95.000 0.01235 0.26028
99.000 0.00530 0.33111
99.900 0.00164 0.41802
99.990 0.00051 0.49202
99.999 0.00016 0.55574
______________________________________________
2-Sided Confidence Limits For Success Fraction
______________________________________________
Number of trials = 200
Number of successes = 20
Number of failures = 180
Observed frequency of occurrence = 0.1000000
___________________________________________
Confidence Lower Upper
Value (%) Limit Limit
___________________________________________
50.000 0.08462 0.11350
75.000 0.07580 0.12469
90.000 0.06726 0.13695
95.000 0.06216 0.14508
99.000 0.05293 0.16170
99.900 0.04343 0.18212
99.990 0.03641 0.20017
99.999 0.03095 0.21664
______________________________________________
2-Sided Confidence Limits For Success Fraction
______________________________________________
Number of trials = 2000
Number of successes = 200
Number of failures = 1800
Observed frequency of occurrence = 0.1000000
___________________________________________
Confidence Lower Upper
Value (%) Limit Limit
___________________________________________
50.000 0.09536 0.10445
75.000 0.09228 0.10776
90.000 0.08916 0.11125
95.000 0.08720 0.11352
99.000 0.08344 0.11802
99.900 0.07921 0.12336
99.990 0.07577 0.12795
99.999 0.07282 0.13206
*/

View File

@@ -0,0 +1,202 @@
// neg_binomial_sample_sizes.cpp
// Copyright Paul A. Bristow 2007
// Copyright John Maddock 2006
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/math/distributions/negative_binomial.hpp>
using boost::math::negative_binomial;
// Default RealType is double so this permits use of:
double find_minimum_number_of_trials(
double k, // number of failures (events), k >= 0.
double p, // fraction of trails for which event occurs, 0 <= p <= 1.
double probability); // probability threshold, 0 <= probability <= 1.
#include <iostream>
using std::cout;
using std::endl;
using std::fixed;
using std::right;
#include <iomanip>
using std::setprecision;
using std::setw;
//[neg_binomial_sample_sizes
/*`
It centres around a routine that prints out
a table of minimum sample sizes for various probability thresholds:
*/
void find_number_of_trials(double failures, double p);
/*`
First define a table of significance levels: these are the maximum
acceptable probability that /failure/ or fewer events will be observed.
*/
double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
/*`
Confidence value as % is (1 - alpha) * 100, so alpha 0.05 == 95% confidence
that the desired number of failures will be observed.
Much of the rest of the program is pretty-printing, the important part
is in the calculation of minimum number of trials required for each
value of alpha using:
(int)ceil(negative_binomial::find_minimum_number_of_trials(failures, p, alpha[i]);
*/
/*`
find_minimum_number_of_trials returns a double,
so ceil rounds this up to ensure we have an integral minimum number of trials.
*/
void find_number_of_trials(double failures, double p)
{
// trials = number of trials
// failures = number of failures before achieving required success(es).
// p = success fraction (0 <= p <= 1.).
//
// Calculate how many trials we need to ensure the
// required number of failures DOES exceed "failures".
cout << "\n""Target number of failures = " << failures;
cout << ", Success fraction = " << 100 * p << "%" << endl;
// Print table header:
cout << "\n\n"
"____________________________\n"
"Confidence Min Number\n"
" Value (%) Of Trials \n"
"____________________________\n";
// Now print out the data for the alpha table values.
for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
{ // Confidence values %:
cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]) << " "
// find_minimum_number_of_trials
<< setw(6) << right
<< (int)ceil(negative_binomial::find_minimum_number_of_trials(failures, p, alpha[i]))
<< endl;
}
cout << endl;
} // void find_number_of_trials(double failures, double p)
/*` finally we can produce some tables of minimum trials for the chosen confidence levels:
*/
int main()
{
find_number_of_trials(5, 0.5);
find_number_of_trials(50, 0.5);
find_number_of_trials(500, 0.5);
find_number_of_trials(50, 0.1);
find_number_of_trials(500, 0.1);
find_number_of_trials(5, 0.9);
return 0;
} // int main()
//] [/neg_binomial_sample_sizes.cpp end of Quickbook in C++ markup]
/*
Output is:
Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\neg_binomial_sample_sizes.exe"
Target number of failures = 5, Success fraction = 50%
____________________________
Confidence Min Number
Value (%) Of Trials
____________________________
50.000 11
75.000 14
90.000 17
95.000 18
99.000 22
99.900 27
99.990 31
99.999 36
Target number of failures = 50.000, Success fraction = 50.000%
____________________________
Confidence Min Number
Value (%) Of Trials
____________________________
50.000 101
75.000 109
90.000 115
95.000 119
99.000 128
99.900 137
99.990 146
99.999 154
Target number of failures = 500.000, Success fraction = 50.000%
____________________________
Confidence Min Number
Value (%) Of Trials
____________________________
50.000 1001
75.000 1023
90.000 1043
95.000 1055
99.000 1078
99.900 1104
99.990 1126
99.999 1146
Target number of failures = 50.000, Success fraction = 10.000%
____________________________
Confidence Min Number
Value (%) Of Trials
____________________________
50.000 56
75.000 58
90.000 60
95.000 61
99.000 63
99.900 66
99.990 68
99.999 71
Target number of failures = 500.000, Success fraction = 10.000%
____________________________
Confidence Min Number
Value (%) Of Trials
____________________________
50.000 556
75.000 562
90.000 567
95.000 570
99.000 576
99.900 583
99.990 588
99.999 594
Target number of failures = 5.000, Success fraction = 90.000%
____________________________
Confidence Min Number
Value (%) Of Trials
____________________________
50.000 57
75.000 73
90.000 91
95.000 103
99.000 127
99.900 159
99.990 189
99.999 217
Target number of failures = 5.000, Success fraction = 40.000%
____________________________
Confidence Min Number
Value (%) Of Trials
____________________________
50.000 10
75.000 11
90.000 13
95.000 15
99.000 18
99.900 21
99.990 25
99.999 28
*/

View File

@@ -0,0 +1,521 @@
// negative_binomial_example1.cpp
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Example 1 of using negative_binomial distribution.
//[negative_binomial_eg1_1
/*`
Based on [@http://en.wikipedia.org/wiki/Negative_binomial_distribution
a problem by Dr. Diane Evans,
Professor of Mathematics at Rose-Hulman Institute of Technology].
Pat is required to sell candy bars to raise money for the 6th grade field trip.
There are thirty houses in the neighborhood,
and Pat is not supposed to return home until five candy bars have been sold.
So the child goes door to door, selling candy bars.
At each house, there is a 0.4 probability (40%) of selling one candy bar
and a 0.6 probability (60%) of selling nothing.
What is the probability mass (density) function (pdf) for selling the last (fifth)
candy bar at the nth house?
The Negative Binomial(r, p) distribution describes the probability of k failures
and r successes in k+r Bernoulli(p) trials with success on the last trial.
(A [@http://en.wikipedia.org/wiki/Bernoulli_distribution Bernoulli trial]
is one with only two possible outcomes, success of failure,
and p is the probability of success).
See also [@ http://en.wikipedia.org/wiki/Bernoulli_distribution Bernoulli distribution]
and [@http://www.math.uah.edu/stat/bernoulli/Introduction.xhtml Bernoulli applications].
In this example, we will deliberately produce a variety of calculations
and outputs to demonstrate the ways that the negative binomial distribution
can be implemented with this library: it is also deliberately over-commented.
First we need to #define macros to control the error and discrete handling policies.
For this simple example, we want to avoid throwing
an exception (the default policy) and just return infinity.
We want to treat the distribution as if it was continuous,
so we choose a discrete_quantile policy of real,
rather than the default policy integer_round_outwards.
*/
#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error
#define BOOST_MATH_DISCRETE_QUANTILE_POLICY real
/*`
After that we need some includes to provide easy access to the negative binomial distribution,
[caution It is vital to #include distributions etc *after* the above #defines]
and we need some std library iostream, of course.
*/
#include <boost/math/distributions/negative_binomial.hpp>
// for negative_binomial_distribution
using boost::math::negative_binomial; // typedef provides default type is double.
using ::boost::math::pdf; // Probability mass function.
using ::boost::math::cdf; // Cumulative density function.
using ::boost::math::quantile;
#include <iostream>
using std::cout; using std::endl;
using std::noshowpoint; using std::fixed; using std::right; using std::left;
#include <iomanip>
using std::setprecision; using std::setw;
#include <limits>
using std::numeric_limits;
//] [negative_binomial_eg1_1]
int main()
{
cout <<"Selling candy bars - using the negative binomial distribution."
<< "\nby Dr. Diane Evans,"
"\nProfessor of Mathematics at Rose-Hulman Institute of Technology,"
<< "\nsee http://en.wikipedia.org/wiki/Negative_binomial_distribution\n"
<< endl;
cout << endl;
cout.precision(5);
// None of the values calculated have a useful accuracy as great this, but
// INF shows wrongly with < 5 !
// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=240227
//[negative_binomial_eg1_2
/*`
It is always sensible to use try and catch blocks because defaults policies are to
throw an exception if anything goes wrong.
A simple catch block (see below) will ensure that you get a
helpful error message instead of an abrupt program abort.
*/
try
{
/*`
Selling five candy bars means getting five successes, so successes r = 5.
The total number of trials (n, in this case, houses visited) this takes is therefore
= sucesses + failures or k + r = k + 5.
*/
double sales_quota = 5; // Pat's sales quota - successes (r).
/*`
At each house, there is a 0.4 probability (40%) of selling one candy bar
and a 0.6 probability (60%) of selling nothing.
*/
double success_fraction = 0.4; // success_fraction (p) - so failure_fraction is 0.6.
/*`
The Negative Binomial(r, p) distribution describes the probability of k failures
and r successes in k+r Bernoulli(p) trials with success on the last trial.
(A [@http://en.wikipedia.org/wiki/Bernoulli_distribution Bernoulli trial]
is one with only two possible outcomes, success of failure,
and p is the probability of success).
We therefore start by constructing a negative binomial distribution
with parameters sales_quota (required successes) and probability of success.
*/
negative_binomial nb(sales_quota, success_fraction); // type double by default.
/*`
To confirm, display the success_fraction & successes parameters of the distribution.
*/
cout << "Pat has a sales per house success rate of " << success_fraction
<< ".\nTherefore he would, on average, sell " << nb.success_fraction() * 100
<< " bars after trying 100 houses." << endl;
int all_houses = 30; // The number of houses on the estate.
cout << "With a success rate of " << nb.success_fraction()
<< ", he might expect, on average,\n"
"to need to visit about " << success_fraction * all_houses
<< " houses in order to sell all " << nb.successes() << " bars. " << endl;
/*`
[pre
Pat has a sales per house success rate of 0.4.
Therefore he would, on average, sell 40 bars after trying 100 houses.
With a success rate of 0.4, he might expect, on average,
to need to visit about 12 houses in order to sell all 5 bars.
]
The random variable of interest is the number of houses
that must be visited to sell five candy bars,
so we substitute k = n - 5 into a negative_binomial(5, 0.4)
and obtain the [link math.dist.pdf probability mass (density) function (pdf or pmf)]
of the distribution of houses visited.
Obviously, the best possible case is that Pat makes sales on all the first five houses.
We calculate this using the pdf function:
*/
cout << "Probability that Pat finishes on the " << sales_quota << "th house is "
<< pdf(nb, 5 - sales_quota) << endl; // == pdf(nb, 0)
/*`
Of course, he could not finish on fewer than 5 houses because he must sell 5 candy bars.
So the 5th house is the first that he could possibly finish on.
To finish on or before the 8th house, Pat must finish at the 5th, 6th, 7th or 8th house.
The probability that he will finish on *exactly* ( == ) on any house
is the Probability Density Function (pdf).
*/
cout << "Probability that Pat finishes on the 6th house is "
<< pdf(nb, 6 - sales_quota) << endl;
cout << "Probability that Pat finishes on the 7th house is "
<< pdf(nb, 7 - sales_quota) << endl;
cout << "Probability that Pat finishes on the 8th house is "
<< pdf(nb, 8 - sales_quota) << endl;
/*`
[pre
Probability that Pat finishes on the 6th house is 0.03072
Probability that Pat finishes on the 7th house is 0.055296
Probability that Pat finishes on the 8th house is 0.077414
]
The sum of the probabilities for these houses is the Cumulative Distribution Function (cdf).
We can calculate it by adding the individual probabilities.
*/
cout << "Probability that Pat finishes on or before the 8th house is sum "
"\n" << "pdf(sales_quota) + pdf(6) + pdf(7) + pdf(8) = "
// Sum each of the mass/density probabilities for houses sales_quota = 5, 6, 7, & 8.
<< pdf(nb, 5 - sales_quota) // 0 failures.
+ pdf(nb, 6 - sales_quota) // 1 failure.
+ pdf(nb, 7 - sales_quota) // 2 failures.
+ pdf(nb, 8 - sales_quota) // 3 failures.
<< endl;
/*`[pre
pdf(sales_quota) + pdf(6) + pdf(7) + pdf(8) = 0.17367
]
Or, usually better, by using the negative binomial *cumulative* distribution function.
*/
cout << "\nProbability of selling his quota of " << sales_quota
<< " bars\non or before the " << 8 << "th house is "
<< cdf(nb, 8 - sales_quota) << endl;
/*`[pre
Probability of selling his quota of 5 bars on or before the 8th house is 0.17367
]*/
cout << "\nProbability that Pat finishes exactly on the 10th house is "
<< pdf(nb, 10 - sales_quota) << endl;
cout << "\nProbability of selling his quota of " << sales_quota
<< " bars\non or before the " << 10 << "th house is "
<< cdf(nb, 10 - sales_quota) << endl;
/*`
[pre
Probability that Pat finishes exactly on the 10th house is 0.10033
Probability of selling his quota of 5 bars on or before the 10th house is 0.3669
]*/
cout << "Probability that Pat finishes exactly on the 11th house is "
<< pdf(nb, 11 - sales_quota) << endl;
cout << "\nProbability of selling his quota of " << sales_quota
<< " bars\non or before the " << 11 << "th house is "
<< cdf(nb, 11 - sales_quota) << endl;
/*`[pre
Probability that Pat finishes on the 11th house is 0.10033
Probability of selling his quota of 5 candy bars
on or before the 11th house is 0.46723
]*/
cout << "Probability that Pat finishes exactly on the 12th house is "
<< pdf(nb, 12 - sales_quota) << endl;
cout << "\nProbability of selling his quota of " << sales_quota
<< " bars\non or before the " << 12 << "th house is "
<< cdf(nb, 12 - sales_quota) << endl;
/*`[pre
Probability that Pat finishes on the 12th house is 0.094596
Probability of selling his quota of 5 candy bars
on or before the 12th house is 0.56182
]
Finally consider the risk of Pat not selling his quota of 5 bars
even after visiting all the houses.
Calculate the probability that he /will/ sell on
or before the last house:
Calculate the probability that he would sell all his quota on the very last house.
*/
cout << "Probability that Pat finishes on the " << all_houses
<< " house is " << pdf(nb, all_houses - sales_quota) << endl;
/*`
Probability of selling his quota of 5 bars on the 30th house is
[pre
Probability that Pat finishes on the 30 house is 0.00069145
]
when he'd be very unlucky indeed!
What is the probability that Pat exhausts all 30 houses in the neighborhood,
and *still* doesn't sell the required 5 candy bars?
*/
cout << "\nProbability of selling his quota of " << sales_quota
<< " bars\non or before the " << all_houses << "th house is "
<< cdf(nb, all_houses - sales_quota) << endl;
/*`
[pre
Probability of selling his quota of 5 bars
on or before the 30th house is 0.99849
]
/*`So the risk of failing even after visiting all the houses is 1 - this probability,
``1 - cdf(nb, all_houses - sales_quota``
But using this expression may cause serious inaccuracy,
so it would be much better to use the complement of the cdf:
So the risk of failing even at, or after, the 31th (non-existent) houses is 1 - this probability,
``1 - cdf(nb, all_houses - sales_quota)``
But using this expression may cause serious inaccuracy.
So it would be much better to use the complement of the cdf.
[link why_complements Why complements?]
*/
cout << "\nProbability of failing to sell his quota of " << sales_quota
<< " bars\neven after visiting all " << all_houses << " houses is "
<< cdf(complement(nb, all_houses - sales_quota)) << endl;
/*`
[pre
Probability of failing to sell his quota of 5 bars
even after visiting all 30 houses is 0.0015101
]
We can also use the quantile (percentile), the inverse of the cdf, to
predict which house Pat will finish on. So for the 8th house:
*/
double p = cdf(nb, (8 - sales_quota));
cout << "Probability of meeting sales quota on or before 8th house is "<< p << endl;
/*`
[pre
Probability of meeting sales quota on or before 8th house is 0.174
]
*/
cout << "If the confidence of meeting sales quota is " << p
<< ", then the finishing house is " << quantile(nb, p) + sales_quota << endl;
cout<< " quantile(nb, p) = " << quantile(nb, p) << endl;
/*`
[pre
If the confidence of meeting sales quota is 0.17367, then the finishing house is 8
]
Demanding absolute certainty that all 5 will be sold,
implies an infinite number of trials.
(Of course, there are only 30 houses on the estate,
so he can't ever be *certain* of selling his quota).
*/
cout << "If the confidence of meeting sales quota is " << 1.
<< ", then the finishing house is " << quantile(nb, 1) + sales_quota << endl;
// 1.#INF == infinity.
/*`[pre
If the confidence of meeting sales quota is 1, then the finishing house is 1.#INF
]
And similarly for a few other probabilities:
*/
cout << "If the confidence of meeting sales quota is " << 0.
<< ", then the finishing house is " << quantile(nb, 0.) + sales_quota << endl;
cout << "If the confidence of meeting sales quota is " << 0.5
<< ", then the finishing house is " << quantile(nb, 0.5) + sales_quota << endl;
cout << "If the confidence of meeting sales quota is " << 1 - 0.00151 // 30 th
<< ", then the finishing house is " << quantile(nb, 1 - 0.00151) + sales_quota << endl;
/*`
[pre
If the confidence of meeting sales quota is 0, then the finishing house is 5
If the confidence of meeting sales quota is 0.5, then the finishing house is 11.337
If the confidence of meeting sales quota is 0.99849, then the finishing house is 30
]
Notice that because we chose a discrete quantile policy of real,
the result can be an 'unreal' fractional house.
If the opposite is true, we don't want to assume any confidence, then this is tantamount
to assuming that all the first sales_quota trials will be successful sales.
*/
cout << "If confidence of meeting quota is zero\n(we assume all houses are successful sales)"
", then finishing house is " << sales_quota << endl;
/*`
[pre
If confidence of meeting quota is zero (we assume all houses are successful sales), then finishing house is 5
If confidence of meeting quota is 0, then finishing house is 5
]
We can list quantiles for a few probabilities:
*/
double ps[] = {0., 0.001, 0.01, 0.05, 0.1, 0.5, 0.9, 0.95, 0.99, 0.999, 1.};
// Confidence as fraction = 1-alpha, as percent = 100 * (1-alpha[i]) %
cout.precision(3);
for (int i = 0; i < sizeof(ps)/sizeof(ps[0]); i++)
{
cout << "If confidence of meeting quota is " << ps[i]
<< ", then finishing house is " << quantile(nb, ps[i]) + sales_quota
<< endl;
}
/*`
[pre
If confidence of meeting quota is 0, then finishing house is 5
If confidence of meeting quota is 0.001, then finishing house is 5
If confidence of meeting quota is 0.01, then finishing house is 5
If confidence of meeting quota is 0.05, then finishing house is 6.2
If confidence of meeting quota is 0.1, then finishing house is 7.06
If confidence of meeting quota is 0.5, then finishing house is 11.3
If confidence of meeting quota is 0.9, then finishing house is 17.8
If confidence of meeting quota is 0.95, then finishing house is 20.1
If confidence of meeting quota is 0.99, then finishing house is 24.8
If confidence of meeting quota is 0.999, then finishing house is 31.1
If confidence of meeting quota is 1, then finishing house is 1.#INF
]
We could have applied a ceil function to obtain a 'worst case' integer value for house.
``ceil(quantile(nb, ps[i]))``
Or, if we had used the default discrete quantile policy, integer_outside, by omitting
``#define BOOST_MATH_DISCRETE_QUANTILE_POLICY real``
we would have achieved the same effect.
The real result gives some suggestion which house is most likely.
For example, compare the real and integer_outside for 95% confidence.
[pre
If confidence of meeting quota is 0.95, then finishing house is 20.1
If confidence of meeting quota is 0.95, then finishing house is 21
]
The real value 20.1 is much closer to 20 than 21, so integer_outside is pessimistic.
We could also use integer_round_nearest policy to suggest that 20 is more likely.
Finally, we can tabulate the probability for the last sale being exactly on each house.
*/
cout << "\nHouse for " << sales_quota << "th (last) sale. Probability (%)" << endl;
cout.precision(5);
for (int i = (int)sales_quota; i < all_houses+1; i++)
{
cout << left << setw(3) << i << " " << setw(8) << cdf(nb, i - sales_quota) << endl;
}
cout << endl;
/*`
[pre
House for 5 th (last) sale. Probability (%)
5 0.01024
6 0.04096
7 0.096256
8 0.17367
9 0.26657
10 0.3669
11 0.46723
12 0.56182
13 0.64696
14 0.72074
15 0.78272
16 0.83343
17 0.874
18 0.90583
19 0.93039
20 0.94905
21 0.96304
22 0.97342
23 0.98103
24 0.98655
25 0.99053
26 0.99337
27 0.99539
28 0.99681
29 0.9978
30 0.99849
]
As noted above, using a catch block is always a good idea, even if you do not expect to use it.
*/
}
catch(const std::exception& e)
{ // Since we have set an overflow policy of ignore_error,
// an overflow exception should never be thrown.
std::cout << "\nMessage from thrown exception was:\n " << e.what() << std::endl;
/*`
For example, without a ignore domain error policy, if we asked for ``pdf(nb, -1)`` for example, we would get:
[pre
Message from thrown exception was:
Error in function boost::math::pdf(const negative_binomial_distribution<double>&, double):
Number of failures argument is -1, but must be >= 0 !
]
*/
//] [/ negative_binomial_eg1_2]
}
return 0;
} // int main()
/*
Output is:
Selling candy bars - using the negative binomial distribution.
by Dr. Diane Evans,
Professor of Mathematics at Rose-Hulman Institute of Technology,
see http://en.wikipedia.org/wiki/Negative_binomial_distribution
Pat has a sales per house success rate of 0.4.
Therefore he would, on average, sell 40 bars after trying 100 houses.
With a success rate of 0.4, he might expect, on average,
to need to visit about 12 houses in order to sell all 5 bars.
Probability that Pat finishes on the 5th house is 0.01024
Probability that Pat finishes on the 6th house is 0.03072
Probability that Pat finishes on the 7th house is 0.055296
Probability that Pat finishes on the 8th house is 0.077414
Probability that Pat finishes on or before the 8th house is sum
pdf(sales_quota) + pdf(6) + pdf(7) + pdf(8) = 0.17367
Probability of selling his quota of 5 bars
on or before the 8th house is 0.17367
Probability that Pat finishes exactly on the 10th house is 0.10033
Probability of selling his quota of 5 bars
on or before the 10th house is 0.3669
Probability that Pat finishes exactly on the 11th house is 0.10033
Probability of selling his quota of 5 bars
on or before the 11th house is 0.46723
Probability that Pat finishes exactly on the 12th house is 0.094596
Probability of selling his quota of 5 bars
on or before the 12th house is 0.56182
Probability that Pat finishes on the 30 house is 0.00069145
Probability of selling his quota of 5 bars
on or before the 30th house is 0.99849
Probability of failing to sell his quota of 5 bars
even after visiting all 30 houses is 0.0015101
Probability of meeting sales quota on or before 8th house is 0.17367
If the confidence of meeting sales quota is 0.17367, then the finishing house is 8
quantile(nb, p) = 3
If the confidence of meeting sales quota is 1, then the finishing house is 1.#INF
If the confidence of meeting sales quota is 0, then the finishing house is 5
If the confidence of meeting sales quota is 0.5, then the finishing house is 11.337
If the confidence of meeting sales quota is 0.99849, then the finishing house is 30
If confidence of meeting quota is zero
(we assume all houses are successful sales), then finishing house is 5
If confidence of meeting quota is 0, then finishing house is 5
If confidence of meeting quota is 0.001, then finishing house is 5
If confidence of meeting quota is 0.01, then finishing house is 5
If confidence of meeting quota is 0.05, then finishing house is 6.2
If confidence of meeting quota is 0.1, then finishing house is 7.06
If confidence of meeting quota is 0.5, then finishing house is 11.3
If confidence of meeting quota is 0.9, then finishing house is 17.8
If confidence of meeting quota is 0.95, then finishing house is 20.1
If confidence of meeting quota is 0.99, then finishing house is 24.8
If confidence of meeting quota is 0.999, then finishing house is 31.1
If confidence of meeting quota is 1, then finishing house is 1.#J
House for 5th (last) sale. Probability (%)
5 0.01024
6 0.04096
7 0.096256
8 0.17367
9 0.26657
10 0.3669
11 0.46723
12 0.56182
13 0.64696
14 0.72074
15 0.78272
16 0.83343
17 0.874
18 0.90583
19 0.93039
20 0.94905
21 0.96304
22 0.97342
23 0.98103
24 0.98655
25 0.99053
26 0.99337
27 0.99539
28 0.99681
29 0.9978
30 0.99849
*/

View File

@@ -0,0 +1,182 @@
// negative_binomial_example2.cpp
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Simple example demonstrating use of the Negative Binomial Distribution.
#include <boost/math/distributions/negative_binomial.hpp>
using boost::math::negative_binomial_distribution;
using boost::math::negative_binomial; // typedef
// In a sequence of trials or events
// (Bernoulli, independent, yes or no, succeed or fail)
// with success_fraction probability p,
// negative_binomial is the probability that k or fewer failures
// preceed the r th trial's success.
#include <iostream>
using std::cout;
using std::endl;
using std::setprecision;
using std::showpoint;
using std::setw;
using std::left;
using std::right;
#include <limits>
using std::numeric_limits;
int main()
{
cout << "Negative_binomial distribution - simple example 2" << endl;
// Construct a negative binomial distribution with:
// 8 successes (r), success fraction (p) 0.25 = 25% or 1 in 4 successes.
negative_binomial mynbdist(8, 0.25); // Shorter method using typedef.
// Display (to check) properties of the distribution just constructed.
cout << "mean(mynbdist) = " << mean(mynbdist) << endl; // 24
cout << "mynbdist.successes() = " << mynbdist.successes() << endl; // 8
// r th successful trial, after k failures, is r + k th trial.
cout << "mynbdist.success_fraction() = " << mynbdist.success_fraction() << endl;
// success_fraction = failures/successes or k/r = 0.25 or 25%.
cout << "mynbdist.percent success = " << mynbdist.success_fraction() * 100 << "%" << endl;
// Show as % too.
// Show some cumulative distribution function values for failures k = 2 and 8
cout << "cdf(mynbdist, 2.) = " << cdf(mynbdist, 2.) << endl; // 0.000415802001953125
cout << "cdf(mynbdist, 8.) = " << cdf(mynbdist, 8.) << endl; // 0.027129956288263202
cout << "cdf(complement(mynbdist, 8.)) = " << cdf(complement(mynbdist, 8.)) << endl; // 0.9728700437117368
// Check that cdf plus its complement is unity.
cout << "cdf + complement = " << cdf(mynbdist, 8.) + cdf(complement(mynbdist, 8.)) << endl; // 1
// Note: No complement for pdf!
// Compare cdf with sum of pdfs.
double sum = 0.; // Calculate the sum of all the pdfs,
int k = 20; // for 20 failures
for(signed i = 0; i <= k; ++i)
{
sum += pdf(mynbdist, double(i));
}
// Compare with the cdf
double cdf8 = cdf(mynbdist, static_cast<double>(k));
double diff = sum - cdf8; // Expect the diference to be very small.
cout << setprecision(17) << "Sum pdfs = " << sum << ' ' // sum = 0.40025683281803698
<< ", cdf = " << cdf(mynbdist, static_cast<double>(k)) // cdf = 0.40025683281803687
<< ", difference = " // difference = 0.50000000000000000
<< setprecision(1) << diff/ (std::numeric_limits<double>::epsilon() * sum)
<< " in epsilon units." << endl;
// Note: Use boost::math::tools::epsilon rather than std::numeric_limits
// to cover RealTypes that do not specialize numeric_limits.
//[neg_binomial_example2
// Print a table of values that can be used to plot
// using Excel, or some other superior graphical display tool.
cout.precision(17); // Use max_digits10 precision, the maximum available for a reference table.
cout << showpoint << endl; // include trailing zeros.
// This is a maximum possible precision for the type (here double) to suit a reference table.
int maxk = static_cast<int>(2. * mynbdist.successes() / mynbdist.success_fraction());
// This maxk shows most of the range of interest, probability about 0.0001 to 0.999.
cout << "\n"" k pdf cdf""\n" << endl;
for (int k = 0; k < maxk; k++)
{
cout << right << setprecision(17) << showpoint
<< right << setw(3) << k << ", "
<< left << setw(25) << pdf(mynbdist, static_cast<double>(k))
<< left << setw(25) << cdf(mynbdist, static_cast<double>(k))
<< endl;
}
cout << endl;
//] [/ neg_binomial_example2]
return 0;
} // int main()
/*
Output is:
negative_binomial distribution - simple example 2
mean(mynbdist) = 24
mynbdist.successes() = 8
mynbdist.success_fraction() = 0.25
mynbdist.percent success = 25%
cdf(mynbdist, 2.) = 0.000415802001953125
cdf(mynbdist, 8.) = 0.027129956288263202
cdf(complement(mynbdist, 8.)) = 0.9728700437117368
cdf + complement = 1
Sum pdfs = 0.40025683281803692 , cdf = 0.40025683281803687, difference = 0.25 in epsilon units.
//[neg_binomial_example2_1
k pdf cdf
0, 1.5258789062500000e-005 1.5258789062500003e-005
1, 9.1552734375000000e-005 0.00010681152343750000
2, 0.00030899047851562522 0.00041580200195312500
3, 0.00077247619628906272 0.0011882781982421875
4, 0.0015932321548461918 0.0027815103530883789
5, 0.0028678178787231476 0.0056493282318115234
6, 0.0046602040529251142 0.010309532284736633
7, 0.0069903060793876605 0.017299838364124298
8, 0.0098301179241389001 0.027129956288263202
9, 0.013106823898851871 0.040236780187115073
10, 0.016711200471036140 0.056947980658151209
11, 0.020509200578089786 0.077457181236241013
12, 0.024354675686481652 0.10181185692272265
13, 0.028101548869017230 0.12991340579173993
14, 0.031614242477644432 0.16152764826938440
15, 0.034775666725408917 0.19630331499479325
16, 0.037492515688331451 0.23379583068312471
17, 0.039697957787645101 0.27349378847076977
18, 0.041352039362130305 0.31484582783290005
19, 0.042440250924291580 0.35728607875719176
20, 0.042970754060845245 0.40025683281803687
21, 0.042970754060845225 0.44322758687888220
22, 0.042482450037426581 0.48571003691630876
23, 0.041558918514873783 0.52726895543118257
24, 0.040260202311284021 0.56752915774246648
25, 0.038649794218832620 0.60617895196129912
26, 0.036791631035234917 0.64297058299653398
27, 0.034747651533277427 0.67771823452981139
28, 0.032575923312447595 0.71029415784225891
29, 0.030329307911589130 0.74062346575384819
30, 0.028054609818219924 0.76867807557206813
31, 0.025792141284492545 0.79447021685656061
32, 0.023575629142856460 0.81804584599941710
33, 0.021432390129869489 0.83947823612928651
34, 0.019383705779220189 0.85886194190850684
35, 0.017445335201298231 0.87630727710980494
36, 0.015628112784496322 0.89193538989430121
37, 0.013938587078064250 0.90587397697236549
38, 0.012379666154859701 0.91825364312722524
39, 0.010951243136991251 0.92920488626421649
40, 0.0096507830144735539 0.93885566927869002
41, 0.0084738582566109364 0.94732952753530097
42, 0.0074146259745345548 0.95474415350983555
43, 0.0064662435824429246 0.96121039709227851
44, 0.0056212231142827853 0.96683162020656122
45, 0.0048717266990450708 0.97170334690560634
46, 0.0042098073105878630 0.97591315421619418
47, 0.0036275999165703964 0.97954075413276465
48, 0.0031174686783026818 0.98265822281106729
49, 0.0026721160099737302 0.98533033882104104
50, 0.0022846591885275322 0.98761499800956853
51, 0.0019486798960970148 0.98956367790566557
52, 0.0016582516423517923 0.99122192954801736
53, 0.0014079495076571762 0.99262987905567457
54, 0.0011928461106539983 0.99382272516632852
55, 0.0010084971662802015 0.99483122233260868
56, 0.00085091948404891532 0.99568214181665760
57, 0.00071656377604119542 0.99639870559269883
58, 0.00060228420831048650 0.99700098980100937
59, 0.00050530624256557675 0.99750629604357488
60, 0.00042319397814867202 0.99792949002172360
61, 0.00035381791615708398 0.99828330793788067
62, 0.00029532382517950324 0.99857863176306016
63, 0.00024610318764958566 0.99882473495070978
//] [neg_binomial_example2_1 end of Quickbook]
*/

View File

@@ -0,0 +1,509 @@
// negative_binomial_example3.cpp
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Example of using normal distribution.
// Note that this file contains Quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[normal_basic1
/*`
First we need some includes to access the normal distribution
(and some std output of course).
*/
#include <boost/math/distributions/normal.hpp> // for normal_distribution
using boost::math::normal; // typedef provides default type is double.
#include <iostream>
using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint;
#include <iomanip>
using std::setw; using std::setprecision;
#include <limits>
using std::numeric_limits;
int main()
{
cout << "Example: Normal distribution, Miscellaneous Applications.";
try
{
{ // Traditional tables and values.
/*`Let's start by printing some traditional tables.
*/
double step = 1.; // in z
double range = 4; // min and max z = -range to +range.
int precision = 17; // traditional tables are only computed to much lower precision.
// Construct a standard normal distribution s
normal s; // (default mean = zero, and standard deviation = unity)
cout << "Standard normal distribution, mean = "<< s.mean()
<< ", standard deviation = " << s.standard_deviation() << endl;
/*` First the probability distribution function (pdf).
*/
cout << "Probability distribution function values" << endl;
cout << " z " " pdf " << endl;
cout.precision(5);
for (double z = -range; z < range + step; z += step)
{
cout << left << setprecision(3) << setw(6) << z << " "
<< setprecision(precision) << setw(12) << pdf(s, z) << endl;
}
cout.precision(6); // default
/*`And the area under the normal curve from -[infin] up to z,
the cumulative distribution function (cdf).
*/
// For a standard normal distribution
cout << "Standard normal mean = "<< s.mean()
<< ", standard deviation = " << s.standard_deviation() << endl;
cout << "Integral (area under the curve) from - infinity up to z " << endl;
cout << " z " " cdf " << endl;
for (double z = -range; z < range + step; z += step)
{
cout << left << setprecision(3) << setw(6) << z << " "
<< setprecision(precision) << setw(12) << cdf(s, z) << endl;
}
cout.precision(6); // default
/*`And all this you can do with a nanoscopic amount of work compared to
the team of *human computers* toiling with Milton Abramovitz and Irene Stegen
at the US National Bureau of Standards (now [@www.nist.gov NIST]).
Starting in 1938, their "Handbook of Mathematical Functions with Formulas, Graphs and Mathematical Tables",
was eventually published in 1964, and has been reprinted numerous times since.
(A major replacement is planned at [@http://dlmf.nist.gov Digital Library of Mathematical Functions]).
Pretty-printing a traditional 2-dimensional table is left as an exercise for the student,
but why bother now that the Math Toolkit lets you write
*/
double z = 2.;
cout << "Area for z = " << z << " is " << cdf(s, z) << endl; // to get the area for z.
/*`
Correspondingly, we can obtain the traditional 'critical' values for significance levels.
For the 95% confidence level, the significance level usually called alpha,
is 0.05 = 1 - 0.95 (for a one-sided test), so we can write
*/
cout << "95% of area has a z below " << quantile(s, 0.95) << endl;
// 95% of area has a z below 1.64485
/*`and a two-sided test (a comparison between two levels, rather than a one-sided test)
*/
cout << "95% of area has a z between " << quantile(s, 0.975)
<< " and " << -quantile(s, 0.975) << endl;
// 95% of area has a z between 1.95996 and -1.95996
/*`
First, define a table of significance levels: these are the probabilities
that the true occurrence frequency lies outside the calculated interval.
It is convenient to have an alpha level for the probability that z lies outside just one standard deviation.
This will not be some nice neat number like 0.05, but we can easily calculate it,
*/
double alpha1 = cdf(s, -1) * 2; // 0.3173105078629142
cout << setprecision(17) << "Significance level for z == 1 is " << alpha1 << endl;
/*`
and place in our array of favorite alpha values.
*/
double alpha[] = {0.3173105078629142, // z for 1 standard deviation.
0.20, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
/*`
Confidence value as % is (1 - alpha) * 100 (so alpha 0.05 == 95% confidence)
that the true occurrence frequency lies *inside* the calculated interval.
*/
cout << "level of significance (alpha)" << setprecision(4) << endl;
cout << "2-sided 1 -sided z(alpha) " << endl;
for (int i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
{
cout << setw(15) << alpha[i] << setw(15) << alpha[i] /2 << setw(10) << quantile(complement(s, alpha[i]/2)) << endl;
// Use quantile(complement(s, alpha[i]/2)) to avoid potential loss of accuracy from quantile(s, 1 - alpha[i]/2)
}
cout << endl;
/*`Notice the distinction between one-sided (also called one-tailed)
where we are using a > *or* < test (and not both)
and considering the area of the tail (integral) from z up to +[infin],
and a two-sided test where we are using two > *and* < tests, and thus considering two tails,
from -[infin] up to z low and z high up to +[infin].
So the 2-sided values alpha[i] are calculated using alpha[i]/2.
If we consider a simple example of alpha = 0.05, then for a two-sided test,
the lower tail area from -[infin] up to -1.96 is 0.025 (alpha/2)
and the upper tail area from +z up to +1.96 is also 0.025 (alpha/2),
and the area between -1.96 up to 12.96 is alpha = 0.95.
and the sum of the two tails is 0.025 + 0.025 = 0.05,
*/
//] [/[normal_basic1]
//[normal_basic2
/*`Armed with the cumulative distribution function, we can easily calculate the
easy to remember proportion of values that lie within 1, 2 and 3 standard deviations from the mean.
*/
cout.precision(3);
cout << showpoint << "cdf(s, s.standard_deviation()) = "
<< cdf(s, s.standard_deviation()) << endl; // from -infinity to 1 sd
cout << "cdf(complement(s, s.standard_deviation())) = "
<< cdf(complement(s, s.standard_deviation())) << endl;
cout << "Fraction 1 standard deviation within either side of mean is "
<< 1 - cdf(complement(s, s.standard_deviation())) * 2 << endl;
cout << "Fraction 2 standard deviations within either side of mean is "
<< 1 - cdf(complement(s, 2 * s.standard_deviation())) * 2 << endl;
cout << "Fraction 3 standard deviations within either side of mean is "
<< 1 - cdf(complement(s, 3 * s.standard_deviation())) * 2 << endl;
/*`
To a useful precision, the 1, 2 & 3 percentages are 68, 95 and 99.7,
and these are worth memorising as useful 'rules of thumb', as, for example, in
[@http://en.wikipedia.org/wiki/Standard_deviation standard deviation]:
[pre
Fraction 1 standard deviation within either side of mean is 0.683
Fraction 2 standard deviations within either side of mean is 0.954
Fraction 3 standard deviations within either side of mean is 0.997
]
We could of course get some really accurate values for these
[@http://en.wikipedia.org/wiki/Confidence_interval confidence intervals]
by using cout.precision(15);
[pre
Fraction 1 standard deviation within either side of mean is 0.682689492137086
Fraction 2 standard deviations within either side of mean is 0.954499736103642
Fraction 3 standard deviations within either side of mean is 0.997300203936740
]
But before you get too excited about this impressive precision,
don't forget that the *confidence intervals of the standard deviation* are surprisingly wide,
especially if you have estimated the standard deviation from only a few measurements.
*/
//] [/[normal_basic2]
//[normal_bulbs_example1
/*`
Examples from K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
ISBN 1 58488 635 8, page 125... implemented using the Math Toolkit library.
A few very simple examples are shown here:
*/
// K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
// ISBN 1 58488 635 8, page 125, example 10.3.5
/*`Mean lifespan of 100 W bulbs is 1100 h with standard deviation of 100 h.
Assuming, perhaps with little evidence and much faith, that the distribution is normal,
we construct a normal distribution called /bulbs/ with these values:
*/
double mean_life = 1100.;
double life_standard_deviation = 100.;
normal bulbs(mean_life, life_standard_deviation);
double expected_life = 1000.;
/*`The we can use the Cumulative distribution function to predict fractions
(or percentages, if * 100) that will last various lifetimes.
*/
cout << "Fraction of bulbs that will last at best (<=) " // P(X <= 1000)
<< expected_life << " is "<< cdf(bulbs, expected_life) << endl;
cout << "Fraction of bulbs that will last at least (>) " // P(X > 1000)
<< expected_life << " is "<< cdf(complement(bulbs, expected_life)) << endl;
double min_life = 900;
double max_life = 1200;
cout << "Fraction of bulbs that will last between "
<< min_life << " and " << max_life << " is "
<< cdf(bulbs, max_life) // P(X <= 1200)
- cdf(bulbs, min_life) << endl; // P(X <= 900)
/*`
[note Real-life failures are often very ab-normal,
with a significant number that 'dead-on-arrival' or suffer failure very early in their life:
the lifetime of the survivors of 'early mortality' may be well described by the normal distribution.]
*/
//] [/normal_bulbs_example1 Quickbook end]
}
{
// K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
// ISBN 1 58488 635 8, page 125, Example 10.3.6
//[normal_bulbs_example3
/*`Weekly demand for 5 lb sacks of onions at a store is normally distributed with mean 140 sacks and standard deviation 10.
*/
double mean = 140.; // sacks per week.
double standard_deviation = 10;
normal sacks(mean, standard_deviation);
double stock = 160.; // per week.
cout << "Percentage of weeks overstocked "
<< cdf(sacks, stock) * 100. << endl; // P(X <=160)
// Percentage of weeks overstocked 97.7
/*`So there will be lots of mouldy onions!
So we should be able to say what stock level will meet demand 95% of the weeks.
*/
double stock_95 = quantile(sacks, 0.95);
cout << "Store should stock " << int(stock_95) << " sacks to meet 95% of demands." << endl;
/*`And it is easy to estimate how to meet 80% of demand, and waste even less.
*/
double stock_80 = quantile(sacks, 0.80);
cout << "Store should stock " << int(stock_80) << " sacks to meet 8 out of 10 demands." << endl;
//] [/normal_bulbs_example3 Quickbook end]
}
{ // K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
// ISBN 1 58488 635 8, page 125, Example 10.3.7
//[normal_bulbs_example4
/*`A machine is set to pack 3 kg of ground beef per pack.
Over a long period of time it is found that the average packed was 3 kg
with a standard deviation of 0.1 kg.
Assuming the packing is normally distributed,
we can find the fraction (or %) of packages that weigh more than 3.1 kg.
*/
double mean = 3.; // kg
double standard_deviation = 0.1; // kg
normal packs(mean, standard_deviation);
double max_weight = 3.1; // kg
cout << "Percentage of packs > " << max_weight << " is "
<< cdf(complement(packs, max_weight)) << endl; // P(X > 3.1)
double under_weight = 2.9;
cout <<"fraction of packs <= " << under_weight << " with a mean of " << mean
<< " is " << cdf(complement(packs, under_weight)) << endl;
// fraction of packs <= 2.9 with a mean of 3 is 0.841345
// This is 0.84 - more than the target 0.95
// Want 95% to be over this weight, so what should we set the mean weight to be?
// KK StatCalc says:
double over_mean = 3.0664;
normal xpacks(over_mean, standard_deviation);
cout << "fraction of packs >= " << under_weight
<< " with a mean of " << xpacks.mean()
<< " is " << cdf(complement(xpacks, under_weight)) << endl;
// fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005
double under_fraction = 0.05; // so 95% are above the minimum weight mean - sd = 2.9
double low_limit = standard_deviation;
double offset = mean - low_limit - quantile(packs, under_fraction);
double nominal_mean = mean + offset;
normal nominal_packs(nominal_mean, standard_deviation);
cout << "Setting the packer to " << nominal_mean << " will mean that "
<< "fraction of packs >= " << under_weight
<< " is " << cdf(complement(nominal_packs, under_weight)) << endl;
/*`
Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95.
Setting the packer to 3.13263 will mean that fraction of packs >= 2.9 is 0.99,
but will more than double the mean loss from 0.0644 to 0.133.
Alternatively, we could invest in a better (more precise) packer with a lower standard deviation.
To estimate how much better (how much smaller standard deviation) it would have to be,
we need to get the 5% quantile to be located at the under_weight limit, 2.9
*/
double p = 0.05; // wanted p th quantile.
cout << "Quantile of " << p << " = " << quantile(packs, p)
<< ", mean = " << packs.mean() << ", sd = " << packs.standard_deviation() << endl; //
/*`
Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1
With the current packer (mean = 3, sd = 0.1), the 5% quantile is at 2.8551 kg,
a little below our target of 2.9 kg.
So we know that the standard deviation is going to have to be smaller.
Let's start by guessing that it (now 0.1) needs to be halved, to a standard deviation of 0.05
*/
normal pack05(mean, 0.05);
cout << "Quantile of " << p << " = " << quantile(pack05, p)
<< ", mean = " << pack05.mean() << ", sd = " << pack05.standard_deviation() << endl;
cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean
<< " and standard deviation of " << pack05.standard_deviation()
<< " is " << cdf(complement(pack05, under_weight)) << endl;
//
/*`
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.9772
So 0.05 was quite a good guess, but we are a little over the 2.9 target,
so the standard deviation could be a tiny bit more. So we could do some
more guessing to get closer, say by increasing to 0.06
*/
normal pack06(mean, 0.06);
cout << "Quantile of " << p << " = " << quantile(pack06, p)
<< ", mean = " << pack06.mean() << ", sd = " << pack06.standard_deviation() << endl;
cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean
<< " and standard deviation of " << pack06.standard_deviation()
<< " is " << cdf(complement(pack06, under_weight)) << endl;
/*`
Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.9522
Now we are getting really close, but to do the job properly,
we could use root finding method, for example the tools provided, and used elsewhere,
in the Math Toolkit, see
[link math_toolkit.toolkit.internals1.roots2 Root Finding Without Derivatives].
But in this normal distribution case, we could be even smarter and make a direct calculation.
*/
normal s; // For standard normal distribution,
double sd = 0.1;
double x = 2.9; // Our required limit.
// then probability p = N((x - mean) / sd)
// So if we want to find the standard deviation that would be required to meet this limit,
// so that the p th quantile is located at x,
// in this case the 0.95 (95%) quantile at 2.9 kg pack weight, when the mean is 3 kg.
double prob = pdf(s, (x - mean) / sd);
double qp = quantile(s, 0.95);
cout << "prob = " << prob << ", quantile(p) " << qp << endl; // p = 0.241971, quantile(p) 1.64485
// Rearranging, we can directly calculate the required standard deviation:
double sd95 = abs((x - mean)) / qp;
cout << "If we want the "<< p << " th quantile to be located at "
<< x << ", would need a standard deviation of " << sd95 << endl;
normal pack95(mean, sd95); // Distribution of the 'ideal better' packer.
cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean
<< " and standard deviation of " << pack95.standard_deviation()
<< " is " << cdf(complement(pack95, under_weight)) << endl;
// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0608 is 0.95
/*`Notice that these two deceptively simple questions
(do we over-fill or measure better) are actually very common.
The weight of beef might be replaced by a measurement of more or less anything.
But the calculations rely on the accuracy of the standard deviation - something
that is almost always less good than we might wish,
especially if based on a few measurements.
*/
//] [/normal_bulbs_example4 Quickbook end]
}
{ // K. Krishnamoorthy, Handbook of Statistical Distributions with Applications,
// ISBN 1 58488 635 8, page 125, example 10.3.8
//[normal_bulbs_example5
/*`A bolt is usable if between 3.9 and 4.1 long.
From a large batch of bolts, a sample of 50 show a
mean length of 3.95 with standard deviation 0.1.
Assuming a normal distribution, what proportion is usable?
The true sample mean is unknown,
but we can use the sample mean and standard deviation to find approximate solutions.
*/
normal bolts(3.95, 0.1);
double top = 4.1;
double bottom = 3.9;
cout << "Fraction long enough [ P(X <= " << top << ") ] is " << cdf(bolts, top) << endl;
cout << "Fraction too short [ P(X <= " << bottom << ") ] is " << cdf(bolts, bottom) << endl;
cout << "Fraction OK -between " << bottom << " and " << top
<< "[ P(X <= " << top << ") - P(X<= " << bottom << " ) ] is "
<< cdf(bolts, top) - cdf(bolts, bottom) << endl;
cout << "Fraction too long [ P(X > " << top << ") ] is "
<< cdf(complement(bolts, top)) << endl;
cout << "95% of bolts are shorter than " << quantile(bolts, 0.95) << endl;
//] [/normal_bulbs_example5 Quickbook end]
}
}
catch(const std::exception& e)
{ // Always useful to include try & catch blocks because default policies
// are to throw exceptions on arguments that cause errors like underflow, overflow.
// Lacking try & catch blocks, the program will abort without a message below,
// which may give some helpful clues as to the cause of the exception.
std::cout <<
"\n""Message from thrown exception was:\n " << e.what() << std::endl;
}
return 0;
} // int main()
/*
Output is:
Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\normal_misc_examples.exe"
Example: Normal distribution, Miscellaneous Applications.Standard normal distribution, mean = 0, standard deviation = 1
Probability distribution function values
z pdf
-4 0.00013383022576488537
-3 0.0044318484119380075
-2 0.053990966513188063
-1 0.24197072451914337
0 0.3989422804014327
1 0.24197072451914337
2 0.053990966513188063
3 0.0044318484119380075
4 0.00013383022576488537
Standard normal mean = 0, standard deviation = 1
Integral (area under the curve) from - infinity up to z
z cdf
-4 3.1671241833119979e-005
-3 0.0013498980316300959
-2 0.022750131948179219
-1 0.1586552539314571
0 0.5
1 0.84134474606854293
2 0.97724986805182079
3 0.9986501019683699
4 0.99996832875816688
Area for z = 2 is 0.97725
95% of area has a z below 1.64485
95% of area has a z between 1.95996 and -1.95996
Significance level for z == 1 is 0.3173105078629142
level of significance (alpha)
2-sided 1 -sided z(alpha)
0.3173 0.1587 1
0.2 0.1 1.282
0.1 0.05 1.645
0.05 0.025 1.96
0.01 0.005 2.576
0.001 0.0005 3.291
0.0001 5e-005 3.891
1e-005 5e-006 4.417
cdf(s, s.standard_deviation()) = 0.841
cdf(complement(s, s.standard_deviation())) = 0.159
Fraction 1 standard deviation within either side of mean is 0.683
Fraction 2 standard deviations within either side of mean is 0.954
Fraction 3 standard deviations within either side of mean is 0.997
Fraction of bulbs that will last at best (<=) 1.00e+003 is 0.159
Fraction of bulbs that will last at least (>) 1.00e+003 is 0.841
Fraction of bulbs that will last between 900. and 1.20e+003 is 0.819
Percentage of weeks overstocked 97.7
Store should stock 156 sacks to meet 95% of demands.
Store should stock 148 sacks to meet 8 out of 10 demands.
Percentage of packs > 3.10 is 0.159
fraction of packs <= 2.90 with a mean of 3.00 is 0.841
fraction of packs >= 2.90 with a mean of 3.07 is 0.952
Setting the packer to 3.06 will mean that fraction of packs >= 2.90 is 0.950
Quantile of 0.0500 = 2.84, mean = 3.00, sd = 0.100
Quantile of 0.0500 = 2.92, mean = 3.00, sd = 0.0500
Fraction of packs >= 2.90 with a mean of 3.00 and standard deviation of 0.0500 is 0.977
Quantile of 0.0500 = 2.90, mean = 3.00, sd = 0.0600
Fraction of packs >= 2.90 with a mean of 3.00 and standard deviation of 0.0600 is 0.952
prob = 0.242, quantile(p) 1.64
If we want the 0.0500 th quantile to be located at 2.90, would need a standard deviation of 0.0608
Fraction of packs >= 2.90 with a mean of 3.00 and standard deviation of 0.0608 is 0.950
Fraction long enough [ P(X <= 4.10) ] is 0.933
Fraction too short [ P(X <= 3.90) ] is 0.309
Fraction OK -between 3.90 and 4.10[ P(X <= 4.10) - P(X<= 3.90 ) ] is 0.625
Fraction too long [ P(X > 4.10) ] is 0.0668
95% of bolts are shorter than 4.11
*/

35
example/policy_eg_1.cpp Normal file
View File

@@ -0,0 +1,35 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>
//[policy_eg_1
#include <boost/math/special_functions/gamma.hpp>
//
// Define the policy to use:
//
using namespace boost::math::policies;
typedef policy<
domain_error<errno_on_error>,
pole_error<errno_on_error>,
overflow_error<errno_on_error>,
evaluation_error<errno_on_error>
> c_policy;
//
// Now use the policy when calling tgamma:
//
int main()
{
errno = 0;
std::cout << "Result of tgamma(30000) is: "
<< boost::math::tgamma(30000, c_policy()) << std::endl;
std::cout << "errno = " << errno << std::endl;
std::cout << "Result of tgamma(-10) is: "
<< boost::math::tgamma(-10, c_policy()) << std::endl;
std::cout << "errno = " << errno << std::endl;
}
//]

171
example/policy_eg_10.cpp Normal file
View File

@@ -0,0 +1,171 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_eg_10
/*`
To understand how the rounding policies for
the discrete distributions can be used, we'll
use the 50-sample binomial distribution with a
success fraction of 0.5 once again, and calculate
all the possible quantiles at 0.05 and 0.95.
Begin by including the needed headers:
*/
#include <iostream>
#include <boost/math/distributions/binomial.hpp>
/*`
Next we'll bring the needed declarations into scope, and
define distribution types for all the available rounding policies:
*/
using namespace boost::math::policies;
using namespace boost::math;
typedef binomial_distribution<
double,
policy<discrete_quantile<integer_round_outwards> > >
binom_round_outwards;
typedef binomial_distribution<
double,
policy<discrete_quantile<integer_round_inwards> > >
binom_round_inwards;
typedef binomial_distribution<
double,
policy<discrete_quantile<integer_round_down> > >
binom_round_down;
typedef binomial_distribution<
double,
policy<discrete_quantile<integer_round_up> > >
binom_round_up;
typedef binomial_distribution<
double,
policy<discrete_quantile<integer_round_nearest> > >
binom_round_nearest;
typedef binomial_distribution<
double,
policy<discrete_quantile<real> > >
binom_real_quantile;
/*`
Now let's set to work calling those quantiles:
*/
int main()
{
std::cout <<
"Testing rounding policies for a 50 sample binomial distribution,\n"
"with a success fraction of 0.5.\n\n"
"Lower quantiles are calculated at p = 0.05\n\n"
"Upper quantiles at p = 0.95.\n\n";
std::cout << std::setw(25) << std::right
<< "Policy"<< std::setw(18) << std::right
<< "Lower Quantile" << std::setw(18) << std::right
<< "Upper Quantile" << std::endl;
// Test integer_round_outwards:
std::cout << std::setw(25) << std::right
<< "integer_round_outwards"
<< std::setw(18) << std::right
<< quantile(binom_round_outwards(50, 0.5), 0.05)
<< std::setw(18) << std::right
<< quantile(binom_round_outwards(50, 0.5), 0.95)
<< std::endl;
// Test integer_round_inwards:
std::cout << std::setw(25) << std::right
<< "integer_round_inwards"
<< std::setw(18) << std::right
<< quantile(binom_round_inwards(50, 0.5), 0.05)
<< std::setw(18) << std::right
<< quantile(binom_round_inwards(50, 0.5), 0.95)
<< std::endl;
// Test integer_round_down:
std::cout << std::setw(25) << std::right
<< "integer_round_down"
<< std::setw(18) << std::right
<< quantile(binom_round_down(50, 0.5), 0.05)
<< std::setw(18) << std::right
<< quantile(binom_round_down(50, 0.5), 0.95)
<< std::endl;
// Test integer_round_up:
std::cout << std::setw(25) << std::right
<< "integer_round_up"
<< std::setw(18) << std::right
<< quantile(binom_round_up(50, 0.5), 0.05)
<< std::setw(18) << std::right
<< quantile(binom_round_up(50, 0.5), 0.95)
<< std::endl;
// Test integer_round_nearest:
std::cout << std::setw(25) << std::right
<< "integer_round_nearest"
<< std::setw(18) << std::right
<< quantile(binom_round_nearest(50, 0.5), 0.05)
<< std::setw(18) << std::right
<< quantile(binom_round_nearest(50, 0.5), 0.95)
<< std::endl;
// Test real:
std::cout << std::setw(25) << std::right
<< "real"
<< std::setw(18) << std::right
<< quantile(binom_real_quantile(50, 0.5), 0.05)
<< std::setw(18) << std::right
<< quantile(binom_real_quantile(50, 0.5), 0.95)
<< std::endl;
}
/*`
Which produces the program output:
[pre
Testing rounding policies for a 50 sample binomial distribution,
with a success fraction of 0.5.
Lower quantiles are calculated at p = 0.05
Upper quantiles at p = 0.95.
Testing rounding policies for a 50 sample binomial distribution,
with a success fraction of 0.5.
Lower quantiles are calculated at p = 0.05
Upper quantiles at p = 0.95.
Policy Lower Quantile Upper Quantile
integer_round_outwards 18 31
integer_round_inwards 19 30
integer_round_down 18 30
integer_round_up 19 31
integer_round_nearest 19 30
real 18.701 30.299
]
*/
//] ends quickbook import

44
example/policy_eg_2.cpp Normal file
View File

@@ -0,0 +1,44 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>
//[policy_eg_2
#include <boost/math/special_functions/gamma.hpp>
int main()
{
using namespace boost::math::policies;
errno = 0;
std::cout << "Result of tgamma(30000) is: "
<< boost::math::tgamma(
30000,
make_policy(
domain_error<errno_on_error>(),
pole_error<errno_on_error>(),
overflow_error<errno_on_error>(),
evaluation_error<errno_on_error>()
)
) << std::endl;
// Check errno was set:
std::cout << "errno = " << errno << std::endl;
// and again with evaluation at a pole:
std::cout << "Result of tgamma(-10) is: "
<< boost::math::tgamma(
-10,
make_policy(
domain_error<errno_on_error>(),
pole_error<errno_on_error>(),
overflow_error<errno_on_error>(),
evaluation_error<errno_on_error>()
)
) << std::endl;
// Check errno was set:
std::cout << "errno = " << errno << std::endl;
}
//]

42
example/policy_eg_3.cpp Normal file
View File

@@ -0,0 +1,42 @@
// Copyright John Maddock 2007.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifdef _MSC_VER
# pragma warning (disable : 4305) // 'initializing' : truncation from 'long double' to 'const eval_type'
# pragma warning (disable : 4244) // conversion from 'long double' to 'const eval_type'
#endif
#include <iostream>
//[policy_eg_3
#include <boost/math/distributions/binomial.hpp>
//
// Begin by defining a policy type, that gives the
// behaviour we want:
//
using namespace boost::math::policies;
typedef policy<
promote_float<false>,
discrete_quantile<integer_round_nearest>
> mypolicy;
//
// Then define a distribution that uses it:
//
typedef boost::math::binomial_distribution<float, mypolicy> mybinom;
//
// And now use it to get the quantile:
//
int main()
{
std::cout << "quantile is: " <<
quantile(mybinom(200, 0.25), 0.05) << std::endl;
}
//]

102
example/policy_eg_4.cpp Normal file
View File

@@ -0,0 +1,102 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
#include <iostream>
//[policy_eg_4
/*`
Suppose we want `C::foo()` to behave in a C-compatible way and set
`::errno` on error rather than throwing any exceptions.
We'll begin by including the needed header:
*/
#include <boost/math/special_functions.hpp>
/*`
Open up the "C" namespace that we'll use for our functions, and
define the policy type we want: in this case one that sets
::errno rather than throwing exceptions. Any policies we don't
specify here will inherit the defaults:
*/
namespace C{
using namespace boost::math::policies;
typedef policy<
domain_error<errno_on_error>,
pole_error<errno_on_error>,
overflow_error<errno_on_error>,
evaluation_error<errno_on_error>
> c_policy;
/*`
All we need do now is invoke the BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS
macro passing our policy type as the single argument:
*/
BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(c_policy)
} // close namespace C
/*`
We now have a set of forwarding functions defined in namespace C
that all look something like this:
``
template <class RealType>
inline typename boost::math::tools::promote_args<RT>::type
tgamma(RT z)
{
return boost::math::tgamma(z, c_policy());
}
``
So that when we call `C::tgamma(z)` we really end up calling
`boost::math::tgamma(z, C::c_policy())`:
*/
int main()
{
errno = 0;
std::cout << "Result of tgamma(30000) is: "
<< C::tgamma(30000) << std::endl;
std::cout << "errno = " << errno << std::endl;
std::cout << "Result of tgamma(-10) is: "
<< C::tgamma(-10) << std::endl;
std::cout << "errno = " << errno << std::endl;
}
/*`
Which outputs:
[pre
Result of C::tgamma(30000) is: 1.#INF
errno = 34
Result of C::tgamma(-10) is: 1.#QNAN
errno = 33
]
This mechanism is particularly useful when we want to define a
project-wide policy, and don't want to modify the Boost source
or set - possibly fragile and easy to forget - project wide
build macros.
*/
//]

41
example/policy_eg_5.cpp Normal file
View File

@@ -0,0 +1,41 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
#include <iostream>
//[policy_eg_5
#include <boost/math/special_functions.hpp>
namespace {
using namespace boost::math::policies;
typedef policy<
domain_error<errno_on_error>,
pole_error<errno_on_error>,
overflow_error<errno_on_error>,
evaluation_error<errno_on_error>
> c_policy;
BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(c_policy)
} // close unnamed namespace
int main()
{
errno = 0;
std::cout << "Result of tgamma(30000) is: "
<< tgamma(30000) << std::endl;
std::cout << "errno = " << errno << std::endl;
std::cout << "Result of tgamma(-10) is: "
<< tgamma(-10) << std::endl;
std::cout << "errno = " << errno << std::endl;
}
//]

119
example/policy_eg_6.cpp Normal file
View File

@@ -0,0 +1,119 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
#include <iostream>
//[policy_eg_6
/*`
Suppose we want a set of distributions to behave as follows:
* Return infinity on overflow, rather than throwing an exception.
* Don't perform any promotion from double to long double internally.
* Return the closest integer result from the quantiles of discrete
distributions.
We'll begin by including the needed header:
*/
#include <boost/math/distributions.hpp>
/*`
Open up an appropriate namespace for our distributions, and
define the policy type we want. Any policies we don't
specify here will inherit the defaults:
*/
namespace my_distributions{
using namespace boost::math::policies;
typedef policy<
// return infinity and set errno rather than throw:
overflow_error<errno_on_error>,
// Don't promote double -> long double internally:
promote_double<false>,
// Return the closest integer result for discrete quantiles:
discrete_quantile<integer_round_nearest>
> my_policy;
/*`
All we need do now is invoke the BOOST_MATH_DECLARE_DISTRIBUTIONS
macro passing the floating point and policy types as arguments:
*/
BOOST_MATH_DECLARE_DISTRIBUTIONS(double, my_policy)
} // close namespace my_namespace
/*`
We now have a set of typedefs defined in namespace my_namespace
that all look something like this:
``
typedef boost::math::normal_distribution<double, my_policy> normal;
typedef boost::math::cauchy_distribution<double, my_policy> cauchy;
typedef boost::math::gamma_distribution<double, my_policy> gamma;
// etc
``
So that when we use my_namespace::normal we really end up using
`boost::math::normal_distribution<double, my_policy>`:
*/
int main()
{
//
// Start with something we know will overflow:
//
my_distributions::normal norm(10, 2);
errno = 0;
std::cout << "Result of quantile(norm, 0) is: "
<< quantile(norm, 0) << std::endl;
std::cout << "errno = " << errno << std::endl;
errno = 0;
std::cout << "Result of quantile(norm, 1) is: "
<< quantile(norm, 1) << std::endl;
std::cout << "errno = " << errno << std::endl;
//
// Now try a discrete distribution:
//
my_distributions::binomial binom(20, 0.25);
std::cout << "Result of quantile(binom, 0.05) is: "
<< quantile(binom, 0.05) << std::endl;
std::cout << "Result of quantile(complement(binom, 0.05)) is: "
<< quantile(complement(binom, 0.05)) << std::endl;
}
/*`
Which outputs:
[pre
Result of quantile(norm, 0) is: -1.#INF
errno = 34
Result of quantile(norm, 1) is: 1.#INF
errno = 34
Result of quantile(binom, 0.05) is: 1
Result of quantile(complement(binom, 0.05)) is: 8
]
This mechanism is particularly useful when we want to define a
project-wide policy, and don't want to modify the Boost source
or set - possibly fragile and easy to forget - project wide
build macros.
*/ //] ends quickbook imported section

57
example/policy_eg_7.cpp Normal file
View File

@@ -0,0 +1,57 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
#include <iostream>
//[policy_eg_7
#include <boost/math/distributions.hpp>
namespace {
using namespace boost::math::policies;
typedef policy<
// return infinity and set errno rather than throw:
overflow_error<errno_on_error>,
// Don't promote double -> long double internally:
promote_double<false>,
// Return the closest integer result for discrete quantiles:
discrete_quantile<integer_round_nearest>
> my_policy;
BOOST_MATH_DECLARE_DISTRIBUTIONS(double, my_policy)
} // close namespace my_namespace
int main()
{
//
// Start with something we know will overflow:
//
normal norm(10, 2);
errno = 0;
std::cout << "Result of quantile(norm, 0) is: "
<< quantile(norm, 0) << std::endl;
std::cout << "errno = " << errno << std::endl;
errno = 0;
std::cout << "Result of quantile(norm, 1) is: "
<< quantile(norm, 1) << std::endl;
std::cout << "errno = " << errno << std::endl;
//
// Now try a discrete distribution:
//
binomial binom(20, 0.25);
std::cout << "Result of quantile(binom, 0.05) is: "
<< quantile(binom, 0.05) << std::endl;
std::cout << "Result of quantile(complement(binom, 0.05)) is: "
<< quantile(complement(binom, 0.05)) << std::endl;
}
//] ends quickbook imported section

135
example/policy_eg_8.cpp Normal file
View File

@@ -0,0 +1,135 @@
// Copyright John Maddock 2007.
// Copyright Paul a. Bristow 2007
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
#ifdef _MSC_VER
# pragma warning (disable : 4100) // 'unreferenced formal parameter
#endif
#include <iostream>
//[policy_eg_8
/*`
Suppose we want our own user-defined error handlers rather than the
any of the default ones supplied by the library to be used. If
we set the policy for a specific type of error to `user_error`
then the library will call a user-supplied error handler.
These are forward declared, but not defined in
boost/math/policies/error_handling.hpp like this:
namespace boost{ namespace math{ namespace policy{
template <class T>
T user_domain_error(const char* function, const char* message, const T& val);
template <class T>
T user_pole_error(const char* function, const char* message, const T& val);
template <class T>
T user_overflow_error(const char* function, const char* message, const T& val);
template <class T>
T user_underflow_error(const char* function, const char* message, const T& val);
template <class T>
T user_denorm_error(const char* function, const char* message, const T& val);
template <class T>
T user_evaluation_error(const char* function, const char* message, const T& val);
}}} // namespaces
So out first job is to include the header we want to use, and then
provide definitions for the user-defined error handlers we want to use:
*/
#include <iostream>
#include <boost/math/special_functions.hpp>
namespace boost{ namespace math{ namespace policies{
template <class T>
T user_domain_error(const char* function, const char* message, const T& val)
{
std::cerr << "Domain Error." << std::endl;
return std::numeric_limits<T>::quiet_NaN();
}
template <class T>
T user_pole_error(const char* function, const char* message, const T& val)
{
std::cerr << "Pole Error." << std::endl;
return std::numeric_limits<T>::quiet_NaN();
}
}}} // namespaces
/*`
Now we'll need to define a suitable policy that will call these handlers,
and define some forwarding functions that make use of the policy:
*/
namespace{
using namespace boost::math::policies;
typedef policy<
domain_error<user_error>,
pole_error<user_error>
> user_error_policy;
BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(user_error_policy)
} // close unnamed namespace
/*`
We now have a set of forwarding functions defined in an unnamed namespace
that all look something like this:
``
template <class RealType>
inline typename boost::math::tools::promote_args<RT>::type
tgamma(RT z)
{
return boost::math::tgamma(z, user_error_policy());
}
``
So that when we call `tgamma(z)` we really end up calling
`boost::math::tgamma(z, user_error_policy())`, and any
errors will get directed to our own error handlers:
*/
int main()
{
std::cout << "Result of erf_inv(-10) is: "
<< erf_inv(-10) << std::endl;
std::cout << "Result of tgamma(-10) is: "
<< tgamma(-10) << std::endl;
}
/*`
Which outputs:
[pre
Domain Error.
Result of erf_inv(-10) is: 1.#QNAN
Pole Error.
Result of tgamma(-10) is: 1.#QNAN
]
*/
//]

316
example/policy_eg_9.cpp Normal file
View File

@@ -0,0 +1,316 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
#include <iostream>
//[policy_eg_9
/*`
The previous example was all well and good, but the custom error handlers
didn't really do much of any use. In this example we'll implement all
the custom handlers and show how the information provided to them can be
used to generate nice formatted error messages.
Each error handler has the general form:
template <class T>
T user_``['error_type]``(
const char* function,
const char* message,
const T& val);
and accepts three arguments:
[variablelist
[[const char* function]
[The name of the function that raised the error, this string
contains one or more %1% format specifiers that should be
replaced by the name of type T.]]
[[const char* message]
[A message associated with the error, normally this
contains a %1% format specifier that should be replaced with
the value of ['value]: however note that overflow and underflow messages
do not contain this %1% specifier (since the value of ['value] is
immaterial in these cases).]]
[[const T& value]
[The value that caused the error: either an argument to the function
if this is a domain or pole error, the tentative result
if this is a denorm or evaluation error, or zero or infinity for
underflow or overflow errors.]]
]
As before we'll include the headers we need first:
*/
#include <iostream>
#include <boost/math/special_functions.hpp>
/*`
Next we'll implement the error handlers for each type of error,
starting with domain errors:
*/
namespace boost{ namespace math{ namespace policies{
template <class T>
T user_domain_error(const char* function, const char* message, const T& val)
{
/*`
We'll begin with a bit of defensive programming:
*/
if(function == 0)
function = "Unknown function with arguments of type %1%";
if(message == 0)
message = "Cause unknown with bad argument %1%";
/*`
Next we'll format the name of the function with the name of type T:
*/
std::string msg("Error in function ");
msg += (boost::format(function) % typeid(T).name()).str();
/*`
Then likewise format the error message with the value of parameter /val/,
making sure we output all the digits of /val/:
*/
msg += ": \n";
int prec = 2 + (std::numeric_limits<T>::digits * 30103UL) / 100000UL;
msg += (boost::format(message) % boost::io::group(std::setprecision(prec), val)).str();
/*`
Now we just have to do something with the message, we could throw an
exception, but for the purposes of this example we'll just dump the message
to std::cerr:
*/
std::cerr << msg << std::endl;
/*`
Finally the only sensible value we can return from a domain error is a NaN:
*/
return std::numeric_limits<T>::quiet_NaN();
}
/*`
Pole errors are essentially a special case of domain errors,
so in this example we'll just return the result of a domain error:
*/
template <class T>
T user_pole_error(const char* function, const char* message, const T& val)
{
return user_domain_error(function, message, val);
}
/*`
Overflow errors are very similar to domain errors, except that there's
no %1% format specifier in the /message/ parameter:
*/
template <class T>
T user_overflow_error(const char* function, const char* message, const T& val)
{
if(function == 0)
function = "Unknown function with arguments of type %1%";
if(message == 0)
message = "Result of function is too large to represent";
std::string msg("Error in function ");
msg += (boost::format(function) % typeid(T).name()).str();
msg += ": \n";
msg += message;
std::cerr << msg << std::endl;
// Value passed to the function is an infinity, just return it:
return val;
}
/*`
Underflow errors are much the same as overflow:
*/
template <class T>
T user_underflow_error(const char* function, const char* message, const T& val)
{
if(function == 0)
function = "Unknown function with arguments of type %1%";
if(message == 0)
message = "Result of function is too small to represent";
std::string msg("Error in function ");
msg += (boost::format(function) % typeid(T).name()).str();
msg += ": \n";
msg += message;
std::cerr << msg << std::endl;
// Value passed to the function is zero, just return it:
return val;
}
/*`
Denormalised results are much the same as underflow:
*/
template <class T>
T user_denorm_error(const char* function, const char* message, const T& val)
{
if(function == 0)
function = "Unknown function with arguments of type %1%";
if(message == 0)
message = "Result of function is denormalised";
std::string msg("Error in function ");
msg += (boost::format(function) % typeid(T).name()).str();
msg += ": \n";
msg += message;
std::cerr << msg << std::endl;
// Value passed to the function is denormalised, just return it:
return val;
}
/*`
Which leaves us with evaluation errors, these occur when an internal
error occurs that prevents the function being fully evaluated.
The parameter /val/ contains the closest approximation to the result
found so far:
*/
template <class T>
T user_evaluation_error(const char* function, const char* message, const T& val)
{
if(function == 0)
function = "Unknown function with arguments of type %1%";
if(message == 0)
message = "An internal evaluation error occured with "
"the best value calculated so far of %1%";
std::string msg("Error in function ");
msg += (boost::format(function) % typeid(T).name()).str();
msg += ": \n";
int prec = 2 + (std::numeric_limits<T>::digits * 30103UL) / 100000UL;
msg += (boost::format(message) % boost::io::group(std::setprecision(prec), val)).str();
std::cerr << msg << std::endl;
// What do we return here? This is generally a fatal error,
// that should never occur, just return a NaN for the purposes
// of the example:
return std::numeric_limits<T>::quiet_NaN();
}
}}} // namespaces
/*`
Now we'll need to define a suitable policy that will call these handlers,
and define some forwarding functions that make use of the policy:
*/
namespace{
using namespace boost::math::policies;
typedef policy<
domain_error<user_error>,
pole_error<user_error>,
overflow_error<user_error>,
underflow_error<user_error>,
denorm_error<user_error>,
evaluation_error<user_error>
> user_error_policy;
BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(user_error_policy)
} // close unnamed namespace
/*`
We now have a set of forwarding functions defined in an unnamed namespace
that all look something like this:
``
template <class RealType>
inline typename boost::math::tools::promote_args<RT>::type
tgamma(RT z)
{
return boost::math::tgamma(z, user_error_policy());
}
``
So that when we call `tgamma(z)` we really end up calling
`boost::math::tgamma(z, user_error_policy())`, and any
errors will get directed to our own error handlers:
*/
int main()
{
// Raise a domain error:
std::cout << "Result of erf_inv(-10) is: "
<< erf_inv(-10) << std::endl << std::endl;
// Raise a pole error:
std::cout << "Result of tgamma(-10) is: "
<< tgamma(-10) << std::endl << std::endl;
// Raise an overflow error:
std::cout << "Result of tgamma(3000) is: "
<< tgamma(3000) << std::endl << std::endl;
// Raise an underflow error:
std::cout << "Result of tgamma(-190.5) is: "
<< tgamma(-190.5) << std::endl << std::endl;
// Unfortunately we can't predicably raise a denormalised
// result, nor can we raise an evaluation error in this example
// since these should never really occur!
}
/*`
Which outputs:
[pre
Error in function boost::math::erf_inv<double>(double, double):
Argument outside range \[-1, 1\] in inverse erf function (got p=-10).
Result of erf_inv(-10) is: 1.#QNAN
Error in function boost::math::tgamma<long double>(long double):
Evaluation of tgamma at a negative integer -10.
Result of tgamma(-10) is: 1.#QNAN
Error in function boost::math::tgamma<long double>(long double):
Result of tgamma is too large to represent.
Error in function boost::math::tgamma<double>(double):
Result of function is too large to represent
Result of tgamma(3000) is: 1.#INF
Error in function boost::math::tgamma<long double>(long double):
Result of tgamma is too large to represent.
Error in function boost::math::tgamma<long double>(long double):
Result of tgamma is too small to represent.
Result of tgamma(-190.5) is: 0
]
Notice how some of the calls result in an error handler being called more
than once, or for more than one handler to be called: this is an artefact
of the fact that many functions are implemented in terms of one or more
sub-routines each of which may have it's own error handling. For example
`tgamma(-190.5)` is implemented in terms of `tgamma(190.5)` - which overflows -
the reflection formula for `tgamma` then notices that it's dividing by
infinity and underflows.
*/
//]

View File

@@ -0,0 +1,44 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
double some_value = 0;
//[policy_ref_snip1
#include <boost/math/special_functions/gamma.hpp>
using namespace boost::math::policies;
using namespace boost::math;
// Define a policy:
typedef policy<
domain_error<errno_on_error>,
pole_error<errno_on_error>,
overflow_error<errno_on_error>,
policies::evaluation_error<errno_on_error>
> my_policy;
// call the function:
double t1 = tgamma(some_value, my_policy());
// Alternatively we could use make_policy and define everything at the call site:
double t2 = tgamma(some_value, make_policy(
domain_error<errno_on_error>(),
pole_error<errno_on_error>(),
overflow_error<errno_on_error>(),
policies::evaluation_error<errno_on_error>()
));
//]
#include <iostream>
int main()
{
std::cout << t1 << " " << t2 << std::endl;
}

View File

@@ -0,0 +1,25 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_ref_snip10
#include <boost/math/special_functions/gamma.hpp>
using namespace boost::math;
using namespace boost::math::policies;
double t = tgamma(12, policy<digits10<5> >());
//]
#include <iostream>
int main()
{
std::cout << t << std::endl;
}

View File

@@ -0,0 +1,27 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_ref_snip11
#include <boost/math/distributions/normal.hpp>
using namespace boost::math;
using namespace boost::math::policies;
double q = quantile(
normal_distribution<double, policy<digits2<25> > >(),
0.05);
//]
#include <iostream>
int main()
{
std::cout << q << std::endl;
}

View File

@@ -0,0 +1,38 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_ref_snip12
#include <boost/math/special_functions/gamma.hpp>
namespace myspace{
using namespace boost::math::policies;
// Define a policy that does not throw on overflow:
typedef policy<overflow_error<errno_on_error> > my_policy;
// Define the special functions in this scope to use the policy:
BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(my_policy)
}
//
// Now we can use myspace::tgamma etc.
// They will automatically use "my_policy":
//
double t = myspace::tgamma(30.0); // will not throw on overflow
//]
#include <iostream>
int main()
{
std::cout << t << std::endl;
}

View File

@@ -0,0 +1,54 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
#ifdef _MSC_VER
#pragma warning (disable : 4189) // 'd' : local variable is initialized but not referenced
#endif
//[policy_ref_snip13
#include <boost/math/distributions/cauchy.hpp>
namespace myspace{
using namespace boost::math::policies;
// Define a policy to use, in this case we want all the distribution
// accessor functions to compile, even if they are mathematically
// undefined:
typedef policy<assert_undefined<false> > my_policy;
BOOST_MATH_DECLARE_DISTRIBUTIONS(double, my_policy)
}
// Now we can use myspace::cauchy etc, which will use policy
// myspace::mypolicy:
//
// This compiles but raises a domain error at runtime:
//
void test_cauchy()
{
try
{
double d = mean(myspace::cauchy());
}
catch(const std::domain_error& e)
{
std::cout << e.what() << std::endl;
}
}
//]
#include <iostream>
int main()
{
test_cauchy();
}

View File

@@ -0,0 +1,34 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_ref_snip2
#include <boost/math/distributions/normal.hpp>
using namespace boost::math::policies;
using namespace boost::math;
// Define a policy:
typedef policy<
overflow_error<ignore_error>
> my_policy;
// Define the distribution:
typedef normal_distribution<double, my_policy> my_norm;
// Get a quantile:
double q = quantile(my_norm(), 0.05);
//]
#include <iostream>
int main()
{
std::cout << q << std::endl;
}

View File

@@ -0,0 +1,36 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
double some_value = 2;
//[policy_ref_snip3
#include <boost/math/special_functions/gamma.hpp>
using namespace boost::math::policies;
using namespace boost::math;
// Define a policy:
typedef policy<
promote_double<false>
> my_policy;
// Call the function:
double t1 = tgamma(some_value, my_policy());
// Alternatively we could use make_policy and define everything at the call site:
double t2 = tgamma(some_value, make_policy(promote_double<false>()));
//]
#include <iostream>
int main()
{
std::cout << t1 << " " << t2 << std::endl;
}

View File

@@ -0,0 +1,40 @@
// Copyright John Maddock 2007.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
#ifdef _MSC_VER
# pragma warning (disable : 4305) // 'initializing' : truncation from 'long double' to 'const eval_type'
# pragma warning (disable : 4244) // 'conversion' : truncation from 'long double' to 'const eval_type'
#endif
//[policy_ref_snip4
#include <boost/math/distributions/normal.hpp>
using namespace boost::math::policies;
using namespace boost::math;
// Define a policy:
typedef policy<
promote_float<false>
> my_policy;
// Define the distribution:
typedef normal_distribution<float, my_policy> my_norm;
// Get a quantile:
float q = quantile(my_norm(), 0.05f);
//] [policy_ref_snip4]
#include <iostream>
int main()
{
std::cout << q << std::endl;
}

View File

@@ -0,0 +1,33 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_ref_snip5
#include <boost/math/distributions/negative_binomial.hpp>
using namespace boost::math;
using namespace boost::math::policies;
typedef negative_binomial_distribution<
double,
policy<discrete_quantile<integer_round_inwards> >
> dist_type;
// Lower quantile:
double x = quantile(dist_type(20, 0.3), 0.05);
// Upper quantile:
double y = quantile(complement(dist_type(20, 0.3), 0.05));
//]
#include <iostream>
int main()
{
std::cout << x << " " << y << std::endl;
}

View File

@@ -0,0 +1,27 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_ref_snip6
#include <boost/math/distributions/negative_binomial.hpp>
using namespace boost::math;
// Lower quantile rounded down:
double x = quantile(negative_binomial(20, 0.3), 0.05);
// Upper quantile rounded up:
double y = quantile(complement(negative_binomial(20, 0.3), 0.05));
//]
#include <iostream>
int main()
{
std::cout << x << " " << y << std::endl;
}

View File

@@ -0,0 +1,33 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_ref_snip7
#include <boost/math/distributions/negative_binomial.hpp>
using namespace boost::math;
using namespace boost::math::policies;
typedef negative_binomial_distribution<
double,
policy<discrete_quantile<integer_round_inwards> >
> dist_type;
// Lower quantile rounded up:
double x = quantile(dist_type(20, 0.3), 0.05);
// Upper quantile rounded down:
double y = quantile(complement(dist_type(20, 0.3), 0.05));
//]
#include <iostream>
int main()
{
std::cout << x << " " << y << std::endl;
}

View File

@@ -0,0 +1,33 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_ref_snip8
#include <boost/math/distributions/negative_binomial.hpp>
using namespace boost::math;
using namespace boost::math::policies;
typedef negative_binomial_distribution<
double,
policy<discrete_quantile<integer_round_nearest> >
> dist_type;
// Lower quantile rounded up:
double x = quantile(dist_type(20, 0.3), 0.05);
// Upper quantile rounded down:
double y = quantile(complement(dist_type(20, 0.3), 0.05));
//]
#include <iostream>
int main()
{
std::cout << x << " " << y << std::endl;
}

View File

@@ -0,0 +1,27 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!
//[policy_ref_snip9
#include <boost/math/special_functions/gamma.hpp>
using namespace boost::math;
using namespace boost::math::policies;
typedef policy<digits10<5> > pol;
double t = tgamma(12, pol());
//]
#include <iostream>
int main()
{
std::cout << t << std::endl;
}

View File

@@ -0,0 +1,101 @@
// students_t_example1.cpp
// Copyright Paul A. Bristow 2006, 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Example 1 of using Student's t
// http://en.wikipedia.org/wiki/Student's_t-test says:
// The t statistic was invented by William Sealy Gosset
// for cheaply monitoring the quality of beer brews.
// "Student" was his pen name.
// WS Gosset was statistician for Guinness brewery in Dublin, Ireland,
// hired due to Claude Guinness's innovative policy of recruiting the
// best graduates from Oxford and Cambridge for applying biochemistry
// and statistics to Guinness's industrial processes.
// Gosset published the t test in Biometrika in 1908,
// but was forced to use a pen name by his employer who regarded the fact
// that they were using statistics as a trade secret.
// In fact, Gosset's identity was unknown not only to fellow statisticians
// but to his employer - the company insisted on the pseudonym
// so that it could turn a blind eye to the breach of its rules.
// Data for this example from:
// P.K.Hou, O. W. Lau & M.C. Wong, Analyst (1983) vol. 108, p 64.
// from Statistics for Analytical Chemistry, 3rd ed. (1994), pp 54-55
// J. C. Miller and J. N. Miller, Ellis Horwood ISBN 0 13 0309907
// Determination of mercury by cold-vapour atomic absorption,
// the following values were obtained fusing a trusted
// Standard Reference Material containing 38.9% mercury,
// which we assume is correct or 'true'.
double standard = 38.9;
const int values = 3;
double value[values] = {38.9, 37.4, 37.1};
// Is there any evidence for systematic error?
// The Students't distribution function is described at
// http://en.wikipedia.org/wiki/Student%27s_t_distribution
#include <boost/math/distributions/students_t.hpp>
using boost::math::students_t; // Probability of students_t(df, t).
#include <iostream>
using std::cout; using std::endl;
#include <iomanip>
using std::setprecision;
#include <cmath>
using std::sqrt;
int main()
{
cout << "Example 1 using Student's t function. " << endl;
// Example/test using tabulated value
// (deliberately coded as naively as possible).
// Null hypothesis is that there is no difference (greater or less)
// between measured and standard.
double degrees_of_freedom = values-1; // 3-1 = 2
cout << "Measurement 1 = " << value[0] << ", measurement 2 = " << value[1] << ", measurement 3 = " << value[2] << endl;
double mean = (value[0] + value[1] + value[2]) / static_cast<double>(values);
cout << "Standard = " << standard << ", mean = " << mean << ", (mean - standard) = " << mean - standard << endl;
double sd = sqrt(((value[0] - mean) * (value[0] - mean) + (value[1] - mean) * (value[1] - mean) + (value[2] - mean) * (value[2] - mean))/ static_cast<double>(values-1));
cout << "Standard deviation = " << sd << endl;
if (sd == 0.)
{
cout << "Measured mean is identical to SRM value," << endl;
cout << "so probability of no difference between measured and standard (the 'null hypothesis') is unity." << endl;
return 0;
}
double t = (mean - standard) * std::sqrt(static_cast<double>(values)) / sd;
cout << "Student's t = " << t << endl;
cout.precision(2); // Useful accuracy is only a few decimal digits.
cout << "Probability of Student's t is " << cdf(students_t(degrees_of_freedom), std::abs(t)) << endl;
// 0.91, is 1 tailed.
// So there is insufficient evidence of a difference to meet a 95% (1 in 20) criterion.
return 0;
} // int main()
/*
Output is:
Example 1 using Student's t function.
Measurement 1 = 38.9, measurement 2 = 37.4, measurement 3 = 37.1
Standard = 38.9, mean = 37.8, (mean - standard) = -1.1
Standard deviation = 0.964365
Student's t = -1.97566
Probability of Student's t is 0.91
*/

View File

@@ -0,0 +1,125 @@
// students_t_example2.cpp
// Copyright Paul A. Bristow 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Example 2 of using Student's t
// A general guide to Student's t is at
// http://en.wikipedia.org/wiki/Student's_t-test
// (and many other elementary and advanced statistics texts).
// It says:
// The t statistic was invented by William Sealy Gosset
// for cheaply monitoring the quality of beer brews.
// "Student" was his pen name.
// Gosset was statistician for Guinness brewery in Dublin, Ireland,
// hired due to Claude Guinness's innovative policy of recruiting the
// best graduates from Oxford and Cambridge for applying biochemistry
// and statistics to Guinness's industrial processes.
// Gosset published the t test in Biometrika in 1908,
// but was forced to use a pen name by his employer who regarded the fact
// that they were using statistics as a trade secret.
// In fact, Gosset's identity was unknown not only to fellow statisticians
// but to his employer - the company insisted on the pseudonym
// so that it could turn a blind eye to the breach of its rules.
// The Students't distribution function is described at
// http://en.wikipedia.org/wiki/Student%27s_t_distribution
#include <boost/math/distributions/students_t.hpp>
using boost::math::students_t; // Probability of students_t(df, t).
#include <iostream>
using std::cout;
using std::endl;
#include <iomanip>
using std::setprecision;
using std::setw;
#include <cmath>
using std::sqrt;
// This example of a one-sided test is from:
//
// from Statistics for Analytical Chemistry, 3rd ed. (1994), pp 59-60
// J. C. Miller and J. N. Miller, Ellis Horwood ISBN 0 13 0309907.
// An acid-base titrimetric method has a significant indicator error and
// thus tends to give results with a positive systematic error (+bias).
// To test this an exactly 0.1 M solution of acid is used to titrate
// 25.00 ml of exactly 0.1 M solution of alkali,
// with the following results (ml):
double reference = 25.00; // 'True' result.
const int values = 6; // titrations.
double data [values] = {25.06, 25.18, 24.87, 25.51, 25.34, 25.41};
int main()
{
cout << "Example2 using Student's t function. ";
#if defined(__FILE__) && defined(__TIMESTAMP__)
cout << " " << __FILE__ << ' ' << __TIMESTAMP__ << ' '<< _MSC_FULL_VER;
#endif
cout << endl;
double sum = 0.;
for (int value = 0; value < values; value++)
{ // Echo data and calculate mean.
sum += data[value];
cout << setw(4) << value << ' ' << setw(14) << data[value] << endl;
}
double mean = sum /static_cast<double>(values);
cout << "Mean = " << mean << endl; // 25.2283
double sd = 0.;
for (int value = 0; value < values; value++)
{ // Calculate standard deviation.
sd +=(data[value] - mean) * (data[value] - mean);
}
int degrees_of_freedom = values - 1; // Use the n-1 formula.
sd /= degrees_of_freedom; // == variance.
sd= sqrt(sd);
cout << "Standard deviation = " << sd<< endl; // = 0.238279
double t = (mean - reference) * sqrt(static_cast<double>(values))/ sd; //
cout << "Student's t = " << t << ", with " << degrees_of_freedom << " degrees of freedom." << endl; // = 2.34725
cout << "Probability of positive bias is " << cdf(students_t(degrees_of_freedom), t) << "."<< endl; // = 0.967108.
// A 1-sided test because only testing for a positive bias.
// If > 0.95 then greater than 1 in 20 conventional (arbitrary) requirement.
return 0;
} // int main()
/*
Output is:
------ Build started: Project: students_t_example2, Configuration: Debug Win32 ------
Compiling...
students_t_example2.cpp
Linking...
Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\students_t_example2.exe"
Example2 using Student's t function. ..\..\..\..\..\..\boost-sandbox\libs\math_functions\example\students_t_example2.cpp Sat Aug 12 16:55:59 2006 140050727
0 25.06
1 25.18
2 24.87
3 25.51
4 25.34
5 25.41
Mean = 25.2283
Standard deviation = 0.238279
Student's t = 2.34725, with 5 degrees of freedom.
Probability of positive bias is 0.967108.
Build Time 0:03
Build log was saved at "file://i:\boost-06-05-03-1300\libs\math\test\Math_test\students_t_example2\Debug\BuildLog.htm"
students_t_example2 - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
*/

View File

@@ -0,0 +1,120 @@
// students_t_example3.cpp
// Copyright Paul A. Bristow 2006, 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Example 3 of using Student's t.
// A general guide to Student's t is at
// http://en.wikipedia.org/wiki/Student's_t-test
// (and many other elementary and advanced statistics texts).
// It says:
// The t statistic was invented by William Sealy Gosset
// for cheaply monitoring the quality of beer brews.
// "Student" was his pen name.
// Gosset was statistician for Guinness brewery in Dublin, Ireland,
// hired due to Claude Guinness's innovative policy of recruiting the
// best graduates from Oxford and Cambridge for applying biochemistry
// and statistics to Guinness's industrial processes.
// Gosset published the t test in Biometrika in 1908,
// but was forced to use a pen name by his employer who regarded the fact
// that they were using statistics as a trade secret.
// In fact, Gosset's identity was unknown not only to fellow statisticians
// but to his employer - the company insisted on the pseudonym
// so that it could turn a blind eye to the breach of its rules.
// The Students't distribution function is described at
// http://en.wikipedia.org/wiki/Student%27s_t_distribution
#include <boost/math/distributions/students_t.hpp>
using boost::math::students_t; // Probability of students_t(df, t).
#include <iostream>
using std::cout; using std::endl;
#include <iomanip>
using std::setprecision; using std::setw;
#include <cmath>
using std::sqrt;
// This example of a two-sided test is from:
// B. M. Smith & M. B. Griffiths, Analyst, 1982, 107, 253,
// from Statistics for Analytical Chemistry, 3rd ed. (1994), pp 58-59
// J. C. Miller and J. N. Miller, Ellis Horwood ISBN 0 13 0309907
// Concentrations of lead (ug/l) determined by two different methods
// for each of four test portions,
// the concentration of each portion is significantly different,
// the values may NOT be pooled.
// (Called a 'paired test' by Miller and Miller
// because each portion analysed has a different concentration.)
// Portion Wet oxidation Direct Extraction
// 1 71 76
// 2 61 68
// 3 50 48
// 4 60 57
const int portions = 4;
const int methods = 2;
float data [portions][methods] = {{71, 76}, {61,68}, {50, 48}, {60, 57}};
float diffs[portions];
int main()
{
cout << "Example3 using Student's t function. " << endl;
float mean_diff = 0.f;
cout << "\n""Portion wet_oxidation Direct_extraction difference" << endl;
for (int portion = 0; portion < portions; portion++)
{ // Echo data and differences.
diffs[portion] = data[portion][0] - data[portion][1];
mean_diff += diffs[portion];
cout << setw(4) << portion << ' ' << setw(14) << data[portion][0] << ' ' << setw(18)<< data[portion][1] << ' ' << setw(9) << diffs[portion] << endl;
}
mean_diff /= portions;
cout << "Mean difference = " << mean_diff << endl; // -1.75
float sd_diffs = 0.f;
for (int portion = 0; portion < portions; portion++)
{ // Calculate standard deviation of differences.
sd_diffs +=(diffs[portion] - mean_diff) * (diffs[portion] - mean_diff);
}
int degrees_of_freedom = portions-1; // Use the n-1 formula.
sd_diffs /= degrees_of_freedom;
sd_diffs = sqrt(sd_diffs);
cout << "Standard deviation of differences = " << sd_diffs << endl; // 4.99166
// Standard deviation of differences = 4.99166
double t = mean_diff * sqrt(static_cast<double>(portions))/ sd_diffs; // -0.70117
cout << "Student's t = " << t << ", if " << degrees_of_freedom << " degrees of freedom." << endl;
// Student's t = -0.70117, if 3 degrees of freedom.
cout << "Probability of the means being different is "
<< 2.F * cdf(students_t(degrees_of_freedom), t) << "."<< endl; // 0.266846 * 2 = 0.533692
// Double the probability because using a 'two-sided test' because
// mean for 'Wet oxidation' could be either
// greater OR LESS THAN for 'Direct extraction'.
return 0;
} // int main()
/*
Output is:
Example3 using Student's t function.
Portion wet_oxidation Direct_extraction difference
0 71 76 -5
1 61 68 -7
2 50 48 2
3 60 57 3
Mean difference = -1.75
Standard deviation of differences = 4.99166
Student's t = -0.70117, if 3 degrees of freedom.
Probability of the means being different is 0.533692.
*/

View File

@@ -0,0 +1,427 @@
// Copyright John Maddock 2006
// Copyright Paul A. Bristow 2007
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifdef _MSC_VER
# pragma warning(disable: 4512) // assignment operator could not be generated.
# pragma warning(disable: 4510) // default constructor could not be generated.
# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required.
#endif
#include <iostream>
#include <iomanip>
#include <boost/math/distributions/students_t.hpp>
void confidence_limits_on_mean(double Sm, double Sd, unsigned Sn)
{
//
// Sm = Sample Mean.
// Sd = Sample Standard Deviation.
// Sn = Sample Size.
//
// Calculate confidence intervals for the mean.
// For example if we set the confidence limit to
// 0.95, we know that if we repeat the sampling
// 100 times, then we expect that the true mean
// will be between out limits on 95 occations.
// Note: this is not the same as saying a 95%
// confidence interval means that there is a 95%
// probability that the interval contains the true mean.
// The interval computed from a given sample either
// contains the true mean or it does not.
// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda352.htm
using namespace std;
using namespace boost::math;
// Print out general info:
cout <<
"__________________________________\n"
"2-Sided Confidence Limits For Mean\n"
"__________________________________\n\n";
cout << setprecision(7);
cout << setw(40) << left << "Number of Observations" << "= " << Sn << "\n";
cout << setw(40) << left << "Mean" << "= " << Sm << "\n";
cout << setw(40) << left << "Standard Deviation" << "= " << Sd << "\n";
//
// Define a table of significance/risk levels:
//
double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
//
// Start by declaring the distribution we'll need:
//
students_t dist(Sn - 1);
//
// Print table header:
//
cout << "\n\n"
"_______________________________________________________________\n"
"Confidence T Interval Lower Upper\n"
" Value (%) Value Width Limit Limit\n"
"_______________________________________________________________\n";
//
// Now print out the data for the table rows.
//
for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
{
// Confidence value:
cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]);
// calculate T:
double T = quantile(complement(dist, alpha[i] / 2));
// Print T:
cout << fixed << setprecision(3) << setw(10) << right << T;
// Calculate width of interval (one sided):
double w = T * Sd / sqrt(double(Sn));
// Print width:
if(w < 0.01)
cout << scientific << setprecision(3) << setw(17) << right << w;
else
cout << fixed << setprecision(3) << setw(17) << right << w;
// Print Limits:
cout << fixed << setprecision(5) << setw(15) << right << Sm - w;
cout << fixed << setprecision(5) << setw(15) << right << Sm + w << endl;
}
cout << endl;
}
void single_sample_t_test(double M, double Sm, double Sd, unsigned Sn, double alpha)
{
//
// M = true mean.
// Sm = Sample Mean.
// Sd = Sample Standard Deviation.
// Sn = Sample Size.
// alpha = Significance Level.
//
// A Students t test applied to a single set of data.
// We are testing the null hypothesis that the true
// mean of the sample is M, and that any variation is down
// to chance. We can also test the alternative hypothesis
// that any difference is not down to chance.
// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda352.htm
//
using namespace std;
using namespace boost::math;
// Print header:
cout <<
"__________________________________\n"
"Student t test for a single sample\n"
"__________________________________\n\n";
cout << setprecision(5);
cout << setw(55) << left << "Number of Observations" << "= " << Sn << "\n";
cout << setw(55) << left << "Sample Mean" << "= " << Sm << "\n";
cout << setw(55) << left << "Sample Standard Deviation" << "= " << Sd << "\n";
cout << setw(55) << left << "Expected True Mean" << "= " << M << "\n\n";
//
// Now we can calculate and output some stats:
//
// Difference in means:
double diff = Sm - M;
cout << setw(55) << left << "Sample Mean - Expected Test Mean" << "= " << diff << "\n";
// Degrees of freedom:
unsigned v = Sn - 1;
cout << setw(55) << left << "Degrees of Freedom" << "= " << v << "\n";
// t-statistic:
double t_stat = diff * sqrt(double(Sn)) / Sd;
cout << setw(55) << left << "T Statistic" << "= " << t_stat << "\n";
//
// Finally define our distribution, and get the probability:
//
students_t dist(v);
double q = cdf(complement(dist, fabs(t_stat)));
cout << setw(55) << left << "Probability that difference is due to chance" << "= "
<< setprecision(3) << scientific << 2 * q << "\n\n";
//
// Finally print out results of alternative hypothesis:
//
cout << setw(55) << left <<
"Results for Alternative Hypothesis and alpha" << "= "
<< setprecision(4) << fixed << alpha << "\n\n";
cout << "Alternative Hypothesis Conclusion\n";
cout << "Mean != " << setprecision(3) << fixed << M << " ";
if(q < alpha / 2)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Mean < " << setprecision(3) << fixed << M << " ";
if(cdf(dist, t_stat) < alpha)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Mean > " << setprecision(3) << fixed << M << " ";
if(cdf(complement(dist, t_stat)) < alpha)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << endl << endl;
}
void single_sample_find_df(double M, double Sm, double Sd)
{
//
// M = true mean.
// Sm = Sample Mean.
// Sd = Sample Standard Deviation.
//
using namespace std;
using namespace boost::math;
// Print out general info:
cout <<
"_____________________________________________________________\n"
"Estimated sample sizes required for various confidence levels\n"
"_____________________________________________________________\n\n";
cout << setprecision(5);
cout << setw(40) << left << "True Mean" << "= " << M << "\n";
cout << setw(40) << left << "Sample Mean" << "= " << Sm << "\n";
cout << setw(40) << left << "Sample Standard Deviation" << "= " << Sd << "\n";
//
// Define a table of significance intervals:
//
double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 };
//
// Print table header:
//
cout << "\n\n"
"_______________________________________________________________\n"
"Confidence Estimated Estimated\n"
" Value (%) Sample Size Sample Size\n"
" (one sided test) (two sided test)\n"
"_______________________________________________________________\n";
//
// Now print out the data for the table rows.
//
for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i)
{
// Confidence value:
cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]);
// calculate df for single sided test:
double df = students_t::find_degrees_of_freedom(
fabs(M - Sm), alpha[i], alpha[i], Sd);
// convert to sample size:
double size = ceil(df) + 1;
// Print size:
cout << fixed << setprecision(0) << setw(16) << right << size;
// calculate df for two sided test:
df = students_t::find_degrees_of_freedom(
fabs(M - Sm), alpha[i]/2, alpha[i], Sd);
// convert to sample size:
size = ceil(df) + 1;
// Print size:
cout << fixed << setprecision(0) << setw(16) << right << size << endl;
}
cout << endl;
}
int main()
{
//
// Run tests for Heat Flow Meter data
// see http://www.itl.nist.gov/div898/handbook/eda/section4/eda428.htm
// The data was collected while calibrating a heat flow meter
// against a known value.
//
confidence_limits_on_mean(9.261460, 0.2278881e-01, 195);
single_sample_t_test(5, 9.261460, 0.2278881e-01, 195, 0.05);
single_sample_find_df(5, 9.261460, 0.2278881e-01);
//
// Data for this example from:
// P.K.Hou, O. W. Lau & M.C. Wong, Analyst (1983) vol. 108, p 64.
// from Statistics for Analytical Chemistry, 3rd ed. (1994), pp 54-55
// J. C. Miller and J. N. Miller, Ellis Horwood ISBN 0 13 0309907
//
// Determination of mercury by cold-vapour atomic absorption,
// the following values were obtained fusing a trusted
// Standard Reference Material containing 38.9% mercury,
// which we assume is correct or 'true'.
//
confidence_limits_on_mean(37.8, 0.964365, 3);
// 95% test:
single_sample_t_test(38.9, 37.8, 0.964365, 3, 0.05);
// 90% test:
single_sample_t_test(38.9, 37.8, 0.964365, 3, 0.1);
// parameter estimate:
single_sample_find_df(38.9, 37.8, 0.964365);
return 0;
}
/*
Output:
------ Build started: Project: students_t_single_sample, Configuration: Debug Win32 ------
Compiling...
students_t_single_sample.cpp
Linking...
Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\students_t_single_sample.exe"
__________________________________
2-Sided Confidence Limits For Mean
__________________________________
Number of Observations = 195
Mean = 9.26146
Standard Deviation = 0.02278881
_______________________________________________________________
Confidence T Interval Lower Upper
Value (%) Value Width Limit Limit
_______________________________________________________________
50.000 0.676 1.103e-003 9.26036 9.26256
75.000 1.154 1.883e-003 9.25958 9.26334
90.000 1.653 2.697e-003 9.25876 9.26416
95.000 1.972 3.219e-003 9.25824 9.26468
99.000 2.601 4.245e-003 9.25721 9.26571
99.900 3.341 5.453e-003 9.25601 9.26691
99.990 3.973 6.484e-003 9.25498 9.26794
99.999 4.537 7.404e-003 9.25406 9.26886
__________________________________
Student t test for a single sample
__________________________________
Number of Observations = 195
Sample Mean = 9.26146
Sample Standard Deviation = 0.02279
Expected True Mean = 5.00000
Sample Mean - Expected Test Mean = 4.26146
Degrees of Freedom = 194
T Statistic = 2611.28380
Probability that difference is due to chance = 0.000e+000
Results for Alternative Hypothesis and alpha = 0.0500
Alternative Hypothesis Conclusion
Mean != 5.000 NOT REJECTED
Mean < 5.000 REJECTED
Mean > 5.000 NOT REJECTED
_____________________________________________________________
Estimated sample sizes required for various confidence levels
_____________________________________________________________
True Mean = 5.00000
Sample Mean = 9.26146
Sample Standard Deviation = 0.02279
_______________________________________________________________
Confidence Estimated Estimated
Value (%) Sample Size Sample Size
(one sided test) (two sided test)
_______________________________________________________________
50.000 2 2
75.000 2 2
90.000 2 2
95.000 2 2
99.000 2 2
99.900 3 3
99.990 3 3
99.999 4 4
__________________________________
2-Sided Confidence Limits For Mean
__________________________________
Number of Observations = 3
Mean = 37.8000000
Standard Deviation = 0.9643650
_______________________________________________________________
Confidence T Interval Lower Upper
Value (%) Value Width Limit Limit
_______________________________________________________________
50.000 0.816 0.455 37.34539 38.25461
75.000 1.604 0.893 36.90717 38.69283
90.000 2.920 1.626 36.17422 39.42578
95.000 4.303 2.396 35.40438 40.19562
99.000 9.925 5.526 32.27408 43.32592
99.900 31.599 17.594 20.20639 55.39361
99.990 99.992 55.673 -17.87346 93.47346
99.999 316.225 176.067 -138.26683 213.86683
__________________________________
Student t test for a single sample
__________________________________
Number of Observations = 3
Sample Mean = 37.80000
Sample Standard Deviation = 0.96437
Expected True Mean = 38.90000
Sample Mean - Expected Test Mean = -1.10000
Degrees of Freedom = 2
T Statistic = -1.97566
Probability that difference is due to chance = 1.869e-001
Results for Alternative Hypothesis and alpha = 0.0500
Alternative Hypothesis Conclusion
Mean != 38.900 REJECTED
Mean < 38.900 REJECTED
Mean > 38.900 REJECTED
__________________________________
Student t test for a single sample
__________________________________
Number of Observations = 3
Sample Mean = 37.80000
Sample Standard Deviation = 0.96437
Expected True Mean = 38.90000
Sample Mean - Expected Test Mean = -1.10000
Degrees of Freedom = 2
T Statistic = -1.97566
Probability that difference is due to chance = 1.869e-001
Results for Alternative Hypothesis and alpha = 0.1000
Alternative Hypothesis Conclusion
Mean != 38.900 REJECTED
Mean < 38.900 NOT REJECTED
Mean > 38.900 REJECTED
_____________________________________________________________
Estimated sample sizes required for various confidence levels
_____________________________________________________________
True Mean = 38.90000
Sample Mean = 37.80000
Sample Standard Deviation = 0.96437
_______________________________________________________________
Confidence Estimated Estimated
Value (%) Sample Size Sample Size
(one sided test) (two sided test)
_______________________________________________________________
50.000 2 2
75.000 3 4
90.000 7 9
95.000 11 13
99.000 20 22
99.900 35 37
99.990 50 53
99.999 66 68
Build Time 0:03
Build log was saved at "file://i:\boost-06-05-03-1300\libs\math\test\Math_test\students_t_single_sample\Debug\BuildLog.htm"
students_t_single_sample - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
*/

View File

@@ -0,0 +1,261 @@
// Copyright John Maddock 2006.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifdef _MSC_VER
# pragma warning(disable: 4512) // assignment operator could not be generated.
# pragma warning(disable: 4510) // default constructor could not be generated.
# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required.
#endif
#include <iostream>
#include <iomanip>
#include <boost/math/distributions/students_t.hpp>
void two_samples_t_test_equal_sd(
double Sm1,
double Sd1,
unsigned Sn1,
double Sm2,
double Sd2,
unsigned Sn2,
double alpha)
{
//
// Sm1 = Sample Mean 1.
// Sd1 = Sample Standard Deviation 1.
// Sn1 = Sample Size 1.
// Sm2 = Sample Mean 2.
// Sd2 = Sample Standard Deviation 2.
// Sn2 = Sample Size 2.
// alpha = Significance Level.
//
// A Students t test applied to two sets of data.
// We are testing the null hypothesis that the two
// samples have the same mean and that any difference
// if due to chance.
// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda353.htm
//
using namespace std;
using namespace boost::math;
// Print header:
cout <<
"_______________________________________________\n"
"Student t test for two samples (equal variances)\n"
"_______________________________________________\n\n";
cout << setprecision(5);
cout << setw(55) << left << "Number of Observations (Sample 1)" << "= " << Sn1 << "\n";
cout << setw(55) << left << "Sample 1 Mean" << "= " << Sm1 << "\n";
cout << setw(55) << left << "Sample 1 Standard Deviation" << "= " << Sd1 << "\n";
cout << setw(55) << left << "Number of Observations (Sample 2)" << "= " << Sn2 << "\n";
cout << setw(55) << left << "Sample 2 Mean" << "= " << Sm2 << "\n";
cout << setw(55) << left << "Sample 2 Standard Deviation" << "= " << Sd2 << "\n";
//
// Now we can calculate and output some stats:
//
// Degrees of freedom:
double v = Sn1 + Sn2 - 2;
cout << setw(55) << left << "Degrees of Freedom" << "= " << v << "\n";
// Pooled variance:
double sp = sqrt(((Sn1-1) * Sd1 * Sd1 + (Sn2-1) * Sd2 * Sd2) / v);
cout << setw(55) << left << "Pooled Standard Deviation" << "= " << v << "\n";
// t-statistic:
double t_stat = (Sm1 - Sm2) / (sp * sqrt(1.0 / Sn1 + 1.0 / Sn2));
cout << setw(55) << left << "T Statistic" << "= " << t_stat << "\n";
//
// Define our distribution, and get the probability:
//
students_t dist(v);
double q = cdf(complement(dist, fabs(t_stat)));
cout << setw(55) << left << "Probability that difference is due to chance" << "= "
<< setprecision(3) << scientific << 2 * q << "\n\n";
//
// Finally print out results of alternative hypothesis:
//
cout << setw(55) << left <<
"Results for Alternative Hypothesis and alpha" << "= "
<< setprecision(4) << fixed << alpha << "\n\n";
cout << "Alternative Hypothesis Conclusion\n";
cout << "Sample 1 Mean != Sample 2 Mean " ;
if(q < alpha / 2)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Sample 1 Mean < Sample 2 Mean ";
if(cdf(dist, t_stat) < alpha)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Sample 1 Mean > Sample 2 Mean ";
if(cdf(complement(dist, t_stat)) < alpha)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << endl << endl;
}
void two_samples_t_test_unequal_sd(
double Sm1,
double Sd1,
unsigned Sn1,
double Sm2,
double Sd2,
unsigned Sn2,
double alpha)
{
//
// Sm1 = Sample Mean 1.
// Sd1 = Sample Standard Deviation 1.
// Sn1 = Sample Size 1.
// Sm2 = Sample Mean 2.
// Sd2 = Sample Standard Deviation 2.
// Sn2 = Sample Size 2.
// alpha = Significance Level.
//
// A Students t test applied to two sets of data.
// We are testing the null hypothesis that the two
// samples have the same mean and that any difference
// if due to chance.
// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda353.htm
//
using namespace std;
using namespace boost::math;
// Print header:
cout <<
"_________________________________________________\n"
"Student t test for two samples (unequal variances)\n"
"_________________________________________________\n\n";
cout << setprecision(5);
cout << setw(55) << left << "Number of Observations (Sample 1)" << "= " << Sn1 << "\n";
cout << setw(55) << left << "Sample 1 Mean" << "= " << Sm1 << "\n";
cout << setw(55) << left << "Sample 1 Standard Deviation" << "= " << Sd1 << "\n";
cout << setw(55) << left << "Number of Observations (Sample 2)" << "= " << Sn2 << "\n";
cout << setw(55) << left << "Sample 2 Mean" << "= " << Sm2 << "\n";
cout << setw(55) << left << "Sample 2 Standard Deviation" << "= " << Sd2 << "\n";
//
// Now we can calculate and output some stats:
//
// Degrees of freedom:
double v = Sd1 * Sd1 / Sn1 + Sd2 * Sd2 / Sn2;
v *= v;
double t1 = Sd1 * Sd1 / Sn1;
t1 *= t1;
t1 /= (Sn1 - 1);
double t2 = Sd2 * Sd2 / Sn2;
t2 *= t2;
t2 /= (Sn2 - 1);
v /= (t1 + t2);
cout << setw(55) << left << "Degrees of Freedom" << "= " << v << "\n";
// t-statistic:
double t_stat = (Sm1 - Sm2) / sqrt(Sd1 * Sd1 / Sn1 + Sd2 * Sd2 / Sn2);
cout << setw(55) << left << "T Statistic" << "= " << t_stat << "\n";
//
// Define our distribution, and get the probability:
//
students_t dist(v);
double q = cdf(complement(dist, fabs(t_stat)));
cout << setw(55) << left << "Probability that difference is due to chance" << "= "
<< setprecision(3) << scientific << 2 * q << "\n\n";
//
// Finally print out results of alternative hypothesis:
//
cout << setw(55) << left <<
"Results for Alternative Hypothesis and alpha" << "= "
<< setprecision(4) << fixed << alpha << "\n\n";
cout << "Alternative Hypothesis Conclusion\n";
cout << "Sample 1 Mean != Sample 2 Mean " ;
if(q < alpha / 2)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Sample 1 Mean < Sample 2 Mean ";
if(cdf(dist, t_stat) < alpha)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << "Sample 1 Mean > Sample 2 Mean ";
if(cdf(complement(dist, t_stat)) < alpha)
cout << "NOT REJECTED\n";
else
cout << "REJECTED\n";
cout << endl << endl;
}
int main()
{
//
// Run tests for Car Mileage sample data
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3531.htm
// from the NIST website http://www.itl.nist.gov. The data compares
// miles per gallon of US cars with miles per gallon of Japanese cars.
//
two_samples_t_test_equal_sd(20.14458, 6.414700, 249, 30.48101, 6.107710, 79, 0.05);
two_samples_t_test_unequal_sd(20.14458, 6.414700, 249, 30.48101, 6.107710, 79, 0.05);
return 0;
} // int main()
/*
Output is
------ Build started: Project: students_t_two_samples, Configuration: Debug Win32 ------
Compiling...
students_t_two_samples.cpp
Linking...
Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\students_t_two_samples.exe"
_______________________________________________
Student t test for two samples (equal variances)
_______________________________________________
Number of Observations (Sample 1) = 249
Sample 1 Mean = 20.145
Sample 1 Standard Deviation = 6.4147
Number of Observations (Sample 2) = 79
Sample 2 Mean = 30.481
Sample 2 Standard Deviation = 6.1077
Degrees of Freedom = 326
Pooled Standard Deviation = 326
T Statistic = -12.621
Probability that difference is due to chance = 5.273e-030
Results for Alternative Hypothesis and alpha = 0.0500
Alternative Hypothesis Conclusion
Sample 1 Mean != Sample 2 Mean NOT REJECTED
Sample 1 Mean < Sample 2 Mean NOT REJECTED
Sample 1 Mean > Sample 2 Mean REJECTED
_________________________________________________
Student t test for two samples (unequal variances)
_________________________________________________
Number of Observations (Sample 1) = 249
Sample 1 Mean = 20.14458
Sample 1 Standard Deviation = 6.41470
Number of Observations (Sample 2) = 79
Sample 2 Mean = 30.48101
Sample 2 Standard Deviation = 6.10771
Degrees of Freedom = 136.87499
T Statistic = -12.94627
Probability that difference is due to chance = 1.571e-025
Results for Alternative Hypothesis and alpha = 0.0500
Alternative Hypothesis Conclusion
Sample 1 Mean != Sample 2 Mean NOT REJECTED
Sample 1 Mean < Sample 2 Mean NOT REJECTED
Sample 1 Mean > Sample 2 Mean REJECTED
Build Time 0:03
Build log was saved at "file://i:\boost-06-05-03-1300\libs\math\test\Math_test\students_t_two_samples\Debug\BuildLog.htm"
students_t_two_samples - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
*/

View File

@@ -0,0 +1,707 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/math/tools/real_cast.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/tools/roots.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <ostream>
#include <istream>
#include <cmath>
#include <NTL/RR.h>
#ifndef BOOST_MATH_NTL_RR_HPP
#define BOOST_MATH_NTL_RR_HPP
namespace boost{ namespace math{
namespace ntl
{
class RR;
RR ldexp(RR r, int exp);
RR frexp(RR r, int* exp);
class RR
{
public:
// Constructors:
RR() {}
RR(const ::NTL::RR& c) : m_value(c){}
RR(char c)
{
m_value = c;
}
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
RR(wchar_t c)
{
m_value = c;
}
#endif
RR(unsigned char c)
{
m_value = c;
}
RR(signed char c)
{
m_value = c;
}
RR(unsigned short c)
{
m_value = c;
}
RR(short c)
{
m_value = c;
}
RR(unsigned int c)
{
assign_large_int(c);
}
RR(int c)
{
assign_large_int(c);
}
RR(unsigned long c)
{
assign_large_int(c);
}
RR(long c)
{
assign_large_int(c);
}
#ifdef BOOST_HAS_LONG_LONG
RR(unsigned long long c)
{
assign_large_int(c);
}
RR(long long c)
{
assign_large_int(c);
}
#endif
RR(float c)
{
m_value = c;
}
RR(double c)
{
m_value = c;
}
RR(long double c)
{
assign_large_real(c);
}
// Assignment:
RR& operator=(char c) { m_value = c; return *this; }
RR& operator=(unsigned char c) { m_value = c; return *this; }
RR& operator=(signed char c) { m_value = c; return *this; }
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
RR& operator=(wchar_t c) { m_value = c; return *this; }
#endif
RR& operator=(short c) { m_value = c; return *this; }
RR& operator=(unsigned short c) { m_value = c; return *this; }
RR& operator=(int c) { assign_large_int(c); return *this; }
RR& operator=(unsigned int c) { assign_large_int(c); return *this; }
RR& operator=(long c) { assign_large_int(c); return *this; }
RR& operator=(unsigned long c) { assign_large_int(c); return *this; }
#ifdef BOOST_HAS_LONG_LONG
RR& operator=(long long c) { assign_large_int(c); return *this; }
RR& operator=(unsigned long long c) { assign_large_int(c); return *this; }
#endif
RR& operator=(float c) { m_value = c; return *this; }
RR& operator=(double c) { m_value = c; return *this; }
RR& operator=(long double c) { assign_large_real(c); return *this; }
// Access:
NTL::RR& value(){ return m_value; }
NTL::RR const& value()const{ return m_value; }
// Member arithmetic:
RR& operator+=(const RR& other)
{ m_value += other.value(); return *this; }
RR& operator-=(const RR& other)
{ m_value -= other.value(); return *this; }
RR& operator*=(const RR& other)
{ m_value *= other.value(); return *this; }
RR& operator/=(const RR& other)
{ m_value /= other.value(); return *this; }
RR operator-()const
{ return -m_value; }
RR const& operator+()const
{ return *this; }
// RR compatibity:
const ::NTL::ZZ& mantissa() const
{ return m_value.mantissa(); }
long exponent() const
{ return m_value.exponent(); }
static void SetPrecision(long p)
{ ::NTL::RR::SetPrecision(p); }
static long precision()
{ return ::NTL::RR::precision(); }
static void SetOutputPrecision(long p)
{ ::NTL::RR::SetOutputPrecision(p); }
static long OutputPrecision()
{ return ::NTL::RR::OutputPrecision(); }
private:
::NTL::RR m_value;
template <class V>
void assign_large_real(const V& a)
{
using std::frexp;
using std::ldexp;
using std::floor;
if (a == 0) {
clear(m_value);
return;
}
if (a == 1) {
NTL::set(m_value);
return;
}
if (!(boost::math::isfinite)(a))
{
throw std::overflow_error("Cannot construct an instance of NTL::RR with an infinite value.");
}
int e;
long double f, term;
::NTL::RR t;
clear(m_value);
f = frexp(a, &e);
while(f)
{
// extract 30 bits from f:
f = ldexp(f, 30);
term = floor(f);
e -= 30;
conv(t.x, (int)term);
t.e = e;
m_value += t;
f -= term;
}
}
template <class V>
void assign_large_int(V a)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4146)
#endif
clear(m_value);
int exp = 0;
NTL::RR t;
bool neg = a < V(0) ? true : false;
if(neg)
a = -a;
while(a)
{
t = static_cast<double>(a & 0xffff);
m_value += ldexp(RR(t), exp).value();
a >>= 16;
exp += 16;
}
if(neg)
m_value = -m_value;
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
};
// Non-member arithmetic:
inline RR operator+(const RR& a, const RR& b)
{
RR result(a);
result += b;
return result;
}
inline RR operator-(const RR& a, const RR& b)
{
RR result(a);
result -= b;
return result;
}
inline RR operator*(const RR& a, const RR& b)
{
RR result(a);
result *= b;
return result;
}
inline RR operator/(const RR& a, const RR& b)
{
RR result(a);
result /= b;
return result;
}
// Comparison:
inline bool operator == (const RR& a, const RR& b)
{ return a.value() == b.value() ? true : false; }
inline bool operator != (const RR& a, const RR& b)
{ return a.value() != b.value() ? true : false;}
inline bool operator < (const RR& a, const RR& b)
{ return a.value() < b.value() ? true : false; }
inline bool operator <= (const RR& a, const RR& b)
{ return a.value() <= b.value() ? true : false; }
inline bool operator > (const RR& a, const RR& b)
{ return a.value() > b.value() ? true : false; }
inline bool operator >= (const RR& a, const RR& b)
{ return a.value() >= b.value() ? true : false; }
#if 0
// Non-member mixed compare:
template <class T>
inline bool operator == (const T& a, const RR& b)
{
return a == b.value();
}
template <class T>
inline bool operator != (const T& a, const RR& b)
{
return a != b.value();
}
template <class T>
inline bool operator < (const T& a, const RR& b)
{
return a < b.value();
}
template <class T>
inline bool operator > (const T& a, const RR& b)
{
return a > b.value();
}
template <class T>
inline bool operator <= (const T& a, const RR& b)
{
return a <= b.value();
}
template <class T>
inline bool operator >= (const T& a, const RR& b)
{
return a >= b.value();
}
#endif // Non-member mixed compare:
// Non-member functions:
/*
inline RR acos(RR a)
{ return ::NTL::acos(a.value()); }
*/
inline RR cos(RR a)
{ return ::NTL::cos(a.value()); }
/*
inline RR asin(RR a)
{ return ::NTL::asin(a.value()); }
inline RR atan(RR a)
{ return ::NTL::atan(a.value()); }
inline RR atan2(RR a, RR b)
{ return ::NTL::atan2(a.value(), b.value()); }
*/
inline RR ceil(RR a)
{ return ::NTL::ceil(a.value()); }
/*
inline RR fmod(RR a, RR b)
{ return ::NTL::fmod(a.value(), b.value()); }
inline RR cosh(RR a)
{ return ::NTL::cosh(a.value()); }
*/
inline RR exp(RR a)
{ return ::NTL::exp(a.value()); }
inline RR fabs(RR a)
{ return ::NTL::fabs(a.value()); }
inline RR abs(RR a)
{ return ::NTL::abs(a.value()); }
inline RR floor(RR a)
{ return ::NTL::floor(a.value()); }
/*
inline RR modf(RR a, RR* ipart)
{
::NTL::RR ip;
RR result = modf(a.value(), &ip);
*ipart = ip;
return result;
}
inline RR frexp(RR a, int* expon)
{ return ::NTL::frexp(a.value(), expon); }
inline RR ldexp(RR a, int expon)
{ return ::NTL::ldexp(a.value(), expon); }
*/
inline RR log(RR a)
{ return ::NTL::log(a.value()); }
inline RR log10(RR a)
{ return ::NTL::log10(a.value()); }
/*
inline RR tan(RR a)
{ return ::NTL::tan(a.value()); }
*/
inline RR pow(RR a, RR b)
{ return ::NTL::pow(a.value(), b.value()); }
inline RR pow(RR a, int b)
{ return ::NTL::power(a.value(), b); }
inline RR sin(RR a)
{ return ::NTL::sin(a.value()); }
/*
inline RR sinh(RR a)
{ return ::NTL::sinh(a.value()); }
*/
inline RR sqrt(RR a)
{ return ::NTL::sqrt(a.value()); }
/*
inline RR tanh(RR a)
{ return ::NTL::tanh(a.value()); }
*/
inline RR pow(const RR& r, long l)
{
return ::NTL::power(r.value(), l);
}
inline RR tan(const RR& a)
{
return sin(a)/cos(a);
}
inline RR frexp(RR r, int* exp)
{
*exp = r.value().e;
r.value().e = 0;
while(r >= 1)
{
*exp += 1;
r.value().e -= 1;
}
while(r < 0.5)
{
*exp -= 1;
r.value().e += 1;
}
BOOST_ASSERT(r < 1);
BOOST_ASSERT(r >= 0.5);
return r;
}
inline RR ldexp(RR r, int exp)
{
r.value().e += exp;
return r;
}
// Streaming:
template <class charT, class traits>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const RR& a)
{
return os << a.value();
}
template <class charT, class traits>
inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, RR& a)
{
long double v;
is >> v;
a = v;
return is;
}
} // namespace ntl
namespace tools
{
template<>
inline int digits<boost::math::ntl::RR>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
{
return ::NTL::RR::precision();
}
template <>
inline float real_cast<float, boost::math::ntl::RR>(boost::math::ntl::RR t)
{
double r;
conv(r, t.value());
return static_cast<float>(r);
}
template <>
inline double real_cast<double, boost::math::ntl::RR>(boost::math::ntl::RR t)
{
double r;
conv(r, t.value());
return r;
}
namespace detail{
template<class I>
void convert_to_long_result(NTL::RR const& r, I& result)
{
result = 0;
I last_result(0);
NTL::RR t(r);
double term;
do
{
conv(term, t);
last_result = result;
result += static_cast<I>(term);
t -= term;
}while(result != last_result);
}
}
template <>
inline long double real_cast<long double, boost::math::ntl::RR>(boost::math::ntl::RR t)
{
long double result(0);
detail::convert_to_long_result(t.value(), result);
return result;
}
template <>
inline boost::math::ntl::RR real_cast<boost::math::ntl::RR, boost::math::ntl::RR>(boost::math::ntl::RR t)
{
return t;
}
template <>
inline unsigned real_cast<unsigned, boost::math::ntl::RR>(boost::math::ntl::RR t)
{
unsigned result;
detail::convert_to_long_result(t.value(), result);
return result;
}
template <>
inline int real_cast<int, boost::math::ntl::RR>(boost::math::ntl::RR t)
{
unsigned result;
detail::convert_to_long_result(t.value(), result);
return result;
}
template <>
inline boost::math::ntl::RR max_value<boost::math::ntl::RR>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
{
static bool has_init = false;
static NTL::RR val;
if(!has_init)
{
val = 1;
val.e = NTL_OVFBND-20;
has_init = true;
}
return val;
}
template <>
inline boost::math::ntl::RR min_value<boost::math::ntl::RR>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
{
static bool has_init = false;
static NTL::RR val;
if(!has_init)
{
val = 1;
val.e = -NTL_OVFBND+20;
has_init = true;
}
return val;
}
template <>
inline boost::math::ntl::RR log_max_value<boost::math::ntl::RR>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
{
static bool has_init = false;
static NTL::RR val;
if(!has_init)
{
val = 1;
val.e = NTL_OVFBND-20;
val = log(val);
has_init = true;
}
return val;
}
template <>
inline boost::math::ntl::RR log_min_value<boost::math::ntl::RR>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
{
static bool has_init = false;
static NTL::RR val;
if(!has_init)
{
val = 1;
val.e = -NTL_OVFBND+20;
val = log(val);
has_init = true;
}
return val;
}
template <>
inline boost::math::ntl::RR epsilon<boost::math::ntl::RR>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
{
return ldexp(boost::math::ntl::RR(1), 1-boost::math::policies::digits<boost::math::ntl::RR, boost::math::policies::policy<> >());
}
} // namespace tools
//
// The number of digits precision in RR can vary with each call
// so we need to recalculate these with each call:
//
namespace constants{
template<> inline boost::math::ntl::RR pi<boost::math::ntl::RR>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
{
NTL::RR result;
ComputePi(result);
return result;
}
template<> inline boost::math::ntl::RR e<boost::math::ntl::RR>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
{
NTL::RR result;
result = 1;
return exp(result);
}
} // namespace constants
namespace ntl{
//
// These are some fairly brain-dead versions of the math
// functions that NTL fails to provide.
//
//
// Inverse trig functions:
//
struct asin_root
{
asin_root(RR const& target) : t(target){}
std::tr1::tuple<RR, RR, RR> operator()(RR const& p)
{
RR f0 = sin(p);
RR f1 = cos(p);
RR f2 = -f0;
f0 -= t;
return std::tr1::make_tuple(f0, f1, f2);
}
private:
RR t;
};
inline RR asin(RR z)
{
double r;
conv(r, z.value());
return boost::math::tools::halley_iterate(
asin_root(z),
RR(std::asin(r)),
RR(-boost::math::constants::pi<RR>()/2),
RR(boost::math::constants::pi<RR>()/2),
NTL::RR::precision());
}
struct acos_root
{
acos_root(RR const& target) : t(target){}
std::tr1::tuple<RR, RR, RR> operator()(RR const& p)
{
RR f0 = cos(p);
RR f1 = -sin(p);
RR f2 = -f0;
f0 -= t;
return std::tr1::make_tuple(f0, f1, f2);
}
private:
RR t;
};
inline RR acos(RR z)
{
double r;
conv(r, z.value());
return boost::math::tools::halley_iterate(
acos_root(z),
RR(std::acos(r)),
RR(-boost::math::constants::pi<RR>()/2),
RR(boost::math::constants::pi<RR>()/2),
NTL::RR::precision());
}
struct atan_root
{
atan_root(RR const& target) : t(target){}
std::tr1::tuple<RR, RR, RR> operator()(RR const& p)
{
RR c = cos(p);
RR ta = tan(p);
RR f0 = ta - t;
RR f1 = 1 / (c * c);
RR f2 = 2 * ta / (c * c);
return std::tr1::make_tuple(f0, f1, f2);
}
private:
RR t;
};
inline RR atan(RR z)
{
double r;
conv(r, z.value());
return boost::math::tools::halley_iterate(
atan_root(z),
RR(std::atan(r)),
-boost::math::constants::pi<RR>()/2,
boost::math::constants::pi<RR>()/2,
NTL::RR::precision());
}
inline RR sinh(RR z)
{
return (expm1(z.value()) - expm1(-z.value())) / 2;
}
inline RR cosh(RR z)
{
return (exp(z) + exp(-z)) / 2;
}
inline RR tanh(RR z)
{
return sinh(z) / cosh(z);
}
inline RR fmod(RR x, RR y)
{
// This is a really crummy version of fmod, we rely on lots
// of digits to get us out of trouble...
RR factor = floor(x/y);
return x - factor * y;
}
} // namespace ntl
} // namespace math
} // namespace boost
#endif // BOOST_MATH_REAL_CONCEPT_HPP

View File

@@ -0,0 +1,203 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// distributions.hpp provides definitions of the concept of a distribution
// and non-member accessor functions that must be implemented by all distributions.
// This is used to verify that
// all the features of a distributions have been fully implemented.
#ifndef BOOST_MATH_DISTRIBUTION_CONCEPT_HPP
#define BOOST_MATH_DISTRIBUTION_CONCEPT_HPP
#include <boost/math/distributions/complement.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4100)
#pragma warning(disable: 4510)
#pragma warning(disable: 4610)
#endif
#include <boost/concept_check.hpp>
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#include <utility>
namespace boost{
namespace math{
namespace concepts
{
// Begin by defining a concept archetype
// for a distribution class:
//
template <class RealType>
class distribution_archetype
{
public:
typedef RealType value_type;
distribution_archetype(const distribution_archetype&); // Copy constructible.
distribution_archetype& operator=(const distribution_archetype&); // Assignable.
// There is no default constructor,
// but we need a way to instantiate the archetype:
static distribution_archetype& get_object()
{
// will never get caled:
return *reinterpret_cast<distribution_archetype*>(0);
}
}; // template <class RealType>class distribution_archetype
// Non-member accessor functions:
// (This list defines the functions that must be implemented by all distributions).
template <class RealType>
RealType pdf(const distribution_archetype<RealType>& dist, const RealType& x);
template <class RealType>
RealType cdf(const distribution_archetype<RealType>& dist, const RealType& x);
template <class RealType>
RealType quantile(const distribution_archetype<RealType>& dist, const RealType& p);
template <class RealType>
RealType cdf(const complemented2_type<distribution_archetype<RealType>, RealType>& c);
template <class RealType>
RealType quantile(const complemented2_type<distribution_archetype<RealType>, RealType>& c);
template <class RealType>
RealType mean(const distribution_archetype<RealType>& dist);
template <class RealType>
RealType standard_deviation(const distribution_archetype<RealType>& dist);
template <class RealType>
RealType variance(const distribution_archetype<RealType>& dist);
template <class RealType>
RealType hazard(const distribution_archetype<RealType>& dist);
template <class RealType>
RealType chf(const distribution_archetype<RealType>& dist);
// http://en.wikipedia.org/wiki/Characteristic_function_%28probability_theory%29
template <class RealType>
RealType coefficient_of_variation(const distribution_archetype<RealType>& dist);
template <class RealType>
RealType mode(const distribution_archetype<RealType>& dist);
template <class RealType>
RealType skewness(const distribution_archetype<RealType>& dist);
template <class RealType>
RealType kurtosis_excess(const distribution_archetype<RealType>& dist);
template <class RealType>
RealType kurtosis(const distribution_archetype<RealType>& dist);
template <class RealType>
RealType median(const distribution_archetype<RealType>& dist);
template <class RealType>
std::pair<RealType, RealType> range(const distribution_archetype<RealType>& dist);
template <class RealType>
std::pair<RealType, RealType> support(const distribution_archetype<RealType>& dist);
//
// Next comes the concept checks for verifying that a class
// fullfils the requirements of a Distribution:
//
template <class Distribution>
struct DistributionConcept
{
void constraints()
{
function_requires<CopyConstructibleConcept<Distribution> >();
function_requires<AssignableConcept<Distribution> >();
typedef typename Distribution::value_type value_type;
const Distribution& dist = DistributionConcept<Distribution>::get_object();
value_type x = 0;
// The result values are ignored in all these checks.
value_type v = cdf(dist, x);
v = cdf(complement(dist, x));
v = pdf(dist, x);
v = quantile(dist, x);
v = quantile(complement(dist, x));
v = mean(dist);
v = mode(dist);
v = standard_deviation(dist);
v = variance(dist);
v = hazard(dist, x);
v = chf(dist, x);
v = coefficient_of_variation(dist);
v = skewness(dist);
v = kurtosis(dist);
v = kurtosis_excess(dist);
v = median(dist);
std::pair<value_type, value_type> pv;
pv = range(dist);
pv = support(dist);
float f = 1;
v = cdf(dist, f);
v = cdf(complement(dist, f));
v = pdf(dist, f);
v = quantile(dist, f);
v = quantile(complement(dist, f));
v = hazard(dist, f);
v = chf(dist, f);
double d = 1;
v = cdf(dist, d);
v = cdf(complement(dist, d));
v = pdf(dist, d);
v = quantile(dist, d);
v = quantile(complement(dist, d));
v = hazard(dist, d);
v = chf(dist, d);
long double ld = 1;
v = cdf(dist, ld);
v = cdf(complement(dist, ld));
v = pdf(dist, ld);
v = quantile(dist, ld);
v = quantile(complement(dist, ld));
v = hazard(dist, ld);
v = chf(dist, ld);
int i = 1;
v = cdf(dist, i);
v = cdf(complement(dist, i));
v = pdf(dist, i);
v = quantile(dist, i);
v = quantile(complement(dist, i));
v = hazard(dist, i);
v = chf(dist, i);
unsigned long li = 1;
v = cdf(dist, li);
v = cdf(complement(dist, li));
v = pdf(dist, li);
v = quantile(dist, li);
v = quantile(complement(dist, li));
v = hazard(dist, li);
v = chf(dist, li);
}
private:
static Distribution& get_object()
{
// will never get called:
return * reinterpret_cast<Distribution*>(0);
}
}; // struct DistributionConcept
} // namespace concepts
} // namespace math
} // namespace boost
#endif // BOOST_MATH_DISTRIBUTION_CONCEPT_HPP

View File

@@ -0,0 +1,349 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Test real concept.
// real_concept is an archetype for User defined Real types.
// This file defines the features, constructors, operators, functions...
// that are essential to use mathematical and statistical functions.
// The template typename "RealType" is used where this type
// (as well as the normal built-in types, float, double & long double)
// can be used.
// That this is the minimum set is confirmed by use as a type
// in tests of all functions & distributions, for example:
// test_spots(0.F); & test_spots(0.); for float and double, but also
// test_spots(boost::math::concepts::real_concept(0.));
// NTL quad_float type is an example of a type meeting the requirements,
// but note minor additions are needed - see ntl.diff and documentation
// "Using With NTL - a High-Precision Floating-Point Library".
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/math/tools/real_cast.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/policies/policy.hpp>
#include <ostream>
#include <istream>
#include <cmath>
#ifndef BOOST_MATH_REAL_CONCEPT_HPP
#define BOOST_MATH_REAL_CONCEPT_HPP
namespace boost{ namespace math{
namespace concepts
{
class real_concept
{
public:
// Constructors:
real_concept() : m_value(0){}
real_concept(char c) : m_value(c){}
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
real_concept(wchar_t c) : m_value(c){}
#endif
real_concept(unsigned char c) : m_value(c){}
real_concept(signed char c) : m_value(c){}
real_concept(unsigned short c) : m_value(c){}
real_concept(short c) : m_value(c){}
real_concept(unsigned int c) : m_value(c){}
real_concept(int c) : m_value(c){}
real_concept(unsigned long c) : m_value(c){}
real_concept(long c) : m_value(c){}
#ifdef BOOST_HAS_LONG_LONG
real_concept(unsigned long long c) : m_value(static_cast<long double>(c)){}
real_concept(long long c) : m_value(static_cast<long double>(c)){}
#elif defined(BOOST_HAS_MS_INT64)
real_concept(unsigned __int64 c) : m_value(static_cast<long double>(c)){}
real_concept(__int64 c) : m_value(static_cast<long double>(c)){}
#endif
real_concept(float c) : m_value(c){}
real_concept(double c) : m_value(c){}
real_concept(long double c) : m_value(c){}
// Assignment:
real_concept& operator=(char c) { m_value = c; return *this; }
real_concept& operator=(unsigned char c) { m_value = c; return *this; }
real_concept& operator=(signed char c) { m_value = c; return *this; }
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
real_concept& operator=(wchar_t c) { m_value = c; return *this; }
#endif
real_concept& operator=(short c) { m_value = c; return *this; }
real_concept& operator=(unsigned short c) { m_value = c; return *this; }
real_concept& operator=(int c) { m_value = c; return *this; }
real_concept& operator=(unsigned int c) { m_value = c; return *this; }
real_concept& operator=(long c) { m_value = c; return *this; }
real_concept& operator=(unsigned long c) { m_value = c; return *this; }
#ifdef BOOST_HAS_LONG_LONG
real_concept& operator=(long long c) { m_value = static_cast<long double>(c); return *this; }
real_concept& operator=(unsigned long long c) { m_value = static_cast<long double>(c); return *this; }
#endif
real_concept& operator=(float c) { m_value = c; return *this; }
real_concept& operator=(double c) { m_value = c; return *this; }
real_concept& operator=(long double c) { m_value = c; return *this; }
// Access:
long double value()const{ return m_value; }
// Member arithmetic:
real_concept& operator+=(const real_concept& other)
{ m_value += other.value(); return *this; }
real_concept& operator-=(const real_concept& other)
{ m_value -= other.value(); return *this; }
real_concept& operator*=(const real_concept& other)
{ m_value *= other.value(); return *this; }
real_concept& operator/=(const real_concept& other)
{ m_value /= other.value(); return *this; }
real_concept operator-()const
{ return -m_value; }
real_concept const& operator+()const
{ return *this; }
private:
long double m_value;
};
// Non-member arithmetic:
inline real_concept operator+(const real_concept& a, const real_concept& b)
{
real_concept result(a);
result += b;
return result;
}
inline real_concept operator-(const real_concept& a, const real_concept& b)
{
real_concept result(a);
result -= b;
return result;
}
inline real_concept operator*(const real_concept& a, const real_concept& b)
{
real_concept result(a);
result *= b;
return result;
}
inline real_concept operator/(const real_concept& a, const real_concept& b)
{
real_concept result(a);
result /= b;
return result;
}
// Comparison:
inline bool operator == (const real_concept& a, const real_concept& b)
{ return a.value() == b.value(); }
inline bool operator != (const real_concept& a, const real_concept& b)
{ return a.value() != b.value();}
inline bool operator < (const real_concept& a, const real_concept& b)
{ return a.value() < b.value(); }
inline bool operator <= (const real_concept& a, const real_concept& b)
{ return a.value() <= b.value(); }
inline bool operator > (const real_concept& a, const real_concept& b)
{ return a.value() > b.value(); }
inline bool operator >= (const real_concept& a, const real_concept& b)
{ return a.value() >= b.value(); }
#if 0
// Non-member mixed compare:
template <class T>
inline bool operator == (const T& a, const real_concept& b)
{
return a == b.value();
}
template <class T>
inline bool operator != (const T& a, const real_concept& b)
{
return a != b.value();
}
template <class T>
inline bool operator < (const T& a, const real_concept& b)
{
return a < b.value();
}
template <class T>
inline bool operator > (const T& a, const real_concept& b)
{
return a > b.value();
}
template <class T>
inline bool operator <= (const T& a, const real_concept& b)
{
return a <= b.value();
}
template <class T>
inline bool operator >= (const T& a, const real_concept& b)
{
return a >= b.value();
}
#endif // Non-member mixed compare:
// Non-member functions:
inline real_concept acos(real_concept a)
{ return std::acos(a.value()); }
inline real_concept cos(real_concept a)
{ return std::cos(a.value()); }
inline real_concept asin(real_concept a)
{ return std::asin(a.value()); }
inline real_concept atan(real_concept a)
{ return std::atan(a.value()); }
inline real_concept atan2(real_concept a, real_concept b)
{ return std::atan2(a.value(), b.value()); }
inline real_concept ceil(real_concept a)
{ return std::ceil(a.value()); }
inline real_concept fmod(real_concept a, real_concept b)
{ return boost::math::tools::fmod_workaround(a.value(), b.value()); }
inline real_concept cosh(real_concept a)
{ return std::cosh(a.value()); }
inline real_concept exp(real_concept a)
{ return std::exp(a.value()); }
inline real_concept fabs(real_concept a)
{ return std::fabs(a.value()); }
inline real_concept abs(real_concept a)
{ return std::abs(a.value()); }
inline real_concept floor(real_concept a)
{ return std::floor(a.value()); }
inline real_concept modf(real_concept a, real_concept* ipart)
{
long double ip;
long double result = std::modf(a.value(), &ip);
*ipart = ip;
return result;
}
inline real_concept frexp(real_concept a, int* expon)
{ return std::frexp(a.value(), expon); }
inline real_concept ldexp(real_concept a, int expon)
{ return std::ldexp(a.value(), expon); }
inline real_concept log(real_concept a)
{ return std::log(a.value()); }
inline real_concept log10(real_concept a)
{ return std::log10(a.value()); }
inline real_concept tan(real_concept a)
{ return std::tan(a.value()); }
inline real_concept pow(real_concept a, real_concept b)
{ return std::pow(a.value(), b.value()); }
inline real_concept pow(real_concept a, int b)
{ return std::pow(a.value(), b); }
inline real_concept sin(real_concept a)
{ return std::sin(a.value()); }
inline real_concept sinh(real_concept a)
{ return std::sinh(a.value()); }
inline real_concept sqrt(real_concept a)
{ return std::sqrt(a.value()); }
inline real_concept tanh(real_concept a)
{ return std::tanh(a.value()); }
// Streaming:
template <class charT, class traits>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const real_concept& a)
{
return os << a.value();
}
template <class charT, class traits>
inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, real_concept& a)
{
long double v;
is >> v;
a = v;
return is;
}
} // namespace concepts
namespace tools
{
// real_cast converts from T to integer and narrower floating-point types.
// Convert from T to integer types.
template <>
inline unsigned int real_cast<unsigned int, concepts::real_concept>(concepts::real_concept r)
{
return static_cast<unsigned int>(r.value());
}
template <>
inline int real_cast<int, concepts::real_concept>(concepts::real_concept r)
{
return static_cast<int>(r.value());
}
template <>
inline long real_cast<long, concepts::real_concept>(concepts::real_concept r)
{
return static_cast<long>(r.value());
}
// Converts from T to narrower floating-point types, float, double & long double.
template <>
inline float real_cast<float, concepts::real_concept>(concepts::real_concept r)
{
return static_cast<float>(r.value());
}
template <>
inline double real_cast<double, concepts::real_concept>(concepts::real_concept r)
{
return static_cast<double>(r.value());
}
template <>
inline long double real_cast<long double, concepts::real_concept>(concepts::real_concept r)
{
return r.value();
}
template <>
inline concepts::real_concept max_value<concepts::real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
return max_value<long double>();
}
template <>
inline concepts::real_concept min_value<concepts::real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
return min_value<long double>();
}
template <>
inline concepts::real_concept log_max_value<concepts::real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
return log_max_value<long double>();
}
template <>
inline concepts::real_concept log_min_value<concepts::real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
return log_min_value<long double>();
}
template <>
inline concepts::real_concept epsilon(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
return tools::epsilon<long double>();
}
template <>
inline int digits<concepts::real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
// Assume number of significand bits is same as long double,
// unless std::numeric_limits<T>::is_specialized to provide digits.
return tools::digits<long double>();
// Note that if numeric_limits real concept is NOT specialized to provide digits10
// (or max_digits10) then the default precision of 6 decimal digits will be used
// by Boost test (giving misleading error messages like
// "difference between {9.79796} and {9.79796} exceeds 5.42101e-19%"
// and by Boost lexical cast and serialization causing loss of accuracy.
}
} // namespace tools
} // namespace math
} // namespace boost
#endif // BOOST_MATH_REAL_CONCEPT_HPP

View File

@@ -0,0 +1,345 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// std_real_concept is an archetype for built-in Real types.
// The main purpose in providing this type is to verify
// that std lib functions are found via a using declaration
// bringing those functions into the current scope, and not
// just because they happen to be in global scope.
//
// If ::pow is found rather than std::pow say, then the code
// will silently compile, but truncation of long doubles to
// double will cause a significant loss of precision.
// A template instantiated with std_real_concept will *only*
// compile if it std::whatever is in scope.
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/math/tools/real_cast.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/policies/policy.hpp>
#include <ostream>
#include <istream>
#include <cmath>
#ifndef BOOST_MATH_STD_REAL_CONCEPT_HPP
#define BOOST_MATH_STD_REAL_CONCEPT_HPP
namespace boost{ namespace math{
namespace concepts
{
class std_real_concept
{
public:
// Constructors:
std_real_concept() : m_value(0){}
std_real_concept(char c) : m_value(c){}
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
std_real_concept(wchar_t c) : m_value(c){}
#endif
std_real_concept(unsigned char c) : m_value(c){}
std_real_concept(signed char c) : m_value(c){}
std_real_concept(unsigned short c) : m_value(c){}
std_real_concept(short c) : m_value(c){}
std_real_concept(unsigned int c) : m_value(c){}
std_real_concept(int c) : m_value(c){}
std_real_concept(unsigned long c) : m_value(c){}
std_real_concept(long c) : m_value(c){}
#ifdef BOOST_HAS_LONG_LONG
std_real_concept(unsigned long long c) : m_value(static_cast<long double>(c)){}
std_real_concept(long long c) : m_value(static_cast<long double>(c)){}
#endif
std_real_concept(float c) : m_value(c){}
std_real_concept(double c) : m_value(c){}
std_real_concept(long double c) : m_value(c){}
// Assignment:
std_real_concept& operator=(char c) { m_value = c; return *this; }
std_real_concept& operator=(unsigned char c) { m_value = c; return *this; }
std_real_concept& operator=(signed char c) { m_value = c; return *this; }
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
std_real_concept& operator=(wchar_t c) { m_value = c; return *this; }
#endif
std_real_concept& operator=(short c) { m_value = c; return *this; }
std_real_concept& operator=(unsigned short c) { m_value = c; return *this; }
std_real_concept& operator=(int c) { m_value = c; return *this; }
std_real_concept& operator=(unsigned int c) { m_value = c; return *this; }
std_real_concept& operator=(long c) { m_value = c; return *this; }
std_real_concept& operator=(unsigned long c) { m_value = c; return *this; }
#ifdef BOOST_HAS_LONG_LONG
std_real_concept& operator=(long long c) { m_value = static_cast<long double>(c); return *this; }
std_real_concept& operator=(unsigned long long c) { m_value = static_cast<long double>(c); return *this; }
#endif
std_real_concept& operator=(float c) { m_value = c; return *this; }
std_real_concept& operator=(double c) { m_value = c; return *this; }
std_real_concept& operator=(long double c) { m_value = c; return *this; }
// Access:
long double value()const{ return m_value; }
// Member arithmetic:
std_real_concept& operator+=(const std_real_concept& other)
{ m_value += other.value(); return *this; }
std_real_concept& operator-=(const std_real_concept& other)
{ m_value -= other.value(); return *this; }
std_real_concept& operator*=(const std_real_concept& other)
{ m_value *= other.value(); return *this; }
std_real_concept& operator/=(const std_real_concept& other)
{ m_value /= other.value(); return *this; }
std_real_concept operator-()const
{ return -m_value; }
std_real_concept const& operator+()const
{ return *this; }
private:
long double m_value;
};
// Non-member arithmetic:
inline std_real_concept operator+(const std_real_concept& a, const std_real_concept& b)
{
std_real_concept result(a);
result += b;
return result;
}
inline std_real_concept operator-(const std_real_concept& a, const std_real_concept& b)
{
std_real_concept result(a);
result -= b;
return result;
}
inline std_real_concept operator*(const std_real_concept& a, const std_real_concept& b)
{
std_real_concept result(a);
result *= b;
return result;
}
inline std_real_concept operator/(const std_real_concept& a, const std_real_concept& b)
{
std_real_concept result(a);
result /= b;
return result;
}
// Comparison:
inline bool operator == (const std_real_concept& a, const std_real_concept& b)
{ return a.value() == b.value(); }
inline bool operator != (const std_real_concept& a, const std_real_concept& b)
{ return a.value() != b.value();}
inline bool operator < (const std_real_concept& a, const std_real_concept& b)
{ return a.value() < b.value(); }
inline bool operator <= (const std_real_concept& a, const std_real_concept& b)
{ return a.value() <= b.value(); }
inline bool operator > (const std_real_concept& a, const std_real_concept& b)
{ return a.value() > b.value(); }
inline bool operator >= (const std_real_concept& a, const std_real_concept& b)
{ return a.value() >= b.value(); }
#if 0
// Non-member mixed compare:
template <class T>
inline bool operator == (const T& a, const std_real_concept& b)
{
return a == b.value();
}
template <class T>
inline bool operator != (const T& a, const std_real_concept& b)
{
return a != b.value();
}
template <class T>
inline bool operator < (const T& a, const std_real_concept& b)
{
return a < b.value();
}
template <class T>
inline bool operator > (const T& a, const std_real_concept& b)
{
return a > b.value();
}
template <class T>
inline bool operator <= (const T& a, const std_real_concept& b)
{
return a <= b.value();
}
template <class T>
inline bool operator >= (const T& a, const std_real_concept& b)
{
return a >= b.value();
}
#endif // Non-member mixed compare:
} // namespace concepts
} // namespace math
} // namespace boost
namespace std{
// Non-member functions:
inline boost::math::concepts::std_real_concept acos(boost::math::concepts::std_real_concept a)
{ return std::acos(a.value()); }
inline boost::math::concepts::std_real_concept cos(boost::math::concepts::std_real_concept a)
{ return std::cos(a.value()); }
inline boost::math::concepts::std_real_concept asin(boost::math::concepts::std_real_concept a)
{ return std::asin(a.value()); }
inline boost::math::concepts::std_real_concept atan(boost::math::concepts::std_real_concept a)
{ return std::atan(a.value()); }
inline boost::math::concepts::std_real_concept atan2(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
{ return std::atan2(a.value(), b.value()); }
inline boost::math::concepts::std_real_concept ceil(boost::math::concepts::std_real_concept a)
{ return std::ceil(a.value()); }
inline boost::math::concepts::std_real_concept fmod(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
{ return boost::math::tools::fmod_workaround(a.value(), b.value()); }
inline boost::math::concepts::std_real_concept cosh(boost::math::concepts::std_real_concept a)
{ return std::cosh(a.value()); }
inline boost::math::concepts::std_real_concept exp(boost::math::concepts::std_real_concept a)
{ return std::exp(a.value()); }
inline boost::math::concepts::std_real_concept fabs(boost::math::concepts::std_real_concept a)
{ return std::fabs(a.value()); }
inline boost::math::concepts::std_real_concept abs(boost::math::concepts::std_real_concept a)
{ return std::abs(a.value()); }
inline boost::math::concepts::std_real_concept floor(boost::math::concepts::std_real_concept a)
{ return std::floor(a.value()); }
inline boost::math::concepts::std_real_concept modf(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept* ipart)
{
long double ip;
long double result = std::modf(a.value(), &ip);
*ipart = ip;
return result;
}
inline boost::math::concepts::std_real_concept frexp(boost::math::concepts::std_real_concept a, int* expon)
{ return std::frexp(a.value(), expon); }
inline boost::math::concepts::std_real_concept ldexp(boost::math::concepts::std_real_concept a, int expon)
{ return std::ldexp(a.value(), expon); }
inline boost::math::concepts::std_real_concept log(boost::math::concepts::std_real_concept a)
{ return std::log(a.value()); }
inline boost::math::concepts::std_real_concept log10(boost::math::concepts::std_real_concept a)
{ return std::log10(a.value()); }
inline boost::math::concepts::std_real_concept tan(boost::math::concepts::std_real_concept a)
{ return std::tan(a.value()); }
inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
{ return std::pow(a.value(), b.value()); }
inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, int b)
{ return std::pow(a.value(), b); }
inline boost::math::concepts::std_real_concept sin(boost::math::concepts::std_real_concept a)
{ return std::sin(a.value()); }
inline boost::math::concepts::std_real_concept sinh(boost::math::concepts::std_real_concept a)
{ return std::sinh(a.value()); }
inline boost::math::concepts::std_real_concept sqrt(boost::math::concepts::std_real_concept a)
{ return std::sqrt(a.value()); }
inline boost::math::concepts::std_real_concept tanh(boost::math::concepts::std_real_concept a)
{ return std::tanh(a.value()); }
} // namespace std
namespace boost{ namespace math{ namespace concepts{
// Streaming:
template <class charT, class traits>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const std_real_concept& a)
{
return os << a.value();
}
template <class charT, class traits>
inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, std_real_concept& a)
{
long double v;
is >> v;
a = v;
return is;
}
} // namespace concepts
namespace tools
{
// real_cast converts from T to integer and narrower floating-point types.
// Convert from T to integer types.
template <>
inline unsigned int real_cast<unsigned int, concepts::std_real_concept>(concepts::std_real_concept r)
{
return static_cast<unsigned int>(r.value());
}
template <>
inline int real_cast<int, concepts::std_real_concept>(concepts::std_real_concept r)
{
return static_cast<int>(r.value());
}
template <>
inline long real_cast<long, concepts::std_real_concept>(concepts::std_real_concept r)
{
return static_cast<long>(r.value());
}
// Converts from T to narrower floating-point types, float, double & long double.
template <>
inline float real_cast<float, concepts::std_real_concept>(concepts::std_real_concept r)
{
return static_cast<float>(r.value());
}
template <>
inline double real_cast<double, concepts::std_real_concept>(concepts::std_real_concept r)
{
return static_cast<double>(r.value());
}
template <>
inline long double real_cast<long double, concepts::std_real_concept>(concepts::std_real_concept r)
{
return r.value();
}
template <>
inline concepts::std_real_concept max_value<concepts::std_real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return max_value<long double>();
}
template <>
inline concepts::std_real_concept min_value<concepts::std_real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return min_value<long double>();
}
template <>
inline concepts::std_real_concept log_max_value<concepts::std_real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return log_max_value<long double>();
}
template <>
inline concepts::std_real_concept log_min_value<concepts::std_real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return log_min_value<long double>();
}
template <>
inline concepts::std_real_concept epsilon(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return tools::epsilon<long double>();
}
template <>
inline int digits<concepts::std_real_concept>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{ // Assume number of significand bits is same as long double,
// unless std::numeric_limits<T>::is_specialized to provide digits.
return digits<long double>();
}
} // namespace tools
} // namespace math
} // namespace boost
#endif // BOOST_MATH_STD_REAL_CONCEPT_HPP

View File

@@ -0,0 +1,75 @@
// Copyright John Maddock 2005-2006.
// Copyright Paul A. Bristow 2006-7.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_CONSTANTS_CONSTANTS_INCLUDED
#define BOOST_MATH_CONSTANTS_CONSTANTS_INCLUDED
#include <boost/config.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4127 4701)
#endif
#include <boost/lexical_cast.hpp>
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
namespace boost{ namespace math
{
namespace constants
{
// To permit other calculations at about 100 decimal digits with NTL::RR type,
// it is obviously necessary to define constants to this accuracy.
// However, some compilers do not accept decimal digits strings as long as this.
// So the constant is split into two parts, with the 1st containing at least
// long double precision, and the 2nd zero if not needed or known.
// The 3rd part permits an exponent to be provided if necessary (use zero if none) -
// the other two parameters may only contain decimal digits (and sign and decimal point),
// and may NOT include an exponent like 1.234E99.
// The second digit string is only used if T is a User-Defined Type,
// when the constant is converted to a long string literal and lexical_casted to type T.
// (This is necessary because you can't use a numeric constant
// since even a long double might not have enough digits).
#define BOOST_DEFINE_MATH_CONSTANT(name, x, y, exp)\
template <class T> inline T name(BOOST_EXPLICIT_TEMPLATE_TYPE(T))\
{\
static const T result = ::boost::lexical_cast<T>(BOOST_STRINGIZE(BOOST_JOIN(BOOST_JOIN(x, y), BOOST_JOIN(e, exp))));\
return result;\
}\
template <> inline float name<float>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(float))\
{ return BOOST_JOIN(BOOST_JOIN(x, BOOST_JOIN(e, exp)), F); }\
template <> inline double name<double>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(double))\
{ return BOOST_JOIN(x, BOOST_JOIN(e, exp)); }\
template <> inline long double name<long double>(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))\
{ return BOOST_JOIN(BOOST_JOIN(x, BOOST_JOIN(e, exp)), L); }
BOOST_DEFINE_MATH_CONSTANT(pi, 3.141592653589793238462643383279502884197169399375105820974944, 59230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196, 0)
BOOST_DEFINE_MATH_CONSTANT(root_pi, 1.7724538509055160272981674833411451827975, 0, 0)
BOOST_DEFINE_MATH_CONSTANT(root_half_pi, 1.253314137315500251207882642405522626503, 0, 0)
BOOST_DEFINE_MATH_CONSTANT(root_two_pi, 2.506628274631000502415765284811045253007, 0, 0)
BOOST_DEFINE_MATH_CONSTANT(root_ln_four, 1.1774100225154746910115693264596996377473856893858205385225257565000, 2658854698492680841813836877081, 0)
BOOST_DEFINE_MATH_CONSTANT(e, 2.7182818284590452353602874713526624977572470936999595749669676, 27724076630353547594571382178525166427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880753195251019011, 0)
BOOST_DEFINE_MATH_CONSTANT(half, 0.5, 0, 0)
BOOST_DEFINE_MATH_CONSTANT(euler, 0.577215664901532860606512090082402431042159335939923598805, 76723488486, 0)
BOOST_DEFINE_MATH_CONSTANT(root_two, 1.414213562373095048801688724209698078569671875376948073, 17667973799073247846210703885038753432764157273501384623091229702492483605585073721264412149709993583141322266592750559275579995050115278206, 0)
BOOST_DEFINE_MATH_CONSTANT(ln_two, 0.693147180559945309417232121458176568075500134360255254, 120680009493393621969694715605863326996418687, 0)
BOOST_DEFINE_MATH_CONSTANT(ln_ln_two, -0.36651292058166432701243915823266946945426344783710526305367771367056, 16153193527385494558228566989083583025230453648347655663425171940646634, 0)
BOOST_DEFINE_MATH_CONSTANT(third, 0.3333333333333333333333333333333333333333333333333333333333333333333333, 3333333333333333333333333333333333333333333333333333333333333333333333333, 0)
BOOST_DEFINE_MATH_CONSTANT(twothirds, 0.66666666666666666666666666666666666666666666666666666666666666666666, 66666666666666666666666666666666666666666666666666666666666666666666667, 0)
BOOST_DEFINE_MATH_CONSTANT(pi_minus_three, 0.141592653589793238462643383279502884197169399375105820974944, 59230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196, 0)
BOOST_DEFINE_MATH_CONSTANT(four_minus_pi, 0.85840734641020676153735661672049711580283060062489417902505540769218359, 0, 0)
BOOST_DEFINE_MATH_CONSTANT(pow23_four_minus_pi, 0.79531676737159754434839533505680658072763917332771320544530223438582161, 0, 0)
BOOST_DEFINE_MATH_CONSTANT(exp_minus_half, 0.6065306597126334236037995349911804534419181354871869556828921587350565194137, 484239986476115079894560, 0)
} // namespace constants
} // namespace math
} // namespace boost
#endif // BOOST_MATH_CONSTANTS_CONSTANTS_INCLUDED

View File

@@ -0,0 +1,42 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2006, 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// This file includes *all* the distributions.
// this may be useful if many are used
// - to avoid including each distribution individually.
#ifndef BOOST_MATH_DISTRIBUTIONS_HPP
#define BOOST_MATH_DISTRIBUTIONS_HPP
#include <boost/math/distributions/bernoulli.hpp>
#include <boost/math/distributions/beta.hpp>
#include <boost/math/distributions/binomial.hpp>
#include <boost/math/distributions/cauchy.hpp>
#include <boost/math/distributions/chi_squared.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/exponential.hpp>
#include <boost/math/distributions/extreme_value.hpp>
#include <boost/math/distributions/fisher_f.hpp>
#include <boost/math/distributions/gamma.hpp>
#include <boost/math/distributions/lognormal.hpp>
#include <boost/math/distributions/negative_binomial.hpp>
#include <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/pareto.hpp>
#include <boost/math/distributions/poisson.hpp>
#include <boost/math/distributions/rayleigh.hpp>
#include <boost/math/distributions/students_t.hpp>
#include <boost/math/distributions/triangular.hpp>
#include <boost/math/distributions/uniform.hpp>
#include <boost/math/distributions/weibull.hpp>
// find location and shape for appropriate distributions,
// normal, cauchy, lognormal, symmetric triangular
// Disabled for now, these are still work in progress.
//#include <boost/math/distributions/find_scale.hpp>
//#include <boost/math/distributions/find_location.hpp>
#endif // BOOST_MATH_DISTRIBUTIONS_HPP

View File

@@ -0,0 +1,325 @@
// boost\math\distributions\bernoulli.hpp
// Copyright John Maddock 2006.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// http://en.wikipedia.org/wiki/bernoulli_distribution
// http://mathworld.wolfram.com/BernoulliDistribution.html
// bernoulli distribution is the discrete probability distribution of
// the number (k) of successes, in a single Bernoulli trials.
// It is a version of the binomial distribution when n = 1.
// But note that the bernoulli distribution
// (like others including the poisson, binomial & negative binomial)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as if a continous function,
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// on k outside this function to ensure that k is integral.
#ifndef BOOST_MATH_SPECIAL_BERNOULLI_HPP
#define BOOST_MATH_SPECIAL_BERNOULLI_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/tools/config.hpp>
#include <boost/math/distributions/complement.hpp> // complements
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
#include <boost/math/special_functions/fpclassify.hpp> // isnan.
#include <utility>
namespace boost
{
namespace math
{
namespace bernoulli_detail
{
// Common error checking routines for bernoulli distribution functions:
template <class RealType, class Policy>
inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& /* pol */)
{
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
{
*result = policies::raise_domain_error<RealType>(
function,
"Success fraction argument is %1%, but must be >= 0 and <= 1 !", p, Policy());
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_dist(const char* function, const RealType& p, RealType* result, const Policy& /* pol */)
{
return check_success_fraction(function, p, result, Policy());
}
template <class RealType, class Policy>
inline bool check_dist_and_k(const char* function, const RealType& p, RealType k, RealType* result, const Policy& pol)
{
if(check_dist(function, p, result, Policy()) == false)
{
return false;
}
if(!(boost::math::isfinite)(k) || !((k == 0) || (k == 1)))
{
*result = policies::raise_domain_error<RealType>(
function,
"Number of successes argument is %1%, but must be 0 or 1 !", k, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_dist_and_prob(const char* function, RealType p, RealType prob, RealType* result, const Policy& /* pol */)
{
if(check_dist(function, p, result, Policy()) && detail::check_probability(function, prob, result, Policy()) == false)
{
return false;
}
return true;
}
} // namespace bernoulli_detail
template <class RealType = double, class Policy = policies::policy<> >
class bernoulli_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
bernoulli_distribution(RealType p = 0.5) : m_p(p)
{ // Default probability = half suits 'fair' coin tossing
// where probability of heads == probability of tails.
RealType result; // of checks.
bernoulli_detail::check_dist(
"boost::math::bernoulli_distribution<%1%>::bernoulli_distribution",
m_p,
&result, Policy());
} // bernoulli_distribution constructor.
RealType success_fraction() const
{ // Probability.
return m_p;
}
private:
RealType m_p; // success_fraction
}; // template <class RealType> class bernoulli_distribution
typedef bernoulli_distribution<double> bernoulli;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const bernoulli_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable k = {0, 1}.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, 1);
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const bernoulli_distribution<RealType, Policy>& /* dist */)
{ // Range of supported values for random variable k = {0, 1}.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
return std::pair<RealType, RealType>(0, 1);
}
template <class RealType, class Policy>
inline RealType mean(const bernoulli_distribution<RealType, Policy>& dist)
{ // Mean of bernoulli distribution = p (n = 1).
return dist.success_fraction();
} // mean
// Rely on dereived_accessors quantile(half)
//template <class RealType>
//inline RealType median(const bernoulli_distribution<RealType, Policy>& dist)
//{ // Median of bernoulli distribution is not defined.
// return tools::domain_error<RealType>(BOOST_CURRENT_FUNCTION, "Median is not implemented, result is %1%!", std::numeric_limits<RealType>::quiet_NaN());
//} // median
template <class RealType, class Policy>
inline RealType variance(const bernoulli_distribution<RealType, Policy>& dist)
{ // Variance of bernoulli distribution =p * q.
return dist.success_fraction() * (1 - dist.success_fraction());
} // variance
template <class RealType, class Policy>
RealType pdf(const bernoulli_distribution<RealType, Policy>& dist, const RealType k)
{ // Probability Density/Mass Function.
BOOST_FPU_EXCEPTION_GUARD
// Error check:
RealType result; // of checks.
if(false == bernoulli_detail::check_dist_and_k(
"boost::math::pdf(bernoulli_distribution<%1%>, %1%)",
dist.success_fraction(), // 0 to 1
k, // 0 or 1
&result, Policy()))
{
return result;
}
// Assume k is integral.
if (k == 0)
{
return 1 - dist.success_fraction(); // 1 - p
}
else // k == 1
{
return dist.success_fraction(); // p
}
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const bernoulli_distribution<RealType, Policy>& dist, const RealType k)
{ // Cumulative Distribution Function Bernoulli.
RealType p = dist.success_fraction();
// Error check:
RealType result;
if(false == bernoulli_detail::check_dist_and_k(
"boost::math::cdf(bernoulli_distribution<%1%>, %1%)",
p,
k,
&result, Policy()))
{
return result;
}
if (k == 0)
{
return 1 - p;
}
else
{ // k == 1
return 1;
}
} // bernoulli cdf
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<bernoulli_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function bernoulli.
RealType const& k = c.param;
bernoulli_distribution<RealType, Policy> const& dist = c.dist;
RealType p = dist.success_fraction();
// Error checks:
RealType result;
if(false == bernoulli_detail::check_dist_and_k(
"boost::math::cdf(bernoulli_distribution<%1%>, %1%)",
p,
k,
&result, Policy()))
{
return result;
}
if (k == 0)
{
return p;
}
else
{ // k == 1
return 0;
}
} // bernoulli cdf complement
template <class RealType, class Policy>
inline RealType quantile(const bernoulli_distribution<RealType, Policy>& dist, const RealType& p)
{ // Quantile or Percent Point Bernoulli function.
// Return the number of expected successes k either 0 or 1.
// for a given probability p.
RealType result; // of error checks:
if(false == bernoulli_detail::check_dist_and_prob(
"boost::math::quantile(bernoulli_distribution<%1%>, %1%)",
dist.success_fraction(),
p,
&result, Policy()))
{
return result;
}
if (p <= (1 - dist.success_fraction()))
{ // p <= pdf(dist, 0) == cdf(dist, 0)
return 0;
}
else
{
return 1;
}
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<bernoulli_distribution<RealType, Policy>, RealType>& c)
{ // Quantile or Percent Point bernoulli function.
// Return the number of expected successes k for a given
// complement of the probability q.
//
// Error checks:
RealType q = c.param;
const bernoulli_distribution<RealType, Policy>& dist = c.dist;
RealType result;
if(false == bernoulli_detail::check_dist_and_prob(
"boost::math::quantile(bernoulli_distribution<%1%>, %1%)",
dist.success_fraction(),
q,
&result, Policy()))
{
return result;
}
if (q <= 1 - dist.success_fraction())
{ // // q <= cdf(complement(dist, 0)) == pdf(dist, 0)
return 1;
}
else
{
return 0;
}
} // quantile complemented.
template <class RealType, class Policy>
inline RealType mode(const bernoulli_distribution<RealType, Policy>& dist)
{
return static_cast<RealType>((dist.success_fraction() <= 0.5) ? 0 : 1); // p = 0.5 can be 0 or 1
}
template <class RealType, class Policy>
inline RealType skewness(const bernoulli_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING; // Aid ADL for sqrt.
RealType p = dist.success_fraction();
return (1 - 2 * p) / sqrt(p * (1 - p));
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const bernoulli_distribution<RealType, Policy>& dist)
{
RealType p = dist.success_fraction();
// Note Wolfram says this is kurtosis in text, but gamma2 is the kurtosis excess,
// and Wikipedia also says this is the kurtosis excess formula.
// return (6 * p * p - 6 * p + 1) / (p * (1 - p));
// But Wolfram kurtosis article gives this simpler formula for kurtosis excess:
return 1 / (1 - p) + 1/p -6;
}
template <class RealType, class Policy>
inline RealType kurtosis(const bernoulli_distribution<RealType, Policy>& dist)
{
RealType p = dist.success_fraction();
return 1 / (1 - p) + 1/p -6 + 3;
// Simpler than:
// return (6 * p * p - 6 * p + 1) / (p * (1 - p)) + 3;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_SPECIAL_BERNOULLI_HPP

View File

@@ -0,0 +1,544 @@
// boost\math\distributions\beta.hpp
// Copyright John Maddock 2006.
// Copyright Paul A. Bristow 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// http://en.wikipedia.org/wiki/Beta_distribution
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda366h.htm
// http://mathworld.wolfram.com/BetaDistribution.html
// The Beta Distribution is a continuous probability distribution.
// The beta distribution is used to model events which are constrained to take place
// within an interval defined by maxima and minima,
// so is used extensively in PERT and other project management systems
// to describe the time to completion.
// The cdf of the beta distribution is used as a convenient way
// of obtaining the sum over a set of binomial outcomes.
// The beta distribution is also used in Bayesian statistics.
#ifndef BOOST_MATH_DIST_BETA_HPP
#define BOOST_MATH_DIST_BETA_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/beta.hpp> // for beta.
#include <boost/math/distributions/complement.hpp> // complements.
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
#include <boost/math/special_functions/fpclassify.hpp> // isnan.
#include <boost/math/tools/roots.hpp> // for root finding.
#if defined (BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code
// in domain_error_imp in error_handling
#endif
#include <utility>
namespace boost
{
namespace math
{
namespace beta_detail
{
// Common error checking routines for beta distribution functions:
template <class RealType, class Policy>
inline bool check_alpha(const char* function, const RealType& alpha, RealType* result, const Policy& pol)
{
if(!(boost::math::isfinite)(alpha) || (alpha <= 0))
{
*result = policies::raise_domain_error<RealType>(
function,
"Alpha argument is %1%, but must be > 0 !", alpha, pol);
return false;
}
return true;
} // bool check_alpha
template <class RealType, class Policy>
inline bool check_beta(const char* function, const RealType& beta, RealType* result, const Policy& pol)
{
if(!(boost::math::isfinite)(beta) || (beta <= 0))
{
*result = policies::raise_domain_error<RealType>(
function,
"Beta argument is %1%, but must be > 0 !", beta, pol);
return false;
}
return true;
} // bool check_beta
template <class RealType, class Policy>
inline bool check_prob(const char* function, const RealType& p, RealType* result, const Policy& pol)
{
if((p < 0) || (p > 1) || !(boost::math::isfinite)(p))
{
*result = policies::raise_domain_error<RealType>(
function,
"Probability argument is %1%, but must be >= 0 and <= 1 !", p, pol);
return false;
}
return true;
} // bool check_prob
template <class RealType, class Policy>
inline bool check_x(const char* function, const RealType& x, RealType* result, const Policy& pol)
{
if(!(boost::math::isfinite)(x) || (x < 0) || (x > 1))
{
*result = policies::raise_domain_error<RealType>(
function,
"x argument is %1%, but must be >= 0 and <= 1 !", x, pol);
return false;
}
return true;
} // bool check_x
template <class RealType, class Policy>
inline bool check_dist(const char* function, const RealType& alpha, const RealType& beta, RealType* result, const Policy& pol)
{ // Check both alpha and beta.
return check_alpha(function, alpha, result, pol)
&& check_beta(function, beta, result, pol);
} // bool check_dist
template <class RealType, class Policy>
inline bool check_dist_and_x(const char* function, const RealType& alpha, const RealType& beta, RealType x, RealType* result, const Policy& pol)
{
return check_dist(function, alpha, beta, result, pol)
&& check_x(function, x, result, pol);
} // bool check_dist_and_x
template <class RealType, class Policy>
inline bool check_dist_and_prob(const char* function, const RealType& alpha, const RealType& beta, RealType p, RealType* result, const Policy& pol)
{
return check_dist(function, alpha, beta, result, pol)
&& check_prob(function, p, result, pol);
} // bool check_dist_and_prob
template <class RealType, class Policy>
inline bool check_mean(const char* function, const RealType& mean, RealType* result, const Policy& pol)
{
if(!(boost::math::isfinite)(mean) || (mean <= 0))
{
*result = policies::raise_domain_error<RealType>(
function,
"mean argument is %1%, but must be > 0 !", mean, pol);
return false;
}
return true;
} // bool check_mean
template <class RealType, class Policy>
inline bool check_variance(const char* function, const RealType& variance, RealType* result, const Policy& pol)
{
if(!(boost::math::isfinite)(variance) || (variance <= 0))
{
*result = policies::raise_domain_error<RealType>(
function,
"variance argument is %1%, but must be > 0 !", variance, pol);
return false;
}
return true;
} // bool check_variance
} // namespace beta_detail
// typedef beta_distribution<double> beta;
// is deliberately NOT included to avoid a name clash with the beta function.
// Use beta_distribution<> mybeta(...) to construct type double.
template <class RealType = double, class Policy = policies::policy<> >
class beta_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
beta_distribution(RealType alpha = 1, RealType beta = 1) : m_alpha(alpha), m_beta(beta)
{
RealType result;
beta_detail::check_dist(
"boost::math::beta_distribution<%1%>::beta_distribution",
m_alpha,
m_beta,
&result, Policy());
} // beta_distribution constructor.
// Accessor functions:
RealType alpha() const
{
return m_alpha;
}
RealType beta() const
{ // .
return m_beta;
}
// Estimation of the alpha & beta parameters.
// http://en.wikipedia.org/wiki/Beta_distribution
// gives formulae in section on parameter estimation.
// Also NIST EDA page 3 & 4 give the same.
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda366h.htm
// http://www.epi.ucdavis.edu/diagnostictests/betabuster.html
static RealType find_alpha(
RealType mean, // Expected value of mean.
RealType variance) // Expected value of variance.
{
static const char* function = "boost::math::beta_distribution<%1%>::find_alpha";
RealType result; // of error checks.
if(false ==
beta_detail::check_mean(
function, mean, &result, Policy())
&&
beta_detail::check_variance(
function, variance, &result, Policy())
)
{
return result;
}
return mean * (( (mean * (1 - mean)) / variance)- 1);
} // RealType find_alpha
static RealType find_beta(
RealType mean, // Expected value of mean.
RealType variance) // Expected value of variance.
{
static const char* function = "boost::math::beta_distribution<%1%>::find_beta";
RealType result; // of error checks.
if(false ==
beta_detail::check_mean(
function, mean, &result, Policy())
&&
beta_detail::check_variance(
function, variance, &result, Policy())
)
{
return result;
}
return (1 - mean) * (((mean * (1 - mean)) /variance)-1);
} // RealType find_beta
// Estimate alpha & beta from either alpha or beta, and x and probability.
// Uses for these parameter estimators are unclear.
static RealType find_alpha(
RealType beta, // from beta.
RealType x, // x.
RealType probability) // cdf
{
static const char* function = "boost::math::beta_distribution<%1%>::find_alpha";
RealType result; // of error checks.
if(false ==
beta_detail::check_prob(
function, probability, &result, Policy())
&&
beta_detail::check_beta(
function, beta, &result, Policy())
&&
beta_detail::check_x(
function, x, &result, Policy())
)
{
return result;
}
return ibeta_inva(beta, x, probability, Policy());
} // RealType find_alpha(beta, a, probability)
static RealType find_beta(
// ibeta_invb(T b, T x, T p); (alpha, x, cdf,)
RealType alpha, // alpha.
RealType x, // probability x.
RealType probability) // probability cdf.
{
static const char* function = "boost::math::beta_distribution<%1%>::find_beta";
RealType result; // of error checks.
if(false ==
beta_detail::check_prob(
function, probability, &result, Policy())
&&
beta_detail::check_alpha(
function, alpha, &result, Policy())
&&
beta_detail::check_x(
function, x, &result, Policy())
)
{
return result;
}
return ibeta_invb(alpha, x, probability, Policy());
} // RealType find_beta(alpha, x, probability)
private:
RealType m_alpha; // Two parameters of the beta distribution.
RealType m_beta;
}; // template <class RealType, class Policy> class beta_distribution
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const beta_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, 1);
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const beta_distribution<RealType, Policy>& /* dist */)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
return std::pair<RealType, RealType>(0, 1);
}
template <class RealType, class Policy>
inline RealType mean(const beta_distribution<RealType, Policy>& dist)
{ // Mean of beta distribution = np.
return dist.alpha() / (dist.alpha() + dist.beta());
} // mean
template <class RealType, class Policy>
inline RealType variance(const beta_distribution<RealType, Policy>& dist)
{ // Variance of beta distribution = np(1-p).
RealType a = dist.alpha();
RealType b = dist.beta();
return (a * b) / ((a + b ) * (a + b) * (a + b + 1));
} // variance
template <class RealType, class Policy>
inline RealType mode(const beta_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::mode(beta_distribution<%1%> const&)";
RealType result;
if ((dist.alpha() <= 1))
{
result = policies::raise_domain_error<RealType>(
function,
"mode undefined for alpha = %1%, must be > 1!", dist.alpha(), Policy());
return result;
}
if ((dist.beta() <= 1))
{
result = policies::raise_domain_error<RealType>(
function,
"mode undefined for beta = %1%, must be > 1!", dist.beta(), Policy());
return result;
}
RealType a = dist.alpha();
RealType b = dist.beta();
return (a-1) / (a + b - 2);
} // mode
//template <class RealType, class Policy>
//inline RealType median(const beta_distribution<RealType, Policy>& dist)
//{ // Median of beta distribution is not defined.
// return tools::domain_error<RealType>(function, "Median is not implemented, result is %1%!", std::numeric_limits<RealType>::quiet_NaN());
//} // median
//But WILL be provided by the derived accessor as quantile(0.5).
template <class RealType, class Policy>
inline RealType skewness(const beta_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // ADL of std functions.
RealType a = dist.alpha();
RealType b = dist.beta();
return (2 * (b-a) * sqrt(a + b + 1)) / ((a + b + 2) * sqrt(a * b));
} // skewness
template <class RealType, class Policy>
inline RealType kurtosis_excess(const beta_distribution<RealType, Policy>& dist)
{
RealType a = dist.alpha();
RealType b = dist.beta();
RealType a_2 = a * a;
RealType n = 6 * (a_2 * a - a_2 * (2 * b - 1) + b * b * (b + 1) - 2 * a * b * (b + 2));
RealType d = a * b * (a + b + 2) * (a + b + 3);
return n / d;
} // kurtosis_excess
template <class RealType, class Policy>
inline RealType kurtosis(const beta_distribution<RealType, Policy>& dist)
{
return 3 + kurtosis_excess(dist);
} // kurtosis
template <class RealType, class Policy>
inline RealType pdf(const beta_distribution<RealType, Policy>& dist, const RealType x)
{ // Probability Density/Mass Function.
BOOST_FPU_EXCEPTION_GUARD
static const char* function = "boost::math::pdf(beta_distribution<%1%> const&, %1%)";
BOOST_MATH_STD_USING // for ADL of std functions
RealType a = dist.alpha();
RealType b = dist.beta();
// Argument checks:
RealType result;
if(false == beta_detail::check_dist_and_x(
function,
a, b, x,
&result, Policy()))
{
return result;
}
using boost::math::beta;
return ibeta_derivative(a, b, x, Policy());
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const beta_distribution<RealType, Policy>& dist, const RealType x)
{ // Cumulative Distribution Function beta.
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(beta_distribution<%1%> const&, %1%)";
RealType a = dist.alpha();
RealType b = dist.beta();
// Argument checks:
RealType result;
if(false == beta_detail::check_dist_and_x(
function,
a, b, x,
&result, Policy()))
{
return result;
}
// Special cases:
if (x == 0)
{
return 0;
}
else if (x == 1)
{
return 1;
}
return ibeta(a, b, x, Policy());
} // beta cdf
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<beta_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function beta.
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(beta_distribution<%1%> const&, %1%)";
RealType const& x = c.param;
beta_distribution<RealType, Policy> const& dist = c.dist;
RealType a = dist.alpha();
RealType b = dist.beta();
// Argument checks:
RealType result;
if(false == beta_detail::check_dist_and_x(
function,
a, b, x,
&result, Policy()))
{
return result;
}
if (x == 0)
{
return 1;
}
else if (x == 1)
{
return 0;
}
// Calculate cdf beta using the incomplete beta function.
// Use of ibeta here prevents cancellation errors in calculating
// 1 - x if x is very small, perhaps smaller than machine epsilon.
return ibetac(a, b, x, Policy());
} // beta cdf
template <class RealType, class Policy>
inline RealType quantile(const beta_distribution<RealType, Policy>& dist, const RealType& p)
{ // Quantile or Percent Point beta function or
// Inverse Cumulative probability distribution function CDF.
// Return x (0 <= x <= 1),
// for a given probability p (0 <= p <= 1).
// These functions take a probability as an argument
// and return a value such that the probability that a random variable x
// will be less than or equal to that value
// is whatever probability you supplied as an argument.
static const char* function = "boost::math::quantile(beta_distribution<%1%> const&, %1%)";
RealType result; // of argument checks:
RealType a = dist.alpha();
RealType b = dist.beta();
if(false == beta_detail::check_dist_and_prob(
function,
a, b, p,
&result, Policy()))
{
return result;
}
// Special cases:
if (p == 0)
{
return 0;
}
if (p == 1)
{
return 1;
}
return ibeta_inv(a, b, p, static_cast<RealType*>(0), Policy());
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<beta_distribution<RealType, Policy>, RealType>& c)
{ // Complement Quantile or Percent Point beta function .
// Return the number of expected x for a given
// complement of the probability q.
static const char* function = "boost::math::quantile(beta_distribution<%1%> const&, %1%)";
//
// Error checks:
RealType q = c.param;
const beta_distribution<RealType, Policy>& dist = c.dist;
RealType result;
RealType a = dist.alpha();
RealType b = dist.beta();
if(false == beta_detail::check_dist_and_prob(
function,
a,
b,
q,
&result, Policy()))
{
return result;
}
// Special cases:
if(q == 1)
{
return 0;
}
if(q == 0)
{
return 1;
}
return ibetac_inv(a, b, q, static_cast<RealType*>(0), Policy());
} // Quantile Complement
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#if defined (BOOST_MSVC)
# pragma warning(pop)
#endif
#endif // BOOST_MATH_DIST_BETA_HPP

View File

@@ -0,0 +1,724 @@
// boost\math\distributions\binomial.hpp
// Copyright John Maddock 2006.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// http://en.wikipedia.org/wiki/binomial_distribution
// Binomial distribution is the discrete probability distribution of
// the number (k) of successes, in a sequence of
// n independent (yes or no, success or failure) Bernoulli trials.
// It expresses the probability of a number of events occurring in a fixed time
// if these events occur with a known average rate (probability of success),
// and are independent of the time since the last event.
// The number of cars that pass through a certain point on a road during a given period of time.
// The number of spelling mistakes a secretary makes while typing a single page.
// The number of phone calls at a call center per minute.
// The number of times a web server is accessed per minute.
// The number of light bulbs that burn out in a certain amount of time.
// The number of roadkill found per unit length of road
// http:/en.wikipedia.org/wiki/binomial_distribution
// Given a sample of N measured values k[i],
// we wish to estimate the value of the parameter x (mean)
// of the binomial population from which the sample was drawn.
// To calculate the maximum likelihood value = 1/N sum i = 1 to N of k[i]
// Also may want a function for EXACTLY k.
// And probability that there are EXACTLY k occurrences is
// exp(-x) * pow(x, k) / factorial(k)
// where x is expected occurrences (mean) during the given interval.
// For example, if events occur, on average, every 4 min,
// and we are interested in number of events occurring in 10 min,
// then x = 10/4 = 2.5
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda366i.htm
// The binomial distribution is used when there are
// exactly two mutually exclusive outcomes of a trial.
// These outcomes are appropriately labeled "success" and "failure".
// The binomial distribution is used to obtain
// the probability of observing x successes in N trials,
// with the probability of success on a single trial denoted by p.
// The binomial distribution assumes that p is fixed for all trials.
// P(x, p, n) = n!/(x! * (n-x)!) * p^x * (1-p)^(n-x)
// http://mathworld.wolfram.com/BinomialCoefficient.html
// The binomial coefficient (n; k) is the number of ways of picking
// k unordered outcomes from n possibilities,
// also known as a combination or combinatorial number.
// The symbols _nC_k and (n; k) are used to denote a binomial coefficient,
// and are sometimes read as "n choose k."
// (n; k) therefore gives the number of k-subsets possible out of a set of n distinct items.
// For example:
// The 2-subsets of {1,2,3,4} are the six pairs {1,2}, {1,3}, {1,4}, {2,3}, {2,4}, and {3,4}, so (4; 2)==6.
// http://functions.wolfram.com/GammaBetaErf/Binomial/ for evaluation.
// But note that the binomial distribution
// (like others including the poisson, negative binomial & Bernoulli)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as if a continous function,
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// on k outside this function to ensure that k is integral.
#ifndef BOOST_MATH_SPECIAL_BINOMIAL_HPP
#define BOOST_MATH_SPECIAL_BINOMIAL_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/beta.hpp> // for incomplete beta.
#include <boost/math/distributions/complement.hpp> // complements
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
#include <boost/math/distributions/detail/inv_discrete_quantile.hpp> // error checks
#include <boost/math/special_functions/fpclassify.hpp> // isnan.
#include <boost/math/tools/roots.hpp> // for root finding.
#include <utility>
namespace boost
{
namespace math
{
template <class RealType, class Policy>
class binomial_distribution;
namespace binomial_detail{
// common error checking routines for binomial distribution functions:
template <class RealType, class Policy>
inline bool check_N(const char* function, const RealType& N, RealType* result, const Policy& pol)
{
if((N < 0) || !(boost::math::isfinite)(N))
{
*result = policies::raise_domain_error<RealType>(
function,
"Number of Trials argument is %1%, but must be >= 0 !", N, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& pol)
{
if((p < 0) || (p > 1) || !(boost::math::isfinite)(p))
{
*result = policies::raise_domain_error<RealType>(
function,
"Success fraction argument is %1%, but must be >= 0 and <= 1 !", p, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_dist(const char* function, const RealType& N, const RealType& p, RealType* result, const Policy& pol)
{
return check_success_fraction(
function, p, result, pol)
&& check_N(
function, N, result, pol);
}
template <class RealType, class Policy>
inline bool check_dist_and_k(const char* function, const RealType& N, const RealType& p, RealType k, RealType* result, const Policy& pol)
{
if(check_dist(function, N, p, result, pol) == false)
return false;
if((k < 0) || !(boost::math::isfinite)(k))
{
*result = policies::raise_domain_error<RealType>(
function,
"Number of Successes argument is %1%, but must be >= 0 !", k, pol);
return false;
}
if(k > N)
{
*result = policies::raise_domain_error<RealType>(
function,
"Number of Successes argument is %1%, but must be <= Number of Trials !", k, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_dist_and_prob(const char* function, const RealType& N, RealType p, RealType prob, RealType* result, const Policy& pol)
{
if(check_dist(function, N, p, result, pol) && detail::check_probability(function, prob, result, pol) == false)
return false;
return true;
}
template <class T, class Policy>
T inverse_binomial_cornish_fisher(T n, T sf, T p, T q, const Policy& pol)
{
BOOST_MATH_STD_USING
// mean:
T m = n * sf;
// standard deviation:
T sigma = sqrt(n * sf * (1 - sf));
// skewness
T sk = (1 - 2 * sf) / sigma;
// kurtosis:
// T k = (1 - 6 * sf * (1 - sf) ) / (n * sf * (1 - sf));
// Get the inverse of a std normal distribution:
T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two<T>();
// Set the sign:
if(p < 0.5)
x = -x;
T x2 = x * x;
// w is correction term due to skewness
T w = x + sk * (x2 - 1) / 6;
/*
// Add on correction due to kurtosis.
// Disabled for now, seems to make things worse?
//
if(n >= 10)
w += k * x * (x2 - 3) / 24 + sk * sk * x * (2 * x2 - 5) / -36;
*/
w = m + sigma * w;
if(w < tools::min_value<T>())
return sqrt(tools::min_value<T>());
if(w > n)
return n;
return w;
}
template <class RealType, class Policy>
RealType quantile_imp(const binomial_distribution<RealType, Policy>& dist, const RealType& p, const RealType& q)
{ // Quantile or Percent Point Binomial function.
// Return the number of expected successes k,
// for a given probability p.
//
// Error checks:
BOOST_MATH_STD_USING // ADL of std names
RealType result;
RealType trials = dist.trials();
RealType success_fraction = dist.success_fraction();
if(false == binomial_detail::check_dist_and_prob(
"boost::math::quantile(binomial_distribution<%1%> const&, %1%)",
trials,
success_fraction,
p,
&result, Policy()))
{
return result;
}
// Special cases:
//
if(p == 0)
{ // There may actually be no answer to this question,
// since the probability of zero successes may be non-zero,
// but zero is the best we can do:
return 0;
}
if(p == 1)
{ // Probability of n or fewer successes is always one,
// so n is the most sensible answer here:
return trials;
}
if (p <= pow(1 - success_fraction, trials))
{ // p <= pdf(dist, 0) == cdf(dist, 0)
return 0; // So the only reasonable result is zero.
} // And root finder would fail otherwise.
// Solve for quantile numerically:
//
RealType guess = binomial_detail::inverse_binomial_cornish_fisher(trials, success_fraction, p, q, Policy());
RealType factor = 8;
if(trials > 100)
factor = 1.01f; // guess is pretty accurate
else if((trials > 10) && (trials - 1 > guess) && (guess > 3))
factor = 1.15f; // less accurate but OK.
else if(trials < 10)
{
// pretty inaccurate guess in this area:
if(guess > trials / 64)
{
guess = trials / 4;
factor = 2;
}
else
guess = trials / 1024;
}
else
factor = 2; // trials largish, but in far tails.
typedef typename Policy::discrete_quantile_type discrete_quantile_type;
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
return detail::inverse_discrete_quantile(
dist,
p,
q,
guess,
factor,
RealType(1),
discrete_quantile_type(),
max_iter);
} // quantile
}
template <class RealType = double, class Policy = policies::policy<> >
class binomial_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
binomial_distribution(RealType n = 1, RealType p = 0.5) : m_n(n), m_p(p)
{ // Default n = 1 is the Bernoulli distribution
// with equal probability of 'heads' or 'tails.
RealType r;
binomial_detail::check_dist(
"boost::math::binomial_distribution<%1%>::binomial_distribution",
m_n,
m_p,
&r, Policy());
} // binomial_distribution constructor.
RealType success_fraction() const
{ // Probability.
return m_p;
}
RealType trials() const
{ // Total number of trials.
return m_n;
}
enum interval_type{
clopper_pearson_exact_interval,
jeffreys_prior_interval
};
//
// Estimation of the success fraction parameter.
// The best estimate is actually simply successes/trials,
// these functions are used
// to obtain confidence intervals for the success fraction.
//
static RealType find_lower_bound_on_p(
RealType trials,
RealType successes,
RealType probability,
interval_type t = clopper_pearson_exact_interval)
{
static const char* function = "boost::math::binomial_distribution<%1%>::find_lower_bound_on_p";
// Error checks:
RealType result;
if(false == binomial_detail::check_dist_and_k(
function, trials, RealType(0), successes, &result, Policy())
&&
binomial_detail::check_dist_and_prob(
function, trials, RealType(0), probability, &result, Policy()))
{ return result; }
if(successes == 0)
return 0;
// NOTE!!! The Clopper Pearson formula uses "successes" not
// "successes+1" as usual to get the lower bound,
// see http://www.itl.nist.gov/div898/handbook/prc/section2/prc241.htm
return (t == clopper_pearson_exact_interval) ? ibeta_inv(successes, trials - successes + 1, probability, static_cast<RealType*>(0), Policy())
: ibeta_inv(successes + 0.5f, trials - successes + 0.5f, probability, static_cast<RealType*>(0), Policy());
}
static RealType find_upper_bound_on_p(
RealType trials,
RealType successes,
RealType probability,
interval_type t = clopper_pearson_exact_interval)
{
static const char* function = "boost::math::binomial_distribution<%1%>::find_upper_bound_on_p";
// Error checks:
RealType result;
if(false == binomial_detail::check_dist_and_k(
function, trials, RealType(0), successes, &result, Policy())
&&
binomial_detail::check_dist_and_prob(
function, trials, RealType(0), probability, &result, Policy()))
{ return result; }
if(trials == successes)
return 1;
return (t == clopper_pearson_exact_interval) ? ibetac_inv(successes + 1, trials - successes, probability, static_cast<RealType*>(0), Policy())
: ibetac_inv(successes + 0.5f, trials - successes + 0.5f, probability, static_cast<RealType*>(0), Policy());
}
// Estimate number of trials parameter:
//
// "How many trials do I need to be P% sure of seeing k events?"
// or
// "How many trials can I have to be P% sure of seeing fewer than k events?"
//
static RealType find_minimum_number_of_trials(
RealType k, // number of events
RealType p, // success fraction
RealType alpha) // risk level
{
static const char* function = "boost::math::binomial_distribution<%1%>::find_minimum_number_of_trials";
// Error checks:
RealType result;
if(false == binomial_detail::check_dist_and_k(
function, k, p, k, &result, Policy())
&&
binomial_detail::check_dist_and_prob(
function, k, p, alpha, &result, Policy()))
{ return result; }
result = ibetac_invb(k + 1, p, alpha, Policy()); // returns n - k
return result + k;
}
static RealType find_maximum_number_of_trials(
RealType k, // number of events
RealType p, // success fraction
RealType alpha) // risk level
{
static const char* function = "boost::math::binomial_distribution<%1%>::find_maximum_number_of_trials";
// Error checks:
RealType result;
if(false == binomial_detail::check_dist_and_k(
function, k, p, k, &result, Policy())
&&
binomial_detail::check_dist_and_prob(
function, k, p, alpha, &result, Policy()))
{ return result; }
result = ibeta_invb(k + 1, p, alpha, Policy()); // returns n - k
return result + k;
}
private:
RealType m_n; // Not sure if this shouldn't be an int?
RealType m_p; // success_fraction
}; // template <class RealType, class Policy> class binomial_distribution
typedef binomial_distribution<> binomial;
// typedef binomial_distribution<double> binomial;
// IS now included since no longer a name clash with function binomial.
//typedef binomial_distribution<double> binomial; // Reserved name of type double.
template <class RealType, class Policy>
const std::pair<RealType, RealType> range(const binomial_distribution<RealType, Policy>& dist)
{ // Range of permissible values for random variable k.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(static_cast<RealType>(0), dist.trials());
}
template <class RealType, class Policy>
const std::pair<RealType, RealType> support(const binomial_distribution<RealType, Policy>& dist)
{ // Range of supported values for random variable k.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
return std::pair<RealType, RealType>(0, dist.trials());
}
template <class RealType, class Policy>
inline RealType mean(const binomial_distribution<RealType, Policy>& dist)
{ // Mean of Binomial distribution = np.
return dist.trials() * dist.success_fraction();
} // mean
template <class RealType, class Policy>
inline RealType variance(const binomial_distribution<RealType, Policy>& dist)
{ // Variance of Binomial distribution = np(1-p).
return dist.trials() * dist.success_fraction() * (1 - dist.success_fraction());
} // variance
template <class RealType, class Policy>
RealType pdf(const binomial_distribution<RealType, Policy>& dist, const RealType k)
{ // Probability Density/Mass Function.
BOOST_FPU_EXCEPTION_GUARD
BOOST_MATH_STD_USING // for ADL of std functions
RealType n = dist.trials();
// Error check:
RealType result;
if(false == binomial_detail::check_dist_and_k(
"boost::math::pdf(binomial_distribution<%1%> const&, %1%)",
n,
dist.success_fraction(),
k,
&result, Policy()))
{
return result;
}
// Special cases of success_fraction, regardless of k successes and regardless of n trials.
if (dist.success_fraction() == 0)
{ // probability of zero successes is 1:
return static_cast<RealType>(k == 0 ? 1 : 0);
}
if (dist.success_fraction() == 1)
{ // probability of n successes is 1:
return static_cast<RealType>(k == n ? 1 : 0);
}
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
if (n == 0)
{
return 1; // Probability = 1 = certainty.
}
if (k == 0)
{ // binomial coeffic (n 0) = 1,
// n ^ 0 = 1
return pow(1 - dist.success_fraction(), n);
}
if (k == n)
{ // binomial coeffic (n n) = 1,
// n ^ 0 = 1
return pow(dist.success_fraction(), k); // * pow((1 - dist.success_fraction()), (n - k)) = 1
}
// Probability of getting exactly k successes
// if C(n, k) is the binomial coefficient then:
//
// f(k; n,p) = C(n, k) * p^k * (1-p)^(n-k)
// = (n!/(k!(n-k)!)) * p^k * (1-p)^(n-k)
// = (tgamma(n+1) / (tgamma(k+1)*tgamma(n-k+1))) * p^k * (1-p)^(n-k)
// = p^k (1-p)^(n-k) / (beta(k+1, n-k+1) * (n+1))
// = ibeta_derivative(k+1, n-k+1, p) / (n+1)
//
using boost::math::ibeta_derivative; // a, b, x
return ibeta_derivative(k+1, n-k+1, dist.success_fraction(), Policy()) / (n+1);
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const binomial_distribution<RealType, Policy>& dist, const RealType k)
{ // Cumulative Distribution Function Binomial.
// The random variate k is the number of successes in n trials.
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
// Returns the sum of the terms 0 through k of the Binomial Probability Density/Mass:
//
// i=k
// -- ( n ) i n-i
// > | | p (1-p)
// -- ( i )
// i=0
// The terms are not summed directly instead
// the incomplete beta integral is employed,
// according to the formula:
// P = I[1-p]( n-k, k+1).
// = 1 - I[p](k + 1, n - k)
BOOST_MATH_STD_USING // for ADL of std functions
RealType n = dist.trials();
RealType p = dist.success_fraction();
// Error check:
RealType result;
if(false == binomial_detail::check_dist_and_k(
"boost::math::cdf(binomial_distribution<%1%> const&, %1%)",
n,
p,
k,
&result, Policy()))
{
return result;
}
if (k == n)
{
return 1;
}
// Special cases, regardless of k.
if (p == 0)
{ // This need explanation:
// the pdf is zero for all cases except when k == 0.
// For zero p the probability of zero successes is one.
// Therefore the cdf is always 1:
// the probability of k or *fewer* successes is always 1
// if there are never any successes!
return 1;
}
if (p == 1)
{ // This is correct but needs explanation:
// when k = 1
// all the cdf and pdf values are zero *except* when k == n,
// and that case has been handled above already.
return 0;
}
//
// P = I[1-p](n - k, k + 1)
// = 1 - I[p](k + 1, n - k)
// Use of ibetac here prevents cancellation errors in calculating
// 1-p if p is very small, perhaps smaller than machine epsilon.
//
// Note that we do not use a finite sum here, since the incomplete
// beta uses a finite sum internally for integer arguments, so
// we'll just let it take care of the necessary logic.
//
return ibetac(k + 1, n - k, p, Policy());
} // binomial cdf
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<binomial_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function Binomial.
// The random variate k is the number of successes in n trials.
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
// Returns the sum of the terms k+1 through n of the Binomial Probability Density/Mass:
//
// i=n
// -- ( n ) i n-i
// > | | p (1-p)
// -- ( i )
// i=k+1
// The terms are not summed directly instead
// the incomplete beta integral is employed,
// according to the formula:
// Q = 1 -I[1-p]( n-k, k+1).
// = I[p](k + 1, n - k)
BOOST_MATH_STD_USING // for ADL of std functions
RealType const& k = c.param;
binomial_distribution<RealType, Policy> const& dist = c.dist;
RealType n = dist.trials();
RealType p = dist.success_fraction();
// Error checks:
RealType result;
if(false == binomial_detail::check_dist_and_k(
"boost::math::cdf(binomial_distribution<%1%> const&, %1%)",
n,
p,
k,
&result, Policy()))
{
return result;
}
if (k == n)
{ // Probability of greater than n successes is necessarily zero:
return 0;
}
// Special cases, regardless of k.
if (p == 0)
{
// This need explanation: the pdf is zero for all
// cases except when k == 0. For zero p the probability
// of zero successes is one. Therefore the cdf is always
// 1: the probability of *more than* k successes is always 0
// if there are never any successes!
return 0;
}
if (p == 1)
{
// This needs explanation, when p = 1
// we always have n successes, so the probability
// of more than k successes is 1 as long as k < n.
// The k == n case has already been handled above.
return 1;
}
//
// Calculate cdf binomial using the incomplete beta function.
// Q = 1 -I[1-p](n - k, k + 1)
// = I[p](k + 1, n - k)
// Use of ibeta here prevents cancellation errors in calculating
// 1-p if p is very small, perhaps smaller than machine epsilon.
//
// Note that we do not use a finite sum here, since the incomplete
// beta uses a finite sum internally for integer arguments, so
// we'll just let it take care of the necessary logic.
//
return ibeta(k + 1, n - k, p, Policy());
} // binomial cdf
template <class RealType, class Policy>
inline RealType quantile(const binomial_distribution<RealType, Policy>& dist, const RealType& p)
{
return binomial_detail::quantile_imp(dist, p, 1-p);
} // quantile
template <class RealType, class Policy>
RealType quantile(const complemented2_type<binomial_distribution<RealType, Policy>, RealType>& c)
{
return binomial_detail::quantile_imp(c.dist, 1-c.param, c.param);
} // quantile
template <class RealType, class Policy>
inline RealType mode(const binomial_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // ADL of std functions.
RealType p = dist.success_fraction();
RealType n = dist.trials();
return floor(p * (n + 1));
}
template <class RealType, class Policy>
inline RealType median(const binomial_distribution<RealType, Policy>& dist)
{ // Bounds for the median of the negative binomial distribution
// VAN DE VEN R. ; WEBER N. C. ;
// Univ. Sydney, school mathematics statistics, Sydney N.S.W. 2006, AUSTRALIE
// Metrika (Metrika) ISSN 0026-1335 CODEN MTRKA8
// 1993, vol. 40, no3-4, pp. 185-189 (4 ref.)
// Bounds for median and 50 percetage point of binomial and negative binomial distribution
// Metrika, ISSN 0026-1335 (Print) 1435-926X (Online)
// Volume 41, Number 1 / December, 1994, DOI 10.1007/BF01895303
BOOST_MATH_STD_USING // ADL of std functions.
RealType p = dist.success_fraction();
RealType n = dist.trials();
// Wikipedia says one of floor(np) -1, floor (np), floor(np) +1
return floor(p * n); // Chose the middle value.
}
template <class RealType, class Policy>
inline RealType skewness(const binomial_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // ADL of std functions.
RealType p = dist.success_fraction();
RealType n = dist.trials();
return (1 - 2 * p) / sqrt(n * p * (1 - p));
}
template <class RealType, class Policy>
inline RealType kurtosis(const binomial_distribution<RealType, Policy>& dist)
{
RealType p = dist.success_fraction();
RealType n = dist.trials();
return 3 - 6 / n + 1 / (n * p * (1 - p));
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const binomial_distribution<RealType, Policy>& dist)
{
RealType p = dist.success_fraction();
RealType q = 1 - p;
RealType n = dist.trials();
return (1 - 6 * p * q) / (n * p * q);
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_SPECIAL_BINOMIAL_HPP

View File

@@ -0,0 +1,347 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_CAUCHY_HPP
#define BOOST_STATS_CAUCHY_HPP
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#endif
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <cmath>
#include <utility>
namespace boost{ namespace math
{
template <class RealType, class Policy>
class cauchy_distribution;
namespace detail
{
template <class RealType, class Policy>
RealType cdf_imp(const cauchy_distribution<RealType, Policy>& dist, const RealType& x, bool complement)
{
//
// This calculates the cdf of the Cauchy distribution and/or its complement.
//
// The usual formula for the Cauchy cdf is:
//
// cdf = 0.5 + atan(x)/pi
//
// But that suffers from cancellation error as x -> -INF.
//
// Recall that for x < 0:
//
// atan(x) = -pi/2 - atan(1/x)
//
// Substituting into the above we get:
//
// CDF = -atan(1/x) ; x < 0
//
// So the proceedure is to calculate the cdf for -fabs(x)
// using the above formula, and then subtract from 1 when required
// to get the result.
//
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(cauchy<%1%>&, %1%)";
RealType result;
RealType location = dist.location();
RealType scale = dist.scale();
if(false == detail::check_location(function, location, &result, Policy()))
{
return result;
}
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(std::numeric_limits<RealType>::has_infinity && x == std::numeric_limits<RealType>::infinity())
{ // cdf +infinity is unity.
return static_cast<RealType>((complement) ? 0 : 1);
}
if(std::numeric_limits<RealType>::has_infinity && x == -std::numeric_limits<RealType>::infinity())
{ // cdf -infinity is zero.
return static_cast<RealType>((complement) ? 1 : 0);
}
if(false == detail::check_x(function, x, &result, Policy()))
{ // Catches x == NaN
return result;
}
RealType mx = -fabs((x - location) / scale); // scale is > 0
if(mx > -tools::epsilon<RealType>() / 8)
{ // special case first: x extremely close to location.
return 0.5;
}
result = -atan(1 / mx) / constants::pi<RealType>();
return (((x > location) != complement) ? 1 - result : result);
} // cdf
template <class RealType, class Policy>
RealType quantile_imp(
const cauchy_distribution<RealType, Policy>& dist,
const RealType& p,
bool complement)
{
// This routine implements the quantile for the Cauchy distribution,
// the value p may be the probability, or its complement if complement=true.
//
// The procedure first performs argument reduction on p to avoid error
// when calculating the tangent, then calulates the distance from the
// mid-point of the distribution. This is either added or subtracted
// from the location parameter depending on whether `complement` is true.
//
static const char* function = "boost::math::quantile(cauchy<%1%>&, %1%)";
BOOST_MATH_STD_USING // for ADL of std functions
RealType result;
RealType location = dist.location();
RealType scale = dist.scale();
if(false == detail::check_location(function, location, &result, Policy()))
{
return result;
}
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_probability(function, p, &result, Policy()))
{
return result;
}
// Special cases:
if(p == 1)
{
return (complement ? -1 : 1) * policies::raise_overflow_error<RealType>(function, 0, Policy());
}
if(p == 0)
{
return (complement ? 1 : -1) * policies::raise_overflow_error<RealType>(function, 0, Policy());
}
RealType P = p - floor(p); // argument reduction of p:
if(P > 0.5)
{
P = P - 1;
}
if(P == 0.5) // special case:
{
return location;
}
result = -scale / tan(constants::pi<RealType>() * P);
return complement ? location - result : location + result;
} // quantile
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class cauchy_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
cauchy_distribution(RealType location = 0, RealType scale = 1)
: m_a(location), m_hg(scale)
{
static const char* function = "boost::math::cauchy_distribution<%1%>::cauchy_distribution";
RealType result;
detail::check_location(function, location, &result, Policy());
detail::check_scale(function, scale, &result, Policy());
} // cauchy_distribution
RealType location()const
{
return m_a;
}
RealType scale()const
{
return m_hg;
}
private:
RealType m_a; // The location, this is the median of the distribution.
RealType m_hg; // The scale )or shape), this is the half width at half height.
};
typedef cauchy_distribution<double> cauchy;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const cauchy_distribution<RealType, Policy>&)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + infinity.
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const cauchy_distribution<RealType, Policy>& )
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
return std::pair<RealType, RealType>(-tools::max_value<RealType>(), tools::max_value<RealType>()); // - to + infinity.
}
template <class RealType, class Policy>
inline RealType pdf(const cauchy_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::pdf(cauchy<%1%>&, %1%)";
RealType result;
RealType location = dist.location();
RealType scale = dist.scale();
if(false == detail::check_scale("boost::math::pdf(cauchy<%1%>&, %1%)", scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location("boost::math::pdf(cauchy<%1%>&, %1%)", location, &result, Policy()))
{
return result;
}
if((boost::math::isinf)(x))
{
return 0; // pdf + and - infinity is zero.
}
// These produce MSVC 4127 warnings, so the above used instead.
//if(std::numeric_limits<RealType>::has_infinity && abs(x) == std::numeric_limits<RealType>::infinity())
//{ // pdf + and - infinity is zero.
// return 0;
//}
if(false == detail::check_x(function, x, &result, Policy()))
{ // Catches x = NaN
return result;
}
RealType xs = (x - location) / scale;
result = 1 / (constants::pi<RealType>() * scale * (1 + xs * xs));
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const cauchy_distribution<RealType, Policy>& dist, const RealType& x)
{
return detail::cdf_imp(dist, x, false);
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const cauchy_distribution<RealType, Policy>& dist, const RealType& p)
{
return detail::quantile_imp(dist, p, false);
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<cauchy_distribution<RealType, Policy>, RealType>& c)
{
return detail::cdf_imp(c.dist, c.param, true);
} // cdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<cauchy_distribution<RealType, Policy>, RealType>& c)
{
return detail::quantile_imp(c.dist, c.param, true);
} // quantile complement
template <class RealType, class Policy>
inline RealType mean(const cauchy_distribution<RealType, Policy>&)
{ // There is no mean:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::mean(cauchy<%1%>&)",
"The Cauchy distribution does not have a mean: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy());
}
template <class RealType, class Policy>
inline RealType variance(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no variance:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::variance(cauchy<%1%>&)",
"The Cauchy distribution does not have a variance: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy());
}
template <class RealType, class Policy>
inline RealType mode(const cauchy_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType median(const cauchy_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType skewness(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no skewness:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::skewness(cauchy<%1%>&)",
"The Cauchy distribution does not have a skewness: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy()); // infinity?
}
template <class RealType, class Policy>
inline RealType kurtosis(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no kurtosis:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::kurtosis(cauchy<%1%>&)",
"The Cauchy distribution does not have a kurtosis: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy());
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no kurtosis excess:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::kurtosis_excess(cauchy<%1%>&)",
"The Cauchy distribution does not have a kurtosis: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy());
}
} // namespace math
} // namespace boost
#ifdef _MSC_VER
#pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_CAUCHY_HPP

View File

@@ -0,0 +1,326 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_DISTRIBUTIONS_CHI_SQUARED_HPP
#define BOOST_MATH_DISTRIBUTIONS_CHI_SQUARED_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/gamma.hpp> // for incomplete beta.
#include <boost/math/distributions/complement.hpp> // complements
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
#include <boost/math/special_functions/fpclassify.hpp>
#include <utility>
namespace boost{ namespace math{
template <class RealType = double, class Policy = policies::policy<> >
class chi_squared_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
chi_squared_distribution(RealType i) : m_df(i)
{
RealType result;
detail::check_df(
"boost::math::chi_squared_distribution<%1%>::chi_squared_distribution", m_df, &result, Policy());
} // chi_squared_distribution
RealType degrees_of_freedom()const
{
return m_df;
}
// Parameter estimation:
static RealType find_degrees_of_freedom(
RealType difference_from_variance,
RealType alpha,
RealType beta,
RealType variance,
RealType hint = 100);
private:
//
// Data member:
//
RealType m_df; // degrees of freedom are a real number.
}; // class chi_squared_distribution
typedef chi_squared_distribution<double> chi_squared;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const chi_squared_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>()); // 0 to + infinity.
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const chi_squared_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
return std::pair<RealType, RealType>(0, tools::max_value<RealType>()); // 0 to + infinity.
}
template <class RealType, class Policy>
RealType pdf(const chi_squared_distribution<RealType, Policy>& dist, const RealType& chi_square)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType degrees_of_freedom = dist.degrees_of_freedom();
// Error check:
RealType error_result;
static const char* function = "boost::math::pdf(const chi_squared_distribution<%1%>&, %1%)";
if(false == detail::check_df(
function, degrees_of_freedom, &error_result, Policy()))
return error_result;
if((chi_square < 0) || !(boost::math::isfinite)(chi_square))
{
return policies::raise_domain_error<RealType>(
function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy());
}
if(chi_square == 0)
{
// Handle special cases:
if(degrees_of_freedom < 2)
{
return policies::raise_overflow_error<RealType>(
function, 0, Policy());
}
else if(degrees_of_freedom == 2)
{
return 0.5f;
}
else
{
return 0;
}
}
return gamma_p_derivative(degrees_of_freedom / 2, chi_square / 2, Policy()) / 2;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const chi_squared_distribution<RealType, Policy>& dist, const RealType& chi_square)
{
RealType degrees_of_freedom = dist.degrees_of_freedom();
// Error check:
RealType error_result;
static const char* function = "boost::math::cdf(const chi_squared_distribution<%1%>&, %1%)";
if(false == detail::check_df(
function, degrees_of_freedom, &error_result, Policy()))
return error_result;
if((chi_square < 0) || !(boost::math::isfinite)(chi_square))
{
return policies::raise_domain_error<RealType>(
function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy());
}
return boost::math::gamma_p(degrees_of_freedom / 2, chi_square / 2, Policy());
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const chi_squared_distribution<RealType, Policy>& dist, const RealType& p)
{
RealType degrees_of_freedom = dist.degrees_of_freedom();
static const char* function = "boost::math::quantile(const chi_squared_distribution<%1%>&, %1%)";
// Error check:
RealType error_result;
if(false == detail::check_df(
function, degrees_of_freedom, &error_result, Policy())
&& detail::check_probability(
function, p, &error_result, Policy()))
return error_result;
return 2 * boost::math::gamma_p_inv(degrees_of_freedom / 2, p, Policy());
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<chi_squared_distribution<RealType, Policy>, RealType>& c)
{
RealType const& degrees_of_freedom = c.dist.degrees_of_freedom();
RealType const& chi_square = c.param;
static const char* function = "boost::math::cdf(const chi_squared_distribution<%1%>&, %1%)";
// Error check:
RealType error_result;
if(false == detail::check_df(
function, degrees_of_freedom, &error_result, Policy()))
return error_result;
if((chi_square < 0) || !(boost::math::isfinite)(chi_square))
{
return policies::raise_domain_error<RealType>(
function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy());
}
return boost::math::gamma_q(degrees_of_freedom / 2, chi_square / 2, Policy());
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<chi_squared_distribution<RealType, Policy>, RealType>& c)
{
RealType const& degrees_of_freedom = c.dist.degrees_of_freedom();
RealType const& q = c.param;
static const char* function = "boost::math::quantile(const chi_squared_distribution<%1%>&, %1%)";
// Error check:
RealType error_result;
if(false == detail::check_df(
function, degrees_of_freedom, &error_result, Policy())
&& detail::check_probability(
function, q, &error_result, Policy()))
return error_result;
return 2 * boost::math::gamma_q_inv(degrees_of_freedom / 2, q, Policy());
}
template <class RealType, class Policy>
inline RealType mean(const chi_squared_distribution<RealType, Policy>& dist)
{ // Mean of Chi-Squared distribution = v.
return dist.degrees_of_freedom();
} // mean
template <class RealType, class Policy>
inline RealType variance(const chi_squared_distribution<RealType, Policy>& dist)
{ // Variance of Chi-Squared distribution = 2v.
return 2 * dist.degrees_of_freedom();
} // variance
template <class RealType, class Policy>
inline RealType mode(const chi_squared_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
static const char* function = "boost::math::mode(const chi_squared_distribution<%1%>&)";
if(df <= 2)
return policies::raise_domain_error<RealType>(
function,
"The Chi-Squared distribution only has a mode for degrees of freedom >= 2, but got degrees of freedom = %1%.",
df, Policy());
return df - 2;
}
//template <class RealType, class Policy>
//inline RealType median(const chi_squared_distribution<RealType, Policy>& dist)
//{ // Median is given by Quantile[dist, 1/2]
// RealType df = dist.degrees_of_freedom();
// if(df <= 1)
// return tools::domain_error<RealType>(
// BOOST_CURRENT_FUNCTION,
// "The Chi-Squared distribution only has a mode for degrees of freedom >= 2, but got degrees of freedom = %1%.",
// df);
// return df - RealType(2)/3;
//}
// Now implemented via quantile(half) in derived accessors.
template <class RealType, class Policy>
inline RealType skewness(const chi_squared_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // For ADL
RealType df = dist.degrees_of_freedom();
return sqrt (8 / df); // == 2 * sqrt(2 / df);
}
template <class RealType, class Policy>
inline RealType kurtosis(const chi_squared_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
return 3 + 12 / df;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const chi_squared_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
return 12 / df;
}
//
// Parameter estimation comes last:
//
namespace detail
{
template <class RealType, class Policy>
struct df_estimator
{
df_estimator(RealType a, RealType b, RealType variance, RealType delta)
: alpha(a), beta(b), ratio(delta/variance) {}
RealType operator()(const RealType& df)
{
if(df <= tools::min_value<RealType>())
return 1;
chi_squared_distribution<RealType, Policy> cs(df);
RealType result;
if(ratio > 0)
{
RealType r = 1 + ratio;
result = cdf(cs, quantile(complement(cs, alpha)) / r) - beta;
}
else
{
RealType r = 1 + ratio;
result = cdf(complement(cs, quantile(cs, alpha) / r)) - beta;
}
return result;
}
private:
RealType alpha, beta, ratio;
};
} // namespace detail
template <class RealType, class Policy>
RealType chi_squared_distribution<RealType, Policy>::find_degrees_of_freedom(
RealType difference_from_variance,
RealType alpha,
RealType beta,
RealType variance,
RealType hint)
{
static const char* function = "boost::math::chi_squared_distribution<%1%>::find_degrees_of_freedom(%1%,%1%,%1%,%1%,%1%)";
// Check for domain errors:
RealType error_result;
if(false == detail::check_probability(
function, alpha, &error_result, Policy())
&& detail::check_probability(function, beta, &error_result, Policy()))
return error_result;
if(hint <= 0)
hint = 1;
detail::df_estimator<RealType, Policy> f(alpha, beta, variance, difference_from_variance);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::pair<RealType, RealType> r = tools::bracket_and_solve_root(f, hint, RealType(2), false, tol, max_iter, Policy());
RealType result = r.first + (r.second - r.first) / 2;
if(max_iter == policies::get_max_root_iterations<Policy>())
{
policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" either there is no answer to how many degrees of freedom are required"
" or the answer is infinite. Current best guess is %1%", result, Policy());
}
return result;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_DISTRIBUTIONS_CHI_SQUARED_HPP

View File

@@ -0,0 +1,195 @@
// (C) Copyright John Maddock 2006.
// (C) Copyright Paul A. Bristow 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_COMPLEMENT_HPP
#define BOOST_STATS_COMPLEMENT_HPP
//
// This code really defines our own tuple type.
// It would be nice to reuse std::tr1::tuple
// while retaining our own type safety, but it's
// not clear if that's possible. In any case this
// code is *very* lightweight.
//
namespace boost{ namespace math{
template <class Dist, class RealType>
struct complemented2_type
{
complemented2_type(
const Dist& d,
const RealType& p1)
: dist(d),
param(p1) {}
const Dist& dist;
const RealType& param;
private:
complemented2_type& operator=(const complemented2_type&);
};
template <class Dist, class RealType1, class RealType2>
struct complemented3_type
{
complemented3_type(
const Dist& d,
const RealType1& p1,
const RealType2& p2)
: dist(d),
param1(p1),
param2(p2) {}
const Dist& dist;
const RealType1& param1;
const RealType2& param2;
private:
complemented3_type& operator=(const complemented3_type&);
};
template <class Dist, class RealType1, class RealType2, class RealType3>
struct complemented4_type
{
complemented4_type(
const Dist& d,
const RealType1& p1,
const RealType2& p2,
const RealType3& p3)
: dist(d),
param1(p1),
param2(p2),
param3(p3) {}
const Dist& dist;
const RealType1& param1;
const RealType2& param2;
const RealType3& param3;
private:
complemented4_type& operator=(const complemented4_type&);
};
template <class Dist, class RealType1, class RealType2, class RealType3, class RealType4>
struct complemented5_type
{
complemented5_type(
const Dist& d,
const RealType1& p1,
const RealType2& p2,
const RealType3& p3,
const RealType4& p4)
: dist(d),
param1(p1),
param2(p2),
param3(p3),
param4(p4) {}
const Dist& dist;
const RealType1& param1;
const RealType2& param2;
const RealType3& param3;
const RealType4& param4;
private:
complemented5_type& operator=(const complemented5_type&);
};
template <class Dist, class RealType1, class RealType2, class RealType3, class RealType4, class RealType5>
struct complemented6_type
{
complemented6_type(
const Dist& d,
const RealType1& p1,
const RealType2& p2,
const RealType3& p3,
const RealType4& p4,
const RealType5& p5)
: dist(d),
param1(p1),
param2(p2),
param3(p3),
param4(p4),
param5(p5) {}
const Dist& dist;
const RealType1& param1;
const RealType2& param2;
const RealType3& param3;
const RealType4& param4;
const RealType5& param5;
private:
complemented6_type& operator=(const complemented6_type&);
};
template <class Dist, class RealType1, class RealType2, class RealType3, class RealType4, class RealType5, class RealType6>
struct complemented7_type
{
complemented7_type(
const Dist& d,
const RealType1& p1,
const RealType2& p2,
const RealType3& p3,
const RealType4& p4,
const RealType5& p5,
const RealType6& p6)
: dist(d),
param1(p1),
param2(p2),
param3(p3),
param4(p4),
param5(p5),
param6(p6) {}
const Dist& dist;
const RealType1& param1;
const RealType2& param2;
const RealType3& param3;
const RealType4& param4;
const RealType5& param5;
const RealType6& param6;
private:
complemented7_type& operator=(const complemented7_type&);
};
template <class Dist, class RealType>
inline complemented2_type<Dist, RealType> complement(const Dist& d, const RealType& r)
{
return complemented2_type<Dist, RealType>(d, r);
}
template <class Dist, class RealType1, class RealType2>
inline complemented3_type<Dist, RealType1, RealType2> complement(const Dist& d, const RealType1& r1, const RealType2& r2)
{
return complemented3_type<Dist, RealType1, RealType2>(d, r1, r2);
}
template <class Dist, class RealType1, class RealType2, class RealType3>
inline complemented4_type<Dist, RealType1, RealType2, RealType3> complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3)
{
return complemented4_type<Dist, RealType1, RealType2, RealType3>(d, r1, r2, r3);
}
template <class Dist, class RealType1, class RealType2, class RealType3, class RealType4>
inline complemented5_type<Dist, RealType1, RealType2, RealType3, RealType4> complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3, const RealType4& r4)
{
return complemented5_type<Dist, RealType1, RealType2, RealType3, RealType4>(d, r1, r2, r3, r4);
}
template <class Dist, class RealType1, class RealType2, class RealType3, class RealType4, class RealType5>
inline complemented6_type<Dist, RealType1, RealType2, RealType3, RealType4, RealType5> complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3, const RealType4& r4, const RealType5& r5)
{
return complemented6_type<Dist, RealType1, RealType2, RealType3, RealType4, RealType5>(d, r1, r2, r3, r4, r5);
}
template <class Dist, class RealType1, class RealType2, class RealType3, class RealType4, class RealType5, class RealType6>
inline complemented7_type<Dist, RealType1, RealType2, RealType3, RealType4, RealType5, RealType6> complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3, const RealType4& r4, const RealType5& r5, const RealType6& r6)
{
return complemented7_type<Dist, RealType1, RealType2, RealType3, RealType4, RealType5, RealType6>(d, r1, r2, r3, r4, r5, r6);
}
} // namespace math
} // namespace boost
#endif // BOOST_STATS_COMPLEMENT_HPP

View File

@@ -0,0 +1,103 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2006, 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_DISTRIBUTIONS_COMMON_ERROR_HANDLING_HPP
#define BOOST_MATH_DISTRIBUTIONS_COMMON_ERROR_HANDLING_HPP
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
// using boost::math::isfinite;
namespace boost{ namespace math{ namespace detail
{
template <class RealType, class Policy>
inline bool check_probability(const char* function, RealType const& prob, RealType* result, const Policy& pol)
{
if((prob < 0) || (prob > 1) || !(boost::math::isfinite)(prob))
{
*result = policies::raise_domain_error<RealType>(
function,
"Probability argument is %1%, but must be >= 0 and <= 1 !", prob, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_df(const char* function, RealType const& df, RealType* result, const Policy& pol)
{
if((df <= 0) || !(boost::math::isfinite)(df))
{
*result = policies::raise_domain_error<RealType>(
function,
"Degrees of freedom argument is %1%, but must be > 0 !", df, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_scale(
const char* function,
RealType scale,
RealType* result,
const Policy& pol)
{
if((scale <= 0) || !(boost::math::isfinite)(scale))
{ // Assume scale == 0 is NOT valid for any distribution.
*result = policies::raise_domain_error<RealType>(
function,
"Scale parameter is %1%, but must be > 0 !", scale, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_location(
const char* function,
RealType location,
RealType* result,
const Policy& pol)
{
if(!(boost::math::isfinite)(location))
{
*result = policies::raise_domain_error<RealType>(
function,
"Location parameter is %1%, but must be finite!", location, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_x(
const char* function,
RealType x,
RealType* result,
const Policy& pol)
{
if(!(boost::math::isfinite)(x))
{
*result = policies::raise_domain_error<RealType>(
function,
"Random variate x is %1%, but must be finite!", x, pol);
return false;
}
return true;
// Note that this test catches both infinity and NaN.
// Some special cases permit x to be infinite, so these must be tested 1st,
// leaving this test to catch any NaNs. see Normal and cauchy for example.
}
} // namespace detail
} // namespace math
} // namespace boost
#endif // BOOST_MATH_DISTRIBUTIONS_COMMON_ERROR_HANDLING_HPP

View File

@@ -0,0 +1,163 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_DERIVED_HPP
#define BOOST_STATS_DERIVED_HPP
// This file implements various common properties of distributions
// that can be implemented in terms of other properties:
// variance OR standard deviation (see note below),
// hazard, cumulative hazard (chf), coefficient_of_variation.
//
// Note that while both variance and standard_deviation are provided
// here, each distribution MUST SPECIALIZE AT LEAST ONE OF THESE
// otherwise these two versions will just call each other over and over
// until stack space runs out ...
// Of course there may be more efficient means of implementing these
// that are specific to a particular distribution, but these generic
// versions give these properties "for free" with most distributions.
//
// In order to make use of this header, it must be included AT THE END
// of the distribution header, AFTER the distribution and its core
// property accessors have been defined: this is so that compilers
// that implement 2-phase lookup and early-type-checking of templates
// can find the definitions refered to herein.
//
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4723) // potential divide by 0
// Suppressing spurious warning in coefficient_of_variation
#endif
namespace boost{ namespace math{
template <class Distribution>
typename Distribution::value_type variance(const Distribution& dist);
template <class Distribution>
inline typename Distribution::value_type standard_deviation(const Distribution& dist)
{
BOOST_MATH_STD_USING // ADL of sqrt.
return sqrt(variance(dist));
}
template <class Distribution>
inline typename Distribution::value_type variance(const Distribution& dist)
{
typename Distribution::value_type result = standard_deviation(dist);
return result * result;
}
template <class Distribution, class RealType>
inline typename Distribution::value_type hazard(const Distribution& dist, const RealType& x)
{ // hazard function
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda362.htm#HAZ
typedef typename Distribution::value_type value_type;
typedef typename Distribution::policy_type policy_type;
value_type p = cdf(complement(dist, x));
value_type d = pdf(dist, x);
if(d > p * tools::max_value<value_type>())
return policies::raise_overflow_error<value_type>(
"boost::math::hazard(const Distribution&, %1%)", 0, policy_type());
if(d == 0)
{
// This protects against 0/0, but is it the right thing to do?
return 0;
}
return d / p;
}
template <class Distribution, class RealType>
inline typename Distribution::value_type chf(const Distribution& dist, const RealType& x)
{ // cumulative hazard function.
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda362.htm#HAZ
BOOST_MATH_STD_USING
return -log(cdf(complement(dist, x)));
}
template <class Distribution>
inline typename Distribution::value_type coefficient_of_variation(const Distribution& dist)
{
typedef typename Distribution::value_type value_type;
typedef typename Distribution::policy_type policy_type;
using std::abs;
value_type m = mean(dist);
value_type d = standard_deviation(dist);
if((abs(m) < 1) && (d > abs(m) * tools::max_value<value_type>()))
{ // Checks too that m is not zero,
return policies::raise_overflow_error<value_type>("boost::math::coefficient_of_variation(const Distribution&, %1%)", 0, policy_type());
}
return d / m; // so MSVC warning on zerodivide is spurious, and suppressed.
}
//
// Next follow overloads of some of the standard accessors with mixed
// argument types. We just use a typecast to forward on to the "real"
// implementation with all arguments of the same type:
//
template <class Distribution, class RealType>
inline typename Distribution::value_type pdf(const Distribution& dist, const RealType& x)
{
typedef typename Distribution::value_type value_type;
return pdf(dist, static_cast<value_type>(x));
}
template <class Distribution, class RealType>
inline typename Distribution::value_type cdf(const Distribution& dist, const RealType& x)
{
typedef typename Distribution::value_type value_type;
return cdf(dist, static_cast<value_type>(x));
}
template <class Distribution, class RealType>
inline typename Distribution::value_type quantile(const Distribution& dist, const RealType& x)
{
typedef typename Distribution::value_type value_type;
return quantile(dist, static_cast<value_type>(x));
}
/*
template <class Distribution, class RealType>
inline typename Distribution::value_type chf(const Distribution& dist, const RealType& x)
{
typedef typename Distribution::value_type value_type;
return chf(dist, static_cast<value_type>(x));
}
*/
template <class Distribution, class RealType>
inline typename Distribution::value_type cdf(const complemented2_type<Distribution, RealType>& c)
{
typedef typename Distribution::value_type value_type;
return cdf(complement(c.dist, static_cast<value_type>(c.param)));
}
template <class Distribution, class RealType>
inline typename Distribution::value_type quantile(const complemented2_type<Distribution, RealType>& c)
{
typedef typename Distribution::value_type value_type;
return quantile(complement(c.dist, static_cast<value_type>(c.param)));
}
template <class Dist>
inline typename Dist::value_type median(const Dist& d)
{ // median - default definition for those distributions for which a
// simple closed form is not known,
// and for which a domain_error and/or NaN generating function is NOT defined.
typedef typename Dist::value_type value_type;
return quantile(d, static_cast<value_type>(0.5f));
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif // BOOST_STATS_DERIVED_HPP

View File

@@ -0,0 +1,481 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE
#include <algorithm>
namespace boost{ namespace math{ namespace detail{
//
// Functor for root finding algorithm:
//
template <class Dist>
struct distribution_quantile_finder
{
typedef typename Dist::value_type value_type;
typedef typename Dist::policy_type policy_type;
distribution_quantile_finder(const Dist d, value_type p, value_type q)
: dist(d), target(p < q ? p : q), comp(p < q ? false : true) {}
value_type operator()(value_type const& x)
{
return comp ? target - cdf(complement(dist, x)) : cdf(dist, x) - target;
}
private:
Dist dist;
value_type target;
bool comp;
};
//
// The purpose of adjust_bounds, is to toggle the last bit of the
// range so that both ends round to the same integer, if possible.
// If they do both round the same then we terminate the search
// for the root *very* quickly when finding an integer result.
// At the point that this function is called we know that "a" is
// below the root and "b" above it, so this change can not result
// in the root no longer being bracketed.
//
template <class Real, class Tol>
void adjust_bounds(Real& /* a */, Real& /* b */, Tol const& /* tol */){}
template <class Real>
void adjust_bounds(Real& /* a */, Real& b, tools::equal_floor const& /* tol */)
{
BOOST_MATH_STD_USING
b -= tools::epsilon<Real>() * b;
}
template <class Real>
void adjust_bounds(Real& a, Real& /* b */, tools::equal_ceil const& /* tol */)
{
BOOST_MATH_STD_USING
a += tools::epsilon<Real>() * a;
}
template <class Real>
void adjust_bounds(Real& a, Real& b, tools::equal_nearest_integer const& /* tol */)
{
BOOST_MATH_STD_USING
a += tools::epsilon<Real>() * a;
b -= tools::epsilon<Real>() * b;
}
//
// This is where all the work is done:
//
template <class Dist, class Tolerance>
typename Dist::value_type
do_inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& q,
typename Dist::value_type guess,
const typename Dist::value_type& multiplier,
typename Dist::value_type adder,
const Tolerance& tol,
boost::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
typedef typename Dist::policy_type policy_type;
static const char* function = "boost::math::do_inverse_discrete_quantile<%1%>";
BOOST_MATH_STD_USING
distribution_quantile_finder<Dist> f(dist, p, q);
//
// Max bounds of the distribution:
//
value_type min_bound, max_bound;
std::tr1::tie(min_bound, max_bound) = support(dist);
if(guess > max_bound)
guess = max_bound;
if(guess < min_bound)
guess = min_bound;
value_type fa = f(guess);
boost::uintmax_t count = max_iter - 1;
value_type fb(fa), a(guess), b =0; // Compiler warning C4701: potentially uninitialized local variable 'b' used
if(fa == 0)
return guess;
//
// For small expected results, just use a linear search:
//
if(guess < 10)
{
b = a;
while((a < 10) && (fa * fb >= 0))
{
if(fb <= 0)
{
a = b;
b = a + 1;
if(b > max_bound)
b = max_bound;
fb = f(b);
--count;
if(fb == 0)
return b;
}
else
{
b = a;
a = (std::max)(b - 1, value_type(0));
if(a < min_bound)
a = min_bound;
fa = f(a);
--count;
if(fa == 0)
return a;
}
}
}
//
// Try and bracket using a couple of additions first,
// we're assuming that "guess" is likely to be accurate
// to the nearest int or so:
//
else if(adder != 0)
{
//
// If we're looking for a large result, then bump "adder" up
// by a bit to increase our chances of bracketing the root:
//
//adder = (std::max)(adder, 0.001f * guess);
if(fa < 0)
{
b = a + adder;
if(b > max_bound)
b = max_bound;
}
else
{
b = (std::max)(a - adder, value_type(0));
if(b < min_bound)
b = min_bound;
}
fb = f(b);
--count;
if(fb == 0)
return b;
if(count && (fa * fb >= 0))
{
//
// We didn't bracket the root, try
// once more:
//
a = b;
fa = fb;
if(fa < 0)
{
b = a + adder;
if(b > max_bound)
b = max_bound;
}
else
{
b = (std::max)(a - adder, value_type(0));
if(b < min_bound)
b = min_bound;
}
fb = f(b);
--count;
}
if(a > b)
{
using std::swap;
swap(a, b);
swap(fa, fb);
}
}
//
// If the root hasn't been bracketed yet, try again
// using the multiplier this time:
//
if(sign(fb) == sign(fa))
{
if(fa < 0)
{
//
// Zero is to the right of x2, so walk upwards
// until we find it:
//
while(sign(fb) == sign(fa))
{
if(count == 0)
policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, policy_type());
a = b;
fa = fb;
b *= multiplier;
if(b > max_bound)
b = max_bound;
fb = f(b);
--count;
BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
}
}
else
{
//
// Zero is to the left of a, so walk downwards
// until we find it:
//
while(sign(fb) == sign(fa))
{
if(fabs(a) < tools::min_value<value_type>())
{
// Escape route just in case the answer is zero!
max_iter -= count;
max_iter += 1;
return 0;
}
if(count == 0)
policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, policy_type());
b = a;
fb = fa;
a /= multiplier;
if(a < min_bound)
a = min_bound;
fa = f(a);
--count;
BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
}
}
}
max_iter -= count;
if(fa == 0)
return a;
if(fb == 0)
return b;
//
// Adjust bounds so that if we're looking for an integer
// result, then both ends round the same way:
//
adjust_bounds(a, b, tol);
//
// We don't want zero or denorm lower bounds:
//
if(a < tools::min_value<value_type>())
a = tools::min_value<value_type>();
//
// Go ahead and find the root:
//
std::pair<value_type, value_type> r = toms748_solve(f, a, b, fa, fb, tol, count, policy_type());
max_iter += count;
BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count);
return (r.first + r.second) / 2;
}
//
// Now finally are the public API functions.
// There is one overload for each policy,
// each one is responsible for selecting the correct
// termination condition, and rounding the result
// to an int where required.
//
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& q,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::real>&,
boost::uintmax_t& max_iter)
{
if(p <= pdf(dist, 0))
return 0;
return do_inverse_discrete_quantile(
dist,
p,
q,
guess,
multiplier,
adder,
tools::eps_tolerance<typename Dist::value_type>(policies::digits<typename Dist::value_type, typename Dist::policy_type>()),
max_iter);
}
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& q,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_outwards>&,
boost::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
if(p <= pdf(dist, 0))
return 0;
//
// What happens next depends on whether we're looking for an
// upper or lower quantile:
//
if(p < 0.5f)
return floor(do_inverse_discrete_quantile(
dist,
p,
q,
(guess < 1 ? value_type(1) : floor(guess)),
multiplier,
adder,
tools::equal_floor(),
max_iter));
// else:
return ceil(do_inverse_discrete_quantile(
dist,
p,
q,
ceil(guess),
multiplier,
adder,
tools::equal_ceil(),
max_iter));
}
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& q,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_inwards>&,
boost::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
if(p <= pdf(dist, 0))
return 0;
//
// What happens next depends on whether we're looking for an
// upper or lower quantile:
//
if(p < 0.5f)
return ceil(do_inverse_discrete_quantile(
dist,
p,
q,
ceil(guess),
multiplier,
adder,
tools::equal_ceil(),
max_iter));
// else:
return floor(do_inverse_discrete_quantile(
dist,
p,
q,
(guess < 1 ? value_type(1) : floor(guess)),
multiplier,
adder,
tools::equal_floor(),
max_iter));
}
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& q,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_down>&,
boost::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
if(p <= pdf(dist, 0))
return 0;
return floor(do_inverse_discrete_quantile(
dist,
p,
q,
(guess < 1 ? value_type(1) : floor(guess)),
multiplier,
adder,
tools::equal_floor(),
max_iter));
}
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& q,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_up>&,
boost::uintmax_t& max_iter)
{
BOOST_MATH_STD_USING
if(p <= pdf(dist, 0))
return 0;
return ceil(do_inverse_discrete_quantile(
dist,
p,
q,
ceil(guess),
multiplier,
adder,
tools::equal_ceil(),
max_iter));
}
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& q,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_nearest>&,
boost::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
if(p <= pdf(dist, 0))
return 0;
//
// Note that we adjust the guess to the nearest half-integer:
// this increase the chances that we will bracket the root
// with two results that both round to the same integer quickly.
//
return floor(do_inverse_discrete_quantile(
dist,
p,
q,
(guess < 0.5f ? value_type(1.5f) : floor(guess + 0.5f) + 0.5f),
multiplier,
adder,
tools::equal_nearest_integer(),
max_iter) + 0.5f);
}
}}} // namespaces
#endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE

View File

@@ -0,0 +1,259 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_EXPONENTIAL_HPP
#define BOOST_STATS_EXPONENTIAL_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <cmath>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
#include <utility>
namespace boost{ namespace math{
namespace detail{
//
// Error check:
//
template <class RealType, class Policy>
inline bool verify_lambda(const char* function, RealType l, RealType* presult, const Policy& pol)
{
if(l <= 0)
{
*presult = policies::raise_domain_error<RealType>(
function,
"The scale parameter \"lambda\" must be > 0, but was: %1%.", l, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool verify_exp_x(const char* function, RealType x, RealType* presult, const Policy& pol)
{
if(x < 0)
{
*presult = policies::raise_domain_error<RealType>(
function,
"The random variable must be >= 0, but was: %1%.", x, pol);
return false;
}
return true;
}
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class exponential_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
exponential_distribution(RealType lambda = 1)
: m_lambda(lambda)
{
RealType err;
detail::verify_lambda("boost::math::exponential_distribution<%1%>::exponential_distribution", lambda, &err, Policy());
} // exponential_distribution
RealType lambda()const { return m_lambda; }
private:
RealType m_lambda;
};
typedef exponential_distribution<double> exponential;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const exponential_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const exponential_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType pdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::pdf(const exponential_distribution<%1%>&, %1%)";
RealType lambda = dist.lambda();
RealType result;
if(0 == detail::verify_lambda(function, lambda, &result, Policy()))
return result;
if(0 == detail::verify_exp_x(function, x, &result, Policy()))
return result;
result = lambda * exp(-lambda * x);
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(const exponential_distribution<%1%>&, %1%)";
RealType result;
RealType lambda = dist.lambda();
if(0 == detail::verify_lambda(function, lambda, &result, Policy()))
return result;
if(0 == detail::verify_exp_x(function, x, &result, Policy()))
return result;
result = -boost::math::expm1(-x * lambda, Policy());
return result;
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const exponential_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const exponential_distribution<%1%>&, %1%)";
RealType result;
RealType lambda = dist.lambda();
if(0 == detail::verify_lambda(function, lambda, &result, Policy()))
return result;
if(0 == detail::check_probability(function, p, &result, Policy()))
return result;
if(p == 0)
return 0;
if(p == 1)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
result = -boost::math::log1p(-p, Policy()) / lambda;
return result;
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<exponential_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(const exponential_distribution<%1%>&, %1%)";
RealType result;
RealType lambda = c.dist.lambda();
if(0 == detail::verify_lambda(function, lambda, &result, Policy()))
return result;
if(0 == detail::verify_exp_x(function, c.param, &result, Policy()))
return result;
result = exp(-c.param * lambda);
return result;
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<exponential_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const exponential_distribution<%1%>&, %1%)";
RealType result;
RealType lambda = c.dist.lambda();
if(0 == detail::verify_lambda(function, lambda, &result, Policy()))
return result;
RealType q = c.param;
if(0 == detail::check_probability(function, q, &result, Policy()))
return result;
if(q == 1)
return 0;
if(q == 0)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
result = -log(q) / lambda;
return result;
}
template <class RealType, class Policy>
inline RealType mean(const exponential_distribution<RealType, Policy>& dist)
{
RealType result;
RealType lambda = dist.lambda();
if(0 == detail::verify_lambda("boost::math::mean(const exponential_distribution<%1%>&)", lambda, &result, Policy()))
return result;
return 1 / lambda;
}
template <class RealType, class Policy>
inline RealType standard_deviation(const exponential_distribution<RealType, Policy>& dist)
{
RealType result;
RealType lambda = dist.lambda();
if(0 == detail::verify_lambda("boost::math::standard_deviation(const exponential_distribution<%1%>&)", lambda, &result, Policy()))
return result;
return 1 / lambda;
}
template <class RealType, class Policy>
inline RealType mode(const exponential_distribution<RealType, Policy>& /*dist*/)
{
return 0;
}
template <class RealType, class Policy>
inline RealType median(const exponential_distribution<RealType, Policy>& dist)
{
using boost::math::constants::ln_two;
return ln_two<RealType>() / dist.lambda(); // ln(2) / lambda
}
template <class RealType, class Policy>
inline RealType skewness(const exponential_distribution<RealType, Policy>& /*dist*/)
{
return 2;
}
template <class RealType, class Policy>
inline RealType kurtosis(const exponential_distribution<RealType, Policy>& /*dist*/)
{
return 9;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const exponential_distribution<RealType, Policy>& /*dist*/)
{
return 6;
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_EXPONENTIAL_HPP

View File

@@ -0,0 +1,260 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_EXTREME_VALUE_HPP
#define BOOST_STATS_EXTREME_VALUE_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <cmath>
//
// This is the maximum extreme value distribution, see
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda366g.htm
// and http://mathworld.wolfram.com/ExtremeValueDistribution.html
// Also known as a Fisher-Tippett distribution, a log-Weibull
// distribution or a Gumbel distribution.
#include <utility>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
namespace boost{ namespace math{
namespace detail{
//
// Error check:
//
template <class RealType, class Policy>
inline bool verify_scale_b(const char* function, RealType b, RealType* presult, const Policy& pol)
{
if(b <= 0)
{
*presult = policies::raise_domain_error<RealType>(
function,
"The scale parameter \"b\" must be > 0, but was: %1%.", b, pol);
return false;
}
return true;
}
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class extreme_value_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
extreme_value_distribution(RealType a = 0, RealType b = 1)
: m_a(a), m_b(b)
{
RealType err;
detail::verify_scale_b("boost::math::extreme_value_distribution<%1%>::extreme_value_distribution", b, &err, Policy());
} // extreme_value_distribution
RealType location()const { return m_a; }
RealType scale()const { return m_b; }
private:
RealType m_a, m_b;
};
typedef extreme_value_distribution<double> extreme_value;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const extreme_value_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const extreme_value_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType pdf(const extreme_value_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType a = dist.location();
RealType b = dist.scale();
RealType result;
if(0 == detail::verify_scale_b("boost::math::pdf(const extreme_value_distribution<%1%>&, %1%)", b, &result, Policy()))
return result;
result = exp((a-x)/b) * exp(-exp((a-x)/b)) / b;
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const extreme_value_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType a = dist.location();
RealType b = dist.scale();
RealType result;
if(0 == detail::verify_scale_b("boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)", b, &result, Policy()))
return result;
result = exp(-exp((a-x)/b));
return result;
} // cdf
template <class RealType, class Policy>
RealType quantile(const extreme_value_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const extreme_value_distribution<%1%>&, %1%)";
RealType a = dist.location();
RealType b = dist.scale();
RealType result;
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_probability(function, p, &result, Policy()))
return result;
if(p == 0)
return -policies::raise_overflow_error<RealType>(function, 0, Policy());
if(p == 1)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
result = a - log(-log(p)) * b;
return result;
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<extreme_value_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType a = c.dist.location();
RealType b = c.dist.scale();
RealType result;
if(0 == detail::verify_scale_b("boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)", b, &result, Policy()))
return result;
result = -boost::math::expm1(-exp((a-c.param)/b), Policy());
return result;
}
template <class RealType, class Policy>
RealType quantile(const complemented2_type<extreme_value_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const extreme_value_distribution<%1%>&, %1%)";
RealType a = c.dist.location();
RealType b = c.dist.scale();
RealType q = c.param;
RealType result;
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_probability(function, q, &result, Policy()))
return result;
if(q == 0)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
if(q == 1)
return -policies::raise_overflow_error<RealType>(function, 0, Policy());
result = a - log(-boost::math::log1p(-q, Policy())) * b;
return result;
}
template <class RealType, class Policy>
inline RealType mean(const extreme_value_distribution<RealType, Policy>& dist)
{
RealType a = dist.location();
RealType b = dist.scale();
RealType result;
if(0 == detail::verify_scale_b("boost::math::mean(const extreme_value_distribution<%1%>&)", b, &result, Policy()))
return result;
return a + constants::euler<RealType>() * b;
}
template <class RealType, class Policy>
inline RealType standard_deviation(const extreme_value_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions.
RealType b = dist.scale();
RealType result;
if(0 == detail::verify_scale_b("boost::math::standard_deviation(const extreme_value_distribution<%1%>&)", b, &result, Policy()))
return result;
return constants::pi<RealType>() * b / sqrt(static_cast<RealType>(6));
}
template <class RealType, class Policy>
inline RealType mode(const extreme_value_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType median(const extreme_value_distribution<RealType, Policy>& dist)
{
using constants::ln_ln_two;
return dist.location() - dist.scale() * ln_ln_two<RealType>();
}
template <class RealType, class Policy>
inline RealType skewness(const extreme_value_distribution<RealType, Policy>& /*dist*/)
{
//
// This is 12 * sqrt(6) * zeta(3) / pi^3:
// See http://mathworld.wolfram.com/ExtremeValueDistribution.html
//
return static_cast<RealType>(1.1395470994046486574927930193898461120875997958366L);
}
template <class RealType, class Policy>
inline RealType kurtosis(const extreme_value_distribution<RealType, Policy>& /*dist*/)
{
// See http://mathworld.wolfram.com/ExtremeValueDistribution.html
return RealType(27) / 5;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const extreme_value_distribution<RealType, Policy>& /*dist*/)
{
// See http://mathworld.wolfram.com/ExtremeValueDistribution.html
return RealType(12) / 5;
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_EXTREME_VALUE_HPP

View File

@@ -0,0 +1,141 @@
// Copyright John Maddock 2007.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_FIND_LOCATION_HPP
#define BOOST_STATS_FIND_LOCATION_HPP
#include <boost/math/distributions/fwd.hpp> // for all distribution signatures.
#include <boost/math/distributions/complement.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/tools/traits.hpp>
#include <boost/static_assert.hpp>
// using boost::math::policies::policy;
// using boost::math::complement; // will be needed by users who want complement,
// but NOT placed here to avoid putting it in global scope.
namespace boost
{
namespace math
{
// Function to find location of random variable z
// to give probability p (given scale)
// Applies to normal, lognormal, extreme value, Cauchy, (and symmetrical triangular),
// enforced by BOOST_STATIC_ASSERT below.
template <class Dist, class Policy>
inline
typename Dist::value_type find_location( // For example, normal mean.
typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p.
// For example, a nominal minimum acceptable z, so that p * 100 % are > z
typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z.
typename Dist::value_type scale, // scale parameter, for example, normal standard deviation.
const Policy& pol
)
{
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
// Will fail to compile here if try to use with a distribution without scale & location,
// for example pareto, and many others.
static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)";
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, pol);
}
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "z parameter was %1%, but must be finite!", z, pol);
}
if(!(boost::math::isfinite)(scale))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "scale parameter was %1%, but must be finite!", scale, pol);
}
//cout << "z " << z << ", p " << p << ", quantile(Dist(), p) "
// << quantile(Dist(), p) << ", quan * scale " << quantile(Dist(), p) * scale << endl;
return z - (quantile(Dist(), p) * scale);
} // find_location
template <class Dist>
inline // with default policy.
typename Dist::value_type find_location( // For example, normal mean.
typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p.
// For example, a nominal minimum acceptable z, so that p * 100 % are > z
typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z.
typename Dist::value_type scale) // scale parameter, for example, normal standard deviation.
{ // Forward to find_location with default policy.
return (find_location<Dist>(z, p, scale, policies::policy<>()));
} // find_location
// So the user can start from the complement q = (1 - p) of the probability p,
// for example, l = find_location<normal>(complement(z, q, sd));
template <class Dist, class Real1, class Real2, class Real3>
inline typename Dist::value_type find_location( // Default policy.
complemented3_type<Real1, Real2, Real3> const& c)
{
static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)";
typename Dist::value_type p = c.param1;
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, policies::policy<>());
}
typename Dist::value_type z = c.dist;
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "z parameter was %1%, but must be finite!", z, policies::policy<>());
}
typename Dist::value_type scale = c.param2;
if(!(boost::math::isfinite)(scale))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "scale parameter was %1%, but must be finite!", scale, policies::policy<>());
}
// cout << "z " << c.dist << ", quantile (Dist(), " << c.param1 << ") * scale " << c.param2 << endl;
return z - quantile(Dist(), p) * scale;
} // find_location complement
template <class Dist, class Real1, class Real2, class Real3, class Real4>
inline typename Dist::value_type find_location( // Explicit policy.
complemented4_type<Real1, Real2, Real3, Real4> const& c)
{
static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)";
typename Dist::value_type p = c.param1;
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, c.param3);
}
typename Dist::value_type z = c.dist;
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "z parameter was %1%, but must be finite!", z, c.param3);
}
typename Dist::value_type scale = c.param2;
if(!(boost::math::isfinite)(scale))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "scale parameter was %1%, but must be finite!", scale, c.param3);
}
// cout << "z " << c.dist << ", quantile (Dist(), " << c.param1 << ") * scale " << c.param2 << endl;
return z - quantile(Dist(), p) * scale;
} // find_location complement
} // namespace boost
} // namespace math
#endif // BOOST_STATS_FIND_LOCATION_HPP

View File

@@ -0,0 +1,203 @@
// Copyright John Maddock 2007.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_FIND_SCALE_HPP
#define BOOST_STATS_FIND_SCALE_HPP
#include <boost/math/distributions/fwd.hpp> // for all distribution signatures.
#include <boost/math/distributions/complement.hpp>
#include <boost/math/policies/policy.hpp>
// using boost::math::policies::policy;
#include <boost/math/tools/traits.hpp>
#include <boost/static_assert.hpp>
// using boost::math::complement; // will be needed by users who want complement,
// but NOT placed here to avoid putting it in global scope.
namespace boost
{
namespace math
{
// Function to find location of random variable z
// to give probability p (given scale)
// Applies to normal, lognormal, extreme value, Cauchy, (and symmetrical triangular),
// distributions that have scale.
// BOOST_STATIC_ASSERTs, see below, are used to enforce this.
template <class Dist, class Policy>
inline
typename Dist::value_type find_scale( // For example, normal mean.
typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p.
// For example, a nominal minimum acceptable weight z, so that p * 100 % are > z
typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z.
typename Dist::value_type location, // location parameter, for example, normal distribution mean.
const Policy& pol
)
{
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
static const char* function = "boost::math::find_scale<Dist, Policy>(%1%, %1%, %1%, Policy)";
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, pol);
}
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "find_scale z parameter was %1%, but must be finite!", z, pol);
}
if(!(boost::math::isfinite)(location))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "find_scale location parameter was %1%, but must be finite!", location, pol);
}
//cout << "z " << z << ", p " << p << ", quantile(Dist(), p) "
//<< quantile(Dist(), p) << ", z - mean " << z - location
//<<", sd " << (z - location) / quantile(Dist(), p) << endl;
//quantile(N01, 0.001) -3.09023
//quantile(N01, 0.01) -2.32635
//quantile(N01, 0.05) -1.64485
//quantile(N01, 0.333333) -0.430728
//quantile(N01, 0.5) 0
//quantile(N01, 0.666667) 0.430728
//quantile(N01, 0.9) 1.28155
//quantile(N01, 0.95) 1.64485
//quantile(N01, 0.99) 2.32635
//quantile(N01, 0.999) 3.09023
typename Dist::value_type result =
(z - location) // difference between desired x and current location.
/ quantile(Dist(), p); // standard distribution.
if (result <= 0)
{ // If policy isn't to throw, return the scale <= 0.
policies::raise_evaluation_error<typename Dist::value_type>(function,
"Computed scale (%1%) is <= 0!" " Was the complement intended?",
result, Policy());
}
return result;
} // template <class Dist, class Policy> find_scale
template <class Dist>
inline // with default policy.
typename Dist::value_type find_scale( // For example, normal mean.
typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p.
// For example, a nominal minimum acceptable z, so that p * 100 % are > z
typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z.
typename Dist::value_type location) // location parameter, for example, mean.
{ // Forward to find_scale using the default policy.
return (find_scale<Dist>(z, p, location, policies::policy<>()));
} // find_scale
template <class Dist, class Real1, class Real2, class Real3, class Policy>
inline typename Dist::value_type find_scale(
complemented4_type<Real1, Real2, Real3, Policy> const& c)
{
//cout << "cparam1 q " << c.param1 // q
// << ", c.dist z " << c.dist // z
// << ", c.param2 l " << c.param2 // l
// << ", quantile (Dist(), c.param1 = q) "
// << quantile(Dist(), c.param1) //q
// << endl;
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
static const char* function = "boost::math::find_scale<Dist, Policy>(complement(%1%, %1%, %1%, Policy))";
// Checks on arguments, as not complemented version,
// Explicit policy.
typename Dist::value_type q = c.param1;
if(!(boost::math::isfinite)(q) || (q < 0) || (q > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", q, c.param3);
}
typename Dist::value_type z = c.dist;
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "find_scale z parameter was %1%, but must be finite!", z, c.param3);
}
typename Dist::value_type location = c.param2;
if(!(boost::math::isfinite)(location))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "find_scale location parameter was %1%, but must be finite!", location, c.param3);
}
typename Dist::value_type result =
(c.dist - c.param2) // difference between desired x and current location.
/ quantile(complement(Dist(), c.param1));
// ( z - location) / (quantile(complement(Dist(), q))
if (result <= 0)
{ // If policy isn't to throw, return the scale <= 0.
policies::raise_evaluation_error<typename Dist::value_type>(function,
"Computed scale (%1%) is <= 0!" " Was the complement intended?",
result, Policy());
}
return result;
} // template <class Dist, class Policy, class Real1, class Real2, class Real3> typename Dist::value_type find_scale
// So the user can start from the complement q = (1 - p) of the probability p,
// for example, s = find_scale<normal>(complement(z, q, l));
template <class Dist, class Real1, class Real2, class Real3>
inline typename Dist::value_type find_scale(
complemented3_type<Real1, Real2, Real3> const& c)
{
//cout << "cparam1 q " << c.param1 // q
// << ", c.dist z " << c.dist // z
// << ", c.param2 l " << c.param2 // l
// << ", quantile (Dist(), c.param1 = q) "
// << quantile(Dist(), c.param1) //q
// << endl;
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
static const char* function = "boost::math::find_scale<Dist, Policy>(complement(%1%, %1%, %1%, Policy))";
// Checks on arguments, as not complemented version,
// default policy policies::policy<>().
typename Dist::value_type q = c.param1;
if(!(boost::math::isfinite)(q) || (q < 0) || (q > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", q, policies::policy<>());
}
typename Dist::value_type z = c.dist;
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "find_scale z parameter was %1%, but must be finite!", z, policies::policy<>());
}
typename Dist::value_type location = c.param2;
if(!(boost::math::isfinite)(location))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "find_scale location parameter was %1%, but must be finite!", location, policies::policy<>());
}
typename Dist::value_type result =
(z - location) // difference between desired x and current location.
/ quantile(complement(Dist(), q));
// ( z - location) / (quantile(complement(Dist(), q))
if (result <= 0)
{ // If policy isn't to throw, return the scale <= 0.
policies::raise_evaluation_error<typename Dist::value_type>(function,
"Computed scale (%1%) is <= 0!" " Was the complement intended?",
result, policies::policy<>()); // This is only the default policy - also Want a version with Policy here.
}
return result;
} // template <class Dist, class Real1, class Real2, class Real3> typename Dist::value_type find_scale
} // namespace boost
} // namespace math
#endif // BOOST_STATS_FIND_SCALE_HPP

View File

@@ -0,0 +1,385 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_DISTRIBUTIONS_FISHER_F_HPP
#define BOOST_MATH_DISTRIBUTIONS_FISHER_F_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/beta.hpp> // for incomplete beta.
#include <boost/math/distributions/complement.hpp> // complements
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
#include <boost/math/special_functions/fpclassify.hpp>
#include <utility>
namespace boost{ namespace math{
template <class RealType = double, class Policy = policies::policy<> >
class fisher_f_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
fisher_f_distribution(const RealType& i, const RealType& j) : m_df1(i), m_df2(j)
{
static const char* function = "fisher_f_distribution<%1%>::fisher_f_distribution";
RealType result;
detail::check_df(
function, m_df1, &result, Policy());
detail::check_df(
function, m_df2, &result, Policy());
} // fisher_f_distribution
RealType degrees_of_freedom1()const
{
return m_df1;
}
RealType degrees_of_freedom2()const
{
return m_df2;
}
private:
//
// Data members:
//
RealType m_df1; // degrees of freedom are a real number.
RealType m_df2; // degrees of freedom are a real number.
};
typedef fisher_f_distribution<double> fisher_f;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const fisher_f_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const fisher_f_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
RealType pdf(const fisher_f_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType df1 = dist.degrees_of_freedom1();
RealType df2 = dist.degrees_of_freedom2();
// Error check:
RealType error_result;
static const char* function = "boost::math::pdf(fisher_f_distribution<%1%> const&, %1%)";
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if((x < 0) || !(boost::math::isfinite)(x))
{
return policies::raise_domain_error<RealType>(
function, "Random variable parameter was %1%, but must be > 0 !", x, Policy());
}
if(x == 0)
{
// special cases:
if(df1 < 2)
return policies::raise_overflow_error<RealType>(
function, 0, Policy());
else if(df1 == 2)
return 1;
else
return 0;
}
//
// You reach this formula by direct differentiation of the
// cdf expressed in terms of the incomplete beta.
//
// There are two versions so we don't pass a value of z
// that is very close to 1 to ibeta_derivative: for some values
// of df1 and df2, all the change takes place in this area.
//
RealType v1x = df1 * x;
RealType result;
if(v1x > df2)
{
result = (df2 * df1) / ((df2 + v1x) * (df2 + v1x));
result *= ibeta_derivative(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy());
}
else
{
result = df2 + df1 * x;
result = (result * df1 - x * df1 * df1) / (result * result);
result *= ibeta_derivative(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy());
}
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const fisher_f_distribution<RealType, Policy>& dist, const RealType& x)
{
static const char* function = "boost::math::cdf(fisher_f_distribution<%1%> const&, %1%)";
RealType df1 = dist.degrees_of_freedom1();
RealType df2 = dist.degrees_of_freedom2();
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if((x < 0) || !(boost::math::isfinite)(x))
{
return policies::raise_domain_error<RealType>(
function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy());
}
RealType v1x = df1 * x;
//
// There are two equivalent formulas used here, the aim is
// to prevent the final argument to the incomplete beta
// from being too close to 1: for some values of df1 and df2
// the rate of change can be arbitrarily large in this area,
// whilst the value we're passing will have lost information
// content as a result of being 0.999999something. Better
// to switch things around so we're passing 1-z instead.
//
return v1x > df2
? boost::math::ibetac(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy())
: boost::math::ibeta(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy());
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const fisher_f_distribution<RealType, Policy>& dist, const RealType& p)
{
static const char* function = "boost::math::quantile(fisher_f_distribution<%1%> const&, %1%)";
RealType df1 = dist.degrees_of_freedom1();
RealType df2 = dist.degrees_of_freedom2();
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy())
&& detail::check_probability(
function, p, &error_result, Policy()))
return error_result;
RealType x, y;
x = boost::math::ibeta_inv(df1 / 2, df2 / 2, p, &y, Policy());
return df2 * x / (df1 * y);
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<fisher_f_distribution<RealType, Policy>, RealType>& c)
{
static const char* function = "boost::math::cdf(fisher_f_distribution<%1%> const&, %1%)";
RealType df1 = c.dist.degrees_of_freedom1();
RealType df2 = c.dist.degrees_of_freedom2();
RealType x = c.param;
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if((x < 0) || !(boost::math::isfinite)(x))
{
return policies::raise_domain_error<RealType>(
function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy());
}
RealType v1x = df1 * x;
//
// There are two equivalent formulas used here, the aim is
// to prevent the final argument to the incomplete beta
// from being too close to 1: for some values of df1 and df2
// the rate of change can be arbitrarily large in this area,
// whilst the value we're passing will have lost information
// content as a result of being 0.999999something. Better
// to switch things around so we're passing 1-z instead.
//
return v1x > df2
? boost::math::ibeta(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy())
: boost::math::ibetac(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy());
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<fisher_f_distribution<RealType, Policy>, RealType>& c)
{
static const char* function = "boost::math::quantile(fisher_f_distribution<%1%> const&, %1%)";
RealType df1 = c.dist.degrees_of_freedom1();
RealType df2 = c.dist.degrees_of_freedom2();
RealType p = c.param;
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy())
&& detail::check_probability(
function, p, &error_result, Policy()))
return error_result;
RealType x, y;
x = boost::math::ibetac_inv(df1 / 2, df2 / 2, p, &y, Policy());
return df2 * x / (df1 * y);
}
template <class RealType, class Policy>
inline RealType mean(const fisher_f_distribution<RealType, Policy>& dist)
{ // Mean of F distribution = v.
static const char* function = "boost::math::mean(fisher_f_distribution<%1%> const&)";
RealType df1 = dist.degrees_of_freedom1();
RealType df2 = dist.degrees_of_freedom2();
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if(df2 <= 2)
{
return policies::raise_domain_error<RealType>(
function, "Second degree of freedom was %1% but must be > 2 in order for the distribution to have a mean.", df2, Policy());
}
return df2 / (df2 - 2);
} // mean
template <class RealType, class Policy>
inline RealType variance(const fisher_f_distribution<RealType, Policy>& dist)
{ // Variance of F distribution.
static const char* function = "boost::math::variance(fisher_f_distribution<%1%> const&)";
RealType df1 = dist.degrees_of_freedom1();
RealType df2 = dist.degrees_of_freedom2();
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if(df2 <= 4)
{
return policies::raise_domain_error<RealType>(
function, "Second degree of freedom was %1% but must be > 4 in order for the distribution to have a valid variance.", df2, Policy());
}
return 2 * df2 * df2 * (df1 + df2 - 2) / (df1 * (df2 - 2) * (df2 - 2) * (df2 - 4));
} // variance
template <class RealType, class Policy>
inline RealType mode(const fisher_f_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::mode(fisher_f_distribution<%1%> const&)";
RealType df1 = dist.degrees_of_freedom1();
RealType df2 = dist.degrees_of_freedom2();
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if(df2 <= 2)
{
return policies::raise_domain_error<RealType>(
function, "Second degree of freedom was %1% but must be > 2 in order for the distribution to have a mode.", df2, Policy());
}
return df2 * (df1 - 2) / (df1 * (df2 + 2));
}
//template <class RealType, class Policy>
//inline RealType median(const fisher_f_distribution<RealType, Policy>& dist)
//{ // Median of Fisher F distribution is not defined.
// return tools::domain_error<RealType>(BOOST_CURRENT_FUNCTION, "Median is not implemented, result is %1%!", std::numeric_limits<RealType>::quiet_NaN());
// } // median
// Now implemented via quantile(half) in derived accessors.
template <class RealType, class Policy>
inline RealType skewness(const fisher_f_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::skewness(fisher_f_distribution<%1%> const&)";
BOOST_MATH_STD_USING // ADL of std names
// See http://mathworld.wolfram.com/F-Distribution.html
RealType df1 = dist.degrees_of_freedom1();
RealType df2 = dist.degrees_of_freedom2();
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if(df2 <= 6)
{
return policies::raise_domain_error<RealType>(
function, "Second degree of freedom was %1% but must be > 6 in order for the distribution to have a skewness.", df2, Policy());
}
return 2 * (df2 + 2 * df1 - 2) * sqrt((2 * df2 - 8) / (df1 * (df2 + df1 - 2))) / (df2 - 6);
}
template <class RealType, class Policy>
RealType kurtosis_excess(const fisher_f_distribution<RealType, Policy>& dist);
template <class RealType, class Policy>
inline RealType kurtosis(const fisher_f_distribution<RealType, Policy>& dist)
{
return 3 + kurtosis_excess(dist);
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const fisher_f_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::kurtosis_excess(fisher_f_distribution<%1%> const&)";
// See http://mathworld.wolfram.com/F-Distribution.html
RealType df1 = dist.degrees_of_freedom1();
RealType df2 = dist.degrees_of_freedom2();
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if(df2 <= 8)
{
return policies::raise_domain_error<RealType>(
function, "Second degree of freedom was %1% but must be > 8 in order for the distribution to have a kutosis.", df2, Policy());
}
RealType df2_2 = df2 * df2;
RealType df1_2 = df1 * df1;
RealType n = -16 + 20 * df2 - 8 * df2_2 + df2_2 * df2 + 44 * df1 - 32 * df2 * df1 + 5 * df2_2 * df1 - 22 * df1_2 + 5 * df2 * df1_2;
n *= 12;
RealType d = df1 * (df2 - 6) * (df2 - 8) * (df1 + df2 - 2);
return n / d;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_DISTRIBUTIONS_FISHER_F_HPP

View File

@@ -0,0 +1,94 @@
// Copyright Paul A. Bristow 2007.
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_DISTRIBUTIONS_FWD_HPP
#define BOOST_MATH_DISTRIBUTIONS_FWD_HPP
namespace boost{ namespace math{
template <class RealType, class Policy>
class bernoulli_distribution;
template <class RealType, class Policy>
class beta_distribution;
template <class RealType, class Policy>
class binomial_distribution;
template <class RealType, class Policy>
class cauchy_distribution;
template <class RealType, class Policy>
class chi_squared_distribution;
template <class RealType, class Policy>
class exponential_distribution;
template <class RealType, class Policy>
class extreme_value_distribution;
template <class RealType, class Policy>
class fisher_f_distribution;
template <class RealType, class Policy>
class gamma_distribution;
template <class RealType, class Policy>
class lognormal_distribution;
template <class RealType, class Policy>
class negative_binomial_distribution;
template <class RealType, class Policy>
class normal_distribution;
template <class RealType, class Policy>
class pareto_distribution;
template <class RealType, class Policy>
class poisson_distribution;
template <class RealType, class Policy>
class rayleigh_distribution;
template <class RealType, class Policy>
class students_t_distribution;
template <class RealType, class Policy>
class triangular_distribution;
template <class RealType, class Policy>
class uniform_distribution;
template <class RealType, class Policy>
class weibull_distribution;
}} // namespaces
#define BOOST_MATH_DECLARE_DISTRIBUTIONS(Type, Policy)\
typedef boost::math::bernoulli_distribution<Type, Policy> bernoulli;\
typedef boost::math::beta_distribution<Type, Policy> beta;\
typedef boost::math::binomial_distribution<Type, Policy> binomial;\
typedef boost::math::cauchy_distribution<Type, Policy> cauchy;\
typedef boost::math::chi_squared_distribution<Type, Policy> chi_squared;\
typedef boost::math::exponential_distribution<Type, Policy> exponential;\
typedef boost::math::extreme_value_distribution<Type, Policy> extreme_value;\
typedef boost::math::fisher_f_distribution<Type, Policy> fisher_f;\
typedef boost::math::gamma_distribution<Type, Policy> gamma;\
typedef boost::math::lognormal_distribution<Type, Policy> lognormal;\
typedef boost::math::negative_binomial_distribution<Type, Policy> negative_binomial;\
typedef boost::math::normal_distribution<Type, Policy> normal;\
typedef boost::math::pareto_distribution<Type, Policy> pareto;\
typedef boost::math::poisson_distribution<Type, Policy> poisson;\
typedef boost::math::rayleigh_distribution<Type, Policy> rayleigh;\
typedef boost::math::students_t_distribution<Type, Policy> students_t;\
typedef boost::math::triangular_distribution<Type, Policy> triangular;\
typedef boost::math::uniform_distribution<Type, Policy> uniform;\
typedef boost::math::weibull_distribution<Type, Policy> weibull;\
#endif // BOOST_MATH_DISTRIBUTIONS_FWD_HPP

View File

@@ -0,0 +1,348 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_GAMMA_HPP
#define BOOST_STATS_GAMMA_HPP
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda366b.htm
// http://mathworld.wolfram.com/GammaDistribution.html
// http://en.wikipedia.org/wiki/Gamma_distribution
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
#include <utility>
namespace boost{ namespace math
{
namespace detail
{
template <class RealType, class Policy>
inline bool check_gamma_shape(
const char* function,
RealType shape,
RealType* result, const Policy& pol)
{
if((shape <= 0) || !(boost::math::isfinite)(shape))
{
*result = policies::raise_domain_error<RealType>(
function,
"Shape parameter is %1%, but must be > 0 !", shape, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_gamma_x(
const char* function,
RealType const& x,
RealType* result, const Policy& pol)
{
if((x < 0) || !(boost::math::isfinite)(x))
{
*result = policies::raise_domain_error<RealType>(
function,
"Random variate is %1% but must be >= 0 !", x, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_gamma(
const char* function,
RealType scale,
RealType shape,
RealType* result, const Policy& pol)
{
return check_scale(function, scale, result, pol) && check_gamma_shape(function, shape, result, pol);
}
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class gamma_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
gamma_distribution(RealType shape, RealType scale = 1)
: m_shape(shape), m_scale(scale)
{
RealType result;
detail::check_gamma("boost::math::gamma_distribution<%1%>::gamma_distribution", scale, shape, &result, Policy());
}
RealType shape()const
{
return m_shape;
}
RealType scale()const
{
return m_scale;
}
private:
//
// Data members:
//
RealType m_shape; // distribution shape
RealType m_scale; // distribution scale
};
// NO typedef because of clash with name of gamma function.
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const gamma_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const gamma_distribution<RealType, Policy>& /* dist */)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType pdf(const gamma_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::pdf(const gamma_distribution<%1%>&, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_gamma_x(function, x, &result, Policy()))
return result;
if(x == 0)
{
return 0;
}
result = gamma_p_derivative(shape, x / scale, Policy()) / scale;
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const gamma_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(const gamma_distribution<%1%>&, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_gamma_x(function, x, &result, Policy()))
return result;
result = boost::math::gamma_p(shape, x / scale, Policy());
return result;
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const gamma_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const gamma_distribution<%1%>&, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_probability(function, p, &result, Policy()))
return result;
if(p == 1)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
result = gamma_p_inv(shape, p, Policy()) * scale;
return result;
}
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<gamma_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const gamma_distribution<%1%>&, %1%)";
RealType shape = c.dist.shape();
RealType scale = c.dist.scale();
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_gamma_x(function, c.param, &result, Policy()))
return result;
result = gamma_q(shape, c.param / scale, Policy());
return result;
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<gamma_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const gamma_distribution<%1%>&, %1%)";
RealType shape = c.dist.shape();
RealType scale = c.dist.scale();
RealType q = c.param;
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_probability(function, q, &result, Policy()))
return result;
if(q == 0)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
result = gamma_q_inv(shape, q, Policy()) * scale;
return result;
}
template <class RealType, class Policy>
inline RealType mean(const gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::mean(const gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
result = shape * scale;
return result;
}
template <class RealType, class Policy>
inline RealType variance(const gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::variance(const gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
result = shape * scale * scale;
return result;
}
template <class RealType, class Policy>
inline RealType mode(const gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::mode(const gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
if(shape < 1)
return policies::raise_domain_error<RealType>(
function,
"The mode of the gamma distribution is only defined for values of the shape parameter >= 1, but got %1%.",
shape, Policy());
result = (shape - 1) * scale;
return result;
}
//template <class RealType, class Policy>
//inline RealType median(const gamma_distribution<RealType, Policy>& dist)
//{ // Rely on default definition in derived accessors.
//}
template <class RealType, class Policy>
inline RealType skewness(const gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::skewness(const gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
result = 2 / sqrt(shape);
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::kurtosis_excess(const gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
result = 6 / shape;
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis(const gamma_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_GAMMA_HPP

View File

@@ -0,0 +1,310 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_LOGNORMAL_HPP
#define BOOST_STATS_LOGNORMAL_HPP
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3669.htm
// http://mathworld.wolfram.com/LogNormalDistribution.html
// http://en.wikipedia.org/wiki/Lognormal_distribution
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/distributions/normal.hpp>
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <utility>
namespace boost{ namespace math
{
namespace detail
{
template <class RealType, class Policy>
inline bool check_lognormal_x(
const char* function,
RealType const& x,
RealType* result, const Policy& pol)
{
if((x < 0) || !(boost::math::isfinite)(x))
{
*result = policies::raise_domain_error<RealType>(
function,
"Random variate is %1% but must be >= 0 !", x, pol);
return false;
}
return true;
}
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class lognormal_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
lognormal_distribution(RealType location = 0, RealType scale = 1)
: m_location(location), m_scale(scale)
{
RealType result;
detail::check_scale("boost::math::lognormal_distribution<%1%>::lognormal_distribution", scale, &result, Policy());
}
RealType location()const
{
return m_location;
}
RealType scale()const
{
return m_scale;
}
private:
//
// Data members:
//
RealType m_location; // distribution location.
RealType m_scale; // distribution scale.
};
typedef lognormal_distribution<double> lognormal;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const lognormal_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x is >0 to +infinity.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const lognormal_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
RealType pdf(const lognormal_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType mu = dist.location();
RealType sigma = dist.scale();
static const char* function = "boost::math::pdf(const lognormal_distribution<%1%>&, %1%)";
RealType result;
if(0 == detail::check_scale(function, sigma, &result, Policy()))
return result;
if(0 == detail::check_lognormal_x(function, x, &result, Policy()))
return result;
if(x == 0)
return 0;
RealType exponent = log(x) - mu;
exponent *= -exponent;
exponent /= 2 * sigma * sigma;
result = exp(exponent);
result /= sigma * sqrt(2 * constants::pi<RealType>()) * x;
return result;
}
template <class RealType, class Policy>
inline RealType cdf(const lognormal_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(const lognormal_distribution<%1%>&, %1%)";
RealType result;
if(0 == detail::check_lognormal_x(function, x, &result, Policy()))
return result;
if(x == 0)
return 0;
normal_distribution<RealType, Policy> norm(dist.location(), dist.scale());
return cdf(norm, log(x));
}
template <class RealType, class Policy>
inline RealType quantile(const lognormal_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const lognormal_distribution<%1%>&, %1%)";
RealType result;
if(0 == detail::check_probability(function, p, &result, Policy()))
return result;
if(p == 0)
return 0;
if(p == 1)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
normal_distribution<RealType, Policy> norm(dist.location(), dist.scale());
return exp(quantile(norm, p));
}
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<lognormal_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(const lognormal_distribution<%1%>&, %1%)";
RealType result;
if(0 == detail::check_lognormal_x(function, c.param, &result, Policy()))
return result;
if(c.param == 0)
return 1;
normal_distribution<RealType, Policy> norm(c.dist.location(), c.dist.scale());
return cdf(complement(norm, log(c.param)));
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<lognormal_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const lognormal_distribution<%1%>&, %1%)";
RealType result;
if(0 == detail::check_probability(function, c.param, &result, Policy()))
return result;
if(c.param == 1)
return 0;
if(c.param == 0)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
normal_distribution<RealType, Policy> norm(c.dist.location(), c.dist.scale());
return exp(quantile(complement(norm, c.param)));
}
template <class RealType, class Policy>
inline RealType mean(const lognormal_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType mu = dist.location();
RealType sigma = dist.scale();
RealType result;
if(0 == detail::check_scale("boost::math::mean(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
return exp(mu + sigma * sigma / 2);
}
template <class RealType, class Policy>
inline RealType variance(const lognormal_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType mu = dist.location();
RealType sigma = dist.scale();
RealType result;
if(0 == detail::check_scale("boost::math::variance(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
return boost::math::expm1(sigma * sigma, Policy()) * exp(2 * mu + sigma * sigma);
}
template <class RealType, class Policy>
inline RealType mode(const lognormal_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType mu = dist.location();
RealType sigma = dist.scale();
RealType result;
if(0 == detail::check_scale("boost::math::mode(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
return exp(mu - sigma * sigma);
}
template <class RealType, class Policy>
inline RealType median(const lognormal_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType mu = dist.location();
return exp(mu); // e^mu
}
template <class RealType, class Policy>
inline RealType skewness(const lognormal_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
//RealType mu = dist.location();
RealType sigma = dist.scale();
RealType ss = sigma * sigma;
RealType ess = exp(ss);
RealType result;
if(0 == detail::check_scale("boost::math::skewness(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
return (ess + 2) * sqrt(boost::math::expm1(ss, Policy()));
}
template <class RealType, class Policy>
inline RealType kurtosis(const lognormal_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
//RealType mu = dist.location();
RealType sigma = dist.scale();
RealType ss = sigma * sigma;
RealType result;
if(0 == detail::check_scale("boost::math::kurtosis(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 3;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const lognormal_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
// RealType mu = dist.location();
RealType sigma = dist.scale();
RealType ss = sigma * sigma;
RealType result;
if(0 == detail::check_scale("boost::math::kurtosis_excess(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 6;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_STUDENTS_T_HPP

View File

@@ -0,0 +1,588 @@
// boost\math\special_functions\negative_binomial.hpp
// Copyright Paul A. Bristow 2007.
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// http://en.wikipedia.org/wiki/negative_binomial_distribution
// http://mathworld.wolfram.com/NegativeBinomialDistribution.html
// http://documents.wolfram.com/teachersedition/Teacher/Statistics/DiscreteDistributions.html
// The negative binomial distribution NegativeBinomialDistribution[n, p]
// is the distribution of the number (k) of failures that occur in a sequence of trials before
// r successes have occurred, where the probability of success in each trial is p.
// In a sequence of Bernoulli trials or events
// (independent, yes or no, succeed or fail) with success_fraction probability p,
// negative_binomial is the probability that k or fewer failures
// preceed the r th trial's success.
// random variable k is the number of failures (NOT the probability).
// Negative_binomial distribution is a discrete probability distribution.
// But note that the negative binomial distribution
// (like others including the binomial, Poisson & Bernoulli)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as if a continous function,
// and permit non-integral values of k.
// However, by default the policy is to use discrete_quantile_policy.
// To enforce the strict mathematical model, users should use conversion
// on k outside this function to ensure that k is integral.
// MATHCAD cumulative negative binomial pnbinom(k, n, p)
// Implementation note: much greater speed, and perhaps greater accuracy,
// might be achieved for extreme values by using a normal approximation.
// This is NOT been tested or implemented.
#ifndef BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP
#define BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/beta.hpp> // for ibeta(a, b, x) == Ix(a, b).
#include <boost/math/distributions/complement.hpp> // complement.
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks domain_error & logic_error.
#include <boost/math/special_functions/fpclassify.hpp> // isnan.
#include <boost/math/tools/roots.hpp> // for root finding.
#include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/if.hpp>
#include <limits> // using std::numeric_limits;
#include <utility>
#if defined (BOOST_MSVC)
# pragma warning(push)
// This believed not now necessary, so commented out.
//# pragma warning(disable: 4702) // unreachable code.
// in domain_error_imp in error_handling.
#endif
namespace boost
{
namespace math
{
namespace negative_binomial_detail
{
// Common error checking routines for negative binomial distribution functions:
template <class RealType, class Policy>
inline bool check_successes(const char* function, const RealType& r, RealType* result, const Policy& pol)
{
if( !(boost::math::isfinite)(r) || (r <= 0) )
{
*result = policies::raise_domain_error<RealType>(
function,
"Number of successes argument is %1%, but must be > 0 !", r, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& pol)
{
if( !(boost::math::isfinite)(p) || (p < 0) || (p > 1) )
{
*result = policies::raise_domain_error<RealType>(
function,
"Success fraction argument is %1%, but must be >= 0 and <= 1 !", p, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_dist(const char* function, const RealType& r, const RealType& p, RealType* result, const Policy& pol)
{
return check_success_fraction(function, p, result, pol)
&& check_successes(function, r, result, pol);
}
template <class RealType, class Policy>
inline bool check_dist_and_k(const char* function, const RealType& r, const RealType& p, RealType k, RealType* result, const Policy& pol)
{
if(check_dist(function, r, p, result, pol) == false)
{
return false;
}
if( !(boost::math::isfinite)(k) || (k < 0) )
{ // Check k failures.
*result = policies::raise_domain_error<RealType>(
function,
"Number of failures argument is %1%, but must be >= 0 !", k, pol);
return false;
}
return true;
} // Check_dist_and_k
template <class RealType, class Policy>
inline bool check_dist_and_prob(const char* function, const RealType& r, RealType p, RealType prob, RealType* result, const Policy& pol)
{
if(check_dist(function, r, p, result, pol) && detail::check_probability(function, prob, result, pol) == false)
{
return false;
}
return true;
} // check_dist_and_prob
} // namespace negative_binomial_detail
template <class RealType = double, class Policy = policies::policy<> >
class negative_binomial_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
negative_binomial_distribution(RealType r, RealType p) : m_r(r), m_p(p)
{ // Constructor.
RealType result;
negative_binomial_detail::check_dist(
"negative_binomial_distribution<%1%>::negative_binomial_distribution",
m_r, // Check successes r > 0.
m_p, // Check success_fraction 0 <= p <= 1.
&result, Policy());
} // negative_binomial_distribution constructor.
// Private data getter class member functions.
RealType success_fraction() const
{ // Probability of success as fraction in range 0 to 1.
return m_p;
}
RealType successes() const
{ // Total number of successes r.
return m_r;
}
static RealType find_lower_bound_on_p(
RealType trials,
RealType successes,
RealType alpha) // alpha 0.05 equivalent to 95% for one-sided test.
{
static const char* function = "boost::math::negative_binomial<%1%>::find_lower_bound_on_p";
RealType result; // of error checks.
RealType failures = trials - successes;
if(false == detail::check_probability(function, alpha, &result, Policy())
&& negative_binomial_detail::check_dist_and_k(
function, successes, RealType(0), failures, &result, Policy()))
{
return result;
}
// Use complement ibeta_inv function for lower bound.
// This is adapted from the corresponding binomial formula
// here: http://www.itl.nist.gov/div898/handbook/prc/section2/prc241.htm
// This is a Clopper-Pearson interval, and may be overly conservative,
// see also "A Simple Improved Inferential Method for Some
// Discrete Distributions" Yong CAI and K. KRISHNAMOORTHY
// http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf
//
return ibeta_inv(successes, failures + 1, alpha, static_cast<RealType*>(0), Policy());
} // find_lower_bound_on_p
static RealType find_upper_bound_on_p(
RealType trials,
RealType successes,
RealType alpha) // alpha 0.05 equivalent to 95% for one-sided test.
{
static const char* function = "boost::math::negative_binomial<%1%>::find_upper_bound_on_p";
RealType result; // of error checks.
RealType failures = trials - successes;
if(false == negative_binomial_detail::check_dist_and_k(
function, successes, RealType(0), failures, &result, Policy())
&& detail::check_probability(function, alpha, &result, Policy()))
{
return result;
}
if(failures == 0)
return 1;
// Use complement ibetac_inv function for upper bound.
// Note adjusted failures value: *not* failures+1 as usual.
// This is adapted from the corresponding binomial formula
// here: http://www.itl.nist.gov/div898/handbook/prc/section2/prc241.htm
// This is a Clopper-Pearson interval, and may be overly conservative,
// see also "A Simple Improved Inferential Method for Some
// Discrete Distributions" Yong CAI and K. KRISHNAMOORTHY
// http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf
//
return ibetac_inv(successes, failures, alpha, static_cast<RealType*>(0), Policy());
} // find_upper_bound_on_p
// Estimate number of trials :
// "How many trials do I need to be P% sure of seeing k or fewer failures?"
static RealType find_minimum_number_of_trials(
RealType k, // number of failures (k >= 0).
RealType p, // success fraction 0 <= p <= 1.
RealType alpha) // risk level threshold 0 <= alpha <= 1.
{
static const char* function = "boost::math::negative_binomial<%1%>::find_minimum_number_of_trials";
// Error checks:
RealType result;
if(false == negative_binomial_detail::check_dist_and_k(
function, RealType(1), p, k, &result, Policy())
&& detail::check_probability(function, alpha, &result, Policy()))
{ return result; }
result = ibeta_inva(k + 1, p, alpha, Policy()); // returns n - k
return result + k;
} // RealType find_number_of_failures
static RealType find_maximum_number_of_trials(
RealType k, // number of failures (k >= 0).
RealType p, // success fraction 0 <= p <= 1.
RealType alpha) // risk level threshold 0 <= alpha <= 1.
{
static const char* function = "boost::math::negative_binomial<%1%>::find_maximum_number_of_trials";
// Error checks:
RealType result;
if(false == negative_binomial_detail::check_dist_and_k(
function, RealType(1), p, k, &result, Policy())
&& detail::check_probability(function, alpha, &result, Policy()))
{ return result; }
result = ibetac_inva(k + 1, p, alpha, Policy()); // returns n - k
return result + k;
} // RealType find_number_of_trials complemented
private:
RealType m_r; // successes.
RealType m_p; // success_fraction
}; // template <class RealType, class Policy> class negative_binomial_distribution
typedef negative_binomial_distribution<double> negative_binomial; // Reserved name of type double.
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const negative_binomial_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable k.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>()); // max_integer?
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const negative_binomial_distribution<RealType, Policy>& /* dist */)
{ // Range of supported values for random variable k.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>()); // max_integer?
}
template <class RealType, class Policy>
inline RealType mean(const negative_binomial_distribution<RealType, Policy>& dist)
{ // Mean of Negative Binomial distribution = r(1-p)/p.
return dist.successes() * (1 - dist.success_fraction() ) / dist.success_fraction();
} // mean
//template <class RealType, class Policy>
//inline RealType median(const negative_binomial_distribution<RealType, Policy>& dist)
//{ // Median of negative_binomial_distribution is not defined.
// return policies::raise_domain_error<RealType>(BOOST_CURRENT_FUNCTION, "Median is not implemented, result is %1%!", std::numeric_limits<RealType>::quiet_NaN());
//} // median
// Now implemented via quantile(half) in derived accessors.
template <class RealType, class Policy>
inline RealType mode(const negative_binomial_distribution<RealType, Policy>& dist)
{ // Mode of Negative Binomial distribution = floor[(r-1) * (1 - p)/p]
BOOST_MATH_STD_USING // ADL of std functions.
return floor((dist.successes() -1) * (1 - dist.success_fraction()) / dist.success_fraction());
} // mode
template <class RealType, class Policy>
inline RealType skewness(const negative_binomial_distribution<RealType, Policy>& dist)
{ // skewness of Negative Binomial distribution = 2-p / (sqrt(r(1-p))
BOOST_MATH_STD_USING // ADL of std functions.
RealType p = dist.success_fraction();
RealType r = dist.successes();
return (2 - p) /
sqrt(r * (1 - p));
} // skewness
template <class RealType, class Policy>
inline RealType kurtosis(const negative_binomial_distribution<RealType, Policy>& dist)
{ // kurtosis of Negative Binomial distribution
// http://en.wikipedia.org/wiki/Negative_binomial is kurtosis_excess so add 3
RealType p = dist.success_fraction();
RealType r = dist.successes();
return 3 + (6 / r) + ((p * p) / (r * (1 - p)));
} // kurtosis
template <class RealType, class Policy>
inline RealType kurtosis_excess(const negative_binomial_distribution<RealType, Policy>& dist)
{ // kurtosis excess of Negative Binomial distribution
// http://mathworld.wolfram.com/Kurtosis.html table of kurtosis_excess
RealType p = dist.success_fraction();
RealType r = dist.successes();
return (6 - p * (6-p)) / (r * (1-p));
} // kurtosis_excess
template <class RealType, class Policy>
inline RealType variance(const negative_binomial_distribution<RealType, Policy>& dist)
{ // Variance of Binomial distribution = r (1-p) / p^2.
return dist.successes() * (1 - dist.success_fraction())
/ (dist.success_fraction() * dist.success_fraction());
} // variance
// RealType standard_deviation(const negative_binomial_distribution<RealType, Policy>& dist)
// standard_deviation provided by derived accessors.
// RealType hazard(const negative_binomial_distribution<RealType, Policy>& dist)
// hazard of Negative Binomial distribution provided by derived accessors.
// RealType chf(const negative_binomial_distribution<RealType, Policy>& dist)
// chf of Negative Binomial distribution provided by derived accessors.
template <class RealType, class Policy>
inline RealType pdf(const negative_binomial_distribution<RealType, Policy>& dist, const RealType k)
{ // Probability Density/Mass Function.
BOOST_FPU_EXCEPTION_GUARD
static const char* function = "boost::math::pdf(const negative_binomial_distribution<%1%>&, %1%)";
RealType r = dist.successes();
RealType p = dist.success_fraction();
RealType result;
if(false == negative_binomial_detail::check_dist_and_k(
function,
r,
dist.success_fraction(),
k,
&result, Policy()))
{
return result;
}
result = (p/(r + k)) * ibeta_derivative(r, static_cast<RealType>(k+1), p, Policy());
// Equivalent to:
// return exp(lgamma(r + k) - lgamma(r) - lgamma(k+1)) * pow(p, r) * pow((1-p), k);
return result;
} // negative_binomial_pdf
template <class RealType, class Policy>
inline RealType cdf(const negative_binomial_distribution<RealType, Policy>& dist, const RealType k)
{ // Cumulative Distribution Function of Negative Binomial.
static const char* function = "boost::math::cdf(const negative_binomial_distribution<%1%>&, %1%)";
using boost::math::ibeta; // Regularized incomplete beta function.
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
RealType p = dist.success_fraction();
RealType r = dist.successes();
// Error check:
RealType result;
if(false == negative_binomial_detail::check_dist_and_k(
function,
r,
dist.success_fraction(),
k,
&result, Policy()))
{
return result;
}
RealType probability = ibeta(r, static_cast<RealType>(k+1), p, Policy());
// Ip(r, k+1) = ibeta(r, k+1, p)
return probability;
} // cdf Cumulative Distribution Function Negative Binomial.
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<negative_binomial_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function Negative Binomial.
static const char* function = "boost::math::cdf(const negative_binomial_distribution<%1%>&, %1%)";
using boost::math::ibetac; // Regularized incomplete beta function complement.
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
RealType const& k = c.param;
negative_binomial_distribution<RealType, Policy> const& dist = c.dist;
RealType p = dist.success_fraction();
RealType r = dist.successes();
// Error check:
RealType result;
if(false == negative_binomial_detail::check_dist_and_k(
function,
r,
p,
k,
&result, Policy()))
{
return result;
}
// Calculate cdf negative binomial using the incomplete beta function.
// Use of ibeta here prevents cancellation errors in calculating
// 1-p if p is very small, perhaps smaller than machine epsilon.
// Ip(k+1, r) = ibetac(r, k+1, p)
// constrain_probability here?
RealType probability = ibetac(r, static_cast<RealType>(k+1), p, Policy());
// Numerical errors might cause probability to be slightly outside the range < 0 or > 1.
// This might cause trouble downstream, so warn, possibly throw exception, but constrain to the limits.
return probability;
} // cdf Cumulative Distribution Function Negative Binomial.
template <class RealType, class Policy>
inline RealType quantile(const negative_binomial_distribution<RealType, Policy>& dist, const RealType& P)
{ // Quantile, percentile/100 or Percent Point Negative Binomial function.
// Return the number of expected failures k for a given probability p.
// Inverse cumulative Distribution Function or Quantile (percentile / 100) of negative_binomial Probability.
// MAthCAD pnbinom return smallest k such that negative_binomial(k, n, p) >= probability.
// k argument may be integral, signed, or unsigned, or floating point.
// BUT Cephes/CodeCogs says: finds argument p (0 to 1) such that cdf(k, n, p) = y
static const char* function = "boost::math::quantile(const negative_binomial_distribution<%1%>&, %1%)";
BOOST_MATH_STD_USING // ADL of std functions.
RealType p = dist.success_fraction();
RealType r = dist.successes();
// Check dist and P.
RealType result;
if(false == negative_binomial_detail::check_dist_and_prob
(function, r, p, P, &result, Policy()))
{
return result;
}
// Special cases.
if (P == 1)
{ // Would need +infinity failures for total confidence.
result = policies::raise_overflow_error<RealType>(
function,
"Probability argument is 1, which implies infinite failures !", Policy());
return result;
// usually means return +std::numeric_limits<RealType>::infinity();
// unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
}
if (P == 0)
{ // No failures are expected if P = 0.
return 0; // Total trials will be just dist.successes.
}
if (P <= pow(dist.success_fraction(), dist.successes()))
{ // p <= pdf(dist, 0) == cdf(dist, 0)
return 0;
}
/*
// Calculate quantile of negative_binomial using the inverse incomplete beta function.
using boost::math::ibeta_invb;
return ibeta_invb(r, p, P, Policy()) - 1; //
*/
RealType guess = 0;
RealType factor = 5;
if(r * r * r * P * p > 0.005)
guess = detail::inverse_negative_binomial_cornish_fisher(r, p, 1-p, P, 1-P, Policy());
if(guess < 10)
{
//
// Cornish-Fisher Negative binomial approximation not accurate in this area:
//
guess = (std::min)(r * 2, RealType(10));
}
else
factor = (1-P < sqrt(tools::epsilon<RealType>())) ? 2 : (guess < 20 ? 1.2f : 1.1f);
BOOST_MATH_INSTRUMENT_CODE("guess = " << guess);
//
// Max iterations permitted:
//
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
typedef typename Policy::discrete_quantile_type discrete_type;
return detail::inverse_discrete_quantile(
dist,
P,
1-P,
guess,
factor,
RealType(1),
discrete_type(),
max_iter);
} // RealType quantile(const negative_binomial_distribution dist, p)
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<negative_binomial_distribution<RealType, Policy>, RealType>& c)
{ // Quantile or Percent Point Binomial function.
// Return the number of expected failures k for a given
// complement of the probability Q = 1 - P.
static const char* function = "boost::math::quantile(const negative_binomial_distribution<%1%>&, %1%)";
BOOST_MATH_STD_USING
// Error checks:
RealType Q = c.param;
const negative_binomial_distribution<RealType, Policy>& dist = c.dist;
RealType p = dist.success_fraction();
RealType r = dist.successes();
RealType result;
if(false == negative_binomial_detail::check_dist_and_prob(
function,
r,
p,
Q,
&result, Policy()))
{
return result;
}
// Special cases:
//
if(Q == 1)
{ // There may actually be no answer to this question,
// since the probability of zero failures may be non-zero,
return 0; // but zero is the best we can do:
}
if (-Q <= powm1(dist.success_fraction(), dist.successes(), Policy()))
{ // q <= cdf(complement(dist, 0)) == pdf(dist, 0)
return 0; //
}
if(Q == 0)
{ // Probability 1 - Q == 1 so infinite failures to achieve certainty.
// Would need +infinity failures for total confidence.
result = policies::raise_overflow_error<RealType>(
function,
"Probability argument complement is 0, which implies infinite failures !", Policy());
return result;
// usually means return +std::numeric_limits<RealType>::infinity();
// unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
}
//return ibetac_invb(r, p, Q, Policy()) -1;
RealType guess = 0;
RealType factor = 5;
if(r * r * r * (1-Q) * p > 0.005)
guess = detail::inverse_negative_binomial_cornish_fisher(r, p, 1-p, 1-Q, Q, Policy());
if(guess < 10)
{
//
// Cornish-Fisher Negative binomial approximation not accurate in this area:
//
guess = (std::min)(r * 2, RealType(10));
}
else
factor = (Q < sqrt(tools::epsilon<RealType>())) ? 2 : (guess < 20 ? 1.2f : 1.1f);
BOOST_MATH_INSTRUMENT_CODE("guess = " << guess);
//
// Max iterations permitted:
//
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
typedef typename Policy::discrete_quantile_type discrete_type;
return detail::inverse_discrete_quantile(
dist,
1-Q,
Q,
guess,
factor,
RealType(1),
discrete_type(),
max_iter);
} // quantile complement
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#if defined (BOOST_MSVC)
# pragma warning(pop)
#endif
#endif // BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP

View File

@@ -0,0 +1,308 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2006, 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_NORMAL_HPP
#define BOOST_STATS_NORMAL_HPP
// http://en.wikipedia.org/wiki/Normal_distribution
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3661.htm
// Also:
// Weisstein, Eric W. "Normal Distribution."
// From MathWorld--A Wolfram Web Resource.
// http://mathworld.wolfram.com/NormalDistribution.html
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/erf.hpp> // for erf/erfc.
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <utility>
namespace boost{ namespace math{
template <class RealType = double, class Policy = policies::policy<> >
class normal_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
normal_distribution(RealType mean = 0, RealType sd = 1)
: m_mean(mean), m_sd(sd)
{ // Default is a 'standard' normal distribution N01.
static const char* function = "boost::math::normal_distribution<%1%>::normal_distribution";
RealType result;
detail::check_scale(function, sd, &result, Policy());
detail::check_location(function, mean, &result, Policy());
}
RealType mean()const
{ // alias for location.
return m_mean;
}
RealType standard_deviation()const
{ // alias for scale.
return m_sd;
}
// Synonyms, provided to allow generic use of find_location and find_scale.
RealType location()const
{ // location.
return m_mean;
}
RealType scale()const
{ // scale.
return m_sd;
}
private:
//
// Data members:
//
RealType m_mean; // distribution mean or location.
RealType m_sd; // distribution standard deviation or scale.
}; // class normal_distribution
typedef normal_distribution<double> normal;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const normal_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const normal_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
}
template <class RealType, class Policy>
inline RealType pdf(const normal_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType sd = dist.standard_deviation();
RealType mean = dist.mean();
static const char* function = "boost::math::pdf(const normal_distribution<%1%>&, %1%)";
if((boost::math::isinf)(x))
{
return 0; // pdf + and - infinity is zero.
}
// Theis produces MSVC 4127 warnings, so the above used instead.
//if(std::numeric_limits<RealType>::has_infinity && abs(x) == std::numeric_limits<RealType>::infinity())
//{ // pdf + and - infinity is zero.
// return 0;
//}
RealType result;
if(false == detail::check_scale(function, sd, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, mean, &result, Policy()))
{
return result;
}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
}
RealType exponent = x - mean;
exponent *= -exponent;
exponent /= 2 * sd * sd;
result = exp(exponent);
result /= sd * sqrt(2 * constants::pi<RealType>());
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const normal_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType sd = dist.standard_deviation();
RealType mean = dist.mean();
static const char* function = "boost::math::cdf(const normal_distribution<%1%>&, %1%)";
RealType result;
if(false == detail::check_scale(function, sd, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, mean, &result, Policy()))
{
return result;
}
if((boost::math::isinf)(x))
{
if(x < 0) return 0; // -infinity
return 1; // + infinity
}
// These produce MSVC 4127 warnings, so the above used instead.
//if(std::numeric_limits<RealType>::has_infinity && x == std::numeric_limits<RealType>::infinity())
//{ // cdf +infinity is unity.
// return 1;
//}
//if(std::numeric_limits<RealType>::has_infinity && x == -std::numeric_limits<RealType>::infinity())
//{ // cdf -infinity is zero.
// return 0;
//}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
}
RealType diff = (x - mean) / (sd * constants::root_two<RealType>());
result = boost::math::erfc(-diff, Policy()) / 2;
return result;
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const normal_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType sd = dist.standard_deviation();
RealType mean = dist.mean();
static const char* function = "boost::math::quantile(const normal_distribution<%1%>&, %1%)";
RealType result;
if(false == detail::check_scale(function, sd, &result, Policy()))
return result;
if(false == detail::check_location(function, mean, &result, Policy()))
return result;
if(false == detail::check_probability(function, p, &result, Policy()))
return result;
result= boost::math::erfc_inv(2 * p, Policy());
result = -result;
result *= sd * constants::root_two<RealType>();
result += mean;
return result;
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<normal_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType sd = c.dist.standard_deviation();
RealType mean = c.dist.mean();
RealType x = c.param;
static const char* function = "boost::math::cdf(const complement(normal_distribution<%1%>&), %1%)";
if((boost::math::isinf)(x))
{
if(x < 0) return 1; // cdf complement -infinity is unity.
return 0; // cdf complement +infinity is zero
}
// These produce MSVC 4127 warnings, so the above used instead.
//if(std::numeric_limits<RealType>::has_infinity && x == std::numeric_limits<RealType>::infinity())
//{ // cdf complement +infinity is zero.
// return 0;
//}
//if(std::numeric_limits<RealType>::has_infinity && x == -std::numeric_limits<RealType>::infinity())
//{ // cdf complement -infinity is unity.
// return 1;
//}
RealType result;
if(false == detail::check_scale(function, sd, &result, Policy()))
return result;
if(false == detail::check_location(function, mean, &result, Policy()))
return result;
if(false == detail::check_x(function, x, &result, Policy()))
return result;
RealType diff = (x - mean) / (sd * constants::root_two<RealType>());
result = boost::math::erfc(diff, Policy()) / 2;
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<normal_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType sd = c.dist.standard_deviation();
RealType mean = c.dist.mean();
static const char* function = "boost::math::quantile(const complement(normal_distribution<%1%>&), %1%)";
RealType result;
if(false == detail::check_scale(function, sd, &result, Policy()))
return result;
if(false == detail::check_location(function, mean, &result, Policy()))
return result;
RealType q = c.param;
if(false == detail::check_probability(function, q, &result, Policy()))
return result;
result = boost::math::erfc_inv(2 * q, Policy());
result *= sd * constants::root_two<RealType>();
result += mean;
return result;
} // quantile
template <class RealType, class Policy>
inline RealType mean(const normal_distribution<RealType, Policy>& dist)
{
return dist.mean();
}
template <class RealType, class Policy>
inline RealType standard_deviation(const normal_distribution<RealType, Policy>& dist)
{
return dist.standard_deviation();
}
template <class RealType, class Policy>
inline RealType mode(const normal_distribution<RealType, Policy>& dist)
{
return dist.mean();
}
template <class RealType, class Policy>
inline RealType median(const normal_distribution<RealType, Policy>& dist)
{
return dist.mean();
}
template <class RealType, class Policy>
inline RealType skewness(const normal_distribution<RealType, Policy>& /*dist*/)
{
return 0;
}
template <class RealType, class Policy>
inline RealType kurtosis(const normal_distribution<RealType, Policy>& /*dist*/)
{
return 3;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const normal_distribution<RealType, Policy>& /*dist*/)
{
return 0;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_NORMAL_HPP

View File

@@ -0,0 +1,443 @@
// Copyright John Maddock 2007.
// Copyright Paul A. Bristow 2007
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_PARETO_HPP
#define BOOST_STATS_PARETO_HPP
// http://en.wikipedia.org/wiki/Pareto_distribution
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3661.htm
// Also:
// Weisstein, Eric W. "Pareto Distribution."
// From MathWorld--A Wolfram Web Resource.
// http://mathworld.wolfram.com/ParetoDistribution.html
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/special_functions/powm1.hpp>
#include <utility> // for BOOST_CURRENT_VALUE?
namespace boost
{
namespace math
{
namespace detail
{ // Parameter checking.
template <class RealType, class Policy>
inline bool check_pareto_location(
const char* function,
RealType location,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(location))
{ // any > 0 finite value is OK.
if (location > 0)
{
return true;
}
else
{
*result = policies::raise_domain_error<RealType>(
function,
"Location parameter is %1%, but must be > 0!", location, pol);
return false;
}
}
else
{ // Not finite.
*result = policies::raise_domain_error<RealType>(
function,
"Location parameter is %1%, but must be finite!", location, pol);
return false;
}
} // bool check_pareto_location
template <class RealType, class Policy>
inline bool check_pareto_shape(
const char* function,
RealType shape,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(shape))
{ // Any finite value > 0 is OK.
if (shape > 0)
{
return true;
}
else
{
*result = policies::raise_domain_error<RealType>(
function,
"Shape parameter is %1%, but must be > 0!", shape, pol);
return false;
}
}
else
{ // Not finite.
*result = policies::raise_domain_error<RealType>(
function,
"Shape parameter is %1%, but must be finite!", shape, pol);
return false;
}
} // bool check_pareto_shape(
template <class RealType, class Policy>
inline bool check_pareto_x(
const char* function,
RealType const& x,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(x))
{ //
if (x > 0)
{
return true;
}
else
{
*result = policies::raise_domain_error<RealType>(
function,
"x parameter is %1%, but must be > 0 !", x, pol);
return false;
}
}
else
{ // Not finite..
*result = policies::raise_domain_error<RealType>(
function,
"x parameter is %1%, but must be finite!", x, pol);
return false;
}
} // bool check_pareto_x
template <class RealType, class Policy>
inline bool check_pareto( // distribution parameters.
const char* function,
RealType location,
RealType shape,
RealType* result, const Policy& pol)
{
return check_pareto_location(function, location, result, pol)
&& check_pareto_shape(function, shape, result, pol);
} // bool check_pareto(
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class pareto_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
pareto_distribution(RealType location = 1, RealType shape = 1)
: m_location(location), m_shape(shape)
{ // Constructor.
RealType result;
detail::check_pareto("boost::math::pareto_distribution<%1%>::pareto_distribution", location, shape, &result, Policy());
}
RealType location()const
{ // AKA Xm and b
return m_location;
}
RealType shape()const
{ // AKA k and a
return m_shape;
}
private:
// Data members:
RealType m_location; // distribution location (xm)
RealType m_shape; // distribution shape (k)
};
typedef pareto_distribution<double> pareto; // Convenience to allow pareto(2., 3.);
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const pareto_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>()); // location zero to + infinity.
} // range
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const pareto_distribution<RealType, Policy>& dist)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(dist.location(), max_value<RealType>() ); // location to + infinity.
} // support
template <class RealType, class Policy>
inline RealType pdf(const pareto_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std function pow.
static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
RealType location = dist.location();
RealType shape = dist.shape();
RealType result;
if(false == (detail::check_pareto_x(function, x, &result, Policy())
&& detail::check_pareto(function, location, shape, &result, Policy())))
return result;
if (x < location)
{ // regardless of shape, pdf is zero.
return 0;
}
result = shape * pow(location, shape) / pow(x, shape+1);
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const pareto_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std function pow.
static const char* function = "boost::math::cdf(const pareto_distribution<%1%>&, %1%)";
RealType location = dist.location();
RealType shape = dist.shape();
RealType result;
if(false == (detail::check_pareto_x(function, x, &result, Policy())
&& detail::check_pareto(function, location, shape, &result, Policy())))
return result;
if (x <= location)
{ // regardless of shape, cdf is zero.
return 0;
}
// result = RealType(1) - pow((location / x), shape);
result = -powm1(location/x, shape, Policy()); // should be more accurate.
return result;
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const pareto_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std function pow.
static const char* function = "boost::math::quantile(const pareto_distribution<%1%>&, %1%)";
RealType result;
RealType location = dist.location();
RealType shape = dist.shape();
if(false == (detail::check_probability(function, p, &result, Policy())
&& detail::check_pareto(function, location, shape, &result, Policy())))
{
return result;
}
if (p == 0)
{
return location; // x must be location (or less).
}
if (p == 1)
{
return tools::max_value<RealType>(); // x = + infinity.
}
result = location /
(pow((1 - p), 1 / shape));
// K. Krishnamoorthy, ISBN 1-58488-635-8 eq 23.1.3
return result;
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<pareto_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std function pow.
static const char* function = "boost::math::cdf(const pareto_distribution<%1%>&, %1%)";
RealType result;
RealType x = c.param;
RealType location = c.dist.location();
RealType shape = c.dist.shape();
if(false == (detail::check_pareto_x(function, x, &result, Policy())
&& detail::check_pareto(function, location, shape, &result, Policy())))
return result;
if (x <= location)
{ // regardless of shape, cdf is zero, and complement is unity.
return 1;
}
result = pow((location/x), shape);
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<pareto_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std function pow.
static const char* function = "boost::math::quantile(const pareto_distribution<%1%>&, %1%)";
RealType result;
RealType q = c.param;
RealType location = c.dist.location();
RealType shape = c.dist.shape();
if(false == (detail::check_probability(function, q, &result, Policy())
&& detail::check_pareto(function, location, shape, &result, Policy())))
{
return result;
}
if (q == 1)
{
return location; // x must be location (or less).
}
if (q == 0)
{
return tools::max_value<RealType>(); // x = + infinity.
}
result = location / (pow(q, 1 / shape));
// K. Krishnamoorthy, ISBN 1-58488-635-8 eq 23.1.3
return result;
} // quantile complement
template <class RealType, class Policy>
inline RealType mean(const pareto_distribution<RealType, Policy>& dist)
{
RealType result;
static const char* function = "boost::math::mean(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.location(), dist.shape(), &result, Policy()))
{
return result;
}
if (dist.shape() > RealType(1))
{
return dist.shape() * dist.location() / (dist.shape() - 1);
}
else
{
using boost::math::tools::max_value;
return max_value<RealType>(); // +infinity.
}
} // mean
template <class RealType, class Policy>
inline RealType mode(const pareto_distribution<RealType, Policy>& dist)
{
return dist.location();
} // mode
template <class RealType, class Policy>
inline RealType median(const pareto_distribution<RealType, Policy>& dist)
{
RealType result;
static const char* function = "boost::math::median(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.location(), dist.shape(), &result, Policy()))
{
return result;
}
BOOST_MATH_STD_USING
return dist.location() * pow(RealType(2), (1/dist.shape()));
} // median
template <class RealType, class Policy>
inline RealType variance(const pareto_distribution<RealType, Policy>& dist)
{
RealType result;
RealType location = dist.location();
RealType shape = dist.shape();
static const char* function = "boost::math::variance(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, location, shape, &result, Policy()))
{
return result;
}
if (shape > 2)
{
result = (location * location * shape) /
((shape - 1) * (shape - 1) * (shape - 2));
}
else
{
result = policies::raise_domain_error<RealType>(
function,
"variance is undefined for shape <= 2, but got %1%.", dist.shape(), Policy());
}
return result;
} // variance
template <class RealType, class Policy>
inline RealType skewness(const pareto_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
RealType result;
RealType shape = dist.shape();
static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.location(), shape, &result, Policy()))
{
return result;
}
if (shape > 3)
{
result = sqrt((shape - 2) / shape) *
2 * (shape + 1) /
(shape - 3);
}
else
{
result = policies::raise_domain_error<RealType>(
function,
"skewness is undefined for shape <= 3, but got %1%.", dist.shape(), Policy());
}
return result;
} // skewness
template <class RealType, class Policy>
inline RealType kurtosis(const pareto_distribution<RealType, Policy>& dist)
{
RealType result;
RealType shape = dist.shape();
static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.location(), shape, &result, Policy()))
{
return result;
}
if (shape > 4)
{
result = 3 * ((shape - 2) * (3 * shape * shape + shape + 2)) /
(shape * (shape - 3) * (shape - 4));
}
else
{
result = policies::raise_domain_error<RealType>(
function,
"kurtosis_excess is undefined for shape <= 4, but got %1%.", shape, Policy());
}
return result;
} // kurtosis
template <class RealType, class Policy>
inline RealType kurtosis_excess(const pareto_distribution<RealType, Policy>& dist)
{
RealType result;
RealType shape = dist.shape();
static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.location(), shape, &result, Policy()))
{
return result;
}
if (shape > 4)
{
result = 6 * ((shape * shape * shape) + (shape * shape) - 6 * shape - 2) /
(shape * (shape - 3) * (shape - 4));
}
else
{
result = policies::raise_domain_error<RealType>(
function,
"kurtosis_excess is undefined for shape <= 4, but got %1%.", dist.shape(), Policy());
}
return result;
} // kurtosis_excess
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_PARETO_HPP

View File

@@ -0,0 +1,602 @@
// boost\math\distributions\poisson.hpp
// Copyright John Maddock 2006.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// Poisson distribution is a discrete probability distribution.
// It expresses the probability of a number (k) of
// events, occurrences, failures or arrivals occurring in a fixed time,
// assuming these events occur with a known average or mean rate (lambda)
// and are independent of the time since the last event.
// The distribution was discovered by Siméon-Denis Poisson (17811840).
// Parameter lambda is the mean number of events in the given time interval.
// The random variate k is the number of events, occurrences or arrivals.
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
// Note that the Poisson distribution
// (like others including the binomial, negative binomial & Bernoulli)
// is strictly defined as a discrete function:
// only integral values of k are envisaged.
// However because the method of calculation uses a continuous gamma function,
// it is convenient to treat it as if a continous function,
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// on k outside this function to ensure that k is integral.
// See http://en.wikipedia.org/wiki/Poisson_distribution
// http://documents.wolfram.com/v5/Add-onsLinks/StandardPackages/Statistics/DiscreteDistributions.html
#ifndef BOOST_MATH_SPECIAL_POISSON_HPP
#define BOOST_MATH_SPECIAL_POISSON_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/gamma.hpp> // for incomplete gamma. gamma_q
#include <boost/math/distributions/complement.hpp> // complements
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
#include <boost/math/special_functions/fpclassify.hpp> // isnan.
#include <boost/math/special_functions/factorials.hpp> // factorials.
#include <boost/math/tools/roots.hpp> // for root finding.
#include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
#include <utility>
namespace boost
{
namespace math
{
namespace detail{
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_nearest>&,
boost::uintmax_t& max_iter);
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_up>&,
boost::uintmax_t& max_iter);
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_down>&,
boost::uintmax_t& max_iter);
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_outwards>&,
boost::uintmax_t& max_iter);
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::integer_round_inwards>&,
boost::uintmax_t& max_iter);
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::real>&,
boost::uintmax_t& max_iter);
}
namespace poisson_detail
{
// Common error checking routines for Poisson distribution functions.
// These are convoluted, & apparently redundant, to try to ensure that
// checks are always performed, even if exceptions are not enabled.
template <class RealType, class Policy>
inline bool check_mean(const char* function, const RealType& mean, RealType* result, const Policy& pol)
{
if(!(boost::math::isfinite)(mean) || (mean < 0))
{
*result = policies::raise_domain_error<RealType>(
function,
"Mean argument is %1%, but must be >= 0 !", mean, pol);
return false;
}
return true;
} // bool check_mean
template <class RealType, class Policy>
inline bool check_mean_NZ(const char* function, const RealType& mean, RealType* result, const Policy& pol)
{ // mean == 0 is considered an error.
if( !(boost::math::isfinite)(mean) || (mean <= 0))
{
*result = policies::raise_domain_error<RealType>(
function,
"Mean argument is %1%, but must be > 0 !", mean, pol);
return false;
}
return true;
} // bool check_mean_NZ
template <class RealType, class Policy>
inline bool check_dist(const char* function, const RealType& mean, RealType* result, const Policy& pol)
{ // Only one check, so this is redundant really but should be optimized away.
return check_mean_NZ(function, mean, result, pol);
} // bool check_dist
template <class RealType, class Policy>
inline bool check_k(const char* function, const RealType& k, RealType* result, const Policy& pol)
{
if((k < 0) || !(boost::math::isfinite)(k))
{
*result = policies::raise_domain_error<RealType>(
function,
"Number of events k argument is %1%, but must be >= 0 !", k, pol);
return false;
}
return true;
} // bool check_k
template <class RealType, class Policy>
inline bool check_dist_and_k(const char* function, RealType mean, RealType k, RealType* result, const Policy& pol)
{
if((check_dist(function, mean, result, pol) == false) ||
(check_k(function, k, result, pol) == false))
{
return false;
}
return true;
} // bool check_dist_and_k
template <class RealType, class Policy>
inline bool check_prob(const char* function, const RealType& p, RealType* result, const Policy& pol)
{ // Check 0 <= p <= 1
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
{
*result = policies::raise_domain_error<RealType>(
function,
"Probability argument is %1%, but must be >= 0 and <= 1 !", p, pol);
return false;
}
return true;
} // bool check_prob
template <class RealType, class Policy>
inline bool check_dist_and_prob(const char* function, RealType mean, RealType p, RealType* result, const Policy& pol)
{
if((check_dist(function, mean, result, pol) == false) ||
(check_prob(function, p, result, pol) == false))
{
return false;
}
return true;
} // bool check_dist_and_prob
} // namespace poisson_detail
template <class RealType = double, class Policy = policies::policy<> >
class poisson_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
poisson_distribution(RealType mean = 1) : m_l(mean) // mean (lambda).
{ // Expected mean number of events that occur during the given interval.
RealType r;
poisson_detail::check_dist(
"boost::math::poisson_distribution<%1%>::poisson_distribution",
m_l,
&r, Policy());
} // poisson_distribution constructor.
RealType mean() const
{ // Private data getter function.
return m_l;
}
private:
// Data member, initialized by constructor.
RealType m_l; // mean number of occurrences.
}; // template <class RealType, class Policy> class poisson_distribution
typedef poisson_distribution<double> poisson; // Reserved name of type double.
// Non-member functions to give properties of the distribution.
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const poisson_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable k.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>()); // Max integer?
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const poisson_distribution<RealType, Policy>& /* dist */)
{ // Range of supported values for random variable k.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType mean(const poisson_distribution<RealType, Policy>& dist)
{ // Mean of poisson distribution = lambda.
return dist.mean();
} // mean
template <class RealType, class Policy>
inline RealType mode(const poisson_distribution<RealType, Policy>& dist)
{ // mode.
BOOST_MATH_STD_USING // ADL of std functions.
return floor(dist.mean());
}
//template <class RealType, class Policy>
//inline RealType median(const poisson_distribution<RealType, Policy>& dist)
//{ // median = approximately lambda + 1/3 - 0.2/lambda
// RealType l = dist.mean();
// return dist.mean() + static_cast<RealType>(0.3333333333333333333333333333333333333333333333)
// - static_cast<RealType>(0.2) / l;
//} // BUT this formula appears to be out-by-one compared to quantile(half)
// Query posted on Wikipedia.
// Now implemented via quantile(half) in derived accessors.
template <class RealType, class Policy>
inline RealType variance(const poisson_distribution<RealType, Policy>& dist)
{ // variance.
return dist.mean();
}
// RealType standard_deviation(const poisson_distribution<RealType, Policy>& dist)
// standard_deviation provided by derived accessors.
template <class RealType, class Policy>
inline RealType skewness(const poisson_distribution<RealType, Policy>& dist)
{ // skewness = sqrt(l).
BOOST_MATH_STD_USING // ADL of std functions.
return 1 / sqrt(dist.mean());
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const poisson_distribution<RealType, Policy>& dist)
{ // skewness = sqrt(l).
return 1 / dist.mean(); // kurtosis_excess 1/mean from Wiki & MathWorld eq 31.
// http://mathworld.wolfram.com/Kurtosis.html explains that the kurtosis excess
// is more convenient because the kurtosis excess of a normal distribution is zero
// whereas the true kurtosis is 3.
} // RealType kurtosis_excess
template <class RealType, class Policy>
inline RealType kurtosis(const poisson_distribution<RealType, Policy>& dist)
{ // kurtosis is 4th moment about the mean = u4 / sd ^ 4
// http://en.wikipedia.org/wiki/Curtosis
// kurtosis can range from -2 (flat top) to +infinity (sharp peak & heavy tails).
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm
return 3 + 1 / dist.mean(); // NIST.
// http://mathworld.wolfram.com/Kurtosis.html explains that the kurtosis excess
// is more convenient because the kurtosis excess of a normal distribution is zero
// whereas the true kurtosis is 3.
} // RealType kurtosis
template <class RealType, class Policy>
RealType pdf(const poisson_distribution<RealType, Policy>& dist, const RealType k)
{ // Probability Density/Mass Function.
// Probability that there are EXACTLY k occurrences (or arrivals).
BOOST_FPU_EXCEPTION_GUARD
BOOST_MATH_STD_USING // for ADL of std functions.
RealType mean = dist.mean();
// Error check:
RealType result;
if(false == poisson_detail::check_dist_and_k(
"boost::math::pdf(const poisson_distribution<%1%>&, %1%)",
mean,
k,
&result, Policy()))
{
return result;
}
// Special case of mean zero, regardless of the number of events k.
if (mean == 0)
{ // Probability for any k is zero.
return 0;
}
if (k == 0)
{ // mean ^ k = 1, and k! = 1, so can simplify.
return exp(-mean);
}
using boost::math::unchecked_factorial;
RealType floork = floor(k);
if ((floork == k) // integral
&& k < max_factorial<RealType>::value)
{ // k is small enough (for float 34, double 170 ...) to use factorial(k).
return exp(-mean) * pow(mean, k) /
unchecked_factorial<RealType>(tools::real_cast<unsigned int>(floork));
}
else
{ // Need to use log(factorial(k)) = lgamma(k+1)
// (e ^ -mean * mean ^ k) / k!
// == exp(log(e ^ -mean) + log (mean ^ k) - lgamma(k+1))
// exp( -mean + log(mean) * k - lgamma(k+1))
return exp(-mean + log(mean) * k - boost::math::lgamma(k+1, Policy()));
// return gamma_p_derivative(k+1, mean); // equivalent & also passes tests.
}
} // pdf
template <class RealType, class Policy>
RealType cdf(const poisson_distribution<RealType, Policy>& dist, const RealType k)
{ // Cumulative Distribution Function Poisson.
// The random variate k is the number of occurrences(or arrivals)
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
// Returns the sum of the terms 0 through k of the Poisson Probability Density or Mass (pdf).
// But note that the Poisson distribution
// (like others including the binomial, negative binomial & Bernoulli)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as if it is a continous function
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// outside this function to ensure that k is integral.
// The terms are not summed directly (at least for larger k)
// instead the incomplete gamma integral is employed,
BOOST_MATH_STD_USING // for ADL of std function exp.
RealType mean = dist.mean();
// Error checks:
RealType result;
if(false == poisson_detail::check_dist_and_k(
"boost::math::cdf(const poisson_distribution<%1%>&, %1%)",
mean,
k,
&result, Policy()))
{
return result;
}
// Special cases:
if (mean == 0)
{ // Probability for any k is zero.
return 0;
}
if (k == 0)
{ // return pdf(dist, static_cast<RealType>(0));
// but mean (and k) have already been checked,
// so this avoids unnecessary repeated checks.
return exp(-mean);
}
// For small integral k could use a finite sum -
// it's cheaper than the gamma function.
// BUT this is now done efficiently by gamma_q function.
// Calculate poisson cdf using the gamma_q function.
return gamma_q(k+1, mean, Policy());
} // binomial cdf
template <class RealType, class Policy>
RealType cdf(const complemented2_type<poisson_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function Poisson
// The random variate k is the number of events, occurrences or arrivals.
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
// But note that the Poisson distribution
// (like others including the binomial, negative binomial & Bernoulli)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as is it is a continous function
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// outside this function to ensure that k is integral.
// Returns the sum of the terms k+1 through inf of the Poisson Probability Density/Mass (pdf).
// The terms are not summed directly (at least for larger k)
// instead the incomplete gamma integral is employed,
RealType const& k = c.param;
poisson_distribution<RealType, Policy> const& dist = c.dist;
RealType mean = dist.mean();
// Error checks:
RealType result;
if(false == poisson_detail::check_dist_and_k(
"boost::math::cdf(const poisson_distribution<%1%>&, %1%)",
mean,
k,
&result, Policy()))
{
return result;
}
// Special case of mean, regardless of the number of events k.
if (mean == 0)
{ // Probability for any k is unity, complement of zero.
return 1;
}
if (k == 0)
{ // Avoid repeated checks on k and mean in gamma_p.
return -boost::math::expm1(-mean, Policy());
}
// Unlike un-complemented cdf (sum from 0 to k),
// can't use finite sum from k+1 to infinity for small integral k,
// anyway it is now done efficiently by gamma_p.
return gamma_p(k + 1, mean, Policy()); // Calculate Poisson cdf using the gamma_p function.
// CCDF = gamma_p(k+1, lambda)
} // poisson ccdf
template <class RealType, class Policy>
inline RealType quantile(const poisson_distribution<RealType, Policy>& dist, const RealType& p)
{ // Quantile (or Percent Point) Poisson function.
// Return the number of expected events k for a given probability p.
RealType result; // of Argument checks:
if(false == poisson_detail::check_prob(
"boost::math::quantile(const poisson_distribution<%1%>&, %1%)",
p,
&result, Policy()))
{
return result;
}
// Special case:
if (dist.mean() == 0)
{ // if mean = 0 then p = 0, so k can be anything?
if (false == poisson_detail::check_mean_NZ(
"boost::math::quantile(const poisson_distribution<%1%>&, %1%)",
dist.mean(),
&result, Policy()))
{
return result;
}
}
/*
BOOST_MATH_STD_USING // ADL of std functions.
// if(p == 0) NOT necessarily zero!
// Not necessarily any special value of k because is unlimited.
if (p <= exp(-dist.mean()))
{ // if p <= cdf for 0 events (== pdf for 0 events), then quantile must be zero.
return 0;
}
return gamma_q_inva(dist.mean(), p, Policy()) - 1;
*/
typedef typename Policy::discrete_quantile_type discrete_type;
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
RealType guess, factor = 8;
RealType z = dist.mean();
if(z < 1)
guess = z;
else
guess = boost::math::detail::inverse_poisson_cornish_fisher(z, p, 1-p, Policy());
if(z > 5)
{
if(z > 1000)
factor = 1.01f;
else if(z > 50)
factor = 1.1f;
else if(guess > 10)
factor = 1.25f;
else
factor = 2;
if(guess < 1.1)
factor = 8;
}
return detail::inverse_discrete_quantile(
dist,
p,
1-p,
guess,
factor,
RealType(1),
discrete_type(),
max_iter);
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<poisson_distribution<RealType, Policy>, RealType>& c)
{ // Quantile (or Percent Point) of Poisson function.
// Return the number of expected events k for a given
// complement of the probability q.
//
// Error checks:
RealType q = c.param;
const poisson_distribution<RealType, Policy>& dist = c.dist;
RealType result; // of argument checks.
if(false == poisson_detail::check_prob(
"boost::math::quantile(const poisson_distribution<%1%>&, %1%)",
q,
&result, Policy()))
{
return result;
}
// Special case:
if (dist.mean() == 0)
{ // if mean = 0 then p = 0, so k can be anything?
if (false == poisson_detail::check_mean_NZ(
"boost::math::quantile(const poisson_distribution<%1%>&, %1%)",
dist.mean(),
&result, Policy()))
{
return result;
}
}
/*
if (-q <= boost::math::expm1(-dist.mean()))
{ // if q <= cdf(complement for 0 events, then quantile must be zero.
return 0;
}
return gamma_p_inva(dist.mean(), q, Policy()) -1;
*/
typedef typename Policy::discrete_quantile_type discrete_type;
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
RealType guess, factor = 8;
RealType z = dist.mean();
if(z < 1)
guess = z;
else
guess = boost::math::detail::inverse_poisson_cornish_fisher(z, 1-q, q, Policy());
if(z > 5)
{
if(z > 1000)
factor = 1.01f;
else if(z > 50)
factor = 1.1f;
else if(guess > 10)
factor = 1.25f;
else
factor = 2;
if(guess < 1.1)
factor = 8;
}
return detail::inverse_discrete_quantile(
dist,
1-q,
q,
guess,
factor,
RealType(1),
discrete_type(),
max_iter);
} // quantile complement.
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
#endif // BOOST_MATH_SPECIAL_POISSON_HPP

View File

@@ -0,0 +1,293 @@
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_rayleigh_HPP
#define BOOST_STATS_rayleigh_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <cmath>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
#include <utility>
namespace boost{ namespace math{
namespace detail
{ // Error checks:
template <class RealType, class Policy>
inline bool verify_sigma(const char* function, RealType sigma, RealType* presult, const Policy& pol)
{
if(sigma <= 0)
{
*presult = policies::raise_domain_error<RealType>(
function,
"The scale parameter \"sigma\" must be > 0, but was: %1%.", sigma, pol);
return false;
}
return true;
} // bool verify_sigma
template <class RealType, class Policy>
inline bool verify_rayleigh_x(const char* function, RealType x, RealType* presult, const Policy& pol)
{
if(x < 0)
{
*presult = policies::raise_domain_error<RealType>(
function,
"The random variable must be >= 0, but was: %1%.", x, pol);
return false;
}
return true;
} // bool verify_rayleigh_x
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class rayleigh_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
rayleigh_distribution(RealType sigma = 1)
: m_sigma(sigma)
{
RealType err;
detail::verify_sigma("boost::math::rayleigh_distribution<%1%>::rayleigh_distribution", sigma, &err, Policy());
} // rayleigh_distribution
RealType sigma()const
{ // Accessor.
return m_sigma;
}
private:
RealType m_sigma;
}; // class rayleigh_distribution
typedef rayleigh_distribution<double> rayleigh;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(static_cast<RealType>(1), max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>((1), max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType pdf(const rayleigh_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std function exp.
RealType sigma = dist.sigma();
RealType result;
static const char* function = "boost::math::pdf(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return result;
}
if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
{
return result;
}
RealType sigmasqr = sigma * sigma;
result = x * (exp(-(x * x) / ( 2 * sigmasqr))) / sigmasqr;
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const rayleigh_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType result;
RealType sigma = dist.sigma();
static const char* function = "boost::math::cdf(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return result;
}
if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
{
return result;
}
result = -boost::math::expm1(-x * x / ( 2 * sigma * sigma), Policy());
return result;
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const rayleigh_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType result;
RealType sigma = dist.sigma();
static const char* function = "boost::math::quantile(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
return result;
if(false == detail::check_probability(function, p, &result, Policy()))
return result;
if(p == 0)
{
return 0;
}
if(p == 1)
{
return policies::raise_overflow_error<RealType>(function, 0, Policy());
}
result = sqrt(-2 * sigma * sigma * boost::math::log1p(-p, Policy()));
return result;
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<rayleigh_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType result;
RealType sigma = c.dist.sigma();
static const char* function = "boost::math::cdf(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return result;
}
RealType x = c.param;
if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
{
return result;
}
result = exp(-x * x / ( 2 * sigma * sigma));
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<rayleigh_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions, log & sqrt.
RealType result;
RealType sigma = c.dist.sigma();
static const char* function = "boost::math::quantile(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return result;
}
RealType q = c.param;
if(false == detail::check_probability(function, q, &result, Policy()))
{
return result;
}
if(q == 1)
{
return 0;
}
if(q == 0)
{
return policies::raise_overflow_error<RealType>(function, 0, Policy());
}
result = sqrt(-2 * sigma * sigma * log(q));
return result;
} // quantile complement
template <class RealType, class Policy>
inline RealType mean(const rayleigh_distribution<RealType, Policy>& dist)
{
RealType result;
RealType sigma = dist.sigma();
static const char* function = "boost::math::mean(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return result;
}
using boost::math::constants::root_half_pi;
return sigma * root_half_pi<RealType>();
} // mean
template <class RealType, class Policy>
inline RealType variance(const rayleigh_distribution<RealType, Policy>& dist)
{
RealType result;
RealType sigma = dist.sigma();
static const char* function = "boost::math::variance(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return result;
}
using boost::math::constants::four_minus_pi;
return four_minus_pi<RealType>() * sigma * sigma / 2;
} // variance
template <class RealType, class Policy>
inline RealType mode(const rayleigh_distribution<RealType, Policy>& dist)
{
return dist.sigma();
}
template <class RealType, class Policy>
inline RealType median(const rayleigh_distribution<RealType, Policy>& dist)
{
using boost::math::constants::root_ln_four;
return root_ln_four<RealType>() * dist.sigma();
}
template <class RealType, class Policy>
inline RealType skewness(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return static_cast<RealType>(0.63111065781893713819189935154422777984404221106391L);
// Computed using NTL at 150 bit, about 50 decimal digits.
// return 2 * root_pi<RealType>() * pi_minus_three<RealType>() / pow23_four_minus_pi<RealType>();
}
template <class RealType, class Policy>
inline RealType kurtosis(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return static_cast<RealType>(3.2450893006876380628486604106197544154170667057995L);
// Computed using NTL at 150 bit, about 50 decimal digits.
// return 3 - (6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
// (four_minus_pi<RealType>() * four_minus_pi<RealType>());
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{
//using namespace boost::math::constants;
// Computed using NTL at 150 bit, about 50 decimal digits.
return static_cast<RealType>(0.2450893006876380628486604106197544154170667057995L);
// return -(6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
// (four_minus_pi<RealType>() * four_minus_pi<RealType>());
} // kurtosis
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_rayleigh_HPP

View File

@@ -0,0 +1,374 @@
// Copyright John Maddock 2006.
// Copyright Paul A. Bristow 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_STUDENTS_T_HPP
#define BOOST_STATS_STUDENTS_T_HPP
// http://en.wikipedia.org/wiki/Student%27s_t_distribution
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3664.htm
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/beta.hpp> // for ibeta(a, b, x).
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <utility>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
namespace boost{ namespace math{
template <class RealType = double, class Policy = policies::policy<> >
class students_t_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
students_t_distribution(RealType i) : m_df(i)
{ // Constructor.
RealType result;
detail::check_df(
"boost::math::students_t_distribution<%1%>::students_t_distribution", m_df, &result, Policy());
} // students_t_distribution
RealType degrees_of_freedom()const
{
return m_df;
}
// Parameter estimation:
static RealType find_degrees_of_freedom(
RealType difference_from_mean,
RealType alpha,
RealType beta,
RealType sd,
RealType hint = 100);
private:
//
// Data members:
//
RealType m_df; // degrees of freedom are a real number.
};
typedef students_t_distribution<double> students_t;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const students_t_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const students_t_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType pdf(const students_t_distribution<RealType, Policy>& dist, const RealType& t)
{
BOOST_FPU_EXCEPTION_GUARD
BOOST_MATH_STD_USING // for ADL of std functions
RealType degrees_of_freedom = dist.degrees_of_freedom();
// Error check:
RealType error_result;
if(false == detail::check_df(
"boost::math::pdf(const students_t_distribution<%1%>&, %1%)", degrees_of_freedom, &error_result, Policy()))
return error_result;
// Might conceivably permit df = +infinity and use normal distribution.
RealType result;
RealType basem1 = t * t / degrees_of_freedom;
if(basem1 < 0.125)
{
result = exp(-boost::math::log1p(basem1, Policy()) * (1+degrees_of_freedom) / 2);
}
else
{
result = pow(1 / (1 + basem1), (degrees_of_freedom + 1) / 2);
}
result /= sqrt(degrees_of_freedom) * boost::math::beta(degrees_of_freedom / 2, RealType(0.5f), Policy());
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const students_t_distribution<RealType, Policy>& dist, const RealType& t)
{
RealType degrees_of_freedom = dist.degrees_of_freedom();
// Error check:
RealType error_result;
if(false == detail::check_df(
"boost::math::cdf(const students_t_distribution<%1%>&, %1%)", degrees_of_freedom, &error_result, Policy()))
return error_result;
if (t == 0)
{
return 0.5;
}
//
// Calculate probability of Student's t using the incomplete beta function.
// probability = ibeta(degrees_of_freedom / 2, 1/2, degrees_of_freedom / (degrees_of_freedom + t*t))
//
// However when t is small compared to the degrees of freedom, that formula
// suffers from rounding error, use the identity formula to work around
// the problem:
//
// I[x](a,b) = 1 - I[1-x](b,a)
//
// and:
//
// x = df / (df + t^2)
//
// so:
//
// 1 - x = t^2 / (df + t^2)
//
RealType t2 = t * t;
RealType probability;
if(degrees_of_freedom > 2 * t2)
{
RealType z = t2 / (degrees_of_freedom + t2);
probability = ibetac(static_cast<RealType>(0.5), degrees_of_freedom / 2, z, Policy()) / 2;
}
else
{
RealType z = degrees_of_freedom / (degrees_of_freedom + t2);
probability = ibeta(degrees_of_freedom / 2, static_cast<RealType>(0.5), z, Policy()) / 2;
}
return (t > 0 ? 1 - probability : probability);
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const students_t_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
//
// Obtain parameters:
//
RealType degrees_of_freedom = dist.degrees_of_freedom();
RealType probability = p;
//
// Check for domain errors:
//
static const char* function = "boost::math::quantile(const students_t_distribution<%1%>&, %1%)";
RealType error_result;
if(false == detail::check_df(
function, degrees_of_freedom, &error_result, Policy())
&& detail::check_probability(function, probability, &error_result, Policy()))
return error_result;
// Special cases, regardless of degrees_of_freedom.
if (probability == 0)
return -policies::raise_overflow_error<RealType>(function, 0, Policy());
if (probability == 1)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
if (probability == static_cast<RealType>(0.5))
return 0;
//
// This next block is disabled in favour of a faster method than
// incomplete beta inverse, code retained for future reference:
//
#if 0
//
// Calculate quantile of Student's t using the incomplete beta function inverse:
//
probability = (probability > 0.5) ? 1 - probability : probability;
RealType t, x, y;
x = ibeta_inv(degrees_of_freedom / 2, RealType(0.5), 2 * probability, &y);
if(degrees_of_freedom * y > tools::max_value<RealType>() * x)
t = tools::overflow_error<RealType>(function);
else
t = sqrt(degrees_of_freedom * y / x);
//
// Figure out sign based on the size of p:
//
if(p < 0.5)
t = -t;
return t;
#endif
//
// Depending on how many digits RealType has, this may forward
// to the incomplete beta inverse as above. Otherwise uses a
// faster method that is accurate to ~15 digits everywhere
// and a couple of epsilon at double precision and in the central
// region where most use cases will occur...
//
return boost::math::detail::fast_students_t_quantile(degrees_of_freedom, probability, Policy());
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<students_t_distribution<RealType, Policy>, RealType>& c)
{
return cdf(c.dist, -c.param);
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<students_t_distribution<RealType, Policy>, RealType>& c)
{
return -quantile(c.dist, c.param);
}
//
// Parameter estimation follows:
//
namespace detail{
//
// Functors for finding degrees of freedom:
//
template <class RealType, class Policy>
struct sample_size_func
{
sample_size_func(RealType a, RealType b, RealType s, RealType d)
: alpha(a), beta(b), ratio(s*s/(d*d)) {}
RealType operator()(const RealType& df)
{
if(df <= tools::min_value<RealType>())
return 1;
students_t_distribution<RealType, Policy> t(df);
RealType qa = quantile(complement(t, alpha));
RealType qb = quantile(complement(t, beta));
qa += qb;
qa *= qa;
qa *= ratio;
qa -= (df + 1);
return qa;
}
RealType alpha, beta, ratio;
};
} // namespace detail
template <class RealType, class Policy>
RealType students_t_distribution<RealType, Policy>::find_degrees_of_freedom(
RealType difference_from_mean,
RealType alpha,
RealType beta,
RealType sd,
RealType hint)
{
static const char* function = "boost::math::students_t_distribution<%1%>::find_degrees_of_freedom";
//
// Check for domain errors:
//
RealType error_result;
if(false == detail::check_probability(
function, alpha, &error_result, Policy())
&& detail::check_probability(function, beta, &error_result, Policy()))
return error_result;
if(hint <= 0)
hint = 1;
detail::sample_size_func<RealType, Policy> f(alpha, beta, sd, difference_from_mean);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::pair<RealType, RealType> r = tools::bracket_and_solve_root(f, hint, RealType(2), false, tol, max_iter, Policy());
RealType result = r.first + (r.second - r.first) / 2;
if(max_iter == policies::get_max_root_iterations<Policy>())
{
policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" either there is no answer to how many degrees of freedom are required"
" or the answer is infinite. Current best guess is %1%", result, Policy());
}
return result;
}
template <class RealType, class Policy>
inline RealType mean(const students_t_distribution<RealType, Policy>& )
{
return 0;
}
template <class RealType, class Policy>
inline RealType variance(const students_t_distribution<RealType, Policy>& dist)
{
// Error check:
RealType error_result;
if(false == detail::check_df(
"boost::math::variance(students_t_distribution<%1%> const&, %1%)", dist.degrees_of_freedom(), &error_result, Policy()))
return error_result;
RealType v = dist.degrees_of_freedom();
return v / (v - 2);
}
template <class RealType, class Policy>
inline RealType mode(const students_t_distribution<RealType, Policy>& /*dist*/)
{
return 0;
}
template <class RealType, class Policy>
inline RealType median(const students_t_distribution<RealType, Policy>& /*dist*/)
{
return 0;
}
template <class RealType, class Policy>
inline RealType skewness(const students_t_distribution<RealType, Policy>& dist)
{
if(dist.degrees_of_freedom() <= 3)
{
policies::raise_domain_error<RealType>(
"boost::math::skewness(students_t_distribution<%1%> const&, %1%)",
"Skewness is undefined for degrees of freedom <= 3, but got %1%.",
dist.degrees_of_freedom(), Policy());
}
return 0;
}
template <class RealType, class Policy>
inline RealType kurtosis(const students_t_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
if(df <= 3)
{
policies::raise_domain_error<RealType>(
"boost::math::kurtosis(students_t_distribution<%1%> const&, %1%)",
"Skewness is undefined for degrees of freedom <= 3, but got %1%.",
df, Policy());
}
return 3 * (df - 2) / (df - 4);
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const students_t_distribution<RealType, Policy>& dist)
{
// see http://mathworld.wolfram.com/Kurtosis.html
RealType df = dist.degrees_of_freedom();
if(df <= 3)
{
policies::raise_domain_error<RealType>(
"boost::math::kurtosis_excess(students_t_distribution<%1%> const&, %1%)",
"Skewness is undefined for degrees of freedom <= 3, but got %1%.",
df, Policy());
}
return 6 / (df - 4);
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_STUDENTS_T_HPP

View File

@@ -0,0 +1,521 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2006, 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_TRIANGULAR_HPP
#define BOOST_STATS_TRIANGULAR_HPP
// http://mathworld.wolfram.com/TriangularDistribution.html
// http://en.wikipedia.org/wiki/Triangular_distribution
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/constants/constants.hpp>
#include <utility>
namespace boost{ namespace math
{
namespace detail
{
template <class RealType, class Policy>
inline bool check_triangular_lower(
const char* function,
RealType lower,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(lower))
{ // Any finite value is OK.
return true;
}
else
{ // Not finite: infinity or NaN.
*result = policies::raise_domain_error<RealType>(
function,
"Lower parameter is %1%, but must be finite!", lower, pol);
return false;
}
} // bool check_triangular_lower(
template <class RealType, class Policy>
inline bool check_triangular_mode(
const char* function,
RealType mode,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(mode))
{ // any finite value is OK.
return true;
}
else
{ // Not finite: infinity or NaN.
*result = policies::raise_domain_error<RealType>(
function,
"Mode parameter is %1%, but must be finite!", mode, pol);
return false;
}
} // bool check_triangular_mode(
template <class RealType, class Policy>
inline bool check_triangular_upper(
const char* function,
RealType upper,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(upper))
{ // any finite value is OK.
return true;
}
else
{ // Not finite: infinity or NaN.
*result = policies::raise_domain_error<RealType>(
function,
"Upper parameter is %1%, but must be finite!", upper, pol);
return false;
}
} // bool check_triangular_upper(
template <class RealType, class Policy>
inline bool check_triangular_x(
const char* function,
RealType const& x,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(x))
{ // Any finite value is OK
return true;
}
else
{ // Not finite: infinity or NaN.
*result = policies::raise_domain_error<RealType>(
function,
"x parameter is %1%, but must be finite!", x, pol);
return false;
}
} // bool check_triangular_x
template <class RealType, class Policy>
inline bool check_triangular(
const char* function,
RealType lower,
RealType mode,
RealType upper,
RealType* result, const Policy& pol)
{
if(check_triangular_lower(function, lower, result, pol)
&& check_triangular_mode(function, mode, result, pol)
&& check_triangular_upper(function, upper, result, pol)
&& (lower < upper) // lower == upper NOT useful.
)
{
if (mode < lower)
{
*result = policies::raise_domain_error<RealType>(
function,
"mode parameter is %1%, but must be >= than lower!", lower, pol);
return false;
}
if (mode > upper )
{
*result = policies::raise_domain_error<RealType>(
function,
"mode parameter is %1%, but must be <= than upper!", upper, pol);
return false;
}
return true;
}
else
{ // upper and lower have each been checked before, so must be lower >= upper.
*result = policies::raise_domain_error<RealType>(
function,
"lower parameter is %1%, but must be less than upper!", lower, pol);
return false;
}
} // bool check_triangular
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class triangular_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
triangular_distribution(RealType lower = -1, RealType mode = 0, RealType upper = 1)
: m_lower(lower), m_mode(mode), m_upper(upper) // Constructor.
{ // Evans says 'standard triangular' is lower 0, mode 1/2, upper 1,
// has median sqrt(c/2) for c <=1/2 and 1 - sqrt(1-c)/2 for c >= 1/2
// But this -1, 0, 1 is more useful in most applications to approximate normal distribution,
// where the central value is the most likely and deviations either side equally likely.
RealType result;
detail::check_triangular("boost::math::triangular_distribution<%1%>::triangular_distribution",lower, mode, upper, &result, Policy());
}
// Accessor functions.
RealType lower()const
{
return m_lower;
}
RealType mode()const
{
return m_mode;
}
RealType upper()const
{
return m_upper;
}
private:
// Data members:
RealType m_lower; // distribution lower aka a
RealType m_mode; // distribution mode aka c
RealType m_upper; // distribution upper aka b
}; // class triangular_distribution
typedef triangular_distribution<double> triangular;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const triangular_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const triangular_distribution<RealType, Policy>& dist)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
return std::pair<RealType, RealType>(dist.lower(), dist.upper());
}
template <class RealType, class Policy>
RealType pdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x)
{
static const char* function = "boost::math::pdf(const triangular_distribution<%1%>&, %1%)";
RealType lower = dist.lower();
RealType mode = dist.mode();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
{
return result;
}
if(false == detail::check_triangular_x(function, x, &result, Policy()))
{
return result;
}
if((x < lower) || (x > upper))
{
return 0;
}
if (x == lower)
{ // (mode - lower) == 0 which would lead to divide by zero!
return (mode == lower) ? 2 / (upper - lower) : 0;
}
else if (x == upper)
{
return (mode == upper) ? 2 / (upper - lower) : 0;
}
else if (x <= mode)
{
return 2 * (x - lower) / ((upper - lower) * (mode - lower));
}
else
{ // (x > mode)
return 2 * (upper - x) / ((upper - lower) * (upper - mode));
}
} // RealType pdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x)
template <class RealType, class Policy>
inline RealType cdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x)
{
static const char* function = "boost::math::cdf(const triangular_distribution<%1%>&, %1%)";
RealType lower = dist.lower();
RealType mode = dist.mode();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
{
return result;
}
if(false == detail::check_triangular_x(function, x, &result, Policy()))
{
return result;
}
if((x <= lower))
{
return 0;
}
if (x >= upper)
{
return 1;
}
// else lower < x < upper
if (x <= mode)
{
return ((x - lower) * (x - lower)) / ((upper - lower) * (mode - lower));
}
else
{
return 1 - (upper - x) * (upper - x) / ((upper - lower) * (upper - mode));
}
} // RealType cdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x)
template <class RealType, class Policy>
RealType quantile(const triangular_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions (sqrt).
static const char* function = "boost::math::quantile(const triangular_distribution<%1%>&, %1%)";
RealType lower = dist.lower();
RealType mode = dist.mode();
RealType upper = dist.upper();
RealType result; // of checks
if(false == detail::check_triangular(function,lower, mode, upper, &result, Policy()))
{
return result;
}
if(false == detail::check_probability(function, p, &result, Policy()))
{
return result;
}
if(p == 0)
{
return lower;
}
if(p == 1)
{
return upper;
}
RealType p0 = (mode - lower) / (upper - lower);
RealType q = 1 - p;
if (p < p0)
{
result = sqrt((upper - lower) * (mode - lower) * p) + lower;
}
else if (p == p0)
{
result = mode;
}
else // p > p0
{
result = upper - sqrt((upper - lower) * (upper - mode) * q);
}
return result;
} // RealType quantile(const triangular_distribution<RealType, Policy>& dist, const RealType& q)
template <class RealType, class Policy>
RealType cdf(const complemented2_type<triangular_distribution<RealType, Policy>, RealType>& c)
{
static const char* function = "boost::math::cdf(const triangular_distribution<%1%>&, %1%)";
RealType lower = c.dist.lower();
RealType mode = c.dist.mode();
RealType upper = c.dist.upper();
RealType x = c.param;
RealType result; // of checks.
if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
{
return result;
}
if(false == detail::check_triangular_x(function, x, &result, Policy()))
{
return result;
}
if (x <= lower)
{
return 1;
}
if (x >= upper)
{
return 0;
}
if (x <= mode)
{
return 1 - ((x - lower) * (x - lower)) / ((upper - lower) * (mode - lower));
}
else
{
return (upper - x) * (upper - x) / ((upper - lower) * (upper - mode));
}
} // RealType cdf(const complemented2_type<triangular_distribution<RealType, Policy>, RealType>& c)
template <class RealType, class Policy>
RealType quantile(const complemented2_type<triangular_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // Aid ADL for sqrt.
static const char* function = "boost::math::quantile(const triangular_distribution<%1%>&, %1%)";
RealType l = c.dist.lower();
RealType m = c.dist.mode();
RealType u = c.dist.upper();
RealType q = c.param; // probability 0 to 1.
RealType result; // of checks.
if(false == detail::check_triangular(function, l, m, u, &result, Policy()))
{
return result;
}
if(false == detail::check_probability(function, q, &result, Policy()))
{
return result;
}
if(q == 0)
{
return u;
}
if(q == 1)
{
return l;
}
RealType lower = c.dist.lower();
RealType mode = c.dist.mode();
RealType upper = c.dist.upper();
RealType p = 1 - q;
RealType p0 = (mode - lower) / (upper - lower);
if(p < p0)
{
RealType s = (upper - lower) * (mode - lower);
s *= p;
result = sqrt((upper - lower) * (mode - lower) * p) + lower;
}
else if (p == p0)
{
result = mode;
}
else // p > p0
{
result = upper - sqrt((upper - lower) * (upper - mode) * q);
}
return result;
} // RealType quantile(const complemented2_type<triangular_distribution<RealType, Policy>, RealType>& c)
template <class RealType, class Policy>
inline RealType mean(const triangular_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::mean(const triangular_distribution<%1%>&)";
RealType lower = dist.lower();
RealType mode = dist.mode();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
{
return result;
}
return (lower + upper + mode) / 3;
} // RealType mean(const triangular_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType variance(const triangular_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::mean(const triangular_distribution<%1%>&)";
RealType lower = dist.lower();
RealType mode = dist.mode();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
{
return result;
}
return (lower * lower + upper * upper + mode * mode - lower * upper - lower * mode - upper * mode) / 18;
} // RealType variance(const triangular_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType mode(const triangular_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::mode(const triangular_distribution<%1%>&)";
RealType mode = dist.mode();
RealType result; // of checks.
if(false == detail::check_triangular_mode(function, mode, &result, Policy()))
{ // This should never happen!
return result;
}
return mode;
} // RealType mode
template <class RealType, class Policy>
inline RealType median(const triangular_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // ADL of std functions.
static const char* function = "boost::math::median(const triangular_distribution<%1%>&)";
RealType mode = dist.mode();
RealType result; // of checks.
if(false == detail::check_triangular_mode(function, mode, &result, Policy()))
{ // This should never happen!
return result;
}
RealType lower = dist.lower();
RealType upper = dist.upper();
if (mode < (upper - lower) / 2)
{
return lower + sqrt((upper - lower) * (mode - lower)) / constants::root_two<RealType>();
}
else
{
return upper - sqrt((upper - lower) * (upper - mode)) / constants::root_two<RealType>();
}
} // RealType mode
template <class RealType, class Policy>
inline RealType skewness(const triangular_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
using namespace boost::math::constants; // for root_two
static const char* function = "boost::math::skewness(const triangular_distribution<%1%>&)";
RealType lower = dist.lower();
RealType mode = dist.mode();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_triangular(function,lower, mode, upper, &result, Policy()))
{
return result;
}
return root_two<RealType>() * (lower + upper - 2 * mode) * (2 * lower - upper - mode) * (lower - 2 * upper + mode) /
(5 * pow((lower * lower + upper + upper + mode * mode - lower * upper - lower * mode - upper * mode), RealType(3)/RealType(2)));
} // RealType skewness(const triangular_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType kurtosis(const triangular_distribution<RealType, Policy>& dist)
{ // These checks may be belt and braces as should have been checked on construction?
static const char* function = "boost::math::kurtosis(const triangular_distribution<%1%>&)";
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType mode = dist.mode();
RealType result; // of checks.
if(false == detail::check_triangular(function,lower, mode, upper, &result, Policy()))
{
return result;
}
return static_cast<RealType>(12)/5; // 12/5 = 2.4;
} // RealType kurtosis_excess(const triangular_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType kurtosis_excess(const triangular_distribution<RealType, Policy>& dist)
{ // These checks may be belt and braces as should have been checked on construction?
static const char* function = "boost::math::kurtosis_excess(const triangular_distribution<%1%>&)";
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType mode = dist.mode();
RealType result; // of checks.
if(false == detail::check_triangular(function,lower, mode, upper, &result, Policy()))
{
return result;
}
return static_cast<RealType>(-3)/5; // - 3/5 = -0.6
// Assuming mathworld really means kurtosis excess? Wikipedia now corrected to match this.
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_TRIANGULAR_HPP

View File

@@ -0,0 +1,375 @@
// Copyright John Maddock 2006.
// Copyright Paul A. Bristow 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// TODO deal with infinity as special better - or remove.
//
#ifndef BOOST_STATS_UNIFORM_HPP
#define BOOST_STATS_UNIFORM_HPP
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3668.htm
// http://mathworld.wolfram.com/UniformDistribution.html
// http://documents.wolfram.com/calculationcenter/v2/Functions/ListsMatrices/Statistics/UniformDistribution.html
// http://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
#include <utility>
namespace boost{ namespace math
{
namespace detail
{
template <class RealType, class Policy>
inline bool check_uniform_lower(
const char* function,
RealType lower,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(lower))
{ // any finite value is OK.
return true;
}
else
{ // Not finite.
*result = policies::raise_domain_error<RealType>(
function,
"Lower parameter is %1%, but must be finite!", lower, pol);
return false;
}
} // bool check_uniform_lower(
template <class RealType, class Policy>
inline bool check_uniform_upper(
const char* function,
RealType upper,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(upper))
{ // Any finite value is OK.
return true;
}
else
{ // Not finite.
*result = policies::raise_domain_error<RealType>(
function,
"Upper parameter is %1%, but must be finite!", upper, pol);
return false;
}
} // bool check_uniform_upper(
template <class RealType, class Policy>
inline bool check_uniform_x(
const char* function,
RealType const& x,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(x))
{ // Any finite value is OK
return true;
}
else
{ // Not finite..
*result = policies::raise_domain_error<RealType>(
function,
"x parameter is %1%, but must be finite!", x, pol);
return false;
}
} // bool check_uniform_x
template <class RealType, class Policy>
inline bool check_uniform(
const char* function,
RealType lower,
RealType upper,
RealType* result, const Policy& pol)
{
if(check_uniform_lower(function, lower, result, pol)
&& check_uniform_upper(function, upper, result, pol)
&& (lower < upper)) // If lower == upper then 1 / (upper-lower) = 1/0 = +infinity!
{
return true;
}
else
{ // upper and lower have been checked before, so must be lower >= upper.
*result = policies::raise_domain_error<RealType>(
function,
"lower parameter is %1%, but must be less than upper!", lower, pol);
return false;
}
} // bool check_uniform(
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class uniform_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
uniform_distribution(RealType lower = 0, RealType upper = 1) // Constructor.
: m_lower(lower), m_upper(upper) // Default is standard uniform distribution.
{
RealType result;
detail::check_uniform("boost::math::uniform_distribution<%1%>::uniform_distribution", lower, upper, &result, Policy());
}
// Accessor functions.
RealType lower()const
{
return m_lower;
}
RealType upper()const
{
return m_upper;
}
private:
// Data members:
RealType m_lower; // distribution lower aka a.
RealType m_upper; // distribution upper aka b.
}; // class uniform_distribution
typedef uniform_distribution<double> uniform;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const uniform_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + infinity
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const uniform_distribution<RealType, Policy>& dist)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(dist.lower(), dist.upper());
}
template <class RealType, class Policy>
inline RealType pdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x)
{
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::pdf(const uniform_distribution<%1%>&, %1%)", lower, upper, &result, Policy()))
{
return result;
}
if(false == detail::check_uniform_x("boost::math::pdf(const uniform_distribution<%1%>&, %1%)", x, &result, Policy()))
{
return result;
}
if((x < lower) || (x > upper) )
{
return 0;
}
else
{
return 1 / (upper - lower);
}
} // RealType pdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x)
template <class RealType, class Policy>
inline RealType cdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x)
{
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::cdf(const uniform_distribution<%1%>&, %1%)",lower, upper, &result, Policy()))
{
return result;
}
if(false == detail::check_uniform_x("boost::math::cdf(const uniform_distribution<%1%>&, %1%)", x, &result, Policy()))
{
return result;
}
if (x < lower)
{
return 0;
}
if (x > upper)
{
return 1;
}
return (x - lower) / (upper - lower); // lower <= x <= upper
} // RealType cdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x)
template <class RealType, class Policy>
inline RealType quantile(const uniform_distribution<RealType, Policy>& dist, const RealType& p)
{
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result; // of checks
if(false == detail::check_uniform("boost::math::quantile(const uniform_distribution<%1%>&, %1%)",lower, upper, &result, Policy()))
{
return result;
}
if(false == detail::check_probability("boost::math::quantile(const uniform_distribution<%1%>&, %1%)", p, &result, Policy()))
{
return result;
}
if(p == 0)
{
return lower;
}
if(p == 1)
{
return upper;
}
return p * (upper - lower) + lower;
} // RealType quantile(const uniform_distribution<RealType, Policy>& dist, const RealType& p)
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c)
{
RealType lower = c.dist.lower();
RealType upper = c.dist.upper();
RealType x = c.param;
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::cdf(const uniform_distribution<%1%>&, %1%)", lower, upper, &result, Policy()))
{
return result;
}
if(false == detail::check_uniform_x("boost::math::cdf(const uniform_distribution<%1%>&, %1%)", x, &result, Policy()))
{
return result;
}
if (x < lower)
{
return 0;
}
if (x > upper)
{
return 1;
}
return (upper - x) / (upper - lower);
} // RealType cdf(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c)
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c)
{
RealType lower = c.dist.lower();
RealType upper = c.dist.upper();
RealType q = c.param;
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::quantile(const uniform_distribution<%1%>&, %1%)", lower, upper, &result, Policy()))
{
return result;
}
if(false == detail::check_probability("boost::math::quantile(const uniform_distribution<%1%>&, %1%)", q, &result, Policy()))
if(q == 0)
{
return lower;
}
if(q == 1)
{
return upper;
}
return -q * (upper - lower) + upper;
} // RealType quantile(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c)
template <class RealType, class Policy>
inline RealType mean(const uniform_distribution<RealType, Policy>& dist)
{
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::mean(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
{
return result;
}
return (lower + upper ) / 2;
} // RealType mean(const uniform_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType variance(const uniform_distribution<RealType, Policy>& dist)
{
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::variance(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
{
return result;
}
return (upper - lower) * ( upper - lower) / 12;
// for standard uniform = 0.833333333333333333333333333333333333333333;
} // RealType variance(const uniform_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType mode(const uniform_distribution<RealType, Policy>& dist)
{
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::mode(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
{
return result;
}
result = lower; // Any value [lower, upper] but arbitrarily choose lower.
return result;
}
template <class RealType, class Policy>
inline RealType median(const uniform_distribution<RealType, Policy>& dist)
{
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::median(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
{
return result;
}
return (lower + upper) / 2; //
}
template <class RealType, class Policy>
inline RealType skewness(const uniform_distribution<RealType, Policy>& dist)
{
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::skewness(const uniform_distribution<%1%>&)",lower, upper, &result, Policy()))
{
return result;
}
return 0;
} // RealType skewness(const uniform_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType kurtosis_excess(const uniform_distribution<RealType, Policy>& dist)
{
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result; // of checks.
if(false == detail::check_uniform("boost::math::kurtosis_execess(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
{
return result;
}
return static_cast<RealType>(-6)/5; // -6/5 = -1.2;
} // RealType kurtosis_excess(const uniform_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType kurtosis(const uniform_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_UNIFORM_HPP

View File

@@ -0,0 +1,382 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STATS_WEIBULL_HPP
#define BOOST_STATS_WEIBULL_HPP
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3668.htm
// http://mathworld.wolfram.com/WeibullDistribution.html
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
#include <utility>
namespace boost{ namespace math
{
namespace detail{
template <class RealType, class Policy>
inline bool check_weibull_shape(
const char* function,
RealType shape,
RealType* result, const Policy& pol)
{
if((shape < 0) || !(boost::math::isfinite)(shape))
{
*result = policies::raise_domain_error<RealType>(
function,
"Shape parameter is %1%, but must be > 0 !", shape, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_weibull_x(
const char* function,
RealType const& x,
RealType* result, const Policy& pol)
{
if((x < 0) || !(boost::math::isfinite)(x))
{
*result = policies::raise_domain_error<RealType>(
function,
"Random variate is %1% but must be >= 0 !", x, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_weibull(
const char* function,
RealType scale,
RealType shape,
RealType* result, const Policy& pol)
{
return check_scale(function, scale, result, pol) && check_weibull_shape(function, shape, result, pol);
}
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class weibull_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
weibull_distribution(RealType shape, RealType scale = 1)
: m_shape(shape), m_scale(scale)
{
RealType result;
detail::check_weibull("boost::math::weibull_distribution<%1%>::weibull_distribution", scale, shape, &result, Policy());
}
RealType shape()const
{
return m_shape;
}
RealType scale()const
{
return m_scale;
}
private:
//
// Data members:
//
RealType m_shape; // distribution shape
RealType m_scale; // distribution scale
};
typedef weibull_distribution<double> weibull;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const weibull_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const weibull_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(0, max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType pdf(const weibull_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::pdf(const weibull_distribution<%1%>, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_weibull_x(function, x, &result, Policy()))
return result;
if(x == 0)
return 0;
result = exp(-pow(x / scale, shape));
result *= pow(x / scale, shape) * shape / x;
return result;
}
template <class RealType, class Policy>
inline RealType cdf(const weibull_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(const weibull_distribution<%1%>, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_weibull_x(function, x, &result, Policy()))
return result;
result = -boost::math::expm1(-pow(x / scale, shape), Policy());
return result;
}
template <class RealType, class Policy>
inline RealType quantile(const weibull_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const weibull_distribution<%1%>, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_probability(function, p, &result, Policy()))
return result;
if(p == 1)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
result = scale * pow(-boost::math::log1p(-p, Policy()), 1 / shape);
return result;
}
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<weibull_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::cdf(const weibull_distribution<%1%>, %1%)";
RealType shape = c.dist.shape();
RealType scale = c.dist.scale();
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_weibull_x(function, c.param, &result, Policy()))
return result;
result = exp(-pow(c.param / scale, shape));
return result;
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<weibull_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const weibull_distribution<%1%>, %1%)";
RealType shape = c.dist.shape();
RealType scale = c.dist.scale();
RealType q = c.param;
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_probability(function, q, &result, Policy()))
return result;
if(q == 0)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
result = scale * pow(-log(q), 1 / shape);
return result;
}
template <class RealType, class Policy>
inline RealType mean(const weibull_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::mean(const weibull_distribution<%1%>)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
result = scale * boost::math::tgamma(1 + 1 / shape, Policy());
return result;
}
template <class RealType, class Policy>
inline RealType variance(const weibull_distribution<RealType, Policy>& dist)
{
RealType shape = dist.shape();
RealType scale = dist.scale();
static const char* function = "boost::math::variance(const weibull_distribution<%1%>)";
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
{
return result;
}
result = boost::math::tgamma(1 + 1 / shape, Policy());
result *= -result;
result += boost::math::tgamma(1 + 2 / shape, Policy());
result *= scale * scale;
return result;
}
template <class RealType, class Policy>
inline RealType mode(const weibull_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std function pow.
static const char* function = "boost::math::mode(const weibull_distribution<%1%>)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
{
return result;
}
result = scale * pow((shape - 1) / shape, 1 / shape);
return result;
}
template <class RealType, class Policy>
inline RealType median(const weibull_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std function pow.
static const char* function = "boost::math::median(const weibull_distribution<%1%>)";
RealType shape = dist.shape(); // Wikipedia k
RealType scale = dist.scale(); // Wikipedia lambda
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
{
return result;
}
using boost::math::constants::ln_two;
result = scale * pow(ln_two<RealType>(), 1 / shape);
return result;
}
template <class RealType, class Policy>
inline RealType skewness(const weibull_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::skewness(const weibull_distribution<%1%>)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
{
return result;
}
RealType g1, g2, g3, d;
g1 = boost::math::tgamma(1 + 1 / shape, Policy());
g2 = boost::math::tgamma(1 + 2 / shape, Policy());
g3 = boost::math::tgamma(1 + 3 / shape, Policy());
d = pow(g2 - g1 * g1, RealType(1.5));
result = (2 * g1 * g1 * g1 - 3 * g1 * g2 + g3) / d;
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const weibull_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::kurtosis_excess(const weibull_distribution<%1%>)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
RealType g1, g2, g3, g4, d, g1_2, g1_4;
g1 = boost::math::tgamma(1 + 1 / shape, Policy());
g2 = boost::math::tgamma(1 + 2 / shape, Policy());
g3 = boost::math::tgamma(1 + 3 / shape, Policy());
g4 = boost::math::tgamma(1 + 4 / shape, Policy());
g1_2 = g1 * g1;
g1_4 = g1_2 * g1_2;
d = g2 - g1_2;
d *= d;
result = -6 * g1_4 + 12 * g1_2 * g2 - 3 * g2 * g2 - 4 * g1 * g3 + g4;
result /= d;
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis(const weibull_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_WEIBULL_HPP

View File

@@ -0,0 +1,509 @@
// Copyright John Maddock 2007.
// Copyright Paul A. Bristow 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP
#define BOOST_MATH_POLICY_ERROR_HANDLING_HPP
#include <stdexcept>
#include <iomanip>
#include <string>
#include <cerrno>
#include <cmath>
#include <stdexcept>
#include <boost/math/tools/config.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/cstdint.hpp>
#ifdef BOOST_MSVC
# pragma warning(push) // Quiet warnings in boost/format.hpp
# pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE
# pragma warning(disable: 4512) // assignment operator could not be generated.
// And warnings in error handling:
# pragma warning(disable: 4702) // unreachable code
// Note that this only occurs when the compiler can deduce code is unreachable,
// for example when policy macros are used to ignore errors rather than throw.
#endif
#include <boost/format.hpp>
namespace boost{ namespace math{
class evaluation_error : public std::runtime_error
{
public:
evaluation_error(const std::string& s) : std::runtime_error(s){}
};
namespace policies{
//
// Forward declarations of user error handlers,
// it's up to the user to provide the definition of these:
//
template <class T>
T user_domain_error(const char* function, const char* message, const T& val);
template <class T>
T user_pole_error(const char* function, const char* message, const T& val);
template <class T>
T user_overflow_error(const char* function, const char* message, const T& val);
template <class T>
T user_underflow_error(const char* function, const char* message, const T& val);
template <class T>
T user_denorm_error(const char* function, const char* message, const T& val);
template <class T>
T user_evaluation_error(const char* function, const char* message, const T& val);
namespace detail
{
template <class E, class T>
void raise_error(const char* function, const char* message)
{
if(function == 0)
function = "Unknown function";
if(message == 0)
message = "Cause unknown";
std::string msg("Error in function ");
msg += (boost::format(function) % typeid(T).name()).str();
msg += ": ";
msg += message;
E e(msg);
boost::throw_exception(e);
}
template <class E, class T>
void raise_error(const char* function, const char* message, const T& val)
{
if(function == 0)
function = "Unknown function";
if(message == 0)
message = "Cause unknown";
std::string msg("Error in function ");
msg += (boost::format(function) % typeid(T).name()).str();
msg += ": ";
msg += message;
int prec = 2 + (boost::math::policies::digits<T, boost::math::policies::policy<> >() * 30103UL) / 100000UL;
msg = (boost::format(msg) % boost::io::group(std::setprecision(prec), val)).str();
E e(msg);
boost::throw_exception(e);
}
template <class T>
inline T raise_domain_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::domain_error, T>(function, message, val);
// we never get here:
return std::numeric_limits<T>::quiet_NaN();
}
template <class T>
inline T raise_domain_error(
const char* ,
const char* ,
const T& ,
const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return std::numeric_limits<T>::quiet_NaN();
}
template <class T>
inline T raise_domain_error(
const char* ,
const char* ,
const T& ,
const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&)
{
errno = EDOM;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return std::numeric_limits<T>::quiet_NaN();
}
template <class T>
inline T raise_domain_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)
{
return user_domain_error(function, message, val);
}
template <class T>
inline T raise_pole_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
{
return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
}
template <class T>
inline T raise_pole_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&)
{
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());
}
template <class T>
inline T raise_pole_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&)
{
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());
}
template <class T>
inline T raise_pole_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)
{
return user_pole_error(function, message, val);
}
template <class T>
inline T raise_overflow_error(
const char* function,
const char* message,
const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
// we never get here:
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
}
template <class T>
inline T raise_overflow_error(
const char* ,
const char* ,
const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
}
template <class T>
inline T raise_overflow_error(
const char* ,
const char* ,
const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
}
template <class T>
inline T raise_overflow_error(
const char* function,
const char* message,
const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
{
return user_overflow_error(function, message, std::numeric_limits<T>::infinity());
}
template <class T>
inline T raise_underflow_error(
const char* function,
const char* message,
const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
// we never get here:
return 0;
}
template <class T>
inline T raise_underflow_error(
const char* ,
const char* ,
const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return T(0);
}
template <class T>
inline T raise_underflow_error(
const char* /* function */,
const char* /* message */,
const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return T(0);
}
template <class T>
inline T raise_underflow_error(
const char* function,
const char* message,
const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)
{
return user_underflow_error(function, message, T(0));
}
template <class T>
inline T raise_denorm_error(
const char* function,
const char* message,
const T& /* val */,
const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");
// we never get here:
return T(0);
}
template <class T>
inline T raise_denorm_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return val;
}
template <class T>
inline T raise_denorm_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return val;
}
template <class T>
inline T raise_denorm_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)
{
return user_denorm_error(function, message, val);
}
template <class T>
inline T raise_evaluation_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<boost::math::evaluation_error, T>(function, message, val);
// we never get here:
return T(0);
}
template <class T>
inline T raise_evaluation_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return val;
}
template <class T>
inline T raise_evaluation_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&)
{
errno = EDOM;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return val;
}
template <class T>
inline T raise_evaluation_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)
{
return user_evaluation_error(function, message, val);
}
} // namespace detail
template <class T, class Policy>
inline T raise_domain_error(const char* function, const char* message, const T& val, const Policy&)
{
typedef typename Policy::domain_error_type policy_type;
return detail::raise_domain_error(
function, message ? message : "Domain Error evaluating function at %1%",
val, policy_type());
}
template <class T, class Policy>
inline T raise_pole_error(const char* function, const char* message, const T& val, const Policy&)
{
typedef typename Policy::pole_error_type policy_type;
return detail::raise_pole_error(
function, message ? message : "Evaluation of function at pole %1%",
val, policy_type());
}
template <class T, class Policy>
inline T raise_overflow_error(const char* function, const char* message, const Policy&)
{
typedef typename Policy::overflow_error_type policy_type;
return detail::raise_overflow_error<T>(
function, message ? message : "Overflow Error",
policy_type());
}
template <class T, class Policy>
inline T raise_underflow_error(const char* function, const char* message, const Policy&)
{
typedef typename Policy::underflow_error_type policy_type;
return detail::raise_underflow_error<T>(
function, message ? message : "Underflow Error",
policy_type());
}
template <class T, class Policy>
inline T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&)
{
typedef typename Policy::denorm_error_type policy_type;
return detail::raise_denorm_error<T>(
function, message ? message : "Denorm Error",
val,
policy_type());
}
template <class T, class Policy>
inline T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&)
{
typedef typename Policy::evaluation_error_type policy_type;
return detail::raise_evaluation_error(
function, message ? message : "Internal Evaluation Error, best value so far was %1%",
val, policy_type());
}
//
// checked_narrowing_cast:
//
namespace detail
{
template <class R, class T, class Policy>
inline bool check_overflow(T val, R* result, const char* function, const Policy& pol)
{
BOOST_MATH_STD_USING
if(fabs(val) > tools::max_value<R>())
{
*result = static_cast<R>(boost::math::policies::detail::raise_overflow_error<R>(function, 0, pol));
return true;
}
return false;
}
template <class R, class T, class Policy>
inline bool check_underflow(T val, R* result, const char* function, const Policy& pol)
{
if((val != 0) && (static_cast<R>(val) == 0))
{
*result = static_cast<R>(boost::math::policies::detail::raise_underflow_error<R>(function, 0, pol));
return true;
}
return false;
}
template <class R, class T, class Policy>
inline bool check_denorm(T val, R* result, const char* function, const Policy& pol)
{
BOOST_MATH_STD_USING
if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))
{
*result = static_cast<R>(boost::math::policies::detail::raise_denorm_error<R>(function, 0, static_cast<R>(val), pol));
return true;
}
return false;
}
// Default instantiations with ignore_error policy.
template <class R, class T>
inline bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&){ return false; }
template <class R, class T>
inline bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&){ return false; }
template <class R, class T>
inline bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&){ return false; }
} // namespace detail
template <class R, class Policy, class T>
inline R checked_narrowing_cast(T val, const char* function)
{
typedef typename Policy::overflow_error_type overflow_type;
typedef typename Policy::underflow_error_type underflow_type;
typedef typename Policy::denorm_error_type denorm_type;
//
// Most of what follows will evaluate to a no-op:
//
R result;
if(detail::check_overflow<R>(val, &result, function, overflow_type()))
return result;
if(detail::check_underflow<R>(val, &result, function, underflow_type()))
return result;
if(detail::check_denorm<R>(val, &result, function, denorm_type()))
return result;
return static_cast<R>(val);
}
template <class Policy>
inline void check_series_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol)
{
if(max_iter >= policies::get_max_series_iterations<Policy>())
raise_evaluation_error<boost::uintmax_t>(
function,
"Series evaluation exceeded %1% iterations, giving up now.", max_iter, pol);
}
} //namespace policies
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
}} // namespaces boost/math
#endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP

View File

@@ -0,0 +1,845 @@
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_POLICY_HPP
#define BOOST_MATH_POLICY_HPP
#define BOOST_PARAMETER_MAX_ARITY 15
#include <boost/mpl/list.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/remove_if.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/comparison.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
#include <boost/assert.hpp>
#include <boost/math/tools/config.hpp>
#include <limits>
// Sadly we do need the .h versions of these to be sure of getting
// FLT_MANT_DIG etc.
#include <limits.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>
namespace boost{ namespace math{
namespace tools{
template <class T>
int digits(BOOST_EXPLICIT_TEMPLATE_TYPE(T));
}
namespace policies{
//
// Define macros for our default policies, if they're not defined already:
//
#ifndef BOOST_MATH_DOMAIN_ERROR_POLICY
#define BOOST_MATH_DOMAIN_ERROR_POLICY throw_on_error
#endif
#ifndef BOOST_MATH_POLE_ERROR_POLICY
#define BOOST_MATH_POLE_ERROR_POLICY throw_on_error
#endif
#ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY
#define BOOST_MATH_OVERFLOW_ERROR_POLICY throw_on_error
#endif
#ifndef BOOST_MATH_EVALUATION_ERROR_POLICY
#define BOOST_MATH_EVALUATION_ERROR_POLICY throw_on_error
#endif
#ifndef BOOST_MATH_UNDERFLOW_ERROR_POLICY
#define BOOST_MATH_UNDERFLOW_ERROR_POLICY ignore_error
#endif
#ifndef BOOST_MATH_DENORM_ERROR_POLICY
#define BOOST_MATH_DENORM_ERROR_POLICY ignore_error
#endif
#ifndef BOOST_MATH_DIGITS10_POLICY
#define BOOST_MATH_DIGITS10_POLICY 0
#endif
#ifndef BOOST_MATH_PROMOTE_FLOAT_POLICY
#define BOOST_MATH_PROMOTE_FLOAT_POLICY true
#endif
#ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY
#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false
#else
#define BOOST_MATH_PROMOTE_DOUBLE_POLICY true
#endif
#endif
#ifndef BOOST_MATH_DISCRETE_QUANTILE_POLICY
#define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_round_outwards
#endif
#ifndef BOOST_MATH_ASSERT_UNDEFINED_POLICY
#define BOOST_MATH_ASSERT_UNDEFINED_POLICY true
#endif
#ifndef BOOST_MATH_MAX_SERIES_ITERATION_POLICY
#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 1000000
#endif
#ifndef BOOST_MATH_MAX_ROOT_ITERATION_POLICY
#define BOOST_MATH_MAX_ROOT_ITERATION_POLICY 200
#endif
#if !defined(__BORLANDC__)
#define BOOST_MATH_META_INT(type, name, Default)\
template <type N = Default> struct name : public boost::mpl::int_<N>{};\
namespace detail{\
template <type N>\
char test_is_valid_arg(const name<N>*);\
char test_is_default_arg(const name<Default>*);\
template <class T> struct is_##name##_imp\
{\
template <type N> static char test(const name<N>*);\
static double test(...);\
BOOST_STATIC_CONSTANT(bool, value = sizeof(test(static_cast<T*>(0))) == 1);\
};\
}\
template <class T> struct is_##name : public boost::mpl::bool_<detail::is_##name##_imp<T>::value>{};
#define BOOST_MATH_META_BOOL(name, Default)\
template <bool N = Default> struct name : public boost::mpl::bool_<N>{};\
namespace detail{\
template <bool N>\
char test_is_valid_arg(const name<N>*);\
char test_is_default_arg(const name<Default>*);\
template <class T> struct is_##name##_imp\
{\
template <bool N> static char test(const name<N>*);\
static double test(...);\
BOOST_STATIC_CONSTANT(bool, value = sizeof(test(static_cast<T*>(0))) == 1);\
};\
}\
template <class T> struct is_##name : public boost::mpl::bool_<detail::is_##name##_imp<T>::value>{};
#else
#define BOOST_MATH_META_INT(Type, name, Default)\
template <Type N = Default> struct name : public boost::mpl::int_<N>{};\
namespace detail{\
template <Type N>\
char test_is_valid_arg(const name<N>*);\
char test_is_default_arg(const name<Default>*);\
template <class T> struct is_##name##_tester\
{\
template <Type N> static char test(const name<N>&);\
static double test(...);\
};\
template <class T> struct is_##name##_imp\
{\
static T inst;\
BOOST_STATIC_CONSTANT(bool, value = sizeof(detail::is_##name##_tester<T>::test(inst)) == 1);\
};\
}\
template <class T> struct is_##name : public boost::mpl::bool_<detail::is_##name##_imp<T>::value>\
{\
template <class U> struct apply{ typedef is_##name<U> type; };\
};
#define BOOST_MATH_META_BOOL(name, Default)\
template <bool N = Default> struct name : public boost::mpl::bool_<N>{};\
namespace detail{\
template <bool N>\
char test_is_valid_arg(const name<N>*);\
char test_is_default_arg(const name<Default>*);\
template <class T> struct is_##name##_tester\
{\
template <bool N> static char test(const name<N>&);\
static double test(...);\
};\
template <class T> struct is_##name##_imp\
{\
static T inst;\
BOOST_STATIC_CONSTANT(bool, value = sizeof(detail::is_##name##_tester<T>::test(inst)) == 1);\
};\
}\
template <class T> struct is_##name : public boost::mpl::bool_<detail::is_##name##_imp<T>::value>\
{\
template <class U> struct apply{ typedef is_##name<U> type; };\
};
#endif
//
// Begin by defining policy types for error handling:
//
enum error_policy_type
{
throw_on_error = 0,
errno_on_error = 1,
ignore_error = 2,
user_error = 3
};
BOOST_MATH_META_INT(error_policy_type, domain_error, BOOST_MATH_DOMAIN_ERROR_POLICY)
BOOST_MATH_META_INT(error_policy_type, pole_error, BOOST_MATH_POLE_ERROR_POLICY)
BOOST_MATH_META_INT(error_policy_type, overflow_error, BOOST_MATH_OVERFLOW_ERROR_POLICY)
BOOST_MATH_META_INT(error_policy_type, underflow_error, BOOST_MATH_UNDERFLOW_ERROR_POLICY)
BOOST_MATH_META_INT(error_policy_type, denorm_error, BOOST_MATH_DENORM_ERROR_POLICY)
BOOST_MATH_META_INT(error_policy_type, evaluation_error, BOOST_MATH_EVALUATION_ERROR_POLICY)
//
// Policy types for internal promotion:
//
BOOST_MATH_META_BOOL(promote_float, BOOST_MATH_PROMOTE_FLOAT_POLICY)
BOOST_MATH_META_BOOL(promote_double, BOOST_MATH_PROMOTE_DOUBLE_POLICY)
BOOST_MATH_META_BOOL(assert_undefined, BOOST_MATH_ASSERT_UNDEFINED_POLICY)
//
// Policy types for discrete quantiles:
//
enum discrete_quantile_policy_type
{
real,
integer_round_outwards,
integer_round_inwards,
integer_round_down,
integer_round_up,
integer_round_nearest
};
BOOST_MATH_META_INT(discrete_quantile_policy_type, discrete_quantile, BOOST_MATH_DISCRETE_QUANTILE_POLICY)
//
// Precision:
//
BOOST_MATH_META_INT(int, digits10, BOOST_MATH_DIGITS10_POLICY)
BOOST_MATH_META_INT(int, digits2, 0)
//
// Iterations:
//
BOOST_MATH_META_INT(unsigned long, max_series_iterations, BOOST_MATH_MAX_SERIES_ITERATION_POLICY)
BOOST_MATH_META_INT(unsigned long, max_root_iterations, BOOST_MATH_MAX_ROOT_ITERATION_POLICY)
//
// Define the names for each possible policy:
//
#define BOOST_MATH_PARAMETER(name)\
BOOST_PARAMETER_TEMPLATE_KEYWORD(name##_name)\
BOOST_PARAMETER_NAME(name##_name)
struct default_policy{};
namespace detail{
//
// Trait to work out bits precision from digits10 and digits2:
//
template <class Digits10, class Digits2>
struct precision
{
//
// Now work out the precision:
//
typedef typename mpl::if_c<
(Digits10::value == 0),
digits2<0>,
digits2<((Digits10::value + 1) * 1000L) / 301L>
>::type digits2_type;
public:
#ifdef __BORLANDC__
typedef typename mpl::if_c<
(Digits2::value > ::boost::math::policies::detail::precision<Digits10,Digits2>::digits2_type::value),
Digits2, digits2_type>::type type;
#else
typedef typename mpl::if_c<
(Digits2::value > digits2_type::value),
Digits2, digits2_type>::type type;
#endif
};
template <class A, class B, bool b>
struct select_result
{
typedef A type;
};
template <class A, class B>
struct select_result<A, B, false>
{
typedef typename mpl::deref<B>::type type;
};
template <class Seq, class Pred, class DefaultType>
struct find_arg
{
private:
typedef typename mpl::find_if<Seq, Pred>::type iter;
typedef typename mpl::end<Seq>::type end_type;
public:
typedef typename select_result<
DefaultType, iter,
::boost::is_same<iter, end_type>::value>::type type;
};
double test_is_valid_arg(...);
double test_is_default_arg(...);
char test_is_valid_arg(const default_policy*);
char test_is_default_arg(const default_policy*);
template <class T>
struct is_valid_policy_imp
{
BOOST_STATIC_CONSTANT(bool, value = sizeof(test_is_valid_arg(static_cast<T*>(0))) == 1);
};
template <class T>
struct is_default_policy_imp
{
BOOST_STATIC_CONSTANT(bool, value = sizeof(test_is_default_arg(static_cast<T*>(0))) == 1);
};
template <class T> struct is_valid_policy
: public mpl::bool_<
::boost::math::policies::detail::is_valid_policy_imp<T>::value>
{};
template <class T> struct is_default_policy
: public mpl::bool_<
::boost::math::policies::detail::is_default_policy_imp<T>::value>
{
template <class U>
struct apply
{
typedef is_default_policy<U> type;
};
};
template <class Seq, class T, int N>
struct append_N
{
typedef typename mpl::push_back<Seq, T>::type new_seq;
typedef typename append_N<new_seq, T, N-1>::type type;
};
template <class Seq, class T>
struct append_N<Seq, T, 0>
{
typedef Seq type;
};
//
// Traits class to work out what template parameters our default
// policy<> class will have when modified for forwarding:
//
template <bool f, bool d>
struct default_args
{
typedef promote_float<false> arg1;
typedef promote_double<false> arg2;
};
template <>
struct default_args<false, false>
{
typedef default_policy arg1;
typedef default_policy arg2;
};
template <>
struct default_args<true, false>
{
typedef promote_float<false> arg1;
typedef default_policy arg2;
};
template <>
struct default_args<false, true>
{
typedef promote_double<false> arg1;
typedef default_policy arg2;
};
typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;
typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg2 forwarding_arg2;
} // detail
//
// Now define the policy type with enough arguments to handle all
// the policies:
//
template <class A1 = default_policy,
class A2 = default_policy,
class A3 = default_policy,
class A4 = default_policy,
class A5 = default_policy,
class A6 = default_policy,
class A7 = default_policy,
class A8 = default_policy,
class A9 = default_policy,
class A10 = default_policy,
class A11 = default_policy,
class A12 = default_policy,
class A13 = default_policy>
struct policy
{
private:
//
// Validate all our arguments:
//
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A1>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A2>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A3>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A4>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A5>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A6>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A7>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A8>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A9>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A10>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A11>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A12>::value);
BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A13>::value);
//
// Typelist of the arguments:
//
typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
public:
typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, domain_error<> >::type domain_error_type;
typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, pole_error<> >::type pole_error_type;
typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, overflow_error<> >::type overflow_error_type;
typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, underflow_error<> >::type underflow_error_type;
typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, denorm_error<> >::type denorm_error_type;
typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, evaluation_error<> >::type evaluation_error_type;
private:
//
// Now work out the precision:
//
typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, digits2<> >::type bits_precision_type;
public:
typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
//
// Internal promotion:
//
typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, promote_float<> >::type promote_float_type;
typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, promote_double<> >::type promote_double_type;
//
// Discrete quantiles:
//
typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, discrete_quantile<> >::type discrete_quantile_type;
//
// Mathematically undefined properties:
//
typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, discrete_quantile<> >::type assert_undefined_type;
//
// Max iterations:
//
typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, max_series_iterations<> >::type max_series_iterations_type;
typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, max_root_iterations<> >::type max_root_iterations_type;
};
//
// These full specializations are defined to reduce the amount of
// template instantiations that have to take place when using the default
// policies, they have quite a large impact on compile times:
//
template <>
struct policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
{
public:
typedef domain_error<> domain_error_type;
typedef pole_error<> pole_error_type;
typedef overflow_error<> overflow_error_type;
typedef underflow_error<> underflow_error_type;
typedef denorm_error<> denorm_error_type;
typedef evaluation_error<> evaluation_error_type;
#if BOOST_MATH_DIGITS10_POLICY == 0
typedef digits2<> precision_type;
#else
typedef detail::precision<digits10<>, digits2<> >::type precision_type;
#endif
typedef promote_float<> promote_float_type;
typedef promote_double<> promote_double_type;
typedef discrete_quantile<> discrete_quantile_type;
typedef assert_undefined<> assert_undefined_type;
typedef max_series_iterations<> max_series_iterations_type;
typedef max_root_iterations<> max_root_iterations_type;
};
template <>
struct policy<detail::forwarding_arg1, detail::forwarding_arg2, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
{
public:
typedef domain_error<> domain_error_type;
typedef pole_error<> pole_error_type;
typedef overflow_error<> overflow_error_type;
typedef underflow_error<> underflow_error_type;
typedef denorm_error<> denorm_error_type;
typedef evaluation_error<> evaluation_error_type;
#if BOOST_MATH_DIGITS10_POLICY == 0
typedef digits2<> precision_type;
#else
typedef detail::precision<digits10<>, digits2<> >::type precision_type;
#endif
typedef promote_float<false> promote_float_type;
typedef promote_double<false> promote_double_type;
typedef discrete_quantile<> discrete_quantile_type;
typedef assert_undefined<> assert_undefined_type;
typedef max_series_iterations<> max_series_iterations_type;
typedef max_root_iterations<> max_root_iterations_type;
};
template <class Policy,
class A1 = default_policy,
class A2 = default_policy,
class A3 = default_policy,
class A4 = default_policy,
class A5 = default_policy,
class A6 = default_policy,
class A7 = default_policy,
class A8 = default_policy,
class A9 = default_policy,
class A10 = default_policy,
class A11 = default_policy,
class A12 = default_policy,
class A13 = default_policy>
struct normalise
{
private:
typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, typename Policy::domain_error_type >::type domain_error_type;
typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, typename Policy::pole_error_type >::type pole_error_type;
typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, typename Policy::overflow_error_type >::type overflow_error_type;
typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, typename Policy::underflow_error_type >::type underflow_error_type;
typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, typename Policy::denorm_error_type >::type denorm_error_type;
typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, typename Policy::evaluation_error_type >::type evaluation_error_type;
//
// Now work out the precision:
//
typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, typename Policy::precision_type >::type bits_precision_type;
typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
//
// Internal promotion:
//
typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, typename Policy::promote_float_type >::type promote_float_type;
typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, typename Policy::promote_double_type >::type promote_double_type;
//
// Discrete quantiles:
//
typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, typename Policy::discrete_quantile_type >::type discrete_quantile_type;
//
// Mathematically undefined properties:
//
typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, discrete_quantile<> >::type assert_undefined_type;
//
// Max iterations:
//
typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, max_series_iterations<> >::type max_series_iterations_type;
typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, max_root_iterations<> >::type max_root_iterations_type;
//
// Define a typelist of the policies:
//
typedef mpl::vector<
domain_error_type,
pole_error_type,
overflow_error_type,
underflow_error_type,
denorm_error_type,
evaluation_error_type,
precision_type,
promote_float_type,
promote_double_type,
discrete_quantile_type,
assert_undefined_type,
max_series_iterations_type,
max_root_iterations_type> result_list;
//
// Remove all the policies that are the same as the default:
//
typedef typename mpl::remove_if<result_list, detail::is_default_policy<mpl::_> >::type reduced_list;
//
// Pad out the list with defaults:
//
typedef typename detail::append_N<reduced_list, default_policy, (14 - ::boost::mpl::size<reduced_list>::value)>::type result_type;
public:
typedef policy<
typename mpl::at<result_type, mpl::int_<0> >::type,
typename mpl::at<result_type, mpl::int_<1> >::type,
typename mpl::at<result_type, mpl::int_<2> >::type,
typename mpl::at<result_type, mpl::int_<3> >::type,
typename mpl::at<result_type, mpl::int_<4> >::type,
typename mpl::at<result_type, mpl::int_<5> >::type,
typename mpl::at<result_type, mpl::int_<6> >::type,
typename mpl::at<result_type, mpl::int_<7> >::type,
typename mpl::at<result_type, mpl::int_<8> >::type,
typename mpl::at<result_type, mpl::int_<9> >::type,
typename mpl::at<result_type, mpl::int_<10> >::type,
typename mpl::at<result_type, mpl::int_<11> >::type,
typename mpl::at<result_type, mpl::int_<12> >::type > type;
};
//
// Full specialisation to speed up compilation of the common case:
//
template <>
struct normalise<policy<>,
promote_float<false>,
promote_double<false>,
discrete_quantile<>,
assert_undefined<>,
default_policy,
default_policy,
default_policy,
default_policy,
default_policy,
default_policy,
default_policy>
{
typedef policy<detail::forwarding_arg1, detail::forwarding_arg2> type;
};
inline policy<> make_policy()
{ return policy<>(); }
template <class A1>
inline typename normalise<policy<>, A1>::type make_policy(const A1&)
{
typedef typename normalise<policy<>, A1>::type result_type;
return result_type();
}
template <class A1, class A2>
inline typename normalise<policy<>, A1, A2>::type make_policy(const A1&, const A2&)
{
typedef typename normalise<policy<>, A1, A2>::type result_type;
return result_type();
}
template <class A1, class A2, class A3>
inline typename normalise<policy<>, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&)
{
typedef typename normalise<policy<>, A1, A2, A3>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4>
inline typename normalise<policy<>, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&)
{
typedef typename normalise<policy<>, A1, A2, A3, A4>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5>
inline typename normalise<policy<>, A1, A2, A3, A4, A5>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&)
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6>
inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&)
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&)
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&)
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&)
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&)
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type result_type;
return result_type();
}
//
// Traits class to handle internal promotion:
//
template <class Real, class Policy>
struct evaluation
{
typedef Real type;
};
template <class Policy>
struct evaluation<float, Policy>
{
typedef typename mpl::if_<typename Policy::promote_float_type, double, float>::type type;
};
template <class Policy>
struct evaluation<double, Policy>
{
typedef typename mpl::if_<typename Policy::promote_double_type, long double, double>::type type;
};
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
template <class Real>
struct basic_digits : public mpl::int_<0>{ };
template <>
struct basic_digits<float> : public mpl::int_<FLT_MANT_DIG>{ };
template <>
struct basic_digits<double> : public mpl::int_<DBL_MANT_DIG>{ };
template <>
struct basic_digits<long double> : public mpl::int_<LDBL_MANT_DIG>{ };
template <class Real, class Policy>
struct precision
{
typedef typename Policy::precision_type precision_type;
typedef basic_digits<Real> digits_t;
typedef typename mpl::if_<
mpl::equal_to<digits_t, mpl::int_<0> >,
// Possibly unknown precision:
precision_type,
typename mpl::if_<
mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, mpl::int_<0> > >,
// Default case, full precision for RealType:
digits2< ::std::numeric_limits<Real>::digits>,
// User customised precision:
precision_type
>::type
>::type type;
};
template <class Policy>
struct precision<float, Policy>
{
typedef digits2<FLT_MANT_DIG> type;
};
template <class Policy>
struct precision<double, Policy>
{
typedef digits2<DBL_MANT_DIG> type;
};
template <class Policy>
struct precision<long double, Policy>
{
typedef digits2<LDBL_MANT_DIG> type;
};
#else
template <class Real, class Policy>
struct precision
{
#ifndef __BORLANDC__
typedef typename Policy::precision_type precision_type;
typedef typename mpl::if_c<
((::std::numeric_limits<Real>::is_specialized == 0) || (::std::numeric_limits<Real>::digits == 0)),
// Possibly unknown precision:
precision_type,
typename mpl::if_c<
((::std::numeric_limits<Real>::digits <= precision_type::value)
|| (Policy::precision_type::value <= 0)),
// Default case, full precision for RealType:
digits2< ::std::numeric_limits<Real>::digits>,
// User customised precision:
precision_type
>::type
>::type type;
#else
typedef typename Policy::precision_type precision_type;
typedef mpl::int_< ::std::numeric_limits<Real>::digits> digits_t;
typedef mpl::bool_< ::std::numeric_limits<Real>::is_specialized> spec_t;
typedef typename mpl::if_<
mpl::or_<mpl::equal_to<spec_t, mpl::false_>, mpl::equal_to<digits_t, mpl::int_<0> > >,
// Possibly unknown precision:
precision_type,
typename mpl::if_<
mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, mpl::int_<0> > >,
// Default case, full precision for RealType:
digits2< ::std::numeric_limits<Real>::digits>,
// User customised precision:
precision_type
>::type
>::type type;
#endif
};
#endif
namespace detail{
template <class T, class Policy>
inline int digits_imp(mpl::true_ const&)
{
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
#else
BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
#endif
typedef typename boost::math::policies::precision<T, Policy>::type p_t;
return p_t::value;
}
template <class T, class Policy>
inline int digits_imp(mpl::false_ const&)
{
return tools::digits<T>();
}
} // namespace detail
template <class T, class Policy>
inline int digits()
{
typedef mpl::bool_< std::numeric_limits<T>::is_specialized > tag_type;
return detail::digits_imp<T, Policy>(tag_type());
}
template <class Policy>
inline unsigned long get_max_series_iterations()
{
typedef typename Policy::max_series_iterations_type iter_type;
return iter_type::value;
}
template <class Policy>
inline unsigned long get_max_root_iterations()
{
typedef typename Policy::max_root_iterations_type iter_type;
return iter_type::value;
}
namespace detail{
template <class A1,
class A2,
class A3,
class A4,
class A5,
class A6,
class A7,
class A8,
class A9,
class A10,
class A11>
char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
double test_is_policy(...);
template <class P>
struct is_policy_imp
{
BOOST_STATIC_CONSTANT(bool, value = (sizeof(test_is_policy(static_cast<P*>(0))) == 1));
};
}
template <class P>
struct is_policy : public mpl::bool_< ::boost::math::policies::detail::is_policy_imp<P>::value> {};
}}} // namespaces
#endif // BOOST_MATH_POLICY_HPP

View File

@@ -0,0 +1,51 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2006, 2007.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// This file includes *all* the special functions.
// this may be useful if many are used
// - to avoid including each function individually.
#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_HPP
#define BOOST_MATH_SPECIAL_FUNCTIONS_HPP
#include <boost/math/special_functions/acosh.hpp>
#include <boost/math/special_functions/asinh.hpp>
#include <boost/math/special_functions/atanh.hpp>
#include <boost/math/special_functions/bessel.hpp>
#include <boost/math/special_functions/beta.hpp>
#include <boost/math/special_functions/binomial.hpp>
#include <boost/math/special_functions/cbrt.hpp>
#include <boost/math/special_functions/cos_pi.hpp>
#include <boost/math/special_functions/digamma.hpp>
#include <boost/math/special_functions/ellint_1.hpp>
#include <boost/math/special_functions/ellint_2.hpp>
#include <boost/math/special_functions/ellint_3.hpp>
#include <boost/math/special_functions/ellint_rc.hpp>
#include <boost/math/special_functions/ellint_rd.hpp>
#include <boost/math/special_functions/ellint_rf.hpp>
#include <boost/math/special_functions/ellint_rj.hpp>
#include <boost/math/special_functions/erf.hpp>
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/special_functions/factorials.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/special_functions/hermite.hpp>
#include <boost/math/special_functions/hypot.hpp>
#include <boost/math/special_functions/laguerre.hpp>
#include <boost/math/special_functions/lanczos.hpp>
#include <boost/math/special_functions/legendre.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/powm1.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <boost/math/special_functions/sin_pi.hpp>
#include <boost/math/special_functions/sinc.hpp>
#include <boost/math/special_functions/sinhc.hpp>
#include <boost/math/special_functions/spherical_harmonic.hpp>
#include <boost/math/special_functions/sqrt1pm1.hpp>
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_HPP

View File

@@ -12,13 +12,10 @@
#include <cmath>
#include <limits>
#include <string>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
// This is the inverse of the hyperbolic cosine function.
@@ -26,6 +23,8 @@ namespace boost
{
namespace math
{
namespace detail
{
#if defined(__GNUC__) && (__GNUC__ < 3)
// gcc 2.x ignores function scope using declarations,
// put them in the scope of the enclosing namespace instead:
@@ -37,39 +36,25 @@ namespace boost
using ::std::numeric_limits;
#endif
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
// This is the main fare
template<typename T>
inline T acosh(const T x)
template<typename T, typename Policy>
inline T acosh_imp(const T x, const Policy& pol)
{
using ::std::abs;
using ::std::sqrt;
using ::std::log;
using ::std::numeric_limits;
T const one = static_cast<T>(1);
T const two = static_cast<T>(2);
static T const taylor_2_bound = sqrt(numeric_limits<T>::epsilon());
static T const taylor_2_bound = sqrt(tools::epsilon<T>());
static T const taylor_n_bound = sqrt(taylor_2_bound);
static T const upper_taylor_2_bound = one/taylor_2_bound;
if (x < one)
if(x < one)
{
if (numeric_limits<T>::has_quiet_NaN)
{
return(numeric_limits<T>::quiet_NaN());
}
else
{
::std::string error_reporting("Argument to atanh is strictly greater than +1 or strictly smaller than -1!");
::std::domain_error bad_argument(error_reporting);
throw(bad_argument);
}
return policies::raise_domain_error<T>(
"boost::math::acosh<%1%>(%1%)",
"acosh requires x >= 1, but got x = %1%.", x, pol);
}
else if (x >= taylor_n_bound)
{
@@ -101,98 +86,27 @@ namespace boost
return(sqrt(static_cast<T>(2))*result);
}
}
#else
// These are implementation details (for main fare see below)
namespace detail
}
template<typename T, typename Policy>
inline typename tools::promote_args<T>::type acosh(const T x, const Policy& pol)
{
template <
typename T,
bool QuietNanSupported
>
struct acosh_helper2_t
{
static T get_NaN()
{
return(::std::numeric_limits<T>::quiet_NaN());
}
}; // boost::detail::acosh_helper2_t
template<typename T>
struct acosh_helper2_t<T, false>
{
static T get_NaN()
{
::std::string error_reporting("Argument to acosh is greater than or equal to +1!");
::std::domain_error bad_argument(error_reporting);
throw(bad_argument);
}
}; // boost::detail::acosh_helper2_t
} // boost::detail
// This is the main fare
template<typename T>
inline T acosh(const T x)
{
using ::std::abs;
using ::std::sqrt;
using ::std::log;
using ::std::numeric_limits;
typedef detail::acosh_helper2_t<T, std::numeric_limits<T>::has_quiet_NaN> helper2_type;
T const one = static_cast<T>(1);
T const two = static_cast<T>(2);
static T const taylor_2_bound = sqrt(numeric_limits<T>::epsilon());
static T const taylor_n_bound = sqrt(taylor_2_bound);
static T const upper_taylor_2_bound = one/taylor_2_bound;
if (x < one)
{
return(helper2_type::get_NaN());
}
else if (x >= taylor_n_bound)
{
if (x > upper_taylor_2_bound)
{
// approximation by laurent series in 1/x at 0+ order from -1 to 0
return( log( x*two) );
}
else
{
return( log( x + sqrt(x*x-one) ) );
}
}
else
{
T y = sqrt(x-one);
// approximation by taylor series in y at 0 up to order 2
T result = y;
if (y >= taylor_2_bound)
{
T y3 = y*y*y;
// approximation by taylor series in y at 0 up to order 4
result -= y3/static_cast<T>(12);
}
return(sqrt(static_cast<T>(2))*result);
}
typedef typename tools::promote_args<T>::type result_type;
return detail::acosh_imp(
static_cast<result_type>(x), pol);
}
#endif /* defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) */
template<typename T>
inline typename tools::promote_args<T>::type acosh(const T x)
{
typedef typename tools::promote_args<T>::type result_type;
return detail::acosh_imp(
static_cast<result_type>(x), policies::policy<>());
}
}
}
#endif /* BOOST_ACOSH_HPP */

View File

@@ -12,13 +12,9 @@
#include <cmath>
#include <limits>
#include <string>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
// This is the inverse of the hyperbolic sine function.
@@ -26,6 +22,7 @@ namespace boost
{
namespace math
{
namespace detail{
#if defined(__GNUC__) && (__GNUC__ < 3)
// gcc 2.x ignores function scope using declarations,
// put them in the scope of the enclosing namespace instead:
@@ -38,19 +35,16 @@ namespace boost
#endif
template<typename T>
inline T asinh(const T x)
inline T asinh_imp(const T x)
{
using ::std::abs;
using ::std::sqrt;
using ::std::log;
using ::std::numeric_limits;
T const one = static_cast<T>(1);
T const two = static_cast<T>(2);
static T const taylor_2_bound = sqrt(numeric_limits<T>::epsilon());
static T const taylor_2_bound = sqrt(tools::epsilon<T>());
static T const taylor_n_bound = sqrt(taylor_2_bound);
static T const upper_taylor_2_bound = one/taylor_2_bound;
static T const upper_taylor_n_bound = one/taylor_n_bound;
@@ -95,6 +89,23 @@ namespace boost
return(result);
}
}
}
template<typename T>
inline typename tools::promote_args<T>::type asinh(const T x)
{
typedef typename tools::promote_args<T>::type result_type;
return detail::asinh_imp(
static_cast<result_type>(x));
}
template<typename T, typename Policy>
inline typename tools::promote_args<T>::type asinh(const T x, const Policy&)
{
typedef typename tools::promote_args<T>::type result_type;
return detail::asinh_imp(
static_cast<result_type>(x));
}
}
}

View File

@@ -12,13 +12,10 @@
#include <cmath>
#include <limits>
#include <string>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
// This is the inverse of the hyperbolic tangent function.
@@ -26,6 +23,8 @@ namespace boost
{
namespace math
{
namespace detail
{
#if defined(__GNUC__) && (__GNUC__ < 3)
// gcc 2.x ignores function scope using declarations,
// put them in the scope of the enclosing namespace instead:
@@ -37,11 +36,10 @@ namespace boost
using ::std::numeric_limits;
#endif
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
// This is the main fare
template<typename T>
inline T atanh(const T x)
template<typename T, typename Policy>
inline T atanh_imp(const T x, const Policy& pol)
{
using ::std::abs;
using ::std::sqrt;
@@ -52,64 +50,32 @@ namespace boost
T const one = static_cast<T>(1);
T const two = static_cast<T>(2);
static T const taylor_2_bound = sqrt(numeric_limits<T>::epsilon());
static T const taylor_2_bound = sqrt(tools::epsilon<T>());
static T const taylor_n_bound = sqrt(taylor_2_bound);
static const char* function = "boost::math::atanh<%1%>(%1%)";
if (x < -one)
{
if (numeric_limits<T>::has_quiet_NaN)
{
return(numeric_limits<T>::quiet_NaN());
}
else
{
::std::string error_reporting("Argument to atanh is strictly greater than +1 or strictly smaller than -1!");
::std::domain_error bad_argument(error_reporting);
throw(bad_argument);
}
return policies::raise_domain_error<T>(
function,
"atanh requires x >= -1, but got x = %1%.", x, pol);
}
else if (x < -one+numeric_limits<T>::epsilon())
else if (x < -one + tools::epsilon<T>())
{
if (numeric_limits<T>::has_infinity)
{
return(-numeric_limits<T>::infinity());
}
else
{
::std::string error_reporting("Argument to atanh is -1 (result: -Infinity)!");
::std::out_of_range bad_argument(error_reporting);
throw(bad_argument);
}
// -Infinity:
return -policies::raise_overflow_error<T>(function, 0, pol);
}
else if (x > +one-numeric_limits<T>::epsilon())
else if (x > one - tools::epsilon<T>())
{
if (numeric_limits<T>::has_infinity)
{
return(+numeric_limits<T>::infinity());
}
else
{
::std::string error_reporting("Argument to atanh is +1 (result: +Infinity)!");
::std::out_of_range bad_argument(error_reporting);
throw(bad_argument);
}
// Infinity:
return -policies::raise_overflow_error<T>(function, 0, pol);
}
else if (x > +one)
{
if (numeric_limits<T>::has_quiet_NaN)
{
return(numeric_limits<T>::quiet_NaN());
}
else
{
::std::string error_reporting("Argument to atanh is strictly greater than +1 or strictly smaller than -1!");
::std::domain_error bad_argument(error_reporting);
throw(bad_argument);
}
return policies::raise_domain_error<T>(
function,
"atanh requires x <= 1, but got x = %1%.", x, pol);
}
else if (abs(x) >= taylor_n_bound)
{
@@ -131,137 +97,26 @@ namespace boost
return(result);
}
}
#else
// These are implementation details (for main fare see below)
namespace detail
}
template<typename T, typename Policy>
inline typename tools::promote_args<T>::type atanh(const T x, const Policy& pol)
{
template <
typename T,
bool InfinitySupported
>
struct atanh_helper1_t
{
static T get_pos_infinity()
{
return(+::std::numeric_limits<T>::infinity());
}
static T get_neg_infinity()
{
return(-::std::numeric_limits<T>::infinity());
}
}; // boost::math::detail::atanh_helper1_t
template<typename T>
struct atanh_helper1_t<T, false>
{
static T get_pos_infinity()
{
::std::string error_reporting("Argument to atanh is +1 (result: +Infinity)!");
::std::out_of_range bad_argument(error_reporting);
throw(bad_argument);
}
static T get_neg_infinity()
{
::std::string error_reporting("Argument to atanh is -1 (result: -Infinity)!");
::std::out_of_range bad_argument(error_reporting);
throw(bad_argument);
}
}; // boost::math::detail::atanh_helper1_t
template <
typename T,
bool QuietNanSupported
>
struct atanh_helper2_t
{
static T get_NaN()
{
return(::std::numeric_limits<T>::quiet_NaN());
}
}; // boost::detail::atanh_helper2_t
template<typename T>
struct atanh_helper2_t<T, false>
{
static T get_NaN()
{
::std::string error_reporting("Argument to atanh is strictly greater than +1 or strictly smaller than -1!");
::std::domain_error bad_argument(error_reporting);
throw(bad_argument);
}
}; // boost::detail::atanh_helper2_t
} // boost::detail
// This is the main fare
typedef typename tools::promote_args<T>::type result_type;
return detail::atanh_imp(
static_cast<result_type>(x), pol);
}
template<typename T>
inline T atanh(const T x)
inline typename tools::promote_args<T>::type atanh(const T x)
{
using ::std::abs;
using ::std::sqrt;
using ::std::log;
using ::std::numeric_limits;
typedef detail::atanh_helper1_t<T, ::std::numeric_limits<T>::has_infinity> helper1_type;
typedef detail::atanh_helper2_t<T, ::std::numeric_limits<T>::has_quiet_NaN> helper2_type;
T const one = static_cast<T>(1);
T const two = static_cast<T>(2);
static T const taylor_2_bound = sqrt(numeric_limits<T>::epsilon());
static T const taylor_n_bound = sqrt(taylor_2_bound);
if (x < -one)
{
return(helper2_type::get_NaN());
}
else if (x < -one+numeric_limits<T>::epsilon())
{
return(helper1_type::get_neg_infinity());
}
else if (x > +one-numeric_limits<T>::epsilon())
{
return(helper1_type::get_pos_infinity());
}
else if (x > +one)
{
return(helper2_type::get_NaN());
}
else if (abs(x) >= taylor_n_bound)
{
return(log( (one + x) / (one - x) ) / two);
}
else
{
// approximation by taylor series in x at 0 up to order 2
T result = x;
if (abs(x) >= taylor_2_bound)
{
T x3 = x*x*x;
// approximation by taylor series in x at 0 up to order 4
result += x3/static_cast<T>(3);
}
return(result);
}
typedef typename tools::promote_args<T>::type result_type;
return detail::atanh_imp(
static_cast<result_type>(x), policies::policy<>());
}
#endif /* defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) */
}
}
#endif /* BOOST_ATANH_HPP */

View File

@@ -0,0 +1,474 @@
// Copyright (c) 2007 John Maddock
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This header just defines the function entry points, and adds dispatch
// to the right implementation method. Most of the implementation details
// are in separate headers and copyright Xiaogang Zhang.
//
#ifndef BOOST_MATH_BESSEL_HPP
#define BOOST_MATH_BESSEL_HPP
#include <boost/math/special_functions/detail/bessel_jy.hpp>
#include <boost/math/special_functions/detail/bessel_jn.hpp>
#include <boost/math/special_functions/detail/bessel_yn.hpp>
#include <boost/math/special_functions/detail/bessel_ik.hpp>
#include <boost/math/special_functions/detail/bessel_i0.hpp>
#include <boost/math/special_functions/detail/bessel_i1.hpp>
#include <boost/math/special_functions/detail/bessel_kn.hpp>
#include <boost/math/special_functions/sin_pi.hpp>
#include <boost/math/special_functions/cos_pi.hpp>
#include <boost/math/special_functions/sinc.hpp>
#include <boost/math/tools/rational.hpp>
#include <boost/math/tools/promotion.hpp>
namespace boost{ namespace math{
namespace detail{
template <class T, class Policy>
struct bessel_j_small_z_series_term
{
typedef T result_type;
bessel_j_small_z_series_term(T v_, T x)
: N(0), v(v_)
{
BOOST_MATH_STD_USING
mult = x / 2;
term = pow(mult, v) / boost::math::tgamma(v+1, Policy());
mult *= -mult;
}
T operator()()
{
T r = term;
++N;
term *= mult / (N * (N + v));
return r;
}
private:
unsigned N;
T v;
T mult;
T term;
};
template <class T, class Policy>
struct sph_bessel_j_small_z_series_term
{
typedef T result_type;
sph_bessel_j_small_z_series_term(unsigned v_, T x)
: N(0), v(v_)
{
BOOST_MATH_STD_USING
mult = x / 2;
term = pow(mult, T(v)) / boost::math::tgamma(v+1+T(0.5f), Policy());
mult *= -mult;
}
T operator()()
{
T r = term;
++N;
term *= mult / (N * T(N + v + 0.5f));
return r;
}
private:
unsigned N;
unsigned v;
T mult;
T term;
};
template <class T, class Policy>
inline T bessel_j_small_z_series(T v, T x, const Policy& pol)
{
bessel_j_small_z_series_term<T, Policy> s(v, x);
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T result = boost::math::tools::sum_series(s, boost::math::policies::digits<T, Policy>(), max_iter);
policies::check_series_iterations("boost::math::bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
return result;
}
template <class T, class Policy>
inline T sph_bessel_j_small_z_series(unsigned v, T x, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names
sph_bessel_j_small_z_series_term<T, Policy> s(v, x);
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T result = boost::math::tools::sum_series(s, boost::math::policies::digits<T, Policy>(), max_iter);
policies::check_series_iterations("boost::math::sph_bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
return result * sqrt(constants::pi<T>() / 4);
}
template <class T, class Policy>
T cyl_bessel_j_imp(T v, T x, const bessel_no_int_tag& t, const Policy& pol)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::bessel_j<%1%>(%1%,%1%)";
if(x < 0)
{
// better have integer v:
if(floor(v) == v)
{
T r = cyl_bessel_j_imp(v, -x, t, pol);
if(tools::real_cast<int>(v) & 1)
r = -r;
return r;
}
else
return policies::raise_domain_error<T>(
function,
"Got x = %1%, but we need x >= 0", x, pol);
}
if(x == 0)
return (v == 0) ? 1 : (v > 0) ? 0 :
policies::raise_domain_error<T>(
function,
"Got v = %1%, but require v >= 0 or a negative integer: the result would be complex.", v, pol);
if((v >= 0) && ((x < 1) || (v > x * x / 4)))
{
return bessel_j_small_z_series(v, x, pol);
}
T j, y;
bessel_jy(v, x, &j, &y, need_j, pol);
return j;
}
template <class T, class Policy>
inline T cyl_bessel_j_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names.
typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
if((fabs(v) < 200) && (floor(v) == v))
{
if(fabs(x) > asymptotic_bessel_j_limit<T>(v, tag_type()))
return asymptotic_bessel_j_large_x_2(v, x);
else
return bessel_jn(tools::real_cast<int>(v), x, pol);
}
return cyl_bessel_j_imp(v, x, bessel_no_int_tag(), pol);
}
template <class T, class Policy>
inline T cyl_bessel_j_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
{
BOOST_MATH_STD_USING
typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
if(fabs(x) > asymptotic_bessel_j_limit<T>(abs(v), tag_type()))
{
T r = asymptotic_bessel_j_large_x_2(static_cast<T>(abs(v)), x);
if((v < 0) && (v & 1))
r = -r;
return r;
}
else
return bessel_jn(v, x, pol);
}
template <class T, class Policy>
inline T sph_bessel_j_imp(unsigned n, T x, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names
if(x < 0)
return policies::raise_domain_error<T>(
"boost::math::sph_bessel_j<%1%>(%1%,%1%)",
"Got x = %1%, but function requires x > 0.", x, pol);
//
// Special case, n == 0 resolves down to the sinus cardinal of x:
//
if(n == 0)
return boost::math::sinc_pi(x, pol);
//
// When x is small we may end up with 0/0, use series evaluation
// instead, especially as it converges rapidly:
//
if(x < 1)
return sph_bessel_j_small_z_series(n, x, pol);
//
// Default case is just a naive evaluation of the definition:
//
return sqrt(constants::pi<T>() / (2 * x))
* cyl_bessel_j_imp(T(n)+T(0.5f), x, bessel_no_int_tag(), pol);
}
template <class T, class Policy>
T cyl_bessel_i_imp(T v, T x, const Policy& pol)
{
//
// This handles all the bessel I functions, note that we don't optimise
// for integer v, other than the v = 0 or 1 special cases, as Millers
// algorithm is at least as inefficient as the general case (the general
// case has better error handling too).
//
BOOST_MATH_STD_USING
if(x < 0)
{
// better have integer v:
if(floor(v) == v)
{
T r = cyl_bessel_i_imp(v, -x, pol);
if(tools::real_cast<int>(v) & 1)
r = -r;
return r;
}
else
return policies::raise_domain_error<T>(
"boost::math::cyl_bessel_i<%1%>(%1%,%1%)",
"Got x = %1%, but we need x >= 0", x, pol);
}
if(x == 0)
{
return (v == 0) ? 1 : 0;
}
if(v == 0.5f)
{
// common special case, note try and avoid overflow in exp(x):
T e = exp(x / 2);
return e * (e / sqrt(2 * x * constants::pi<T>()));
}
if(policies::digits<T, Policy>() <= 64)
{
if(v == 0)
{
return bessel_i0(x);
}
if(v == 1)
{
return bessel_i1(x);
}
}
T I, K;
bessel_ik(v, x, &I, &K, need_i, pol);
return I;
}
template <class T, class Policy>
inline T cyl_bessel_k_imp(T v, T x, const bessel_no_int_tag& /* t */, const Policy& pol)
{
static const char* function = "boost::math::cyl_bessel_k<%1%>(%1%,%1%)";
BOOST_MATH_STD_USING
if(x < 0)
{
return policies::raise_domain_error<T>(
function,
"Got x = %1%, but we need x > 0", x, pol);
}
if(x == 0)
{
return (v == 0) ? policies::raise_overflow_error<T>(function, 0, pol)
: policies::raise_domain_error<T>(
function,
"Got x = %1%, but we need x > 0", x, pol);
}
T I, K;
bessel_ik(v, x, &I, &K, need_k, pol);
return K;
}
template <class T, class Policy>
inline T cyl_bessel_k_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
{
BOOST_MATH_STD_USING
if((floor(v) == v))
{
return bessel_kn(tools::real_cast<int>(v), x, pol);
}
return cyl_bessel_k_imp(v, x, bessel_no_int_tag(), pol);
}
template <class T, class Policy>
inline T cyl_bessel_k_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
{
return bessel_kn(v, x, pol);
}
template <class T, class Policy>
inline T cyl_neumann_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol)
{
static const char* function = "boost::math::cyl_neumann<%1%>(%1%,%1%)";
if(x <= 0)
{
return (v == 0) && (x == 0) ?
policies::raise_overflow_error<T>(function, 0, pol)
: policies::raise_domain_error<T>(
function,
"Got x = %1%, but result is complex for x <= 0", x, pol);
}
T j, y;
bessel_jy(v, x, &j, &y, need_y, pol);
//
// Post evaluation check for internal overflow during evaluation,
// can occur when x is small and v is large, in which case the result
// is -INF:
//
if(!(boost::math::isfinite)(y))
return -policies::raise_overflow_error<T>(function, 0, pol);
return y;
}
template <class T, class Policy>
inline T cyl_neumann_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
{
BOOST_MATH_STD_USING
typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
if(floor(v) == v)
{
if((fabs(x) > asymptotic_bessel_y_limit<T>(tag_type())) && (fabs(x) > 5 * abs(v)))
{
T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
if((v < 0) && (tools::real_cast<int>(v) & 1))
r = -r;
return r;
}
else
return bessel_yn(tools::real_cast<int>(v), x, pol);
}
return cyl_neumann_imp<T>(v, x, bessel_no_int_tag(), pol);
}
template <class T, class Policy>
inline T cyl_neumann_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
{
BOOST_MATH_STD_USING
typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
if((fabs(x) > asymptotic_bessel_y_limit<T>(tag_type())) && (fabs(x) > 5 * abs(v)))
{
T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
if((v < 0) && (v & 1))
r = -r;
return r;
}
else
return bessel_yn(tools::real_cast<int>(v), x, pol);
}
template <class T, class Policy>
inline T sph_neumann_imp(unsigned v, T x, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names
static const char* function = "boost::math::sph_neumann<%1%>(%1%,%1%)";
//
// Nothing much to do here but check for errors, and
// evaluate the function's definition directly:
//
if(x < 0)
return policies::raise_domain_error<T>(
function,
"Got x = %1%, but function requires x > 0.", x, pol);
if(x < 2 * tools::min_value<T>())
return -policies::raise_overflow_error<T>(function, 0, pol);
T result = cyl_neumann_imp(T(v)+0.5f, x, bessel_no_int_tag(), pol);
T tx = sqrt(constants::pi<T>() / (2 * x));
if((tx > 1) && (tools::max_value<T>() / tx < result))
return -policies::raise_overflow_error<T>(function, 0, pol);
return result * tx;
}
} // namespace detail
template <class T1, class T2, class Policy>
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j(T1 v, T2 x, const Policy& pol)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_imp<value_type>(v, static_cast<value_type>(x), tag_type(), pol), "boost::math::cyl_bessel_j<%1%>(%1%,%1%)");
}
template <class T1, class T2>
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j(T1 v, T2 x)
{
return cyl_bessel_j(v, x, policies::policy<>());
}
template <class T, class Policy>
inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel(unsigned v, T x, const Policy& pol)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_imp<value_type>(v, static_cast<value_type>(x), pol), "boost::math::sph_bessel<%1%>(%1%,%1%)");
}
template <class T>
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel(unsigned v, T x)
{
return sph_bessel(v, x, policies::policy<>());
}
template <class T1, class T2, class Policy>
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i(T1 v, T2 x, const Policy& pol)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_imp<value_type>(v, static_cast<value_type>(x), pol), "boost::math::cyl_bessel_i<%1%>(%1%,%1%)");
}
template <class T1, class T2>
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i(T1 v, T2 x)
{
return cyl_bessel_i(v, x, policies::policy<>());
}
template <class T1, class T2, class Policy>
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k(T1 v, T2 x, const Policy& pol)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_imp<value_type>(v, static_cast<value_type>(x), tag_type(), pol), "boost::math::cyl_bessel_k<%1%>(%1%,%1%)");
}
template <class T1, class T2>
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k(T1 v, T2 x)
{
return cyl_bessel_k(v, x, policies::policy<>());
}
template <class T1, class T2, class Policy>
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann(T1 v, T2 x, const Policy& pol)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_imp<value_type>(v, static_cast<value_type>(x), tag_type(), pol), "boost::math::cyl_neumann<%1%>(%1%,%1%)");
}
template <class T1, class T2>
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann(T1 v, T2 x)
{
return cyl_neumann(v, x, policies::policy<>());
}
template <class T, class Policy>
inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann(unsigned v, T x, const Policy& pol)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_imp<value_type>(v, static_cast<value_type>(x), pol), "boost::math::sph_neumann<%1%>(%1%,%1%)");
}
template <class T>
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann(unsigned v, T x)
{
return sph_neumann(v, x, policies::policy<>());
}
} // namespace math
} // namespace boost
#endif // BOOST_MATH_BESSEL_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
// Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_SF_BINOMIAL_HPP
#define BOOST_MATH_SF_BINOMIAL_HPP
#include <boost/math/special_functions/factorials.hpp>
#include <boost/math/special_functions/beta.hpp>
#include <boost/math/policies/error_handling.hpp>
namespace boost{ namespace math{
template <class T, class Policy>
T binomial_coefficient(unsigned n, unsigned k, const Policy& pol)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::binomial_coefficient<%1%>(unsigned, unsigned)";
if(k > n)
return policies::raise_domain_error<T>(
function,
"The binomial coefficient is undefined for k > n, but got k = %1%.",
k, pol);
T result;
if((k == 0) || (k == n))
return 1;
if((k == 1) || (k == n-1))
return n;
if(n <= max_factorial<T>::value)
{
// Use fast table lookup:
result = unchecked_factorial<T>(n);
result /= unchecked_factorial<T>(n-k);
result /= unchecked_factorial<T>(k);
}
else
{
// Use the beta function:
if(k < n - k)
result = k * beta(static_cast<T>(k), static_cast<T>(n-k+1), pol);
else
result = (n - k) * beta(static_cast<T>(k+1), static_cast<T>(n-k), pol);
if(result == 0)
return policies::raise_overflow_error<T>(function, 0, pol);
result = 1 / result;
}
// convert to nearest integer:
return ceil(result - 0.5f);
}
//
// Type float can only store the first 35 factorials, in order to
// increase the chance that we can use a table driven implementation
// we'll promote to double:
//
template <>
inline float binomial_coefficient<float, policies::policy<> >(unsigned n, unsigned k, const policies::policy<>& pol)
{
return policies::checked_narrowing_cast<float, policies::policy<> >(binomial_coefficient<double>(n, k, pol), "boost::math::binomial_coefficient<%1%>(unsigned,unsigned)");
}
template <class T>
inline T binomial_coefficient(unsigned n, unsigned k)
{
return binomial_coefficient<T>(n, k, policies::policy<>());
}
} // namespace math
} // namespace boost
#endif // BOOST_MATH_SF_BINOMIAL_HPP

View File

@@ -0,0 +1,72 @@
// (C) Copyright John Maddock 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_SF_CBRT_HPP
#define BOOST_MATH_SF_CBRT_HPP
#include <boost/math/tools/roots.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
namespace boost{ namespace math{
namespace detail
{
template <class T>
struct cbrt_functor
{
cbrt_functor(T const& target) : a(target){}
std::tr1::tuple<T, T, T> operator()(T const& z)
{
T sqr = z * z;
return std::tr1::make_tuple(sqr * z - a, 3 * sqr, 6 * z);
}
private:
T a;
};
template <class T, class Policy>
T cbrt_imp(T z, const Policy&)
{
BOOST_MATH_STD_USING
int i_exp, sign(1);
if(z < 0)
{
z = -z;
sign = -sign;
}
if(z == 0)
return 0;
frexp(z, &i_exp);
T min = static_cast<T>(ldexp(0.5, i_exp/3));
T max = static_cast<T>(ldexp(2.0, i_exp/3));
T guess = static_cast<T>(ldexp(1.0, i_exp/3));
int digits = (policies::digits<T, Policy>()) / 2;
return sign * tools::halley_iterate(detail::cbrt_functor<T>(z), guess, min, max, digits);
}
} // namespace detail
template <class T, class Policy>
inline typename tools::promote_args<T>::type cbrt(T z, const Policy& pol)
{
typedef typename tools::promote_args<T>::type result_type;
return detail::cbrt_imp(result_type(z), pol);
}
template <class T>
inline typename tools::promote_args<T>::type cbrt(T z)
{
return cbrt(z, policies::policy<>());
}
} // namespace math
} // namespace boost
#endif // BOOST_MATH_SF_CBRT_HPP

View File

@@ -0,0 +1,53 @@
// Copyright (c) 2007 John Maddock
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_COS_PI_HPP
#define BOOST_MATH_COS_PI_HPP
#include <cmath>
#include <boost/math/tools/config.hpp>
#include <boost/math/tools/real_cast.hpp>
#include <boost/math/constants/constants.hpp>
namespace boost{ namespace math{
template <class T>
T cos_pi(T x)
{
BOOST_MATH_STD_USING // ADL of std names
// cos of pi*x:
bool invert = false;
if(x < 0.5)
return cos(constants::pi<T>() * x);
if(x < 1)
{
x = -x;
}
T rem = floor(x);
if(tools::real_cast<int>(rem) & 1)
invert = !invert;
rem = x - rem;
if(rem > 0.5f)
{
rem = 1 - rem;
invert = !invert;
}
if(rem == 0.5f)
return 0;
rem = cos(constants::pi<T>() * rem);
return invert ? -rem : rem;
}
template <class T, class Policy>
inline T cos_pi(T x, const Policy&)
{
return cos_pi(x);
}
} // namespace math
} // namespace boost
#endif

View File

@@ -0,0 +1,96 @@
// Copyright (c) 2006 Xiaogang Zhang
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_BESSEL_I0_HPP
#define BOOST_MATH_BESSEL_I0_HPP
#include <boost/math/tools/rational.hpp>
#include <boost/assert.hpp>
// Modified Bessel function of the first kind of order zero
// minimax rational approximations on intervals, see
// Blair and Edwards, Chalk River Report AECL-4928, 1974
namespace boost { namespace math { namespace detail{
template <typename T>
T bessel_i0(T x)
{
static const T P1[] = {
static_cast<T>(-2.2335582639474375249e+15L),
static_cast<T>(-5.5050369673018427753e+14L),
static_cast<T>(-3.2940087627407749166e+13L),
static_cast<T>(-8.4925101247114157499e+11L),
static_cast<T>(-1.1912746104985237192e+10L),
static_cast<T>(-1.0313066708737980747e+08L),
static_cast<T>(-5.9545626019847898221e+05L),
static_cast<T>(-2.4125195876041896775e+03L),
static_cast<T>(-7.0935347449210549190e+00L),
static_cast<T>(-1.5453977791786851041e-02L),
static_cast<T>(-2.5172644670688975051e-05L),
static_cast<T>(-3.0517226450451067446e-08L),
static_cast<T>(-2.6843448573468483278e-11L),
static_cast<T>(-1.5982226675653184646e-14L),
static_cast<T>(-5.2487866627945699800e-18L),
};
static const T Q1[] = {
static_cast<T>(-2.2335582639474375245e+15L),
static_cast<T>(7.8858692566751002988e+12L),
static_cast<T>(-1.2207067397808979846e+10L),
static_cast<T>(1.0377081058062166144e+07L),
static_cast<T>(-4.8527560179962773045e+03L),
static_cast<T>(1.0L),
};
static const T P2[] = {
static_cast<T>(-2.2210262233306573296e-04L),
static_cast<T>(1.3067392038106924055e-02L),
static_cast<T>(-4.4700805721174453923e-01L),
static_cast<T>(5.5674518371240761397e+00L),
static_cast<T>(-2.3517945679239481621e+01L),
static_cast<T>(3.1611322818701131207e+01L),
static_cast<T>(-9.6090021968656180000e+00L),
};
static const T Q2[] = {
static_cast<T>(-5.5194330231005480228e-04L),
static_cast<T>(3.2547697594819615062e-02L),
static_cast<T>(-1.1151759188741312645e+00L),
static_cast<T>(1.3982595353892851542e+01L),
static_cast<T>(-6.0228002066743340583e+01L),
static_cast<T>(8.5539563258012929600e+01L),
static_cast<T>(-3.1446690275135491500e+01L),
static_cast<T>(1.0L),
};
T value, factor, r;
BOOST_MATH_STD_USING
using namespace boost::math::tools;
if (x < 0)
{
x = -x; // even function
}
if (x == 0)
{
return static_cast<T>(1);
}
if (x <= 15) // x in (0, 15]
{
T y = x * x;
value = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
}
else // x in (15, \infty)
{
T y = 1 / x - T(1) / 15;
r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
factor = exp(x) / sqrt(x);
value = factor * r;
}
return value;
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_I0_HPP

View File

@@ -0,0 +1,99 @@
// Copyright (c) 2006 Xiaogang Zhang
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_BESSEL_I1_HPP
#define BOOST_MATH_BESSEL_I1_HPP
#include <boost/math/tools/rational.hpp>
#include <boost/assert.hpp>
// Modified Bessel function of the first kind of order one
// minimax rational approximations on intervals, see
// Blair and Edwards, Chalk River Report AECL-4928, 1974
namespace boost { namespace math { namespace detail{
template <typename T>
T bessel_i1(T x)
{
static const T P1[] = {
static_cast<T>(-1.4577180278143463643e+15L),
static_cast<T>(-1.7732037840791591320e+14L),
static_cast<T>(-6.9876779648010090070e+12L),
static_cast<T>(-1.3357437682275493024e+11L),
static_cast<T>(-1.4828267606612366099e+09L),
static_cast<T>(-1.0588550724769347106e+07L),
static_cast<T>(-5.1894091982308017540e+04L),
static_cast<T>(-1.8225946631657315931e+02L),
static_cast<T>(-4.7207090827310162436e-01L),
static_cast<T>(-9.1746443287817501309e-04L),
static_cast<T>(-1.3466829827635152875e-06L),
static_cast<T>(-1.4831904935994647675e-09L),
static_cast<T>(-1.1928788903603238754e-12L),
static_cast<T>(-6.5245515583151902910e-16L),
static_cast<T>(-1.9705291802535139930e-19L),
};
static const T Q1[] = {
static_cast<T>(-2.9154360556286927285e+15L),
static_cast<T>(9.7887501377547640438e+12L),
static_cast<T>(-1.4386907088588283434e+10L),
static_cast<T>(1.1594225856856884006e+07L),
static_cast<T>(-5.1326864679904189920e+03L),
static_cast<T>(1.0L),
};
static const T P2[] = {
static_cast<T>(1.4582087408985668208e-05L),
static_cast<T>(-8.9359825138577646443e-04L),
static_cast<T>(2.9204895411257790122e-02L),
static_cast<T>(-3.4198728018058047439e-01L),
static_cast<T>(1.3960118277609544334e+00L),
static_cast<T>(-1.9746376087200685843e+00L),
static_cast<T>(8.5591872901933459000e-01L),
static_cast<T>(-6.0437159056137599999e-02L),
};
static const T Q2[] = {
static_cast<T>(3.7510433111922824643e-05L),
static_cast<T>(-2.2835624489492512649e-03L),
static_cast<T>(7.4212010813186530069e-02L),
static_cast<T>(-8.5017476463217924408e-01L),
static_cast<T>(3.2593714889036996297e+00L),
static_cast<T>(-3.8806586721556593450e+00L),
static_cast<T>(1.0L),
};
T value, factor, r, w;
BOOST_MATH_STD_USING
using namespace boost::math::tools;
w = abs(x);
if (x == 0)
{
return static_cast<T>(0);
}
if (w <= 15) // w in (0, 15]
{
T y = x * x;
r = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
factor = w;
value = factor * r;
}
else // w in (15, \infty)
{
T y = 1 / w - T(1) / 15;
r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
factor = exp(w) / sqrt(w);
value = factor * r;
}
if (x < 0)
{
value *= -value; // odd function
}
return value;
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_I1_HPP

View File

@@ -0,0 +1,331 @@
// Copyright (c) 2006 Xiaogang Zhang
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_BESSEL_IK_HPP
#define BOOST_MATH_BESSEL_IK_HPP
#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/special_functions/sin_pi.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/tools/config.hpp>
// Modified Bessel functions of the first and second kind of fractional order
namespace boost { namespace math {
namespace detail {
// Calculate K(v, x) and K(v+1, x) by method analogous to
// Temme, Journal of Computational Physics, vol 21, 343 (1976)
template <typename T, typename Policy>
int temme_ik(T v, T x, T* K, T* K1, const Policy& pol)
{
T f, h, p, q, coef, sum, sum1, tolerance;
T a, b, c, d, sigma, gamma1, gamma2;
unsigned long k;
BOOST_MATH_STD_USING
using namespace boost::math::tools;
using namespace boost::math::constants;
// |x| <= 2, Temme series converge rapidly
// |x| > 2, the larger the |x|, the slower the convergence
BOOST_ASSERT(abs(x) <= 2);
BOOST_ASSERT(abs(v) <= 0.5f);
T gp = tgamma1pm1(v, pol);
T gm = tgamma1pm1(-v, pol);
a = log(x / 2);
b = exp(v * a);
sigma = -a * v;
c = abs(v) < tools::epsilon<T>() ?
1 : sin_pi(v) / (v * pi<T>());
d = abs(sigma) < tools::epsilon<T>() ?
1 : sinh(sigma) / sigma;
gamma1 = abs(v) < tools::epsilon<T>() ?
-euler<T>() : (0.5f / v) * (gp - gm) * c;
gamma2 = (2 + gp + gm) * c / 2;
// initial values
p = (gp + 1) / (2 * b);
q = (1 + gm) * b / 2;
f = (cosh(sigma) * gamma1 + d * (-a) * gamma2) / c;
h = p;
coef = 1;
sum = coef * f;
sum1 = coef * h;
// series summation
tolerance = tools::epsilon<T>();
for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++)
{
f = (k * f + p + q) / (k*k - v*v);
p /= k - v;
q /= k + v;
h = p - k * f;
coef *= x * x / (4 * k);
sum += coef * f;
sum1 += coef * h;
if (abs(coef * f) < abs(sum) * tolerance)
{
break;
}
}
policies::check_series_iterations("boost::math::bessel_ik<%1%>(%1%,%1%) in temme_ik", k, pol);
*K = sum;
*K1 = 2 * sum1 / x;
return 0;
}
// Evaluate continued fraction fv = I_(v+1) / I_v, derived from
// Abramowitz and Stegun, Handbook of Mathematical Functions, 1972, 9.1.73
template <typename T, typename Policy>
int CF1_ik(T v, T x, T* fv, const Policy& pol)
{
T C, D, f, a, b, delta, tiny, tolerance;
unsigned long k;
BOOST_MATH_STD_USING
// |x| <= |v|, CF1_ik converges rapidly
// |x| > |v|, CF1_ik needs O(|x|) iterations to converge
// modified Lentz's method, see
// Lentz, Applied Optics, vol 15, 668 (1976)
tolerance = 2 * tools::epsilon<T>();
BOOST_MATH_INSTRUMENT_VARIABLE(tolerance);
tiny = sqrt(tools::min_value<T>());
BOOST_MATH_INSTRUMENT_VARIABLE(tiny);
C = f = tiny; // b0 = 0, replace with tiny
D = 0;
for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++)
{
a = 1;
b = 2 * (v + k) / x;
C = b + a / C;
D = b + a * D;
if (C == 0) { C = tiny; }
if (D == 0) { D = tiny; }
D = 1 / D;
delta = C * D;
f *= delta;
BOOST_MATH_INSTRUMENT_VARIABLE(delta-1);
if (abs(delta - 1) <= tolerance)
{
break;
}
}
BOOST_MATH_INSTRUMENT_VARIABLE(k);
policies::check_series_iterations("boost::math::bessel_ik<%1%>(%1%,%1%) in CF1_ik", k, pol);
*fv = f;
return 0;
}
// Calculate K(v, x) and K(v+1, x) by evaluating continued fraction
// z1 / z0 = U(v+1.5, 2v+1, 2x) / U(v+0.5, 2v+1, 2x), see
// Thompson and Barnett, Computer Physics Communications, vol 47, 245 (1987)
template <typename T, typename Policy>
int CF2_ik(T v, T x, T* Kv, T* Kv1, const Policy& pol)
{
BOOST_MATH_STD_USING
using namespace boost::math::constants;
T S, C, Q, D, f, a, b, q, delta, tolerance, current, prev;
unsigned long k;
// |x| >= |v|, CF2_ik converges rapidly
// |x| -> 0, CF2_ik fails to converge
BOOST_ASSERT(abs(x) > 1);
// Steed's algorithm, see Thompson and Barnett,
// Journal of Computational Physics, vol 64, 490 (1986)
tolerance = tools::epsilon<T>();
a = v * v - 0.25f;
b = 2 * (x + 1); // b1
D = 1 / b; // D1 = 1 / b1
f = delta = D; // f1 = delta1 = D1, coincidence
prev = 0; // q0
current = 1; // q1
Q = C = -a; // Q1 = C1 because q1 = 1
S = 1 + Q * delta; // S1
BOOST_MATH_INSTRUMENT_VARIABLE(tolerance);
BOOST_MATH_INSTRUMENT_VARIABLE(a);
BOOST_MATH_INSTRUMENT_VARIABLE(b);
BOOST_MATH_INSTRUMENT_VARIABLE(D);
BOOST_MATH_INSTRUMENT_VARIABLE(f);
for (k = 2; k < policies::get_max_series_iterations<Policy>(); k++) // starting from 2
{
// continued fraction f = z1 / z0
a -= 2 * (k - 1);
b += 2;
D = 1 / (b + a * D);
delta *= b * D - 1;
f += delta;
// series summation S = 1 + \sum_{n=1}^{\infty} C_n * z_n / z_0
q = (prev - (b - 2) * current) / a;
prev = current;
current = q; // forward recurrence for q
C *= -a / k;
Q += C * q;
S += Q * delta;
// S converges slower than f
BOOST_MATH_INSTRUMENT_VARIABLE(Q * delta);
BOOST_MATH_INSTRUMENT_VARIABLE(abs(S) * tolerance);
if (abs(Q * delta) < abs(S) * tolerance)
{
break;
}
}
policies::check_series_iterations("boost::math::bessel_ik<%1%>(%1%,%1%) in CF2_ik", k, pol);
*Kv = sqrt(pi<T>() / (2 * x)) * exp(-x) / S;
*Kv1 = *Kv * (0.5f + v + x + (v * v - 0.25f) * f) / x;
BOOST_MATH_INSTRUMENT_VARIABLE(*Kv);
BOOST_MATH_INSTRUMENT_VARIABLE(*Kv1);
return 0;
}
enum{
need_i = 1,
need_k = 2
};
// Compute I(v, x) and K(v, x) simultaneously by Temme's method, see
// Temme, Journal of Computational Physics, vol 19, 324 (1975)
template <typename T, typename Policy>
int bessel_ik(T v, T x, T* I, T* K, int kind, const Policy& pol)
{
// Kv1 = K_(v+1), fv = I_(v+1) / I_v
// Ku1 = K_(u+1), fu = I_(u+1) / I_u
T u, Iv, Kv, Kv1, Ku, Ku1, fv;
T W, current, prev, next;
bool reflect = false;
unsigned n, k;
BOOST_MATH_INSTRUMENT_VARIABLE(v);
BOOST_MATH_INSTRUMENT_VARIABLE(x);
BOOST_MATH_INSTRUMENT_VARIABLE(kind);
BOOST_MATH_STD_USING
using namespace boost::math::tools;
using namespace boost::math::constants;
static const char* function = "boost::math::bessel_ik<%1%>(%1%,%1%)";
if (v < 0)
{
reflect = true;
v = -v; // v is non-negative from here
kind |= need_k;
}
n = tools::real_cast<unsigned>(v + 0.5f);
u = v - n; // -1/2 <= u < 1/2
BOOST_MATH_INSTRUMENT_VARIABLE(n);
BOOST_MATH_INSTRUMENT_VARIABLE(u);
if (x < 0)
{
*I = *K = policies::raise_domain_error<T>(function,
"Got x = %1% but real argument x must be non-negative, complex number result not supported.", x, pol);
return 1;
}
if (x == 0)
{
Iv = (v == 0) ? static_cast<T>(1) : static_cast<T>(0);
if(kind & need_k)
{
Kv = policies::raise_overflow_error<T>(function, 0, pol);
}
else
{
Kv = std::numeric_limits<T>::quiet_NaN(); // any value will do
}
if(reflect && (kind & need_i))
{
T z = (u + n % 2);
Iv = sin_pi(z, pol) == 0 ?
Iv :
policies::raise_overflow_error<T>(function, 0, pol); // reflection formula
}
*I = Iv;
*K = Kv;
return 0;
}
// x is positive until reflection
W = 1 / x; // Wronskian
if (x <= 2) // x in (0, 2]
{
temme_ik(u, x, &Ku, &Ku1, pol); // Temme series
}
else // x in (2, \infty)
{
CF2_ik(u, x, &Ku, &Ku1, pol); // continued fraction CF2_ik
}
prev = Ku;
current = Ku1;
for (k = 1; k <= n; k++) // forward recurrence for K
{
next = 2 * (u + k) * current / x + prev;
prev = current;
current = next;
}
Kv = prev;
Kv1 = current;
if(kind & need_i)
{
T lim = (4 * v * v + 10) / (8 * x);
lim *= lim;
lim *= lim;
lim /= 24;
if((lim < tools::epsilon<T>() * 10) && (x > 100))
{
// x is huge compared to v, CF1 may be very slow
// to converge so use asymptotic expansion for large
// x case instead. Note that the asymptotic expansion
// isn't very accurate - so it's deliberately very hard
// to get here - probably we're going to overflow:
Iv = asymptotic_bessel_i_large_x(v, x, pol);
}
else
{
CF1_ik(v, x, &fv, pol); // continued fraction CF1_ik
Iv = W / (Kv * fv + Kv1); // Wronskian relation
}
}
else
Iv = std::numeric_limits<T>::quiet_NaN(); // any value will do
if (reflect)
{
T z = (u + n % 2);
*I = Iv + (2 / pi<T>()) * sin_pi(z) * Kv; // reflection formula
*K = Kv;
}
else
{
*I = Iv;
*K = Kv;
}
BOOST_MATH_INSTRUMENT_VARIABLE(*I);
BOOST_MATH_INSTRUMENT_VARIABLE(*K);
return 0;
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_IK_HPP

View File

@@ -0,0 +1,147 @@
// Copyright (c) 2006 Xiaogang Zhang
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_BESSEL_J0_HPP
#define BOOST_MATH_BESSEL_J0_HPP
#include <boost/math/constants/constants.hpp>
#include <boost/math/tools/rational.hpp>
#include <boost/assert.hpp>
// Bessel function of the first kind of order zero
// x <= 8, minimax rational approximations on root-bracketing intervals
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
namespace boost { namespace math { namespace detail{
template <typename T>
T bessel_j0(T x)
{
static const T P1[] = {
static_cast<T>(-4.1298668500990866786e+11L),
static_cast<T>(2.7282507878605942706e+10L),
static_cast<T>(-6.2140700423540120665e+08L),
static_cast<T>(6.6302997904833794242e+06L),
static_cast<T>(-3.6629814655107086448e+04L),
static_cast<T>(1.0344222815443188943e+02L),
static_cast<T>(-1.2117036164593528341e-01L)
};
static const T Q1[] = {
static_cast<T>(2.3883787996332290397e+12L),
static_cast<T>(2.6328198300859648632e+10L),
static_cast<T>(1.3985097372263433271e+08L),
static_cast<T>(4.5612696224219938200e+05L),
static_cast<T>(9.3614022392337710626e+02L),
static_cast<T>(1.0L),
static_cast<T>(0.0L)
};
static const T P2[] = {
static_cast<T>(-1.8319397969392084011e+03L),
static_cast<T>(-1.2254078161378989535e+04L),
static_cast<T>(-7.2879702464464618998e+03L),
static_cast<T>(1.0341910641583726701e+04L),
static_cast<T>(1.1725046279757103576e+04L),
static_cast<T>(4.4176707025325087628e+03L),
static_cast<T>(7.4321196680624245801e+02L),
static_cast<T>(4.8591703355916499363e+01L)
};
static const T Q2[] = {
static_cast<T>(-3.5783478026152301072e+05L),
static_cast<T>(2.4599102262586308984e+05L),
static_cast<T>(-8.4055062591169562211e+04L),
static_cast<T>(1.8680990008359188352e+04L),
static_cast<T>(-2.9458766545509337327e+03L),
static_cast<T>(3.3307310774649071172e+02L),
static_cast<T>(-2.5258076240801555057e+01L),
static_cast<T>(1.0L)
};
static const T PC[] = {
static_cast<T>(2.2779090197304684302e+04L),
static_cast<T>(4.1345386639580765797e+04L),
static_cast<T>(2.1170523380864944322e+04L),
static_cast<T>(3.4806486443249270347e+03L),
static_cast<T>(1.5376201909008354296e+02L),
static_cast<T>(8.8961548424210455236e-01L)
};
static const T QC[] = {
static_cast<T>(2.2779090197304684318e+04L),
static_cast<T>(4.1370412495510416640e+04L),
static_cast<T>(2.1215350561880115730e+04L),
static_cast<T>(3.5028735138235608207e+03L),
static_cast<T>(1.5711159858080893649e+02L),
static_cast<T>(1.0L)
};
static const T PS[] = {
static_cast<T>(-8.9226600200800094098e+01L),
static_cast<T>(-1.8591953644342993800e+02L),
static_cast<T>(-1.1183429920482737611e+02L),
static_cast<T>(-2.2300261666214198472e+01L),
static_cast<T>(-1.2441026745835638459e+00L),
static_cast<T>(-8.8033303048680751817e-03L)
};
static const T QS[] = {
static_cast<T>(5.7105024128512061905e+03L),
static_cast<T>(1.1951131543434613647e+04L),
static_cast<T>(7.2642780169211018836e+03L),
static_cast<T>(1.4887231232283756582e+03L),
static_cast<T>(9.0593769594993125859e+01L),
static_cast<T>(1.0L)
};
static const T x1 = static_cast<T>(2.4048255576957727686e+00L),
x2 = static_cast<T>(5.5200781102863106496e+00L),
x11 = static_cast<T>(6.160e+02L),
x12 = static_cast<T>(-1.42444230422723137837e-03L),
x21 = static_cast<T>(1.4130e+03L),
x22 = static_cast<T>(5.46860286310649596604e-04L);
T value, factor, r, rc, rs;
BOOST_MATH_STD_USING
using namespace boost::math::tools;
using namespace boost::math::constants;
if (x < 0)
{
x = -x; // even function
}
if (x == 0)
{
return static_cast<T>(1);
}
if (x <= 4) // x in (0, 4]
{
T y = x * x;
BOOST_ASSERT(sizeof(P1) == sizeof(Q1));
r = evaluate_rational(P1, Q1, y);
factor = (x + x1) * ((x - x11/256) - x12);
value = factor * r;
}
else if (x <= 8.0) // x in (4, 8]
{
T y = 1 - (x * x)/64;
BOOST_ASSERT(sizeof(P2) == sizeof(Q2));
r = evaluate_rational(P2, Q2, y);
factor = (x + x2) * ((x - x21/256) - x22);
value = factor * r;
}
else // x in (8, \infty)
{
T y = 8 / x;
T y2 = y * y;
T z = x - 0.25f * pi<T>();
BOOST_ASSERT(sizeof(PC) == sizeof(QC));
BOOST_ASSERT(sizeof(PS) == sizeof(QS));
rc = evaluate_rational(PC, QC, y2);
rs = evaluate_rational(PS, QS, y2);
factor = sqrt(2 / (x * pi<T>()));
value = factor * (rc * cos(z) - y * rs * sin(z));
}
return value;
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_J0_HPP

View File

@@ -0,0 +1,152 @@
// Copyright (c) 2006 Xiaogang Zhang
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_BESSEL_J1_HPP
#define BOOST_MATH_BESSEL_J1_HPP
#include <boost/math/constants/constants.hpp>
#include <boost/math/tools/rational.hpp>
#include <boost/assert.hpp>
// Bessel function of the first kind of order one
// x <= 8, minimax rational approximations on root-bracketing intervals
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
namespace boost { namespace math{ namespace detail{
template <typename T>
T bessel_j1(T x)
{
static const T P1[] = {
static_cast<T>(-1.4258509801366645672e+11L),
static_cast<T>(6.6781041261492395835e+09L),
static_cast<T>(-1.1548696764841276794e+08L),
static_cast<T>(9.8062904098958257677e+05L),
static_cast<T>(-4.4615792982775076130e+03L),
static_cast<T>(1.0650724020080236441e+01L),
static_cast<T>(-1.0767857011487300348e-02L)
};
static const T Q1[] = {
static_cast<T>(4.1868604460820175290e+12L),
static_cast<T>(4.2091902282580133541e+10L),
static_cast<T>(2.0228375140097033958e+08L),
static_cast<T>(5.9117614494174794095e+05L),
static_cast<T>(1.0742272239517380498e+03L),
static_cast<T>(1.0L),
static_cast<T>(0.0L)
};
static const T P2[] = {
static_cast<T>(-1.7527881995806511112e+16L),
static_cast<T>(1.6608531731299018674e+15L),
static_cast<T>(-3.6658018905416665164e+13L),
static_cast<T>(3.5580665670910619166e+11L),
static_cast<T>(-1.8113931269860667829e+09L),
static_cast<T>(5.0793266148011179143e+06L),
static_cast<T>(-7.5023342220781607561e+03L),
static_cast<T>(4.6179191852758252278e+00L)
};
static const T Q2[] = {
static_cast<T>(1.7253905888447681194e+18L),
static_cast<T>(1.7128800897135812012e+16L),
static_cast<T>(8.4899346165481429307e+13L),
static_cast<T>(2.7622777286244082666e+11L),
static_cast<T>(6.4872502899596389593e+08L),
static_cast<T>(1.1267125065029138050e+06L),
static_cast<T>(1.3886978985861357615e+03L),
static_cast<T>(1.0L)
};
static const T PC[] = {
static_cast<T>(-4.4357578167941278571e+06L),
static_cast<T>(-9.9422465050776411957e+06L),
static_cast<T>(-6.6033732483649391093e+06L),
static_cast<T>(-1.5235293511811373833e+06L),
static_cast<T>(-1.0982405543459346727e+05L),
static_cast<T>(-1.6116166443246101165e+03L),
static_cast<T>(0.0L)
};
static const T QC[] = {
static_cast<T>(-4.4357578167941278568e+06L),
static_cast<T>(-9.9341243899345856590e+06L),
static_cast<T>(-6.5853394797230870728e+06L),
static_cast<T>(-1.5118095066341608816e+06L),
static_cast<T>(-1.0726385991103820119e+05L),
static_cast<T>(-1.4550094401904961825e+03L),
static_cast<T>(1.0L)
};
static const T PS[] = {
static_cast<T>(3.3220913409857223519e+04L),
static_cast<T>(8.5145160675335701966e+04L),
static_cast<T>(6.6178836581270835179e+04L),
static_cast<T>(1.8494262873223866797e+04L),
static_cast<T>(1.7063754290207680021e+03L),
static_cast<T>(3.5265133846636032186e+01L),
static_cast<T>(0.0L)
};
static const T QS[] = {
static_cast<T>(7.0871281941028743574e+05L),
static_cast<T>(1.8194580422439972989e+06L),
static_cast<T>(1.4194606696037208929e+06L),
static_cast<T>(4.0029443582266975117e+05L),
static_cast<T>(3.7890229745772202641e+04L),
static_cast<T>(8.6383677696049909675e+02L),
static_cast<T>(1.0L)
};
static const T x1 = static_cast<T>(3.8317059702075123156e+00L),
x2 = static_cast<T>(7.0155866698156187535e+00L),
x11 = static_cast<T>(9.810e+02L),
x12 = static_cast<T>(-3.2527979248768438556e-04L),
x21 = static_cast<T>(1.7960e+03L),
x22 = static_cast<T>(-3.8330184381246462950e-05L);
T value, factor, r, rc, rs, w;
BOOST_MATH_STD_USING
using namespace boost::math::tools;
using namespace boost::math::constants;
w = abs(x);
if (x == 0)
{
return static_cast<T>(0);
}
if (w <= 4) // w in (0, 4]
{
T y = x * x;
BOOST_ASSERT(sizeof(P1) == sizeof(Q1));
r = evaluate_rational(P1, Q1, y);
factor = w * (w + x1) * ((w - x11/256) - x12);
value = factor * r;
}
else if (w <= 8) // w in (4, 8]
{
T y = x * x;
BOOST_ASSERT(sizeof(P2) == sizeof(Q2));
r = evaluate_rational(P2, Q2, y);
factor = w * (w + x2) * ((w - x21/256) - x22);
value = factor * r;
}
else // w in (8, \infty)
{
T y = 8 / w;
T y2 = y * y;
T z = w - 0.75f * pi<T>();
BOOST_ASSERT(sizeof(PC) == sizeof(QC));
BOOST_ASSERT(sizeof(PS) == sizeof(QS));
rc = evaluate_rational(PC, QC, y2);
rs = evaluate_rational(PS, QS, y2);
factor = sqrt(2 / (w * pi<T>()));
value = factor * (rc * cos(z) - y * rs * sin(z));
}
if (x < 0)
{
value *= -1; // odd function
}
return value;
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_J1_HPP

View File

@@ -0,0 +1,86 @@
// Copyright (c) 2006 Xiaogang Zhang
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_BESSEL_JN_HPP
#define BOOST_MATH_BESSEL_JN_HPP
#include <boost/math/special_functions/detail/bessel_j0.hpp>
#include <boost/math/special_functions/detail/bessel_j1.hpp>
#include <boost/math/special_functions/detail/bessel_jy.hpp>
// Bessel function of the first kind of integer order
// J_n(z) is the minimal solution
// n < abs(z), forward recurrence stable and usable
// n >= abs(z), forward recurrence unstable, use Miller's algorithm
namespace boost { namespace math { namespace detail{
template <typename T, typename Policy>
T bessel_jn(int n, T x, const Policy& pol)
{
T value(0), factor, current, prev, next;
BOOST_MATH_STD_USING
if (n == 0)
{
return bessel_j0(x);
}
if (n == 1)
{
return bessel_j1(x);
}
if (n < 0)
{
factor = (n & 0x1) ? -1 : 1; // J_{-n}(z) = (-1)^n J_n(z)
n = -n;
}
else
{
factor = 1;
}
if (x == 0) // n >= 2
{
return static_cast<T>(0);
}
if (n < abs(x)) // forward recurrence
{
prev = bessel_j0(x);
current = bessel_j1(x);
for (int k = 1; k < n; k++)
{
value = 2 * k * current / x - prev;
prev = current;
current = value;
}
}
else // backward recurrence
{
T fn; int s; // fn = J_(n+1) / J_n
// |x| <= n, fast convergence for continued fraction CF1
boost::math::detail::CF1_jy(static_cast<T>(n), x, &fn, &s, pol);
// tiny initial value to prevent overflow
T init = sqrt(tools::min_value<T>());
prev = fn * init;
current = init;
for (int k = n; k > 0; k--)
{
next = 2 * k * current / x - prev;
prev = current;
current = next;
}
T ratio = init / current; // scaling ratio
value = bessel_j0(x) * ratio; // normalization
}
value *= factor;
return value;
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_JN_HPP

Some files were not shown because too many files have changed in this diff Show More