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:
79
example/Jamfile.v2
Normal file
79
example/Jamfile.v2
Normal 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 ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
237
example/binomial_coinflip_example.cpp
Normal file
237
example/binomial_coinflip_example.cpp
Normal 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]
|
||||
159
example/binomial_confidence_limits.cpp
Normal file
159
example/binomial_confidence_limits.cpp
Normal 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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
91
example/binomial_example3.cpp
Normal file
91
example/binomial_example3.cpp
Normal 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
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
91
example/binomial_example_nag.cpp
Normal file
91
example/binomial_example_nag.cpp
Normal 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
|
||||
|
||||
|
||||
*/
|
||||
|
||||
520
example/binomial_quiz_example.cpp
Normal file
520
example/binomial_quiz_example.cpp
Normal 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.
|
||||
|
||||
*/
|
||||
|
||||
76
example/binomial_sample_sizes.cpp
Normal file
76
example/binomial_sample_sizes.cpp
Normal 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;
|
||||
}
|
||||
|
||||
74
example/c_error_policy_example.cpp
Normal file
74
example/c_error_policy_example.cpp
Normal 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
|
||||
|
||||
*/
|
||||
552
example/chi_square_std_dev_test.cpp
Normal file
552
example/chi_square_std_dev_test.cpp
Normal 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
|
||||
*/
|
||||
|
||||
201
example/distribution_construction.cpp
Normal file
201
example/distribution_construction.cpp
Normal 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]
|
||||
|
||||
143
example/error_handling_example.cpp
Normal file
143
example/error_handling_example.cpp
Normal 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]
|
||||
97
example/error_policies_example.cpp
Normal file
97
example/error_policies_example.cpp
Normal 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
|
||||
|
||||
*/
|
||||
88
example/error_policy_example.cpp
Normal file
88
example/error_policy_example.cpp
Normal 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
184
example/f_test.cpp
Normal 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
|
||||
|
||||
*/
|
||||
|
||||
170
example/find_location_example.cpp
Normal file
170
example/find_location_example.cpp
Normal 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]
|
||||
408
example/find_mean_and_sd_normal.cpp
Normal file
408
example/find_mean_and_sd_normal.cpp
Normal 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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
239
example/find_root_example.cpp
Normal file
239
example/find_root_example.cpp
Normal 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:
|
||||
|
||||
|
||||
|
||||
*/
|
||||
180
example/find_scale_example.cpp
Normal file
180
example/find_scale_example.cpp
Normal 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]
|
||||
179
example/neg_binom_confidence_limits.cpp
Normal file
179
example/neg_binom_confidence_limits.cpp
Normal 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
|
||||
*/
|
||||
202
example/neg_binomial_sample_sizes.cpp
Normal file
202
example/neg_binomial_sample_sizes.cpp
Normal 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
|
||||
|
||||
*/
|
||||
521
example/negative_binomial_example1.cpp
Normal file
521
example/negative_binomial_example1.cpp
Normal 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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
182
example/negative_binomial_example2.cpp
Normal file
182
example/negative_binomial_example2.cpp
Normal 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]
|
||||
|
||||
*/
|
||||
509
example/normal_misc_examples.cpp
Normal file
509
example/normal_misc_examples.cpp
Normal 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
35
example/policy_eg_1.cpp
Normal 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
171
example/policy_eg_10.cpp
Normal 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
44
example/policy_eg_2.cpp
Normal 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
42
example/policy_eg_3.cpp
Normal 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
102
example/policy_eg_4.cpp
Normal 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
41
example/policy_eg_5.cpp
Normal 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
119
example/policy_eg_6.cpp
Normal 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
57
example/policy_eg_7.cpp
Normal 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
135
example/policy_eg_8.cpp
Normal 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
316
example/policy_eg_9.cpp
Normal 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.
|
||||
|
||||
*/
|
||||
|
||||
//]
|
||||
|
||||
44
example/policy_ref_snip1.cpp
Normal file
44
example/policy_ref_snip1.cpp
Normal 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;
|
||||
}
|
||||
25
example/policy_ref_snip10.cpp
Normal file
25
example/policy_ref_snip10.cpp
Normal 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;
|
||||
}
|
||||
27
example/policy_ref_snip11.cpp
Normal file
27
example/policy_ref_snip11.cpp
Normal 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;
|
||||
}
|
||||
38
example/policy_ref_snip12.cpp
Normal file
38
example/policy_ref_snip12.cpp
Normal 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;
|
||||
}
|
||||
54
example/policy_ref_snip13.cpp
Normal file
54
example/policy_ref_snip13.cpp
Normal 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();
|
||||
}
|
||||
34
example/policy_ref_snip2.cpp
Normal file
34
example/policy_ref_snip2.cpp
Normal 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;
|
||||
}
|
||||
36
example/policy_ref_snip3.cpp
Normal file
36
example/policy_ref_snip3.cpp
Normal 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;
|
||||
}
|
||||
40
example/policy_ref_snip4.cpp
Normal file
40
example/policy_ref_snip4.cpp
Normal 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;
|
||||
}
|
||||
33
example/policy_ref_snip5.cpp
Normal file
33
example/policy_ref_snip5.cpp
Normal 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;
|
||||
}
|
||||
27
example/policy_ref_snip6.cpp
Normal file
27
example/policy_ref_snip6.cpp
Normal 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;
|
||||
}
|
||||
33
example/policy_ref_snip7.cpp
Normal file
33
example/policy_ref_snip7.cpp
Normal 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;
|
||||
}
|
||||
33
example/policy_ref_snip8.cpp
Normal file
33
example/policy_ref_snip8.cpp
Normal 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;
|
||||
}
|
||||
27
example/policy_ref_snip9.cpp
Normal file
27
example/policy_ref_snip9.cpp
Normal 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;
|
||||
}
|
||||
101
example/students_t_example1.cpp
Normal file
101
example/students_t_example1.cpp
Normal 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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
125
example/students_t_example2.cpp
Normal file
125
example/students_t_example2.cpp
Normal 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 ==========
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
120
example/students_t_example3.cpp
Normal file
120
example/students_t_example3.cpp
Normal 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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
427
example/students_t_single_sample.cpp
Normal file
427
example/students_t_single_sample.cpp
Normal 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 ==========
|
||||
|
||||
|
||||
*/
|
||||
|
||||
261
example/students_t_two_samples.cpp
Normal file
261
example/students_t_two_samples.cpp
Normal 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 ==========
|
||||
|
||||
*/
|
||||
|
||||
707
include/boost/math/bindings/rr.hpp
Normal file
707
include/boost/math/bindings/rr.hpp
Normal 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
|
||||
|
||||
|
||||
203
include/boost/math/concepts/distributions.hpp
Normal file
203
include/boost/math/concepts/distributions.hpp
Normal 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
|
||||
|
||||
349
include/boost/math/concepts/real_concept.hpp
Normal file
349
include/boost/math/concepts/real_concept.hpp
Normal 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
|
||||
|
||||
|
||||
345
include/boost/math/concepts/std_real_concept.hpp
Normal file
345
include/boost/math/concepts/std_real_concept.hpp
Normal 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
|
||||
|
||||
|
||||
75
include/boost/math/constants/constants.hpp
Normal file
75
include/boost/math/constants/constants.hpp
Normal 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
|
||||
42
include/boost/math/distributions.hpp
Normal file
42
include/boost/math/distributions.hpp
Normal 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
|
||||
|
||||
325
include/boost/math/distributions/bernoulli.hpp
Normal file
325
include/boost/math/distributions/bernoulli.hpp
Normal 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
|
||||
|
||||
|
||||
|
||||
544
include/boost/math/distributions/beta.hpp
Normal file
544
include/boost/math/distributions/beta.hpp
Normal 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
|
||||
|
||||
|
||||
724
include/boost/math/distributions/binomial.hpp
Normal file
724
include/boost/math/distributions/binomial.hpp
Normal 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
|
||||
|
||||
|
||||
347
include/boost/math/distributions/cauchy.hpp
Normal file
347
include/boost/math/distributions/cauchy.hpp
Normal 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
|
||||
326
include/boost/math/distributions/chi_squared.hpp
Normal file
326
include/boost/math/distributions/chi_squared.hpp
Normal 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
|
||||
195
include/boost/math/distributions/complement.hpp
Normal file
195
include/boost/math/distributions/complement.hpp
Normal 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
|
||||
|
||||
@@ -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
|
||||
163
include/boost/math/distributions/detail/derived_accessors.hpp
Normal file
163
include/boost/math/distributions/detail/derived_accessors.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
|
||||
259
include/boost/math/distributions/exponential.hpp
Normal file
259
include/boost/math/distributions/exponential.hpp
Normal 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
|
||||
260
include/boost/math/distributions/extreme_value.hpp
Normal file
260
include/boost/math/distributions/extreme_value.hpp
Normal 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
|
||||
141
include/boost/math/distributions/find_location.hpp
Normal file
141
include/boost/math/distributions/find_location.hpp
Normal 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
|
||||
|
||||
203
include/boost/math/distributions/find_scale.hpp
Normal file
203
include/boost/math/distributions/find_scale.hpp
Normal 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
|
||||
385
include/boost/math/distributions/fisher_f.hpp
Normal file
385
include/boost/math/distributions/fisher_f.hpp
Normal 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
|
||||
94
include/boost/math/distributions/fwd.hpp
Normal file
94
include/boost/math/distributions/fwd.hpp
Normal 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
|
||||
348
include/boost/math/distributions/gamma.hpp
Normal file
348
include/boost/math/distributions/gamma.hpp
Normal 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
|
||||
|
||||
|
||||
310
include/boost/math/distributions/lognormal.hpp
Normal file
310
include/boost/math/distributions/lognormal.hpp
Normal 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
|
||||
|
||||
|
||||
588
include/boost/math/distributions/negative_binomial.hpp
Normal file
588
include/boost/math/distributions/negative_binomial.hpp
Normal 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
|
||||
308
include/boost/math/distributions/normal.hpp
Normal file
308
include/boost/math/distributions/normal.hpp
Normal 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
|
||||
|
||||
|
||||
443
include/boost/math/distributions/pareto.hpp
Normal file
443
include/boost/math/distributions/pareto.hpp
Normal 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
|
||||
|
||||
|
||||
602
include/boost/math/distributions/poisson.hpp
Normal file
602
include/boost/math/distributions/poisson.hpp
Normal 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 (1781–1840).
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
|
||||
293
include/boost/math/distributions/rayleigh.hpp
Normal file
293
include/boost/math/distributions/rayleigh.hpp
Normal 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
|
||||
374
include/boost/math/distributions/students_t.hpp
Normal file
374
include/boost/math/distributions/students_t.hpp
Normal 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
|
||||
521
include/boost/math/distributions/triangular.hpp
Normal file
521
include/boost/math/distributions/triangular.hpp
Normal 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
|
||||
|
||||
|
||||
|
||||
375
include/boost/math/distributions/uniform.hpp
Normal file
375
include/boost/math/distributions/uniform.hpp
Normal 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
|
||||
|
||||
|
||||
|
||||
382
include/boost/math/distributions/weibull.hpp
Normal file
382
include/boost/math/distributions/weibull.hpp
Normal 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
|
||||
|
||||
|
||||
509
include/boost/math/policies/error_handling.hpp
Normal file
509
include/boost/math/policies/error_handling.hpp
Normal 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
|
||||
|
||||
845
include/boost/math/policies/policy.hpp
Normal file
845
include/boost/math/policies/policy.hpp
Normal 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
|
||||
|
||||
|
||||
51
include/boost/math/special_functions.hpp
Normal file
51
include/boost/math/special_functions.hpp
Normal 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
|
||||
@@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
|
||||
474
include/boost/math/special_functions/bessel.hpp
Normal file
474
include/boost/math/special_functions/bessel.hpp
Normal 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
|
||||
1350
include/boost/math/special_functions/beta.hpp
Normal file
1350
include/boost/math/special_functions/beta.hpp
Normal file
File diff suppressed because it is too large
Load Diff
75
include/boost/math/special_functions/binomial.hpp
Normal file
75
include/boost/math/special_functions/binomial.hpp
Normal 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
|
||||
|
||||
|
||||
72
include/boost/math/special_functions/cbrt.hpp
Normal file
72
include/boost/math/special_functions/cbrt.hpp
Normal 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
|
||||
|
||||
|
||||
|
||||
53
include/boost/math/special_functions/cos_pi.hpp
Normal file
53
include/boost/math/special_functions/cos_pi.hpp
Normal 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
|
||||
96
include/boost/math/special_functions/detail/bessel_i0.hpp
Normal file
96
include/boost/math/special_functions/detail/bessel_i0.hpp
Normal 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
|
||||
99
include/boost/math/special_functions/detail/bessel_i1.hpp
Normal file
99
include/boost/math/special_functions/detail/bessel_i1.hpp
Normal 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
|
||||
331
include/boost/math/special_functions/detail/bessel_ik.hpp
Normal file
331
include/boost/math/special_functions/detail/bessel_ik.hpp
Normal 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
|
||||
147
include/boost/math/special_functions/detail/bessel_j0.hpp
Normal file
147
include/boost/math/special_functions/detail/bessel_j0.hpp
Normal 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
|
||||
152
include/boost/math/special_functions/detail/bessel_j1.hpp
Normal file
152
include/boost/math/special_functions/detail/bessel_j1.hpp
Normal 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
|
||||
86
include/boost/math/special_functions/detail/bessel_jn.hpp
Normal file
86
include/boost/math/special_functions/detail/bessel_jn.hpp
Normal 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
Reference in New Issue
Block a user